pull in new policy updates
[profile/ivi/smartdevicelink.git] / src / components / policy / src / policy / src / policy_manager_impl.cc
1 /*
2  Copyright (c) 2013, Ford Motor Company
3  All rights reserved.
4
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are met:
7
8  Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10
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
14  distribution.
15
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.
19
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.
31  */
32
33 #include <algorithm>
34 #include <set>
35 #include <iterator>
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"
44
45 policy::PolicyManager* CreateManager() {
46   return new policy::PolicyManagerImpl();
47 }
48
49 namespace {
50 void CheckPreloadedGroups(policy_table::ApplicationParams& app_param) {
51
52 }
53 }
54
55 namespace policy {
56
57 CREATE_LOGGERPTR_GLOBAL(logger_, "PolicyManagerImpl")
58
59 #if defined(__QNXNTO__) and defined(GCOV_ENABLED)
60 bool CheckGcov() {
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.");
64   return true;
65 }
66 bool check_gcov = CheckGcov();
67 #endif
68
69 PolicyManagerImpl::PolicyManagerImpl()
70   : PolicyManager(),
71     listener_(NULL),
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();
78 }
79
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();
88 }
89
90 void PolicyManagerImpl::set_listener(PolicyListener* listener) {
91   listener_ = listener;
92 }
93
94 PolicyManagerImpl::~PolicyManagerImpl() {
95   LOG4CXX_INFO(logger_, "Destroying policy manager.");
96   policy_table_.pt_data()->SaveUpdateRequired(update_required_);
97 }
98
99 bool PolicyManagerImpl::LoadPTFromFile(const std::string& file_name) {
100   LOG4CXX_INFO(logger_, "LoadPTFromFile: " << file_name);
101
102   BinaryMessage json_string;
103   bool final_result = false;
104   final_result = file_system::ReadBinaryFile(file_name, json_string);
105   if (!final_result) {
106     LOG4CXX_WARN(logger_, "Failed to read pt file.");
107     utils::SharedPtr<policy_table::Table> table = new policy_table::Table();
108     return final_result;
109   }
110   utils::SharedPtr<policy_table::Table> table = Parse(json_string);
111   if (!table) {
112     LOG4CXX_WARN(logger_, "Failed to parse policy table");
113     utils::SharedPtr<policy_table::Table> table = new policy_table::Table();
114     return false;
115   }
116   final_result = final_result && policy_table_.pt_data()->Save(*table);
117   LOG4CXX_INFO(
118     logger_,
119     "Loading from file was " << (final_result ? "successful" : "unsuccessful"));
120
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");
127       return final_result;
128     }
129   }
130
131   RefreshRetrySequence();
132   return final_result;
133 }
134
135 utils::SharedPtr<policy_table::Table> PolicyManagerImpl::Parse(
136   const BinaryMessage& pt_content) {
137   std::string json(pt_content.begin(), pt_content.end());
138   Json::Value value;
139   Json::Reader reader;
140   if (reader.parse(json.c_str(), value)) {
141     return new policy_table::Table(&value);
142   } else {
143     return utils::SharedPtr<policy_table::Table>();
144   }
145 }
146
147 bool PolicyManagerImpl::LoadPT(const std::string& file,
148                                const BinaryMessage& pt_content) {
149   LOG4CXX_INFO(logger_, "LoadPTFromString of size " << pt_content.size());
150
151   // Parse message into table struct
152   utils::SharedPtr<policy_table::Table> pt_update = Parse(pt_content);
153
154   if (!pt_update) {
155     LOG4CXX_WARN(logger_, "Parsed table pointer is 0.");
156     return false;
157   }
158
159 #if defined (EXTENDED_POLICY)
160   file_system::DeleteFile(file);
161 #endif
162
163   set_exchange_in_progress(false);
164
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));
169     return false;
170   }
171
172   // Check and update permissions for applications, send notifications
173   CheckPermissionsChanges(pt_update);
174
175   // Replace current data with updated
176   policy_table_snapshot_->policy_table.functional_groupings = pt_update
177       ->policy_table.functional_groupings;
178
179   policy_table_snapshot_->policy_table.module_config = pt_update->policy_table
180       .module_config;
181
182   bool is_message_part_updated = pt_update->policy_table
183                                  .consumer_friendly_messages.is_initialized();
184
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;
188   }
189
190   //policy_table.module_meta
191
192   // Save data to DB
193   if (!policy_table_.pt_data()->Save(*policy_table_snapshot_)) {
194     LOG4CXX_WARN(logger_, "Unsuccessful save of updated policy table.");
195     return false;
196   }
197
198   // Removing last app request from update requests
199   RemoveAppFromUpdateList();
200
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()) {
204     if (listener_) {
205       listener_->OnPTExchangeNeeded();
206     }
207   } else {
208     LOG4CXX_INFO(logger_, "Update request queue is empty.");
209   }
210
211   RefreshRetrySequence();
212   return true;
213 }
214
215 void PolicyManagerImpl::CheckPermissionsChanges(
216   const utils::SharedPtr<policy_table::Table> pt_update) {
217   LOG4CXX_INFO(logger_, "Checking incoming permissions.");
218
219   std::for_each(pt_update->policy_table.app_policies.begin(),
220                 pt_update->policy_table.app_policies.end(),
221                 CheckAppPolicy(this, pt_update));
222 }
223
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) {
229
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);
233 }
234
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;
240   CheckUpdateStatus();
241 }
242
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;
248   CheckUpdateStatus();
249 }
250
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;
255   CheckUpdateStatus();
256 }
257
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(),
265         application_id);
266   if (it == update_requests_list_.end()) {
267     update_requests_list_.push_back(application_id);
268   }
269 }
270
271 void PolicyManagerImpl::RemoveAppFromUpdateList() {
272   sync_primitives::AutoLock lock(update_request_list_lock_);
273   if (update_requests_list_.empty()) {
274     return;
275   }
276   LOG4CXX_INFO(
277     logger_,
278     "Removing application " << update_requests_list_.front() << " from update list");
279   update_requests_list_.pop_front();
280 }
281
282 std::string PolicyManagerImpl::GetUpdateUrl(int service_type) {
283   LOG4CXX_INFO(logger_, "PolicyManagerImpl::GetUpdateUrl");
284   EndpointUrls urls = policy_table_.pt_data()->GetUpdateUrls(service_type);
285
286   static int index = 0;
287   std::string url;
288   if (index < urls.size()) {
289     url = urls[index].url;
290   } else if (!urls.empty()) {
291     index = 0;
292     url = urls[index].url;
293   }
294   ++index;
295
296   return url;
297 }
298
299 EndpointUrls PolicyManagerImpl::GetUpdateUrls(int service_type) {
300   LOG4CXX_INFO(logger_, "PolicyManagerImpl::GetUpdateUrls");
301   return policy_table_.pt_data()->GetUpdateUrls(service_type);
302 }
303
304 BinaryMessageSptr PolicyManagerImpl::RequestPTUpdate() {
305   LOG4CXX_INFO(logger_, "Creating PT Snapshot");
306
307   // Update policy table for the first time with system information
308   if (policy_table_.pt_data()->IsPTPreloaded()) {
309     listener()->OnSystemInfoUpdateRequired();
310   }
311
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");
315     return NULL;
316   }
317
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);
324       continue;
325     }
326     if (policy_table_.pt_data()->IsPredataPolicy(it->first)) {
327       it->second.set_to_string(kPreDataConsentId);
328       continue;
329     }
330   }
331
332   if (!exchange_pending_) {
333     set_update_required(false);
334   }
335
336   set_exchange_in_progress(true);
337   set_exchange_pending(false);
338
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_
342                                 .pt_data().get());
343   if (pt_ext) {
344     pt_ext->UnpairedDevicesList(&unpaired_device_ids_);
345   }
346 #endif  // EXTENDED_POLICY
347
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());
352 }
353
354 CheckPermissionResult PolicyManagerImpl::CheckPermissions(
355   const PTString& app_id, const PTString& hmi_level, const PTString& rpc) {
356   LOG4CXX_INFO(
357     logger_,
358     "CheckPermissions for " << app_id << " and rpc " << rpc << " for "
359     << hmi_level << " level.");
360
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);
366
367   // Fill struct with known groups RPCs
368   policy_table::FunctionalGroupings functional_groupings;
369   policy_table_.pt_data()->GetFunctionalGroupings(functional_groupings);
370
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);
378   }
379
380   Permissions rpc_permissions;
381   PrepareNotificationData(functional_groupings, app_groups,
382                           app_group_permissions, rpc_permissions);
383
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
389     return result;
390   }
391
392   // Check HMI level
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;
397   }
398
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;
403   }
404
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));
410
411   return result;
412 #else
413   return policy_table_.pt_data()->CheckPermissions(app_id, hmi_level, rpc);
414 #endif
415 }
416
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_
421                                 .pt_data().get());
422   if (pt_ext) {
423     return pt_ext->ResetUserConsent();
424   }
425   return false;
426 #else
427   return true;
428 #endif
429 }
430
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)) {
436     LOG4CXX_INFO(
437       logger_,
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_
443                                     .pt_data().get());
444       if (!pt_ext) {
445         LOG4CXX_WARN(logger_, "Can't cleanup unpaired devices.");
446         return;
447       }
448       pt_ext->SetPredataPolicy(application_id);
449     } else {
450       policy_table_.pt_data()->SetDefaultPolicy(application_id);
451     }
452 #else
453     policy_table_.pt_data()->SetDefaultPolicy(application_id);
454 #endif
455     SendNotificationOnPermissionsUpdated(application_id);
456   } else {
457     if (!policy_table_.pt_data()->IsDefaultPolicy(application_id)
458         || (kDeviceHasNoConsent != device_consent
459             && policy_table_.pt_data()->IsPredataPolicy(application_id))) {
460       return;
461     }
462   }
463
464   AddAppToUpdateList(application_id);
465
466   if (PolicyTableStatus::StatusUpToDate == GetPolicyTableStatus()) {
467     set_update_required(true);
468   } else {
469     set_exchange_pending(true);
470   }
471 }
472
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 << "'");
479     return;
480   }
481
482   std::vector<FunctionalGroupPermission> app_group_permissions;
483   GetUserPermissionsForApp(device_id, application_id, app_group_permissions);
484
485   policy_table::FunctionalGroupings functional_groupings;
486   policy_table_.pt_data()->GetFunctionalGroupings(functional_groupings);
487
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);
495   }
496
497   Permissions notification_data;
498   PrepareNotificationData(functional_groupings, app_groups, app_group_permissions,
499                           notification_data);
500
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_
504                                 .pt_data().get());
505   if (!pt_ext) {
506     LOG4CXX_WARN(logger_, "Can't get default hmi level for " << application_id);
507     return;
508   }
509
510   pt_ext->GetDefaultHMI(application_id, &default_hmi);
511   listener()->OnPermissionsUpdated(application_id, notification_data,
512                                    default_hmi);
513 }
514
515 bool PolicyManagerImpl::CleanupUnpairedDevices() {
516   LOG4CXX_INFO(logger_, "CleanupUnpairedDevices");
517 #ifdef EXTENDED_POLICY
518   PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
519                                 .pt_data().get());
520   if (!pt_ext) {
521     LOG4CXX_WARN(logger_, "Can't cleanup unpaired devices.");
522     return false;
523   }
524
525   return pt_ext->CleanupUnpairedDevices(unpaired_device_ids_);
526 #else  // EXTENDED_POLICY
527   // For SDL-specific it doesn't matter
528   return true;
529 #endif  // EXTENDED_POLICY
530 }
531
532 PolicyTableStatus PolicyManagerImpl::GetPolicyTableStatus() {
533   if (!exchange_in_progress_ && !exchange_pending_ && !update_required_) {
534     return PolicyTableStatus::StatusUpToDate;
535   }
536
537   if (update_required_ && !exchange_in_progress_ && !exchange_pending_) {
538     return PolicyTableStatus::StatusUpdateRequired;
539   }
540
541   return PolicyTableStatus::StatusUpdatePending;
542 }
543
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_
550                                 .pt_data().get());
551   if (!pt_ext) {
552     LOG4CXX_WARN(logger_, "Can't get user consent for device");
553     return kDeviceDisallowed;
554   }
555
556   // Get device permission groups from app_policies section, which hadn't been
557   // preconsented
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;
563   }
564
565   StringArray list_of_permissions;
566   std::for_each(
567     groups.begin(), groups.end(),
568     FunctionalGroupInserter(preconsented_groups, list_of_permissions));
569
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;
577     }
578
579     if (consented_groups.empty() && disallowed_groups.empty()) {
580       return kDeviceHasNoConsent;
581     }
582
583     std::sort(list_of_permissions.begin(), list_of_permissions.end());
584     std::sort(consented_groups.begin(), consented_groups.end());
585
586     StringArray to_be_consented_by_user;
587     std::set_difference(
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;
595     }
596
597     return kDeviceDisallowed;
598   }
599
600   return kDeviceAllowed;
601 #else
602   return kDeviceAllowed;
603 #endif
604 }
605
606 void PolicyManagerImpl::SetUserConsentForDevice(const std::string& device_id,
607     bool is_allowed) {
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_
612                                 .pt_data().get());
613   if (!pt_ext) {
614     LOG4CXX_WARN(logger_, "Can't set user consent for device");
615     return;
616   }
617
618   // Get device permission groups from app_policies section, which hadn't been
619   // preconsented
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.");
624     return;
625   }
626
627   StringArray list_of_permissions;
628   std::for_each(
629     groups.begin(), groups.end(),
630     FunctionalGroupInserter(preconsented_groups, list_of_permissions));
631
632   if (list_of_permissions.empty()) {
633     return;
634   }
635
636   StringArray consented_groups;
637   StringArray disallowed_groups;
638
639   // Supposed only one group for device date consent
640   if (is_allowed) {
641     consented_groups.push_back(list_of_permissions[0]);
642   } else {
643     disallowed_groups.push_back(list_of_permissions[0]);
644   }
645
646   if (!pt_ext->SetUserPermissionsForDevice(device_id, consented_groups,
647       disallowed_groups)) {
648     LOG4CXX_WARN(logger_, "Can't set user consent for device");
649     return;
650   }
651 #endif
652 }
653
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_
659                                 .pt_data().get());
660   if (!pt_ext) {
661     LOG4CXX_WARN(logger_, "Can't set user consent for device");
662     return false;
663   }
664   return pt_ext->ReactOnUserDevConsentForApp(app_id, is_device_allowed);
665 #endif
666   return true;
667 }
668
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,
674          app_hmi_types);
675 }
676
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_
683                                 .pt_data().get());
684   if (pt_ext) {
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.");
690     }
691   }
692 #endif
693 }
694
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_
700                                 .pt_data().get());
701   if (pt_ext) {
702     // TODO(AOleynik): Change device id to appropriate value (MAC with SHA-256)
703     // in parameters
704     if (!pt_ext->SetUserPermissionsForApp(permissions)) {
705       LOG4CXX_WARN(logger_, "Can't set user permissions for application.");
706     }
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);
712
713     // Get current functional groups from DB with RPC permissions
714     policy_table::FunctionalGroupings functional_groups;
715     policy_table_.pt_data()->GetFunctionalGroupings(functional_groups);
716
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);
725     }
726
727     // Fill notification data according to group permissions
728     Permissions notification_data;
729     PrepareNotificationData(functional_groups, app_groups,
730                             app_group_permissons, notification_data);
731
732     std::string default_hmi;
733     pt_ext->GetDefaultHMI(permissions.policy_app_id, &default_hmi);
734
735     listener()->OnPermissionsUpdated(permissions.policy_app_id,
736                                      notification_data,
737                                      default_hmi);
738   }
739 #endif
740 }
741
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_
748                                 .pt_data().get());
749   if (!pt_ext) {
750     LOG4CXX_WARN(logger_, "Can't get default hmi level.");
751     return false;
752   }
753
754   return pt_ext->GetDefaultHMI(policy_app_id, default_hmi);
755 #else
756   return false;
757 #endif
758 }
759
760 bool PolicyManagerImpl::GetPriority(const std::string& policy_app_id,
761                                     std::string* priority) {
762   LOG4CXX_INFO(logger_, "GetPriority");
763   if (!priority) {
764     LOG4CXX_WARN(logger_, "Input priority parameter is null.");
765     return false;
766   }
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_
770                                 .pt_data().get());
771   if (!pt_ext) {
772     LOG4CXX_WARN(logger_, "Can't get priority.");
773     return false;
774   }
775
776   return pt_ext->GetPriority(policy_app_id, priority);
777 #else
778   priority->clear();
779   return true;
780 #endif
781 }
782
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_
788                                 .pt_data().get());
789   // For extended policy
790   if (pt_ext) {
791     return pt_ext->GetUserFriendlyMsg(message_code, language);
792   }
793 #endif
794   // For basic policy
795   return policy_table_.pt_data()->GetUserFriendlyMsg(message_code, language);
796 }
797
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_
805                                 .pt_data().get());
806   if (pt_ext) {
807     FunctionalIdType group_types;
808     if (!pt_ext->GetUserPermissionsForApp(device_id, policy_app_id,
809                                           &group_types)) {
810       LOG4CXX_WARN(logger_, "Can't get user permissions for app "
811                    << policy_app_id);
812       return;
813     }
814
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];
823
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());
831
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));
841
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));
850
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));
864
865     FunctionalGroupNames group_names;
866     if (!pt_ext->GetFunctionalGroupNames(group_names)) {
867       LOG4CXX_WARN(logger_, "Can't get functional group names");
868       return;
869     }
870
871     // Fill result
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);
878   }
879 #else
880   // For basic policy
881   permissions = std::vector<FunctionalGroupPermission>();
882 #endif
883 }
884
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;
891
892   DeviceConsent device_consent = GetUserConsentForDevice(device_id);
893   // Application is limited to pre_DataConsent permission until device is
894   // allowed by user
895   if (kDeviceHasNoConsent == device_consent ||
896       kDeviceDisallowed == device_consent) {
897     app_id_to_check = kPreDataConsentId;
898   }
899
900   // TODO(AOleynik): Check design for more convenient access to policy ext data
901   PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
902                                 .pt_data().get());
903   // For extended policy
904   if (pt_ext) {
905     FunctionalIdType group_types;
906     if (!pt_ext->GetUserPermissionsForApp(device_id, app_id_to_check,
907                                           &group_types)) {
908       LOG4CXX_WARN(logger_, "Can't get user permissions for app "
909                    << policy_app_id);
910       return;
911     }
912
913     FunctionalGroupIDs all_groups = group_types[kTypeGeneral];
914     // If application is limited to pre_Dataconsent only related groups are
915     // allowed
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];
927
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());
933
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));
953
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()));
972
973
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));
979
980     FunctionalGroupNames group_names;
981     if (!pt_ext->GetFunctionalGroupNames(group_names)) {
982       LOG4CXX_WARN(logger_, "Can't get functional group names");
983       return;
984     }
985
986     // Fill result
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);
993
994     return;
995   }
996 #else
997   // For basic policy
998   permissions = std::vector<FunctionalGroupPermission>();
999 #endif
1000 }
1001
1002 std::string& PolicyManagerImpl::GetCurrentDeviceId(
1003   const std::string& policy_app_id) {
1004   LOG4CXX_INFO(logger_, "GetDeviceInfo");
1005   last_device_id_ =
1006     listener()->OnCurrentDeviceIdUpdateRequired(policy_app_id);
1007   return last_device_id_;
1008 }
1009
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_
1014                                 .pt_data().get());
1015   if (pt_ext) {
1016     pt_ext->SetSystemLanguage(language);
1017     return;
1018   }
1019 #endif
1020 }
1021
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_
1029                                 .pt_data().get());
1030   if (pt_ext) {
1031     pt_ext->SetMetaInfo(ccpu_version, wers_country_code, language);
1032     return;
1033   }
1034 #endif
1035 }
1036
1037 bool PolicyManagerImpl::ExceededIgnitionCycles() {
1038   return policy_table_.pt_data()->IgnitionCyclesBeforeExchange() == 0;
1039 }
1040
1041 bool PolicyManagerImpl::ExceededDays(int days) {
1042   return policy_table_.pt_data()->DaysBeforeExchange(days) == 0;
1043 }
1044
1045 bool PolicyManagerImpl::ExceededKilometers(int kilometers) {
1046   return policy_table_.pt_data()->KilometersBeforeExchange(kilometers) == 0;
1047 }
1048
1049 void PolicyManagerImpl::IncrementIgnitionCycles() {
1050   policy_table_.pt_data()->IncrementIgnitionCycles();
1051 }
1052
1053 int PolicyManagerImpl::NextRetryTimeout() {
1054   sync_primitives::AutoLock auto_lock(retry_sequence_lock_);
1055   LOG4CXX_DEBUG(logger_, "Index: " << retry_sequence_index_);
1056   int next = 0;
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_;
1061   }
1062   return next;
1063 }
1064
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_);
1070 }
1071
1072 void PolicyManagerImpl::ResetRetrySequence() {
1073   sync_primitives::AutoLock auto_lock(retry_sequence_lock_);
1074   retry_sequence_index_ = 0;
1075
1076   if (exchange_in_progress_) {
1077     set_exchange_pending(true);
1078   }
1079   set_update_required(true);
1080 }
1081
1082 int PolicyManagerImpl::TimeoutExchange() {
1083   return retry_sequence_timeout_;
1084 }
1085
1086 const std::vector<int> PolicyManagerImpl::RetrySequenceDelaysSeconds() {
1087   sync_primitives::AutoLock auto_lock(retry_sequence_lock_);
1088   return retry_sequence_seconds_;
1089 }
1090
1091 void PolicyManagerImpl::OnExceededTimeout() {
1092   set_exchange_in_progress(false);
1093 }
1094
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();
1102 }
1103
1104 void PolicyManagerImpl::Increment(usage_statistics::GlobalCounterId type) {
1105   std::string counter;
1106   switch (type) {
1107     case usage_statistics::IAP_BUFFER_FULL:
1108       counter = "count_of_iap_buffer_full";
1109       break;
1110     case usage_statistics::SYNC_OUT_OF_MEMORY:
1111       counter = "count_sync_out_of_memory";
1112       break;
1113     case usage_statistics::SYNC_REBOOTS:
1114       counter = "count_of_sync_reboots";
1115       break;
1116     default:
1117       LOG4CXX_INFO(logger_, "Type global counter is unknown");
1118       return;
1119   }
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_
1123                                 .pt_data().get());
1124   pt_ext->Increment(counter);
1125 #endif
1126 }
1127
1128 void PolicyManagerImpl::Increment(const std::string& app_id,
1129                                   usage_statistics::AppCounterId type) {
1130   std::string counter;
1131   switch (type) {
1132     case usage_statistics::USER_SELECTIONS:
1133       counter = "count_of_user_selections";
1134       break;
1135     case usage_statistics::REJECTIONS_SYNC_OUT_OF_MEMORY:
1136       counter = "count_of_rejections_sync_out_of_memory";
1137       break;
1138     case usage_statistics::REJECTIONS_NICKNAME_MISMATCH:
1139       counter = "count_of_rejections_nickname_mismatch";
1140       break;
1141     case usage_statistics::REJECTIONS_DUPLICATE_NAME:
1142       counter = "count_of_rejections_duplicate_name";
1143       break;
1144     case usage_statistics::REJECTED_RPC_CALLS:
1145       counter = "count_of_ejected_rpc_calls";
1146       break;
1147     case usage_statistics::RPCS_IN_HMI_NONE:
1148       counter = "count_of_rpcs_sent_in_hmi_none";
1149       break;
1150     case usage_statistics::REMOVALS_MISBEHAVED:
1151       counter = "count_of_removals_misbehaved";
1152       break;
1153     case usage_statistics::RUN_ATTEMPTS_WHILE_REVOKED:
1154       counter = "count_of_run_attempts_while_revoked";
1155       break;
1156     default:
1157       LOG4CXX_INFO(logger_, "Type app counter is unknown");
1158       return;
1159   }
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_
1163                                 .pt_data().get());
1164   sync_primitives::AutoLock locker(statistics_lock_);
1165   pt_ext->Increment(app_id, counter);
1166 #endif
1167 }
1168
1169 void PolicyManagerImpl::Set(const std::string& app_id,
1170                             usage_statistics::AppInfoId type,
1171                             const std::string& value) {
1172   std::string info;
1173   switch (type) {
1174     case usage_statistics::LANGUAGE_GUI:
1175       info = "app_registration_language_gui";
1176       break;
1177     case usage_statistics::LANGUAGE_VUI:
1178       info = "app_registration_language_vui";
1179       break;
1180     default:
1181       LOG4CXX_INFO(logger_, "Type app info is unknown");
1182       return;
1183   }
1184
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_
1188                                 .pt_data().get());
1189   sync_primitives::AutoLock locker(statistics_lock_);
1190   pt_ext->Set(app_id, info, value);
1191 #endif
1192 }
1193
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;
1199   switch (type) {
1200     // TODO(KKolodiy): rename fields in database
1201     case usage_statistics::SECONDS_HMI_FULL:
1202       stopwatch = "minutes_hmi_full";
1203       break;
1204     case usage_statistics::SECONDS_HMI_LIMITED:
1205       stopwatch = "minutes_hmi_limited";
1206       break;
1207     case usage_statistics::SECONDS_HMI_BACKGROUND:
1208       stopwatch = "minutes_hmi_background";
1209       break;
1210     case usage_statistics::SECONDS_HMI_NONE:
1211       stopwatch = "minutes_hmi_none";
1212       break;
1213     default:
1214       LOG4CXX_INFO(logger_, "Type app stopwatch is unknown");
1215       return;
1216   }
1217   // TODO(KKolodiy): Check design for more convenient access to policy ext data
1218   PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1219                                 .pt_data().get());
1220   sync_primitives::AutoLock locker(statistics_lock_);
1221   pt_ext->Add(app_id, stopwatch, timespan_seconds);
1222 #endif
1223 }
1224
1225 bool PolicyManagerImpl::IsApplicationRevoked(const std::string& app_id) const {
1226   return policy_table_.pt_data()->IsApplicationRevoked(app_id);
1227 }
1228
1229 int PolicyManagerImpl::IsConsentNeeded(const std::string& app_id) {
1230 #if defined (EXTENDED_POLICY)
1231   PTExtRepresentation* pt_ext = dynamic_cast<PTExtRepresentation*>(policy_table_
1232                                 .pt_data().get());
1233   const std::string device_id = GetCurrentDeviceId(app_id);
1234   int count = 0;
1235   if (pt_ext->CountUnconsentedGroups(app_id, device_id, &count)) {
1236     return count;
1237   } else {
1238     return 0;
1239   }
1240 #endif
1241   return 0;
1242 }
1243
1244 void PolicyManagerImpl::CheckUpdateStatus() {
1245   LOG4CXX_INFO(logger_, "CheckUpdateStatus");
1246   policy::PolicyTableStatus status = GetPolicyTableStatus();
1247   if (last_update_status_ != status) {
1248     listener_->OnUpdateStatusChanged(status);
1249   }
1250   last_update_status_ = status;
1251 }
1252
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;
1260   } else {
1261     permissions.appPermissionsConsentNeeded = IsConsentNeeded(app_id);
1262     permissions.appRevoked = IsApplicationRevoked(app_id);
1263     GetPriority(permissions.application_id, &permissions.priority);
1264   }
1265   return permissions;
1266 }
1267
1268 void PolicyManagerImpl::RemovePendingPermissionChanges(
1269   const std::string& app_id) {
1270   app_permissions_diff_.erase(app_id);
1271 }
1272
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_
1277                                 .pt_data().get());
1278   if (pt_ext) {
1279     return pt_ext->CanAppKeepContext(app_id);
1280   }
1281   return false;
1282 #else
1283   return false;
1284 #endif
1285 }
1286
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_
1291                                 .pt_data().get());
1292   if (pt_ext) {
1293     return pt_ext->CanAppStealFocus(app_id);
1294   }
1295   return false;
1296 #else
1297   return false;
1298 #endif
1299 }
1300
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_
1305                                 .pt_data().get());
1306   if (pt_ext) {
1307     pt_ext->SetUnpairedDevice(device_id);
1308     SetUserConsentForDevice(device_id, false);
1309   }
1310 #endif  // EXTENDED_POLICY
1311 }
1312
1313 bool PolicyManagerImpl::ResetPT(const std::string& file_name) {
1314   return policy_table_.pt_data()->Clear() && LoadPTFromFile(file_name);
1315 }
1316
1317 bool PolicyManagerImpl::InitPT(const std::string& file_name) {
1318   bool ret = false;
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.");
1323       ret = true;
1324     } break;
1325     case InitResult::SUCCESS: {
1326       LOG4CXX_INFO(logger_, "Policy Table was inited successfully");
1327       ret = LoadPTFromFile(file_name);
1328     } break;
1329     case InitResult::FAIL:
1330     default: {
1331       LOG4CXX_ERROR(logger_, "Failed to init policy table.");
1332       ret = false;
1333     }
1334   }
1335   return ret;
1336 }
1337
1338 }  //  namespace policy
1339