APPLINK-5487. Add sending OnPermissionChange on user changes via HMI.
authorAndrey Oleynik <AOleynik@luxoft.com>
Tue, 1 Apr 2014 09:38:52 +0000 (12:38 +0300)
committerJustin Dickow <jjdickow@gmail.com>
Tue, 8 Jul 2014 22:32:06 +0000 (18:32 -0400)
Signed-off-by: Justin Dickow <jjdickow@gmail.com>
Conflicts:
src/components/application_manager/include/application_manager/policies/policy_handler.h
src/components/application_manager/src/policies/policy_handler.cc
src/components/policy

src/components/application_manager/include/application_manager/policies/policy_handler.h [new file with mode: 0644]
src/components/application_manager/src/commands/hmi/on_app_permission_consent_notification.cc [new file with mode: 0644]
src/components/application_manager/src/policies/policy_handler.cc [new file with mode: 0644]

diff --git a/src/components/application_manager/include/application_manager/policies/policy_handler.h b/src/components/application_manager/include/application_manager/policies/policy_handler.h
new file mode 100644 (file)
index 0000000..d41ce03
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ Copyright (c) 2013, Ford Motor Company
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of the Ford Motor Company nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_POLICY_HANDLER_H_
+#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_POLICY_HANDLER_H_
+
+#include <string>
+#include <map>
+#include <set>
+#include <vector>
+#include "policy/policy_manager.h"
+#include "application_manager/policies/policy_event_observer.h"
+#include "application_manager/policies/pt_exchange_handler.h"
+#include "utils/logger.h"
+#include "utils/lock.h"
+#include "utils/threads/thread.h"
+#include "utils/singleton.h"
+
+namespace Json {
+class Value;
+}
+
+namespace policy {
+
+typedef std::vector<uint32_t> AppIds;
+typedef std::vector<uint32_t> DeviceHandles;
+
+class PolicyHandler : public utils::Singleton<PolicyHandler>,
+    public PolicyListener {
+ public:
+  virtual ~PolicyHandler();
+  PolicyManager* LoadPolicyLibrary();
+  PolicyManager* LoadPolicyLibrary(const std::string& path);
+  PolicyManager* policy_manager() const {
+    return policy_manager_;
+  }
+  bool InitPolicyTable();
+  bool RevertPolicyTable();
+  bool SendMessageToSDK(const BinaryMessage& pt_string);
+  bool ReceiveMessageFromSDK(const BinaryMessage& pt_string);
+  bool UnloadPolicyLibrary();
+  void OnPTExchangeNeeded();
+  void OnPermissionsUpdated(const std::string& policy_app_id,
+                            const Permissions& permissions);
+  /**
+   * @brief Checks, if policy update is necessary for application
+   */
+  void CheckAppPolicyState(const std::string& application_id);
+
+  /**
+   * Starts proccess updating policy table
+   */
+  void StartPTExchange(bool skip_device_selection = false);
+
+  /**
+   * Lets client to notify PolicyHandler that more kilometers expired
+   * @param kms New value of odometer
+   */
+  void KmsChanged(int kms);
+
+  /**
+   * @brief Gather information for application and sends it to HMI
+   * @param connection_key Connection key for application
+   */
+  void OnActivateApp(const std::string& connection_key,
+                     uint32_t correlation_id);
+
+  /**
+   * @brief Process user consent on mobile data connection access
+   * @param Device id or 0, if concern to all SDL functionality
+   * @param User consent from response
+   */
+  void OnAllowSDLFunctionalityNotification(bool is_allowed, uint32_t device_id =
+                                               0);
+  /**
+   * @brief Send request to HMI for requesting the allowance for some
+   * application functionality
+   * @param List of permissions required by application
+   * @param Unique appication id, if omitted - allow/disallow all applications
+   */
+  void SendAllowApp(const PermissionsList& list_of_permissions,
+                    uint32_t application_id = 0);
+
+  /**
+   * @brief Process application permission, which was set by user
+   * @param List of user-defined permissions for application
+   */
+  void OnAllowAppResponse(PermissionsList& list_of_permissions);
+
+  /**
+   * @brief Process application permission, which was set by user
+   * @param List of user-defined permissions for application
+   * @param Unique application id, if omitted - allow/disallow all
+   * applications
+   */
+  void OnAllowAppNotification(PermissionsList& list_of_permissions,
+                              uint32_t appication_id = 0);
+
+  /**
+   * @brief Increment counter for ignition cycles
+   */
+  void OnIgnitionCycleOver();
+
+  /**
+   * @brief Send notification to HMI concerning revocation of application
+   * @param policy_app_id Unique identifier of application
+   */
+  void OnAppRevoked(const std::string& policy_app_id);
+
+  /**
+   * Initializes PT exchange at ignition if need
+   */
+  void PTExchangeAtIgnition();
+
+  /**
+   * @brief Save device info for specific device to policy table
+   * @param device_id Device mac address
+   * @param device_info Device params
+   */
+  void SetDeviceInfo(std::string& device_id, const DeviceInfo& device_info);
+
+  /**
+   * @brief Store user-changed permissions consent to DB
+   * @param permissions User-changed group permissions consent
+   */
+  void OnAppPermissionConsent(const PermissionConsent& permissions);
+
+ protected:
+  /**
+   * Starts next retry exchange policy table
+   */
+  void StartNextRetry();
+
+  /**
+   * Initializes PT exchange at odometer if need
+   * @param kilometers value from odometer in kilometers
+   */
+  void PTExchangeAtOdometer(int kilometers);  
+
+ private:
+  /**
+   * @brief Choose application id to be used for snapshot sending
+   * @return Application id or 0, if there are no applications registered
+   */
+  uint32_t GetAppIdForSending();
+
+  /**
+   * @brief Choose device according to app HMI status and user consent for
+   * device
+   * @param device_info Struct with selected device parameters
+   * @return consent status for selected device
+   */
+   DeviceConsent GetDeviceForSending(DeviceParams& device_params);
+
+ private:
+  PolicyHandler();
+  static PolicyHandler* instance_;
+  static const std::string kLibrary;
+  PolicyManager* policy_manager_;
+  void* dl_handle_;
+  AppIds last_used_app_ids_;
+  static log4cxx::LoggerPtr logger_;
+  threads::Thread retry_sequence_;
+  sync_primitives::Lock retry_sequence_lock_;
+  PTExchangeHandler* exchange_handler_;
+  utils::SharedPtr<PolicyEventObserver> event_observer_;
+
+  /**
+   * @brief Contains device handles, which were sent for user consent to HMI
+   */
+  DeviceHandles pending_device_handles_;
+
+  /**
+   * @brief True, if PTS was sent, but PTU was not reseived yet,
+   * otherwise - false
+   * Used for limiting device consent request per PTS/PTU session
+   */
+  bool is_exchange_in_progress_;
+
+  inline PolicyManager* CreateManager();
+
+  DISALLOW_COPY_AND_ASSIGN(PolicyHandler);FRIEND_BASE_SINGLETON_CLASS_INSTANCE(PolicyHandler);
+  friend class RetrySequence;
+};
+
+}  //  namespace policy
+
+#endif  // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_POLICY_HANDLER_H_
diff --git a/src/components/application_manager/src/commands/hmi/on_app_permission_consent_notification.cc b/src/components/application_manager/src/commands/hmi/on_app_permission_consent_notification.cc
new file mode 100644 (file)
index 0000000..a02a3e5
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "application_manager/commands/hmi/on_app_permission_consent_notification.h"
+#include "application_manager/application_manager_impl.h"
+#include "application_manager/message_helper.h"
+#include "application_manager/policies/policy_handler.h"
+
+namespace application_manager {
+
+namespace commands {
+
+OnAppPermissionConsent::OnAppPermissionConsent(const MessageSharedPtr& message)
+    : NotificationFromHMI(message) {
+}
+
+OnAppPermissionConsent::~OnAppPermissionConsent() {
+}
+
+void OnAppPermissionConsent::Run() {
+  LOG4CXX_INFO(logger_, "OnAppPermissionConsent::Run");
+  smart_objects::SmartObject& msg_params = (*message_)[strings::msg_params];
+
+  policy::PermissionConsent permission_consent;
+  // If user defined group permissions for specific app
+  if (msg_params.keyExists(strings::app_id)) {
+    permission_consent.policy_app_id = msg_params[strings::app_id].asString();
+
+    typedef std::set<Application*> ApplicationList;
+    const ApplicationList app_list =
+        application_manager::ApplicationManagerImpl::instance()->applications();
+
+    ApplicationList::const_iterator it_app_list = app_list.begin();
+    ApplicationList::const_iterator it_app_list_end = app_list.end();
+    for (; it_app_list != it_app_list_end; ++it_app_list) {
+      if (permission_consent.policy_app_id.compare(
+            (*it_app_list)->mobile_app_id()->asString()) == 0) {
+        policy::DeviceParams device_params;
+        application_manager::MessageHelper::GetDeviceInfoForHandle(
+              (*it_app_list)->device(),
+              &device_params);
+
+        permission_consent.device_id = device_params.device_mac_address;
+      }
+    }
+  }
+
+  smart_objects::SmartArray* user_consent =
+      msg_params["consentedFunctions"].asArray();
+
+  smart_objects::SmartArray::const_iterator it = user_consent->begin();
+  smart_objects::SmartArray::const_iterator it_end = user_consent->end();
+  for (; it != it_end; ++it) {
+    policy::FunctionalGroupPermission permissions;
+    permissions.group_id = (*it)["id"].asInt();
+    permissions.group_name = (*it)["name"].asString();
+    permissions.is_allowed = (*it)["allowed"].asBool();
+    permission_consent.group_permissions.push_back(permissions);
+  }
+
+  permission_consent.consent_source = msg_params["source"].asString();
+
+  policy::PolicyHandler::instance()->OnAppPermissionConsent(permission_consent);
+}
+
+}  // namespace commands
+
+}  // namespace application_manager
diff --git a/src/components/application_manager/src/policies/policy_handler.cc b/src/components/application_manager/src/policies/policy_handler.cc
new file mode 100644 (file)
index 0000000..f697e1f
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+ Copyright (c) 2013, Ford Motor Company
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of the Ford Motor Company nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+#include <dlfcn.h>
+#include <algorithm>
+#include "application_manager/policies/policy_handler.h"
+#include "application_manager/policies/policy_retry_sequence.h"
+#include "application_manager/policies/pt_exchange_handler_impl.h"
+#include "application_manager/policies/pt_exchange_handler_ext.h"
+#include "application_manager/application_manager_impl.h"
+#include "application_manager/message_helper.h"
+#include "policy/policy_manager_impl.h"
+#include "utils/macro.h"
+#include "utils/date_time.h"
+#include "json/value.h"
+#include "config_profile/profile.h"
+
+namespace policy {
+typedef std::set<application_manager::Application*> ApplicationList;
+
+PolicyHandler* PolicyHandler::instance_ = NULL;
+const std::string PolicyHandler::kLibrary = "libPolicy.so";
+
+log4cxx::LoggerPtr PolicyHandler::logger_ = log4cxx::LoggerPtr(
+    log4cxx::Logger::getLogger("PolicyHandler"));
+
+PolicyHandler::PolicyHandler()
+    : policy_manager_(0),
+      dl_handle_(0),
+      exchange_handler_(NULL),
+      is_exchange_in_progress_(false),
+      retry_sequence_("RetrySequence", new RetrySequence(this)) {
+}
+
+PolicyHandler::~PolicyHandler() {
+  UnloadPolicyLibrary();
+}
+
+PolicyManager* PolicyHandler::LoadPolicyLibrary() {
+  return LoadPolicyLibrary("./");
+}
+
+PolicyManager* PolicyHandler::LoadPolicyLibrary(const std::string& path) {
+  std::string filename = path + kLibrary;
+  dl_handle_ = dlopen(filename.c_str(), RTLD_LAZY);
+
+  char* error_string = dlerror();
+  if (error_string == NULL) {
+    policy_manager_ = CreateManager();
+    policy_manager_->set_listener(this);
+#if defined (EXTENDED_POLICY)
+    exchange_handler_ = new PTExchangeHandlerExt(this);
+#else
+    exchange_handler_ = new PTExchangeHandlerImpl(this);
+#endif
+  } else {
+    LOG4CXX_ERROR(logger_, error_string);
+  }
+
+  return policy_manager_;
+}
+
+PolicyManager* PolicyHandler::CreateManager() {
+  typedef PolicyManager* (*CreateManager)();
+  CreateManager create_manager = 0;
+  *(void**) (&create_manager) = dlsym(dl_handle_, "CreateManager");
+  char* error_string = dlerror();
+  if (error_string == NULL) {
+    policy_manager_ = (*create_manager)();
+  } else {
+    LOG4CXX_WARN(logger_, error_string);
+  }
+  return policy_manager_;
+}
+
+bool PolicyHandler::InitPolicyTable() {
+  std::string preloaded_file =
+      profile::Profile::instance()->preloaded_pt_file();
+  DCHECK(policy_manager_);
+  return policy_manager_->LoadPTFromFile(preloaded_file);
+}
+
+bool PolicyHandler::RevertPolicyTable() {
+  LOG4CXX_INFO(logger_, "Removing user consent records in policy table.");
+  DCHECK(policy_manager_);
+  return policy_manager()->ResetUserConsent();
+}
+
+uint32_t PolicyHandler::GetAppIdForSending() {
+  // Get app.list
+  const ApplicationList app_list =
+      application_manager::ApplicationManagerImpl::instance()->applications();
+
+  if (app_list.empty()) {
+    return 0;
+  }
+
+  // Choose application
+  uint32_t selected_app_id = 0;
+  AppIds app_ids_last_resort;
+  AppIds app_ids_preferred;
+
+  ApplicationList::const_iterator it_app_list = app_list.begin();
+  ApplicationList::const_iterator it_app_list_end = app_list.end();
+  for (; it_app_list != it_app_list_end; ++it_app_list) {
+    switch ((*it_app_list)->hmi_level()) {
+      case mobile_apis::HMILevel::HMI_NONE:
+        app_ids_last_resort.push_back((*it_app_list)->app_id());
+        break;
+      default:
+        app_ids_preferred.push_back((*it_app_list)->app_id());
+        break;
+    }
+  }
+
+  AppIds& app_ids_to_use =
+      app_ids_preferred.empty() ? app_ids_last_resort : app_ids_preferred;
+
+  // Checking, if some of currently known apps was not used already
+  std::sort(last_used_app_ids_.begin(), last_used_app_ids_.end());
+  std::sort(app_ids_to_use.begin(), app_ids_to_use.end());
+
+  bool is_all_used = std::includes(last_used_app_ids_.begin(),
+                                   last_used_app_ids_.end(),
+                                   app_ids_to_use.begin(),
+                                   app_ids_to_use.end());
+
+  if (is_all_used) {
+    last_used_app_ids_.clear();
+  }
+
+  // Leave only unused apps
+  AppIds::iterator it_apps_to_use = app_ids_to_use.begin();
+  AppIds::iterator it_apps_to_use_end = app_ids_to_use.end();
+
+  AppIds::const_iterator it_last_used_app_ids =
+      last_used_app_ids_.begin();
+  AppIds::const_iterator it_last_used_app_ids_end =
+      last_used_app_ids_.end();
+
+  for (; it_last_used_app_ids != it_last_used_app_ids_end;
+      ++it_last_used_app_ids) {
+
+    std::remove(it_apps_to_use, it_apps_to_use_end,
+                *it_last_used_app_ids);
+  }
+
+  // Random selection of filtered apps
+  std::srand(time(0));
+  selected_app_id = *(app_ids_to_use.begin()
+      + (rand() % app_ids_to_use.size()));
+
+  last_used_app_ids_.push_back(selected_app_id);
+  return selected_app_id;
+}
+
+DeviceConsent PolicyHandler::GetDeviceForSending(DeviceParams& device_params) {
+  uint32_t app_id = 0;
+  uint32_t app_id_previous = 0;
+  while (true) {
+    app_id = GetAppIdForSending();
+    if (!app_id) {
+      LOG4CXX_WARN(logger_,
+                   "There is no appropriate application for sending PTS.");
+      return kDeviceDisallowed;
+    }
+
+    // If only one application is available, return its device params
+    if (app_id == app_id_previous) {
+      return kDeviceDisallowed;
+    }
+
+    app_id_previous = app_id;
+
+    char buffer[16];
+    snprintf(buffer, 16, "%d", app_id);
+    application_manager::MessageHelper::GetDeviceInfoForApp(std::string(buffer),
+                                                            &device_params);
+
+    DeviceConsent consent =
+        policy_manager_->GetUserConsentForDevice(device_params.device_mac_address);
+    switch (consent) {
+    case kDeviceAllowed:
+      return consent;
+    case kDeviceDisallowed:
+      continue;
+    case kDeviceHasNoConsent:
+      return consent;
+    default:
+      LOG4CXX_WARN(logger_, "Consent result is not impelemented.");
+      return consent;
+    }
+  }
+  return kDeviceDisallowed;
+}
+
+void PolicyHandler::SetDeviceInfo(std::string& device_id,
+                                  const DeviceInfo& device_info) {
+  LOG4CXX_INFO(logger_, "SetDeviceInfo");
+  policy_manager_->SetDeviceInfo(device_id, device_info);
+}
+
+void PolicyHandler::OnAppPermissionConsent(
+    const PermissionConsent& permissions) {
+  LOG4CXX_INFO(logger_, "OnAppPermissionConsent");
+  DCHECK(policy_manager_);
+  if (!permissions.policy_app_id.empty()) {
+    policy_manager_->SetUserConsentForApp(permissions);
+  }
+
+  //TODO(AOleynik): Handle situation for all apps (policy_app_id is empty)
+}
+
+void PolicyHandler::OnAppRevoked(const std::string& policy_app_id) {
+  LOG4CXX_INFO(logger_, "OnAppRevoked");
+  const ApplicationList app_list =
+      application_manager::ApplicationManagerImpl::instance()->applications();
+  ApplicationList::const_iterator it = app_list.begin();
+  ApplicationList::const_iterator it_end = app_list.end();
+  for (; it != it_end; ++it) {
+    if ((*(*it)).mobile_app_id()->asString() == policy_app_id) {
+      LOG4CXX_INFO(logger_,
+                   "Application_id " << policy_app_id << " is revoked.");
+      AppPermissions permissions(atoi(policy_app_id.c_str()));
+      permissions.appRevoked = true;
+      application_manager::MessageHelper::SendOnAppPermissionsChangedNotification(
+          (*it)->app_id(), permissions);
+      application_manager::ApplicationManagerImpl::instance()
+          ->DeactivateApplication(*it);
+      (*(*it)).set_hmi_level(mobile_apis::HMILevel::HMI_NONE);
+      return;
+    }
+  }
+  LOG4CXX_WARN(logger_,
+               "Application_id " << policy_app_id << " is not registered.");
+}
+
+bool PolicyHandler::SendMessageToSDK(const BinaryMessage& pt_string) {
+  LOG4CXX_INFO(logger_, "PolicyHandler::SendMessageToSDK");
+
+  is_exchange_in_progress_ = true;
+
+  std::string url;
+  uint32_t app_id = last_used_app_ids_.back();
+  if (policy_manager_) {
+    const std::string& mobile_app_id =
+        application_manager::ApplicationManagerImpl::instance()->application(
+            app_id)->mobile_app_id()->asString();
+    url = policy_manager_->GetUpdateUrl(mobile_app_id);
+  }
+  LOG4CXX_INFO(
+      logger_,
+      "Update url is " << url << " for application " << application_manager::ApplicationManagerImpl::instance()-> application(app_id)->name());
+
+  application_manager::MessageHelper::SendPolicySnapshotNotification(app_id,
+                                                                     pt_string,
+                                                                     url, 0);
+  return true;
+}
+
+bool PolicyHandler::ReceiveMessageFromSDK(const BinaryMessage& pt_string) {
+  if (!policy_manager_) {
+    LOG4CXX_WARN(logger_, "The shared library of policy is not loaded");
+    return false;
+  }
+
+  is_exchange_in_progress_ = false;
+
+  bool ret = policy_manager_->LoadPT(pt_string);
+  LOG4CXX_INFO(logger_, "Policy table is saved: " << std::boolalpha << ret);
+  if (ret) {
+    LOG4CXX_INFO(logger_, "PTU was successful.");
+    retry_sequence_lock_.Ackquire();
+    retry_sequence_.stop();
+    retry_sequence_lock_.Release();
+    int32_t correlation_id =
+        application_manager::ApplicationManagerImpl::instance()
+            ->GetNextHMICorrelationID();
+    event_observer_ = new PolicyEventObserver(policy_manager_);
+    event_observer_.get()->subscribe_on_event(
+        hmi_apis::FunctionID::VehicleInfo_GetVehicleData, correlation_id);
+    application_manager::MessageHelper::CreateGetDeviceData(correlation_id);
+    // TODO(KKolodiy): when we must reset counter of ignition cyles, update days
+    // and kms?
+  }
+  return ret;
+}
+
+bool PolicyHandler::UnloadPolicyLibrary() {
+  bool ret = true;
+  delete policy_manager_;
+  policy_manager_ = 0;
+  if (dl_handle_) {
+    ret = (dlclose(dl_handle_) == 0);
+    dl_handle_ = 0;
+  }
+  return ret;
+}
+
+void PolicyHandler::StartPTExchange(bool skip_device_selection) {
+  LOG4CXX_INFO(logger_, "PolicyHandler::StartPTExchange");
+  if (!policy_manager_) {
+    LOG4CXX_WARN(logger_, "The shared library of policy is not loaded");
+    return;
+  }
+
+  if (is_exchange_in_progress_) {
+    LOG4CXX_INFO(logger_, "Starting exchange skipped, since another exchange "
+                 "is in progress.");
+    return;
+  }
+
+  if (!skip_device_selection) {
+    DeviceParams device_params;
+    DeviceConsent consent = GetDeviceForSending(device_params);
+    switch (consent) {
+    case kDeviceHasNoConsent:
+      // Send OnSDLConsentNeeded to HMI for user consent on device usage
+      pending_device_handles_.push_back(device_params.device_handle);
+      application_manager::MessageHelper::SendOnSDLConsentNeeded(device_params);
+      return;
+    case kDeviceDisallowed:
+      return;
+    default:
+      break;
+    }
+  }
+
+  // TODO(KKolodiy): when we must reset counter of ignition cyles,
+  // update days and kms?
+
+  retry_sequence_lock_.Ackquire();
+  retry_sequence_.stop();
+  policy_manager_->ResetRetrySequence();
+  retry_sequence_.start();
+  retry_sequence_lock_.Release();
+}
+
+void PolicyHandler::StartNextRetry() {
+  DCHECK(exchange_handler_);
+  exchange_handler_->StartExchange();
+}
+
+void PolicyHandler::OnAllowSDLFunctionalityNotification(bool is_allowed,
+                                                        uint32_t device_id) {
+  LOG4CXX_INFO(logger_, "OnAllowSDLFunctionalityNotification");
+  if (device_id) {
+    DeviceParams device_params;
+    application_manager::MessageHelper::GetDeviceInfoForHandle(device_id,
+                                                               &device_params);
+    policy_manager_->SetUserConsentForDevice(device_params.device_mac_address,
+                                             is_allowed);
+
+    DeviceHandles::iterator it = std::find(pending_device_handles_.begin(),
+                                           pending_device_handles_.end(),
+                                           device_id);
+    // If consent done from HMI menu
+    if (it == pending_device_handles_.end()) {
+      return;
+    }
+
+    pending_device_handles_.erase(it);
+    if (is_allowed) {
+      // Skip device selection, since user already consented device usage
+      StartPTExchange(true);
+    }
+
+    return;
+  }
+
+  // TODO(AOleynik): Handle situation, if general functionality is concerned
+}
+
+void PolicyHandler::SendAllowApp(const PermissionsList& list_of_permissions,
+                                 uint32_t application_id) {
+  LOG4CXX_INFO(logger_,
+               "Sending allow request for application id:" << application_id);
+  // TODO(PV): change
+  /*application_manager::MessageHelper::SendAllowAppRequest(list_of_permissions,
+   application_id);*/
+}
+
+void PolicyHandler::OnAllowAppResponse(PermissionsList& list_of_permissions) {
+  // TODO(AOleynik): Impelement response processing for user-defined permissions
+  // for application
+}
+
+void PolicyHandler::OnAllowAppNotification(PermissionsList& list_of_permissions,
+                                           uint32_t appication_id) {
+  // TODO(AOleynik): Implement notification processing for user-defined
+  // permissions for applicaiton
+}
+
+void PolicyHandler::OnIgnitionCycleOver() {
+  LOG4CXX_INFO(logger_, "OnIgnitionCycleOver");
+  policy_manager_->IncrementIgnitionCycles();
+}
+
+void PolicyHandler::KmsChanged(int kms) {
+  LOG4CXX_INFO(logger_, "PolicyHandler::KmsChanged " << kms << " kilometers");
+  PTExchangeAtOdometer(kms);
+}
+
+void PolicyHandler::OnActivateApp(const std::string& policy_app_id,
+                                  uint32_t correlation_id) {
+  LOG4CXX_INFO(logger_, "OnActivateApp");
+  if (!policy_manager_) {
+    LOG4CXX_WARN(logger_, "The shared library of policy is not loaded");
+    return;
+  }
+  // Should be gathered:
+  // - isSDLAllowed, i.e. device data usage consent
+
+  AppPermissions permissions(atoi(policy_app_id.c_str()));
+  DeviceConsent consent = GetDeviceForSending(permissions.deviceInfo);
+  permissions.isSDLAllowed = kDeviceAllowed == consent ? true : false;
+
+  // If isSDLAllowed is false, we should provide device params for user consent
+  if (!permissions.isSDLAllowed) {
+    pending_device_handles_.push_back(permissions.deviceInfo.device_handle);
+  }
+
+  // TODO(AOleynik): Fill following:
+  // - isPermissionsConsentNeeded, i.e. specific application permissions
+  // - isAppPermissionsRevoked
+  // - isAppRevoked
+
+  application_manager::MessageHelper::SendActivateAppResponse(permissions,
+                                                              correlation_id);
+}
+
+void PolicyHandler::PTExchangeAtIgnition() {
+  LOG4CXX_INFO(logger_, "PTExchangeAtIgnition");
+  if (!policy_manager_) {
+    LOG4CXX_WARN(logger_, "The shared library of policy is not loaded");
+    return;
+  }
+
+  TimevalStruct current_time = date_time::DateTime::getCurrentTime();
+  const int kSecondsInDay = 60 * 60 * 24;
+  int days = current_time.tv_sec / kSecondsInDay;
+
+  // Start update on limits exhaustion, if update wasn't started already by any
+  // other event
+  LOG4CXX_INFO(
+      logger_,
+      "\nIgnition cycles exceeded: " << std::boolalpha << policy_manager_->ExceededIgnitionCycles() << "\nDays exceeded: " << std::boolalpha << policy_manager_->ExceededDays(days) << "\nStatusUpdateRequired: " << std::boolalpha << (policy_manager_->GetPolicyTableStatus() == StatusUpdateRequired));
+  if (policy_manager_->ExceededIgnitionCycles()
+      || policy_manager_->ExceededDays(days)
+      || policy_manager_->GetPolicyTableStatus() == StatusUpdateRequired) {
+    StartPTExchange();
+  }
+}
+
+void PolicyHandler::PTExchangeAtOdometer(int kilometers) {
+  if (!policy_manager_) {
+    LOG4CXX_WARN(logger_, "The shared library of policy is not loaded");
+    return;
+  }
+  if (policy_manager_->ExceededKilometers(kilometers)) {
+    LOG4CXX_INFO(logger_, "Enough kilometers passed to send for PT update.");
+    StartPTExchange();
+  }
+}
+
+void PolicyHandler::OnPTExchangeNeeded() {
+  StartPTExchange();
+}
+
+void PolicyHandler::OnPermissionsUpdated(const std::string& policy_app_id,
+                                         const Permissions& permissions) {
+  const ApplicationList app_list =
+      application_manager::ApplicationManagerImpl::instance()->applications();
+
+  // Find appropriate connection_key for application_id
+  ApplicationList::const_iterator it_app_list = app_list.begin();
+  ApplicationList::const_iterator it_app_list_end = app_list.end();
+  for (; it_app_list != it_app_list_end; ++it_app_list) {
+    if (policy_app_id.compare((*it_app_list)->mobile_app_id()->asString())
+        == 0) {
+      application_manager::MessageHelper::SendOnPermissionsChangeNotification(
+          (*it_app_list)->app_id(), permissions);
+
+      LOG4CXX_INFO(
+          logger_,
+          "Notification sent for application_id:" << policy_app_id << " and connection_key " << (*it_app_list)->app_id());
+
+      return;
+    }
+  }
+
+  LOG4CXX_WARN(logger_,
+               "Connection_key not found for application_id:" << policy_app_id);
+}
+
+void PolicyHandler::CheckAppPolicyState(const std::string& application_id) {
+  LOG4CXX_INFO(logger_, "CheckAppPolicyState");
+  policy_manager()->CheckAppPolicyState(application_id);
+}
+
+}  //  namespace policy