From: Andrey Oleynik Date: Tue, 1 Apr 2014 09:38:52 +0000 (+0300) Subject: APPLINK-5487. Add sending OnPermissionChange on user changes via HMI. X-Git-Tag: 3.5~156 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=664933a8cfd31556205757dbfac3f5223f7ef77c;p=profile%2Fivi%2Fsmartdevicelink.git APPLINK-5487. Add sending OnPermissionChange on user changes via HMI. Signed-off-by: Justin Dickow Conflicts: src/components/application_manager/include/application_manager/policies/policy_handler.h src/components/application_manager/src/policies/policy_handler.cc src/components/policy --- 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 index 0000000..d41ce03 --- /dev/null +++ b/src/components/application_manager/include/application_manager/policies/policy_handler.h @@ -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 +#include +#include +#include +#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 AppIds; +typedef std::vector DeviceHandles; + +class PolicyHandler : public utils::Singleton, + 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 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 index 0000000..a02a3e5 --- /dev/null +++ b/src/components/application_manager/src/commands/hmi/on_app_permission_consent_notification.cc @@ -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 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 index 0000000..f697e1f --- /dev/null +++ b/src/components/application_manager/src/policies/policy_handler.cc @@ -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 +#include +#include +#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 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