2 Copyright (c) 2013, Ford Motor Company
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
11 Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided with the
16 Neither the name of the Ford Motor Company nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
36 #include "json/reader.h"
37 #include "json/writer.h"
38 #include "policy/policy_table.h"
39 #include "policy/pt_representation.h"
40 #include "policy/policy_manager_impl.h"
41 #include "policy/policy_helper.h"
42 #include "utils/file_system.h"
43 #include "utils/logger.h"
45 policy::PolicyManager* CreateManager() {
46 return new policy::PolicyManagerImpl();
50 void CheckPreloadedGroups(policy_table::ApplicationParams& app_param) {
57 CREATE_LOGGERPTR_GLOBAL(logger_, "PolicyManagerImpl")
59 #if defined(__QNXNTO__) and defined(GCOV_ENABLED)
61 LOG4CXX_ERROR(log4cxx::Logger::getLogger("appMain"),
62 "Attention! This application was built with unsupported "
63 "configuration (gcov + QNX). Use it at your own risk.");
66 bool check_gcov = CheckGcov();
69 PolicyManagerImpl::PolicyManagerImpl()
72 exchange_in_progress_(false),
73 update_required_(policy_table_.pt_data()->UpdateRequired()),
74 exchange_pending_(false),
75 retry_sequence_index_(0),
76 last_update_status_(policy::StatusUnknown) {
77 RefreshRetrySequence();
80 void PolicyManagerImpl::ResetDefaultPT(const PolicyTable& policy_table) {
81 policy_table_ = policy_table;
82 exchange_in_progress_ = false;
83 update_required_ = policy_table_.pt_data()->UpdateRequired();
84 exchange_pending_ = false;
85 retry_sequence_index_ = 0;
86 last_update_status_ = policy::StatusUnknown;
87 RefreshRetrySequence();
90 void PolicyManagerImpl::set_listener(PolicyListener* listener) {
94 PolicyManagerImpl::~PolicyManagerImpl() {
95 LOG4CXX_INFO(logger_, "Destroying policy manager.");
96 policy_table_.pt_data()->SaveUpdateRequired(update_required_);
99 bool PolicyManagerImpl::LoadPTFromFile(const std::string& file_name) {
100 LOG4CXX_INFO(logger_, "LoadPTFromFile: " << file_name);
102 BinaryMessage json_string;
103 bool final_result = false;
104 final_result = file_system::ReadBinaryFile(file_name, json_string);
106 LOG4CXX_WARN(logger_, "Failed to read pt file.");
107 utils::SharedPtr<policy_table::Table> table = new policy_table::Table();
110 utils::SharedPtr<policy_table::Table> table = Parse(json_string);
112 LOG4CXX_WARN(logger_, "Failed to parse policy table");
113 utils::SharedPtr<policy_table::Table> table = new policy_table::Table();
116 final_result = final_result && policy_table_.pt_data()->Save(*table);
119 "Loading from file was " << (final_result ? "successful" : "unsuccessful"));
121 // Initial setting of snapshot data
122 if (!policy_table_snapshot_) {
123 policy_table_snapshot_ = policy_table_.pt_data()->GenerateSnapshot();
124 if (!policy_table_snapshot_) {
125 LOG4CXX_WARN(logger_,
126 "Failed to create initial snapshot of policy table");
131 RefreshRetrySequence();
135 utils::SharedPtr<policy_table::Table> PolicyManagerImpl::Parse(
136 const BinaryMessage& pt_content) {
137 std::string json(pt_content.begin(), pt_content.end());
140 if (reader.parse(json.c_str(), value)) {
141 return new policy_table::Table(&value);
143 return utils::SharedPtr<policy_table::Table>();
147 bool PolicyManagerImpl::LoadPT(const std::string& file,
148 const BinaryMessage& pt_content) {
149 LOG4CXX_INFO(logger_, "LoadPTFromString of size " << pt_content.size());
151 // Parse message into table struct
152 utils::SharedPtr<policy_table::Table> pt_update = Parse(pt_content);
155 LOG4CXX_WARN(logger_, "Parsed table pointer is 0.");
159 #if defined (EXTENDED_POLICY)
160 file_system::DeleteFile(file);
163 set_exchange_in_progress(false);
165 if (!pt_update->is_valid()) {
166 rpc::ValidationReport report("policy_table");
167 pt_update->ReportErrors(&report);
168 LOG4CXX_WARN(logger_, "Parsed table is not valid " << rpc::PrettyFormat(report));
172 // Check and update permissions for applications, send notifications
173 CheckPermissionsChanges(pt_update);
175 // Replace current data with updated
176 policy_table_snapshot_->policy_table.functional_groupings = pt_update
177 ->policy_table.functional_groupings;
179 policy_table_snapshot_->policy_table.module_config = pt_update->policy_table
182 bool is_message_part_updated = pt_update->policy_table
183 .consumer_friendly_messages.is_initialized();
185 if (is_message_part_updated) {
186 policy_table_snapshot_->policy_table.consumer_friendly_messages->messages =
187 pt_update->policy_table.consumer_friendly_messages->messages;
190 //policy_table.module_meta
193 if (!policy_table_.pt_data()->Save(*policy_table_snapshot_)) {
194 LOG4CXX_WARN(logger_, "Unsuccessful save of updated policy table.");
198 // Removing last app request from update requests
199 RemoveAppFromUpdateList();
201 // TODO(AOleynik): Check, if there is updated info present for apps in list
202 // and skip update in this case for given app
203 if (!update_requests_list_.empty()) {
205 listener_->OnPTExchangeNeeded();
208 LOG4CXX_INFO(logger_, "Update request queue is empty.");
211 RefreshRetrySequence();
215 void PolicyManagerImpl::CheckPermissionsChanges(
216 const utils::SharedPtr<policy_table::Table> pt_update) {
217 LOG4CXX_INFO(logger_, "Checking incoming permissions.");
219 std::for_each(pt_update->policy_table.app_policies.begin(),
220 pt_update->policy_table.app_policies.end(),
221 CheckAppPolicy(this, pt_update));
224 void PolicyManagerImpl::PrepareNotificationData(
225 const policy_table::FunctionalGroupings& groups,
226 const policy_table::Strings& group_names,
227 const std::vector<FunctionalGroupPermission>& group_permission,
228 Permissions& notification_data) {
230 LOG4CXX_INFO(logger_, "Preparing data for notification.");
231 ProcessFunctionalGroup processor(groups, group_permission, notification_data);
232 std::for_each(group_names.begin(), group_names.end(), processor);
235 void PolicyManagerImpl::set_exchange_in_progress(bool value) {
236 sync_primitives::AutoLock lock(exchange_in_progress_lock_);
237 LOG4CXX_INFO(logger_,
238 "Exchange in progress value is:" << std::boolalpha << value);
239 exchange_in_progress_ = value;
243 void PolicyManagerImpl::set_exchange_pending(bool value) {
244 sync_primitives::AutoLock lock(exchange_pending_lock_);
245 LOG4CXX_INFO(logger_,
246 "Exchange pending value is:" << std::boolalpha << value);
247 exchange_pending_ = value;
251 void PolicyManagerImpl::set_update_required(bool value) {
252 sync_primitives::AutoLock lock(update_required_lock_);
253 LOG4CXX_INFO(logger_, "Update required value is:" << std::boolalpha << value);
254 update_required_ = value;
258 void PolicyManagerImpl::AddAppToUpdateList(const std::string& application_id) {
259 sync_primitives::AutoLock lock(update_request_list_lock_);
260 LOG4CXX_INFO(logger_,
261 "Adding application " << application_id << " to update list");
262 // Add application id only once
263 std::list<std::string>::const_iterator it = std::find(
264 update_requests_list_.begin(), update_requests_list_.end(),
266 if (it == update_requests_list_.end()) {
267 update_requests_list_.push_back(application_id);
271 void PolicyManagerImpl::RemoveAppFromUpdateList() {
272 sync_primitives::AutoLock lock(update_request_list_lock_);
273 if (update_requests_list_.empty()) {
278 "Removing application " << update_requests_list_.front() << " from update list");
279 update_requests_list_.pop_front();
282 std::string PolicyManagerImpl::GetUpdateUrl(int service_type) {
283 LOG4CXX_INFO(logger_, "PolicyManagerImpl::GetUpdateUrl");
284 EndpointUrls urls = policy_table_.pt_data()->GetUpdateUrls(service_type);
286 static int index = 0;
288 if (index < urls.size()) {
289 url = urls[index].url;
290 } else if (!urls.empty()) {
292 url = urls[index].url;
299 EndpointUrls PolicyManagerImpl::GetUpdateUrls(int service_type) {
300 LOG4CXX_INFO(logger_, "PolicyManagerImpl::GetUpdateUrls");
301 return policy_table_.pt_data()->GetUpdateUrls(service_type);
304 BinaryMessageSptr PolicyManagerImpl::RequestPTUpdate() {
305 LOG4CXX_INFO(logger_, "Creating PT Snapshot");
307 // Update policy table for the first time with system information
308 if (policy_table_.pt_data()->IsPTPreloaded()) {
309 listener()->OnSystemInfoUpdateRequired();
312 policy_table_snapshot_ = policy_table_.pt_data()->GenerateSnapshot();
313 if (!policy_table_snapshot_) {
314 LOG4CXX_ERROR(logger_, "Failed to create snapshot of policy table");
318 policy_table::ApplicationPolicies& apps = policy_table_snapshot_->policy_table.app_policies;
319 std::map<std::string,
320 rpc::Stringifyable<rpc::Nullable<rpc::policy_table_interface_base::ApplicationParams>>>::iterator it = apps.begin();
321 for (; apps.end() != it; ++it) {
322 if (policy_table_.pt_data()->IsDefaultPolicy(it->first)) {
323 it->second.set_to_string(kDefaultId);
326 if (policy_table_.pt_data()->IsPredataPolicy(it->first)) {
327 it->second.set_to_string(kPreDataConsentId);
332 if (!exchange_pending_) {
333 set_update_required(false);
336 set_exchange_in_progress(true);
337 set_exchange_pending(false);
339 #ifdef EXTENDED_POLICY
340 // TODO(KKolodiy): Check design for more convenient access to policy ext data
341 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
344 pt_ext->UnpairedDevicesList(&unpaired_device_ids_);
346 #endif // EXTENDED_POLICY
348 Json::Value value = policy_table_snapshot_->ToJsonValue();
349 Json::FastWriter writer;
350 std::string message_string = writer.write(value);
351 return new BinaryMessage(message_string.begin(), message_string.end());
354 CheckPermissionResult PolicyManagerImpl::CheckPermissions(
355 const PTString& app_id, const PTString& hmi_level, const PTString& rpc) {
358 "CheckPermissions for " << app_id << " and rpc " << rpc << " for "
359 << hmi_level << " level.");
361 #if defined (EXTENDED_POLICY)
362 const std::string device_id = GetCurrentDeviceId(app_id);
363 // Get actual application group permission according to user consents
364 std::vector<FunctionalGroupPermission> app_group_permissions;
365 GetUserPermissionsForApp(device_id, app_id, app_group_permissions);
367 // Fill struct with known groups RPCs
368 policy_table::FunctionalGroupings functional_groupings;
369 policy_table_.pt_data()->GetFunctionalGroupings(functional_groupings);
371 policy_table::Strings app_groups;
372 std::vector<FunctionalGroupPermission>::const_iterator it =
373 app_group_permissions.begin();
374 std::vector<FunctionalGroupPermission>::const_iterator it_end =
375 app_group_permissions.end();
376 for (; it != it_end; ++it) {
377 app_groups.push_back((*it).group_name);
380 Permissions rpc_permissions;
381 PrepareNotificationData(functional_groupings, app_groups,
382 app_group_permissions, rpc_permissions);
384 CheckPermissionResult result;
385 // If RPC is present in list, but not found in allowed and userDisallowed ==
386 // disallowed both by backend and by user, which is default value for result
387 if (rpc_permissions.end() == rpc_permissions.find(rpc)) {
388 // RPC not found in list == disallowed by backend
393 if (rpc_permissions[rpc].hmi_permissions[kAllowedKey].end() !=
394 rpc_permissions[rpc].hmi_permissions[kAllowedKey].find(hmi_level)) {
395 // RPC found in allowed == allowed by backend and user
396 result.hmi_level_permitted = kRpcAllowed;
399 if (rpc_permissions[rpc].hmi_permissions[kUserDisallowedKey].end() !=
400 rpc_permissions[rpc].hmi_permissions[kUserDisallowedKey].find(hmi_level)) {
401 // RPC found in allowed == allowed by backend, but disallowed by user
402 result.hmi_level_permitted = kRpcUserDisallowed;
405 // Add parameters of RPC, if any
406 result.list_of_allowed_params = new std::vector<PTString>();
407 std::copy(rpc_permissions[rpc].parameter_permissions[kAllowedKey].begin(),
408 rpc_permissions[rpc].parameter_permissions[kAllowedKey].end(),
409 std::back_inserter(*result.list_of_allowed_params));
413 return policy_table_.pt_data()->CheckPermissions(app_id, hmi_level, rpc);
417 bool PolicyManagerImpl::ResetUserConsent() {
418 #if defined (EXTENDED_POLICY)
419 // TODO(AOleynik): Check design for more convenient access to policy ext data
420 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
423 return pt_ext->ResetUserConsent();
431 void PolicyManagerImpl::CheckAppPolicyState(const std::string& application_id) {
432 LOG4CXX_INFO(logger_, "CheckAppPolicyState");
433 const std::string device_id = GetCurrentDeviceId(application_id);
434 DeviceConsent device_consent = GetUserConsentForDevice(device_id);
435 if (!policy_table_.pt_data()->IsApplicationRepresented(application_id)) {
438 "Setting default permissions for application id: " << application_id);
439 #if defined (EXTENDED_POLICY)
440 if (kDeviceHasNoConsent == device_consent ||
441 kDeviceDisallowed == device_consent) {
442 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
445 LOG4CXX_WARN(logger_, "Can't cleanup unpaired devices.");
448 pt_ext->SetPredataPolicy(application_id);
450 policy_table_.pt_data()->SetDefaultPolicy(application_id);
453 policy_table_.pt_data()->SetDefaultPolicy(application_id);
455 SendNotificationOnPermissionsUpdated(application_id);
457 if (!policy_table_.pt_data()->IsDefaultPolicy(application_id)
458 || (kDeviceHasNoConsent != device_consent
459 && policy_table_.pt_data()->IsPredataPolicy(application_id))) {
464 AddAppToUpdateList(application_id);
466 if (PolicyTableStatus::StatusUpToDate == GetPolicyTableStatus()) {
467 set_update_required(true);
469 set_exchange_pending(true);
473 void PolicyManagerImpl::SendNotificationOnPermissionsUpdated(
474 const std::string& application_id) {
475 const std::string device_id = GetCurrentDeviceId(application_id);
476 if (device_id.empty()) {
477 LOG4CXX_WARN(logger_, "Couldn't find device info for application id "
478 "'" << application_id << "'");
482 std::vector<FunctionalGroupPermission> app_group_permissions;
483 GetUserPermissionsForApp(device_id, application_id, app_group_permissions);
485 policy_table::FunctionalGroupings functional_groupings;
486 policy_table_.pt_data()->GetFunctionalGroupings(functional_groupings);
488 policy_table::Strings app_groups;
489 std::vector<FunctionalGroupPermission>::const_iterator it =
490 app_group_permissions.begin();
491 std::vector<FunctionalGroupPermission>::const_iterator it_end =
492 app_group_permissions.end();
493 for (; it != it_end; ++it) {
494 app_groups.push_back((*it).group_name);
497 Permissions notification_data;
498 PrepareNotificationData(functional_groupings, app_groups, app_group_permissions,
501 LOG4CXX_INFO(logger_, "Send notification for application_id:" << application_id);
502 std::string default_hmi;
503 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
506 LOG4CXX_WARN(logger_, "Can't get default hmi level for " << application_id);
510 pt_ext->GetDefaultHMI(application_id, &default_hmi);
511 listener()->OnPermissionsUpdated(application_id, notification_data,
515 bool PolicyManagerImpl::CleanupUnpairedDevices() {
516 LOG4CXX_INFO(logger_, "CleanupUnpairedDevices");
517 #ifdef EXTENDED_POLICY
518 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
521 LOG4CXX_WARN(logger_, "Can't cleanup unpaired devices.");
525 return pt_ext->CleanupUnpairedDevices(unpaired_device_ids_);
526 #else // EXTENDED_POLICY
527 // For SDL-specific it doesn't matter
529 #endif // EXTENDED_POLICY
532 PolicyTableStatus PolicyManagerImpl::GetPolicyTableStatus() {
533 if (!exchange_in_progress_ && !exchange_pending_ && !update_required_) {
534 return PolicyTableStatus::StatusUpToDate;
537 if (update_required_ && !exchange_in_progress_ && !exchange_pending_) {
538 return PolicyTableStatus::StatusUpdateRequired;
541 return PolicyTableStatus::StatusUpdatePending;
544 DeviceConsent PolicyManagerImpl::GetUserConsentForDevice(
545 const std::string& device_id) {
546 LOG4CXX_INFO(logger_, "GetUserConsentForDevice");
547 #if defined (EXTENDED_POLICY)
548 // TODO(AOleynik): Check design for more convenient access to policy ext data
549 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
552 LOG4CXX_WARN(logger_, "Can't get user consent for device");
553 return kDeviceDisallowed;
556 // Get device permission groups from app_policies section, which hadn't been
558 policy_table::Strings groups;
559 policy_table::Strings preconsented_groups;
560 if (!pt_ext->GetDeviceGroupsFromPolicies(&groups, &preconsented_groups)) {
561 LOG4CXX_WARN(logger_, "Can't get device groups from policies.");
562 return kDeviceDisallowed;
565 StringArray list_of_permissions;
567 groups.begin(), groups.end(),
568 FunctionalGroupInserter(preconsented_groups, list_of_permissions));
570 // Check device permission groups for user consent in device_data section
571 if (!list_of_permissions.empty()) {
572 StringArray consented_groups;
573 StringArray disallowed_groups;
574 if (!pt_ext->GetUserPermissionsForDevice(device_id, &consented_groups,
575 &disallowed_groups)) {
576 return kDeviceDisallowed;
579 if (consented_groups.empty() && disallowed_groups.empty()) {
580 return kDeviceHasNoConsent;
583 std::sort(list_of_permissions.begin(), list_of_permissions.end());
584 std::sort(consented_groups.begin(), consented_groups.end());
586 StringArray to_be_consented_by_user;
588 list_of_permissions.begin(),
589 list_of_permissions.end(),
590 consented_groups.begin(),
591 consented_groups.end(),
592 std::back_inserter(to_be_consented_by_user));
593 if (to_be_consented_by_user.empty()) {
594 return kDeviceAllowed;
597 return kDeviceDisallowed;
600 return kDeviceAllowed;
602 return kDeviceAllowed;
606 void PolicyManagerImpl::SetUserConsentForDevice(const std::string& device_id,
608 LOG4CXX_INFO(logger_, "SetUserConsentForDevice");
609 #if defined (EXTENDED_POLICY)
610 // TODO(AOleynik): Check design for more convenient access to policy ext data
611 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
614 LOG4CXX_WARN(logger_, "Can't set user consent for device");
618 // Get device permission groups from app_policies section, which hadn't been
620 policy_table::Strings groups;
621 policy_table::Strings preconsented_groups;
622 if (!pt_ext->GetDeviceGroupsFromPolicies(&groups, &preconsented_groups)) {
623 LOG4CXX_WARN(logger_, "Can't get device groups from policies.");
627 StringArray list_of_permissions;
629 groups.begin(), groups.end(),
630 FunctionalGroupInserter(preconsented_groups, list_of_permissions));
632 if (list_of_permissions.empty()) {
636 StringArray consented_groups;
637 StringArray disallowed_groups;
639 // Supposed only one group for device date consent
641 consented_groups.push_back(list_of_permissions[0]);
643 disallowed_groups.push_back(list_of_permissions[0]);
646 if (!pt_ext->SetUserPermissionsForDevice(device_id, consented_groups,
647 disallowed_groups)) {
648 LOG4CXX_WARN(logger_, "Can't set user consent for device");
654 bool PolicyManagerImpl::ReactOnUserDevConsentForApp(const std::string app_id,
655 bool is_device_allowed) {
656 #if defined (EXTENDED_POLICY)
657 // TODO(AOleynik): Check design for more convenient access to policy ext data
658 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
661 LOG4CXX_WARN(logger_, "Can't set user consent for device");
664 return pt_ext->ReactOnUserDevConsentForApp(app_id, is_device_allowed);
669 bool PolicyManagerImpl::GetInitialAppData(const std::string& application_id,
670 StringArray* nicknames,
671 StringArray* app_hmi_types) {
672 LOG4CXX_INFO(logger_, "GetInitialAppData");
673 return policy_table_.pt_data()->GetInitialAppData(application_id, nicknames,
677 void PolicyManagerImpl::SetDeviceInfo(const std::string& device_id,
678 const DeviceInfo& device_info) {
679 LOG4CXX_INFO(logger_, "SetDeviceInfo");
680 #if defined (EXTENDED_POLICY)
681 // TODO(AOleynik): Check design for more convenient access to policy ext data
682 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
685 if (!pt_ext->SetDeviceData(device_id, device_info.hardware,
686 device_info.firmware_rev, device_info.os,
687 device_info.os_ver, device_info.carrier,
688 device_info.max_number_rfcom_ports)) {
689 LOG4CXX_WARN(logger_, "Can't set device data.");
695 void PolicyManagerImpl::SetUserConsentForApp(
696 const PermissionConsent& permissions) {
697 LOG4CXX_INFO(logger_, "SetUserConsentForApp");
698 #if defined (EXTENDED_POLICY)
699 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
702 // TODO(AOleynik): Change device id to appropriate value (MAC with SHA-256)
704 if (!pt_ext->SetUserPermissionsForApp(permissions)) {
705 LOG4CXX_WARN(logger_, "Can't set user permissions for application.");
707 // Send OnPermissionChange notification, since consents were changed
708 std::vector<FunctionalGroupPermission> app_group_permissons;
709 GetUserPermissionsForApp(permissions.device_id,
710 permissions.policy_app_id,
711 app_group_permissons);
713 // Get current functional groups from DB with RPC permissions
714 policy_table::FunctionalGroupings functional_groups;
715 policy_table_.pt_data()->GetFunctionalGroupings(functional_groups);
717 // Get list of groups assigned to application
718 policy_table::Strings app_groups;
719 std::vector<FunctionalGroupPermission>::const_iterator it =
720 app_group_permissons.begin();
721 std::vector<FunctionalGroupPermission>::const_iterator it_end =
722 app_group_permissons.end();
723 for (; it != it_end; ++it) {
724 app_groups.push_back((*it).group_name);
727 // Fill notification data according to group permissions
728 Permissions notification_data;
729 PrepareNotificationData(functional_groups, app_groups,
730 app_group_permissons, notification_data);
732 std::string default_hmi;
733 pt_ext->GetDefaultHMI(permissions.policy_app_id, &default_hmi);
735 listener()->OnPermissionsUpdated(permissions.policy_app_id,
742 bool PolicyManagerImpl::GetDefaultHmi(const std::string& policy_app_id,
743 std::string* default_hmi) {
744 LOG4CXX_INFO(logger_, "GetDefaultHmi");
745 #if defined (EXTENDED_POLICY)
746 // TODO(AOleynik): Check design for more convenient access to policy ext data
747 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
750 LOG4CXX_WARN(logger_, "Can't get default hmi level.");
754 return pt_ext->GetDefaultHMI(policy_app_id, default_hmi);
760 bool PolicyManagerImpl::GetPriority(const std::string& policy_app_id,
761 std::string* priority) {
762 LOG4CXX_INFO(logger_, "GetPriority");
764 LOG4CXX_WARN(logger_, "Input priority parameter is null.");
767 #if defined (EXTENDED_POLICY)
768 // TODO(AOleynik): Check design for more convenient access to policy ext data
769 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
772 LOG4CXX_WARN(logger_, "Can't get priority.");
776 return pt_ext->GetPriority(policy_app_id, priority);
783 std::vector<UserFriendlyMessage> PolicyManagerImpl::GetUserFriendlyMessages(
784 const std::vector<std::string>& message_code, const std::string& language) {
785 #if defined (EXTENDED_POLICY)
786 // TODO(AOleynik): Check design for more convenient access to policy ext data
787 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
789 // For extended policy
791 return pt_ext->GetUserFriendlyMsg(message_code, language);
795 return policy_table_.pt_data()->GetUserFriendlyMsg(message_code, language);
798 void PolicyManagerImpl::GetUserConsentForApp(
799 const std::string& device_id, const std::string& policy_app_id,
800 std::vector<FunctionalGroupPermission>& permissions) {
801 LOG4CXX_INFO(logger_, "GetUserPermissionsForApp");
802 #if defined (EXTENDED_POLICY)
803 // TODO(KKolodiy): Check design for more convenient access to policy ext data
804 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
807 FunctionalIdType group_types;
808 if (!pt_ext->GetUserPermissionsForApp(device_id, policy_app_id,
810 LOG4CXX_WARN(logger_, "Can't get user permissions for app "
815 FunctionalGroupIDs all_groups = group_types[kTypeGeneral];
816 FunctionalGroupIDs preconsented_groups = group_types[kTypePreconsented];
817 FunctionalGroupIDs consent_allowed_groups = group_types[kTypeAllowed];
818 FunctionalGroupIDs consent_disallowed_groups = group_types[kTypeDisallowed];
819 FunctionalGroupIDs default_groups = group_types[kTypeDefault];
820 FunctionalGroupIDs predataconsented_groups =
821 group_types[kTypePreDataConsented];
822 FunctionalGroupIDs device_groups = group_types[kTypeDevice];
824 std::sort(all_groups.begin(), all_groups.end());
825 std::sort(preconsented_groups.begin(), preconsented_groups.end());
826 std::sort(consent_allowed_groups.begin(), consent_allowed_groups.end());
827 std::sort(consent_disallowed_groups.begin(), consent_disallowed_groups.end());
828 std::sort(default_groups.begin(), default_groups.end());
829 std::sort(predataconsented_groups.begin(), predataconsented_groups.end());
830 std::sort(device_groups.begin(), device_groups.end());
832 FunctionalGroupIDs allowed_preconsented;
833 std::set_difference(preconsented_groups.begin(), preconsented_groups.end(),
834 consent_disallowed_groups.begin(),
835 consent_disallowed_groups.end(),
836 std::back_inserter(allowed_preconsented));
837 FunctionalGroupIDs allowed_groups;
838 std::set_union(consent_allowed_groups.begin(), consent_allowed_groups.end(),
839 allowed_preconsented.begin(), allowed_preconsented.end(),
840 std::back_inserter(allowed_groups));
842 FunctionalGroupIDs first_excluded_groups;
843 std::set_union(default_groups.begin(), default_groups.end(),
844 predataconsented_groups.begin(), predataconsented_groups.end(),
845 std::back_inserter(first_excluded_groups));
846 FunctionalGroupIDs excluded_groups;
847 std::set_union(first_excluded_groups.begin(), first_excluded_groups.end(),
848 device_groups.begin(), device_groups.end(),
849 std::back_inserter(excluded_groups));
851 FunctionalGroupIDs only_needed_groups;
852 std::set_difference(all_groups.begin(), all_groups.end(),
853 excluded_groups.begin(), excluded_groups.end(),
854 std::back_inserter(only_needed_groups));
855 FunctionalGroupIDs no_disallowed_groups;
856 std::set_difference(only_needed_groups.begin(), only_needed_groups.end(),
857 consent_disallowed_groups.begin(),
858 consent_disallowed_groups.end(),
859 std::back_inserter(no_disallowed_groups));
860 FunctionalGroupIDs undefined_consent;
861 std::set_difference(no_disallowed_groups.begin(), no_disallowed_groups.end(),
862 allowed_groups.begin(), allowed_groups.end(),
863 std::back_inserter(undefined_consent));
865 FunctionalGroupNames group_names;
866 if (!pt_ext->GetFunctionalGroupNames(group_names)) {
867 LOG4CXX_WARN(logger_, "Can't get functional group names");
872 FillFunctionalGroupPermissions(undefined_consent, group_names,
873 kGroupUndefined, permissions);
874 FillFunctionalGroupPermissions(allowed_groups, group_names,
875 kGroupAllowed, permissions);
876 FillFunctionalGroupPermissions(consent_disallowed_groups, group_names,
877 kGroupDisallowed, permissions);
881 permissions = std::vector<FunctionalGroupPermission>();
885 void PolicyManagerImpl::GetUserPermissionsForApp(
886 const std::string& device_id, const std::string& policy_app_id,
887 std::vector<FunctionalGroupPermission>& permissions) {
888 LOG4CXX_INFO(logger_, "GetUserPermissionsForApp");
889 #if defined (EXTENDED_POLICY)
890 std::string app_id_to_check = policy_app_id;
892 DeviceConsent device_consent = GetUserConsentForDevice(device_id);
893 // Application is limited to pre_DataConsent permission until device is
895 if (kDeviceHasNoConsent == device_consent ||
896 kDeviceDisallowed == device_consent) {
897 app_id_to_check = kPreDataConsentId;
900 // TODO(AOleynik): Check design for more convenient access to policy ext data
901 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
903 // For extended policy
905 FunctionalIdType group_types;
906 if (!pt_ext->GetUserPermissionsForApp(device_id, app_id_to_check,
908 LOG4CXX_WARN(logger_, "Can't get user permissions for app "
913 FunctionalGroupIDs all_groups = group_types[kTypeGeneral];
914 // If application is limited to pre_Dataconsent only related groups are
916 FunctionalGroupIDs allowed_groups =
917 app_id_to_check == kPreDataConsentId ?
918 group_types[kTypeGeneral] :
919 group_types[kTypeAllowed];
920 FunctionalGroupIDs disallowed_groups = group_types[kTypeDisallowed];
921 FunctionalGroupIDs preconsented_groups = group_types[kTypePreconsented];
922 // If application is limited to pre_DataConsent - no default groups
923 // permissions should be used
924 FunctionalGroupIDs default_groups =
925 app_id_to_check == kPreDataConsentId ?
926 FunctionalGroupIDs() : group_types[kTypeDefault];
928 std::sort(all_groups.begin(), all_groups.end());
929 std::sort(allowed_groups.begin(), allowed_groups.end());
930 std::sort(disallowed_groups.begin(), disallowed_groups.end());
931 std::sort(preconsented_groups.begin(), preconsented_groups.end());
932 std::sort(default_groups.begin(), default_groups.end());
934 // Find groups with undefinded consent
935 FunctionalGroupIDs no_preconsented;
936 std::set_difference(all_groups.begin(), all_groups.end(),
937 preconsented_groups.begin(), preconsented_groups.end(),
938 std::back_inserter(no_preconsented));
939 FunctionalGroupIDs no_allowed_preconsented;
940 std::set_difference(no_preconsented.begin(), no_preconsented.end(),
941 allowed_groups.begin(), allowed_groups.end(),
942 std::back_inserter(no_allowed_preconsented));
943 FunctionalGroupIDs no_allowed_preconsented_default;
944 std::set_difference(no_allowed_preconsented.begin(),
945 no_allowed_preconsented.end(),
946 default_groups.begin(), default_groups.end(),
947 std::back_inserter(no_allowed_preconsented_default));
948 FunctionalGroupIDs undefined_consent;
949 std::set_difference(no_allowed_preconsented_default.begin(),
950 no_allowed_preconsented_default.end(),
951 disallowed_groups.begin(), disallowed_groups.end(),
952 std::back_inserter(undefined_consent));
954 // Find common allowed groups
955 FunctionalGroupIDs preconsented_allowed;
956 std::merge(allowed_groups.begin(), allowed_groups.end(),
957 preconsented_groups.begin(), preconsented_groups.end(),
958 std::back_inserter(preconsented_allowed));
959 FunctionalGroupIDs merged_allowed_preconsented(preconsented_allowed.begin(),
960 std::unique(preconsented_allowed.begin(),
961 preconsented_allowed.end()));
962 // Default groups are always allowed
963 FunctionalGroupIDs merged_allowed_preconsented_default;
964 std::merge(merged_allowed_preconsented.begin(),
965 merged_allowed_preconsented.end(),
966 default_groups.begin(), default_groups.end(),
967 std::back_inserter(merged_allowed_preconsented_default));
968 FunctionalGroupIDs common_allowed(
969 merged_allowed_preconsented_default.begin(),
970 std::unique(merged_allowed_preconsented_default.begin(),
971 merged_allowed_preconsented_default.end()));
974 // Find common disallowed groups
975 FunctionalGroupIDs common_disallowed;
976 std::set_difference(disallowed_groups.begin(), disallowed_groups.end(),
977 preconsented_groups.begin(), preconsented_groups.end(),
978 std::back_inserter(common_disallowed));
980 FunctionalGroupNames group_names;
981 if (!pt_ext->GetFunctionalGroupNames(group_names)) {
982 LOG4CXX_WARN(logger_, "Can't get functional group names");
987 FillFunctionalGroupPermissions(undefined_consent, group_names,
988 kGroupUndefined, permissions);
989 FillFunctionalGroupPermissions(common_allowed, group_names,
990 kGroupAllowed, permissions);
991 FillFunctionalGroupPermissions(common_disallowed, group_names,
992 kGroupDisallowed, permissions);
998 permissions = std::vector<FunctionalGroupPermission>();
1002 std::string& PolicyManagerImpl::GetCurrentDeviceId(
1003 const std::string& policy_app_id) {
1004 LOG4CXX_INFO(logger_, "GetDeviceInfo");
1006 listener()->OnCurrentDeviceIdUpdateRequired(policy_app_id);
1007 return last_device_id_;
1010 void PolicyManagerImpl::SetSystemLanguage(const std::string& language) {
1011 #if defined (EXTENDED_POLICY)
1012 // TODO(AOleynik): Check design for more convenient access to policy ext data
1013 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1016 pt_ext->SetSystemLanguage(language);
1022 void PolicyManagerImpl::SetSystemInfo(const std::string& ccpu_version,
1023 const std::string& wers_country_code,
1024 const std::string& language) {
1025 LOG4CXX_INFO(logger_, "SetSystemInfo");
1026 #if defined (EXTENDED_POLICY)
1027 // TODO(AOleynik): Check design for more convenient access to policy ext data
1028 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1031 pt_ext->SetMetaInfo(ccpu_version, wers_country_code, language);
1037 bool PolicyManagerImpl::ExceededIgnitionCycles() {
1038 return policy_table_.pt_data()->IgnitionCyclesBeforeExchange() == 0;
1041 bool PolicyManagerImpl::ExceededDays(int days) {
1042 return policy_table_.pt_data()->DaysBeforeExchange(days) == 0;
1045 bool PolicyManagerImpl::ExceededKilometers(int kilometers) {
1046 return policy_table_.pt_data()->KilometersBeforeExchange(kilometers) == 0;
1049 void PolicyManagerImpl::IncrementIgnitionCycles() {
1050 policy_table_.pt_data()->IncrementIgnitionCycles();
1053 int PolicyManagerImpl::NextRetryTimeout() {
1054 sync_primitives::AutoLock auto_lock(retry_sequence_lock_);
1055 LOG4CXX_DEBUG(logger_, "Index: " << retry_sequence_index_);
1057 if (!retry_sequence_seconds_.empty()
1058 && retry_sequence_index_ < retry_sequence_seconds_.size()) {
1059 next = retry_sequence_seconds_[retry_sequence_index_];
1060 ++retry_sequence_index_;
1065 void PolicyManagerImpl::RefreshRetrySequence() {
1066 sync_primitives::AutoLock auto_lock(retry_sequence_lock_);
1067 retry_sequence_timeout_ = policy_table_.pt_data()->TimeoutResponse();
1068 retry_sequence_seconds_.clear();
1069 policy_table_.pt_data()->SecondsBetweenRetries(&retry_sequence_seconds_);
1072 void PolicyManagerImpl::ResetRetrySequence() {
1073 sync_primitives::AutoLock auto_lock(retry_sequence_lock_);
1074 retry_sequence_index_ = 0;
1076 if (exchange_in_progress_) {
1077 set_exchange_pending(true);
1079 set_update_required(true);
1082 int PolicyManagerImpl::TimeoutExchange() {
1083 return retry_sequence_timeout_;
1086 const std::vector<int> PolicyManagerImpl::RetrySequenceDelaysSeconds() {
1087 sync_primitives::AutoLock auto_lock(retry_sequence_lock_);
1088 return retry_sequence_seconds_;
1091 void PolicyManagerImpl::OnExceededTimeout() {
1092 set_exchange_in_progress(false);
1095 void PolicyManagerImpl::PTUpdatedAt(int kilometers, int days_after_epoch) {
1096 LOG4CXX_INFO(logger_, "PTUpdatedAt");
1097 LOG4CXX_INFO(logger_,
1098 "Kilometers: " << kilometers << " Days: " << days_after_epoch);
1099 policy_table_.pt_data()->SetCountersPassedForSuccessfulUpdate(
1100 kilometers, days_after_epoch);
1101 policy_table_.pt_data()->ResetIgnitionCycles();
1104 void PolicyManagerImpl::Increment(usage_statistics::GlobalCounterId type) {
1105 std::string counter;
1107 case usage_statistics::IAP_BUFFER_FULL:
1108 counter = "count_of_iap_buffer_full";
1110 case usage_statistics::SYNC_OUT_OF_MEMORY:
1111 counter = "count_sync_out_of_memory";
1113 case usage_statistics::SYNC_REBOOTS:
1114 counter = "count_of_sync_reboots";
1117 LOG4CXX_INFO(logger_, "Type global counter is unknown");
1120 #if defined (EXTENDED_POLICY)
1121 // TODO(KKolodiy): Check design for more convenient access to policy ext data
1122 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1124 pt_ext->Increment(counter);
1128 void PolicyManagerImpl::Increment(const std::string& app_id,
1129 usage_statistics::AppCounterId type) {
1130 std::string counter;
1132 case usage_statistics::USER_SELECTIONS:
1133 counter = "count_of_user_selections";
1135 case usage_statistics::REJECTIONS_SYNC_OUT_OF_MEMORY:
1136 counter = "count_of_rejections_sync_out_of_memory";
1138 case usage_statistics::REJECTIONS_NICKNAME_MISMATCH:
1139 counter = "count_of_rejections_nickname_mismatch";
1141 case usage_statistics::REJECTIONS_DUPLICATE_NAME:
1142 counter = "count_of_rejections_duplicate_name";
1144 case usage_statistics::REJECTED_RPC_CALLS:
1145 counter = "count_of_ejected_rpc_calls";
1147 case usage_statistics::RPCS_IN_HMI_NONE:
1148 counter = "count_of_rpcs_sent_in_hmi_none";
1150 case usage_statistics::REMOVALS_MISBEHAVED:
1151 counter = "count_of_removals_misbehaved";
1153 case usage_statistics::RUN_ATTEMPTS_WHILE_REVOKED:
1154 counter = "count_of_run_attempts_while_revoked";
1157 LOG4CXX_INFO(logger_, "Type app counter is unknown");
1160 #if defined (EXTENDED_POLICY)
1161 // TODO(KKolodiy): Check design for more convenient access to policy ext data
1162 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1164 sync_primitives::AutoLock locker(statistics_lock_);
1165 pt_ext->Increment(app_id, counter);
1169 void PolicyManagerImpl::Set(const std::string& app_id,
1170 usage_statistics::AppInfoId type,
1171 const std::string& value) {
1174 case usage_statistics::LANGUAGE_GUI:
1175 info = "app_registration_language_gui";
1177 case usage_statistics::LANGUAGE_VUI:
1178 info = "app_registration_language_vui";
1181 LOG4CXX_INFO(logger_, "Type app info is unknown");
1185 #if defined (EXTENDED_POLICY)
1186 // TODO(KKolodiy): Check design for more convenient access to policy ext data
1187 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1189 sync_primitives::AutoLock locker(statistics_lock_);
1190 pt_ext->Set(app_id, info, value);
1194 void PolicyManagerImpl::Add(const std::string& app_id,
1195 usage_statistics::AppStopwatchId type,
1196 int32_t timespan_seconds) {
1197 #if defined (EXTENDED_POLICY)
1198 std::string stopwatch;
1200 // TODO(KKolodiy): rename fields in database
1201 case usage_statistics::SECONDS_HMI_FULL:
1202 stopwatch = "minutes_hmi_full";
1204 case usage_statistics::SECONDS_HMI_LIMITED:
1205 stopwatch = "minutes_hmi_limited";
1207 case usage_statistics::SECONDS_HMI_BACKGROUND:
1208 stopwatch = "minutes_hmi_background";
1210 case usage_statistics::SECONDS_HMI_NONE:
1211 stopwatch = "minutes_hmi_none";
1214 LOG4CXX_INFO(logger_, "Type app stopwatch is unknown");
1217 // TODO(KKolodiy): Check design for more convenient access to policy ext data
1218 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1220 sync_primitives::AutoLock locker(statistics_lock_);
1221 pt_ext->Add(app_id, stopwatch, timespan_seconds);
1225 bool PolicyManagerImpl::IsApplicationRevoked(const std::string& app_id) const {
1226 return policy_table_.pt_data()->IsApplicationRevoked(app_id);
1229 int PolicyManagerImpl::IsConsentNeeded(const std::string& app_id) {
1230 #if defined (EXTENDED_POLICY)
1231 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1233 const std::string device_id = GetCurrentDeviceId(app_id);
1235 if (pt_ext->CountUnconsentedGroups(app_id, device_id, &count)) {
1244 void PolicyManagerImpl::CheckUpdateStatus() {
1245 LOG4CXX_INFO(logger_, "CheckUpdateStatus");
1246 policy::PolicyTableStatus status = GetPolicyTableStatus();
1247 if (last_update_status_ != status) {
1248 listener_->OnUpdateStatusChanged(status);
1250 last_update_status_ = status;
1253 AppPermissions PolicyManagerImpl::GetAppPermissionsChanges(
1254 const std::string& app_id) {
1255 typedef std::map<std::string, AppPermissions>::const_iterator PermissionsIt;
1256 PermissionsIt app_id_diff = app_permissions_diff_.find(app_id);
1257 AppPermissions permissions(app_id);
1258 if (app_permissions_diff_.end() != app_id_diff) {
1259 permissions = app_id_diff->second;
1261 permissions.appPermissionsConsentNeeded = IsConsentNeeded(app_id);
1262 permissions.appRevoked = IsApplicationRevoked(app_id);
1263 GetPriority(permissions.application_id, &permissions.priority);
1268 void PolicyManagerImpl::RemovePendingPermissionChanges(
1269 const std::string& app_id) {
1270 app_permissions_diff_.erase(app_id);
1273 bool PolicyManagerImpl::CanAppKeepContext(const std::string& app_id) {
1274 #if defined (EXTENDED_POLICY)
1275 // TODO(AOleynik): Check design for more convenient access to policy ext data
1276 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1279 return pt_ext->CanAppKeepContext(app_id);
1287 bool PolicyManagerImpl::CanAppStealFocus(const std::string& app_id) {
1288 #if defined (EXTENDED_POLICY)
1289 // TODO(AOleynik): Check design for more convenient access to policy ext data
1290 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1293 return pt_ext->CanAppStealFocus(app_id);
1301 void PolicyManagerImpl::MarkUnpairedDevice(const std::string& device_id) {
1302 #ifdef EXTENDED_POLICY
1303 // TODO(KKolodiy): Check design for more convenient access to policy ext data
1304 PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1307 pt_ext->SetUnpairedDevice(device_id);
1308 SetUserConsentForDevice(device_id, false);
1310 #endif // EXTENDED_POLICY
1313 bool PolicyManagerImpl::ResetPT(const std::string& file_name) {
1314 return policy_table_.pt_data()->Clear() && LoadPTFromFile(file_name);
1317 bool PolicyManagerImpl::InitPT(const std::string& file_name) {
1319 InitResult init_result = policy_table_.pt_data()->Init();
1320 switch (init_result) {
1321 case InitResult::EXISTS: {
1322 LOG4CXX_INFO(logger_, "Policy Table exists, was loaded correctly.");
1325 case InitResult::SUCCESS: {
1326 LOG4CXX_INFO(logger_, "Policy Table was inited successfully");
1327 ret = LoadPTFromFile(file_name);
1329 case InitResult::FAIL:
1331 LOG4CXX_ERROR(logger_, "Failed to init policy table.");
1338 } // namespace policy