diff options
Diffstat (limited to 'src/components/policy/policy_external/src')
14 files changed, 14194 insertions, 0 deletions
diff --git a/src/components/policy/policy_external/src/cache_manager.cc b/src/components/policy/policy_external/src/cache_manager.cc new file mode 100644 index 0000000000..22040c88b2 --- /dev/null +++ b/src/components/policy/policy_external/src/cache_manager.cc @@ -0,0 +1,2664 @@ +/* + * Copyright (c) 2014, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "policy/cache_manager.h" + +#include <algorithm> +#include <functional> +#include <ctime> +#include <cmath> +#include <utility> +#include <string> +#include <vector> + +#include "utils/file_system.h" +#include "json/reader.h" +#include "json/features.h" +#include "json/writer.h" +#include "utils/logger.h" +#include "utils/date_time.h" +#include "utils/gen_hash.h" +#include "utils/threads/thread.h" +#include "utils/threads/thread_delegate.h" +#include "rpc_base/rpc_base.h" +#include "policy/policy_table/enums.h" +#include "policy/policy_helper.h" +#include "policy/sql_pt_ext_representation.h" + +namespace policy_table = rpc::policy_table_interface_base; + +namespace { + +/** + * @brief Looks for ExternalConsent entity in the list of entities + * @param entities ExternalConsent entities list + * @param entity Entity to look for + * @return True if found in the list, otherwise - false + */ +bool IsEntityExists( + const policy_table::DisallowedByExternalConsentEntities& entities, + const policy_table::ExternalConsentEntity& entity) { + const policy_table::DisallowedByExternalConsentEntities::const_iterator + it_entity = std::find(entities.begin(), entities.end(), entity); + + return entities.end() != it_entity; +} + +/** + * @brief Looks for ExternalConsent entity in + * disallowed_by_external_consent_entities_on/off sections + * of each functional group + */ +struct GroupByEntityFinder + : public std::unary_function< + void, + const policy_table::FunctionalGroupings::value_type&> { + GroupByEntityFinder( + const policy::ExternalConsentStatusItem& external_consent_item, + policy::GroupsByExternalConsentStatus& out_groups_by_external_consent) + : external_consent_item_(external_consent_item) + , out_groups_by_external_consent_(out_groups_by_external_consent) {} + + void operator()( + const policy_table::FunctionalGroupings::value_type& group) const { + if (!group.second.user_consent_prompt.is_initialized()) { + return; + } + + policy_table::ExternalConsentEntity entity( + external_consent_item_.entity_type_, external_consent_item_.entity_id_); + const std::string group_name = group.first; + + if (IsEntityExists(*group.second.disallowed_by_external_consent_entities_on, + entity)) { + const bool disallowed_by_external_consent_entities_on_marker = true; + out_groups_by_external_consent_[external_consent_item_].push_back( + std::make_pair(group_name, + disallowed_by_external_consent_entities_on_marker)); + } + + if (IsEntityExists( + *group.second.disallowed_by_external_consent_entities_off, + entity)) { + const bool disallowed_by_external_consent_entities_off_marker = false; + out_groups_by_external_consent_[external_consent_item_].push_back( + std::make_pair(group_name, + disallowed_by_external_consent_entities_off_marker)); + } + } + + private: + const policy::ExternalConsentStatusItem& external_consent_item_; + policy::GroupsByExternalConsentStatus& out_groups_by_external_consent_; +}; + +/** + * @brief Maps ExternalConsent status item to the list of functional groups + * names specifying + * container where item is found. If item is not found it won't be added. + */ +struct GroupByExternalConsentItemFinder + : public std::unary_function< + void, + const policy::ExternalConsentStatus::value_type&> { + GroupByExternalConsentItemFinder( + const policy_table::FunctionalGroupings& groups, + policy::GroupsByExternalConsentStatus& out_groups_by_external_consent) + : groups_(groups), out_groups_by_css_(out_groups_by_external_consent) {} + + void operator()(const policy::ExternalConsentStatus::value_type& + external_consent_item) const { + GroupByEntityFinder group_finder(external_consent_item, out_groups_by_css_); + std::for_each(groups_.begin(), groups_.end(), group_finder); + } + + private: + const policy_table::FunctionalGroupings& groups_; + policy::GroupsByExternalConsentStatus& out_groups_by_css_; +}; + +/** + * @brief Template for getting 'first' of std::pair to use with standard + * algorithm below + */ +template <typename T1, typename T2> +const T1& pair_first(const std::pair<T1, T2>& item) { + return item.first; +} + +/** + * @brief Collects known links device-to-application form + * device_data/user_consent_records is any record is present + */ +struct LinkCollector + : public std::unary_function<void, + const policy_table::DeviceData::value_type&> { + typedef std::vector<policy_table::UserConsentRecords::key_type> + ApplicationsIds; + + LinkCollector(std::map<std::string, std::string>& links) : links_(links) {} + + void operator()(const policy_table::DeviceData::value_type& value) { + using namespace policy_table; + + device_id_ = value.first; + + ApplicationsIds applications_ids; + std::transform(value.second.user_consent_records->begin(), + value.second.user_consent_records->end(), + std::back_inserter(applications_ids), + &pair_first<UserConsentRecords::key_type, + UserConsentRecords::mapped_type>); + + std::for_each(applications_ids.begin(), + applications_ids.end(), + std::bind1st(std::mem_fun(&LinkCollector::FillLinks), this)); + } + + private: + void FillLinks(const ApplicationsIds::value_type app_id) const { + links_.insert(std::make_pair(device_id_, app_id)); + } + + std::string device_id_; + std::map<std::string, std::string>& links_; +}; + +/** + * @brief Returns group consent record constructed from input group permissions + */ +struct ExternalConsentConsentGroupAppender + : public std::unary_function<policy_table::ConsentGroups, + const policy::FunctionalGroupPermission&> { + policy_table::ConsentGroups::value_type operator()( + const policy::FunctionalGroupPermission& value) const { + return std::make_pair(value.group_name, + rpc::Boolean(value.state == policy::kGroupAllowed)); + } +}; + +} // namespace + +namespace policy { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +#define CACHE_MANAGER_CHECK(return_value) \ + { \ + if (!pt_) { \ + LOG4CXX_WARN(logger_, "The cache manager is not initialized"); \ + return return_value; \ + } \ + } + +#define CACHE_MANAGER_CHECK_VOID() \ + { \ + if (!pt_) { \ + LOG4CXX_WARN(logger_, "The cache manager is not initialized"); \ + return; \ + } \ + } + +struct LanguageFinder { + explicit LanguageFinder(const std::string& language) : language_(language) {} + bool operator()(const policy_table::Languages::value_type& lang) const { + return !strcasecmp(language_.c_str(), lang.first.c_str()); + } + + private: + const std::string& language_; +}; + +policy_table::MessageString FindLanguage( + const policy_table::MessageLanguages& msg_languages, + const std::string& lang) { + LanguageFinder finder(lang); + policy_table::Languages::const_iterator it = std::find_if( + msg_languages.languages.begin(), msg_languages.languages.end(), finder); + return (msg_languages.languages.end() == it) ? policy_table::MessageString() + : it->second; +} + +CacheManager::CacheManager() + : CacheManagerInterface() + , pt_(new policy_table::Table) + , backup_(new SQLPTExtRepresentation()) + , update_required(false) { + InitBackupThread(); +} + +CacheManager::CacheManager(bool in_memory) + : CacheManagerInterface() + , pt_(new policy_table::Table) + , backup_(new SQLPTExtRepresentation(in_memory)) + , update_required(false) { + InitBackupThread(); +} + +CacheManager::~CacheManager() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(backuper_locker_); + backup_thread_->join(); + delete backup_thread_->delegate(); + threads::DeleteThread(backup_thread_); +} + +ConsentPriorityType CacheManager::GetConsentsPriority( + const std::string& device_id, const std::string& application_id) const { + LOG4CXX_AUTO_TRACE(logger_); + ConsentPriorityType prio_type = ConsentPriorityType::kExternalConsentPrio; + CACHE_MANAGER_CHECK(prio_type); + policy_table::DeviceData::const_iterator dev_params_iter = + pt_->policy_table.device_data->find(device_id); + + if (pt_->policy_table.device_data->end() == dev_params_iter) { + LOG4CXX_DEBUG(logger_, "Device id " << device_id << " not found."); + return prio_type; + } + + const policy_table::DeviceParams& dev_par = (*dev_params_iter).second; + + policy_table::UserConsentRecords::const_iterator app_consent_record = + dev_par.user_consent_records->find(application_id); + + if (dev_par.user_consent_records->end() == app_consent_record) { + LOG4CXX_DEBUG(logger_, + "Application id " << application_id << " not found."); + return prio_type; + } + + const policy_table::ConsentRecords& record = app_consent_record->second; + + return record.consent_last_updated > record.ext_consent_last_updated + ? ConsentPriorityType::kUserConsentPrio + : ConsentPriorityType::kExternalConsentPrio; +} + +const policy_table::Strings& CacheManager::GetGroups(const PTString& app_id) { + return pt_->policy_table.app_policies_section.apps[app_id].groups; +} + +bool CacheManager::CanAppKeepContext(const std::string& app_id) const { + CACHE_MANAGER_CHECK(false); + bool result = false; + if (kDeviceId == app_id) { + result = pt_->policy_table.app_policies_section.device.keep_context; + } else if (IsApplicationRepresented(app_id)) { + result = pt_->policy_table.app_policies_section.apps[app_id].keep_context; + } + return result; +} + +uint32_t CacheManager::HeartBeatTimeout(const std::string& app_id) const { + CACHE_MANAGER_CHECK(0); + uint32_t result = 0; + if (!IsApplicationRepresented(app_id)) { + return result; + } + + const policy_table::ApplicationPolicies::mapped_type& app = + pt_->policy_table.app_policies_section.apps[app_id]; + if (app.heart_beat_timeout_ms.is_initialized()) { + result = *(app.heart_beat_timeout_ms); + } + + return result; +} + +const policy_table::AppHMITypes* CacheManager::GetHMITypes( + const std::string& app_id) { + const policy_table::ApplicationPolicies& apps = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::const_iterator i = apps.find(app_id); + if (i != apps.end()) { + return &(*i->second.AppHMIType); + } + return NULL; +} + +int32_t CacheManager::GenerateHash(const std::string& str_to_hash) { + uint32_t hash = 5381U; + std::string::const_iterator it = str_to_hash.begin(); + std::string::const_iterator it_end = str_to_hash.end(); + + for (; it != it_end; ++it) { + hash = ((hash << 5) + hash) + (*it); + } + + // Reset sign bit in case it has been set. + // This is needed to avoid overflow for signed int. + const int32_t result = hash & 0x7FFFFFFF; + return result; +} + +bool CacheManager::CanAppStealFocus(const std::string& app_id) const { + CACHE_MANAGER_CHECK(false); + bool result = false; + if (kDeviceId == app_id) { + result = pt_->policy_table.app_policies_section.device.steal_focus; + } else if (IsApplicationRepresented(app_id)) { + result = pt_->policy_table.app_policies_section.apps[app_id].steal_focus; + } + return result; +} + +bool CacheManager::GetDefaultHMI(const std::string& app_id, + std::string& default_hmi) const { + CACHE_MANAGER_CHECK(false); + bool result = false; + default_hmi.clear(); + if (kDeviceId == app_id) { + default_hmi = EnumToJsonString( + pt_->policy_table.app_policies_section.device.default_hmi); + } else if (IsApplicationRepresented(app_id)) { + default_hmi = EnumToJsonString( + pt_->policy_table.app_policies_section.apps[app_id].default_hmi); + } + result = !default_hmi.empty(); + + return result; +} + +bool CacheManager::ResetUserConsent() { + CACHE_MANAGER_CHECK(false); + sync_primitives::AutoLock lock(cache_lock_); + policy_table::DeviceData::iterator iter = + pt_->policy_table.device_data->begin(); + policy_table::DeviceData::iterator iter_end = + pt_->policy_table.device_data->end(); + + for (; iter != iter_end; ++iter) { + iter->second.user_consent_records->clear(); + } + Backup(); + return true; +} + +bool CacheManager::GetUserPermissionsForDevice( + const std::string& device_id, + StringArray& consented_groups, + StringArray& disallowed_groups) const { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(false); + policy_table::DeviceData& device_data = *pt_->policy_table.device_data; + if (device_data.end() == device_data.find(device_id)) { + LOG4CXX_ERROR(logger_, + "Device with " << device_id << "was not found in PT"); + return false; + } + const policy_table::DeviceParams& params = device_data[device_id]; + const policy_table::UserConsentRecords& ucr = *(params.user_consent_records); + policy_table::UserConsentRecords::const_iterator iter = ucr.begin(); + policy_table::UserConsentRecords::const_iterator iter_end = ucr.end(); + + for (; iter != iter_end; ++iter) { + policy_table::ConsentGroups::const_iterator con_iter; + policy_table::ConsentGroups::const_iterator con_iter_end; + + con_iter = (*iter).second.consent_groups->begin(); + con_iter_end = (*iter).second.consent_groups->end(); + for (; con_iter != con_iter_end; ++con_iter) { + if (true == (*con_iter).second) { + consented_groups.push_back((*con_iter).first); + } else { + disallowed_groups.push_back((*con_iter).first); + } + } + } + return true; +} + +void CacheManager::GetAllAppGroups(const std::string& app_id, + FunctionalGroupIDs& all_group_ids) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + if (kDeviceId == app_id) { + policy_table::DevicePolicy& device = + pt_->policy_table.app_policies_section.device; + + policy_table::Strings::const_iterator iter = device.groups.begin(); + policy_table::Strings::const_iterator iter_end = device.groups.end(); + + for (; iter != iter_end; ++iter) { + const uint32_t group_id = + static_cast<uint32_t>((utils::Djb2HashFromString(*iter))); + all_group_ids.push_back(group_id); + } + + return; + } + + policy_table::ApplicationPolicies::const_iterator app_params_iter = + pt_->policy_table.app_policies_section.apps.find(app_id); + + if (pt_->policy_table.app_policies_section.apps.end() != app_params_iter) { + policy_table::Strings::const_iterator iter = + (*app_params_iter).second.groups.begin(); + policy_table::Strings::const_iterator iter_end = + (*app_params_iter).second.groups.end(); + + for (; iter != iter_end; ++iter) { + const uint32_t group_id = + static_cast<uint32_t>((utils::Djb2HashFromString(*iter))); + all_group_ids.push_back(group_id); + } + } +} + +void CacheManager::GetPreConsentedGroups( + const std::string& app_id, FunctionalGroupIDs& preconsented_groups) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + if (kDeviceId == app_id) { + policy_table::DevicePolicy& device = + pt_->policy_table.app_policies_section.device; + + policy_table::Strings::const_iterator iter = + device.preconsented_groups->begin(); + policy_table::Strings::const_iterator iter_end = + device.preconsented_groups->end(); + + for (; iter != iter_end; ++iter) { + const uint32_t group_id = + static_cast<uint32_t>((utils::Djb2HashFromString(*iter))); + preconsented_groups.push_back(group_id); + } + + return; + } + + policy_table::ApplicationPolicies::const_iterator app_param_iter = + pt_->policy_table.app_policies_section.apps.find(app_id); + if (pt_->policy_table.app_policies_section.apps.end() != app_param_iter) { + policy_table::Strings::const_iterator iter = + (*app_param_iter).second.preconsented_groups->begin(); + policy_table::Strings::const_iterator iter_end = + (*app_param_iter).second.preconsented_groups->end(); + for (; iter != iter_end; ++iter) { + const int32_t group_id = utils::Djb2HashFromString(*iter); + + preconsented_groups.push_back(group_id); + } + } +} + +void CacheManager::GetConsentedGroups(const std::string& device_id, + const std::string& app_id, + FunctionalGroupIDs& allowed_groups, + FunctionalGroupIDs& disallowed_groups) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + policy_table::DeviceData::iterator dev_params_iter = + pt_->policy_table.device_data->find(device_id); + + if (pt_->policy_table.device_data->end() != dev_params_iter) { + const policy_table::DeviceParams& dev_par = (*dev_params_iter).second; + + policy_table::UserConsentRecords::const_iterator iter = + dev_par.user_consent_records->find(app_id); + + if (dev_par.user_consent_records->end() != iter) { + policy_table::ConsentGroups::const_iterator consent_iter = + (*iter).second.consent_groups->begin(); + policy_table::ConsentGroups::const_iterator consent_iter_end = + (*iter).second.consent_groups->end(); + + for (; consent_iter != consent_iter_end; ++consent_iter) { + const int32_t group_id = + utils::Djb2HashFromString((*consent_iter).first); + + if (true == (*consent_iter).second) { + allowed_groups.push_back(group_id); + } else { + disallowed_groups.push_back(group_id); + } + } + } + } +} + +void CacheManager::GetUnconsentedGroups( + const std::string& device_id, + const std::string& policy_app_id, + FunctionalGroupIDs& unconsented_groups) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + + if (!IsApplicationRepresented(policy_app_id)) { + LOG4CXX_WARN(logger_, + "The application with app_id: " << policy_app_id + << " is not reresented"); + return; + } + + policy_table::Strings::iterator iter_groups; + policy_table::Strings::iterator iter_groups_end; + if (kDeviceId == policy_app_id) { + iter_groups = pt_->policy_table.app_policies_section.device.groups.begin(); + iter_groups_end = + pt_->policy_table.app_policies_section.device.groups.end(); + } else { + iter_groups = pt_->policy_table.app_policies_section.apps[policy_app_id] + .groups.begin(); + iter_groups_end = + pt_->policy_table.app_policies_section.apps[policy_app_id].groups.end(); + } + + for (; iter_groups != iter_groups_end; ++iter_groups) { + // Try to find app-specific group in common groups list; + policy_table::FunctionalGroupings::const_iterator func_groups = + pt_->policy_table.functional_groupings.find(*iter_groups); + if (pt_->policy_table.functional_groupings.end() != func_groups) { + // Check if groups have user consents field. + if (func_groups->second.user_consent_prompt.is_initialized()) { + // Try to find certain group among already consented groups. + policy_table::DeviceData::const_iterator device_iter = + pt_->policy_table.device_data->find(device_id); + if (pt_->policy_table.device_data->end() != device_iter) { + policy_table::UserConsentRecords::const_iterator ucr_iter = + device_iter->second.user_consent_records->find(policy_app_id); + if (device_iter->second.user_consent_records->end() != ucr_iter) { + if ((*ucr_iter).second.consent_groups->end() == + (*ucr_iter).second.consent_groups->find(*iter_groups)) { + unconsented_groups.push_back( + utils::Djb2HashFromString(*iter_groups)); + } + } else { + unconsented_groups.push_back( + utils::Djb2HashFromString(*iter_groups)); + } + } + } + } + } +} + +void CacheManager::RemoveAppConsentForGroup(const std::string& app_id, + const std::string& group_name) { + CACHE_MANAGER_CHECK_VOID(); + policy_table::DeviceData::iterator device_iter = + pt_->policy_table.device_data->begin(); + policy_table::DeviceData::iterator device_iter_end = + pt_->policy_table.device_data->end(); + + policy_table::UserConsentRecords::iterator ucr_iter; + for (; device_iter != device_iter_end; ++device_iter) { + ucr_iter = device_iter->second.user_consent_records->find(app_id); + if (device_iter->second.user_consent_records->end() != ucr_iter) { + ucr_iter->second.consent_groups->erase(group_name); + } + } +} + +using rpc::policy_table_interface_base::RequestTypes; +using rpc::policy_table_interface_base::RequestType; + +void CacheManager::ProcessUpdate( + const policy_table::ApplicationPolicies::const_iterator + initial_policy_iter) { + using namespace policy; + const RequestTypes& new_request_types = + *(initial_policy_iter->second.RequestType); + + const std::string& app_id = initial_policy_iter->first; + RequestTypes merged_pt_request_types; + + if (app_id == kDefaultId || app_id == kPreDataConsentId) { + if (new_request_types.is_omitted()) { + LOG4CXX_INFO(logger_, + "Application " << app_id + << " has omitted RequestTypes." + " Previous values will be kept."); + return; + } + if (new_request_types.empty()) { + if (new_request_types.is_cleaned_up()) { + LOG4CXX_INFO(logger_, + "Application " << app_id + << " has cleaned up all values." + " Previous values will be kept."); + return; + } + LOG4CXX_INFO(logger_, + "Application " << app_id + << " has empty RequestTypes." + " Any parameter will be allowed."); + } + merged_pt_request_types = new_request_types; + } else { + merged_pt_request_types = new_request_types; + } + pt_->policy_table.app_policies_section.apps[app_id] = + initial_policy_iter->second; + *(pt_->policy_table.app_policies_section.apps[app_id].RequestType) = + merged_pt_request_types; +} + +bool CacheManager::ApplyUpdate(const policy_table::Table& update_pt) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(false); + sync_primitives::AutoLock auto_lock(cache_lock_); + pt_->policy_table.functional_groupings = + update_pt.policy_table.functional_groupings; + + policy_table::ApplicationPolicies::const_iterator iter = + update_pt.policy_table.app_policies_section.apps.begin(); + policy_table::ApplicationPolicies::const_iterator iter_end = + update_pt.policy_table.app_policies_section.apps.end(); + + for (; iter != iter_end; ++iter) { + if (iter->second.is_null()) { + pt_->policy_table.app_policies_section.apps[iter->first] = + policy_table::ApplicationParams(); + pt_->policy_table.app_policies_section.apps[iter->first].set_to_null(); + pt_->policy_table.app_policies_section.apps[iter->first].set_to_string( + ""); + } else if (policy::kDefaultId == (iter->second).get_string()) { + policy_table::ApplicationPolicies::const_iterator iter_default = + update_pt.policy_table.app_policies_section.apps.find(kDefaultId); + if (update_pt.policy_table.app_policies_section.apps.end() == + iter_default) { + LOG4CXX_ERROR(logger_, "The default section was not found in PTU"); + continue; + } + ProcessUpdate(iter_default); + } else { + ProcessUpdate(iter); + } + } + + pt_->policy_table.app_policies_section.device = + update_pt.policy_table.app_policies_section.device; + + pt_->policy_table.module_config.SafeCopyFrom( + update_pt.policy_table.module_config); + + pt_->policy_table.consumer_friendly_messages.assign_if_valid( + update_pt.policy_table.consumer_friendly_messages); + + ResetCalculatedPermissions(); + Backup(); + + if (*pt_->policy_table.module_config.preloaded_pt && update_pt.is_valid()) { + *pt_->policy_table.module_config.preloaded_pt = false; + } + + return true; +} + +void CacheManager::GetHMIAppTypeAfterUpdate( + std::map<std::string, StringArray>& app_hmi_types) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + policy_table::ApplicationPolicies::const_iterator policy_iter_begin = + pt_->policy_table.app_policies_section.apps.begin(); + policy_table::ApplicationPolicies::const_iterator policy_iter_end = + pt_->policy_table.app_policies_section.apps.end(); + std::vector<std::string> transform_app_hmi_types; + for (; policy_iter_begin != policy_iter_end; ++policy_iter_begin) { + const policy_table::ApplicationParams& app_params = + (*policy_iter_begin).second; + if (app_params.AppHMIType.is_initialized()) { + if (!(transform_app_hmi_types.empty())) { + transform_app_hmi_types.clear(); + } + std::transform(app_params.AppHMIType->begin(), + app_params.AppHMIType->end(), + std::back_inserter(transform_app_hmi_types), + AppHMITypeToString()); + app_hmi_types[(*policy_iter_begin).first] = transform_app_hmi_types; + } + } +} + +bool CacheManager::AppHasHMIType(const std::string& application_id, + policy_table::AppHMIType hmi_type) const { + const policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + + policy_table::ApplicationPolicies::const_iterator policy_iter = + policies.find(application_id); + + if (policy_iter == policies.end()) { + return false; + } + + if (policy_iter->second.AppHMIType.is_initialized()) { + return helpers::in_range(*(policy_iter->second.AppHMIType), + rpc::Enum<policy_table::AppHMIType>(hmi_type)); + } + + return false; +} + +void CacheManager::Backup() { + sync_primitives::AutoLock lock(backuper_locker_); + DCHECK(backuper_); + backuper_->DoBackup(); +} + +std::string CacheManager::currentDateTime() { + time_t now = time(0); + struct tm tstruct; + char buf[80]; + tstruct = *localtime(&now); + // ISO_8601 format is expected, e.g. “2000-01-01T12:18:53Z” + strftime(buf, sizeof(buf), "%Y-%m-%dT%XZ", &tstruct); + return buf; +} + +bool CacheManager::GetPermissionsForApp(const std::string& device_id, + const std::string& app_id, + FunctionalIdType& group_types) { + LOG4CXX_AUTO_TRACE(logger_); + GetAllAppGroups(app_id, group_types[kTypeGeneral]); + GetAllAppGroups(kDefaultId, group_types[kTypeDefault]); + GetAllAppGroups(kPreDataConsentId, group_types[kTypePreDataConsented]); + GetPreConsentedGroups(app_id, group_types[kTypePreconsented]); + + GetConsentedGroups(device_id, + app_id, + group_types[kTypeAllowed], + group_types[kTypeDisallowed]); + + GetUnconsentedGroups(device_id, app_id, group_types[kTypeUnconsented]); + + GetAllAppGroups(kDeviceId, group_types[kTypeDevice]); + return true; +} + +bool CacheManager::GetDeviceGroupsFromPolicies( + policy_table::Strings& groups, + policy_table::Strings& preconsented_groups) const { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(false); + groups = pt_->policy_table.app_policies_section.device.groups; + preconsented_groups = + *(pt_->policy_table.app_policies_section.device).preconsented_groups; + return true; +} + +bool CacheManager::IsDeviceConsentCached(const std::string& device_id) const { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(false); + sync_primitives::AutoLock lock(cached_device_permissions_lock_); + CachedDevicePermissions::const_iterator cached_dev_consent_iter; + cached_dev_consent_iter = cached_device_permissions_.find(device_id); + return cached_dev_consent_iter != cached_device_permissions_.end(); +} + +DeviceConsent CacheManager::GetCachedDeviceConsent( + const std::string& device_id) const { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(cached_device_permissions_lock_); + DeviceConsent result = kDeviceHasNoConsent; + CACHE_MANAGER_CHECK(result); + CachedDevicePermissions::const_iterator cached_dev_consent_iter; + cached_dev_consent_iter = cached_device_permissions_.find(device_id); + if (cached_dev_consent_iter != cached_device_permissions_.end()) { + return cached_dev_consent_iter->second; + } + return result; +} + +void CacheManager::SaveDeviceConsentToCache(const std::string& device_id, + const bool is_allowed) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + sync_primitives::AutoLock lock(cached_device_permissions_lock_); + DeviceConsent result = is_allowed ? kDeviceAllowed : kDeviceDisallowed; + cached_device_permissions_[device_id] = result; +} + +bool CacheManager::GetPermissionsList(StringArray& perm_list) const { + // Get device permission groups from app_policies section, which hadn't been + // preconsented + policy_table::Strings groups; + policy_table::Strings preconsented_groups; + if (!GetDeviceGroupsFromPolicies(groups, preconsented_groups)) { + LOG4CXX_WARN(logger_, "Can't get device groups from policies."); + return false; + } + + std::for_each(groups.begin(), + groups.end(), + FunctionalGroupInserter(preconsented_groups, perm_list)); + return true; +} + +bool CacheManager::HasDeviceSpecifiedConsent(const std::string& device_id, + const bool is_allowed) const { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Device :" << device_id); + const DeviceConsent current_consent = GetDeviceConsent(device_id); + const bool is_current_device_allowed = + DeviceConsent::kDeviceAllowed == current_consent ? true : false; + + if (DeviceConsent::kDeviceHasNoConsent == current_consent || + is_current_device_allowed != is_allowed) { + return false; + } + const std::string consent = is_allowed ? "allowed" : "disallowed"; + LOG4CXX_INFO(logger_, + "DeviceGetDeviceGroupsFromPolicies is already " << consent + << "."); + return true; +} + +void CacheManager::SetDeviceConsent(const std::string& device_id, + const bool is_allowed) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + if (HasDeviceSpecifiedConsent(device_id, is_allowed)) { + return; + } + ResetCalculatedPermissionsForDevice(device_id); + // Remove unpaired mark, if device re-paired and re-consented again + if (is_allowed) { + SetUnpairedDevice(device_id, false); + } + + StringArray list_of_permissions; + if (!GetPermissionsList(list_of_permissions) || list_of_permissions.empty()) { + LOG4CXX_WARN(logger_, "List of permissions can't be received or empty"); + return; + } + + StringArray consented_groups; + StringArray disallowed_groups; + + // Supposed only one group for device date consent + if (is_allowed) { + consented_groups = list_of_permissions; + } else { + disallowed_groups = list_of_permissions; + } + + if (!SetUserPermissionsForDevice( + device_id, consented_groups, disallowed_groups)) { + LOG4CXX_WARN(logger_, "Can't set user consent for device"); + return; + } + SaveDeviceConsentToCache(device_id, is_allowed); +} + +DeviceConsent CacheManager::GetDeviceConsent( + const std::string& device_id) const { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(kDeviceHasNoConsent); + if (IsDeviceConsentCached(device_id)) { + return GetCachedDeviceConsent(device_id); + } + StringArray list_of_permissions; + if (!GetPermissionsList(list_of_permissions)) { + return kDeviceDisallowed; + } + + // Check device permission groups for user consent in device_data + // section + if (list_of_permissions.empty()) { + return kDeviceAllowed; + } + StringArray consented_groups; + StringArray disallowed_groups; + if (!GetUserPermissionsForDevice( + device_id, consented_groups, disallowed_groups)) { + return kDeviceDisallowed; + } + + if (consented_groups.empty() && disallowed_groups.empty()) { + return kDeviceHasNoConsent; + } + + std::sort(list_of_permissions.begin(), list_of_permissions.end()); + std::sort(consented_groups.begin(), consented_groups.end()); + + StringArray to_be_consented_by_user; + std::set_difference(list_of_permissions.begin(), + list_of_permissions.end(), + consented_groups.begin(), + consented_groups.end(), + std::back_inserter(to_be_consented_by_user)); + if (to_be_consented_by_user.empty()) { + return kDeviceAllowed; + } + return kDeviceDisallowed; +} + +bool CacheManager::AddDevice(const std::string& device_id, + const std::string& connection_type) { + LOG4CXX_AUTO_TRACE(logger_); + + sync_primitives::AutoLock auto_lock(cache_lock_); + CACHE_MANAGER_CHECK(false); + policy_table::DeviceParams& params = + (*(pt_->policy_table.device_data))[device_id]; + *params.connection_type = connection_type; + + // We have to set preloaded flag as false in policy table on adding new + // information (SDLAQ-CRS-2365). It can happens only after device addition. + *pt_->policy_table.module_config.preloaded_pt = false; + + Backup(); + return true; +} + +bool CacheManager::SetDeviceData(const std::string& device_id, + const std::string& hardware, + const std::string& firmware, + const std::string& os, + const std::string& os_version, + const std::string& carrier, + const uint32_t number_of_ports, + const std::string& connection_type) { + LOG4CXX_AUTO_TRACE(logger_); + + sync_primitives::AutoLock auto_lock(cache_lock_); + CACHE_MANAGER_CHECK(false); + + if (pt_->policy_table.device_data->end() == + pt_->policy_table.device_data->find(device_id)) { + LOG4CXX_ERROR(logger_, "Unable to find mobile device: " << device_id); + return false; + } + + policy_table::DeviceParams& params = + (*(pt_->policy_table.device_data))[device_id]; + *params.hardware = hardware; + *params.firmware_rev = firmware; + *params.os = os; + *params.os_version = os_version; + *params.carrier = carrier; + *params.max_number_rfcom_ports = number_of_ports; + *params.connection_type = connection_type; + + Backup(); + return true; +} + +bool CacheManager::SetUserPermissionsForDevice( + const std::string& device_id, + const StringArray& consented_groups, + const StringArray& disallowed_groups) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(cache_lock_); + CACHE_MANAGER_CHECK(false); + policy_table::DeviceParams& params = + (*pt_->policy_table.device_data)[device_id]; + policy_table::UserConsentRecords& ucr = *(params.user_consent_records); + + StringArray::const_iterator consent_iter_end = consented_groups.end(); + StringArray::const_iterator consent_iter = consented_groups.begin(); + StringArray::const_iterator un_consent_iter_end = disallowed_groups.end(); + StringArray::const_iterator un_consent_iter = disallowed_groups.begin(); + + for (; consent_iter != consent_iter_end; ++consent_iter) { + (*ucr[kDeviceId].consent_groups)[*consent_iter] = true; + } + + for (; un_consent_iter != un_consent_iter_end; ++un_consent_iter) { + (*ucr[kDeviceId].consent_groups)[*un_consent_iter] = false; + } + + policy_table::UserConsentRecords::iterator ucr_iter = ucr.begin(); + policy_table::UserConsentRecords::iterator ucr_iter_end = ucr.end(); + // TODO(AGaliuzov): Get this info from external data + for (; ucr_iter != ucr_iter_end; ++ucr_iter) { + *ucr_iter->second.input = policy_table::Input::I_GUI; + *ucr_iter->second.time_stamp = currentDateTime(); + } + Backup(); + return true; +} + +bool CacheManager::ReactOnUserDevConsentForApp(const std::string& app_id, + bool is_device_allowed) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(false); + bool result = true; + if (is_device_allowed) { + // If app has pre_DataConsented groups it should be 'promoted' to default + if (IsPredataPolicy(app_id)) { + result = SetDefaultPolicy(app_id); + } + } else { + SetIsPredata(app_id); + } + Backup(); + return result; +} + +void CacheManager::GetGroupNameByHashID(const int32_t group_id, + std::string& group_name) { + CACHE_MANAGER_CHECK_VOID(); + policy_table::FunctionalGroupings::const_iterator fg_iter = + pt_->policy_table.functional_groupings.begin(); + policy_table::FunctionalGroupings::const_iterator fg_iter_end = + pt_->policy_table.functional_groupings.end(); + + for (; fg_iter != fg_iter_end; ++fg_iter) { + const int32_t id = utils::Djb2HashFromString((*fg_iter).first); + if (group_id == id) { + group_name = (*fg_iter).first; + } + } +} + +bool CacheManager::SetUserPermissionsForApp( + const PermissionConsent& permissions, bool* out_app_permissions_changed) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(cache_lock_); + CACHE_MANAGER_CHECK(false); + std::vector<FunctionalGroupPermission>::const_iterator iter = + permissions.group_permissions.begin(); + std::vector<FunctionalGroupPermission>::const_iterator iter_end = + permissions.group_permissions.end(); + *out_app_permissions_changed = false; + + std::string group_name; + for (; iter != iter_end; ++iter) { + if (policy::kGroupUndefined != (*iter).state) { + policy_table::DeviceParams& params = + (*pt_->policy_table.device_data)[permissions.device_id]; + rpc::policy_table_interface_base::ConsentRecords& ucr = + (*params.user_consent_records)[permissions.policy_app_id]; + + GetGroupNameByHashID((*iter).group_id, group_name); + + policy_table::ConsentGroups::const_iterator it_group = + ucr.consent_groups->find(group_name); + + const bool is_allowed = (*iter).state == policy::kGroupAllowed; + if (ucr.consent_groups->end() == it_group || + it_group->second != is_allowed) { + *out_app_permissions_changed = true; + + const TimevalStruct tm = date_time::DateTime::getCurrentTime(); + int64_t current_time_msec = date_time::DateTime::getmSecs(tm); + ucr.consent_last_updated = current_time_msec; + LOG4CXX_DEBUG(logger_, "Updating consents time " << current_time_msec); + } + + (*ucr.consent_groups)[group_name] = is_allowed; + *ucr.input = policy_table::Input::I_GUI; + *ucr.time_stamp = currentDateTime(); + } + } + Backup(); + return true; +} + +bool CacheManager::UpdateRequired() const { + return update_required; +} + +void CacheManager::SaveUpdateRequired(bool status) { + update_required = status; + Backup(); +} + +bool CacheManager::IsApplicationRevoked(const std::string& app_id) const { + CACHE_MANAGER_CHECK(false); + if (!IsApplicationRepresented(app_id)) { + return false; + } + const bool is_revoked = + pt_->policy_table.app_policies_section.apps[app_id].is_null(); + return is_revoked; +} + +void CacheManager::CheckPermissions(const PTString& app_id, + const PTString& hmi_level, + const PTString& rpc, + CheckPermissionResult& result) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + + if (!IsApplicationRepresented(app_id)) { + LOG4CXX_ERROR( + logger_, "Application id " << app_id << " was not found in policy DB."); + return; + } + + policy_table::Strings::const_iterator app_groups_iter = + pt_->policy_table.app_policies_section.apps[app_id].groups.begin(); + + policy_table::Strings::const_iterator app_groups_iter_end = + pt_->policy_table.app_policies_section.apps[app_id].groups.end(); + + policy_table::FunctionalGroupings::const_iterator concrete_group; + + for (; app_groups_iter != app_groups_iter_end; ++app_groups_iter) { + concrete_group = + pt_->policy_table.functional_groupings.find(*app_groups_iter); + if (pt_->policy_table.functional_groupings.end() != concrete_group) { + const policy_table::Rpcs& rpcs = concrete_group->second; + + policy_table::Rpc::const_iterator rpc_iter = rpcs.rpcs.find(rpc); + if (rpcs.rpcs.end() != rpc_iter) { + policy_table::RpcParameters rpc_param = rpc_iter->second; + + policy_table::HmiLevel hmi_level_e; + policy_table::EnumFromJsonString(hmi_level, &hmi_level_e); + + policy_table::HmiLevels::const_iterator hmi_iter = + std::find(rpc_param.hmi_levels.begin(), + rpc_param.hmi_levels.end(), + hmi_level_e); + + if (rpc_param.hmi_levels.end() != hmi_iter) { + result.hmi_level_permitted = PermitResult::kRpcAllowed; + + policy_table::Parameters::const_iterator params_iter = + rpc_param.parameters->begin(); + policy_table::Parameters::const_iterator params_iter_end = + rpc_param.parameters->end(); + + for (; params_iter != params_iter_end; ++params_iter) { + result.list_of_allowed_params.insert( + policy_table::EnumToJsonString(*params_iter)); + } + } + } + } + } +} + +bool CacheManager::IsPTPreloaded() { + CACHE_MANAGER_CHECK(false); + return *pt_->policy_table.module_config.preloaded_pt; +} + +int CacheManager::IgnitionCyclesBeforeExchange() { + CACHE_MANAGER_CHECK(0); + const uint8_t limit = std::max( + static_cast<int>( + pt_->policy_table.module_config.exchange_after_x_ignition_cycles), + 0); + LOG4CXX_DEBUG( + logger_, + "IgnitionCyclesBeforeExchange limit:" << static_cast<int>(limit)); + uint8_t current = 0; + + const int last_exch = static_cast<int>( + *pt_->policy_table.module_meta->ignition_cycles_since_last_exchange); + current = std::max(last_exch, 0); + LOG4CXX_DEBUG( + logger_, + "IgnitionCyclesBeforeExchange current:" << static_cast<int>(current)); + + return std::max(limit - current, 0); +} + +int CacheManager::KilometersBeforeExchange(int current) { + CACHE_MANAGER_CHECK(0); + const int limit = + std::max(static_cast<int>( + pt_->policy_table.module_config.exchange_after_x_kilometers), + 0); + LOG4CXX_DEBUG(logger_, "KilometersBeforeExchange limit:" << limit); + int last = 0; + + const int odo_val = static_cast<int>( + *pt_->policy_table.module_meta->pt_exchanged_at_odometer_x); + last = std::max(odo_val, 0); + LOG4CXX_DEBUG(logger_, "KilometersBeforeExchange last:" << last); + + const int actual = std::max((current - last), 0); + LOG4CXX_DEBUG(logger_, "KilometersBeforeExchange actual:" << actual); + return std::max(limit - actual, 0); +} + +bool CacheManager::SetCountersPassedForSuccessfulUpdate( + policy::Counters counter, int value) { + CACHE_MANAGER_CHECK(false); + switch (counter) { + case KILOMETERS: + *pt_->policy_table.module_meta->pt_exchanged_at_odometer_x = value; + LOG4CXX_DEBUG(logger_, + "SetCountersPassedForSuccessfulUpdate km:" << value); + break; + case DAYS_AFTER_EPOCH: + *pt_->policy_table.module_meta->pt_exchanged_x_days_after_epoch = value; + LOG4CXX_DEBUG( + logger_, + "SetCountersPassedForSuccessfulUpdate days after epoch:" << value); + break; + default: + LOG4CXX_ERROR(logger_, + "Unknown counter was requested to set: " << counter); + return false; + } + + Backup(); + return true; +} + +int CacheManager::DaysBeforeExchange(uint16_t current) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(0); + + const rpc::Optional<rpc::Integer<uint16_t, 0, 65535> >& days_after_epoch = + (pt_->policy_table.module_meta->pt_exchanged_x_days_after_epoch); + + if (!days_after_epoch->is_initialized()) { + return -1; + } + + const uint8_t limit = pt_->policy_table.module_config.exchange_after_x_days; + LOG4CXX_DEBUG(logger_, + "Exchange after: " << static_cast<int>(limit) << " days"); + + LOG4CXX_DEBUG(logger_, "Epoch since last update: " << *days_after_epoch); + + const uint16_t actual = + std::max(static_cast<uint16_t>(current - *days_after_epoch), uint16_t(0)); + LOG4CXX_DEBUG(logger_, "The days since last update: " << actual); + + return std::max(limit - actual, 0); +} + +void CacheManager::IncrementIgnitionCycles() { + CACHE_MANAGER_CHECK_VOID(); + const int ign_val = static_cast<int>( + *pt_->policy_table.module_meta->ignition_cycles_since_last_exchange); + (*pt_->policy_table.module_meta->ignition_cycles_since_last_exchange) = + ign_val + 1; + LOG4CXX_DEBUG(logger_, "IncrementIgnitionCycles ignitions:" << ign_val); + Backup(); +} + +void CacheManager::ResetIgnitionCycles() { + CACHE_MANAGER_CHECK_VOID(); + (*pt_->policy_table.module_meta->ignition_cycles_since_last_exchange) = 0; + Backup(); +} + +int CacheManager::TimeoutResponse() { + CACHE_MANAGER_CHECK(0); + return pt_->policy_table.module_config.timeout_after_x_seconds * + date_time::DateTime::MILLISECONDS_IN_SECOND; +} + +bool CacheManager::SecondsBetweenRetries(std::vector<int>& seconds) { + CACHE_MANAGER_CHECK(false); + rpc::policy_table_interface_base::SecondsBetweenRetries::iterator iter = + pt_->policy_table.module_config.seconds_between_retries.begin(); + rpc::policy_table_interface_base::SecondsBetweenRetries::iterator iter_end = + pt_->policy_table.module_config.seconds_between_retries.end(); + + const std::size_t size = + pt_->policy_table.module_config.seconds_between_retries.size(); + seconds.reserve(size); + for (; iter != iter_end; ++iter) { + seconds.push_back(*iter); + } + return true; +} + +const policy::VehicleInfo CacheManager::GetVehicleInfo() const { + CACHE_MANAGER_CHECK(VehicleInfo()); + policy_table::ModuleConfig& module_config = pt_->policy_table.module_config; + VehicleInfo vehicle_info; + vehicle_info.vehicle_make = *module_config.vehicle_make; + vehicle_info.vehicle_model = *module_config.vehicle_model; + vehicle_info.vehicle_year = *module_config.vehicle_year; + LOG4CXX_DEBUG( + logger_, + "Vehicle info (make, model, year):" << vehicle_info.vehicle_make << "," + << vehicle_info.vehicle_model << "," + << vehicle_info.vehicle_year); + return vehicle_info; +} + +std::vector<UserFriendlyMessage> CacheManager::GetUserFriendlyMsg( + const std::vector<std::string>& msg_codes, + const std::string& language, + const std::string& active_hmi_language) { + LOG4CXX_AUTO_TRACE(logger_); + std::vector<UserFriendlyMessage> result; + CACHE_MANAGER_CHECK(result); + + std::vector<std::string>::const_iterator it = msg_codes.begin(); + std::vector<std::string>::const_iterator it_end = msg_codes.end(); + for (; it != it_end; ++it) { + policy_table::MessageLanguages msg_languages = + (*pt_->policy_table.consumer_friendly_messages->messages)[*it]; + + // If message has no records with required language, fallback language + // should be used instead. + policy_table::MessageString message_string = + FindLanguage(msg_languages, language); + + if (!message_string.is_valid()) { + LOG4CXX_WARN(logger_, + "Language " + << language + << " haven't been found for message code: " << *it); + policy_table::MessageString active_hmi_language_message_string = + FindLanguage(msg_languages, active_hmi_language); + if (!active_hmi_language_message_string.is_valid()) { + LOG4CXX_WARN(logger_, + "Active hmi language " + << active_hmi_language + << " haven't been found for message code: " << *it); + + policy_table::MessageString fallback_message_string = + FindLanguage(msg_languages, "en-us"); + if (!fallback_message_string.is_valid()) { + LOG4CXX_ERROR(logger_, + "No fallback language found for message code: " << *it); + continue; + } + message_string = fallback_message_string; + } + message_string = active_hmi_language_message_string; + } + + UserFriendlyMessage msg; + msg.message_code = *it; + msg.tts = *message_string.tts; + msg.label = *message_string.label; + msg.line1 = *message_string.line1; + msg.line2 = *message_string.line2; + msg.text_body = *message_string.textBody; + + result.push_back(msg); + } + return result; +} + +void CacheManager::GetUpdateUrls(const uint32_t service_type, + EndpointUrls& out_end_points) { + std::stringstream service_type_stream; + service_type_stream << (service_type <= 9 ? "0x0" : "0x") << service_type; + + const std::string service_type_str = service_type_stream.str(); + GetUpdateUrls(service_type_str, out_end_points); +} + +void CacheManager::GetUpdateUrls(const std::string& service_type, + EndpointUrls& out_end_points) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + + LOG4CXX_DEBUG(logger_, "Search service value is: " << service_type); + + policy_table::ServiceEndpoints::const_iterator iter = + pt_->policy_table.module_config.endpoints.find(service_type); + + if (pt_->policy_table.module_config.endpoints.end() != iter) { + policy_table::URLList::const_iterator url_list_iter = + (*iter).second.begin(); + policy_table::URLList::const_iterator url_list_iter_end = + (*iter).second.end(); + for (; url_list_iter != url_list_iter_end; ++url_list_iter) { + EndpointData data; + data.app_id = (*url_list_iter).first; + std::copy((*url_list_iter).second.begin(), + (*url_list_iter).second.end(), + std::back_inserter(data.url)); + + out_end_points.push_back(data); + } + } +} + +std::string CacheManager::GetLockScreenIconUrl() const { + if (backup_) { + return backup_->GetLockScreenIconUrl(); + } + return std::string(""); +} + +rpc::policy_table_interface_base::NumberOfNotificationsType +CacheManager::GetNotificationsNumber(const std::string& priority) { + CACHE_MANAGER_CHECK(0); + typedef rpc::policy_table_interface_base::NumberOfNotificationsPerMinute NNPM; + + const NNPM& nnpm = + pt_->policy_table.module_config.notifications_per_minute_by_priority; + + NNPM::const_iterator priority_iter = nnpm.find(priority); + + const uint32_t result = + (nnpm.end() != priority_iter ? (*priority_iter).second : 0); + return result; +} + +bool CacheManager::GetPriority(const std::string& policy_app_id, + std::string& priority) const { + CACHE_MANAGER_CHECK(false); + if (kDeviceId == policy_app_id) { + priority = EnumToJsonString( + pt_->policy_table.app_policies_section.device.priority); + return true; + } + + const policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + + policy_table::ApplicationPolicies::const_iterator policy_iter = + policies.find(policy_app_id); + const bool app_id_exists = policies.end() != policy_iter; + if (app_id_exists) { + priority = EnumToJsonString((*policy_iter).second.priority); + } + + return app_id_exists; +} + +void CacheManager::CheckSnapshotInitialization() { + CACHE_MANAGER_CHECK_VOID(); + if (!snapshot_) { + LOG4CXX_ERROR(logger_, "Snapshot pointer is not initialized"); + return; + } + + *(snapshot_->policy_table.module_config.preloaded_pt) = false; + + // SDL must not send certificate in snapshot + snapshot_->policy_table.module_config.certificate = + rpc::Optional<rpc::String<0, 65535> >(); + + snapshot_->policy_table.consumer_friendly_messages->messages = + rpc::Optional<policy_table::Messages>(); + + rpc::Optional<policy_table::ModuleMeta>& module_meta = + snapshot_->policy_table.module_meta; + if (!module_meta->pt_exchanged_at_odometer_x->is_initialized()) { + *(module_meta->pt_exchanged_at_odometer_x) = 0; + } + if (!module_meta->ignition_cycles_since_last_exchange->is_initialized()) { + *(module_meta->ignition_cycles_since_last_exchange) = 0; + } + + if (!module_meta->pt_exchanged_x_days_after_epoch->is_initialized()) { + *(module_meta->pt_exchanged_x_days_after_epoch) = 0; + } + + rpc::Optional<policy_table::UsageAndErrorCounts>& usage_and_error_counts = + snapshot_->policy_table.usage_and_error_counts; + if (!usage_and_error_counts->count_of_iap_buffer_full->is_initialized()) { + *(usage_and_error_counts->count_of_iap_buffer_full) = 0; + } + + if (!usage_and_error_counts->count_of_sync_reboots->is_initialized()) { + *(usage_and_error_counts->count_of_sync_reboots) = 0; + } + + if (!usage_and_error_counts->count_sync_out_of_memory->is_initialized()) { + *(usage_and_error_counts->count_sync_out_of_memory) = 0; + } + + if (usage_and_error_counts->app_level->is_initialized()) { + policy_table::AppLevels::iterator it = + usage_and_error_counts->app_level->begin(); + policy_table::AppLevels::const_iterator it_end = + usage_and_error_counts->app_level->end(); + for (; it != it_end; ++it) { + if (!(*it).second.minutes_in_hmi_full.is_initialized()) { + (*it).second.minutes_in_hmi_full = 0; + } + + if (!(*it).second.app_registration_language_gui.is_initialized()) { + (*it).second.app_registration_language_gui = "unknown"; + } + + if (!(*it).second.app_registration_language_vui.is_initialized()) { + (*it).second.app_registration_language_vui = "unknown"; + } + + if (!(*it).second.minutes_in_hmi_limited.is_initialized()) { + (*it).second.minutes_in_hmi_limited = 0; + } + + if (!(*it).second.minutes_in_hmi_background.is_initialized()) { + (*it).second.minutes_in_hmi_background = 0; + } + + if (!(*it).second.minutes_in_hmi_none.is_initialized()) { + (*it).second.minutes_in_hmi_none = 0; + } + + if (!(*it).second.count_of_user_selections.is_initialized()) { + (*it).second.count_of_user_selections = 0; + } + + if (!(*it) + .second.count_of_rejections_sync_out_of_memory + .is_initialized()) { + (*it).second.count_of_rejections_sync_out_of_memory = 0; + } + + if (!(*it) + .second.count_of_rejections_nickname_mismatch.is_initialized()) { + (*it).second.count_of_rejections_nickname_mismatch = 0; + } + + if (!(*it).second.count_of_rejections_duplicate_name.is_initialized()) { + (*it).second.count_of_rejections_duplicate_name = 0; + } + + if (!(*it).second.count_of_rejected_rpc_calls.is_initialized()) { + (*it).second.count_of_rejected_rpc_calls = 0; + } + + if (!(*it).second.count_of_rpcs_sent_in_hmi_none.is_initialized()) { + (*it).second.count_of_rpcs_sent_in_hmi_none = 0; + } + + if (!(*it).second.count_of_removals_for_bad_behavior.is_initialized()) { + (*it).second.count_of_removals_for_bad_behavior = 0; + } + + if (!(*it).second.count_of_tls_errors.is_initialized()) { + (*it).second.count_of_tls_errors = 0; + } + + if (!(*it).second.count_of_run_attempts_while_revoked.is_initialized()) { + (*it).second.count_of_run_attempts_while_revoked = 0; + } + } + } +} + +void CacheManager::PersistData() { + LOG4CXX_AUTO_TRACE(logger_); + if (backup_.valid()) { + if (pt_.valid()) { + cache_lock_.Acquire(); + policy_table::Table copy_pt(*pt_); + cache_lock_.Release(); + + backup_->Save(copy_pt); + backup_->SaveUpdateRequired(update_required); + + policy_table::ApplicationPolicies::const_iterator app_policy_iter = + copy_pt.policy_table.app_policies_section.apps.begin(); + policy_table::ApplicationPolicies::const_iterator app_policy_iter_end = + copy_pt.policy_table.app_policies_section.apps.end(); + + bool is_revoked = false; + + for (; app_policy_iter != app_policy_iter_end; ++app_policy_iter) { + const std::string app_id = (*app_policy_iter).first; + + if (IsApplicationRepresented(app_id)) { + is_revoked = + copy_pt.policy_table.app_policies_section.apps[app_id].is_null(); + } + + const bool kIsDefaultPolicy = + IsApplicationRepresented(app_id) && + policy::kDefaultId == + copy_pt.policy_table.app_policies_section.apps[app_id] + .get_string(); + + // TODO(AOleynik): Remove this field from DB + const bool kIsPredataPolicy = + IsApplicationRepresented(app_id) && + policy::kPreDataConsentId == + copy_pt.policy_table.app_policies_section.apps[app_id] + .get_string(); + + backup_->SaveApplicationCustomData( + app_id, is_revoked, kIsDefaultPolicy, kIsPredataPolicy); + is_revoked = false; + } + + // In case of extended policy the meta info should be backuped as well. + if (ex_backup_.valid()) { + ex_backup_->SetMetaInfo( + *(*copy_pt.policy_table.module_meta).ccpu_version, + *(*copy_pt.policy_table.module_meta).wers_country_code, + *(*copy_pt.policy_table.module_meta).language); + ex_backup_->SetVINValue(*(*copy_pt.policy_table.module_meta).vin); + + // Save unpaired flag for devices + policy_table::DeviceData::const_iterator it_device = + copy_pt.policy_table.device_data->begin(); + policy_table::DeviceData::const_iterator it_end_device = + copy_pt.policy_table.device_data->end(); + +#ifdef ENABLE_LOG + policy_table::DeviceData& device_data = + *copy_pt.policy_table.device_data; + LOG4CXX_DEBUG(logger_, "Device_data size is: " << device_data.size()); +#endif // ENABLE_LOG + for (; it_device != it_end_device; ++it_device) { + if (is_unpaired_.end() != is_unpaired_.find(it_device->first)) { + ex_backup_->SetUnpairedDevice(it_device->first, true); + } else { + ex_backup_->SetUnpairedDevice(it_device->first, false); + } + } + LOG4CXX_DEBUG(logger_, "Device_data size is: " << device_data.size()); + } + backup_->WriteDb(); + } + } +} + +void CacheManager::ResetCalculatedPermissions() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(calculated_permissions_lock_); + calculated_permissions_.clear(); +} + +void CacheManager::ResetCalculatedPermissionsForDevice( + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(calculated_permissions_lock_); + calculated_permissions_.erase(device_id); +} + +void CacheManager::AddCalculatedPermissions(const std::string& device_id, + const std::string& policy_app_id, + const Permissions& permissions) { + LOG4CXX_DEBUG(logger_, + "AddCalculatedPermissions for device: " + << device_id << " and app: " << policy_app_id); + sync_primitives::AutoLock lock(calculated_permissions_lock_); + calculated_permissions_[device_id][policy_app_id] = permissions; +} + +bool CacheManager::IsPermissionsCalculated(const std::string& device_id, + const std::string& policy_app_id, + Permissions& permission) { + LOG4CXX_DEBUG(logger_, + "IsPermissionsCalculated for device: " + << device_id << " and app: " << policy_app_id); + sync_primitives::AutoLock lock(calculated_permissions_lock_); + CalculatedPermissions::const_iterator it = + calculated_permissions_.find(device_id); + + if (calculated_permissions_.end() == it) { + return false; + } + + AppCalculatedPermissions::const_iterator app_it = + (*it).second.find(policy_app_id); + if ((*it).second.end() == app_it) { + return false; + } else { + permission = (*app_it).second; + return true; + } + return false; +} + +utils::SharedPtr<policy_table::Table> CacheManager::GenerateSnapshot() { + CACHE_MANAGER_CHECK(snapshot_); + sync_primitives::AutoLock lock(cache_lock_); + snapshot_ = new policy_table::Table(); + snapshot_->policy_table = pt_->policy_table; + + snapshot_->SetPolicyTableType(policy_table::PT_SNAPSHOT); + + CheckSnapshotInitialization(); + return snapshot_; +} + +bool CacheManager::GetInitialAppData(const std::string& app_id, + StringArray& nicknames, + StringArray& app_hmi_types) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(false); + policy_table::ApplicationPolicies::const_iterator policy_iter = + pt_->policy_table.app_policies_section.apps.find(app_id); + + if (pt_->policy_table.app_policies_section.apps.end() != policy_iter) { + const policy_table::ApplicationParams& app_params = (*policy_iter).second; + + std::copy(app_params.nicknames->begin(), + app_params.nicknames->end(), + std::back_inserter(nicknames)); + + std::transform(app_params.AppHMIType->begin(), + app_params.AppHMIType->end(), + std::back_inserter(app_hmi_types), + AppHMITypeToString()); + } + return true; +} + +bool CacheManager::GetFunctionalGroupings( + policy_table::FunctionalGroupings& groups) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(false); + const policy_table::FunctionalGroupings& f_groupings = + pt_->policy_table.functional_groupings; + + groups.insert(f_groupings.begin(), f_groupings.end()); + return true; +} + +int CacheManager::CountUnconsentedGroups(const std::string& policy_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(false); + LOG4CXX_DEBUG(logger_, "Application id: " << policy_app_id); + int result = 0; + if (kDeviceId != policy_app_id && !IsApplicationRepresented(policy_app_id)) { + return 0; + } else if (IsDefaultPolicy(policy_app_id)) { + return 0; + } else if (IsPredataPolicy(policy_app_id)) { + return 0; + } + + policy_table::FunctionalGroupings::const_iterator groups_iter_end = + pt_->policy_table.functional_groupings.end(); + + policy_table::ApplicationPoliciesSection& app_policies_section = + pt_->policy_table.app_policies_section; + + policy_table::Strings::iterator app_groups; + policy_table::Strings::iterator app_groups_end = app_groups; + policy_table::Strings::iterator app_pre_groups; + policy_table::Strings::iterator app_pre_groups_end = app_pre_groups; + + if (kDeviceId == policy_app_id) { + app_groups = app_policies_section.device.groups.begin(); + + app_groups_end = app_policies_section.device.groups.end(); + + app_pre_groups = app_policies_section.device.preconsented_groups->begin(); + + app_pre_groups_end = app_policies_section.device.preconsented_groups->end(); + } else { + app_groups = app_policies_section.apps[policy_app_id].groups.begin(); + + app_groups_end = app_policies_section.apps[policy_app_id].groups.end(); + + app_pre_groups = + app_policies_section.apps[policy_app_id].preconsented_groups->begin(); + + app_pre_groups_end = + app_policies_section.apps[policy_app_id].preconsented_groups->end(); + } + + policy_table::Strings groups_to_be_consented; + policy_table::FunctionalGroupings::iterator current_groups_iter; + for (; app_groups != app_groups_end; ++app_groups) { + current_groups_iter = + pt_->policy_table.functional_groupings.find(*app_groups); + + if (groups_iter_end != current_groups_iter) { + if (current_groups_iter->second.user_consent_prompt.is_initialized()) { + // Check if groups which requires user consent prompt + // not included in "preconsented_groups" section + if (app_pre_groups_end == + std::find(app_pre_groups, app_pre_groups_end, *app_groups)) { + groups_to_be_consented.push_back(*app_groups); + } + } + } + } + + if (groups_to_be_consented.empty()) { + return 0; + } + + // If there is no device record, all groups with consents should be consented + if (pt_->policy_table.device_data->end() == + pt_->policy_table.device_data->find(device_id)) { + return groups_to_be_consented.size(); + } + + policy_table::DeviceParams& params = + (*pt_->policy_table.device_data)[device_id]; + + policy_table::UserConsentRecords& ucr = *(params.user_consent_records); + + // If there is no application record, all groups with consents should be + // consented + if (ucr.end() == ucr.find(policy_app_id)) { + return groups_to_be_consented.size(); + } + + policy_table::ConsentRecords& cgr = ucr[policy_app_id]; + + policy_table::Strings::const_iterator to_consent_it = + groups_to_be_consented.begin(); + + for (; to_consent_it != groups_to_be_consented.end(); ++to_consent_it) { + policy_table::ConsentGroups::const_iterator already_consented_iter = + cgr.consent_groups->find(*to_consent_it); + if (already_consented_iter == cgr.consent_groups->end()) { + ++result; + } + } + + return result; +} + +bool CacheManager::SetMetaInfo(const std::string& ccpu_version, + const std::string& wers_country_code, + const std::string& language) { + CACHE_MANAGER_CHECK(false); + *pt_->policy_table.module_meta->ccpu_version = ccpu_version; + *pt_->policy_table.module_meta->wers_country_code = wers_country_code; + *pt_->policy_table.module_meta->language = language; + + // We have to set preloaded flag as false in policy table on any response + // of GetSystemInfo (SDLAQ-CRS-2365) + *pt_->policy_table.module_config.preloaded_pt = false; + + Backup(); + return true; +} + +bool CacheManager::IsMetaInfoPresent() const { + CACHE_MANAGER_CHECK(false); + bool result = true; + result = NULL != pt_->policy_table.module_meta->ccpu_version && + NULL != pt_->policy_table.module_meta->wers_country_code && + NULL != pt_->policy_table.module_meta->language; + return result; +} + +bool CacheManager::SetSystemLanguage(const std::string& language) { + CACHE_MANAGER_CHECK(false); + *pt_->policy_table.module_meta->language = language; + Backup(); + return true; +} + +bool CacheManager::GetFunctionalGroupNames(FunctionalGroupNames& names) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(false); + rpc::policy_table_interface_base::FunctionalGroupings::iterator iter = + pt_->policy_table.functional_groupings.begin(); + rpc::policy_table_interface_base::FunctionalGroupings::iterator iter_end = + pt_->policy_table.functional_groupings.end(); + + for (; iter != iter_end; ++iter) { + const int32_t id = utils::Djb2HashFromString((*iter).first); + std::pair<std::string, std::string> value = + std::make_pair(*(*iter).second.user_consent_prompt, (*iter).first); + + names.insert( + std::pair<uint32_t, std::pair<std::string, std::string> >(id, value)); + } + return true; +} + +bool CacheManager::CleanupUnpairedDevices() { + CACHE_MANAGER_CHECK(false); + sync_primitives::AutoLock lock(cache_lock_); + sync_primitives::AutoLock lock_unpaired(unpaired_lock_); + UnpairedDevices::iterator iter = is_unpaired_.begin(); + UnpairedDevices::const_iterator iter_end = is_unpaired_.end(); + LOG4CXX_DEBUG(logger_, "Is_unpaired size is: " << is_unpaired_.size()); + for (; iter != iter_end; ++iter) { + // Delete device + if (!pt_->policy_table.device_data.is_initialized()) { + LOG4CXX_ERROR(logger_, "Device_data section is not initialized."); + return false; + } + policy_table::DeviceData& device_data = *pt_->policy_table.device_data; + policy_table::DeviceData::iterator it_device = device_data.find(*iter); + if (device_data.end() == it_device) { + LOG4CXX_INFO(logger_, + "No device id " + << *iter << " had been found in device_data section."); + return false; + } + + LOG4CXX_DEBUG(logger_, "Device_data size is: " << device_data.size()); + device_data.erase(it_device); + LOG4CXX_INFO(logger_, + "Device id " << *iter + << " had been deleted from device_data section."); + LOG4CXX_DEBUG(logger_, "Device_data size is: " << device_data.size()); + } + is_unpaired_.clear(); + Backup(); + return true; +} + +void CacheManager::Increment(usage_statistics::GlobalCounterId type) { + CACHE_MANAGER_CHECK_VOID(); + sync_primitives::AutoLock lock(cache_lock_); + switch (type) { + case usage_statistics::IAP_BUFFER_FULL: + ++(*pt_->policy_table.usage_and_error_counts->count_of_iap_buffer_full); + break; + case usage_statistics::SYNC_OUT_OF_MEMORY: + ++(*pt_->policy_table.usage_and_error_counts->count_sync_out_of_memory); + break; + case usage_statistics::SYNC_REBOOTS: + ++(*pt_->policy_table.usage_and_error_counts->count_of_sync_reboots); + break; + default: + LOG4CXX_WARN(logger_, "Type global counter is unknown"); + return; + } + Backup(); +} + +void CacheManager::Increment(const std::string& app_id, + usage_statistics::AppCounterId type) { + CACHE_MANAGER_CHECK_VOID(); + sync_primitives::AutoLock lock(cache_lock_); + switch (type) { + case usage_statistics::USER_SELECTIONS: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .count_of_user_selections; + break; + case usage_statistics::REJECTIONS_SYNC_OUT_OF_MEMORY: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .count_of_rejections_sync_out_of_memory; + break; + case usage_statistics::REJECTIONS_NICKNAME_MISMATCH: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .count_of_rejections_nickname_mismatch; + break; + case usage_statistics::REJECTIONS_DUPLICATE_NAME: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .count_of_rejections_duplicate_name; + break; + case usage_statistics::REJECTED_RPC_CALLS: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .count_of_rejected_rpc_calls; + break; + case usage_statistics::RPCS_IN_HMI_NONE: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .count_of_rpcs_sent_in_hmi_none; + break; + case usage_statistics::REMOVALS_MISBEHAVED: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .count_of_removals_for_bad_behavior; + break; + case usage_statistics::RUN_ATTEMPTS_WHILE_REVOKED: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .count_of_run_attempts_while_revoked; + break; + case usage_statistics::COUNT_OF_TLS_ERRORS: + ++(*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .count_of_tls_errors; + break; + default: + LOG4CXX_WARN(logger_, "Type app counter is unknown"); + return; + } + Backup(); +} + +void CacheManager::Set(const std::string& app_id, + usage_statistics::AppInfoId type, + const std::string& value) { + CACHE_MANAGER_CHECK_VOID(); + sync_primitives::AutoLock lock(cache_lock_); + switch (type) { + case usage_statistics::LANGUAGE_GUI: + (*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .app_registration_language_gui = value; + break; + case usage_statistics::LANGUAGE_VUI: + (*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .app_registration_language_vui = value; + break; + default: + LOG4CXX_WARN(logger_, "Type app info is unknown"); + return; + } + Backup(); +} + +void CacheManager::Add(const std::string& app_id, + usage_statistics::AppStopwatchId type, + int seconds) { + CACHE_MANAGER_CHECK_VOID(); + sync_primitives::AutoLock lock(cache_lock_); + const int minutes = ConvertSecondsToMinute(seconds); + switch (type) { + case usage_statistics::SECONDS_HMI_FULL: + (*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .minutes_in_hmi_full += minutes; + break; + case usage_statistics::SECONDS_HMI_LIMITED: + (*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .minutes_in_hmi_limited += minutes; + break; + case usage_statistics::SECONDS_HMI_BACKGROUND: + (*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .minutes_in_hmi_background += minutes; + break; + case usage_statistics::SECONDS_HMI_NONE: + (*pt_->policy_table.usage_and_error_counts->app_level)[app_id] + .minutes_in_hmi_none += minutes; + break; + default: + LOG4CXX_WARN(logger_, "Type app stopwatch is unknown"); + return; + } + Backup(); +} + +long CacheManager::ConvertSecondsToMinute(int seconds) { + const float seconds_in_minute = 60.0; + return std::round(seconds / seconds_in_minute); +} + +bool CacheManager::SetDefaultPolicy(const std::string& app_id) { + CACHE_MANAGER_CHECK(false); + sync_primitives::AutoLock lock(cache_lock_); + auto& apps = pt_->policy_table.app_policies_section.apps; + + DCHECK_OR_RETURN(IsApplicationRepresented(kDefaultId), false); + + apps[app_id] = apps[kDefaultId]; + apps[app_id].set_to_string(kDefaultId); + Backup(); + return true; +} + +bool CacheManager::IsDefaultPolicy(const std::string& app_id) const { + CACHE_MANAGER_CHECK(false); + const bool result = + IsApplicationRepresented(app_id) && + policy::kDefaultId == + pt_->policy_table.app_policies_section.apps[app_id].get_string(); + + return result; +} + +bool CacheManager::SetIsDefault(const std::string& app_id) { + CACHE_MANAGER_CHECK(false); + + if (IsApplicationRepresented(app_id)) { + pt_->policy_table.app_policies_section.apps[app_id].set_to_string( + kDefaultId); + } + return true; +} + +bool policy::CacheManager::SetIsPredata(const std::string& app_id) { + CACHE_MANAGER_CHECK(false); + sync_primitives::AutoLock lock(cache_lock_); + if (IsApplicationRepresented(app_id)) { + pt_->policy_table.app_policies_section.apps[app_id].set_to_string( + kPreDataConsentId); + } + + return true; +} + +bool CacheManager::SetPredataPolicy(const std::string& app_id) { + CACHE_MANAGER_CHECK(false); + sync_primitives::AutoLock lock(cache_lock_); + policy_table::ApplicationPolicies::const_iterator iter = + pt_->policy_table.app_policies_section.apps.find(kPreDataConsentId); + + if (pt_->policy_table.app_policies_section.apps.end() == iter) { + LOG4CXX_ERROR(logger_, + "Could not set " << kPreDataConsentId + << " permissions for app " << app_id); + return false; + } + + pt_->policy_table.app_policies_section.apps[app_id] = + pt_->policy_table.app_policies_section.apps[kPreDataConsentId]; + + pt_->policy_table.app_policies_section.apps[app_id].set_to_string( + kPreDataConsentId); + + Backup(); + return true; +} + +bool CacheManager::IsPredataPolicy(const std::string& app_id) const { + if (!IsApplicationRepresented(app_id)) { + return false; + } + return kPreDataConsentId == + pt_->policy_table.app_policies_section.apps[app_id].get_string(); +} + +bool CacheManager::SetUnpairedDevice(const std::string& device_id, + bool unpaired) { + const bool result = pt_->policy_table.device_data->end() != + pt_->policy_table.device_data->find(device_id); + if (!result) { + LOG4CXX_DEBUG(logger_, + "Couldn't set unpaired flag for device id " + << device_id << " , since it wasn't found."); + return false; + } + + sync_primitives::AutoLock lock(unpaired_lock_); + if (unpaired) { + is_unpaired_.insert(device_id); + LOG4CXX_DEBUG(logger_, "Unpaired flag was set for device id " << device_id); + } else { + is_unpaired_.erase(device_id); + LOG4CXX_DEBUG(logger_, + "Unpaired flag was removed for device id " << device_id); + } + return result; +} + +bool CacheManager::SetVINValue(const std::string& value) { + CACHE_MANAGER_CHECK(false); + cache_lock_.Acquire(); + *pt_->policy_table.module_meta->vin = value; + cache_lock_.Release(); + Backup(); + return true; +} + +bool CacheManager::IsApplicationRepresented(const std::string& app_id) const { + CACHE_MANAGER_CHECK(false); + policy_table::ApplicationPolicies::const_iterator iter = + pt_->policy_table.app_policies_section.apps.find(app_id); + return pt_->policy_table.app_policies_section.apps.end() != iter; +} + +bool CacheManager::Init(const std::string& file_name, + const PolicySettings* settings) { + LOG4CXX_AUTO_TRACE(logger_); + settings_ = settings; + InitResult init_result = backup_->Init(settings); + ex_backup_ = utils::SharedPtr<PTRepresentation>::dynamic_pointer_cast< + PTExtRepresentation>(backup_); + + bool result = true; + switch (init_result) { + case InitResult::EXISTS: { + LOG4CXX_INFO(logger_, "Policy Table exists, was loaded correctly."); + result = LoadFromBackup(); + if (result) { + if (!backup_->IsDBVersionActual()) { + if (!backup_->RefreshDB()) { + return false; + } + backup_->UpdateDBVersion(); + Backup(); + } + if (!MergePreloadPT(file_name)) { + result = false; + } + } + } break; + case InitResult::SUCCESS: { + LOG4CXX_INFO(logger_, "Policy Table was inited successfully"); + result = LoadFromFile(file_name, *pt_); + utils::SharedPtr<policy_table::Table> snapshot = GenerateSnapshot(); + + result &= snapshot->is_valid(); + LOG4CXX_DEBUG(logger_, + "Check if snapshot valid: " << std::boolalpha << result); + + if (result) { + backup_->UpdateDBVersion(); + Backup(); + *pt_->policy_table.module_config.preloaded_pt = true; + } else { + rpc::ValidationReport report("policy_table"); + snapshot->ReportErrors(&report); + ex_backup_->RemoveDB(); + } + } break; + default: { + result = false; + LOG4CXX_ERROR(logger_, "Failed to init policy table."); + } break; + } + + return result; +} + +void CacheManager::FillDeviceSpecificData() { + DeviceIds unpaired_ids; + ex_backup_->UnpairedDevicesList(&unpaired_ids); + sync_primitives::AutoLock lock(unpaired_lock_); + is_unpaired_.clear(); + for (DeviceIds::const_iterator ids_iter = unpaired_ids.begin(); + ids_iter != unpaired_ids.end(); + ++ids_iter) { + is_unpaired_.insert(*ids_iter); + } +} + +bool CacheManager::LoadFromBackup() { + sync_primitives::AutoLock lock(cache_lock_); + pt_ = backup_->GenerateSnapshot(); + update_required = backup_->UpdateRequired(); + + FillDeviceSpecificData(); + + return true; +} + +bool CacheManager::LoadFromFile(const std::string& file_name, + policy_table::Table& table) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Loading policy table from file " << file_name); + BinaryMessage json_string; + if (!file_system::ReadBinaryFile(file_name, json_string)) { + LOG4CXX_FATAL(logger_, "Failed to read policy table source file."); + return false; + } + + Json::Value value; + Json::Reader reader(Json::Features::strictMode()); + std::string json(json_string.begin(), json_string.end()); + if (!reader.parse(json.c_str(), value)) { + LOG4CXX_FATAL( + logger_, + "Preloaded PT is corrupted: " << reader.getFormattedErrorMessages()); + return false; + } + + LOG4CXX_DEBUG(logger_, + "Start verification of policy table loaded from file."); + + table = policy_table::Table(&value); + +#ifdef ENABLE_LOG + Json::StyledWriter s_writer; + LOG4CXX_DEBUG( + logger_, + "Policy table content loaded:" << s_writer.write(table.ToJsonValue())); +#endif // ENABLE_LOG + + if (!table.is_valid()) { + rpc::ValidationReport report("policy_table"); + table.ReportErrors(&report); + LOG4CXX_FATAL(logger_, + "Parsed table is not valid " << rpc::PrettyFormat(report)); + return false; + } + return true; +} + +bool CacheManager::ResetPT(const std::string& file_name) { + LOG4CXX_AUTO_TRACE(logger_); + is_unpaired_.clear(); + if (!backup_->RefreshDB()) { + LOG4CXX_ERROR(logger_, "Can't re-create policy database. Reset failed."); + return false; + } + sync_primitives::AutoLock lock(cache_lock_); + pt_.reset(new policy_table::Table()); + const bool result = LoadFromFile(file_name, *pt_); + if (result) { + Backup(); + *pt_->policy_table.module_config.preloaded_pt = true; + } + return result; +} + +void CacheManager::GetAppRequestTypes( + const std::string& policy_app_id, + std::vector<std::string>& request_types) const { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + if (kDeviceId == policy_app_id) { + LOG4CXX_DEBUG(logger_, + "Request types not applicable for app_id " << kDeviceId); + return; + } + policy_table::ApplicationPolicies::iterator policy_iter = + pt_->policy_table.app_policies_section.apps.find(policy_app_id); + if (pt_->policy_table.app_policies_section.apps.end() == policy_iter) { + LOG4CXX_DEBUG(logger_, + "Can't find request types for app_id " << policy_app_id); + return; + } + if (policy_iter->second.RequestType.is_initialized()) { + policy_table::RequestTypes::iterator it_request_type = + policy_iter->second.RequestType->begin(); + for (; it_request_type != policy_iter->second.RequestType->end(); + ++it_request_type) { + request_types.push_back(EnumToJsonString(*it_request_type)); + } + } + return; +} + +const MetaInfo CacheManager::GetMetaInfo() const { + LOG4CXX_AUTO_TRACE(logger_); + MetaInfo meta_info; + meta_info.ccpu_version = *pt_->policy_table.module_meta->ccpu_version; + meta_info.wers_country_code = + *pt_->policy_table.module_meta->wers_country_code; + meta_info.language = *pt_->policy_table.module_meta->language; + return meta_info; +} + +std::string CacheManager::GetCertificate() const { + CACHE_MANAGER_CHECK(std::string("")); + if (pt_->policy_table.module_config.certificate.is_initialized()) { + return *pt_->policy_table.module_config.certificate; + } + return std::string(""); +} + +void CacheManager::SetDecryptedCertificate(const std::string& certificate) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + sync_primitives::AutoLock auto_lock(cache_lock_); + *pt_->policy_table.module_config.certificate = certificate; + Backup(); +} + +bool CacheManager::SetExternalConsentStatus( + const ExternalConsentStatus& status) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(cache_lock_); + if (status.empty()) { + LOG4CXX_INFO(logger_, "No ExternalConsent status update."); + return false; + } + + return ex_backup_->SaveExternalConsentStatus(status); +} + +ExternalConsentStatus CacheManager::GetExternalConsentStatus() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(cache_lock_); + return ex_backup_->GetExternalConsentStatus(); +} + +ExternalConsentStatus CacheManager::GetExternalConsentEntities() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(cache_lock_); + ExternalConsentStatus items; + for (policy_table::FunctionalGroupings::const_iterator it = + pt_->policy_table.functional_groupings.begin(); + it != pt_->policy_table.functional_groupings.end(); + ++it) { + policy_table::DisallowedByExternalConsentEntities::const_iterator it_1 = + (*it->second.disallowed_by_external_consent_entities_on).begin(); + for (; + it_1 != (*it->second.disallowed_by_external_consent_entities_on).end(); + ++it_1) { + items.insert(ExternalConsentStatusItem( + it_1->entity_type, it_1->entity_id, EntityStatus::kStatusOn)); + } + policy_table::DisallowedByExternalConsentEntities::const_iterator it_2 = + (*it->second.disallowed_by_external_consent_entities_off).begin(); + for (; it_2 != + (*it->second.disallowed_by_external_consent_entities_off).end(); + ++it_2) { + items.insert(ExternalConsentStatusItem( + it_2->entity_type, it_2->entity_id, EntityStatus::kStatusOff)); + } + } + return items; +} + +GroupsByExternalConsentStatus CacheManager::GetGroupsWithSameEntities( + const ExternalConsentStatus& status) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(policy::GroupsByExternalConsentStatus()); + sync_primitives::AutoLock auto_lock(cache_lock_); + GroupsByExternalConsentStatus groups_by_external_consent; + + GroupByExternalConsentItemFinder groups_by_external_consent_finder( + pt_->policy_table.functional_groupings, groups_by_external_consent); + std::for_each( + status.begin(), status.end(), groups_by_external_consent_finder); + + return groups_by_external_consent; +} + +std::map<std::string, std::string> CacheManager::GetKnownLinksFromPT() { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK((std::map<std::string, std::string>())); + std::map<std::string, std::string> links; + sync_primitives::AutoLock auto_lock(cache_lock_); + + LinkCollector collector(links); + std::for_each(pt_->policy_table.device_data->begin(), + pt_->policy_table.device_data->end(), + collector); + + return links; +} + +bool CacheManager::ConsentsSame( + const policy_table::ConsentGroups& external_consent_groups, + const PermissionConsent& permissions) const { + const std::vector<FunctionalGroupPermission>& group_permissions = + permissions.group_permissions; + + std::vector<FunctionalGroupPermission>::const_iterator it_gp = + group_permissions.begin(); + + for (; group_permissions.end() != it_gp; ++it_gp) { + const policy_table::ConsentGroups::value_type value = std::make_pair( + it_gp->group_name, rpc::Boolean(it_gp->state == kGroupAllowed)); + + const bool is_found = external_consent_groups.end() != + std::find(external_consent_groups.begin(), + external_consent_groups.end(), + value); + + if (!is_found) { + return false; + } + } + + return true; +} + +void CacheManager::SetExternalConsentForApp( + const PermissionConsent& permissions) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + sync_primitives::AutoLock auto_lock(cache_lock_); + policy_table::ConsentGroups& external_consent_groups = + *(*(*pt_->policy_table.device_data)[permissions.device_id] + .user_consent_records)[permissions.policy_app_id] + .external_consent_status_groups; + + if (ConsentsSame(external_consent_groups, permissions)) { + LOG4CXX_DEBUG(logger_, "External consents already have same values."); + return; + } + + external_consent_groups.clear(); + + ExternalConsentConsentGroupAppender appender; + std::transform( + permissions.group_permissions.begin(), + permissions.group_permissions.end(), + std::inserter(external_consent_groups, external_consent_groups.begin()), + appender); + + policy_table::ConsentRecords& app_consent_records = + (*(*pt_->policy_table.device_data)[permissions.device_id] + .user_consent_records)[permissions.policy_app_id]; + + const TimevalStruct tm = date_time::DateTime::getCurrentTime(); + int64_t current_time_msec = date_time::DateTime::getmSecs(tm); + app_consent_records.ext_consent_last_updated = current_time_msec; + LOG4CXX_DEBUG(logger_, "Updating consents time " << current_time_msec); + + Backup(); +} + +bool CacheManager::MergePreloadPT(const std::string& file_name) { + LOG4CXX_AUTO_TRACE(logger_); + policy_table::Table table; + if (!LoadFromFile(file_name, table)) { + LOG4CXX_DEBUG(logger_, "Unable to load preloaded PT."); + return false; + } + + sync_primitives::AutoLock lock(cache_lock_); + policy_table::PolicyTable& current = pt_->policy_table; + policy_table::PolicyTable& new_table = table.policy_table; + const std::string date_current = *current.module_config.preloaded_date; + const std::string date_new = *new_table.module_config.preloaded_date; + if (date_current != date_new) { + MergeMC(new_table, current); + MergeFG(new_table, current); + MergeAP(new_table, current); + MergeCFM(new_table, current); + Backup(); + } + return true; +} + +void CacheManager::MergeMC(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt) { + LOG4CXX_AUTO_TRACE(logger_); + policy_table::ModuleConfig copy(pt.module_config); + + pt.module_config = new_pt.module_config; + pt.module_config.vehicle_make = copy.vehicle_make; + pt.module_config.vehicle_year = copy.vehicle_year; + pt.module_config.vehicle_model = copy.vehicle_model; +} + +void CacheManager::MergeFG(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt) { + LOG4CXX_AUTO_TRACE(logger_); + policy_table::FunctionalGroupings::const_iterator it = + new_pt.functional_groupings.begin(); + + for (; it != new_pt.functional_groupings.end(); ++it) { + LOG4CXX_DEBUG(logger_, "Merge functional group: " << it->first); + pt.functional_groupings[it->first] = it->second; + } +} + +void CacheManager::MergeAP(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt) { + LOG4CXX_AUTO_TRACE(logger_); + pt.app_policies_section.device = const_cast<policy_table::PolicyTable&>( + new_pt).app_policies_section.device; + + pt.app_policies_section.apps[kDefaultId] = + const_cast<policy_table::PolicyTable&>(new_pt) + .app_policies_section.apps[kDefaultId]; + + pt.app_policies_section.apps[kPreDataConsentId] = + const_cast<policy_table::PolicyTable&>(new_pt) + .app_policies_section.apps[kPreDataConsentId]; +} + +void CacheManager::MergeCFM(const policy_table::PolicyTable& new_pt, + policy_table::PolicyTable& pt) { + LOG4CXX_AUTO_TRACE(logger_); + if (new_pt.consumer_friendly_messages.is_initialized()) { + if (!pt.consumer_friendly_messages.is_initialized()) { + pt.consumer_friendly_messages = new_pt.consumer_friendly_messages; + } else { + policy_table::Messages::const_iterator it = + new_pt.consumer_friendly_messages->messages->begin(); + + pt.consumer_friendly_messages->version = + new_pt.consumer_friendly_messages->version; + for (; it != new_pt.consumer_friendly_messages->messages->end(); ++it) { + LOG4CXX_DEBUG(logger_, "Merge CFM: " << it->first); + if (!(pt.consumer_friendly_messages->messages.is_initialized())) { + LOG4CXX_DEBUG(logger_, "CFM not initialized."); + } + (*pt.consumer_friendly_messages->messages)[it->first] = it->second; + } + } + } +} + +void CacheManager::InitBackupThread() { + LOG4CXX_AUTO_TRACE(logger_); + backuper_ = new BackgroundBackuper(this); + backup_thread_ = threads::CreateThread("Backup thread", backuper_); + backup_thread_->start(); +} + +const PolicySettings& CacheManager::get_settings() const { + DCHECK(settings_); + + return *settings_; +} + +CacheManager::BackgroundBackuper::BackgroundBackuper( + CacheManager* cache_manager) + : cache_manager_(cache_manager) + , stop_flag_(false) + , new_data_available_(false) { + LOG4CXX_AUTO_TRACE(logger_); +} + +CacheManager::BackgroundBackuper::~BackgroundBackuper() { + LOG4CXX_AUTO_TRACE(logger_); +} + +void CacheManager::BackgroundBackuper::InternalBackup() { + LOG4CXX_AUTO_TRACE(logger_); + DCHECK(cache_manager_); + + while (new_data_available_) { + new_data_available_ = false; + LOG4CXX_DEBUG(logger_, "DoBackup"); + cache_manager_->PersistData(); + } +} + +void CacheManager::BackgroundBackuper::threadMain() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(need_backup_lock_); + while (!stop_flag_) { + need_backup_lock_.Release(); + InternalBackup(); + need_backup_lock_.Acquire(); + if (new_data_available_ || stop_flag_) { + continue; + } + LOG4CXX_DEBUG(logger_, "Wait for a next backup"); + backup_notifier_.Wait(need_backup_lock_); + } +} + +void CacheManager::BackgroundBackuper::exitThreadMain() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(need_backup_lock_); + stop_flag_ = true; + backup_notifier_.NotifyOne(); +} + +void CacheManager::BackgroundBackuper::DoBackup() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(need_backup_lock_); + new_data_available_ = true; + backup_notifier_.NotifyOne(); +} + +} // namespace policy diff --git a/src/components/policy/policy_external/src/policy_helper.cc b/src/components/policy/policy_external/src/policy_helper.cc new file mode 100644 index 0000000000..cb27e7f0b3 --- /dev/null +++ b/src/components/policy/policy_external/src/policy_helper.cc @@ -0,0 +1,868 @@ +/* + Copyright (c) 2013, Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include <algorithm> +#include <sstream> +#include <string.h> +#include "utils/logger.h" +#include "utils/custom_string.h" +#include "policy/policy_helper.h" +#include "policy/policy_manager_impl.h" + +namespace policy { + +namespace custom_str = utils::custom_string; + +namespace { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +bool Compare(const StringsValueType& first, const StringsValueType& second) { + const std::string& first_str = first; + const std::string& second_str = second; + return (strcasecmp(first_str.c_str(), second_str.c_str()) < 0); +} + +struct CheckGroupName { + explicit CheckGroupName(const policy::StringsValueType& value) + : value_(value) {} + + bool operator()(const FunctionalGroupNames::value_type& value) const { + return value.second.second == std::string(value_); + } + + private: + const policy::StringsValueType& value_; +}; + +struct CopyAttributes { + CopyAttributes(const FunctionalGroupNames& groups_attributes, + std::vector<FunctionalGroupPermission>& groups_permissions) + : groups_attributes_(groups_attributes) + , groups_permissions_(groups_permissions) {} + + bool operator()(const policy::StringsValueType& value) { + CheckGroupName checker(value); + FunctionalGroupNames::const_iterator it = std::find_if( + groups_attributes_.begin(), groups_attributes_.end(), checker); + if (groups_attributes_.end() == it) { + return false; + } + FunctionalGroupPermission group; + group.group_name = it->second.second; + group.group_alias = it->second.first; + group.group_id = it->first; + groups_permissions_.push_back(group); + return true; + } + + private: + const FunctionalGroupNames& groups_attributes_; + std::vector<FunctionalGroupPermission>& groups_permissions_; +}; +} // namespace + +CompareGroupName::CompareGroupName(const StringsValueType& group_name) + : group_name_(group_name) {} + +bool CompareGroupName::operator()( + const StringsValueType& group_name_to_compare) const { + const std::string gn_ = group_name_; + const std::string gn_compare = group_name_to_compare; + return !(strcasecmp(gn_.c_str(), gn_compare.c_str())); +} + +bool operator!=(const policy_table::ApplicationParams& first, + const policy_table::ApplicationParams& second) { + if (first.groups.size() != second.groups.size()) { + return true; + } + StringsConstItr it_first = first.groups.begin(); + StringsConstItr it_first_end = first.groups.end(); + StringsConstItr it_second = second.groups.begin(); + StringsConstItr it_second_end = second.groups.end(); + for (; it_first != it_first_end; ++it_first) { + CompareGroupName gp(*it_first); + StringsConstItr it = std::find_if(it_second, it_second_end, gp); + if (it_first_end == it) { + return true; + } + } + return false; +} + +CheckAppPolicy::CheckAppPolicy( + PolicyManagerImpl* pm, + const utils::SharedPtr<policy_table::Table> update, + const utils::SharedPtr<policy_table::Table> snapshot, + CheckAppPolicyResults& out_results) + : pm_(pm) + , update_(update) + , snapshot_(snapshot) + , out_results_(out_results) {} + +bool policy::CheckAppPolicy::HasRevokedGroups( + const policy::AppPoliciesValueType& app_policy, + policy_table::Strings* revoked_groups) const { + AppPoliciesConstItr it = + snapshot_->policy_table.app_policies_section.apps.find(app_policy.first); + + policy_table::Strings groups_new = app_policy.second.groups; + std::sort(groups_new.begin(), groups_new.end(), Compare); + + policy_table::Strings groups_curr = (*it).second.groups; + std::sort(groups_curr.begin(), groups_curr.end(), Compare); + + StringsConstItr it_groups_new = groups_new.begin(); + StringsConstItr it_groups_new_end = groups_new.end(); + + StringsConstItr it_groups_curr = groups_curr.begin(); + StringsConstItr it_groups_curr_end = groups_curr.end(); + + policy_table::Strings revoked_group_list; + std::set_difference(it_groups_curr, + it_groups_curr_end, + it_groups_new, + it_groups_new_end, + std::back_inserter(revoked_group_list), + Compare); + + // Remove groups which are not required user consent + policy_table::Strings::iterator it_revoked = revoked_group_list.begin(); + for (; revoked_group_list.end() != it_revoked;) { + if (!IsConsentRequired(app_policy.first, std::string(*it_revoked))) { + revoked_group_list.erase(it_revoked); + it_revoked = revoked_group_list.begin(); + } else { + ++it_revoked; + } + } + + if (revoked_groups) { + *revoked_groups = revoked_group_list; + } + + return !revoked_group_list.empty(); +} + +bool policy::CheckAppPolicy::HasNewGroups( + const policy::AppPoliciesValueType& app_policy, + policy_table::Strings* new_groups) const { + AppPoliciesConstItr it = + snapshot_->policy_table.app_policies_section.apps.find(app_policy.first); + + policy_table::Strings groups_new = app_policy.second.groups; + std::sort(groups_new.begin(), groups_new.end(), Compare); + + policy_table::Strings groups_curr = (*it).second.groups; + std::sort(groups_curr.begin(), groups_curr.end(), Compare); + + StringsConstItr it_groups_new = groups_new.begin(); + StringsConstItr it_groups_new_end = groups_new.end(); + + StringsConstItr it_groups_curr = groups_curr.begin(); + StringsConstItr it_groups_curr_end = groups_curr.end(); + + policy_table::Strings new_group_list; + std::set_difference(it_groups_new, + it_groups_new_end, + it_groups_curr, + it_groups_curr_end, + std::back_inserter(new_group_list), + Compare); + + if (new_groups) { + *new_groups = new_group_list; + } + + return !new_group_list.empty(); +} + +bool policy::CheckAppPolicy::HasConsentNeededGroups( + const policy::AppPoliciesValueType& app_policy) const { + policy_table::Strings new_groups; + if (!HasNewGroups(app_policy, &new_groups)) { + return false; + } + + StringsConstItr it_new = new_groups.begin(); + StringsConstItr it_new_end = new_groups.end(); + for (; it_new != it_new_end; ++it_new) { + if (IsConsentRequired(app_policy.first, *it_new)) { + return true; + } + } + + return false; +} + +std::vector<FunctionalGroupPermission> policy::CheckAppPolicy::GetRevokedGroups( + const policy::AppPoliciesValueType& app_policy) const { + policy_table::Strings revoked_groups_names; + if (!HasRevokedGroups(app_policy, &revoked_groups_names)) { + return std::vector<FunctionalGroupPermission>(); + } + + FunctionalGroupNames groups_attributes; + if (!pm_->cache_->GetFunctionalGroupNames(groups_attributes)) { + LOG4CXX_WARN(logger_, "Can't get functional group names"); + return std::vector<FunctionalGroupPermission>(); + } + + std::vector<FunctionalGroupPermission> revoked_groups_permissions; + CopyAttributes copier(groups_attributes, revoked_groups_permissions); + std::for_each( + revoked_groups_names.begin(), revoked_groups_names.end(), copier); + + return revoked_groups_permissions; +} + +void policy::CheckAppPolicy::RemoveRevokedConsents( + const AppPoliciesValueType& app_policy, + const std::vector<FunctionalGroupPermission>& revoked_groups) const { + std::vector<policy::FunctionalGroupPermission>::const_iterator it = + revoked_groups.begin(); + std::vector<policy::FunctionalGroupPermission>::const_iterator it_end = + revoked_groups.end(); + for (; it != it_end; ++it) { + pm_->RemoveAppConsentForGroup(app_policy.first, it->group_name); + } +} + +bool CheckAppPolicy::IsKnownAppication( + const std::string& application_id) const { + const policy_table::ApplicationPolicies& current_policies = + snapshot_->policy_table.app_policies_section.apps; + + return !(current_policies.end() == current_policies.find(application_id)); +} + +bool CheckAppPolicy::IsAppRevoked( + const AppPoliciesValueType& app_policy) const { + LOG4CXX_AUTO_TRACE(logger_); + // Application params are not initialized = application revoked + // i.e. "123":null + return app_policy.second.is_null(); +} + +bool CheckAppPolicy::NicknamesMatch( + const AppPoliciesValueType& app_policy) const { + const std::string& app_id = app_policy.first; + const custom_str::CustomString app_name = pm_->listener()->GetAppName(app_id); + if (!app_name.empty() && app_policy.second.nicknames && + !app_policy.second.nicknames->empty()) { + for (policy_table::Strings::const_iterator it = + app_policy.second.nicknames->begin(); + app_policy.second.nicknames->end() != it; + ++it) { + std::string temp = *it; + if (app_name.CompareIgnoreCase(temp.c_str())) { + return true; + } + } + return false; + } + return true; +} + +void CheckAppPolicy::AddResult(const std::string& app_id, + PermissionsCheckResult result) { + out_results_.insert(std::make_pair(app_id, result)); +} + +bool CheckAppPolicy::operator()(const AppPoliciesValueType& app_policy) { + const std::string app_id = app_policy.first; + + if (!IsKnownAppication(app_id)) { + LOG4CXX_WARN(logger_, + "Application:" << app_id << " is not present in snapshot."); + return true; + } + + if (!IsPredefinedApp(app_policy) && IsAppRevoked(app_policy)) { + SetPendingPermissions(app_policy, RESULT_APP_REVOKED); + AddResult(app_id, RESULT_APP_REVOKED); + return true; + } + + if (!IsPredefinedApp(app_policy) && !NicknamesMatch(app_policy)) { + SetPendingPermissions(app_policy, RESULT_NICKNAME_MISMATCH); + AddResult(app_id, RESULT_NICKNAME_MISMATCH); + return true; + } + + PermissionsCheckResult result = CheckPermissionsChanges(app_policy); + + if (!IsPredefinedApp(app_policy) && IsRequestTypeChanged(app_policy)) { + SetPendingPermissions(app_policy, RESULT_REQUEST_TYPE_CHANGED); + AddResult(app_id, RESULT_REQUEST_TYPE_CHANGED); + } + + if (RESULT_NO_CHANGES == result) { + LOG4CXX_INFO(logger_, + "Permissions for application:" << app_id + << " wasn't changed."); + AddResult(app_id, result); + return true; + } + + LOG4CXX_INFO(logger_, + "Permissions for application:" << app_id + << " have been changed."); + + if (!IsPredefinedApp(app_policy)) { + SetPendingPermissions(app_policy, result); + AddResult(app_id, result); + } + + return true; +} + +void policy::CheckAppPolicy::SetPendingPermissions( + const AppPoliciesValueType& app_policy, + PermissionsCheckResult result) const { + using namespace rpc::policy_table_interface_base; + const std::string app_id = app_policy.first; + AppPermissions permissions_diff(app_id); + + const std::string priority = + policy_table::EnumToJsonString(app_policy.second.priority); + const std::string current_prio = EnumToJsonString( + snapshot_->policy_table.app_policies_section.apps[app_id].priority); + + bool need_send_priority = (current_prio != priority); + + switch (result) { + case RESULT_APP_REVOKED: + need_send_priority = false; + permissions_diff.appRevoked = true; + break; + case RESULT_NICKNAME_MISMATCH: + need_send_priority = false; + permissions_diff.appUnauthorized = true; + break; + case RESULT_PERMISSIONS_REVOKED: + permissions_diff.priority = priority; + permissions_diff.isAppPermissionsRevoked = true; + permissions_diff.appRevokedPermissions = GetRevokedGroups(app_policy); + RemoveRevokedConsents(app_policy, permissions_diff.appRevokedPermissions); + break; + case RESULT_CONSENT_NEEDED: + permissions_diff.priority = priority; + permissions_diff.appPermissionsConsentNeeded = true; + break; + case RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED: + permissions_diff.priority = priority; + permissions_diff.isAppPermissionsRevoked = true; + permissions_diff.appPermissionsConsentNeeded = true; + permissions_diff.appRevokedPermissions = GetRevokedGroups(app_policy); + RemoveRevokedConsents(app_policy, permissions_diff.appRevokedPermissions); + break; + case RESULT_REQUEST_TYPE_CHANGED: + permissions_diff.requestTypeChanged = true; + { + // Getting RequestTypes from PTU (not from cache) + policy_table::RequestTypes::const_iterator it_request_type = + app_policy.second.RequestType->begin(); + for (; app_policy.second.RequestType->end() != it_request_type; + ++it_request_type) { + permissions_diff.requestType.push_back( + EnumToJsonString(*it_request_type)); + } + } + + break; + default: + return; + } + + if (need_send_priority) { + permissions_diff.priority = priority; + } + + pm_->app_permissions_diff_lock_.Acquire(); + pm_->app_permissions_diff_.insert(std::make_pair(app_id, permissions_diff)); + pm_->app_permissions_diff_lock_.Release(); +} + +PermissionsCheckResult CheckAppPolicy::CheckPermissionsChanges( + const policy::AppPoliciesValueType& app_policy) const { + bool has_revoked_groups = HasRevokedGroups(app_policy); + + bool has_consent_needed_groups = HasConsentNeededGroups(app_policy); + + bool has_new_groups = HasNewGroups(app_policy); + + if (has_revoked_groups && has_consent_needed_groups) { + return RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED; + } else if (has_revoked_groups) { + return RESULT_PERMISSIONS_REVOKED; + } else if (has_consent_needed_groups) { + return RESULT_CONSENT_NEEDED; + } else if (has_new_groups) { + return RESULT_CONSENT_NOT_REQIURED; + } + + return RESULT_NO_CHANGES; +} + +bool CheckAppPolicy::IsConsentRequired(const std::string& app_id, + const std::string& group_name) const { + const policy_table::FunctionalGroupings& functional_groupings = + snapshot_->policy_table.functional_groupings; + + FuncGroupConstItr it = functional_groupings.find(group_name); + + if (functional_groupings.end() == it) { + return false; + } + + bool is_preconsented = false; + policy_table::Strings::value_type str(group_name); + policy_table::Strings::iterator pre_begin = + update_->policy_table.app_policies_section.apps[app_id] + .preconsented_groups->begin(); + policy_table::Strings::iterator pre_end = + update_->policy_table.app_policies_section.apps[app_id] + .preconsented_groups->end(); + + policy_table::Strings::iterator it2 = std::find(pre_begin, pre_end, str); + + is_preconsented = pre_end != it2; + + return it->second.user_consent_prompt.is_initialized() && !is_preconsented; +} + +bool CheckAppPolicy::IsRequestTypeChanged( + const AppPoliciesValueType& app_policy) const { + policy::AppPoliciesConstItr it = + snapshot_->policy_table.app_policies_section.apps.find(app_policy.first); + if (it == snapshot_->policy_table.app_policies_section.apps.end()) { + if (!app_policy.second.RequestType->empty()) { + return true; + } + return false; + } + if (it->second.RequestType->size() != app_policy.second.RequestType->size()) { + return true; + } + policy_table::RequestTypes diff; + std::set_difference(it->second.RequestType->begin(), + it->second.RequestType->end(), + app_policy.second.RequestType->begin(), + app_policy.second.RequestType->end(), + std::back_inserter(diff)); + return diff.size(); +} + +FillNotificationData::FillNotificationData(Permissions& data, + GroupConsent group_state, + GroupConsent undefined_group_consent, + bool does_require_user_consent) + : data_(data), does_require_user_consent_(does_require_user_consent) { + switch (group_state) { + case kGroupAllowed: + current_key_ = kAllowedKey; + break; + case kGroupUndefined: + if (kGroupUndefined == undefined_group_consent) { + current_key_ = kUndefinedKey; + break; + } + current_key_ = kGroupAllowed == undefined_group_consent + ? kAllowedKey + : kUserDisallowedKey; + break; + default: + current_key_ = kUserDisallowedKey; + break; + } +} + +bool FillNotificationData::operator()(const RpcValueType& rpc) { + Permissions::iterator it = data_.find(rpc.first); + // If rpc is present already - update its permissions + if (data_.end() != it) { + UpdateHMILevels(rpc.second.hmi_levels, (*it).second.hmi_permissions); + UpdateParameters(*rpc.second.parameters, + (*it).second.parameter_permissions); + ExcludeSame(it->second); + } else { + // Init mandatory keys, since they should be present irrespectively of + // values presence + InitRpcKeys(rpc.first); + // If rpc is not present - add its permissions + UpdateHMILevels(rpc.second.hmi_levels, data_[rpc.first].hmi_permissions); + UpdateParameters(*rpc.second.parameters, + data_[rpc.first].parameter_permissions); + } + return true; +} + +void FillNotificationData::UpdateHMILevels( + const policy_table::HmiLevels& in_hmi, HMIPermissions& out_hmi) { + HMILevelsConstItr it_hmi_levels = in_hmi.begin(); + HMILevelsConstItr it_hmi_levels_end = in_hmi.end(); + + for (; it_hmi_levels != it_hmi_levels_end; ++it_hmi_levels) { + out_hmi[current_key_].insert( + policy_table::EnumToJsonString(*it_hmi_levels)); + } +} + +void FillNotificationData::UpdateParameters( + const policy_table::Parameters& in_parameters, + ParameterPermissions& out_parameter) { + ParametersConstItr it_parameters = in_parameters.begin(); + ParametersConstItr it_parameters_end = in_parameters.end(); + + // Due to APPLINK-24201 SDL must consider cases when 'parameters' section is + // not present for RPC or present, but is empty. + + // If 'parameters' section is like: 'parameters' : [] + if (in_parameters.is_initialized() && in_parameters.empty()) { + if (!does_require_user_consent_) { + out_parameter.any_parameter_disallowed_by_policy = true; + } + if (does_require_user_consent_ && kAllowedKey == current_key_) { + out_parameter.any_parameter_disallowed_by_user = true; + } + } + + // If 'parameters' section is omitted + if (!in_parameters.is_initialized()) { + if (!does_require_user_consent_) { + out_parameter.any_parameter_allowed = true; + } + if (does_require_user_consent_ && kAllowedKey == current_key_) { + out_parameter.any_parameter_allowed = true; + } + } + + for (; it_parameters != it_parameters_end; ++it_parameters) { + out_parameter[current_key_].insert( + policy_table::EnumToJsonString(*it_parameters)); + } +} + +void FillNotificationData::ExcludeSame(RpcPermissions& rpc) { + HMIPermissions::const_iterator it_hmi_allowed = + rpc.hmi_permissions.find(kAllowedKey); + HMIPermissions::const_iterator it_hmi_undefined = + rpc.hmi_permissions.find(kUndefinedKey); + HMIPermissions::const_iterator it_hmi_user_disallowed = + rpc.hmi_permissions.find(kUserDisallowedKey); + + // There is different logic of processing RPCs with and w/o 'parameters' + if (RpcParametersEmpty(rpc)) { + // First, remove disallowed from other types + if (rpc.hmi_permissions.end() != it_hmi_user_disallowed) { + if (rpc.hmi_permissions.end() != it_hmi_allowed) { + ExcludeSameHMILevels(rpc.hmi_permissions[kAllowedKey], + rpc.hmi_permissions[kUserDisallowedKey]); + } + if (rpc.hmi_permissions.end() != it_hmi_undefined) { + ExcludeSameHMILevels(rpc.hmi_permissions[kUndefinedKey], + rpc.hmi_permissions[kUserDisallowedKey]); + } + } + + // Then, remove undefined from allowed + if (rpc.hmi_permissions.end() != it_hmi_undefined) { + if (rpc.hmi_permissions.end() != it_hmi_allowed) { + ExcludeSameHMILevels(rpc.hmi_permissions[kAllowedKey], + rpc.hmi_permissions[kUndefinedKey]); + } + } + + return; + } + + ParameterPermissions::const_iterator it_parameter_allowed = + rpc.parameter_permissions.find(kAllowedKey); + ParameterPermissions::const_iterator it_parameter_undefined = + rpc.parameter_permissions.find(kUndefinedKey); + ParameterPermissions::const_iterator it_parameter_user_disallowed = + rpc.parameter_permissions.find(kUserDisallowedKey); + + // First, removing allowed HMI levels from other types, permissions will be + // dependent on parameters instead of HMI levels since w/o parameters RPC + // won't passed to HMI + if (rpc.hmi_permissions.end() != it_hmi_allowed) { + if (rpc.hmi_permissions.end() != it_hmi_user_disallowed) { + ExcludeSameHMILevels(rpc.hmi_permissions[kUserDisallowedKey], + rpc.hmi_permissions[kAllowedKey]); + } + if (rpc.hmi_permissions.end() != it_hmi_undefined) { + ExcludeSameHMILevels(rpc.hmi_permissions[kUndefinedKey], + rpc.hmi_permissions[kAllowedKey]); + } + } + + // Removing disallowed parameters from allowed and undefined (by user consent) + if (rpc.parameter_permissions.end() != it_parameter_user_disallowed) { + if (rpc.parameter_permissions.end() != it_parameter_allowed) { + ExcludeSameParameters(rpc.parameter_permissions[kAllowedKey], + rpc.parameter_permissions[kUserDisallowedKey]); + } + if (rpc.parameter_permissions.end() != it_parameter_undefined) { + ExcludeSameParameters(rpc.parameter_permissions[kUndefinedKey], + rpc.parameter_permissions[kUserDisallowedKey]); + } + } + + // Removing undefined (by user consent) parameters from allowed + if (rpc.parameter_permissions.end() != it_parameter_undefined) { + if (rpc.parameter_permissions.end() != it_parameter_allowed) { + ExcludeSameParameters(rpc.parameter_permissions[kAllowedKey], + rpc.parameter_permissions[kUndefinedKey]); + } + } +} + +void FillNotificationData::ExcludeSameHMILevels( + std::set<HMILevel>& source, const std::set<HMILevel>& target) { + std::set<HMILevel> diff_hmi; + + std::set_difference(source.begin(), + source.end(), + target.begin(), + target.end(), + std::inserter(diff_hmi, diff_hmi.begin())); + + source = diff_hmi; +} + +void FillNotificationData::ExcludeSameParameters( + std::set<Parameter>& source, const std::set<Parameter>& target) { + std::set<Parameter> diff_parameter; + + std::set_difference(source.begin(), + source.end(), + target.begin(), + target.end(), + std::inserter(diff_parameter, diff_parameter.begin())); + + source = diff_parameter; +} + +void FillNotificationData::InitRpcKeys(const std::string& rpc_name) { + data_[rpc_name].hmi_permissions[kAllowedKey]; + data_[rpc_name].hmi_permissions[kUserDisallowedKey]; + data_[rpc_name].parameter_permissions[kAllowedKey]; + data_[rpc_name].parameter_permissions[kUserDisallowedKey]; +} + +bool FillNotificationData::RpcParametersEmpty(RpcPermissions& rpc) { + const bool no_allowed_parameters = + IsSectionEmpty(rpc.parameter_permissions, kAllowedKey); + const bool no_user_disallowed_parameters = + IsSectionEmpty(rpc.parameter_permissions, kUserDisallowedKey); + const bool no_undefined_parameters = + IsSectionEmpty(rpc.parameter_permissions, kUndefinedKey); + + return no_allowed_parameters && no_undefined_parameters && + no_user_disallowed_parameters; +} + +bool FillNotificationData::IsSectionEmpty(ParameterPermissions& permissions, + const std::string& section) { + ParameterPermissions::const_iterator it_section = permissions.find(section); + ParameterPermissions::const_iterator end = permissions.end(); + if (end != it_section) { + return permissions[section].empty(); + } + return true; +} + +ProcessFunctionalGroup::ProcessFunctionalGroup( + const policy_table::FunctionalGroupings& fg, + const std::vector<FunctionalGroupPermission>& group_permissions, + Permissions& data, + GroupConsent undefined_group_consent) + : fg_(fg) + , group_permissions_(group_permissions) + , data_(data) + , undefined_group_consent_(undefined_group_consent) {} + +bool ProcessFunctionalGroup::operator()(const StringsValueType& group_name) { + const std::string group_name_str = group_name; + FuncGroupConstItr it = fg_.find(group_name_str); + const bool does_require_user_consent = + it->second.user_consent_prompt.is_initialized(); + + if (fg_.end() != it) { + const policy_table::Rpc& rpcs = (*it).second.rpcs; + FillNotificationData filler(data_, + GetGroupState(group_name_str), + undefined_group_consent_, + does_require_user_consent); + std::for_each(rpcs.begin(), rpcs.end(), filler); + } + return true; +} + +GroupConsent ProcessFunctionalGroup::GetGroupState( + const std::string& group_name) { + std::vector<FunctionalGroupPermission>::const_iterator it = + group_permissions_.begin(); + std::vector<FunctionalGroupPermission>::const_iterator it_end = + group_permissions_.end(); + for (; it != it_end; ++it) { + if (group_name == (*it).group_name) { + return (*it).state; + } + } + return kGroupUndefined; +} + +FunctionalGroupInserter::FunctionalGroupInserter( + const policy_table::Strings& preconsented_groups, PermissionsList& list) + : list_(list), preconsented_(preconsented_groups) {} + +void FunctionalGroupInserter::operator()(const StringsValueType& group_name) { + CompareGroupName name(group_name); + if (std::find_if(preconsented_.begin(), preconsented_.end(), name) == + preconsented_.end()) { + list_.push_back(group_name); + } +} + +void FillFunctionalGroupPermissions( + FunctionalGroupIDs& ids, + FunctionalGroupNames& names, + GroupConsent state, + std::vector<FunctionalGroupPermission>& permissions) { + LOG4CXX_INFO(logger_, "FillFunctionalGroupPermissions"); + FunctionalGroupIDs::const_iterator it = ids.begin(); + FunctionalGroupIDs::const_iterator it_end = ids.end(); + for (; it != it_end; ++it) { + FunctionalGroupPermission current_group; + current_group.group_id = *it; + current_group.group_alias = names[*it].first; + current_group.group_name = names[*it].second; + current_group.state = state; + permissions.push_back(current_group); + } +} + +bool IsPredefinedApp(const AppPoliciesValueType& app) { + return app.first == kDefaultId || app.first == kPreDataConsentId || + app.first == kDeviceId; +} + +FunctionalGroupIDs ExcludeSame(const FunctionalGroupIDs& from, + const FunctionalGroupIDs& what) { + LOG4CXX_INFO(logger_, "Exclude same groups"); + FunctionalGroupIDs from_copy(from); + FunctionalGroupIDs what_copy(what); + + std::sort(from_copy.begin(), from_copy.end()); + std::sort(what_copy.begin(), what_copy.end()); + + FunctionalGroupIDs no_same; + std::set_difference(from_copy.begin(), + from_copy.end(), + what_copy.begin(), + what_copy.end(), + std::back_inserter(no_same)); + + no_same.resize(std::distance(no_same.begin(), + std::unique(no_same.begin(), no_same.end()))); + + return no_same; +} + +FunctionalGroupIDs Merge(const FunctionalGroupIDs& first, + const FunctionalGroupIDs& second) { + LOG4CXX_INFO(logger_, "Merge groups"); + FunctionalGroupIDs first_copy(first); + FunctionalGroupIDs second_copy(second); + + std::sort(first_copy.begin(), first_copy.end()); + std::sort(second_copy.begin(), second_copy.end()); + + FunctionalGroupIDs merged; + std::set_union(first_copy.begin(), + first_copy.end(), + second_copy.begin(), + second_copy.end(), + std::back_inserter(merged)); + + merged.resize( + std::distance(merged.begin(), std::unique(merged.begin(), merged.end()))); + + return merged; +} + +FunctionalGroupIDs FindSame(const FunctionalGroupIDs& first, + const FunctionalGroupIDs& second) { + LOG4CXX_INFO(logger_, "Find same groups"); + FunctionalGroupIDs first_copy(first); + FunctionalGroupIDs second_copy(second); + + std::sort(first_copy.begin(), first_copy.end()); + std::sort(second_copy.begin(), second_copy.end()); + + FunctionalGroupIDs same; + std::set_intersection(first_copy.begin(), + first_copy.end(), + second_copy.begin(), + second_copy.end(), + std::back_inserter(same)); + + same.resize( + std::distance(same.begin(), std::unique(same.begin(), same.end()))); + + return same; +} + +bool UnwrapAppPolicies(policy_table::ApplicationPolicies& app_policies) { + policy_table::ApplicationPolicies::iterator it_default = + app_policies.find(kDefaultId); + if (app_policies.end() == it_default) { + LOG4CXX_ERROR(logger_, "No default application policy found in PTU."); + return false; + } + + policy_table::ApplicationPolicies::iterator it = app_policies.begin(); + for (; app_policies.end() != it; ++it) { + // Set default policies for app, if there is record like "123":"default" + if (kDefaultId.compare((*it).second.get_string()) == 0) { + (*it).second = (*it_default).second; + it->second.set_to_string(kDefaultId); + } + } + + return true; +} +} diff --git a/src/components/policy/policy_external/src/policy_manager_impl.cc b/src/components/policy/policy_external/src/policy_manager_impl.cc new file mode 100644 index 0000000000..0a774f6b79 --- /dev/null +++ b/src/components/policy/policy_external/src/policy_manager_impl.cc @@ -0,0 +1,1883 @@ +/* + Copyright (c) 2013, Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ +#include "policy/policy_manager_impl.h" + +#include <algorithm> +#include <set> +#include <queue> +#include <iterator> +#include <limits> +#include <vector> +#include <functional> +#include "json/reader.h" +#include "json/writer.h" +#include "policy/policy_table.h" +#include "policy/pt_representation.h" +#include "policy/policy_helper.h" +#include "utils/file_system.h" +#include "utils/logger.h" +#include "utils/date_time.h" +#include "policy/cache_manager.h" +#include "policy/update_status_manager.h" +#include "config_profile/profile.h" +#include "utils/make_shared.h" + +policy::PolicyManager* CreateManager() { + return new policy::PolicyManagerImpl(); +} +void DeleteManager(policy::PolicyManager* pm) { + delete pm; +} +namespace { + +/** + * @brief Extracts group name from group permission structure + */ +struct GroupNamesAppender + : public std::unary_function<void, + const policy::FunctionalGroupPermission&> { + GroupNamesAppender(policy_table::Strings& names) : names_(names) {} + + void operator()(const policy::FunctionalGroupPermission& value) { + names_.push_back(value.group_name); + } + + private: + policy_table::Strings& names_; +}; + +/** + * @brief Updates permission state of input group permission value in case + * group name is found within allowed or disallowed groups lists considering + * current priorities of consents + * Also collects matched groups names to separate collection for futher + * processing + */ +struct ConsentsUpdater + : public std::unary_function<void, policy::FunctionalGroupPermission&> { + ConsentsUpdater(const policy::GroupsNames& allowed, + const policy::GroupsNames& disallowed, + std::vector<policy::FunctionalGroupPermission>& + out_external_consent_matches, + const policy::ConsentPriorityType prio) + : allowed_(allowed) + , disallowed_(disallowed) + , out_external_consent_matches_(out_external_consent_matches) + , prio_(prio) {} + + void operator()(policy::FunctionalGroupPermission& value) { + if (helpers::in_range(disallowed_, value.group_name)) { + policy::FunctionalGroupPermission external_consent = value; + external_consent.state = policy::kGroupDisallowed; + out_external_consent_matches_.push_back(external_consent); + + if (IsAllowedToChangedUserConsent(value.state)) { + value.state = policy::kGroupDisallowed; + } + return; + } + + if (helpers::in_range(allowed_, value.group_name)) { + policy::FunctionalGroupPermission external_consent = value; + external_consent.state = policy::kGroupAllowed; + out_external_consent_matches_.push_back(external_consent); + + if (IsAllowedToChangedUserConsent(value.state)) { + value.state = policy::kGroupAllowed; + } + } + } + + private: + bool IsAllowedToChangedUserConsent( + policy::GroupConsent current_consent) const { + if (policy::GroupConsent::kGroupUndefined == current_consent) { + return true; + } + + return policy::ConsentPriorityType::kUserConsentPrio != prio_; + } + + const policy::GroupsNames& allowed_; + const policy::GroupsNames& disallowed_; + std::vector<policy::FunctionalGroupPermission>& out_external_consent_matches_; + const policy::ConsentPriorityType prio_; +}; + +/** + * @brief Checks whether ExternalConsent entity status is the same as name of + * group + * container where entity has been found in. In case of match group is added to + * 'disallowed' list, otherwise - to 'allowed' one. + * E.g. if entity has "ON" status and is found in + * 'disallowed_by_external_consent_entities_on' it will be added to + * 'disallowed'. If it has + * been found in 'disallowed_by_external_consent_entities_off' than group is + * added to + * 'allowed' list. + */ +struct GroupChecker + : std::unary_function< + void, + policy::GroupsByExternalConsentStatus::mapped_type::value_type> { + GroupChecker(const policy::EntityStatus entity_status, + policy::GroupsNames& out_allowed, + policy::GroupsNames& out_disallowed) + : entity_status_(entity_status) + , out_allowed_(out_allowed) + , out_disallowed_(out_disallowed) {} + + void operator()( + const policy::GroupsByExternalConsentStatus::mapped_type::value_type + value) { + using namespace policy; + + const std::string group_name = value.first; + + if ((value.second && (kStatusOn == entity_status_)) || + (!value.second && (kStatusOff == entity_status_))) { + out_disallowed_.insert(group_name); + } else { + out_allowed_.insert(group_name); + } + } + + private: + const policy::EntityStatus entity_status_; + policy::GroupsNames& out_allowed_; + policy::GroupsNames& out_disallowed_; +}; + +/** + * @brief Sorts groups for 'allowed' and 'disallowed' by ExternalConsent + * entities statuses. + * Wraps GroupChecker logic. + */ +struct GroupSorter + : std::unary_function< + void, + const policy::GroupsByExternalConsentStatus::value_type&> { + GroupSorter(policy::GroupsNames& out_allowed, + policy::GroupsNames& out_disallowed) + : out_allowed_(out_allowed), out_disallowed_(out_disallowed) {} + + void operator()( + const policy::GroupsByExternalConsentStatus::value_type& value) { + GroupChecker checker(value.first.status_, out_allowed_, out_disallowed_); + std::for_each(value.second.begin(), value.second.end(), checker); + } + + private: + policy::GroupsNames& out_allowed_; + policy::GroupsNames& out_disallowed_; +}; + +} // namespace + +namespace policy { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +PolicyManagerImpl::PolicyManagerImpl() + : PolicyManager() + , listener_(NULL) + , cache_(new CacheManager) + , retry_sequence_timeout_(60) + , retry_sequence_index_(0) + , ignition_check(true) + , retry_sequence_url_(0, 0, "") {} + +PolicyManagerImpl::PolicyManagerImpl(bool in_memory) + : PolicyManager() + , listener_(NULL) + , cache_(new CacheManager(in_memory)) + , retry_sequence_timeout_(60) + , retry_sequence_index_(0) + , ignition_check(true) + , retry_sequence_url_(0, 0, "") + , wrong_ptu_update_received_(false) + , send_on_update_sent_out_(false) + , trigger_ptu_(false) {} + +void PolicyManagerImpl::set_listener(PolicyListener* listener) { + listener_ = listener; + update_status_manager_.set_listener(listener); +} + +utils::SharedPtr<policy_table::Table> PolicyManagerImpl::Parse( + const BinaryMessage& pt_content) { + std::string json(pt_content.begin(), pt_content.end()); + Json::Value value; + Json::Reader reader; + if (reader.parse(json.c_str(), value)) { + return new policy_table::Table(&value); + } else { + return utils::SharedPtr<policy_table::Table>(); + } +} + +void PolicyManagerImpl::CheckTriggers() { + LOG4CXX_AUTO_TRACE(logger_); + const bool exceed_ignition_cycles = ExceededIgnitionCycles(); + const bool exceed_days = ExceededDays(); + + LOG4CXX_DEBUG( + logger_, + "\nDays exceeded: " << std::boolalpha << exceed_days + << "\nIgnition cycles exceeded: " << std::boolalpha + << exceed_ignition_cycles); + + if (exceed_ignition_cycles || exceed_days) { + update_status_manager_.ScheduleUpdate(); + } +} + +std::string PolicyManagerImpl::GetLockScreenIconUrl() const { + return cache_->GetLockScreenIconUrl(); +} + +bool PolicyManagerImpl::LoadPT(const std::string& file, + const BinaryMessage& pt_content) { + LOG4CXX_INFO(logger_, "LoadPT of size " << pt_content.size()); + + // Parse message into table struct + utils::SharedPtr<policy_table::Table> pt_update = Parse(pt_content); + if (!pt_update) { + LOG4CXX_WARN(logger_, "Parsed table pointer is NULL."); + update_status_manager_.OnWrongUpdateReceived(); + return false; + } + + file_system::DeleteFile(file); + + if (!IsPTValid(pt_update, policy_table::PT_UPDATE)) { + wrong_ptu_update_received_ = true; + update_status_manager_.OnWrongUpdateReceived(); + return false; + } + + update_status_manager_.OnValidUpdateReceived(); + cache_->SaveUpdateRequired(false); + + { + sync_primitives::AutoLock lock(apps_registration_lock_); + + // Get current DB data, since it could be updated during awaiting of PTU + utils::SharedPtr<policy_table::Table> policy_table_snapshot = + cache_->GenerateSnapshot(); + if (!policy_table_snapshot) { + LOG4CXX_ERROR(logger_, "Failed to create snapshot of policy table"); + return false; + } + + // Checking of difference between PTU and current policy state + // Must to be done before PTU applying since it is possible, that functional + // groups, which had been present before are absent in PTU and will be + // removed after update. So in case of revoked groups system has to know + // names and ids of revoked groups before they will be removed. + CheckAppPolicyResults results = + CheckPermissionsChanges(pt_update, policy_table_snapshot); + + // Replace current data with updated + if (!cache_->ApplyUpdate(*pt_update)) { + LOG4CXX_WARN(logger_, "Unsuccessful save of updated policy table."); + return false; + } + + ExternalConsentStatus status = cache_->GetExternalConsentStatus(); + GroupsByExternalConsentStatus groups_by_status = + cache_->GetGroupsWithSameEntities(status); + + ProcessExternalConsentStatusUpdate( + groups_by_status, ConsentProcessingPolicy::kExternalConsentBased); + + ProcessAppPolicyCheckResults( + results, pt_update->policy_table.app_policies_section.apps); + + listener_->OnCertificateUpdated( + *(pt_update->policy_table.module_config.certificate)); + + std::map<std::string, StringArray> app_hmi_types; + cache_->GetHMIAppTypeAfterUpdate(app_hmi_types); + if (!app_hmi_types.empty()) { + LOG4CXX_INFO(logger_, "app_hmi_types is full calling OnUpdateHMIAppType"); + listener_->OnUpdateHMIAppType(app_hmi_types); + } else { + LOG4CXX_INFO(logger_, "app_hmi_types empty"); + } + } + + // If there was a user request for policy table update, it should be started + // right after current update is finished + if (update_status_manager_.IsUpdateRequired()) { + StartPTExchange(); + return true; + } + + RefreshRetrySequence(); + return true; +} + +CheckAppPolicyResults PolicyManagerImpl::CheckPermissionsChanges( + const utils::SharedPtr<policy_table::Table> pt_update, + const utils::SharedPtr<policy_table::Table> snapshot) { + LOG4CXX_INFO(logger_, "Checking incoming permissions."); + + // Replace predefined policies with its actual setting, e.g. "123":"default" + // to actual values of default section + UnwrapAppPolicies(pt_update->policy_table.app_policies_section.apps); + + CheckAppPolicyResults out_results; + std::for_each(pt_update->policy_table.app_policies_section.apps.begin(), + pt_update->policy_table.app_policies_section.apps.end(), + CheckAppPolicy(this, pt_update, snapshot, out_results)); + + return out_results; +} + +void PolicyManagerImpl::ProcessAppPolicyCheckResults( + const CheckAppPolicyResults& results, + const policy_table::ApplicationPolicies& app_policies) { + CheckAppPolicyResults::const_iterator it_results = results.begin(); + + for (; results.end() != it_results; ++it_results) { + const policy_table::ApplicationPolicies::const_iterator app_policy = + app_policies.find(it_results->first); + + if (app_policies.end() == app_policy) { + continue; + } + + if (IsPredefinedApp(*app_policy)) { + continue; + } + + switch (it_results->second) { + case RESULT_NO_CHANGES: + continue; + case RESULT_APP_REVOKED: + NotifySystem(*app_policy); + continue; + case RESULT_NICKNAME_MISMATCH: + NotifySystem(*app_policy); + continue; + case RESULT_CONSENT_NEEDED: + case RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED: { + // Post-check after ExternalConsent consent changes + const std::string policy_app_id = app_policy->first; + if (!IsConsentNeeded(policy_app_id)) { + sync_primitives::AutoLock lock(app_permissions_diff_lock_); + + PendingPermissions::iterator app_id_diff = + app_permissions_diff_.find(policy_app_id); + + if (app_permissions_diff_.end() != app_id_diff) { + app_id_diff->second.appPermissionsConsentNeeded = false; + } + } + } break; + case RESULT_CONSENT_NOT_REQIURED: + case RESULT_PERMISSIONS_REVOKED: + case RESULT_REQUEST_TYPE_CHANGED: + break; + default: + continue; + } + NotifySystem(*app_policy); + SendPermissionsToApp(*app_policy); + } +} + +void PolicyManagerImpl::PrepareNotificationData( + const policy_table::FunctionalGroupings& groups, + const policy_table::Strings& group_names, + const std::vector<FunctionalGroupPermission>& group_permission, + Permissions& notification_data) { + LOG4CXX_INFO(logger_, "Preparing data for notification."); + ProcessFunctionalGroup processor(groups, group_permission, notification_data); + std::for_each(group_names.begin(), group_names.end(), processor); +} + +std::string PolicyManagerImpl::GetUpdateUrl(int service_type) { + LOG4CXX_AUTO_TRACE(logger_); + EndpointUrls urls; + GetUpdateUrls(service_type, urls); + + std::string url; + if (!urls.empty()) { + static uint32_t index = 0; + + if (index >= urls.size()) { + index = 0; + } + url = urls[index].url.empty() ? "" : urls[index].url[0]; + + ++index; + } else { + LOG4CXX_ERROR(logger_, "The endpoint entry is empty"); + } + return url; +} + +void PolicyManagerImpl::GetUpdateUrls(const std::string& service_type, + EndpointUrls& out_end_points) { + LOG4CXX_AUTO_TRACE(logger_); + cache_->GetUpdateUrls(service_type, out_end_points); +} +void PolicyManagerImpl::GetUpdateUrls(const uint32_t service_type, + EndpointUrls& out_end_points) { + LOG4CXX_AUTO_TRACE(logger_); + cache_->GetUpdateUrls(service_type, out_end_points); +} + +void PolicyManagerImpl::RequestPTUpdate() { + LOG4CXX_AUTO_TRACE(logger_); + utils::SharedPtr<policy_table::Table> policy_table_snapshot = + cache_->GenerateSnapshot(); + if (!policy_table_snapshot) { + LOG4CXX_ERROR(logger_, "Failed to create snapshot of policy table"); + return; + } + + if (IsPTValid(policy_table_snapshot, policy_table::PT_SNAPSHOT)) { + Json::Value value = policy_table_snapshot->ToJsonValue(); + Json::FastWriter writer; + std::string message_string = writer.write(value); + + LOG4CXX_DEBUG(logger_, "Snapshot contents is : " << message_string); + + BinaryMessage update(message_string.begin(), message_string.end()); + + listener_->OnSnapshotCreated( + update, RetrySequenceDelaysSeconds(), TimeoutExchangeMSec()); + } else { + LOG4CXX_ERROR(logger_, "Invalid Policy table snapshot - PTUpdate failed"); + } +} + +void PolicyManagerImpl::StartPTExchange() { + LOG4CXX_AUTO_TRACE(logger_); + + if (ignition_check) { + CheckTriggers(); + ignition_check = false; + } + + if (update_status_manager_.IsAppsSearchInProgress() && + update_status_manager_.IsUpdateRequired()) { + LOG4CXX_INFO(logger_, + "Starting exchange skipped, since applications " + "search is in progress."); + return; + } + + if (update_status_manager_.IsUpdatePending()) { + if (trigger_ptu_) { + update_status_manager_.ScheduleUpdate(); + } + LOG4CXX_INFO(logger_, + "Starting exchange skipped, since another exchange " + "is in progress."); + return; + } + LOG4CXX_INFO(logger_, "Policy want to call RequestPTUpdate"); + if (listener_ && listener_->CanUpdate()) { + LOG4CXX_INFO(logger_, "Listener CanUpdate"); + if (update_status_manager_.IsUpdateRequired()) { + LOG4CXX_INFO(logger_, "IsUpdateRequired"); + RequestPTUpdate(); + } + } +} + +void PolicyManagerImpl::OnAppsSearchStarted() { + LOG4CXX_AUTO_TRACE(logger_); + update_status_manager_.OnAppsSearchStarted(); +} + +void PolicyManagerImpl::OnAppsSearchCompleted(const bool trigger_ptu) { + LOG4CXX_AUTO_TRACE(logger_); + update_status_manager_.OnAppsSearchCompleted(); + + trigger_ptu_ = trigger_ptu; + + if (update_status_manager_.IsUpdateRequired()) { + StartPTExchange(); + } +} + +const std::vector<std::string> PolicyManagerImpl::GetAppRequestTypes( + const std::string policy_app_id) const { + std::vector<std::string> request_types; + if (kDeviceDisallowed == + cache_->GetDeviceConsent(GetCurrentDeviceId(policy_app_id))) { + cache_->GetAppRequestTypes(kPreDataConsentId, request_types); + } else { + cache_->GetAppRequestTypes(policy_app_id, request_types); + } + return request_types; +} + +const VehicleInfo PolicyManagerImpl::GetVehicleInfo() const { + return cache_->GetVehicleInfo(); +} + +void PolicyManagerImpl::CheckPermissions(const PTString& app_id, + const PTString& hmi_level, + const PTString& rpc, + const RPCParams& rpc_params, + CheckPermissionResult& result) { + LOG4CXX_INFO(logger_, + "CheckPermissions for " << app_id << " and rpc " << rpc + << " for " << hmi_level << " level."); + + const std::string device_id = GetCurrentDeviceId(app_id); + + Permissions rpc_permissions; + + // Check, if there are calculated permission present in cache + if (!cache_->IsPermissionsCalculated(device_id, app_id, rpc_permissions)) { + LOG4CXX_DEBUG(logger_, + "IsPermissionsCalculated for device: " + << device_id << " and app: " << app_id + << " returns false"); + // Get actual application group permission according to user consents + std::vector<FunctionalGroupPermission> app_group_permissions; + GetPermissionsForApp(device_id, app_id, app_group_permissions); + + // Fill struct with known groups RPCs + policy_table::FunctionalGroupings functional_groupings; + cache_->GetFunctionalGroupings(functional_groupings); + + policy_table::Strings app_groups = GetGroupsNames(app_group_permissions); + + // Undefined groups (without user consent) disallowed by default, since + // OnPermissionsChange notification has no "undefined" section + // For RPC permission checking undefinded group will be treated as separate + // type + ProcessFunctionalGroup processor(functional_groupings, + app_group_permissions, + rpc_permissions, + GroupConsent::kGroupUndefined); + std::for_each(app_groups.begin(), app_groups.end(), processor); + + cache_->AddCalculatedPermissions(device_id, app_id, rpc_permissions); + } else { + LOG4CXX_DEBUG(logger_, + "IsPermissionsCalculated for device: " + << device_id << " and app: " << app_id + << " returns true"); + } + + const bool known_rpc = rpc_permissions.end() != rpc_permissions.find(rpc); + LOG4CXX_INFO(logger_, "Is known rpc " << known_rpc); + if (!known_rpc) { + // RPC not found in list == disallowed by backend + result.hmi_level_permitted = kRpcDisallowed; + return; + } + + // Check HMI level + if (rpc_permissions[rpc].hmi_permissions[kAllowedKey].end() != + rpc_permissions[rpc].hmi_permissions[kAllowedKey].find(hmi_level)) { + // RPC found in allowed == allowed by backend and user + result.hmi_level_permitted = kRpcAllowed; + } else if (rpc_permissions[rpc].hmi_permissions[kUndefinedKey].end() != + rpc_permissions[rpc].hmi_permissions[kUndefinedKey].find( + hmi_level)) { + // RPC found in undefined == allowed by backend, but not consented yet by + // user + result.hmi_level_permitted = kRpcDisallowed; + } else if (rpc_permissions[rpc].hmi_permissions[kUserDisallowedKey].end() != + rpc_permissions[rpc].hmi_permissions[kUserDisallowedKey].find( + hmi_level)) { + // RPC found in allowed == allowed by backend, but disallowed by user + result.hmi_level_permitted = kRpcUserDisallowed; + } else { + LOG4CXX_DEBUG(logger_, + "HMI level " << hmi_level << " wasn't found " + << " for rpc " << rpc << " and appID " + << app_id); + return; + } + + if (kRpcAllowed != result.hmi_level_permitted) { + LOG4CXX_DEBUG(logger_, "RPC is not allowed. Stop parameters processing."); + result.list_of_allowed_params = + rpc_permissions[rpc].parameter_permissions[kAllowedKey]; + + result.list_of_disallowed_params = + rpc_permissions[rpc].parameter_permissions[kUserDisallowedKey]; + + result.list_of_undefined_params = + rpc_permissions[rpc].parameter_permissions[kUndefinedKey]; + return; + } + + // Considered that items disallowed by user take priority over system (policy) + // permissions, so that flag is processed first + if (rpc_permissions[rpc] + .parameter_permissions.any_parameter_disallowed_by_user) { + LOG4CXX_DEBUG(logger_, "All parameters are disallowed by user."); + result.list_of_disallowed_params = rpc_params; + result.hmi_level_permitted = kRpcUserDisallowed; + return; + } + + if (rpc_permissions[rpc] + .parameter_permissions.any_parameter_disallowed_by_policy) { + LOG4CXX_DEBUG(logger_, "All parameters are disallowed by policy."); + result.list_of_undefined_params = rpc_params; + result.hmi_level_permitted = kRpcDisallowed; + return; + } + + if (rpc_permissions[rpc].parameter_permissions.any_parameter_allowed) { + LOG4CXX_DEBUG(logger_, "All parameters are allowed."); + result.list_of_allowed_params = rpc_params; + return; + } + + result.list_of_allowed_params = + rpc_permissions[rpc].parameter_permissions[kAllowedKey]; + + result.list_of_disallowed_params = + rpc_permissions[rpc].parameter_permissions[kUserDisallowedKey]; + + result.list_of_undefined_params = + rpc_permissions[rpc].parameter_permissions[kUndefinedKey]; + + // In case of some parameters of RPC are missing in current policy table + // they will be considered as disallowed by policy itself, not by user. + // Undefined parameters contain parameters present in policy table, but which + // have not been allowed or disallowed explicitly by user, so missing params + // are being added to undefined. + RPCParams::const_iterator parameter = rpc_params.begin(); + RPCParams::const_iterator end = rpc_params.end(); + for (; end != parameter; ++parameter) { + if (!result.HasParameter(*parameter)) { + LOG4CXX_DEBUG(logger_, + "Parameter " << *parameter << " is unknown." + " Adding to undefined list."); + result.list_of_undefined_params.insert(*parameter); + } + } + + if (result.DisallowedInclude(rpc_params)) { + LOG4CXX_DEBUG(logger_, "All parameters are disallowed."); + result.hmi_level_permitted = kRpcUserDisallowed; + } else if (!result.IsAnyAllowed(rpc_params)) { + LOG4CXX_DEBUG(logger_, "There are no parameters allowed."); + result.hmi_level_permitted = kRpcDisallowed; + } + + if (cache_->IsApplicationRevoked(app_id)) { + // SDL must be able to notify mobile side with its status after app has + // been revoked by backend + if ("OnHMIStatus" == rpc && "NONE" == hmi_level) { + result.hmi_level_permitted = kRpcAllowed; + } else { + result.hmi_level_permitted = kRpcDisallowed; + } + return; + } +} + +bool PolicyManagerImpl::ResetUserConsent() { + bool result = true; + result = cache_->ResetUserConsent(); + + return result; +} + +policy_table::Strings PolicyManagerImpl::GetGroupsNames( + const std::vector<FunctionalGroupPermission>& app_group_permissions) const { + policy_table::Strings app_groups; + GroupNamesAppender appender(app_groups); + std::for_each( + app_group_permissions.begin(), app_group_permissions.end(), appender); + + return app_groups; +} + +void PolicyManagerImpl::SendNotificationOnPermissionsUpdated( + const std::string& application_id) { + LOG4CXX_AUTO_TRACE(logger_); + const std::string device_id = GetCurrentDeviceId(application_id); + if (device_id.empty()) { + LOG4CXX_WARN(logger_, + "Couldn't find device info for application id " + "'" << application_id << "'"); + return; + } + + std::vector<FunctionalGroupPermission> app_group_permissions; + GetPermissionsForApp(device_id, application_id, app_group_permissions); + + policy_table::FunctionalGroupings functional_groupings; + cache_->GetFunctionalGroupings(functional_groupings); + + policy_table::Strings app_groups = GetGroupsNames(app_group_permissions); + + Permissions notification_data; + PrepareNotificationData(functional_groupings, + app_groups, + app_group_permissions, + notification_data); + + LOG4CXX_INFO(logger_, + "Send notification for application_id:" << application_id); + + std::string default_hmi; + GetDefaultHmi(application_id, &default_hmi); + + listener()->OnPermissionsUpdated( + application_id, notification_data, default_hmi); +} + +bool PolicyManagerImpl::CleanupUnpairedDevices() { + LOG4CXX_AUTO_TRACE(logger_); + return cache_->CleanupUnpairedDevices(); +} + +DeviceConsent PolicyManagerImpl::GetUserConsentForDevice( + const std::string& device_id) const { + LOG4CXX_AUTO_TRACE(logger_); + return cache_->GetDeviceConsent(device_id); +} + +void PolicyManagerImpl::SetUserConsentForDevice(const std::string& device_id, + const bool is_allowed) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Device :" << device_id); + cache_->SetDeviceConsent(device_id, is_allowed); + if (listener_) { + listener_->OnDeviceConsentChanged(device_id, is_allowed); + } else { + LOG4CXX_WARN(logger_, + "Event listener is not initialized. " + "Can't call OnDeviceConsentChanged"); + } + if (is_allowed) { + update_status_manager_.OnDeviceConsented(); + } + StartPTExchange(); +} + +bool PolicyManagerImpl::ReactOnUserDevConsentForApp( + const std::string& app_id, const bool is_device_allowed) { + std::vector<std::string> current_request_types = GetAppRequestTypes(app_id); + std::string current_priority, new_priority; + GetPriority(app_id, ¤t_priority); + + bool result = cache_->ReactOnUserDevConsentForApp(app_id, is_device_allowed); + + std::vector<std::string> new_request_types = GetAppRequestTypes(app_id); + GetPriority(app_id, &new_priority); + std::sort(current_request_types.begin(), current_request_types.end()); + std::sort(new_request_types.begin(), new_request_types.end()); + + std::vector<std::string> diff; + std::set_symmetric_difference(current_request_types.begin(), + current_request_types.end(), + new_request_types.begin(), + new_request_types.end(), + std::back_inserter(diff)); + + AppPermissions permissions(app_id); + + if (!diff.empty()) { + permissions.requestType = new_request_types; + permissions.requestTypeChanged = true; + } + + if ((!current_priority.empty()) && (!new_priority.empty()) && + (current_priority != new_priority)) { + permissions.priority = new_priority; + } + + if (permissions.requestTypeChanged || (!permissions.priority.empty())) { + listener_->SendOnAppPermissionsChanged(permissions, app_id); + } + return result; +} + +bool PolicyManagerImpl::GetInitialAppData(const std::string& application_id, + StringArray* nicknames, + StringArray* app_hmi_types) { + LOG4CXX_AUTO_TRACE(logger_); + const bool result = nicknames && app_hmi_types; + if (result) { + cache_->GetInitialAppData(application_id, *nicknames, *app_hmi_types); + } + return result; +} + +void PolicyManagerImpl::AddDevice(const std::string& device_id, + const std::string& connection_type) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Device: " << device_id); + if (!cache_->AddDevice(device_id, connection_type)) { + LOG4CXX_WARN(logger_, "Can't add device."); + } +} + +void PolicyManagerImpl::SetDeviceInfo(const std::string& device_id, + const DeviceInfo& device_info) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Device :" << device_id); + if (!cache_->SetDeviceData(device_id, + device_info.hardware, + device_info.firmware_rev, + device_info.os, + device_info.os_ver, + device_info.carrier, + device_info.max_number_rfcom_ports, + device_info.connection_type)) { + LOG4CXX_WARN(logger_, "Can't set device data."); + } +} + +PermissionConsent PolicyManagerImpl::EnsureCorrectPermissionConsent( + const PermissionConsent& permissions_to_check) { + std::vector<FunctionalGroupPermission> current_user_consents; + GetUserConsentForApp(permissions_to_check.device_id, + permissions_to_check.policy_app_id, + current_user_consents); + + PermissionConsent permissions_to_set; + permissions_to_set.device_id = permissions_to_check.device_id; + permissions_to_set.policy_app_id = permissions_to_check.policy_app_id; + permissions_to_set.consent_source = permissions_to_check.consent_source; + + std::vector<FunctionalGroupPermission>::const_iterator it = + permissions_to_check.group_permissions.begin(); + std::vector<FunctionalGroupPermission>::const_iterator it_end = + permissions_to_check.group_permissions.end(); + + for (; it != it_end; ++it) { + std::vector<FunctionalGroupPermission>::const_iterator it_curr = + current_user_consents.begin(); + std::vector<FunctionalGroupPermission>::const_iterator it_curr_end = + current_user_consents.end(); + + for (; it_curr != it_curr_end; ++it_curr) { + if (it->group_alias == it_curr->group_alias && + it->group_id == it_curr->group_id) { + permissions_to_set.group_permissions.push_back(*it); + } + } + } + + return permissions_to_set; +} + +void PolicyManagerImpl::CheckPendingPermissionsChanges( + const std::string& policy_app_id, + const std::vector<FunctionalGroupPermission>& current_permissions) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(app_permissions_diff_lock_); + PendingPermissions::iterator it_pending = + app_permissions_diff_.find(policy_app_id); + if (app_permissions_diff_.end() == it_pending) { + LOG4CXX_WARN( + logger_, + "No pending permissions had been found for appID: " << policy_app_id); + return; + } + + LOG4CXX_DEBUG( + logger_, + "Pending permissions had been found for appID: " << policy_app_id); + + // Change appPermissionsConsentNeeded depending on unconsented groups + // presence + std::vector<policy::FunctionalGroupPermission>::const_iterator it_groups = + current_permissions.begin(); + std::vector<policy::FunctionalGroupPermission>::const_iterator it_end_groups = + current_permissions.end(); + + for (; it_groups != it_end_groups; ++it_groups) { + if (policy::kGroupUndefined == it_groups->state) { + LOG4CXX_DEBUG( + logger_, + "Unconsented groups still present for appID: " << policy_app_id); + it_pending->second.appPermissionsConsentNeeded = true; + return; + } + } + + LOG4CXX_DEBUG( + logger_, + "Unconsented groups not present anymore for appID: " << policy_app_id); + it_pending->second.appPermissionsConsentNeeded = false; + return; +} + +void PolicyManagerImpl::NotifyPermissionsChanges( + const std::string& policy_app_id, + const std::vector<FunctionalGroupPermission>& app_group_permissions) { + // Get current functional groups from DB with RPC permissions + policy_table::FunctionalGroupings functional_groups; + cache_->GetFunctionalGroupings(functional_groups); + + // Get list of groups assigned to application + policy_table::Strings app_groups = GetGroupsNames(app_group_permissions); + + // Fill notification data according to group permissions + Permissions notification_data; + PrepareNotificationData( + functional_groups, app_groups, app_group_permissions, notification_data); + + listener()->OnPermissionsUpdated(policy_app_id, notification_data); +} + +void PolicyManagerImpl::SetUserConsentForApp( + const PermissionConsent& permissions, const NotificationMode mode) { + LOG4CXX_AUTO_TRACE(logger_); + + if (permissions.group_permissions.empty()) { + LOG4CXX_DEBUG(logger_, "Permissions list is empty, skipping update."); + return; + } + + cache_->ResetCalculatedPermissions(); + PermissionConsent verified_permissions = + EnsureCorrectPermissionConsent(permissions); + + bool app_permissions_changed = false; + if (!cache_->SetUserPermissionsForApp(verified_permissions, + &app_permissions_changed)) { + LOG4CXX_WARN(logger_, "Can't set user permissions for application."); + return; + } + + if (kSilentMode == mode) { + LOG4CXX_WARN(logger_, + "Silent mode is enabled. Application won't be informed."); + return; + } + + if (!app_permissions_changed) { + LOG4CXX_WARN(logger_, + "Application already has same consents. " + "Notificaton won't be sent."); + return; + } + + std::vector<FunctionalGroupPermission> updated_app_group_permissons; + GetPermissionsForApp(verified_permissions.device_id, + verified_permissions.policy_app_id, + updated_app_group_permissons); + + CheckPendingPermissionsChanges(verified_permissions.policy_app_id, + updated_app_group_permissons); + + NotifyPermissionsChanges(verified_permissions.policy_app_id, + updated_app_group_permissons); +} + +bool PolicyManagerImpl::GetDefaultHmi(const std::string& policy_app_id, + std::string* default_hmi) const { + LOG4CXX_AUTO_TRACE(logger_); + const std::string device_id = GetCurrentDeviceId(policy_app_id); + DeviceConsent device_consent = GetUserConsentForDevice(device_id); + const std::string app_id = policy::kDeviceAllowed != device_consent + ? kPreDataConsentId + : policy_app_id; + return cache_->GetDefaultHMI(app_id, *default_hmi); +} + +bool PolicyManagerImpl::GetPriority(const std::string& policy_app_id, + std::string* priority) const { + LOG4CXX_AUTO_TRACE(logger_); + if (!priority) { + LOG4CXX_WARN(logger_, "Input priority parameter is null."); + return false; + } + + return cache_->GetPriority(policy_app_id, *priority); +} + +std::vector<UserFriendlyMessage> PolicyManagerImpl::GetUserFriendlyMessages( + const std::vector<std::string>& message_code, + const std::string& language, + const std::string& active_hmi_language) { + return cache_->GetUserFriendlyMsg( + message_code, language, active_hmi_language); +} + +void PolicyManagerImpl::GetUserConsentForApp( + const std::string& device_id, + const std::string& policy_app_id, + std::vector<FunctionalGroupPermission>& permissions) { + LOG4CXX_AUTO_TRACE(logger_); + + FunctionalIdType group_types; + if (!cache_->GetPermissionsForApp(device_id, policy_app_id, group_types)) { + LOG4CXX_WARN(logger_, + "Can't get user permissions for app " << policy_app_id); + return; + } + + // Functional groups w/o alias ("user_consent_prompt") considered as + // automatically allowed and it could not be changed by user + FunctionalGroupNames group_names; + if (!cache_->GetFunctionalGroupNames(group_names)) { + LOG4CXX_WARN(logger_, "Can't get functional group names"); + return; + } + + FunctionalGroupNames::const_iterator it = group_names.begin(); + FunctionalGroupNames::const_iterator it_end = group_names.end(); + FunctionalGroupIDs auto_allowed_groups; + for (; it != it_end; ++it) { + if (it->second.first.empty()) { + auto_allowed_groups.push_back(it->first); + } + } + + FunctionalGroupIDs all_groups = group_types[kTypeGeneral]; + FunctionalGroupIDs preconsented_groups = group_types[kTypePreconsented]; + FunctionalGroupIDs consent_allowed_groups = group_types[kTypeAllowed]; + FunctionalGroupIDs consent_disallowed_groups = group_types[kTypeDisallowed]; + FunctionalGroupIDs default_groups = group_types[kTypeDefault]; + FunctionalGroupIDs predataconsented_groups = + group_types[kTypePreDataConsented]; + FunctionalGroupIDs device_groups = group_types[kTypeDevice]; + + // Sorting groups by consent + FunctionalGroupIDs preconsented_wo_auto = + ExcludeSame(preconsented_groups, auto_allowed_groups); + + FunctionalGroupIDs preconsented_wo_disallowed_auto = + ExcludeSame(preconsented_wo_auto, consent_disallowed_groups); + + FunctionalGroupIDs allowed_groups = + Merge(consent_allowed_groups, preconsented_wo_disallowed_auto); + + FunctionalGroupIDs merged_stage_1 = + Merge(default_groups, predataconsented_groups); + + FunctionalGroupIDs merged_stage_2 = Merge(merged_stage_1, device_groups); + + FunctionalGroupIDs merged_stage_3 = + Merge(merged_stage_2, auto_allowed_groups); + + FunctionalGroupIDs excluded_stage_1 = ExcludeSame(all_groups, merged_stage_3); + + FunctionalGroupIDs excluded_stage_2 = + ExcludeSame(excluded_stage_1, consent_disallowed_groups); + + FunctionalGroupIDs undefined_consent = + ExcludeSame(excluded_stage_2, allowed_groups); + + // Fill result + FillFunctionalGroupPermissions( + undefined_consent, group_names, kGroupUndefined, permissions); + FillFunctionalGroupPermissions( + allowed_groups, group_names, kGroupAllowed, permissions); + FillFunctionalGroupPermissions( + consent_disallowed_groups, group_names, kGroupDisallowed, permissions); +} + +void PolicyManagerImpl::GetPermissionsForApp( + const std::string& device_id, + const std::string& policy_app_id, + std::vector<FunctionalGroupPermission>& permissions) { + LOG4CXX_AUTO_TRACE(logger_); + std::string app_id_to_check = policy_app_id; + + if (!cache_->IsApplicationRepresented(policy_app_id)) { + LOG4CXX_WARN(logger_, + "Application with id " << policy_app_id + << " is not found within known apps."); + return; + } + + bool allowed_by_default = false; + if (cache_->IsDefaultPolicy(policy_app_id)) { + app_id_to_check = kDefaultId; + allowed_by_default = true; + } else if (cache_->IsPredataPolicy(policy_app_id) || + policy::kDeviceDisallowed == GetUserConsentForDevice(device_id)) { + app_id_to_check = kPreDataConsentId; + allowed_by_default = true; + } + + FunctionalIdType group_types; + if (!cache_->GetPermissionsForApp(device_id, app_id_to_check, group_types)) { + LOG4CXX_WARN(logger_, + "Can't get user permissions for app " << policy_app_id); + return; + } + + // Functional groups w/o alias ("user_consent_prompt") considered as + // automatically allowed and it could not be changed by user + FunctionalGroupNames group_names; + if (!cache_->GetFunctionalGroupNames(group_names)) { + LOG4CXX_WARN(logger_, "Can't get functional group names"); + return; + } + + // The "default" and "pre_DataConsent" are auto-allowed groups + // So, check if application in the one of these mode. + if (allowed_by_default) { + LOG4CXX_INFO(logger_, "Get auto allowed groups"); + GroupType type = + (kDefaultId == app_id_to_check ? kTypeDefault : kTypePreDataConsented); + + FillFunctionalGroupPermissions( + group_types[type], group_names, kGroupAllowed, permissions); + } else { + // The code bellow allows to process application which + // has specific permissions(not default and pre_DataConsent). + + // All groups for specific application + FunctionalGroupIDs all_groups = group_types[kTypeGeneral]; + + // Groups assigned by the user for specific application + FunctionalGroupIDs allowed_groups = group_types[kTypeAllowed]; + + // Groups disallowed by the user for specific application + FunctionalGroupIDs common_disallowed = group_types[kTypeDisallowed]; + + // Groups that allowed by default but can be changed by the user + FunctionalGroupIDs preconsented_groups = group_types[kTypePreconsented]; + + // Groups which has user consent promt but there is no any consnets now. + FunctionalGroupIDs unconsented_groups = group_types[kTypeUnconsented]; + + // Pull common groups from allowed and preconsented parts. + FunctionalGroupIDs allowed_preconsented = + Merge(allowed_groups, preconsented_groups); + + // Get all groups that we suppose are allowed. + FunctionalGroupIDs all_allowed = Merge(allowed_preconsented, all_groups); + + // In case when same groups exists in disallowed and allowed tables, + // disallowed one have priority over allowed. So we have to remove + // all disallowed groups from allowed table. + FunctionalGroupIDs common_allowed = + ExcludeSame(all_allowed, common_disallowed); + FunctionalGroupIDs consent_disallowed = + ExcludeSame(unconsented_groups, preconsented_groups); + + // Disallowed groups are contain all directly disallowed, + // plus unconsented minus preconsented. + FunctionalGroupIDs all_disallowed = + Merge(common_disallowed, consent_disallowed); + + // Fill result + FillFunctionalGroupPermissions( + consent_disallowed, group_names, kGroupUndefined, permissions); + FillFunctionalGroupPermissions( + common_allowed, group_names, kGroupAllowed, permissions); + FillFunctionalGroupPermissions( + all_disallowed, group_names, kGroupDisallowed, permissions); + } + return; +} + +std::string& PolicyManagerImpl::GetCurrentDeviceId( + const std::string& policy_app_id) const { + LOG4CXX_INFO(logger_, "GetDeviceInfo"); + last_device_id_ = listener()->OnCurrentDeviceIdUpdateRequired(policy_app_id); + return last_device_id_; +} + +void PolicyManagerImpl::SetSystemLanguage(const std::string& language) { + cache_->SetSystemLanguage(language); +} + +void PolicyManagerImpl::SetSystemInfo(const std::string& ccpu_version, + const std::string& wers_country_code, + const std::string& language) { + LOG4CXX_AUTO_TRACE(logger_); + cache_->SetMetaInfo(ccpu_version, wers_country_code, language); +} + +void PolicyManagerImpl::OnSystemReady() { + // Update policy table for the first time with system information + if (!cache_->IsMetaInfoPresent()) { + listener()->OnSystemInfoUpdateRequired(); + } +} + +uint32_t PolicyManagerImpl::GetNotificationsNumber( + const std::string& priority) const { + LOG4CXX_AUTO_TRACE(logger_); + return cache_->GetNotificationsNumber(priority); +} + +bool PolicyManagerImpl::ExceededIgnitionCycles() { + return 0 == cache_->IgnitionCyclesBeforeExchange(); +} + +bool PolicyManagerImpl::IsPTValid( + utils::SharedPtr<policy_table::Table> policy_table, + policy_table::PolicyTableType type) const { + policy_table->SetPolicyTableType(type); + if (!policy_table->is_valid()) { + LOG4CXX_ERROR(logger_, "Policy table is not valid."); + rpc::ValidationReport report("policy_table"); + policy_table->ReportErrors(&report); + LOG4CXX_DEBUG(logger_, "Errors: " << rpc::PrettyFormat(report)); + return false; + } + return true; +} + +const PolicySettings& PolicyManagerImpl::get_settings() const { + DCHECK(settings_); + return *settings_; +} + +void PolicyManagerImpl::UpdateAppConsentWithExternalConsent( + const std::string& device_id, + const std::string& application_id, + const GroupsNames& allowed_groups, + const GroupsNames& disallowed_groups, + const ConsentProcessingPolicy processing_policy) { + LOG4CXX_AUTO_TRACE(logger_); + + if (allowed_groups.empty() && disallowed_groups.empty()) { + LOG4CXX_DEBUG(logger_, + "Allowed and disallowed groups are empty, skipping update by " + "external user consent."); + return; + } + + std::vector<FunctionalGroupPermission> current_permissions; + GetUserConsentForApp(device_id, application_id, current_permissions); + + ConsentPriorityType prio = ConsentPriorityType::kExternalConsentPrio; + if (ConsentProcessingPolicy::kTimestampBased == processing_policy) { + prio = cache_->GetConsentsPriority(device_id, application_id); + } + + std::vector<FunctionalGroupPermission> external_consent_groups_matches; + ConsentsUpdater updater( + allowed_groups, disallowed_groups, external_consent_groups_matches, prio); + std::for_each( + current_permissions.begin(), current_permissions.end(), updater); + + const std::string source = "GUI"; + + PermissionConsent updated_user_permissions; + updated_user_permissions.group_permissions = current_permissions; + updated_user_permissions.device_id = device_id; + updated_user_permissions.policy_app_id = application_id; + updated_user_permissions.consent_source = source; + + // Need to check to which app to send notification since maybe app registered + // from different device + SetUserConsentForApp(updated_user_permissions, + PolicyManager::kNotifyApplicationMode); + + PermissionConsent updated_external_consent_permissions; + updated_external_consent_permissions.group_permissions = + external_consent_groups_matches; + updated_external_consent_permissions.device_id = device_id; + updated_external_consent_permissions.policy_app_id = application_id; + updated_user_permissions.consent_source = source; + + cache_->SetExternalConsentForApp(updated_external_consent_permissions); +} + +void PolicyManagerImpl::NotifySystem( + const PolicyManagerImpl::AppPoliciesValueType& app_policy) const { + listener()->OnPendingPermissionChange(app_policy.first); +} + +void PolicyManagerImpl::SendPermissionsToApp( + const PolicyManagerImpl::AppPoliciesValueType& app_policy) { + const std::string app_id = app_policy.first; + + const std::string device_id = GetCurrentDeviceId(app_id); + if (device_id.empty()) { + LOG4CXX_WARN(logger_, + "Couldn't find device info for application id: " << app_id); + return; + } + std::vector<FunctionalGroupPermission> group_permissons; + GetPermissionsForApp(device_id, app_id, group_permissons); + + Permissions notification_data; + + // Need to get rid of this call + utils::SharedPtr<policy_table::Table> policy_table_snapshot = + cache_->GenerateSnapshot(); + + PrepareNotificationData( + policy_table_snapshot->policy_table.functional_groupings, + app_policy.second.groups, + group_permissons, + notification_data); + + LOG4CXX_INFO(logger_, "Send notification for application_id: " << app_id); + listener()->OnPermissionsUpdated( + app_id, + notification_data, + policy_table::EnumToJsonString(app_policy.second.default_hmi)); +} + +void PolicyManagerImpl::ProcessExternalConsentStatusUpdate( + const GroupsByExternalConsentStatus& groups_by_status, + const ConsentProcessingPolicy processing_policy) { + GroupsNames allowed_groups; + GroupsNames disallowed_groups; + CalculateGroupsConsentFromExternalConsent( + groups_by_status, allowed_groups, disallowed_groups); + + std::map<std::string, std::string> known_links = + cache_->GetKnownLinksFromPT(); + std::map<std::string, std::string> registered_links; + listener_->GetRegisteredLinks(registered_links); + + std::map<std::string, std::string> all_known; + std::merge(known_links.begin(), + known_links.end(), + registered_links.begin(), + registered_links.end(), + std::inserter(all_known, all_known.begin())); + + std::map<std::string, std::string>::const_iterator it_links = + all_known.begin(); + for (; all_known.end() != it_links; ++it_links) { + UpdateAppConsentWithExternalConsent(it_links->first, + it_links->second, + allowed_groups, + disallowed_groups, + processing_policy); + } +} + +bool ConsentStatusComparatorFunc(const ExternalConsentStatusItem& i1, + const ExternalConsentStatusItem& i2) { + return (i1.entity_id_ < i2.entity_id_) || + (i1.entity_type_ < i2.entity_type_) || (i1.status_ < i2.status_); +} + +bool PolicyManagerImpl::IsNeedToUpdateExternalConsentStatus( + const ExternalConsentStatus& new_status) const { + LOG4CXX_AUTO_TRACE(logger_); + typedef std::vector<ExternalConsentStatusItem> ItemV; + const ExternalConsentStatus existing_status = + cache_->GetExternalConsentEntities(); + + ItemV new_status_v(new_status.begin(), new_status.end()); + ItemV existing_status_v(existing_status.begin(), existing_status.end()); + + ItemV difference_v; + difference_v.resize(new_status_v.size() + existing_status_v.size()); + + ItemV::iterator ci = difference_v.begin(); + ci = std::set_difference(new_status_v.begin(), + new_status_v.end(), + existing_status_v.begin(), + existing_status_v.end(), + difference_v.begin(), + ConsentStatusComparatorFunc); + difference_v.resize(ci - difference_v.begin()); + + return !difference_v.empty(); +} + +bool PolicyManagerImpl::SetExternalConsentStatus( + const ExternalConsentStatus& status) { + LOG4CXX_AUTO_TRACE(logger_); + + if (status.empty()) { + LOG4CXX_INFO(logger_, "External consent status is empty, skipping update."); + return false; + } + + if (!cache_->SetExternalConsentStatus(status)) { + LOG4CXX_WARN(logger_, "Can't set external user consent status."); + return false; + } + + GroupsByExternalConsentStatus groups_by_status = + cache_->GetGroupsWithSameEntities(status); + ProcessExternalConsentStatusUpdate( + groups_by_status, ConsentProcessingPolicy::kExternalConsentBased); + + return true; +} + +ExternalConsentStatus PolicyManagerImpl::GetExternalConsentStatus() { + LOG4CXX_AUTO_TRACE(logger_); + return cache_->GetExternalConsentStatus(); +} + +void PolicyManagerImpl::CalculateGroupsConsentFromExternalConsent( + const GroupsByExternalConsentStatus& groups_by_external_consent, + GroupsNames& out_allowed_groups, + GroupsNames& out_disallowed_groups) const { + LOG4CXX_AUTO_TRACE(logger_); + GroupSorter sorter(out_allowed_groups, out_disallowed_groups); + std::for_each(groups_by_external_consent.begin(), + groups_by_external_consent.end(), + sorter); + + GroupsNames filtered_allowed_groups; + std::set_difference( + out_allowed_groups.begin(), + out_allowed_groups.end(), + out_disallowed_groups.begin(), + out_disallowed_groups.end(), + std::inserter(filtered_allowed_groups, filtered_allowed_groups.begin())); + + out_allowed_groups = filtered_allowed_groups; +} + +bool PolicyManagerImpl::ExceededDays() { + LOG4CXX_AUTO_TRACE(logger_); + + TimevalStruct current_time = date_time::DateTime::getCurrentTime(); + const int kSecondsInDay = 60 * 60 * 24; + const int days = current_time.tv_sec / kSecondsInDay; + + DCHECK(std::numeric_limits<uint16_t>::max() >= days); + + if (std::numeric_limits<uint16_t>::max() <= days) { + LOG4CXX_WARN(logger_, "The days since epoch exceeds maximum value."); + return false; + } + return 0 == cache_->DaysBeforeExchange(static_cast<uint16_t>(days)); +} + +void PolicyManagerImpl::KmsChanged(int kilometers) { + LOG4CXX_AUTO_TRACE(logger_); + if (0 == cache_->KilometersBeforeExchange(kilometers)) { + LOG4CXX_INFO(logger_, "Enough kilometers passed to send for PT update."); + update_status_manager_.ScheduleUpdate(); + StartPTExchange(); + PTUpdatedAt(KILOMETERS, kilometers); + } +} + +void PolicyManagerImpl::IncrementIgnitionCycles() { + cache_->IncrementIgnitionCycles(); +} + +std::string PolicyManagerImpl::ForcePTExchange() { + update_status_manager_.ScheduleUpdate(); + StartPTExchange(); + return update_status_manager_.StringifiedUpdateStatus(); +} + +std::string PolicyManagerImpl::ForcePTExchangeAtUserRequest() { + LOG4CXX_AUTO_TRACE(logger_); + update_status_manager_.ScheduleManualUpdate(); + StartPTExchange(); + return update_status_manager_.StringifiedUpdateStatus(); +} + +std::string PolicyManagerImpl::GetPolicyTableStatus() const { + return update_status_manager_.StringifiedUpdateStatus(); +} + +int PolicyManagerImpl::NextRetryTimeout() { + sync_primitives::AutoLock auto_lock(retry_sequence_lock_); + LOG4CXX_DEBUG(logger_, "Index: " << retry_sequence_index_); + int next = 0; + if (!retry_sequence_seconds_.empty() && + retry_sequence_index_ < retry_sequence_seconds_.size()) { + next = retry_sequence_seconds_[retry_sequence_index_]; + ++retry_sequence_index_; + } + return next; +} + +void PolicyManagerImpl::RefreshRetrySequence() { + sync_primitives::AutoLock auto_lock(retry_sequence_lock_); + retry_sequence_timeout_ = cache_->TimeoutResponse(); + retry_sequence_seconds_.clear(); + cache_->SecondsBetweenRetries(retry_sequence_seconds_); +} + +void PolicyManagerImpl::ResetRetrySequence() { + sync_primitives::AutoLock auto_lock(retry_sequence_lock_); + retry_sequence_index_ = 0; + update_status_manager_.OnResetRetrySequence(); +} + +uint32_t PolicyManagerImpl::TimeoutExchangeMSec() { + return retry_sequence_timeout_; +} + +const std::vector<int> PolicyManagerImpl::RetrySequenceDelaysSeconds() { + sync_primitives::AutoLock auto_lock(retry_sequence_lock_); + return retry_sequence_seconds_; +} + +void PolicyManagerImpl::OnExceededTimeout() { + update_status_manager_.OnUpdateTimeoutOccurs(); +} + +void PolicyManagerImpl::OnUpdateStarted() { + uint32_t update_timeout = TimeoutExchangeMSec(); + LOG4CXX_DEBUG(logger_, + "Update timeout will be set to (milisec): " << update_timeout); + send_on_update_sent_out_ = + !wrong_ptu_update_received_ && !update_status_manager_.IsUpdatePending(); + + if (send_on_update_sent_out_) { + update_status_manager_.OnUpdateSentOut(update_timeout); + } + cache_->SaveUpdateRequired(true); +} + +void PolicyManagerImpl::PTUpdatedAt(Counters counter, int value) { + LOG4CXX_AUTO_TRACE(logger_); + cache_->SetCountersPassedForSuccessfulUpdate(counter, value); + cache_->ResetIgnitionCycles(); +} + +void PolicyManagerImpl::Increment(usage_statistics::GlobalCounterId type) { + LOG4CXX_INFO(logger_, "Increment without app id"); + cache_->Increment(type); +} + +void PolicyManagerImpl::Increment(const std::string& app_id, + usage_statistics::AppCounterId type) { + LOG4CXX_DEBUG(logger_, "Increment " << app_id << " AppCounter: " << type); + cache_->Increment(app_id, type); +} + +void PolicyManagerImpl::Set(const std::string& app_id, + usage_statistics::AppInfoId type, + const std::string& value) { + LOG4CXX_INFO(logger_, "Set " << app_id); + cache_->Set(app_id, type, value); +} + +void PolicyManagerImpl::Add(const std::string& app_id, + usage_statistics::AppStopwatchId type, + int32_t timespan_seconds) { + LOG4CXX_INFO(logger_, "Add " << app_id); + cache_->Add(app_id, type, timespan_seconds); +} + +bool PolicyManagerImpl::IsApplicationRevoked(const std::string& app_id) const { + return cache_->IsApplicationRevoked(app_id); +} + +bool PolicyManagerImpl::IsConsentNeeded(const std::string& app_id) { + LOG4CXX_AUTO_TRACE(logger_); + const std::string device_id = GetCurrentDeviceId(app_id); + int count = cache_->CountUnconsentedGroups(app_id, device_id); + LOG4CXX_DEBUG(logger_, "There are: " << count << " unconsented groups."); + return count != 0; +} + +void PolicyManagerImpl::SetVINValue(const std::string& value) { + cache_->SetVINValue(value); +} + +AppPermissions PolicyManagerImpl::GetAppPermissionsChanges( + const std::string& policy_app_id) { + PendingPermissions::iterator app_id_diff = + app_permissions_diff_.find(policy_app_id); + + AppPermissions permissions(policy_app_id); + + if (app_permissions_diff_.end() != app_id_diff) { + permissions = app_id_diff->second; + } else { + permissions.appPermissionsConsentNeeded = IsConsentNeeded(policy_app_id); + permissions.appRevoked = IsApplicationRevoked(policy_app_id); + GetPriority(permissions.application_id, &permissions.priority); + } + return permissions; +} + +void PolicyManagerImpl::RemovePendingPermissionChanges( + const std::string& app_id) { + app_permissions_diff_.erase(app_id); +} + +bool PolicyManagerImpl::CanAppKeepContext(const std::string& app_id) const { + return cache_->CanAppKeepContext(app_id); +} + +bool PolicyManagerImpl::CanAppStealFocus(const std::string& app_id) const { + return cache_->CanAppStealFocus(app_id); +} + +void PolicyManagerImpl::MarkUnpairedDevice(const std::string& device_id) { + if (!cache_->SetUnpairedDevice(device_id)) { + LOG4CXX_DEBUG(logger_, "Could not set unpaired flag for " << device_id); + return; + } + SetUserConsentForDevice(device_id, false); +} + +void PolicyManagerImpl::OnAppRegisteredOnMobile( + const std::string& application_id) { + StartPTExchange(); + SendNotificationOnPermissionsUpdated(application_id); +} + +const MetaInfo PolicyManagerImpl::GetMetaInfo() const { + LOG4CXX_AUTO_TRACE(logger_); + return cache_->GetMetaInfo(); +} + +std::string PolicyManagerImpl::RetrieveCertificate() const { + LOG4CXX_AUTO_TRACE(logger_); + return cache_->GetCertificate(); +} + +bool PolicyManagerImpl::HasCertificate() const { + return !cache_->GetCertificate().empty(); +} + +void PolicyManagerImpl::SetDecryptedCertificate( + const std::string& certificate) { + LOG4CXX_AUTO_TRACE(logger_); + cache_->SetDecryptedCertificate(certificate); +} + +AppIdURL PolicyManagerImpl::GetNextUpdateUrl(const EndpointUrls& urls) { + LOG4CXX_AUTO_TRACE(logger_); + + const AppIdURL next_app_url = RetrySequenceUrl(retry_sequence_url_, urls); + + retry_sequence_url_.url_idx_ = next_app_url.second + 1; + retry_sequence_url_.app_idx_ = next_app_url.first; + retry_sequence_url_.policy_app_id_ = urls[next_app_url.first].app_id; + + return next_app_url; +} + +AppIdURL PolicyManagerImpl::RetrySequenceUrl(const struct RetrySequenceURL& rs, + const EndpointUrls& urls) const { + uint32_t url_idx = rs.url_idx_; + uint32_t app_idx = rs.app_idx_; + const std::string& app_id = rs.policy_app_id_; + + if (urls.size() <= app_idx) { + // Index of current application doesn't exist any more due to app(s) + // unregistration + url_idx = 0; + app_idx = 0; + } else if (urls[app_idx].app_id != app_id) { + // Index of current application points to another one due to app(s) + // registration/unregistration + url_idx = 0; + } else if (url_idx >= urls[app_idx].url.size()) { + // Index of current application is OK, but all of its URL are sent, + // move to the next application + url_idx = 0; + if (++app_idx >= urls.size()) { + app_idx = 0; + } + } + const AppIdURL next_app_url = std::make_pair(app_idx, url_idx); + + return next_app_url; +} + +/** + * @brief The CallStatusChange class notify update manager aboun new application + */ +class CallStatusChange : public utils::Callable { + public: + CallStatusChange(UpdateStatusManager& upd_manager, + const DeviceConsent& device_consent) + : upd_manager_(upd_manager), device_consent_(device_consent) {} + + // Callable interface + void operator()() const { + upd_manager_.OnNewApplicationAdded(device_consent_); + } + + private: + UpdateStatusManager& upd_manager_; + const DeviceConsent device_consent_; +}; + +StatusNotifier PolicyManagerImpl::AddApplication( + const std::string& application_id, + const rpc::policy_table_interface_base::AppHmiTypes& hmi_types) { + LOG4CXX_AUTO_TRACE(logger_); + const std::string device_id = GetCurrentDeviceId(application_id); + DeviceConsent device_consent = GetUserConsentForDevice(device_id); + sync_primitives::AutoLock lock(apps_registration_lock_); + if (IsNewApplication(application_id)) { + AddNewApplication(application_id, device_consent); + return utils::MakeShared<CallStatusChange>(update_status_manager_, + device_consent); + } else { + PromoteExistedApplication(application_id, device_consent); + if (helpers::in_range(hmi_types, policy_table::AHT_NAVIGATION) && + !HasCertificate()) { + LOG4CXX_DEBUG(logger_, "Certificate does not exist, scheduling update."); + update_status_manager_.ScheduleUpdate(); + } + return utils::MakeShared<utils::CallNothing>(); + } +} + +void PolicyManagerImpl::RemoveAppConsentForGroup( + const std::string& app_id, const std::string& group_name) { + cache_->RemoveAppConsentForGroup(app_id, group_name); +} + +bool PolicyManagerImpl::IsPredataPolicy( + const std::string& policy_app_id) const { + LOG4CXX_INFO(logger_, "IsPredataApp"); + return cache_->IsPredataPolicy(policy_app_id); +} + +void PolicyManagerImpl::ProcessExternalConsentStatusForApp( + const std::string& application_id, + const ConsentProcessingPolicy processing_policy) { + ExternalConsentStatus status = cache_->GetExternalConsentStatus(); + GroupsByExternalConsentStatus groups_by_status = + cache_->GetGroupsWithSameEntities(status); + + GroupsNames allowed_groups; + GroupsNames disallowed_groups; + CalculateGroupsConsentFromExternalConsent( + groups_by_status, allowed_groups, disallowed_groups); + + const std::string device_id = GetCurrentDeviceId(application_id); + UpdateAppConsentWithExternalConsent(device_id, + application_id, + allowed_groups, + disallowed_groups, + processing_policy); +} + +void PolicyManagerImpl::AddNewApplication(const std::string& application_id, + DeviceConsent device_consent) { + LOG4CXX_AUTO_TRACE(logger_); + + if (kDeviceHasNoConsent == device_consent || + kDeviceDisallowed == device_consent) { + LOG4CXX_INFO(logger_, + "Setting " + << policy::kPreDataConsentId + << " permissions for application id: " << application_id); + cache_->SetPredataPolicy(application_id); + } else { + LOG4CXX_INFO(logger_, + "Setting " + << policy::kDefaultId + << " permissions for application id: " << application_id); + cache_->SetDefaultPolicy(application_id); + } + + ProcessExternalConsentStatusForApp( + application_id, ConsentProcessingPolicy::kExternalConsentBased); +} + +void PolicyManagerImpl::PromoteExistedApplication( + const std::string& application_id, DeviceConsent device_consent) { + // If device consent changed to allowed during application being + // disconnected, app permissions should be changed also + if (kDeviceAllowed == device_consent && + cache_->IsPredataPolicy(application_id)) { + cache_->SetDefaultPolicy(application_id); + } + ProcessExternalConsentStatusForApp(application_id, + ConsentProcessingPolicy::kTimestampBased); +} + +bool PolicyManagerImpl::IsNewApplication( + const std::string& application_id) const { + return false == cache_->IsApplicationRepresented(application_id); +} + +bool PolicyManagerImpl::ResetPT(const std::string& file_name) { + LOG4CXX_AUTO_TRACE(logger_); + cache_->ResetCalculatedPermissions(); + const bool result = cache_->ResetPT(file_name); + if (result) { + RefreshRetrySequence(); + } + return result; +} + +bool PolicyManagerImpl::CheckAppStorageFolder() const { + LOG4CXX_AUTO_TRACE(logger_); + const std::string app_storage_folder = get_settings().app_storage_folder(); + LOG4CXX_DEBUG(logger_, "AppStorageFolder " << app_storage_folder); + if (!file_system::DirectoryExists(app_storage_folder)) { + LOG4CXX_WARN(logger_, + "Storage directory doesn't exist " << app_storage_folder); + return false; + } + if (!(file_system::IsWritingAllowed(app_storage_folder) && + file_system::IsReadingAllowed(app_storage_folder))) { + LOG4CXX_WARN(logger_, + "Storage directory doesn't have read/write permissions " + << app_storage_folder); + return false; + } + return true; +} + +bool PolicyManagerImpl::InitPT(const std::string& file_name, + const PolicySettings* settings) { + LOG4CXX_AUTO_TRACE(logger_); + settings_ = settings; + if (!CheckAppStorageFolder()) { + LOG4CXX_ERROR(logger_, "Can not read/write into AppStorageFolder"); + return false; + } + const bool ret = cache_->Init(file_name, settings); + if (ret) { + RefreshRetrySequence(); + update_status_manager_.OnPolicyInit(cache_->UpdateRequired()); + } + return ret; +} + +uint32_t PolicyManagerImpl::HeartBeatTimeout(const std::string& app_id) const { + return cache_->HeartBeatTimeout(app_id); +} + +void PolicyManagerImpl::SaveUpdateStatusRequired(bool is_update_needed) { + cache_->SaveUpdateRequired(is_update_needed); +} + +void PolicyManagerImpl::set_cache_manager( + CacheManagerInterface* cache_manager) { + cache_ = cache_manager; +} + +} // namespace policy diff --git a/src/components/policy/policy_external/src/policy_table.cc b/src/components/policy/policy_external/src/policy_table.cc new file mode 100644 index 0000000000..7a63fac50d --- /dev/null +++ b/src/components/policy/policy_external/src/policy_table.cc @@ -0,0 +1,52 @@ +/* + Copyright (c) 2013, Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include "policy/policy_table.h" + +#include "policy/sql_pt_ext_representation.h" + +#include "utils/logger.h" + +namespace policy { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +PolicyTable::PolicyTable() : pt_data_(new SQLPTExtRepresentation()) {} + +PolicyTable::PolicyTable(utils::SharedPtr<PTRepresentation> pt_data) + : pt_data_(pt_data) {} + +PolicyTable::~PolicyTable() { + LOG4CXX_INFO(logger_, "Destroying policy table."); +} + +} // namespace policy diff --git a/src/components/policy/policy_external/src/policy_table/enums.cc b/src/components/policy/policy_external/src/policy_table/enums.cc new file mode 100644 index 0000000000..e70167c94b --- /dev/null +++ b/src/components/policy/policy_external/src/policy_table/enums.cc @@ -0,0 +1,723 @@ +// This file is generated, do not edit +#include "policy/policy_table/enums.h" + +namespace rpc { +namespace policy_table_interface_base { +bool IsValidEnum(Priority val) { + switch (val) { + case P_EMERGENCY: + return true; + case P_NAVIGATION: + return true; + case P_VOICECOM: + return true; + case P_COMMUNICATION: + return true; + case P_NORMAL: + return true; + case P_NONE: + return true; + default: + return false; + } +} +const char* EnumToJsonString(Priority val) { + switch (val) { + case P_EMERGENCY: + return "EMERGENCY"; + case P_NAVIGATION: + return "NAVIGATION"; + case P_VOICECOM: + return "VOICECOM"; + case P_COMMUNICATION: + return "COMMUNICATION"; + case P_NORMAL: + return "NORMAL"; + case P_NONE: + return "NONE"; + default: + return ""; + } +} +bool EnumFromJsonString(const std::string& literal, Priority* result) { + if ("EMERGENCY" == literal) { + *result = P_EMERGENCY; + return true; + } else if ("NAVIGATION" == literal) { + *result = P_NAVIGATION; + return true; + } else if ("VOICECOM" == literal) { + *result = P_VOICECOM; + return true; + } else if ("COMMUNICATION" == literal) { + *result = P_COMMUNICATION; + return true; + } else if ("NORMAL" == literal) { + *result = P_NORMAL; + return true; + } else if ("NONE" == literal) { + *result = P_NONE; + return true; + } else { + return false; + } +} + +bool IsValidEnum(HmiLevel val) { + switch (val) { + case HL_BACKGROUND: + return true; + case HL_FULL: + return true; + case HL_LIMITED: + return true; + case HL_NONE: + return true; + default: + return false; + } +} +const char* EnumToJsonString(HmiLevel val) { + switch (val) { + case HL_BACKGROUND: + return "BACKGROUND"; + case HL_FULL: + return "FULL"; + case HL_LIMITED: + return "LIMITED"; + case HL_NONE: + return "NONE"; + default: + return ""; + } +} +bool EnumFromJsonString(const std::string& literal, HmiLevel* result) { + if ("BACKGROUND" == literal) { + *result = HL_BACKGROUND; + return true; + } else if ("FULL" == literal) { + *result = HL_FULL; + return true; + } else if ("LIMITED" == literal) { + *result = HL_LIMITED; + return true; + } else if ("NONE" == literal) { + *result = HL_NONE; + return true; + } else { + return false; + } +} + +bool IsValidEnum(Parameter val) { + switch (val) { + case P_GPS: + return true; + case P_SPEED: + return true; + case P_ENGINETORQUE: + return true; + case P_EXTERNALTEMPERATURE: + return true; + case P_FUELLEVEL: + return true; + case P_FUELLEVEL_STATE: + return true; + case P_HEADLAMPSTATUS: + return true; + case P_INSTANTFUELCONSUMPTION: + return true; + case P_ODOMETER: + return true; + case P_TIREPRESSURE: + return true; + case P_WIPERSTATUS: + return true; + case P_VIN: + return true; + case P_ACCPEDALPOSITION: + return true; + case P_BELTSTATUS: + return true; + case P_DRIVERBRAKING: + return true; + case P_PRNDL: + return true; + case P_RPM: + return true; + case P_STEERINGWHEELANGLE: + return true; + case P_MYKEY: + return true; + case P_AIRBAGSTATUS: + return true; + case P_BODYINFORMATION: + return true; + case P_CLUSTERMODESTATUS: + return true; + case P_DEVICESTATUS: + return true; + case P_EMERGENCYEVENT: + return true; + case P_ECALLINFO: + return true; + case P_ABS_STATE: + return true; + case P_TURN_SIGNAL: + return true; + case P_FUEL_RANGE: + return true; + case P_TIRE_PRESSURE_VALUE: + return true; + case P_TPMS: + return true; + case P_LONGTITUDE_DEGREES: + return true; + case P_LATITUDE_DEGREES: + return true; + case P_LOCATION_NAME: + return true; + case P_LOCATION_DESCRIPTION: + return true; + case P_ADDRESS_LINES: + return true; + case P_PHONE_NUMBER: + return true; + case P_LOCATION_IMAGE: + return true; + case P_DELIVERY_MODE: + return true; + case P_TIMESTAMP: + return true; + case P_ADDRESS: + return true; + case P_EMPTY: + return true; + default: + return false; + } +} + +const char* EnumToJsonString(Parameter val) { + switch (val) { + case P_GPS: + return "gps"; + case P_SPEED: + return "speed"; + case P_ENGINETORQUE: + return "engineTorque"; + case P_EXTERNALTEMPERATURE: + return "externalTemperature"; + case P_FUELLEVEL: + return "fuelLevel"; + case P_FUELLEVEL_STATE: + return "fuelLevel_State"; + case P_HEADLAMPSTATUS: + return "headLampStatus"; + case P_INSTANTFUELCONSUMPTION: + return "instantFuelConsumption"; + case P_ODOMETER: + return "odometer"; + case P_TIREPRESSURE: + return "tirePressure"; + case P_WIPERSTATUS: + return "wiperStatus"; + case P_VIN: + return "vin"; + case P_ACCPEDALPOSITION: + return "accPedalPosition"; + case P_BELTSTATUS: + return "beltStatus"; + case P_DRIVERBRAKING: + return "driverBraking"; + case P_PRNDL: + return "prndl"; + case P_RPM: + return "rpm"; + case P_STEERINGWHEELANGLE: + return "steeringWheelAngle"; + case P_MYKEY: + return "myKey"; + case P_AIRBAGSTATUS: + return "airbagStatus"; + case P_BODYINFORMATION: + return "bodyInformation"; + case P_CLUSTERMODESTATUS: + return "clusterModeStatus"; + case P_DEVICESTATUS: + return "deviceStatus"; + case P_EMERGENCYEVENT: + return "emergencyEvent"; + case P_ECALLINFO: + return "eCallInfo"; + case P_ABS_STATE: + return "abs_State"; + case P_TURN_SIGNAL: + return "turnSignal"; + case P_FUEL_RANGE: + return "fuelRange"; + case P_TIRE_PRESSURE_VALUE: + return "tirePressureValue"; + case P_TPMS: + return "tpms"; + case P_LONGTITUDE_DEGREES: + return "longitudeDegrees"; + case P_LATITUDE_DEGREES: + return "latitudeDegrees"; + case P_LOCATION_NAME: + return "locationName"; + case P_LOCATION_DESCRIPTION: + return "locationDescription"; + case P_ADDRESS_LINES: + return "addressLines"; + case P_PHONE_NUMBER: + return "phoneNumber"; + case P_LOCATION_IMAGE: + return "locationImage"; + case P_DELIVERY_MODE: + return "deliveryMode"; + case P_TIMESTAMP: + return "timeStamp"; + case P_ADDRESS: + return "address"; + case P_EMPTY: + return "EMPTY"; + default: + return ""; + } +} + +bool EnumFromJsonString(const std::string& literal, Parameter* result) { + if ("gps" == literal) { + *result = P_GPS; + return true; + } else if ("speed" == literal) { + *result = P_SPEED; + return true; + } else if ("engineTorque" == literal) { + *result = P_ENGINETORQUE; + return true; + } else if ("externalTemperature" == literal) { + *result = P_EXTERNALTEMPERATURE; + return true; + } else if ("fuelLevel" == literal) { + *result = P_FUELLEVEL; + return true; + } else if ("fuelLevel_State" == literal) { + *result = P_FUELLEVEL_STATE; + return true; + } else if ("headLampStatus" == literal) { + *result = P_HEADLAMPSTATUS; + return true; + } else if ("instantFuelConsumption" == literal) { + *result = P_INSTANTFUELCONSUMPTION; + return true; + } else if ("odometer" == literal) { + *result = P_ODOMETER; + return true; + } else if ("tirePressure" == literal) { + *result = P_TIREPRESSURE; + return true; + } else if ("wiperStatus" == literal) { + *result = P_WIPERSTATUS; + return true; + } else if ("vin" == literal) { + *result = P_VIN; + return true; + } else if ("accPedalPosition" == literal) { + *result = P_ACCPEDALPOSITION; + return true; + } else if ("beltStatus" == literal) { + *result = P_BELTSTATUS; + return true; + } else if ("driverBraking" == literal) { + *result = P_DRIVERBRAKING; + return true; + } else if ("prndl" == literal) { + *result = P_PRNDL; + return true; + } else if ("rpm" == literal) { + *result = P_RPM; + return true; + } else if ("steeringWheelAngle" == literal) { + *result = P_STEERINGWHEELANGLE; + return true; + } else if ("myKey" == literal) { + *result = P_MYKEY; + return true; + } else if ("airbagStatus" == literal) { + *result = P_AIRBAGSTATUS; + return true; + } else if ("bodyInformation" == literal) { + *result = P_BODYINFORMATION; + return true; + } else if ("clusterModeStatus" == literal) { + *result = P_CLUSTERMODESTATUS; + return true; + } else if ("deviceStatus" == literal) { + *result = P_DEVICESTATUS; + return true; + } else if ("emergencyEvent" == literal) { + *result = P_EMERGENCYEVENT; + return true; + } else if ("eCallInfo" == literal) { + *result = P_ECALLINFO; + return true; + } else if ("abs_State" == literal) { + *result = P_ABS_STATE; + return true; + } else if ("turnSignal" == literal) { + *result = P_TURN_SIGNAL; + return true; + } else if ("fuelRange" == literal) { + *result = P_FUEL_RANGE; + return true; + } else if ("tirePressureValue" == literal) { + *result = P_TIRE_PRESSURE_VALUE; + return true; + } else if ("tpms" == literal) { + *result = P_TPMS; + return true; + } else if ("longitudeDegrees" == literal) { + *result = P_LONGTITUDE_DEGREES; + return true; + } else if ("latitudeDegrees" == literal) { + *result = P_LATITUDE_DEGREES; + return true; + } else if ("locationName" == literal) { + *result = P_LOCATION_NAME; + return true; + } else if ("locationDescription" == literal) { + *result = P_LOCATION_DESCRIPTION; + return true; + } else if ("addressLines" == literal) { + *result = P_ADDRESS_LINES; + return true; + } else if ("phoneNumber" == literal) { + *result = P_PHONE_NUMBER; + return true; + } else if ("locationImage" == literal) { + *result = P_LOCATION_IMAGE; + return true; + } else if ("deliveryMode" == literal) { + *result = P_DELIVERY_MODE; + return true; + } else if ("timeStamp" == literal) { + *result = P_TIMESTAMP; + return true; + } else if ("address" == literal) { + *result = P_ADDRESS; + return true; + } else if ("EMPTY" == literal) { + *result = P_EMPTY; + return true; + } else { + return false; + } +} + +bool IsValidEnum(AppHMIType val) { + switch (val) { + case AHT_DEFAULT: + return true; + case AHT_COMMUNICATION: + return true; + case AHT_MEDIA: + return true; + case AHT_MESSAGING: + return true; + case AHT_NAVIGATION: + return true; + case AHT_INFORMATION: + return true; + case AHT_SOCIAL: + return true; + case AHT_BACKGROUND_PROCESS: + return true; + case AHT_TESTING: + return true; + case AHT_SYSTEM: + return true; + default: + return false; + } +} +const char* EnumToJsonString(AppHMIType val) { + switch (val) { + case AHT_DEFAULT: + return "DEFAULT"; + case AHT_COMMUNICATION: + return "COMMUNICATION"; + case AHT_MEDIA: + return "MEDIA"; + case AHT_MESSAGING: + return "MESSAGING"; + case AHT_NAVIGATION: + return "NAVIGATION"; + case AHT_INFORMATION: + return "INFORMATION"; + case AHT_SOCIAL: + return "SOCIAL"; + case AHT_BACKGROUND_PROCESS: + return "BACKGROUND_PROCESS"; + case AHT_TESTING: + return "TESTING"; + case AHT_SYSTEM: + return "SYSTEM"; + default: + return ""; + } +} +bool EnumFromJsonString(const std::string& literal, AppHMIType* result) { + if ("DEFAULT" == literal) { + *result = AHT_DEFAULT; + return true; + } else if ("COMMUNICATION" == literal) { + *result = AHT_COMMUNICATION; + return true; + } else if ("MEDIA" == literal) { + *result = AHT_MEDIA; + return true; + } else if ("MESSAGING" == literal) { + *result = AHT_MESSAGING; + return true; + } else if ("NAVIGATION" == literal) { + *result = AHT_NAVIGATION; + return true; + } else if ("INFORMATION" == literal) { + *result = AHT_INFORMATION; + return true; + } else if ("SOCIAL" == literal) { + *result = AHT_SOCIAL; + return true; + } else if ("BACKGROUND_PROCESS" == literal) { + *result = AHT_BACKGROUND_PROCESS; + return true; + } else if ("TESTING" == literal) { + *result = AHT_TESTING; + return true; + } else if ("SYSTEM" == literal) { + *result = AHT_SYSTEM; + return true; + } else { + return false; + } +} + +bool IsValidEnum(Input val) { + switch (val) { + case I_GUI: + return true; + case I_VUI: + return true; + default: + return false; + } +} +const char* EnumToJsonString(Input val) { + switch (val) { + case I_GUI: + return "GUI"; + case I_VUI: + return "VUI"; + default: + return ""; + } +} +bool EnumFromJsonString(const std::string& literal, Input* result) { + if ("GUI" == literal) { + *result = I_GUI; + return true; + } else if ("VUI" == literal) { + *result = I_VUI; + return true; + } else { + return false; + } +} + +bool IsValidEnum(RequestType val) { + switch (val) { + case RT_HTTP: + return true; + case RT_FILE_RESUME: + return true; + case RT_AUTH_REQUEST: + return true; + case RT_AUTH_CHALLENGE: + return true; + case RT_AUTH_ACK: + return true; + case RT_PROPRIETARY: + return true; + case RT_QUERY_APPS: + return true; + case RT_LAUNCH_APP: + return true; + case RT_LOCK_SCREEN_ICON_URL: + return true; + case RT_TRAFFIC_MESSAGE_CHANNEL: + return true; + case RT_DRIVER_PROFILE: + return true; + case RT_VOICE_SEARCH: + return true; + case RT_NAVIGATION: + return true; + case RT_PHONE: + return true; + case RT_CLIMATE: + return true; + case RT_SETTINGS: + return true; + case RT_VEHICLE_DIAGNOSTICS: + return true; + case RT_EMERGENCY: + return true; + case RT_MEDIA: + return true; + case RT_FOTA: + return true; + default: + return false; + } +} + +const char* EnumToJsonString(RequestType val) { + switch (val) { + case RT_HTTP: + return "HTTP"; + case RT_FILE_RESUME: + return "FILE_RESUME"; + case RT_AUTH_REQUEST: + return "AUTH_REQUEST"; + case RT_AUTH_CHALLENGE: + return "AUTH_CHALLENGE"; + case RT_AUTH_ACK: + return "AUTH_ACK"; + case RT_PROPRIETARY: + return "PROPRIETARY"; + case RT_QUERY_APPS: + return "QUERY_APPS"; + case RT_LAUNCH_APP: + return "LAUNCH_APP"; + case RT_LOCK_SCREEN_ICON_URL: + return "LOCK_SCREEN_ICON_URL"; + case RT_TRAFFIC_MESSAGE_CHANNEL: + return "TRAFFIC_MESSAGE_CHANNEL"; + case RT_DRIVER_PROFILE: + return "DRIVER_PROFILE"; + case RT_VOICE_SEARCH: + return "VOICE_SEARCH"; + case RT_NAVIGATION: + return "NAVIGATION"; + case RT_PHONE: + return "PHONE"; + case RT_CLIMATE: + return "CLIMATE"; + case RT_SETTINGS: + return "SETTINGS"; + case RT_VEHICLE_DIAGNOSTICS: + return "VEHICLE_DIAGNOSTICS"; + case RT_EMERGENCY: + return "EMERGENCY"; + case RT_MEDIA: + return "MEDIA"; + case RT_FOTA: + return "FOTA"; + default: + return ""; + } +} + +bool EnumFromJsonString(const std::string& literal, RequestType* result) { + if ("HTTP" == literal) { + *result = RT_HTTP; + return true; + } + if ("FILE_RESUME" == literal) { + *result = RT_FILE_RESUME; + return true; + } + if ("AUTH_REQUEST" == literal) { + *result = RT_AUTH_REQUEST; + return true; + } + if ("AUTH_CHALLENGE" == literal) { + *result = RT_AUTH_CHALLENGE; + return true; + } + if ("AUTH_ACK" == literal) { + *result = RT_AUTH_ACK; + return true; + } + if ("PROPRIETARY" == literal) { + *result = RT_PROPRIETARY; + return true; + } + if ("QUERY_APPS" == literal) { + *result = RT_QUERY_APPS; + return true; + } + if ("LAUNCH_APP" == literal) { + *result = RT_LAUNCH_APP; + return true; + } + if ("LOCK_SCREEN_ICON_URL" == literal) { + *result = RT_LOCK_SCREEN_ICON_URL; + return true; + } + if ("TRAFFIC_MESSAGE_CHANNEL" == literal) { + *result = RT_TRAFFIC_MESSAGE_CHANNEL; + return true; + } + if ("DRIVER_PROFILE" == literal) { + *result = RT_DRIVER_PROFILE; + return true; + } + if ("VOICE_SEARCH" == literal) { + *result = RT_VOICE_SEARCH; + return true; + } + if ("NAVIGATION" == literal) { + *result = RT_NAVIGATION; + return true; + } + if ("PHONE" == literal) { + *result = RT_PHONE; + return true; + } + if ("CLIMATE" == literal) { + *result = RT_CLIMATE; + return true; + } + if ("SETTINGS" == literal) { + *result = RT_SETTINGS; + return true; + } + if ("VEHICLE_DIAGNOSTICS" == literal) { + *result = RT_VEHICLE_DIAGNOSTICS; + return true; + } + if ("EMERGENCY" == literal) { + *result = RT_EMERGENCY; + return true; + } + if ("MEDIA" == literal) { + *result = RT_MEDIA; + return true; + } + if ("FOTA" == literal) { + *result = RT_FOTA; + return true; + } else { + return false; + } +} + +const std::string kDefaultApp = "default"; +const std::string kPreDataConsentApp = "pre_DataConsent"; +const std::string kDeviceApp = "device"; + +} // namespace policy_table_interface_base +} // namespace rpc diff --git a/src/components/policy/policy_external/src/policy_table/types.cc b/src/components/policy/policy_external/src/policy_table/types.cc new file mode 100644 index 0000000000..528d70a426 --- /dev/null +++ b/src/components/policy/policy_external/src/policy_table/types.cc @@ -0,0 +1,2134 @@ +#include <algorithm> +#include "policy/policy_table/types.h" +#include "rpc_base/rpc_base_json_inl.h" + +namespace rpc { +namespace policy_table_interface_base { + +std::string PolicyTableTypeToString(const PolicyTableType pt_type) { + switch (pt_type) { + case PT_PRELOADED: { + return "PT_PRELOADED"; + } + case PT_UPDATE: { + return "PT_UPDATE"; + } + case PT_SNAPSHOT: { + return "PT_SNAPSHOT"; + } + default: { return "INVALID_PT_TYPE"; } + } +} + +// PolicyBase methods +PolicyBase::PolicyBase() : CompositeType(kUninitialized) {} + +PolicyBase::PolicyBase(const Strings& groups, + Priority priority, + HmiLevel default_hmi, + bool keep_context, + bool steal_focus) + : CompositeType(kUninitialized) + , groups(groups) + , priority(priority) + , default_hmi(default_hmi) + , keep_context(keep_context) + , steal_focus(steal_focus) {} + +PolicyBase::~PolicyBase() {} + +PolicyBase::PolicyBase(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , groups(impl::ValueMember(value__, "groups")) + , preconsented_groups(impl::ValueMember(value__, "preconsented_groups")) + , priority(impl::ValueMember(value__, "priority")) + , default_hmi(impl::ValueMember(value__, "default_hmi")) + , keep_context(impl::ValueMember(value__, "keep_context")) + , steal_focus(impl::ValueMember(value__, "steal_focus")) {} + +Json::Value PolicyBase::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("groups", groups, &result__); + impl::WriteJsonField("preconsented_groups", preconsented_groups, &result__); + impl::WriteJsonField("priority", priority, &result__); + impl::WriteJsonField("default_hmi", default_hmi, &result__); + impl::WriteJsonField("keep_context", keep_context, &result__); + impl::WriteJsonField("steal_focus", steal_focus, &result__); + return result__; +} + +bool PolicyBase::is_valid() const { + if (!groups.is_valid()) { + return false; + } + if (!preconsented_groups.is_valid()) { + return false; + } + if (!priority.is_valid()) { + return false; + } + if (!default_hmi.is_valid()) { + return false; + } + if (!keep_context.is_valid()) { + return false; + } + if (!steal_focus.is_valid()) { + return false; + } + return Validate(); +} + +bool PolicyBase::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool PolicyBase::struct_empty() const { + if (groups.is_initialized()) { + return false; + } + if (preconsented_groups.is_initialized()) { + return false; + } + if (priority.is_initialized()) { + return false; + } + if (default_hmi.is_initialized()) { + return false; + } + if (keep_context.is_initialized()) { + return false; + } + if (steal_focus.is_initialized()) { + return false; + } + return true; +} + +void PolicyBase::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!groups.is_valid()) { + groups.ReportErrors(&report__->ReportSubobject("groups")); + } + if (!preconsented_groups.is_valid()) { + preconsented_groups.ReportErrors( + &report__->ReportSubobject("preconsented_groups")); + } + if (!priority.is_valid()) { + priority.ReportErrors(&report__->ReportSubobject("priority")); + } + if (!default_hmi.is_valid()) { + default_hmi.ReportErrors(&report__->ReportSubobject("default_hmi")); + } + if (!keep_context.is_valid()) { + keep_context.ReportErrors(&report__->ReportSubobject("keep_context")); + } + if (!steal_focus.is_valid()) { + steal_focus.ReportErrors(&report__->ReportSubobject("steal_focus")); + } +} + +void PolicyBase::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + groups.SetPolicyTableType(pt_type); + priority.SetPolicyTableType(pt_type); +} + +// DevicePolicy methods +DevicePolicy::DevicePolicy() : PolicyBase() {} + +DevicePolicy::DevicePolicy(const Strings& groups, + Priority priority, + HmiLevel default_hmi, + bool keep_context, + bool steal_focus) + : PolicyBase(groups, priority, default_hmi, keep_context, steal_focus) {} + +DevicePolicy::~DevicePolicy() {} + +DevicePolicy::DevicePolicy(const Json::Value* value__) : PolicyBase(value__) {} + +// AppPoliciesSection methods +ApplicationPoliciesSection::ApplicationPoliciesSection() + : CompositeType(kUninitialized) {} + +ApplicationPoliciesSection::ApplicationPoliciesSection( + const ApplicationPolicies& apps, const DevicePolicy& device) + : CompositeType(kUninitialized), apps(apps), device(device) {} + +ApplicationPoliciesSection::~ApplicationPoliciesSection() {} + +ApplicationPoliciesSection::ApplicationPoliciesSection( + const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , apps(value__) + , device(impl::ValueMember(value__, "device")) { + // Since "device" is moved to separate struct, we have to delete it from + // parsed apps to avoid validation issues due to possible wrong params in + // device section + apps.erase("device"); +} + +Json::Value ApplicationPoliciesSection::ToJsonValue() const { + Json::Value result__(Json::objectValue); + result__ = apps.ToJsonValue(); + impl::WriteJsonField("device", device, &result__); + return result__; +} + +bool ApplicationPoliciesSection::is_valid() const { + if (!device.is_valid()) { + return false; + } + if (!apps.is_valid()) { + return false; + } + return Validate(); +} + +bool ApplicationPoliciesSection::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool ApplicationPoliciesSection::struct_empty() const { + if (device.is_initialized()) { + return false; + } + if (apps.is_initialized()) { + return false; + } + return true; +} + +void ApplicationPoliciesSection::ReportErrors( + rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!device.is_valid()) { + device.ReportErrors(&report__->ReportSubobject("device")); + } + if (!apps.is_valid()) { + apps.ReportErrors(&report__->ReportSubobject("apps")); + } +} + +void ApplicationPoliciesSection::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + device.SetPolicyTableType(pt_type); + apps.SetPolicyTableType(pt_type); +} + +// ApplicationParams methods +ApplicationParams::ApplicationParams() : PolicyBase() {} + +ApplicationParams::ApplicationParams(const Strings& groups, + Priority priority, + HmiLevel default_hmi, + bool keep_context, + bool steal_focus) + : PolicyBase(groups, priority, default_hmi, keep_context, steal_focus) {} + +ApplicationParams::~ApplicationParams() {} + +ApplicationParams::ApplicationParams(const Json::Value* value__) + : PolicyBase(value__) + , nicknames(impl::ValueMember(value__, "nicknames")) + , AppHMIType(impl::ValueMember(value__, "AppHMIType")) + , RequestType(impl::ValueMember(value__, "RequestType")) + , memory_kb(impl::ValueMember(value__, "memory_kb"), 0) + , heart_beat_timeout_ms( + impl::ValueMember(value__, "heart_beat_timeout_ms")) {} + +Json::Value ApplicationParams::ToJsonValue() const { + Json::Value result__(PolicyBase::ToJsonValue()); + impl::WriteJsonField("nicknames", nicknames, &result__); + impl::WriteJsonField("AppHMIType", AppHMIType, &result__); + impl::WriteJsonField("RequestType", RequestType, &result__); + impl::WriteJsonField("memory_kb", memory_kb, &result__); + impl::WriteJsonField( + "heart_beat_timeout_ms", heart_beat_timeout_ms, &result__); + return result__; +} + +bool ApplicationParams::is_valid() const { + // RequestType is not validated since there is high-level validation logic, + // which takes into account information not available here. + if (!PolicyBase::is_valid()) { + return false; + } + if (!nicknames.is_valid()) { + return false; + } + if (!AppHMIType.is_valid()) { + return false; + } + if (!memory_kb.is_valid()) { + return false; + } + if (!heart_beat_timeout_ms.is_valid()) { + return false; + } + return Validate(); +} + +bool ApplicationParams::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool ApplicationParams::struct_empty() const { + if (!PolicyBase::is_initialized()) { + return false; + } + if (nicknames.is_initialized()) { + return false; + } + if (AppHMIType.is_initialized()) { + return false; + } + if (RequestType.is_initialized()) { + return false; + } + if (memory_kb.is_initialized()) { + return false; + } + if (heart_beat_timeout_ms.is_initialized()) { + return false; + } + return true; +} + +void ApplicationParams::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!groups.is_valid()) { + groups.ReportErrors(&report__->ReportSubobject("groups")); + } + if (!nicknames.is_valid()) { + nicknames.ReportErrors(&report__->ReportSubobject("nicknames")); + } + if (!preconsented_groups.is_valid()) { + preconsented_groups.ReportErrors( + &report__->ReportSubobject("preconsented_groups")); + } + if (!AppHMIType.is_valid()) { + AppHMIType.ReportErrors(&report__->ReportSubobject("AppHMIType")); + } + if (!RequestType.is_valid()) { + RequestType.ReportErrors(&report__->ReportSubobject("RequestType")); + } + if (!priority.is_valid()) { + priority.ReportErrors(&report__->ReportSubobject("priority")); + } + if (!default_hmi.is_valid()) { + default_hmi.ReportErrors(&report__->ReportSubobject("default_hmi")); + } + if (!keep_context.is_valid()) { + keep_context.ReportErrors(&report__->ReportSubobject("keep_context")); + } + if (!steal_focus.is_valid()) { + steal_focus.ReportErrors(&report__->ReportSubobject("steal_focus")); + } + if (!memory_kb.is_valid()) { + memory_kb.ReportErrors(&report__->ReportSubobject("memory_kb")); + } + if (!heart_beat_timeout_ms.is_valid()) { + heart_beat_timeout_ms.ReportErrors( + &report__->ReportSubobject("heart_beat_timeout_ms")); + } +} + +void ApplicationParams::SetPolicyTableType(PolicyTableType pt_type) { + PolicyBase::SetPolicyTableType(pt_type); + AppHMIType.SetPolicyTableType(pt_type); + RequestType.SetPolicyTableType(pt_type); + memory_kb.SetPolicyTableType(pt_type); + heart_beat_timeout_ms.SetPolicyTableType(pt_type); +} + +// RpcParameters methods +RpcParameters::RpcParameters() : CompositeType(kUninitialized) {} + +RpcParameters::RpcParameters(const HmiLevels& hmi_levels) + : CompositeType(kUninitialized), hmi_levels(hmi_levels) {} + +RpcParameters::~RpcParameters() {} + +RpcParameters::RpcParameters(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , hmi_levels(impl::ValueMember(value__, "hmi_levels")) + , parameters(impl::ValueMember(value__, "parameters")) {} + +Json::Value RpcParameters::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("hmi_levels", hmi_levels, &result__); + impl::WriteJsonField("parameters", parameters, &result__); + return result__; +} + +bool RpcParameters::is_valid() const { + if (!hmi_levels.is_valid()) { + return false; + } + if (!parameters.is_valid()) { + return false; + } + return Validate(); +} + +bool RpcParameters::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool RpcParameters::struct_empty() const { + if (hmi_levels.is_initialized()) { + return false; + } + if (parameters.is_initialized()) { + return false; + } + return true; +} + +void RpcParameters::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!hmi_levels.is_valid()) { + hmi_levels.ReportErrors(&report__->ReportSubobject("hmi_levels")); + } + if (!parameters.is_valid()) { + parameters.ReportErrors(&report__->ReportSubobject("parameters")); + } +} + +void RpcParameters::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + hmi_levels.SetPolicyTableType(pt_type); + parameters.SetPolicyTableType(pt_type); +} + +// Rpcs methods +Rpcs::Rpcs() : CompositeType(kUninitialized) {} + +Rpcs::Rpcs(const Rpc& rpcs) : CompositeType(kUninitialized), rpcs(rpcs) {} + +Rpcs::~Rpcs() {} + +Rpcs::Rpcs(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , user_consent_prompt(impl::ValueMember(value__, "user_consent_prompt")) + , rpcs(impl::ValueMember(value__, "rpcs")) + , disallowed_by_external_consent_entities_on(impl::ValueMember( + value__, "disallowed_by_external_consent_entities_on")) + , disallowed_by_external_consent_entities_off(impl::ValueMember( + value__, "disallowed_by_external_consent_entities_off")) {} + +Json::Value Rpcs::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("user_consent_prompt", user_consent_prompt, &result__); + impl::WriteJsonField("rpcs", rpcs, &result__); + impl::WriteJsonField("disallowed_by_external_consent_entities_on", + disallowed_by_external_consent_entities_on, + &result__); + impl::WriteJsonField("disallowed_by_external_consent_entities_off", + disallowed_by_external_consent_entities_off, + &result__); + return result__; +} + +bool Rpcs::is_valid() const { + if (!user_consent_prompt.is_valid()) { + return false; + } + if (!rpcs.is_valid()) { + return false; + } + if (!disallowed_by_external_consent_entities_on.is_valid()) { + return false; + } + if (!disallowed_by_external_consent_entities_off.is_valid()) { + return false; + } + return Validate(); +} + +bool Rpcs::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool Rpcs::struct_empty() const { + if (user_consent_prompt.is_initialized()) { + return false; + } + if (rpcs.is_initialized()) { + return false; + } + if (disallowed_by_external_consent_entities_on.is_initialized()) { + return false; + } + if (disallowed_by_external_consent_entities_off.is_initialized()) { + return false; + } + return true; +} + +void Rpcs::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!user_consent_prompt.is_valid()) { + user_consent_prompt.ReportErrors( + &report__->ReportSubobject("user_consent_prompt")); + } + if (!rpcs.is_valid()) { + rpcs.ReportErrors(&report__->ReportSubobject("rpcs")); + } + if (!disallowed_by_external_consent_entities_on.is_valid()) { + disallowed_by_external_consent_entities_on.ReportErrors( + &report__->ReportSubobject( + "disallowed_by_external_consent_entities_on")); + } + if (!disallowed_by_external_consent_entities_off.is_valid()) { + disallowed_by_external_consent_entities_off.ReportErrors( + &report__->ReportSubobject( + "disallowed_by_external_consent_entities_off")); + } +} + +void Rpcs::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + user_consent_prompt.SetPolicyTableType(pt_type); + rpcs.SetPolicyTableType(pt_type); + disallowed_by_external_consent_entities_off.SetPolicyTableType(pt_type); + disallowed_by_external_consent_entities_on.SetPolicyTableType(pt_type); +} + +// ModuleConfig methods +ModuleConfig::ModuleConfig() : CompositeType(kUninitialized) {} + +ModuleConfig::ModuleConfig( + uint8_t exchange_after_x_ignition_cycles, + int64_t exchange_after_x_kilometers, + uint8_t exchange_after_x_days, + uint16_t timeout_after_x_seconds, + const SecondsBetweenRetries& seconds_between_retries, + const ServiceEndpoints& endpoints, + const NumberOfNotificationsPerMinute& notifications_per_minute_by_priority) + : CompositeType(kUninitialized) + , exchange_after_x_ignition_cycles(exchange_after_x_ignition_cycles) + , exchange_after_x_kilometers(exchange_after_x_kilometers) + , exchange_after_x_days(exchange_after_x_days) + , timeout_after_x_seconds(timeout_after_x_seconds) + , seconds_between_retries(seconds_between_retries) + , endpoints(endpoints) + , notifications_per_minute_by_priority( + notifications_per_minute_by_priority) {} + +ModuleConfig::~ModuleConfig() {} + +ModuleConfig::ModuleConfig(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , exchange_after_x_ignition_cycles( + impl::ValueMember(value__, "exchange_after_x_ignition_cycles")) + , exchange_after_x_kilometers( + impl::ValueMember(value__, "exchange_after_x_kilometers")) + , exchange_after_x_days(impl::ValueMember(value__, "exchange_after_x_days")) + , timeout_after_x_seconds( + impl::ValueMember(value__, "timeout_after_x_seconds")) + , seconds_between_retries( + impl::ValueMember(value__, "seconds_between_retries")) + , endpoints(impl::ValueMember(value__, "endpoints")) + , notifications_per_minute_by_priority( + impl::ValueMember(value__, "notifications_per_minute_by_priority")) + , vehicle_make(impl::ValueMember(value__, "vehicle_make")) + , vehicle_model(impl::ValueMember(value__, "vehicle_model")) + , vehicle_year(impl::ValueMember(value__, "vehicle_year")) + , preloaded_date(impl::ValueMember(value__, "preloaded_date")) + , certificate(impl::ValueMember(value__, "certificate")) + , preloaded_pt(impl::ValueMember(value__, "preloaded_pt")) {} + +void ModuleConfig::SafeCopyFrom(const ModuleConfig& from) { + exchange_after_x_days = from.exchange_after_x_days; + exchange_after_x_kilometers = from.exchange_after_x_kilometers; + exchange_after_x_days = from.exchange_after_x_days; + exchange_after_x_ignition_cycles = from.exchange_after_x_ignition_cycles; + timeout_after_x_seconds = from.timeout_after_x_seconds; + seconds_between_retries = from.seconds_between_retries; + endpoints = from.endpoints; + notifications_per_minute_by_priority = + from.notifications_per_minute_by_priority; + + certificate.assign_if_valid(from.certificate); + vehicle_make.assign_if_valid(from.vehicle_make); + vehicle_model.assign_if_valid(from.vehicle_model); + vehicle_year.assign_if_valid(from.vehicle_year); +} + +Json::Value ModuleConfig::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("certificate", certificate, &result__); + impl::WriteJsonField("preloaded_pt", preloaded_pt, &result__); + impl::WriteJsonField("exchange_after_x_ignition_cycles", + exchange_after_x_ignition_cycles, + &result__); + impl::WriteJsonField( + "exchange_after_x_kilometers", exchange_after_x_kilometers, &result__); + impl::WriteJsonField( + "exchange_after_x_days", exchange_after_x_days, &result__); + impl::WriteJsonField( + "timeout_after_x_seconds", timeout_after_x_seconds, &result__); + impl::WriteJsonField( + "seconds_between_retries", seconds_between_retries, &result__); + impl::WriteJsonField("endpoints", endpoints, &result__); + impl::WriteJsonField("notifications_per_minute_by_priority", + notifications_per_minute_by_priority, + &result__); + impl::WriteJsonField("vehicle_make", vehicle_make, &result__); + impl::WriteJsonField("vehicle_model", vehicle_model, &result__); + impl::WriteJsonField("vehicle_year", vehicle_year, &result__); + impl::WriteJsonField("certificate", certificate, &result__); + impl::WriteJsonField("preloaded_date", preloaded_date, &result__); + return result__; +} + +bool ModuleConfig::is_valid() const { + if (!certificate.is_valid()) { + return false; + } + if (!preloaded_pt.is_valid()) { + return false; + } + if (!exchange_after_x_ignition_cycles.is_valid()) { + return false; + } + if (!exchange_after_x_kilometers.is_valid()) { + return false; + } + if (!exchange_after_x_days.is_valid()) { + return false; + } + if (!timeout_after_x_seconds.is_valid()) { + return false; + } + if (!seconds_between_retries.is_valid()) { + return false; + } + if (!endpoints.is_valid()) { + return false; + } + if (!notifications_per_minute_by_priority.is_valid()) { + return false; + } + if (!vehicle_make.is_valid()) { + return false; + } + if (!vehicle_model.is_valid()) { + return false; + } + if (!vehicle_year.is_valid()) { + return false; + } + if (!certificate.is_valid()) { + return false; + } + if (!preloaded_date.is_valid()) { + return false; + } + return Validate(); +} + +bool ModuleConfig::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool ModuleConfig::struct_empty() const { + if (certificate.is_initialized()) { + return false; + } + if (preloaded_pt.is_initialized()) { + return false; + } + + if (exchange_after_x_ignition_cycles.is_initialized()) { + return false; + } + if (exchange_after_x_kilometers.is_initialized()) { + return false; + } + + if (exchange_after_x_days.is_initialized()) { + return false; + } + if (timeout_after_x_seconds.is_initialized()) { + return false; + } + + if (seconds_between_retries.is_initialized()) { + return false; + } + if (endpoints.is_initialized()) { + return false; + } + + if (notifications_per_minute_by_priority.is_initialized()) { + return false; + } + if (vehicle_make.is_initialized()) { + return false; + } + + if (vehicle_model.is_initialized()) { + return false; + } + if (vehicle_year.is_initialized()) { + return false; + } + return true; +} + +void ModuleConfig::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!certificate.is_valid()) { + certificate.ReportErrors(&report__->ReportSubobject("certificate")); + } + if (!preloaded_pt.is_valid()) { + preloaded_pt.ReportErrors(&report__->ReportSubobject("preloaded_pt")); + } + if (!exchange_after_x_ignition_cycles.is_valid()) { + exchange_after_x_ignition_cycles.ReportErrors( + &report__->ReportSubobject("exchange_after_x_ignition_cycles")); + } + if (!exchange_after_x_kilometers.is_valid()) { + exchange_after_x_kilometers.ReportErrors( + &report__->ReportSubobject("exchange_after_x_kilometers")); + } + if (!exchange_after_x_days.is_valid()) { + exchange_after_x_days.ReportErrors( + &report__->ReportSubobject("exchange_after_x_days")); + } + if (!timeout_after_x_seconds.is_valid()) { + timeout_after_x_seconds.ReportErrors( + &report__->ReportSubobject("timeout_after_x_seconds")); + } + if (!seconds_between_retries.is_valid()) { + seconds_between_retries.ReportErrors( + &report__->ReportSubobject("seconds_between_retries")); + } + if (!endpoints.is_valid()) { + endpoints.ReportErrors(&report__->ReportSubobject("endpoints")); + } + if (!notifications_per_minute_by_priority.is_valid()) { + notifications_per_minute_by_priority.ReportErrors( + &report__->ReportSubobject("notifications_per_minute_by_priority")); + } + if (!vehicle_make.is_valid()) { + vehicle_make.ReportErrors(&report__->ReportSubobject("vehicle_make")); + } + if (!vehicle_model.is_valid()) { + vehicle_model.ReportErrors(&report__->ReportSubobject("vehicle_model")); + } + if (!vehicle_year.is_valid()) { + vehicle_year.ReportErrors(&report__->ReportSubobject("vehicle_year")); + } + const std::string validation_info = + omitted_validation_info + PolicyTableTypeToString(GetPolicyTableType()); + + rpc::ValidationReport* omitted_field_report = NULL; + switch (GetPolicyTableType()) { + case PT_PRELOADED: { + if (vehicle_make.is_initialized()) { + omitted_field_report = &report__->ReportSubobject("vehicle_make"); + omitted_field_report->set_validation_info(validation_info); + } + if (vehicle_year.is_initialized()) { + omitted_field_report = &report__->ReportSubobject("vehicle_year"); + omitted_field_report->set_validation_info(validation_info); + } + if (vehicle_model.is_initialized()) { + omitted_field_report = &report__->ReportSubobject("vehicle_model"); + omitted_field_report->set_validation_info(validation_info); + } + break; + } + case PT_UPDATE: { + if (preloaded_pt.is_initialized()) { + omitted_field_report = &report__->ReportSubobject("preloaded_pt"); + omitted_field_report->set_validation_info(validation_info); + } + if (preloaded_date.is_initialized()) { + rpc::ValidationReport& preloaded_pt_omitted_field_report = + report__->ReportSubobject("preloaded_date"); + preloaded_pt_omitted_field_report.set_validation_info(validation_info); + } + break; + } + default: + break; + } +} + +void ModuleConfig::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + certificate.SetPolicyTableType(pt_type); + preloaded_pt.SetPolicyTableType(pt_type); + exchange_after_x_ignition_cycles.SetPolicyTableType(pt_type); + exchange_after_x_kilometers.SetPolicyTableType(pt_type); + exchange_after_x_days.SetPolicyTableType(pt_type); + timeout_after_x_seconds.SetPolicyTableType(pt_type); + seconds_between_retries.SetPolicyTableType(pt_type); + endpoints.SetPolicyTableType(pt_type); + notifications_per_minute_by_priority.SetPolicyTableType(pt_type); + vehicle_make.SetPolicyTableType(pt_type); + vehicle_model.SetPolicyTableType(pt_type); + vehicle_year.SetPolicyTableType(pt_type); +} + +// MessageString methods +MessageString::MessageString() : CompositeType(kUninitialized) {} + +MessageString::~MessageString() {} + +MessageString::MessageString(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , line1(impl::ValueMember(value__, "line1")) + , line2(impl::ValueMember(value__, "line2")) + , tts(impl::ValueMember(value__, "tts")) + , label(impl::ValueMember(value__, "label")) + , textBody(impl::ValueMember(value__, "textBody")) {} + +Json::Value MessageString::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("line1", line1, &result__); + impl::WriteJsonField("line2", line2, &result__); + impl::WriteJsonField("tts", tts, &result__); + impl::WriteJsonField("label", label, &result__); + impl::WriteJsonField("textBody", textBody, &result__); + return result__; +} + +bool MessageString::is_valid() const { + if (struct_empty()) { + return initialization_state__ == kInitialized && Validate(); + } + if (!line1.is_valid()) { + return false; + } + if (!line2.is_valid()) { + return false; + } + if (!tts.is_valid()) { + return false; + } + if (!label.is_valid()) { + return false; + } + if (!textBody.is_valid()) { + return false; + } + return Validate(); +} + +bool MessageString::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool MessageString::struct_empty() const { + if (line1.is_initialized()) { + return false; + } + if (line2.is_initialized()) { + return false; + } + + if (tts.is_initialized()) { + return false; + } + if (label.is_initialized()) { + return false; + } + + if (textBody.is_initialized()) { + return false; + } + return true; +} + +void MessageString::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!line1.is_valid()) { + line1.ReportErrors(&report__->ReportSubobject("line1")); + } + if (!line2.is_valid()) { + line2.ReportErrors(&report__->ReportSubobject("line2")); + } + if (!tts.is_valid()) { + tts.ReportErrors(&report__->ReportSubobject("tts")); + } + if (!label.is_valid()) { + label.ReportErrors(&report__->ReportSubobject("label")); + } + if (!textBody.is_valid()) { + textBody.ReportErrors(&report__->ReportSubobject("textBody")); + } +} + +void MessageString::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + line1.SetPolicyTableType(pt_type); + line2.SetPolicyTableType(pt_type); + tts.SetPolicyTableType(pt_type); + label.SetPolicyTableType(pt_type); + textBody.SetPolicyTableType(pt_type); +} + +// MessageLanguages methods +const std::string MessageLanguages::kMandatoryLanguage_("en-us"); + +MessageLanguages::MessageLanguages() : CompositeType(kUninitialized) {} + +MessageLanguages::MessageLanguages(const Languages& languages) + : CompositeType(kUninitialized), languages(languages) {} + +MessageLanguages::~MessageLanguages() {} + +MessageLanguages::MessageLanguages(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , languages(impl::ValueMember(value__, "languages")) {} + +Json::Value MessageLanguages::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("languages", languages, &result__); + return result__; +} + +bool MessageLanguages::is_valid() const { + if (!languages.is_valid()) { + return false; + } + // Each RPC must have message in english + if (languages.end() == languages.find(kMandatoryLanguage_)) { + return false; + } + return Validate(); +} + +bool MessageLanguages::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool MessageLanguages::struct_empty() const { + if (languages.is_initialized()) { + return false; + } + return true; +} + +void MessageLanguages::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (PT_SNAPSHOT == GetPolicyTableType()) { + if (languages.is_initialized()) { + std::string validation_info = + omitted_validation_info + + PolicyTableTypeToString(GetPolicyTableType()); + report__->ReportSubobject("languages") + .set_validation_info(validation_info); + } + } + if (!languages.is_valid()) { + languages.ReportErrors(&report__->ReportSubobject("languages")); + } + if (languages.end() == languages.find(kMandatoryLanguage_)) { + report__->set_validation_info("no mandatory language '" + + kMandatoryLanguage_ + "' is present"); + } +} + +void MessageLanguages::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + languages.SetPolicyTableType(pt_type); +} + +// ConsumerFriendlyMessages methods +ConsumerFriendlyMessages::ConsumerFriendlyMessages() + : CompositeType(kUninitialized) {} + +ConsumerFriendlyMessages::ConsumerFriendlyMessages(const std::string& version) + : CompositeType(kUninitialized), version(version) {} + +ConsumerFriendlyMessages::~ConsumerFriendlyMessages() {} + +ConsumerFriendlyMessages::ConsumerFriendlyMessages(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , version(impl::ValueMember(value__, "version")) + , messages(impl::ValueMember(value__, "messages")) {} + +Json::Value ConsumerFriendlyMessages::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("version", version, &result__); + // According to requirements, it is not necessary to provide this to PTS + // impl::WriteJsonField("messages", messages, &result__); + return result__; +} + +bool ConsumerFriendlyMessages::is_valid() const { + if (!version.is_valid()) { + return false; + } + if (!messages.is_valid()) { + return false; + } + return Validate(); +} + +bool ConsumerFriendlyMessages::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool ConsumerFriendlyMessages::struct_empty() const { + if (version.is_initialized()) { + return false; + } + if (messages.is_initialized()) { + return false; + } + + return true; +} + +void ConsumerFriendlyMessages::ReportErrors( + rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!version.is_valid()) { + version.ReportErrors(&report__->ReportSubobject("version")); + } + if (PT_SNAPSHOT == GetPolicyTableType()) { + if (messages.is_initialized()) { + std::string validation_info = + omitted_validation_info + + PolicyTableTypeToString(GetPolicyTableType()); + report__->ReportSubobject("messages") + .set_validation_info(validation_info); + } + } + if (!messages.is_valid()) { + messages.ReportErrors(&report__->ReportSubobject("messages")); + } +} + +void ConsumerFriendlyMessages::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + version.SetPolicyTableType(pt_type); + messages.SetPolicyTableType(pt_type); +} + +// ModuleMeta methods +ModuleMeta::ModuleMeta() : CompositeType(kUninitialized) {} + +ModuleMeta::~ModuleMeta() {} + +ModuleMeta::ModuleMeta(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , ccpu_version(impl::ValueMember(value__, "ccpu_version")) + , language(impl::ValueMember(value__, "language")) + , wers_country_code(impl::ValueMember(value__, "wers_country_code")) + , pt_exchanged_at_odometer_x( + impl::ValueMember(value__, "pt_exchanged_at_odometer_x")) + , pt_exchanged_x_days_after_epoch( + impl::ValueMember(value__, "pt_exchanged_x_days_after_epoch")) + , ignition_cycles_since_last_exchange( + impl::ValueMember(value__, "ignition_cycles_since_last_exchange")) + , vin(impl::ValueMember(value__, "vin")) {} + +Json::Value ModuleMeta::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("ccpu_version", ccpu_version, &result__); + impl::WriteJsonField("language", language, &result__); + impl::WriteJsonField("wers_country_code", wers_country_code, &result__); + impl::WriteJsonField( + "pt_exchanged_at_odometer_x", pt_exchanged_at_odometer_x, &result__); + impl::WriteJsonField("pt_exchanged_x_days_after_epoch", + pt_exchanged_x_days_after_epoch, + &result__); + impl::WriteJsonField("ignition_cycles_since_last_exchange", + ignition_cycles_since_last_exchange, + &result__); + impl::WriteJsonField("vin", vin, &result__); + return result__; +} + +bool ModuleMeta::is_valid() const { + if (struct_empty()) { + return initialization_state__ == kInitialized && Validate(); + } + if (!ccpu_version.is_valid()) { + return false; + } + if (!language.is_valid()) { + return false; + } + if (!wers_country_code.is_valid()) { + return false; + } + if (!pt_exchanged_at_odometer_x.is_valid()) { + return false; + } + if (!pt_exchanged_x_days_after_epoch.is_valid()) { + return false; + } + if (!ignition_cycles_since_last_exchange.is_valid()) { + return false; + } + if (!vin.is_valid()) { + return false; + } + return Validate(); +} + +bool ModuleMeta::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool ModuleMeta::struct_empty() const { + if (ccpu_version.is_initialized()) { + return false; + } + if (language.is_initialized()) { + return false; + } + + if (wers_country_code.is_initialized()) { + return false; + } + if (pt_exchanged_at_odometer_x.is_initialized()) { + return false; + } + + if (pt_exchanged_x_days_after_epoch.is_initialized()) { + return false; + } + if (ignition_cycles_since_last_exchange.is_initialized()) { + return false; + } + + if (vin.is_initialized()) { + return false; + } + return true; +} + +void ModuleMeta::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!ccpu_version.is_valid()) { + ccpu_version.ReportErrors(&report__->ReportSubobject("ccpu_version")); + } + if (!language.is_valid()) { + language.ReportErrors(&report__->ReportSubobject("language")); + } + if (!wers_country_code.is_valid()) { + wers_country_code.ReportErrors( + &report__->ReportSubobject("wers_country_code")); + } + if (!pt_exchanged_at_odometer_x.is_valid()) { + pt_exchanged_at_odometer_x.ReportErrors( + &report__->ReportSubobject("pt_exchanged_at_odometer_x")); + } + if (!pt_exchanged_x_days_after_epoch.is_valid()) { + pt_exchanged_x_days_after_epoch.ReportErrors( + &report__->ReportSubobject("pt_exchanged_x_days_after_epoch")); + } + if (!ignition_cycles_since_last_exchange.is_valid()) { + ignition_cycles_since_last_exchange.ReportErrors( + &report__->ReportSubobject("ignition_cycles_since_last_exchange")); + } + if (!vin.is_valid()) { + vin.ReportErrors(&report__->ReportSubobject("vin")); + } + if (GetPolicyTableType() == PT_UPDATE || + GetPolicyTableType() == PT_PRELOADED) { + std::string validation_info = + omitted_validation_info + PolicyTableTypeToString(GetPolicyTableType()); + report__->set_validation_info(validation_info.c_str()); + } +} + +void ModuleMeta::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + ccpu_version.SetPolicyTableType(pt_type); + language.SetPolicyTableType(pt_type); + wers_country_code.SetPolicyTableType(pt_type); + pt_exchanged_at_odometer_x.SetPolicyTableType(pt_type); + pt_exchanged_x_days_after_epoch.SetPolicyTableType(pt_type); + ignition_cycles_since_last_exchange.SetPolicyTableType(pt_type); + vin.SetPolicyTableType(pt_type); +} + +// AppLevel methods +AppLevel::AppLevel() : CompositeType(kUninitialized) {} + +AppLevel::AppLevel(uint16_t minutes_in_hmi_full, + const std::string& app_registration_language_gui, + const std::string& app_registration_language_vui, + uint16_t minutes_in_hmi_limited, + uint16_t minutes_in_hmi_background, + uint16_t minutes_in_hmi_none, + uint16_t count_of_user_selections, + uint16_t count_of_rejections_sync_out_of_memory, + uint16_t count_of_rejections_nickname_mismatch, + uint16_t count_of_rejections_duplicate_name, + uint16_t count_of_rejected_rpc_calls, + uint16_t count_of_rpcs_sent_in_hmi_none, + uint16_t count_of_removals_for_bad_behavior, + uint16_t count_of_tls_errors, + uint16_t count_of_run_attempts_while_revoked) + : CompositeType(kUninitialized) + , minutes_in_hmi_full(minutes_in_hmi_full) + , app_registration_language_gui(app_registration_language_gui) + , app_registration_language_vui(app_registration_language_vui) + , minutes_in_hmi_limited(minutes_in_hmi_limited) + , minutes_in_hmi_background(minutes_in_hmi_background) + , minutes_in_hmi_none(minutes_in_hmi_none) + , count_of_user_selections(count_of_user_selections) + , count_of_rejections_sync_out_of_memory( + count_of_rejections_sync_out_of_memory) + , count_of_rejections_nickname_mismatch( + count_of_rejections_nickname_mismatch) + , count_of_rejections_duplicate_name(count_of_rejections_duplicate_name) + , count_of_rejected_rpc_calls(count_of_rejected_rpc_calls) + , count_of_rpcs_sent_in_hmi_none(count_of_rpcs_sent_in_hmi_none) + , count_of_removals_for_bad_behavior(count_of_removals_for_bad_behavior) + , count_of_tls_errors(count_of_tls_errors) + , count_of_run_attempts_while_revoked(count_of_run_attempts_while_revoked) { +} + +AppLevel::~AppLevel() {} + +AppLevel::AppLevel(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , minutes_in_hmi_full(impl::ValueMember(value__, "minutes_in_hmi_full")) + , app_registration_language_gui( + impl::ValueMember(value__, "app_registration_language_gui")) + , app_registration_language_vui( + impl::ValueMember(value__, "app_registration_language_vui")) + , minutes_in_hmi_limited( + impl::ValueMember(value__, "minutes_in_hmi_limited")) + , minutes_in_hmi_background( + impl::ValueMember(value__, "minutes_in_hmi_background")) + , minutes_in_hmi_none(impl::ValueMember(value__, "minutes_in_hmi_none")) + , count_of_user_selections( + impl::ValueMember(value__, "count_of_user_selections")) + , count_of_rejections_sync_out_of_memory( + impl::ValueMember(value__, "count_of_rejections_sync_out_of_memory")) + , count_of_rejections_nickname_mismatch( + impl::ValueMember(value__, "count_of_rejections_nickname_mismatch")) + , count_of_rejections_duplicate_name( + impl::ValueMember(value__, "count_of_rejections_duplicate_name")) + , count_of_rejected_rpc_calls( + impl::ValueMember(value__, "count_of_rejected_rpc_calls")) + , count_of_rpcs_sent_in_hmi_none( + impl::ValueMember(value__, "count_of_rpcs_sent_in_hmi_none")) + , count_of_removals_for_bad_behavior( + impl::ValueMember(value__, "count_of_removals_for_bad_behavior")) + , count_of_tls_errors(impl::ValueMember(value__, "count_of_tls_errors")) + , count_of_run_attempts_while_revoked( + impl::ValueMember(value__, "count_of_run_attempts_while_revoked")) {} + +Json::Value AppLevel::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("minutes_in_hmi_full", minutes_in_hmi_full, &result__); + impl::WriteJsonField("app_registration_language_gui", + app_registration_language_gui, + &result__); + impl::WriteJsonField("app_registration_language_vui", + app_registration_language_vui, + &result__); + impl::WriteJsonField( + "minutes_in_hmi_limited", minutes_in_hmi_limited, &result__); + impl::WriteJsonField( + "minutes_in_hmi_background", minutes_in_hmi_background, &result__); + impl::WriteJsonField("minutes_in_hmi_none", minutes_in_hmi_none, &result__); + impl::WriteJsonField( + "count_of_user_selections", count_of_user_selections, &result__); + impl::WriteJsonField("count_of_rejections_sync_out_of_memory", + count_of_rejections_sync_out_of_memory, + &result__); + impl::WriteJsonField("count_of_rejections_nickname_mismatch", + count_of_rejections_nickname_mismatch, + &result__); + impl::WriteJsonField("count_of_rejections_duplicate_name", + count_of_rejections_duplicate_name, + &result__); + impl::WriteJsonField( + "count_of_rejected_rpc_calls", count_of_rejected_rpc_calls, &result__); + impl::WriteJsonField("count_of_rpcs_sent_in_hmi_none", + count_of_rpcs_sent_in_hmi_none, + &result__); + impl::WriteJsonField("count_of_removals_for_bad_behavior", + count_of_removals_for_bad_behavior, + &result__); + impl::WriteJsonField("count_of_TLS_errors", count_of_tls_errors, &result__); + impl::WriteJsonField("count_of_run_attempts_while_revoked", + count_of_run_attempts_while_revoked, + &result__); + return result__; +} + +bool AppLevel::is_valid() const { + if (!minutes_in_hmi_full.is_valid()) { + return false; + } + if (!app_registration_language_gui.is_valid()) { + return false; + } + if (!app_registration_language_vui.is_valid()) { + return false; + } + if (!minutes_in_hmi_limited.is_valid()) { + return false; + } + if (!minutes_in_hmi_background.is_valid()) { + return false; + } + if (!minutes_in_hmi_none.is_valid()) { + return false; + } + if (!count_of_user_selections.is_valid()) { + return false; + } + if (!count_of_rejections_sync_out_of_memory.is_valid()) { + return false; + } + if (!count_of_rejections_nickname_mismatch.is_valid()) { + return false; + } + if (!count_of_rejections_duplicate_name.is_valid()) { + return false; + } + if (!count_of_rejected_rpc_calls.is_valid()) { + return false; + } + if (!count_of_rpcs_sent_in_hmi_none.is_valid()) { + return false; + } + if (!count_of_removals_for_bad_behavior.is_valid()) { + return false; + } + if (!count_of_tls_errors.is_valid()) { + return false; + } + if (!count_of_run_attempts_while_revoked.is_valid()) { + return false; + } + return Validate(); +} + +bool AppLevel::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool AppLevel::struct_empty() const { + if (minutes_in_hmi_full.is_initialized()) { + return false; + } + if (app_registration_language_gui.is_initialized()) { + return false; + } + + if (app_registration_language_vui.is_initialized()) { + return false; + } + + if (minutes_in_hmi_limited.is_initialized()) { + return false; + } + if (minutes_in_hmi_background.is_initialized()) { + return false; + } + + if (minutes_in_hmi_none.is_initialized()) { + return false; + } + if (count_of_user_selections.is_initialized()) { + return false; + } + + if (count_of_rejections_sync_out_of_memory.is_initialized()) { + return false; + } + if (count_of_rejections_nickname_mismatch.is_initialized()) { + return false; + } + + if (count_of_rejections_duplicate_name.is_initialized()) { + return false; + } + if (count_of_rejected_rpc_calls.is_initialized()) { + return false; + } + + if (count_of_rpcs_sent_in_hmi_none.is_initialized()) { + return false; + } + if (count_of_removals_for_bad_behavior.is_initialized()) { + return false; + } + if (count_of_tls_errors.is_initialized()) { + return false; + } + if (count_of_run_attempts_while_revoked.is_initialized()) { + return false; + } + return true; +} + +void AppLevel::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!minutes_in_hmi_full.is_valid()) { + minutes_in_hmi_full.ReportErrors( + &report__->ReportSubobject("minutes_in_hmi_full")); + } + if (!app_registration_language_gui.is_valid()) { + app_registration_language_gui.ReportErrors( + &report__->ReportSubobject("app_registration_language_gui")); + } + if (!app_registration_language_vui.is_valid()) { + app_registration_language_vui.ReportErrors( + &report__->ReportSubobject("app_registration_language_vui")); + } + if (!minutes_in_hmi_limited.is_valid()) { + minutes_in_hmi_limited.ReportErrors( + &report__->ReportSubobject("minutes_in_hmi_limited")); + } + if (!minutes_in_hmi_background.is_valid()) { + minutes_in_hmi_background.ReportErrors( + &report__->ReportSubobject("minutes_in_hmi_background")); + } + if (!minutes_in_hmi_none.is_valid()) { + minutes_in_hmi_none.ReportErrors( + &report__->ReportSubobject("minutes_in_hmi_none")); + } + if (!count_of_user_selections.is_valid()) { + count_of_user_selections.ReportErrors( + &report__->ReportSubobject("count_of_user_selections")); + } + if (!count_of_rejections_sync_out_of_memory.is_valid()) { + count_of_rejections_sync_out_of_memory.ReportErrors( + &report__->ReportSubobject("count_of_rejections_sync_out_of_memory")); + } + if (!count_of_rejections_nickname_mismatch.is_valid()) { + count_of_rejections_nickname_mismatch.ReportErrors( + &report__->ReportSubobject("count_of_rejections_nickname_mismatch")); + } + if (!count_of_rejections_duplicate_name.is_valid()) { + count_of_rejections_duplicate_name.ReportErrors( + &report__->ReportSubobject("count_of_rejections_duplicate_name")); + } + if (!count_of_rejected_rpc_calls.is_valid()) { + count_of_rejected_rpc_calls.ReportErrors( + &report__->ReportSubobject("count_of_rejected_rpc_calls")); + } + if (!count_of_rpcs_sent_in_hmi_none.is_valid()) { + count_of_rpcs_sent_in_hmi_none.ReportErrors( + &report__->ReportSubobject("count_of_rpcs_sent_in_hmi_none")); + } + if (!count_of_removals_for_bad_behavior.is_valid()) { + count_of_removals_for_bad_behavior.ReportErrors( + &report__->ReportSubobject("count_of_removals_for_bad_behavior")); + } + if (!count_of_run_attempts_while_revoked.is_valid()) { + count_of_run_attempts_while_revoked.ReportErrors( + &report__->ReportSubobject("count_of_run_attempts_while_revoked")); + } + if (PT_PRELOADED == GetPolicyTableType() || + PT_UPDATE == GetPolicyTableType()) { + std::string validation_info = + omitted_validation_info + PolicyTableTypeToString(GetPolicyTableType()); + report__->set_validation_info(validation_info); + } +} + +void AppLevel::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + app_registration_language_gui.SetPolicyTableType(pt_type); + app_registration_language_vui.SetPolicyTableType(pt_type); + minutes_in_hmi_limited.SetPolicyTableType(pt_type); + minutes_in_hmi_full.SetPolicyTableType(pt_type); + minutes_in_hmi_background.SetPolicyTableType(pt_type); + minutes_in_hmi_none.SetPolicyTableType(pt_type); + count_of_user_selections.SetPolicyTableType(pt_type); + count_of_rejections_sync_out_of_memory.SetPolicyTableType(pt_type); + count_of_rejections_nickname_mismatch.SetPolicyTableType(pt_type); + count_of_rejections_duplicate_name.SetPolicyTableType(pt_type); + count_of_rejected_rpc_calls.SetPolicyTableType(pt_type); + count_of_rpcs_sent_in_hmi_none.SetPolicyTableType(pt_type); + count_of_removals_for_bad_behavior.SetPolicyTableType(pt_type); + count_of_run_attempts_while_revoked.SetPolicyTableType(pt_type); +} + +// UsageAndErrorCounts methods +UsageAndErrorCounts::UsageAndErrorCounts() : CompositeType(kUninitialized) {} + +UsageAndErrorCounts::~UsageAndErrorCounts() {} + +UsageAndErrorCounts::UsageAndErrorCounts(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , count_of_iap_buffer_full( + impl::ValueMember(value__, "count_of_iap_buffer_full")) + , count_sync_out_of_memory( + impl::ValueMember(value__, "count_sync_out_of_memory")) + , count_of_sync_reboots(impl::ValueMember(value__, "count_of_sync_reboots")) + , app_level(impl::ValueMember(value__, "app_level")) {} + +Json::Value UsageAndErrorCounts::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField( + "count_of_iap_buffer_full", count_of_iap_buffer_full, &result__); + impl::WriteJsonField( + "count_sync_out_of_memory", count_sync_out_of_memory, &result__); + impl::WriteJsonField( + "count_of_sync_reboots", count_of_sync_reboots, &result__); + impl::WriteJsonField("app_level", app_level, &result__); + return result__; +} + +bool UsageAndErrorCounts::is_valid() const { + if (struct_empty()) { + return initialization_state__ == kInitialized && Validate(); + } + if (!count_of_iap_buffer_full.is_valid()) { + return false; + } + if (!count_sync_out_of_memory.is_valid()) { + return false; + } + if (!count_of_sync_reboots.is_valid()) { + return false; + } + if (!app_level.is_valid()) { + return false; + } + return Validate(); +} + +bool UsageAndErrorCounts::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool UsageAndErrorCounts::struct_empty() const { + if (count_of_iap_buffer_full.is_initialized()) { + return false; + } + if (count_sync_out_of_memory.is_initialized()) { + return false; + } + + if (count_of_sync_reboots.is_initialized()) { + return false; + } + if (app_level.is_initialized()) { + return false; + } + + return true; +} + +void UsageAndErrorCounts::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (PT_PRELOADED == GetPolicyTableType() || + PT_UPDATE == GetPolicyTableType()) { + std::string validation_info = + omitted_validation_info + PolicyTableTypeToString(GetPolicyTableType()); + report__->set_validation_info(validation_info); + } + if (!count_of_iap_buffer_full.is_valid()) { + count_of_iap_buffer_full.ReportErrors( + &report__->ReportSubobject("count_of_iap_buffer_full")); + } + if (!count_sync_out_of_memory.is_valid()) { + count_sync_out_of_memory.ReportErrors( + &report__->ReportSubobject("count_sync_out_of_memory")); + } + if (!count_of_sync_reboots.is_valid()) { + count_of_sync_reboots.ReportErrors( + &report__->ReportSubobject("count_of_sync_reboots")); + } + if (!app_level.is_valid()) { + app_level.ReportErrors(&report__->ReportSubobject("app_level")); + } +} + +void UsageAndErrorCounts::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + count_of_iap_buffer_full.SetPolicyTableType(pt_type); + count_sync_out_of_memory.SetPolicyTableType(pt_type); + count_of_sync_reboots.SetPolicyTableType(pt_type); + app_level.SetPolicyTableType(pt_type); +} + +// ConsentRecords methods +ConsentRecords::ConsentRecords() + : CompositeType(kUninitialized) + , consent_last_updated(0) + , ext_consent_last_updated(0) {} + +ConsentRecords::~ConsentRecords() {} + +ConsentRecords::ConsentRecords(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , consent_groups(impl::ValueMember(value__, "consent_groups")) + , external_consent_status_groups( + impl::ValueMember(value__, "external_consent_status_groups")) + , input(impl::ValueMember(value__, "input")) + , time_stamp(impl::ValueMember(value__, "time_stamp")) + , consent_last_updated(0) + , ext_consent_last_updated(0) {} + +Json::Value ConsentRecords::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("consent_groups", consent_groups, &result__); + impl::WriteJsonField("external_consent_status_groups", + external_consent_status_groups, + &result__); + impl::WriteJsonField("input", input, &result__); + impl::WriteJsonField("time_stamp", time_stamp, &result__); + return result__; +} + +bool ConsentRecords::is_valid() const { + if (struct_empty()) { + return initialization_state__ == kUninitialized && Validate(); + } + if (!consent_groups.is_valid()) { + return false; + } + if (!external_consent_status_groups.is_valid()) { + return false; + } + if (!input.is_valid()) { + return false; + } + if (!time_stamp.is_valid()) { + return false; + } + return Validate(); +} + +bool ConsentRecords::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool ConsentRecords::struct_empty() const { + if (consent_groups.is_initialized()) { + return false; + } + + if (external_consent_status_groups.is_initialized()) { + return false; + } + if (input.is_initialized()) { + return false; + } + + if (time_stamp.is_initialized()) { + return false; + } + + return true; +} + +void ConsentRecords::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!consent_groups.is_valid()) { + consent_groups.ReportErrors(&report__->ReportSubobject("consent_groups")); + } + if (!external_consent_status_groups.is_valid()) { + external_consent_status_groups.ReportErrors( + &report__->ReportSubobject("external_consent_status_groups")); + } + if (!input.is_valid()) { + input.ReportErrors(&report__->ReportSubobject("input")); + } + if (!time_stamp.is_valid()) { + time_stamp.ReportErrors(&report__->ReportSubobject("time_stamp")); + } +} + +void ConsentRecords::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + consent_groups.SetPolicyTableType(pt_type); + external_consent_status_groups.SetPolicyTableType(pt_type); + input.SetPolicyTableType(pt_type); + time_stamp.SetPolicyTableType(pt_type); +} + +// DeviceParams methods +DeviceParams::DeviceParams() : CompositeType(kUninitialized) {} + +DeviceParams::~DeviceParams() {} + +DeviceParams::DeviceParams(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , hardware(impl::ValueMember(value__, "hardware")) + , firmware_rev(impl::ValueMember(value__, "firmware_rev")) + , os(impl::ValueMember(value__, "os")) + , os_version(impl::ValueMember(value__, "os_version")) + , carrier(impl::ValueMember(value__, "carrier")) + , user_consent_records(impl::ValueMember(value__, "user_consent_records")) + , max_number_rfcom_ports( + impl::ValueMember(value__, "max_number_rfcom_ports")) + , connection_type(impl::ValueMember(value__, "connection_type")) {} + +Json::Value DeviceParams::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("hardware", hardware, &result__); + impl::WriteJsonField("firmware_rev", firmware_rev, &result__); + impl::WriteJsonField("os", os, &result__); + impl::WriteJsonField("os_version", os_version, &result__); + impl::WriteJsonField("carrier", carrier, &result__); + impl::WriteJsonField("user_consent_records", user_consent_records, &result__); + impl::WriteJsonField( + "max_number_rfcom_ports", max_number_rfcom_ports, &result__); + impl::WriteJsonField("connection_type", connection_type, &result__); + return result__; +} + +bool DeviceParams::is_valid() const { + if (struct_empty()) { + return initialization_state__ == kInitialized && Validate(); + } + if (!hardware.is_valid()) { + return false; + } + if (!firmware_rev.is_valid()) { + return false; + } + if (!os.is_valid()) { + return false; + } + if (!os_version.is_valid()) { + return false; + } + if (!carrier.is_valid()) { + return false; + } + if (!user_consent_records.is_valid()) { + return false; + } + if (!max_number_rfcom_ports.is_valid()) { + return false; + } + if (!connection_type.is_valid()) { + return false; + } + return Validate(); +} + +bool DeviceParams::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool DeviceParams::struct_empty() const { + if (hardware.is_initialized()) { + return false; + } + if (firmware_rev.is_initialized()) { + return false; + } + + if (os.is_initialized()) { + return false; + } + if (os_version.is_initialized()) { + return false; + } + + if (carrier.is_initialized()) { + return false; + } + if (user_consent_records.is_initialized()) { + return false; + } + + if (max_number_rfcom_ports.is_initialized()) { + return false; + } + + if (connection_type.is_initialized()) { + return false; + } + return true; +} + +void DeviceParams::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!hardware.is_valid()) { + hardware.ReportErrors(&report__->ReportSubobject("hardware")); + } + if (!firmware_rev.is_valid()) { + firmware_rev.ReportErrors(&report__->ReportSubobject("firmware_rev")); + } + if (!os.is_valid()) { + os.ReportErrors(&report__->ReportSubobject("os")); + } + if (!os_version.is_valid()) { + os_version.ReportErrors(&report__->ReportSubobject("os_version")); + } + if (!carrier.is_valid()) { + carrier.ReportErrors(&report__->ReportSubobject("carrier")); + } + if (!user_consent_records.is_valid()) { + user_consent_records.ReportErrors( + &report__->ReportSubobject("user_consent_records")); + } + if (!max_number_rfcom_ports.is_valid()) { + max_number_rfcom_ports.ReportErrors( + &report__->ReportSubobject("max_number_rfcom_ports")); + } + if (!connection_type.is_valid()) { + connection_type.ReportErrors(&report__->ReportSubobject("connection_type")); + } +} + +void DeviceParams::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + hardware.SetPolicyTableType(pt_type); + firmware_rev.SetPolicyTableType(pt_type); + os.SetPolicyTableType(pt_type); + os_version.SetPolicyTableType(pt_type); + carrier.SetPolicyTableType(pt_type); + user_consent_records.SetPolicyTableType(pt_type); + max_number_rfcom_ports.SetPolicyTableType(pt_type); + connection_type.SetPolicyTableType(pt_type); +} + +// PolicyTable methods +PolicyTable::PolicyTable() : CompositeType(kUninitialized) {} + +PolicyTable::PolicyTable( + const ApplicationPoliciesSection& app_policies_section, + const FunctionalGroupings& functional_groupings, + const ConsumerFriendlyMessages& consumer_friendly_messages, + const ModuleConfig& module_config) + : CompositeType(kUninitialized) + , app_policies_section(app_policies_section) + , functional_groupings(functional_groupings) + , consumer_friendly_messages(consumer_friendly_messages) + , module_config(module_config) {} + +PolicyTable::~PolicyTable() {} + +PolicyTable::PolicyTable(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , app_policies_section(impl::ValueMember(value__, "app_policies")) + , functional_groupings(impl::ValueMember(value__, "functional_groupings")) + , consumer_friendly_messages( + impl::ValueMember(value__, "consumer_friendly_messages")) + , module_config(impl::ValueMember(value__, "module_config")) + , module_meta(impl::ValueMember(value__, "module_meta")) + , usage_and_error_counts( + impl::ValueMember(value__, "usage_and_error_counts")) + , device_data(impl::ValueMember(value__, "device_data")) {} + +Json::Value PolicyTable::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("app_policies", app_policies_section, &result__); + impl::WriteJsonField("functional_groupings", functional_groupings, &result__); + impl::WriteJsonField( + "consumer_friendly_messages", consumer_friendly_messages, &result__); + impl::WriteJsonField("module_config", module_config, &result__); + impl::WriteJsonField("module_meta", module_meta, &result__); + impl::WriteJsonField( + "usage_and_error_counts", usage_and_error_counts, &result__); + impl::WriteJsonField("device_data", device_data, &result__); + return result__; +} + +bool PolicyTable::is_valid() const { + if (!app_policies_section.is_valid()) { + return false; + } + if (!functional_groupings.is_valid()) { + return false; + } + if (!consumer_friendly_messages.is_valid()) { + return false; + } + if (!module_config.is_valid()) { + return false; + } + if (!module_meta.is_valid()) { + return false; + } + if (!usage_and_error_counts.is_valid()) { + return false; + } + if (!device_data.is_valid()) { + return false; + } + return Validate(); +} + +bool PolicyTable::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool PolicyTable::struct_empty() const { + if (app_policies_section.is_initialized()) { + return false; + } + if (functional_groupings.is_initialized()) { + return false; + } + + if (consumer_friendly_messages.is_initialized()) { + return false; + } + if (module_config.is_initialized()) { + return false; + } + + if (module_meta.is_initialized()) { + return false; + } + if (usage_and_error_counts.is_initialized()) { + return false; + } + + if (device_data.is_initialized()) { + return false; + } + return true; +} + +void PolicyTable::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (PT_PRELOADED == GetPolicyTableType() || + PT_UPDATE == GetPolicyTableType()) { + std::string validation_info = + omitted_validation_info + PolicyTableTypeToString(GetPolicyTableType()); + + if (device_data.is_initialized()) { + report__->ReportSubobject("device_data") + .set_validation_info(validation_info); + } + } + if (!app_policies_section.is_valid()) { + app_policies_section.ReportErrors( + &report__->ReportSubobject("app_policies")); + } + if (!functional_groupings.is_valid()) { + functional_groupings.ReportErrors( + &report__->ReportSubobject("functional_groupings")); + } + if (!consumer_friendly_messages.is_valid()) { + consumer_friendly_messages.ReportErrors( + &report__->ReportSubobject("consumer_friendly_messages")); + } + if (!module_config.is_valid()) { + module_config.ReportErrors(&report__->ReportSubobject("module_config")); + } + if (!module_meta.is_valid()) { + module_meta.ReportErrors(&report__->ReportSubobject("module_meta")); + } + if (!usage_and_error_counts.is_valid()) { + usage_and_error_counts.ReportErrors( + &report__->ReportSubobject("usage_and_error_counts")); + } + if (!device_data.is_valid()) { + device_data.ReportErrors(&report__->ReportSubobject("device_data")); + } +} + +void PolicyTable::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + app_policies_section.SetPolicyTableType(pt_type); + functional_groupings.SetPolicyTableType(pt_type); + consumer_friendly_messages.SetPolicyTableType(pt_type); + module_config.SetPolicyTableType(pt_type); + module_meta.SetPolicyTableType(pt_type); + usage_and_error_counts.SetPolicyTableType(pt_type); + device_data.SetPolicyTableType(pt_type); +} + +// Table methods +Table::Table() : CompositeType(kUninitialized) {} + +Table::Table(const PolicyTable& policy_table) + : CompositeType(kUninitialized), policy_table(policy_table) {} + +Table::~Table() {} + +Table::Table(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , policy_table(impl::ValueMember(value__, "policy_table")) {} + +Json::Value Table::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("policy_table", policy_table, &result__); + return result__; +} + +bool Table::is_valid() const { + if (!policy_table.is_valid()) { + return false; + } + return Validate(); +} + +bool Table::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool Table::struct_empty() const { + if (policy_table.is_initialized()) { + return false; + } + return true; +} + +void Table::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!policy_table.is_valid()) { + policy_table.ReportErrors(&report__->ReportSubobject("policy_table")); + } +} + +void Table::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + policy_table.SetPolicyTableType(pt_type); +} + +RequestTypes::RequestTypes() : RequestsTypeArray(), is_cleaned_up_(false) {} + +RequestTypes::RequestTypes(Json::Value* value) + : RequestsTypeArray(value), is_cleaned_up_(false) {} + +RequestTypes::RequestTypes(const Json::Value* value) + : RequestsTypeArray(value), is_cleaned_up_(false) {} + +void RequestTypes::CleanUp() { + if (!this->size()) { + return; + } + this->erase( + std::remove_if( + this->begin(), + this->end(), + std::not1(std::mem_fun_ref(&RequestTypes::value_type::is_valid))), + this->end()); + + is_cleaned_up_ = !this->size(); +} + +bool RequestTypes::is_valid() const { + // Array size must be within allowed range + if (!Range<size_t>(0, 255).Includes(this->size())) { + return false; + } + RequestTypes::const_iterator it = std::find_if( + this->begin(), + this->end(), + std::not1(std::mem_fun_ref(&RequestTypes::value_type::is_valid))); + if (this->end() != it) { + return false; + } + return true; +} + +bool RequestTypes::is_omitted() const { + return this->empty() && !this->is_initialized(); +} + +bool RequestTypes::is_empty() const { + return this->empty() && this->is_initialized(); +} + +bool RequestTypes::is_cleaned_up() const { + return is_cleaned_up_; +} + +ExternalConsentEntity::ExternalConsentEntity() + : CompositeType(kUninitialized) + , entity_type(INT32_MAX) + , entity_id(INT32_MAX) {} + +ExternalConsentEntity::ExternalConsentEntity(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , entity_type(impl::ValueMember(value__, "entityType")) + , entity_id(impl::ValueMember(value__, "entityID")) {} + +ExternalConsentEntity::ExternalConsentEntity(const int32_t type, + const int32_t id) + : CompositeType(kInitialized), entity_type(type), entity_id(id) {} + +Json::Value ExternalConsentEntity::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("entityType", entity_type, &result__); + impl::WriteJsonField("entityID", entity_id, &result__); + return result__; +} + +bool ExternalConsentEntity::operator==(const ExternalConsentEntity& rhs) const { + return rhs.entity_id == this->entity_id && + rhs.entity_type == this->entity_type; +} + +bool ExternalConsentEntity::is_valid() const { + if (!is_initialized()) { + return false; + } + if (!entity_type.is_valid()) { + return false; + } + if (!entity_id.is_valid()) { + return false; + } + return true; +} + +bool ExternalConsentEntity::is_initialized() const { + return kInitialized == initialization_state__; +} + +void ExternalConsentEntity::ReportErrors(ValidationReport* report__) const { + if (!entity_type.is_valid()) { + entity_type.ReportErrors(&report__->ReportSubobject("entityType")); + } + if (!entity_id.is_valid()) { + entity_id.ReportErrors(&report__->ReportSubobject("entityID")); + } +} + +void ExternalConsentEntity::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + entity_type.SetPolicyTableType(pt_type); + entity_id.SetPolicyTableType(pt_type); +} + +} // namespace policy_table_interface_base +} // namespace rpc diff --git a/src/components/policy/policy_external/src/policy_table/validation.cc b/src/components/policy/policy_external/src/policy_table/validation.cc new file mode 100644 index 0000000000..45034c6fe8 --- /dev/null +++ b/src/components/policy/policy_external/src/policy_table/validation.cc @@ -0,0 +1,256 @@ +#include <iostream> +#include <algorithm> +#include "policy/policy_table/types.h" +#include "utils/logger.h" +#include "utils/helpers.h" + +namespace { +bool IsPredefinedApplication(const std::string& app_id) { + using namespace rpc::policy_table_interface_base; + return kPreDataConsentApp == app_id || kDefaultApp == app_id; +} +} + +namespace rpc { +namespace policy_table_interface_base { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +bool VerifyPredefinedApp(ApplicationPolicies::value_type& app_policies) { + const std::string& app_id = app_policies.first; + if (!IsPredefinedApplication(app_id)) { + return true; + } + + RequestTypes& predefined_request_types = *app_policies.second.RequestType; + + if (!predefined_request_types.is_valid()) { + LOG4CXX_WARN(logger_, + app_id << " policy invalid RequestTypes will be cleaned."); + predefined_request_types.CleanUp(); + if (PT_PRELOADED == app_policies.second.GetPolicyTableType() && + predefined_request_types.is_cleaned_up()) { + LOG4CXX_ERROR( + logger_, + app_id << " policy RequestTypes is empty after clean-up. Exiting."); + return false; + } + + LOG4CXX_WARN(logger_, app_id << " request types have cleaned up."); + } + return true; +} + +bool PolicyBase::Validate() const { + // Check for empty "groups" sub-sections + if (groups.empty()) { + return false; + } + return true; +} + +bool ApplicationPoliciesSection::Validate() const { + ApplicationPolicies::iterator it_default_policy = apps.find(kDefaultApp); + ApplicationPolicies::iterator it_pre_data_policy = + apps.find(kPreDataConsentApp); + + // Default and PreData policies are mandatory + if (apps.end() == it_default_policy || apps.end() == it_pre_data_policy) { + LOG4CXX_ERROR(logger_, "Default or preData policy is not present."); + return false; + } + + // Device policy is mandatory + if (!device.is_initialized()) { + LOG4CXX_ERROR(logger_, "Device policy is not present."); + return false; + } + + PolicyTableType pt_type = GetPolicyTableType(); + if (PT_PRELOADED != pt_type && PT_UPDATE != pt_type) { + return true; + } + + if (!VerifyPredefinedApp(*it_default_policy)) { + return false; + } + + if (!VerifyPredefinedApp(*it_pre_data_policy)) { + return false; + } + + ApplicationPolicies::iterator iter = apps.begin(); + ApplicationPolicies::iterator end_iter = apps.end(); + + while (iter != end_iter) { + const std::string app_id = iter->first; + if (IsPredefinedApplication(app_id)) { + ++iter; + continue; + } + + RequestTypes& app_request_types = *iter->second.RequestType; + + if (app_request_types.is_omitted()) { + LOG4CXX_WARN(logger_, + "RequestTypes omitted for " + << app_id << " Will be replaced with default."); + app_request_types = *apps[kDefaultApp].RequestType; + ++iter; + continue; + } + + if (!app_request_types.is_valid()) { + LOG4CXX_WARN(logger_, + "Invalid RequestTypes for " << app_id + << " Will be cleaned up."); + app_request_types.CleanUp(); + if (app_request_types.is_cleaned_up()) { + if (PT_PRELOADED == pt_type) { + LOG4CXX_ERROR(logger_, + "RequestTypes empty after clean-up for " + << app_id << " Exiting."); + return false; + } + + LOG4CXX_WARN(logger_, + "RequestTypes empty after clean-up for " + << app_id << " Will be replaced with default."); + + app_request_types = *apps[kDefaultApp].RequestType; + } + + LOG4CXX_DEBUG(logger_, "Clean up for " << app_id << " is done."); + + ++iter; + continue; + } + + if (app_request_types.is_empty()) { + LOG4CXX_WARN(logger_, "RequestTypes is empty for " << app_id); + } + + ++iter; + } + + return true; +} +bool ApplicationParams::Validate() const { + if (is_initialized()) { + if (preconsented_groups.is_initialized()) { + const Strings& all = groups; + const Strings& preconsented = *preconsented_groups; + if (preconsented.size() > all.size()) { + return false; + } + } + } + return true; +} +bool RpcParameters::Validate() const { + return true; +} +bool Rpcs::Validate() const { + return true; +} +bool ModuleConfig::Validate() const { + switch (GetPolicyTableType()) { + case PT_PRELOADED: { + if (helpers::Compare<bool, helpers::EQ, helpers::ONE>( + true, + vehicle_make.is_initialized(), + vehicle_year.is_initialized(), + vehicle_model.is_initialized())) { + return false; + } + break; + } + case PT_UPDATE: { + if (preloaded_pt->is_initialized()) { + return false; + } + if (preloaded_date->is_initialized()) { + return false; + } + break; + } + default: + break; + } + return true; +} + +bool MessageString::Validate() const { + return true; +} +bool MessageLanguages::Validate() const { + if (PT_SNAPSHOT == GetPolicyTableType()) { + return false; + } + return true; +} +bool ConsumerFriendlyMessages::Validate() const { + return true; +} +bool ModuleMeta::Validate() const { + if (GetPolicyTableType() == PT_UPDATE || + GetPolicyTableType() == PT_PRELOADED) { + return false; + } + return true; +} +bool AppLevel::Validate() const { + if (PT_PRELOADED == GetPolicyTableType() || + PT_UPDATE == GetPolicyTableType()) { + return false; + } + return true; +} +bool UsageAndErrorCounts::Validate() const { + if (PT_PRELOADED == GetPolicyTableType() || + PT_UPDATE == GetPolicyTableType()) { + return false; + } + return true; +} +bool ConsentRecords::Validate() const { + if (PT_SNAPSHOT != GetPolicyTableType()) { + return !external_consent_status_groups->is_initialized(); + } + + return true; +} +bool DeviceParams::Validate() const { + return true; +} +bool PolicyTable::Validate() const { + PolicyTableType policy_table_type = GetPolicyTableType(); + + if (PT_PRELOADED == policy_table_type || PT_UPDATE == policy_table_type) { + if (device_data.is_initialized()) { + return false; + } + } + + if (PT_PRELOADED == policy_table_type || PT_SNAPSHOT == policy_table_type) { + // Check upper bound of each "groups" sub section in the app policies + const FunctionalGroupings::size_type functional_groupings_count = + functional_groupings.size(); + for (ApplicationPolicies::const_iterator app_policiies_it = + app_policies_section.apps.begin(); + app_policies_section.apps.end() != app_policiies_it; + ++app_policiies_it) { + if (app_policiies_it->second.groups.size() > functional_groupings_count) { + return false; + } + } + } + + return true; +} + +bool Table::Validate() const { + return true; +} +} // namespace policy_table_interface_base +} // namespace rpc diff --git a/src/components/policy/policy_external/src/sql_pt_ext_queries.cc b/src/components/policy/policy_external/src/sql_pt_ext_queries.cc new file mode 100644 index 0000000000..afb1180692 --- /dev/null +++ b/src/components/policy/policy_external/src/sql_pt_ext_queries.cc @@ -0,0 +1,299 @@ +/* + Copyright (c) 2013, " Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, " with or without + modification, " are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, " this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, " + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, " INCLUDING, " BUT NOT LIMITED TO, " THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, " INDIRECT, " INCIDENTAL, " SPECIAL, " EXEMPLARY, " OR + CONSEQUENTIAL DAMAGES (INCLUDING, " BUT NOT LIMITED TO, " PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, " DATA, " OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, " WHETHER IN + CONTRACT, " STRICT LIABILITY, " OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, " EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include "policy/sql_pt_ext_queries.h" + +namespace policy { +namespace sql_pt_ext { + +const std::string kSelectKeepContext = + "SELECT `keep_context` FROM `application` WHERE `id` = ? LIMIT 1"; + +const std::string kSelectStealFocus = + "SELECT `steal_focus` FROM `application` WHERE `id` = ? LIMIT 1"; + +const std::string kSelectDefaultHmi = + "SELECT `default_hmi` FROM `application` WHERE `id` = ? LIMIT 1"; + +const std::string kResetDeviceConsents = "DELETE FROM `device_consent_group`"; + +const std::string kResetAppConsents = "DELETE FROM `consent_group`"; + +const std::string kCountDeviceConsentGroup = + "SELECT COUNT (`device_id`) " + "FROM `device_consent_group` WHERE `device_id` = ?"; + +const std::string kCountDevice = + "SELECT COUNT (`id`) " + "FROM `device` WHERE `id` = ?"; + +const std::string kSelectDeviceConsentedGroup = + "SELECT * FROM `device_consent_group` WHERE `device_id` = ?"; + +const std::string kUpdateDeviceConsentedGroup = + "UPDATE `device_consent_group` SET `is_consented` = ?, `input` = ? WHERE " + "(`device_id` = ? AND `functional_group_id` = ?)"; + +const std::string kUpdateDevice = + "UPDATE `device` SET `hardware` = ?, `firmware_rev` = ?, `os` = ?, " + "`os_version` = ?, `carrier` = ?, `max_number_rfcom_ports` = ?, " + " `connection_type` = ? WHERE `id` = ? "; + +const std::string kInsertDeviceConsentedGroup = + "INSERT OR REPLACE INTO `device_consent_group` " + "(`device_id`, `functional_group_id`, `is_consented`, `input`, " + "`time_stamp`) " + "VALUES (?,?,?,?,?)"; + +const std::string kInsertDevice = + "INSERT OR IGNORE INTO `device` " + "(`id`, `hardware`, `firmware_rev`, `os`, `os_version`, `carrier`," + "`max_number_rfcom_ports`, `connection_type`) " + "VALUES (?,?,?,?,?,?,?,?)"; + +const std::string kSelectDeviceData = "SELECT * FROM `device`"; + +const std::string kSelectConsentGroup = + "SELECT * FROM `consent_group` WHERE `device_id` = ? "; + +const std::string kSelectExternalConsentStatusGroup = + "SELECT * FROM `external_consent_status_group` WHERE `device_id` = ? "; + +const std::string kInsertPreconsentedGroups = + "INSERT INTO `preconsented_group` (`application_id`, `functional_group_id`)" + " SELECT ?, `id` FROM `functional_group` WHERE `name` = ? LIMIT 1"; + +const std::string kSelectPreconsentedGroups = + "SELECT `f`.`name` FROM `preconsented_group` AS `p`" + " LEFT JOIN `functional_group` AS `f` " + " ON (`f`.`id` = `p`.`functional_group_id`)" + " WHERE `p`.`application_id` = ?"; + +const std::string kDeletePreconsentedGroups = + "DELETE FROM `preconsented_group`"; + +const std::string kSelectUsageAndErrorCount = + "SELECT `count_of_iap_buffer_full`, `count_sync_out_of_memory`, " + " `count_of_sync_reboots` " + "FROM `usage_and_error_count` LIMIT 1"; + +const std::string kSelectAppLevels = + "SELECT `application_id`, `minutes_in_hmi_full`, `minutes_in_hmi_limited`, " + " `minutes_in_hmi_background`, `minutes_in_hmi_none`, " + " `count_of_user_selections`, " + " `count_of_rejections_sync_out_of_memory`, " + " `count_of_rejections_nickname_mismatch`, " + " `count_of_rejections_duplicate_name`, " + " `count_of_rejected_rpcs_calls`, " + " `count_of_rpcs_sent_in_hmi_none`, " + " `count_of_removals_for_bad_behavior`, " + " `count_of_run_attempts_while_revoked`, " + " `app_registration_language_gui`, " + " `app_registration_language_vui`, " + " `count_of_tls_errors` " + "FROM `app_level`"; + +const std::string kUpdateGlobalCounters = + "UPDATE `usage_and_error_count` SET " + "`count_of_iap_buffer_full` = ?, " + "`count_sync_out_of_memory` = ?, " + "`count_of_sync_reboots` = ? "; + +const std::string kInsertDeviceData = + "INSERT OR IGNORE INTO `device` " + "(`id`, `hardware`, `firmware_rev`, `os`, `os_version`, `carrier`, " + "`max_number_rfcom_ports`,`connection_type`) VALUES (?,?,?,?,?,?,?,?) "; + +const std::string kInsertConsentGroups = + "INSERT OR REPLACE INTO `consent_group` " + "(`device_id`, `application_id`, `functional_group_id`, `is_consented`, " + "`input`, `time_stamp`, `last_updated`) " + "VALUES (?,?,?,?,?,?,?)"; + +const std::string kInsertExternalConsentStatusGroups = + "INSERT OR REPLACE INTO `external_consent_status_group` " + "(`device_id`, `application_id`, `functional_group_id`, `is_consented`, " + "`input`, `time_stamp`, `last_updated`) " + "VALUES (?,?,?,?,?,?,?)"; + +const std::string kDeleteAppGroupConsent = + "DELETE FROM `consent_group` WHERE " + "`application_id` = ? AND `functional_group_id` = ? "; + +const std::string kSelectGroupId = + "SELECT `id` FROM `functional_group` WHERE `name` = ? "; + +const std::string kCountUnconsentedGroups = + "SELECT COUNT(`a`.`functional_group_id`) FROM `app_group` AS `a` " + " WHERE `a`.`application_id` = ? AND NOT EXISTS " + " (SELECT NULL FROM `preconsented_group` AS `p` WHERE " + " (`p`.`functional_group_id` = `a`.`functional_group_id` AND " + " `p`.`application_id` = `a`.`application_id`)) " + " AND NOT EXISTS (SELECT NULL FROM `consent_group` AS `c` " + " WHERE (`c`.`application_id` = `a`.`application_id` " + " AND `c`.`functional_group_id` = `a`.`functional_group_id` " + " AND `c`.`device_id` = ?)) AND NOT EXISTS " + " (SELECT NULL FROM `app_group` AS `def` WHERE " + " (`def`.`application_id` = ? OR " + " `def`.`application_id` = ?) " + " AND `def`.`functional_group_id` = `a`.`functional_group_id`)" + " AND NOT EXISTS (SELECT NULL FROM `functional_group` AS `f` " + " WHERE (`a`.`functional_group_id` = `f`.`id`" + " AND`f`.`user_consent_prompt` IS NULL))"; + +const std::string kSelectModuleMeta = "SELECT* FROM `module_meta`"; + +const std::string kUpdateMetaParams = + "UPDATE `module_meta` SET " + "`ccpu_version` = ?, `wers_country_code` = ?, `language` = ? "; + +const std::string kUpdateModuleMetaVinParam = + "UPDATE `module_meta` SET `vin` = ? "; + +const std::string kSaveModuleMeta = + "UPDATE `module_meta` SET `ccpu_version` = ?, `language` = ?," + "`wers_country_code` = ?, `pt_exchanged_at_odometer_x` = ?," + "`pt_exchanged_x_days_after_epoch` = ?," + "`ignition_cycles_since_last_exchange` = ?, `vin` = ?"; + +const std::string kSelectMetaParams = + "SELECT `ccpu_version`, " + "`wers_country_code`, `language` from `module_meta`"; + +const std::string kUpdateMetaLanguage = + "UPDATE `module_meta` SET `language` = ? "; + +const std::string kCountAppLevel = + "SELECT COUNT(`application_id`) FROM `app_level`" + " WHERE `application_id` = ? "; + +const std::string kUpdateGroupPermissions = + "UPDATE `consent_group` " + "SET `is_consented` = ?, `input` = ? " + "WHERE(`application_id` = ? AND `functional_group_id` = ? AND `device_id` " + "= ?) "; + +const std::string kInsertApplication = + "INSERT OR IGNORE INTO `application`(`id`, `keep_context`, `steal_focus`, " + " `default_hmi`, `priority_value`, `is_revoked`, `memory_kb`, " + " `heart_beat_timeout_ms`) VALUES( ?, ?, ?, ?, ?, ?, ?, ?) "; + +const std::string kCollectFriendlyMsg = "SELECT * FROM `message`"; + +const std::string kSelectFriendlyMsg = + "SELECT `tts`, `label`, `line1`, `line2`, `textBody` FROM `message` " + "WHERE `message_type_name` = ? AND `language_code` = ? LIMIT 1"; + +const std::string kSelectAppGroupsId = + "SELECT `functional_group_id` " + "FROM `app_group` WHERE `application_id` = ? "; + +const std::string kSelectConsentedGroupsId = + "SELECT `functional_group_id`, `is_consented` " + "FROM `consent_group` WHERE(`application_id` = ? AND `device_id` = ?) "; + +const std::string kCountAppConsents = + "SELECT COUNT(*) from `consent_group`" + "WHERE(`device_id` = ? AND `application_id` = ? AND " + "`functional_group_id` = ?) "; + +const std::string kSelectPreconsentedGroupsId = + "SELECT `functional_group_id` " + "FROM `preconsented_group` WHERE `application_id` = ? "; + +const std::string kSelectAppPolicies = + "SELECT `id`, `priority_value`, `default_hmi`, `keep_context`, " + "`steal_focus`, " + " `memory_kb`, `heart_beat_timeout_ms` FROM `application`"; + +const std::string kSelectFunctionalGroupNames = + "SELECT `id`, `user_consent_prompt`, `name`" + " FROM `functional_group`"; + +const std::string kDeleteDeviceConsent = + "DELETE FROM `device_consent_group` " + "WHERE `device_id` = ? "; + +const std::string kDeleteAppConsent = + "DELETE FROM `consent_group` " + "WHERE `device_id` = ? "; + +const std::string kSelectApplicationIsPreData = + "SELECT `is_predata` FROM `application` WHERE `id` = ? "; + +const std::string kUpdateIsPredata = + "UPDATE `application` SET `is_predata` = ? WHERE `id` = ? "; + +const std::string kHasAppPreloadedGroups = + "SELECT COUNT(`a1`.`functional_group_id`) FROM `app_group` " + " AS `a1` JOIN `app_group` AS `a2` " + " ON `a1`.`functional_group_id` = `a2`.`functional_group_id` " + " WHERE `a1`.`application_id` = ? AND `a2`.`application_id` = ? "; + +const std::string kUpdateUnpairedDevice = + "UPDATE `device` SET `unpaired` = ? WHERE `id` = ? "; + +const std::string kSelectUnpairedDevices = + "SELECT `id` FROM `device` WHERE `unpaired` = 1"; + +const std::string kHasMsgLanguageCode = + "SELECT COUNT (`id`) FROM message " + "WHERE `message_type_name` = ? AND `language_code` = ? "; + +const std::string kDeletePreconsentedGroupsByApplicationId = + "DELETE FROM `preconsented_group` WHERE `application_id` = ?"; + +const std::string kSelectExternalConsentStatus = + "SELECT `entity_type`, `entity_id`, `on_off` from " + "`_internal_external_consent_status`"; + +const std::string kInsertExternalConsentStatus = + "INSERT OR REPLACE INTO `_internal_external_consent_status` " + "(`id`,`entity_type`, " + "`entity_id`, `on_off`) VALUES ((SELECT `id` from " + "`_internal_external_consent_status` " + "WHERE `entity_type` = ? AND `entity_id` = ?), ?, ?, ?)"; + +const std::string kDeleteExternalConsentEntities = + "DELETE FROM `external_consent_entities`"; + +const std::string kInsertExternalConsentEntity = + "INSERT INTO `external_consent_entities` (`group_id`, `entity_type`, " + "`entity_id`, `on_off`) " + " VALUES (?, ?, ?, ?)"; + +const std::string kSelectExternalConsentEntity = + "SELECT `group_id`, `entity_type`, `entity_id`, `on_off` from " + "`external_consent_entities`"; + +} // namespace sql_pt_ext +} // namespace policy diff --git a/src/components/policy/policy_external/src/sql_pt_ext_representation.cc b/src/components/policy/policy_external/src/sql_pt_ext_representation.cc new file mode 100644 index 0000000000..f58a7f0b82 --- /dev/null +++ b/src/components/policy/policy_external/src/sql_pt_ext_representation.cc @@ -0,0 +1,1937 @@ +/* + Copyright (c) 2015, Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ +#include <algorithm> +#include <utility> +#include "utils/logger.h" +#include "policy/sql_pt_ext_representation.h" +#include "policy/sql_wrapper.h" +#include "policy/sql_pt_queries.h" +#include "policy/sql_pt_ext_queries.h" +#include "policy/policy_helper.h" +#include "policy/cache_manager.h" + +namespace policy { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +SQLPTExtRepresentation::SQLPTExtRepresentation() {} +SQLPTExtRepresentation::SQLPTExtRepresentation(bool in_memory) + : SQLPTRepresentation(in_memory) {} + +bool SQLPTExtRepresentation::CanAppKeepContext(const std::string& app_id) { + utils::dbms::SQLQuery query(db()); + if (query.Prepare(sql_pt_ext::kSelectKeepContext)) { + query.Bind(0, app_id); + if (query.Exec()) { + return query.GetBoolean(0); + } + } + return false; +} + +bool SQLPTExtRepresentation::CanAppStealFocus(const std::string& app_id) { + utils::dbms::SQLQuery query(db()); + if (query.Prepare(sql_pt_ext::kSelectStealFocus)) { + query.Bind(0, app_id); + if (query.Exec()) { + return query.GetBoolean(0); + } + } + return false; +} + +bool SQLPTExtRepresentation::ResetUserConsent() { + return ResetDeviceConsents() && ResetAppConsents(); +} + +bool SQLPTExtRepresentation::ResetDeviceConsents() { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kResetDeviceConsents)) { + LOG4CXX_WARN(logger_, "Incorrect delete statement from device_consents."); + return false; + } + return query.Exec(); +} + +bool SQLPTExtRepresentation::ResetAppConsents() { + return utils::dbms::SQLQuery(db()).Exec(sql_pt_ext::kResetAppConsents); +} + +bool SQLPTExtRepresentation::GetUserPermissionsForDevice( + const std::string& device_id, + StringArray* consented_groups, + StringArray* disallowed_groups) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectDeviceConsentedGroup)) { + LOG4CXX_WARN(logger_, "Incorrect select from device consented groups"); + return false; + } + query.Bind(0, device_id); + while (query.Next()) { + if (query.GetBoolean(2)) { + if (!consented_groups) { + continue; + } + consented_groups->push_back(query.GetString(1)); + } else { + if (!disallowed_groups) { + continue; + } + disallowed_groups->push_back(query.GetString(1)); + } + } + + return true; +} + +bool SQLPTExtRepresentation::GetPermissionsForApp( + const std::string& device_id, + const std::string& policy_app_id, + FunctionalIdType* group_types) { + LOG4CXX_AUTO_TRACE(logger_); + if (!group_types) { + LOG4CXX_WARN(logger_, "Input parameter for group types is null."); + return false; + } + // Get all app groups for specified device and application + FunctionalGroupIDs all_groups; + if (!GetAllAppGroups(policy_app_id, all_groups)) { + return false; + } + // Get preconsented group + FunctionalGroupIDs preconsented_groups; + if (!GetPreconsentedGroups(policy_app_id, preconsented_groups)) { + return false; + } + // Get consented (allowed/disallowed) groups + FunctionalGroupIDs allowed_groups; + FunctionalGroupIDs disallowed_groups; + if (!GetConsentedGroups( + policy_app_id, device_id, allowed_groups, disallowed_groups)) { + return false; + } + // Get all default groups + FunctionalGroupIDs default_groups; + if (!GetAllAppGroups(kDefaultId, default_groups)) { + return false; + } + + // Get all pre_DataConsent groups + FunctionalGroupIDs predataconsented_groups; + if (!GetAllAppGroups(kPreDataConsentId, predataconsented_groups)) { + return false; + } + + // Get all device groups + FunctionalGroupIDs device_groups; + if (!GetAllAppGroups(kDeviceId, device_groups)) { + return false; + } + + (*group_types)[kTypeDefault] = default_groups; + (*group_types)[kTypeAllowed] = allowed_groups; + (*group_types)[kTypeDisallowed] = disallowed_groups; + (*group_types)[kTypePreconsented] = preconsented_groups; + (*group_types)[kTypeGeneral] = all_groups; + (*group_types)[kTypePreDataConsented] = predataconsented_groups; + (*group_types)[kTypeDevice] = device_groups; + + return true; +} + +bool SQLPTExtRepresentation::GetDeviceGroupsFromPolicies( + policy_table::Strings* groups, policy_table::Strings* preconsented_groups) { + LOG4CXX_AUTO_TRACE(logger_); + if (groups) { + GatherAppGroup(kDeviceId, groups); + } + if (preconsented_groups) { + GatherPreconsentedGroup(kDeviceId, preconsented_groups); + } + return true; +} + +bool SQLPTExtRepresentation::SetDeviceData(const std::string& device_id, + const std::string& hardware, + const std::string& firmware, + const std::string& os, + const std::string& os_version, + const std::string& carrier, + const uint32_t number_of_ports, + const std::string& connection_type) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery count_query(db()); + if (!count_query.Prepare(sql_pt_ext::kCountDevice)) { + LOG4CXX_WARN(logger_, "Incorrect statement for count of device."); + return false; + } + + count_query.Bind(0, device_id); + + if (!count_query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect count of device."); + return false; + } + + bool update = count_query.GetInteger(0); + + // Update old value + if (update) { + utils::dbms::SQLQuery update_query(db()); + if (!update_query.Prepare(sql_pt_ext::kUpdateDevice)) { + LOG4CXX_WARN(logger_, "Incorrect statement for udpate device."); + return false; + } + + update_query.Bind(0, hardware); + update_query.Bind(1, firmware); + update_query.Bind(2, os); + update_query.Bind(3, os_version); + update_query.Bind(4, carrier); + update_query.Bind(5, static_cast<int>(number_of_ports)); + update_query.Bind(6, device_id); + update_query.Bind(7, connection_type); + + if (!update_query.Exec() || !update_query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect update for device."); + return false; + } + + return true; + } + + // Insert new data + utils::dbms::SQLQuery insert_query(db()); + if (!insert_query.Prepare(sql_pt_ext::kInsertDevice)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for device."); + return false; + } + + insert_query.Bind(0, device_id); + insert_query.Bind(1, hardware); + insert_query.Bind(2, firmware); + insert_query.Bind(3, os); + insert_query.Bind(4, os_version); + insert_query.Bind(5, carrier); + insert_query.Bind(6, static_cast<int>(number_of_ports)); + insert_query.Bind(7, connection_type); + + if (!insert_query.Exec() || !insert_query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert to device."); + return false; + } + + SetPreloaded(false); + + return true; +} + +bool SQLPTExtRepresentation::SetUserPermissionsForDevice( + const std::string& device_id, + const StringArray& consented_groups, + const StringArray& disallowed_groups) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery count_query(db()); + if (!count_query.Prepare(sql_pt_ext::kCountDeviceConsentGroup)) { + LOG4CXX_WARN(logger_, "Incorrect count of device consented groups"); + return false; + } + + count_query.Bind(0, device_id); + + if (!count_query.Exec()) { + LOG4CXX_WARN(logger_, "Failed count of device consented groups"); + return false; + } + + bool update = count_query.GetInteger(0); + + // TODO(AOleynik): Split to several methods? + utils::dbms::SQLQuery query(db()); + // Update old values + if (update) { + if (!query.Prepare(sql_pt_ext::kUpdateDeviceConsentedGroup)) { + LOG4CXX_WARN( + logger_, + "Incorrect statement for updating consented groups on device"); + return false; + } + + StringArray::const_iterator it_consented_groups = consented_groups.begin(); + StringArray::const_iterator it_consented_groups_end = + consented_groups.end(); + for (; it_consented_groups != it_consented_groups_end; + ++it_consented_groups) { + query.Bind(0, true); + query.Bind(1, std::string("GUI")); + query.Bind(2, device_id); + query.Bind(3, *it_consented_groups); + // TODO(AOleynik): Get this info from external data + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, + "Failed update of device allowed consented groups."); + return false; + } + } + + StringArray::const_iterator it_disallowed_groups = + disallowed_groups.begin(); + StringArray::const_iterator it_disallowed_groups_end = + disallowed_groups.end(); + for (; it_disallowed_groups != it_disallowed_groups_end; + ++it_disallowed_groups) { + query.Bind(0, false); + query.Bind(1); + query.Bind(2, device_id); + query.Bind(3, *it_disallowed_groups); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, + "Failed update of device disallowed consented groups."); + return false; + } + } + + return true; + } + + // Insert new values + if (!query.Prepare(sql_pt_ext::kInsertDeviceConsentedGroup)) { + LOG4CXX_WARN(logger_, + "Incorrect statement of inserting to device consented groups"); + return false; + } + + StringArray::const_iterator it_consented_groups = consented_groups.begin(); + StringArray::const_iterator it_consented_groups_end = consented_groups.end(); + for (; it_consented_groups != it_consented_groups_end; + ++it_consented_groups) { + query.Bind(0, device_id); + query.Bind(1, *it_consented_groups); + query.Bind(2, true); + // TODO(AOleynik): Get this info from external data + query.Bind(3, std::string("GUI")); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, + "Failed insert to device allowed consented groups."); + return false; + } + } + + StringArray::const_iterator it_disallowed_groups = disallowed_groups.begin(); + StringArray::const_iterator it_disallowed_groups_end = + disallowed_groups.end(); + for (; it_disallowed_groups != it_disallowed_groups_end; + ++it_disallowed_groups) { + query.Bind(0, device_id); + query.Bind(1, *it_disallowed_groups); + query.Bind(2, false); + query.Bind(3); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, + "Failed insert to device disallowed consented groups."); + return false; + } + } + + return true; +} + +bool SQLPTExtRepresentation::ReactOnUserDevConsentForApp( + const std::string& app_id, bool is_device_allowed) { + bool result = true; + if (is_device_allowed) { + // If app has pre_DataConsented groups it should be 'promoted' to default + // If app has only pre_DataConsented flag it should be only set to false and + // all groups get restored automatically + if (IsPredataPolicy(app_id)) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kHasAppPreloadedGroups)) { + LOG4CXX_WARN(logger_, + "Incorrect statement for has app preloaded groups"); + return false; + } + query.Bind(0, app_id); + query.Bind(1, kPreDataConsentId); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, + "Incorrect select for app has predataconsted groups"); + return false; + } + if (query.GetInteger(0) > 0) { + result = result && SetDefaultPolicy(app_id); + } else { + result = result && SetIsPredata(app_id, false); + } + } + } else { + // If app has default groups change them to pre_DataConsented + // If app has 'normal' groups leave them as is and set + // pre_DataConsented flag to true. + if (IsDefaultPolicy(app_id)) { + result = result && SetPredataPolicy(app_id); + } else { + result = result && SetIsPredata(app_id, true); + } + } + return result; +} + +bool SQLPTExtRepresentation::SetUserPermissionsForApp( + const PermissionConsent& permissions) { + LOG4CXX_AUTO_TRACE(logger_); + // TODO(AOleynik): Handle situation, when no application was specified, i.e. + // general permissions were set + std::vector<FunctionalGroupPermission>::const_iterator it = + permissions.group_permissions.begin(); + std::vector<FunctionalGroupPermission>::const_iterator it_end = + permissions.group_permissions.end(); + + utils::dbms::SQLQuery query(db()); + for (; it != it_end; ++it) { + utils::dbms::SQLQuery counter(db()); + if (!counter.Prepare(sql_pt_ext::kCountAppConsents)) { + LOG4CXX_WARN(logger_, "Incorrect statement for consent group count."); + return false; + } + + counter.Bind(0, permissions.device_id); + counter.Bind(1, permissions.policy_app_id); + counter.Bind(2, static_cast<int>((*it).group_id)); + if (!counter.Exec()) { + LOG4CXX_WARN(logger_, "Incorrent count on consent groups."); + return false; + } + + bool update_required = counter.GetInteger(0); + + // Update already present consent record + if (update_required) { + if (!query.Prepare(sql_pt_ext::kUpdateGroupPermissions)) { + LOG4CXX_WARN(logger_, "Incorrect statement for update consent groups."); + return false; + } + + // Skip consent saving, if user didn't choose any state + if (policy::kGroupUndefined == (*it).state) { + continue; + } + query.Bind(0, (*it).state == kGroupAllowed ? 1 : 0); + query.Bind(1, permissions.consent_source); + query.Bind(2, permissions.policy_app_id); + query.Bind(3, static_cast<int>((*it).group_id)); + query.Bind(4, permissions.device_id); + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, + "Incorrect update on user defined permissions " + "for app groups."); + return false; + } + continue; + } + + // Insert new consent record + if (!query.Prepare(sql_pt_ext::kInsertConsentGroups)) { + LOG4CXX_WARN(logger_, + "Incorrect statement for update app group permissions."); + return false; + } + + // Skip consent saving, if user didn't choose any state + if (policy::kGroupUndefined == (*it).state) { + continue; + } + query.Bind(0, permissions.device_id); + query.Bind(1, permissions.policy_app_id); + query.Bind(2, static_cast<int>((*it).group_id)); + query.Bind(3, (*it).state == kGroupAllowed ? 1 : 0); + query.Bind(4, permissions.consent_source); + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, + "Incorrect insert to user defined permissions " + "for app groups."); + return false; + } + continue; + } + return true; +} + +std::vector<UserFriendlyMessage> SQLPTExtRepresentation::GetUserFriendlyMsg( + const std::vector<std::string>& msg_codes, const std::string& language) { + utils::dbms::SQLQuery query(db()); + std::vector<UserFriendlyMessage> result; + if (!query.Prepare(sql_pt_ext::kSelectFriendlyMsg)) { + LOG4CXX_WARN(logger_, "Incorrect statement for select friendly messages."); + return result; + } + + const std::string fallback_language = "en-us"; + std::vector<std::string>::const_iterator it = msg_codes.begin(); + std::vector<std::string>::const_iterator it_end = msg_codes.end(); + for (; it != it_end; ++it) { + std::string msg_language = language; + // If message has no records with required language, fallback language + // should be used instead. + if (!IsMsgLanguagePresent((*it), language)) { + msg_language = fallback_language; + } + query.Bind(0, *it); + query.Bind(1, msg_language); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect select from friendly messages."); + return result; + } + + UserFriendlyMessage msg; + + msg.message_code = *it; + msg.tts = query.GetString(0); + msg.label = query.GetString(1); + msg.line1 = query.GetString(2); + msg.line2 = query.GetString(3); + msg.text_body = query.GetString(4); + + result.push_back(msg); + + if (!query.Reset()) { + LOG4CXX_WARN(logger_, + "Failed reset statement for selecting friendly " + "messages."); + return result; + } + } + + return result; +} + +bool SQLPTExtRepresentation::GatherConsumerFriendlyMessages( + policy_table::ConsumerFriendlyMessages* messages) const { + if (NULL == messages) { + LOG4CXX_ERROR(logger_, "NULL pointer has been passed to fill"); + return false; + } + + if (!SQLPTRepresentation::GatherConsumerFriendlyMessages(messages)) { + return false; + } + + utils::dbms::SQLQuery query(db()); + bool result = query.Prepare(sql_pt_ext::kCollectFriendlyMsg); + + if (result) { + while (query.Next()) { + UserFriendlyMessage msg; + + msg.tts = query.GetString(1); + msg.label = query.GetString(2); + msg.line1 = query.GetString(3); + msg.line2 = query.GetString(4); + msg.text_body = query.GetString(5); + msg.message_code = query.GetString(7); + + std::string language = query.GetString(6); + if (!msg.tts.empty()) { + *(*messages->messages)[msg.message_code].languages[language].tts = + msg.tts; + } + if (!msg.label.empty()) { + *(*messages->messages)[msg.message_code].languages[language].label = + msg.label; + } + if (!msg.line1.empty()) { + *(*messages->messages)[msg.message_code].languages[language].line1 = + msg.line1; + } + if (!msg.line2.empty()) { + *(*messages->messages)[msg.message_code].languages[language].line2 = + msg.line2; + } + if (!msg.text_body.empty()) { + *(*messages->messages)[msg.message_code].languages[language].textBody = + msg.text_body; + } + } + } else { + LOG4CXX_WARN(logger_, "Incorrect statement for select friendly messages."); + } + return result; +} + +bool SQLPTExtRepresentation::SetMetaInfo(const std::string& ccpu_version, + const std::string& wers_country_code, + const std::string& language) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kUpdateMetaParams)) { + LOG4CXX_WARN(logger_, "Incorrect statement for insert to module meta."); + return false; + } + + query.Bind(0, ccpu_version); + query.Bind(1, wers_country_code); + query.Bind(2, language); + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert to module meta."); + return false; + } + return true; +} + +bool SQLPTExtRepresentation::IsMetaInfoPresent() { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectMetaParams)) { + LOG4CXX_WARN(logger_, "Incorrect statement for selecting meta info."); + return false; + } + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect select from module meta."); + return false; + } + + return !query.IsNull(0) && !query.IsNull(1) && !query.IsNull(2); +} + +bool SQLPTExtRepresentation::SetSystemLanguage(const std::string& language) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kUpdateMetaLanguage)) { + LOG4CXX_WARN(logger_, "Incorrect statement for update meta language."); + return false; + } + + query.Bind(0, language); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect update for meta language."); + return false; + } + + return true; +} + +bool SQLPTExtRepresentation::SaveApplicationPoliciesSection( + const policy_table::ApplicationPoliciesSection& policies) { + LOG4CXX_INFO(logger_, "SaveApplicationPolicies ext"); + utils::dbms::SQLQuery query_delete(db()); + if (!query_delete.Exec(sql_pt::kDeleteAppGroup)) { + LOG4CXX_WARN(logger_, "Incorrect delete from app_group."); + return false; + } + + utils::dbms::SQLQuery query_delete_preconsented(db()); + if (!query_delete_preconsented.Exec(sql_pt_ext::kDeletePreconsentedGroups)) { + LOG4CXX_WARN(logger_, "Incorrect delete from preconsented_group."); + return false; + } + + if (!query_delete.Exec(sql_pt::kDeleteApplication)) { + LOG4CXX_WARN(logger_, "Incorrect delete from application."); + return false; + } + + if (!query_delete.Exec(sql_pt::kDeleteRequestType)) { + LOG4CXX_WARN(logger_, "Incorrect delete from request type."); + return false; + } + + // First, all predefined apps (e.g. default, pre_DataConsent) should be saved, + // otherwise another app with the predefined permissions can get incorrect + // permissions + policy_table::ApplicationPolicies::const_iterator it_default = + policies.apps.find(kDefaultId); + if (policies.apps.end() != it_default) { + if (!SaveSpecificAppPolicy(*it_default)) { + return false; + } + } + policy_table::ApplicationPolicies::const_iterator it_pre_data_consent = + policies.apps.find(kPreDataConsentId); + if (policies.apps.end() != it_pre_data_consent) { + if (!SaveSpecificAppPolicy(*it_pre_data_consent)) { + return false; + } + } + + if (!SaveDevicePolicy(policies.device)) { + return false; + } + + policy_table::ApplicationPolicies::const_iterator it; + for (it = policies.apps.begin(); it != policies.apps.end(); ++it) { + // Skip saving of predefined app, since they should be saved before + if (IsPredefinedApp(*it)) { + continue; + } + if (!SaveSpecificAppPolicy(*it)) { + return false; + } + } + + return true; +} + +bool SQLPTExtRepresentation::SaveSpecificAppPolicy( + const policy_table::ApplicationPolicies::value_type& app) { + if (app.second.is_string()) { + if (kDefaultId.compare(app.second.get_string()) == 0) { + if (!SetDefaultPolicy(app.first)) { + return false; + } + if (!SaveRequestType(app.first, *app.second.RequestType)) { + return false; + } + } else if (kPreDataConsentId.compare(app.second.get_string()) == 0) { + if (!SetPredataPolicy(app.first)) { + return false; + } + if (!SaveRequestType(app.first, *app.second.RequestType)) { + return false; + } + } + + // Stop saving other params, since predefined permissions already set + return true; + } + + SetIsDefault(app.first, false); + SetIsPredata(app.first, false); + + utils::dbms::SQLQuery app_query(db()); + if (!app_query.Prepare(sql_pt_ext::kInsertApplication)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement into application."); + return false; + } + + app_query.Bind(0, app.first); + app_query.Bind(1, app.second.keep_context); + app_query.Bind(2, app.second.steal_focus); + app_query.Bind( + 3, std::string(policy_table::EnumToJsonString(app.second.default_hmi))); + app_query.Bind( + 4, std::string(policy_table::EnumToJsonString(app.second.priority))); + app_query.Bind(5, app.second.is_null()); + app_query.Bind(6, *app.second.memory_kb); + app_query.Bind(7, static_cast<int64_t>(*app.second.heart_beat_timeout_ms)); + + if (!app_query.Exec() || !app_query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into application."); + return false; + } + + if (!SaveAppGroup(app.first, app.second.groups)) { + return false; + } + if (!SaveNickname(app.first, *app.second.nicknames)) { + return false; + } + if (!SaveAppType(app.first, *app.second.AppHMIType)) { + return false; + } + if (!SavePreconsentedGroup(app.first, *app.second.preconsented_groups)) { + return false; + } + + if (!SaveRequestType(app.first, *app.second.RequestType)) { + return false; + } + + return true; +} + +bool policy::SQLPTExtRepresentation::SaveDevicePolicy( + const policy_table::DevicePolicy& device) { + utils::dbms::SQLQuery app_query(db()); + if (!app_query.Prepare(sql_pt_ext::kInsertApplication)) { + LOG4CXX_WARN(logger_, + "Incorrect insert statement into application (device)."); + return false; + } + app_query.Bind(0, kDeviceId); + app_query.Bind(1, device.keep_context); + app_query.Bind(2, device.steal_focus); + app_query.Bind( + 3, std::string(policy_table::EnumToJsonString(device.default_hmi))); + app_query.Bind(4, + std::string(policy_table::EnumToJsonString(device.priority))); + app_query.Bind(5, false); + app_query.Bind(6, 0); + app_query.Bind(7, 0); + + if (!app_query.Exec() || !app_query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into application."); + return false; + } + + if (!SaveAppGroup(kDeviceId, device.groups)) { + return false; + } + if (!SavePreconsentedGroup(kDeviceId, *device.preconsented_groups)) { + return false; + } + + return true; +} + +bool SQLPTExtRepresentation::GatherApplicationPoliciesSection( + policy_table::ApplicationPoliciesSection* policies) const { + LOG4CXX_INFO(logger_, "Gather applications policies"); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectAppPolicies)) { + LOG4CXX_WARN(logger_, "Incorrect select from app_policies"); + return false; + } + + while (query.Next()) { + rpc::Nullable<policy_table::ApplicationParams> params; + const std::string& app_id = query.GetString(0); + if (IsApplicationRevoked(app_id)) { + params.set_to_null(); + (*policies).apps[app_id] = params; + continue; + } + if (IsDefaultPolicy(app_id)) { + (*policies).apps[app_id].set_to_string(kDefaultId); + } + if (IsPredataPolicy(app_id)) { + (*policies).apps[app_id].set_to_string(kPreDataConsentId); + } + if (kDeviceId == app_id) { + policy_table::DevicePolicy device_policy; + policy_table::Priority priority; + policy_table::EnumFromJsonString(query.GetString(1), &priority); + device_policy.priority = priority; + policy_table::HmiLevel hmi; + policy_table::EnumFromJsonString(query.GetString(2), &hmi); + device_policy.default_hmi = hmi; + device_policy.keep_context = query.GetBoolean(3); + device_policy.steal_focus = query.GetBoolean(4); + if (!GatherAppGroup(app_id, &device_policy.groups)) { + return false; + } + GatherPreconsentedGroup(app_id, &*device_policy.preconsented_groups); + (*policies).device = device_policy; + continue; + } + policy_table::Priority priority; + policy_table::EnumFromJsonString(query.GetString(1), &priority); + params.priority = priority; + policy_table::HmiLevel hmi; + policy_table::EnumFromJsonString(query.GetString(2), &hmi); + params.default_hmi = hmi; + params.keep_context = query.GetBoolean(3); + params.steal_focus = query.GetBoolean(4); + *params.memory_kb = query.GetInteger(5); + *params.heart_beat_timeout_ms = query.GetUInteger(6); + + if (!GatherAppGroup(app_id, ¶ms.groups)) { + return false; + } + if (!GatherNickName(app_id, &*params.nicknames)) { + return false; + } + if (!GatherAppType(app_id, &*params.AppHMIType)) { + return false; + } + if (!GatherRequestType(app_id, &*params.RequestType)) { + return false; + } + GatherPreconsentedGroup(app_id, &*params.preconsented_groups); + (*policies).apps[app_id] = params; + } + return true; +} + +void SQLPTExtRepresentation::GatherPreconsentedGroup( + const std::string& app_id, policy_table::Strings* groups) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectPreconsentedGroups)) { + LOG4CXX_WARN(logger_, "Incorrect select from preconsented group"); + return; + } + + query.Bind(0, app_id); + while (query.Next()) { + groups->push_back(query.GetString(0)); + } +} + +bool SQLPTExtRepresentation::GatherUsageAndErrorCounts( + policy_table::UsageAndErrorCounts* counts) const { + LOG4CXX_INFO(logger_, "Gather Usage and Error Counts."); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectUsageAndErrorCount) || !query.Exec()) { + LOG4CXX_INFO(logger_, "Failed select from user_and_error_count"); + return false; + } + + *counts->count_of_iap_buffer_full = query.GetInteger(0); + *counts->count_sync_out_of_memory = query.GetInteger(1); + *counts->count_of_sync_reboots = query.GetInteger(2); + + return GatherAppLevels(&*counts->app_level); +} + +bool SQLPTExtRepresentation::GatherAppLevels( + policy_table::AppLevels* apps) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectAppLevels)) { + LOG4CXX_INFO(logger_, + "Failed select from app_level. SQLError = " + << query.LastError().text()); + return false; + } + while (query.Next()) { + policy_table::AppLevel level; + // value of time fields database is seconds + level.minutes_in_hmi_full = query.GetInteger(1); + level.minutes_in_hmi_limited = query.GetInteger(2); + level.minutes_in_hmi_background = query.GetInteger(3); + level.minutes_in_hmi_none = query.GetInteger(4); + level.count_of_user_selections = query.GetInteger(5); + level.count_of_rejections_sync_out_of_memory = query.GetInteger(6); + level.count_of_rejections_nickname_mismatch = query.GetInteger(7); + level.count_of_rejections_duplicate_name = query.GetInteger(8); + level.count_of_rejected_rpc_calls = query.GetInteger(9); + level.count_of_rpcs_sent_in_hmi_none = query.GetInteger(10); + level.count_of_removals_for_bad_behavior = query.GetInteger(11); + level.count_of_run_attempts_while_revoked = query.GetInteger(12); + level.app_registration_language_gui = query.GetString(13); + level.app_registration_language_vui = query.GetString(14); + level.count_of_tls_errors = query.GetInteger(15); + (*apps)[query.GetString(0)] = level; + } + + return true; +} + +void SQLPTExtRepresentation::GatherDeviceData( + policy_table::DeviceData* data) const { + LOG4CXX_INFO(logger_, "Gather device data."); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectDeviceData)) { + LOG4CXX_WARN(logger_, "Incorrect select statement for device data."); + return; + } + data->mark_initialized(); + while (query.Next()) { + policy_table::DeviceParams* specific_device = &(*data)[query.GetString(0)]; + *specific_device->hardware = query.GetString(1); + *specific_device->firmware_rev = query.GetString(2); + *specific_device->os = query.GetString(3); + *specific_device->os_version = query.GetString(4); + *specific_device->carrier = query.GetString(5); + *specific_device->max_number_rfcom_ports = query.GetInteger(6); + + // TODO(IKozyrenko): Check logic if optional container is missing + GatherConsentGroup(query.GetString(0), + &(*specific_device->user_consent_records)); + } +} + +void SQLPTExtRepresentation::GatherConsentGroup( + const std::string& device_id, + policy_table::UserConsentRecords* records) const { + LOG4CXX_INFO(logger_, "Gather consent records."); + utils::dbms::SQLQuery query(db()); + // Fill data for device + if (!query.Prepare(sql_pt_ext::kSelectDeviceConsentedGroup)) { + LOG4CXX_WARN(logger_, + "Incorrect select statement for device consented groups."); + return; + } + + query.Bind(0, device_id); + + // Fill device_data -> user_consent_records -> "device" + while (query.Next()) { + policy_table::ConsentRecords* device_consent_records = + &(*records)[kDeviceId]; + // TODO(IKozyrenko): Check logic if optional container is missing + policy_table::ConsentGroups& consent_groups = + *device_consent_records->consent_groups; + consent_groups[query.GetString(1)] = query.GetBoolean(2); + policy_table::Input input; + policy_table::EnumFromJsonString(query.GetString(3), &input); + *device_consent_records->input = input; + *device_consent_records->time_stamp = query.GetString(4); + } + + if (!query.Reset()) { + return; + } + + // Fill data for applications + if (!query.Prepare(sql_pt_ext::kSelectConsentGroup)) { + LOG4CXX_WARN(logger_, + "Incorrect select statement for app consented groups."); + return; + } + + query.Bind(0, device_id); + + // Fill device_data -> user_consent_records -> <app_id> + while (query.Next()) { + policy_table::ConsentRecords* app_consent_records = + &(*records)[query.GetString(1)]; + // TODO(IKozyrenko): Check logic if optional container is missing + policy_table::ConsentGroups& consent_groups = + *app_consent_records->consent_groups; + + consent_groups[query.GetString(2)] = query.GetBoolean(3); + policy_table::Input input; + policy_table::EnumFromJsonString(query.GetString(4), &input); + *app_consent_records->input = input; + *app_consent_records->time_stamp = query.GetString(5); + app_consent_records->consent_last_updated = query.GetInteger(6); + } + if (!query.Reset()) { + return; + } + + // Fill data for ExternalConsent consents + if (!query.Prepare(sql_pt_ext::kSelectExternalConsentStatusGroup)) { + LOG4CXX_WARN( + logger_, + "Incorrect select statement for ExternalConsent consented groups."); + return; + } + + query.Bind(0, device_id); + + // Fill device_data -> user_consent_records -> <app_id> -> + // external_consent_status_groups + while (query.Next()) { + policy_table::ConsentRecords* app_consent_records = + &(*records)[query.GetString(1)]; + policy_table::ConsentGroups& external_consent_status_groups = + *app_consent_records->external_consent_status_groups; + external_consent_status_groups[query.GetString(2)] = query.GetBoolean(3); + policy_table::Input input; + policy_table::EnumFromJsonString(query.GetString(4), &input); + app_consent_records->ext_consent_last_updated = query.GetInteger(6); + } +} + +bool SQLPTExtRepresentation::SaveDeviceData( + const policy_table::DeviceData& devices) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery drop_device_query(db()); + const std::string drop_device = "DELETE FROM `device`"; + if (!drop_device_query.Exec(drop_device)) { + LOG4CXX_WARN(logger_, "Could not clear device table."); + return false; + } + + utils::dbms::SQLQuery drop_device_consents_query(db()); + const std::string drop_device_consents = "DELETE FROM `device_consent_group`"; + if (!drop_device_consents_query.Exec(drop_device_consents)) { + LOG4CXX_WARN(logger_, "Could not clear device consents."); + return false; + } + + utils::dbms::SQLQuery drop_user_consents_query(db()); + const std::string drop_user_consents = "DELETE FROM `consent_group`"; + if (!drop_user_consents_query.Exec(drop_user_consents)) { + LOG4CXX_WARN(logger_, "Could not clear user consents."); + return false; + } + + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kInsertDeviceData)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for device data."); + return false; + } + + policy_table::DeviceData::const_iterator it = devices.begin(); + policy_table::DeviceData::const_iterator it_end = devices.end(); + for (; it != it_end; ++it) { + query.Bind(0, it->first); + query.Bind(1, *(it->second.hardware)); + query.Bind(2, *(it->second.firmware_rev)); + query.Bind(3, *(it->second.os)); + query.Bind(4, *(it->second.os_version)); + query.Bind(5, *(it->second.carrier)); + query.Bind(6, *(it->second.max_number_rfcom_ports)); + query.Bind(7, *(it->second.connection_type)); + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into device data."); + return false; + } + + // TODO(IKozyrenko): Check logic if optional container is missing + if (!SaveConsentGroup(it->first, *it->second.user_consent_records)) { + return false; + } + } + + return true; +} + +bool SQLPTExtRepresentation::SaveConsentGroup( + const std::string& device_id, + const policy_table::UserConsentRecords& records) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + + policy_table::UserConsentRecords::const_iterator it = records.begin(); + policy_table::UserConsentRecords::const_iterator it_end = records.end(); + for (; it != it_end; ++it) { + // TODO(IKozyrenko): Check logic if optional container is missing + policy_table::ConsentGroups::const_iterator it_groups = + it->second.consent_groups->begin(); + policy_table::ConsentGroups::const_iterator it_groups_end = + it->second.consent_groups->end(); + for (; it_groups != it_groups_end; ++it_groups) { + if (kDeviceId == it->first) { + if (!query.Prepare(sql_pt_ext::kInsertDeviceConsentedGroup)) { + LOG4CXX_WARN(logger_, + "Incorrect insert statement for device consent group."); + return false; + } + query.Bind(0, device_id); + query.Bind(1, it_groups->first); + query.Bind(2, it_groups->second); + query.Bind( + 3, + std::string(policy_table::EnumToJsonString(*(it->second.input)))); + query.Bind(4, std::string(*(it->second.time_stamp))); + LOG4CXX_INFO(logger_, + "Device:" + << "time stamp " + << std::string(*(it->second.time_stamp)) << " group " + << it_groups->first << " consent " + << it_groups->second); + } else { + if (!query.Prepare(sql_pt_ext::kInsertConsentGroups)) { + LOG4CXX_WARN(logger_, + "Incorrect insert statement for consent group."); + return false; + } + query.Bind(0, device_id); + query.Bind(1, it->first); + query.Bind(2, it_groups->first); + query.Bind(3, it_groups->second); + query.Bind( + 4, + std::string(policy_table::EnumToJsonString(*(it->second.input)))); + query.Bind(5, std::string(*(it->second.time_stamp))); + query.Bind(6, (it->second.consent_last_updated)); + LOG4CXX_INFO(logger_, + "Device:" + << "time stamp " + << std::string(*(it->second.time_stamp)) << " group " + << it_groups->first << " consent " + << it_groups->second); + } + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into consent group."); + return false; + } + } + + policy_table::ConsentGroups::const_iterator it_external_consent_consent = + it->second.external_consent_status_groups->begin(); + policy_table::ConsentGroups::const_iterator end_external_consent_consent = + it->second.external_consent_status_groups->end(); + + for (; end_external_consent_consent != it_external_consent_consent; + ++it_external_consent_consent) { + if (!query.Prepare(sql_pt_ext::kInsertExternalConsentStatusGroups)) { + LOG4CXX_WARN(logger_, + "Incorrect insert statement for external consent group."); + return false; + } + query.Bind(0, device_id); + query.Bind(1, it->first); + query.Bind(2, it_external_consent_consent->first); + query.Bind(3, it_external_consent_consent->second); + query.Bind( + 4, std::string(policy_table::EnumToJsonString(*(it->second.input)))); + query.Bind(5, std::string(*(it->second.time_stamp))); + query.Bind(6, (it->second.ext_consent_last_updated)); + LOG4CXX_INFO(logger_, + "Device:" + << "time stamp " << std::string(*(it->second.time_stamp)) + << " group " << it_external_consent_consent->first + << " consent " << it_external_consent_consent->second); + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into external consent group."); + return false; + } + } // external_consent_consent_group + } + + return true; +} + +bool SQLPTExtRepresentation::SavePreconsentedGroup( + const std::string& app_id, const policy_table::Strings& groups) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kInsertPreconsentedGroups)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for preconsented groups"); + return false; + } + + policy_table::Strings::const_iterator it; + for (it = groups.begin(); it != groups.end(); ++it) { + query.Bind(0, app_id); + query.Bind(1, *it); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into preconsented groups."); + return false; + } + } + + return true; +} + +void SQLPTExtRepresentation::GatherModuleMeta( + policy_table::ModuleMeta* meta) const { + LOG4CXX_INFO(logger_, "Gather Module Meta Info"); + utils::dbms::SQLQuery query(db()); + if (query.Prepare(sql_pt_ext::kSelectModuleMeta) && query.Next()) { + *meta->ccpu_version = query.GetString(0); + *meta->language = query.GetString(1); + *meta->wers_country_code = query.GetString(2); + *meta->pt_exchanged_at_odometer_x = query.GetInteger(3); + *meta->pt_exchanged_x_days_after_epoch = query.GetInteger(4); + *meta->ignition_cycles_since_last_exchange = query.GetInteger(5); + *meta->vin = query.GetString(6); + } +} + +void SQLPTExtRepresentation::Increment(const std::string& type) const { + utils::dbms::SQLQuery query(db()); + std::string update_counter = + "UPDATE `usage_and_error_count` SET `" + type + "` = `" + type + "` + 1"; + if (!query.Exec(update_counter)) { + LOG4CXX_INFO(logger_, "Failed updating global counter"); + } +} + +bool SQLPTExtRepresentation::IsExistAppLevel(const std::string& app_id) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kCountAppLevel)) { + LOG4CXX_INFO(logger_, "Incorrect statement of count app_level"); + return false; + } + query.Bind(0, app_id); + if (!query.Exec()) { + LOG4CXX_INFO(logger_, "Failed count app_level"); + return false; + } + return query.GetInteger(0) > 0; +} + +bool SQLPTExtRepresentation::GetAllAppGroups(const std::string& policy_app_id, + FunctionalGroupIDs& all_groups) { + LOG4CXX_INFO(logger_, "GetAllAppGroups for '" << policy_app_id << "'"); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectAppGroupsId)) { + LOG4CXX_WARN(logger_, "Incorrect statement for select app groups id."); + return false; + } + + query.Bind(0, policy_app_id); + + while (query.Next()) { + all_groups.push_back(query.GetInteger(0)); + } + + return true; +} + +bool SQLPTExtRepresentation::GetConsentedGroups( + const std::string& policy_app_id, + const std::string& device_id, + FunctionalGroupIDs& allowed_groups, + FunctionalGroupIDs& disallowed_groups) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectConsentedGroupsId)) { + LOG4CXX_WARN(logger_, "Incorrect statement for select consent groups id."); + return false; + } + + query.Bind(0, policy_app_id); + query.Bind(1, device_id); + + while (query.Next()) { + if (query.GetBoolean(1)) { + allowed_groups.push_back(query.GetInteger(0)); + } else { + disallowed_groups.push_back(query.GetInteger(0)); + } + } + + return true; +} + +bool SQLPTExtRepresentation::GetPreconsentedGroups( + const std::string& policy_app_id, FunctionalGroupIDs& preconsented_groups) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectPreconsentedGroupsId)) { + LOG4CXX_WARN(logger_, + "Incorrect statement for select preconsented groups id."); + return false; + } + + query.Bind(0, policy_app_id); + + while (query.Next()) { + preconsented_groups.push_back(query.GetInteger(0)); + } + + return true; +} + +bool SQLPTExtRepresentation::GetFunctionalGroupNames( + FunctionalGroupNames& names) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectFunctionalGroupNames)) { + LOG4CXX_WARN(logger_, + "Incorrect statement for select functional groups names."); + return false; + } + + while (query.Next()) { + // Some of functional grous doesn't have filled user_consent_prompt + if (query.IsNull(1)) { + names[query.GetInteger(0)] = + std::make_pair<std::string, std::string>("", query.GetString(2)); + } else { + names[query.GetInteger(0)] = std::make_pair<std::string, std::string>( + query.GetString(1), query.GetString(2)); + } + } + + return true; +} + +void SQLPTExtRepresentation::FillFunctionalGroupPermissions( + FunctionalGroupIDs& ids, + FunctionalGroupNames& names, + GroupConsent state, + std::vector<FunctionalGroupPermission>& permissions) { + FunctionalGroupIDs::const_iterator it = ids.begin(); + FunctionalGroupIDs::const_iterator it_end = ids.end(); + for (; it != it_end; ++it) { + FunctionalGroupPermission current_group; + current_group.group_id = *it; + current_group.group_alias = names[*it].first; + current_group.group_name = names[*it].second; + current_group.state = state; + permissions.push_back(current_group); + } +} + +void SQLPTExtRepresentation::Increment(const std::string& app_id, + const std::string& type) const { + utils::dbms::SQLQuery query(db()); + std::string sql_counter; + if (IsExistAppLevel(app_id)) { + // update + sql_counter = "UPDATE `app_level` SET `" + type + "` = `" + type + + "` + 1 WHERE `application_id` = ?"; + } else { + // insert + sql_counter = "INSERT INTO `app_level` (`application_id`, `" + type + + "`) " + "VALUES (?, 1)"; + } + if (!query.Prepare(sql_counter)) { + LOG4CXX_INFO(logger_, "Incorrect statement of update app counter"); + return; + } + query.Bind(0, app_id); + if (!query.Exec()) { + LOG4CXX_INFO(logger_, "Failed updating app counter"); + } +} + +void SQLPTExtRepresentation::Set(const std::string& app_id, + const std::string& type, + const std::string& value) const { + utils::dbms::SQLQuery query(db()); + std::string sql_info; + if (IsExistAppLevel(app_id)) { + // update + sql_info = "UPDATE `app_level` SET `" + type + + "` = ? " + "WHERE `application_id` = ?"; + } else { + // insert + sql_info = "INSERT INTO `app_level` (`" + type + + "`, `application_id`) " + "VALUES (?, ?)"; + } + if (!query.Prepare(sql_info)) { + LOG4CXX_INFO(logger_, "Incorrect statement of update app info"); + return; + } + query.Bind(0, value); + query.Bind(1, app_id); + if (!query.Exec()) { + LOG4CXX_INFO(logger_, "Failed updating app info"); + } +} + +void SQLPTExtRepresentation::Add(const std::string& app_id, + const std::string& type, + int seconds) const { + utils::dbms::SQLQuery query(db()); + std::string sql_stopwatch; + if (IsExistAppLevel(app_id)) { + // update + sql_stopwatch = "UPDATE `app_level` SET `" + type + "` = `" + type + + "` + ? WHERE `application_id` = ?"; + } else { + // insert + sql_stopwatch = "INSERT INTO `app_level` (`" + type + + "`, `application_id`) " + "VALUES (?, ?)"; + } + if (!query.Prepare(sql_stopwatch)) { + LOG4CXX_INFO(logger_, "Incorrect statement of update app stopwatch"); + return; + } + query.Bind(0, seconds); + query.Bind(1, app_id); + if (!query.Exec()) { + LOG4CXX_INFO(logger_, "Failed updating app stopwatch"); + } +} + +bool SQLPTExtRepresentation::GetDefaultHMI(const std::string& policy_app_id, + std::string* default_hmi) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectDefaultHmi)) { + LOG4CXX_INFO(logger_, "Incorrect statement for default hmi."); + return false; + } + + query.Bind(0, policy_app_id); + + if (!query.Exec()) { + LOG4CXX_INFO(logger_, "Error during default hmi getting."); + return false; + } + + if (query.IsNull(0)) { + default_hmi->clear(); + return true; + } + + default_hmi->assign(query.GetString(0)); + + return true; +} + +bool SQLPTExtRepresentation::CountUnconsentedGroups( + const std::string& policy_app_id, + const std::string& device_id, + int* result) const { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kCountUnconsentedGroups)) { + LOG4CXX_WARN(logger_, "Incorrect select for unconsented groups."); + return false; + } + + query.Bind(0, policy_app_id); + query.Bind(1, device_id); + query.Bind(2, kDefaultId); + query.Bind(3, kPreDataConsentId); + + if (!query.Exec()) { + LOG4CXX_INFO(logger_, "Error during executing unconsented groups."); + return false; + } + *result = query.GetInteger(0); + return true; +} + +bool SQLPTExtRepresentation::IsMsgLanguagePresent(const std::string& message, + const std::string& language) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kHasMsgLanguageCode)) { + LOG4CXX_WARN(logger_, "Incorrect statement for message language check."); + return false; + } + + query.Bind(0, message); + query.Bind(1, language); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed to check message language code."); + return false; + } + + return query.GetInteger(0) != 0; +} + +bool SQLPTExtRepresentation::SaveMessageString( + const std::string& type, + const std::string& lang, + const policy_table::MessageString& strings) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertMessageString)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for message."); + return false; + } + + if (strings.tts.is_initialized()) { + query.Bind(0, *strings.tts); + } + if (strings.label.is_initialized()) { + query.Bind(1, *strings.label); + } + if (strings.line1.is_initialized()) { + query.Bind(2, *strings.line1); + } + if (strings.line2.is_initialized()) { + query.Bind(3, *strings.line2); + } + query.Bind(4, lang); + query.Bind(5, type); + if (strings.textBody.is_initialized()) { + query.Bind(6, *strings.textBody); + } + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into message."); + return false; + } + + return true; +} + +bool SQLPTExtRepresentation::SaveUsageAndErrorCounts( + const policy_table::UsageAndErrorCounts& counts) { + return SaveAppCounters(*counts.app_level) && SaveGlobalCounters(counts); +} + +bool SQLPTExtRepresentation::SaveModuleMeta( + const policy_table::ModuleMeta& meta) { + utils::dbms::SQLQuery query(db()); + + if (!query.Prepare(sql_pt_ext::kSaveModuleMeta)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for module_meta."); + return false; + } + const int64_t odometer = *(meta.pt_exchanged_at_odometer_x); + + query.Bind(0, *(meta.ccpu_version)); + query.Bind(1, *(meta.language)); + query.Bind(2, *(meta.wers_country_code)); + query.Bind(3, odometer); + query.Bind(4, *(meta.pt_exchanged_x_days_after_epoch)); + query.Bind(5, *(meta.ignition_cycles_since_last_exchange)); + query.Bind(6, *(meta.vin)); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect update for module_meta."); + return false; + } + + return true; +} + +bool SQLPTExtRepresentation::SaveAppCounters( + const rpc::policy_table_interface_base::AppLevels& app_levels) { + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kDeleteAppLevel)) { + LOG4CXX_WARN(logger_, "Incorrect delete from app level."); + return false; + } + if (!query.Prepare(sql_pt::kInsertAppLevel)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for app level."); + return false; + } + + policy_table::AppLevels::const_iterator it; + for (it = app_levels.begin(); it != app_levels.end(); ++it) { + query.Bind(0, it->first); + query.Bind(1, it->second.minutes_in_hmi_full); + query.Bind(2, it->second.minutes_in_hmi_limited); + query.Bind(3, it->second.minutes_in_hmi_background); + query.Bind(4, it->second.minutes_in_hmi_none); + query.Bind(5, it->second.count_of_user_selections); + query.Bind(6, it->second.count_of_rejections_sync_out_of_memory); + query.Bind(7, it->second.count_of_rejections_nickname_mismatch); + query.Bind(8, it->second.count_of_rejections_duplicate_name); + query.Bind(9, it->second.count_of_rejected_rpc_calls); + query.Bind(10, it->second.count_of_rpcs_sent_in_hmi_none); + query.Bind(11, it->second.count_of_removals_for_bad_behavior); + query.Bind(12, it->second.count_of_run_attempts_while_revoked); + query.Bind(13, it->second.app_registration_language_gui); + query.Bind(14, it->second.app_registration_language_vui); + query.Bind(15, it->second.count_of_tls_errors); + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into app level."); + return false; + } + } + return true; +} + +bool SQLPTExtRepresentation::SaveGlobalCounters( + const rpc::policy_table_interface_base::UsageAndErrorCounts& counts) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kUpdateGlobalCounters)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for global counters."); + return false; + } + + query.Bind(0, *counts.count_of_iap_buffer_full); + query.Bind(1, *counts.count_sync_out_of_memory); + query.Bind(2, *counts.count_of_sync_reboots); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect insert into global counters."); + return false; + } + + return true; +} + +bool SQLPTExtRepresentation::CleanupUnpairedDevices( + const DeviceIds& device_ids) const { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery delete_device_query(db()); + if (!delete_device_query.Prepare(sql_pt::kDeleteDevice)) { + LOG4CXX_WARN(logger_, "Incorrect statement for device delete."); + return true; + } + + utils::dbms::SQLQuery delete_device_consent_query(db()); + if (!delete_device_consent_query.Prepare(sql_pt_ext::kDeleteDeviceConsent)) { + LOG4CXX_WARN(logger_, "Incorrect statement for delete device consent."); + return false; + } + + utils::dbms::SQLQuery delete_app_consent_query(db()); + if (!delete_app_consent_query.Prepare(sql_pt_ext::kDeleteAppConsent)) { + LOG4CXX_WARN(logger_, "Incorrect statement for delete app consent."); + return false; + } + + DeviceIds::const_iterator it = device_ids.begin(); + DeviceIds::const_iterator it_end = device_ids.end(); + for (; it != it_end; ++it) { + delete_device_query.Bind(0, (*it)); + if (!delete_device_query.Exec() || !delete_device_query.Reset()) { + LOG4CXX_WARN(logger_, "Failed to delete from device"); + return false; + } + + delete_device_consent_query.Bind(0, (*it)); + if (!delete_device_consent_query.Exec() || + !delete_device_consent_query.Reset()) { + LOG4CXX_WARN(logger_, "Failed to delete from device consent."); + return false; + } + + delete_app_consent_query.Bind(0, (*it)); + if (!delete_app_consent_query.Exec() || !delete_app_consent_query.Reset()) { + LOG4CXX_WARN(logger_, "Failed to delete from app consent."); + return false; + } + } + return true; +} + +bool SQLPTExtRepresentation::SetDefaultPolicy(const std::string& app_id) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kDeleteAppGroupByApplicationId)) { + LOG4CXX_ERROR(logger_, "Incorrect statement to delete from app_group."); + return false; + } + query.Bind(0, app_id); + if (!query.Exec()) { + LOG4CXX_ERROR(logger_, "Failed deleting from app_group."); + return false; + } + + if (!query.Prepare(sql_pt_ext::kDeletePreconsentedGroupsByApplicationId)) { + LOG4CXX_ERROR(logger_, "Incorrect statement to delete from app_group."); + return false; + } + query.Bind(0, app_id); + if (!query.Exec()) { + LOG4CXX_ERROR(logger_, "Failed deleting from app_group."); + return false; + } + + if (!CopyApplication(kDefaultId, app_id)) { + return false; + } + + SetPreloaded(false); + + policy_table::Strings default_groups; + policy_table::Strings default_preconsented_groups; + GatherAppGroup(kDefaultId, &default_groups); + GatherPreconsentedGroup(kDefaultId, &default_preconsented_groups); + if (SaveAppGroup(app_id, default_groups) && + SavePreconsentedGroup(app_id, default_preconsented_groups)) { + return SetIsDefault(app_id, true) && SetIsPredata(app_id, false); + } + + return false; +} + +bool SQLPTExtRepresentation::SetPredataPolicy(const std::string& app_id) { + LOG4CXX_INFO(logger_, + "SQLPTExtRepresentation::SetPredataPolicy for " << app_id); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kDeleteAppGroupByApplicationId)) { + LOG4CXX_ERROR(logger_, "Incorrect statement to delete from app_group."); + return false; + } + query.Bind(0, app_id); + if (!query.Exec()) { + LOG4CXX_ERROR(logger_, "Failed deleting from app_group."); + return false; + } + + if (!query.Prepare(sql_pt_ext::kDeletePreconsentedGroupsByApplicationId)) { + LOG4CXX_ERROR(logger_, "Incorrect statement to delete from app_group."); + return false; + } + query.Bind(0, app_id); + if (!query.Exec()) { + LOG4CXX_ERROR(logger_, "Failed deleting from app_group."); + return false; + } + + if (!CopyApplication(kPreDataConsentId, app_id)) { + return false; + } + + SetPreloaded(false); + + policy_table::Strings predataconsent_groups; + policy_table::Strings predataconsent_preconsented_groups; + GatherAppGroup(kPreDataConsentId, &predataconsent_groups); + GatherPreconsentedGroup(kPreDataConsentId, &predataconsent_groups); + if (SaveAppGroup(app_id, predataconsent_groups) && + SavePreconsentedGroup(app_id, predataconsent_groups)) { + return SetIsDefault(app_id, false) && SetIsPredata(app_id, true); + } + return false; +} + +bool SQLPTExtRepresentation::IsPredataPolicy(const std::string& app_id) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectApplicationIsPreData)) { + LOG4CXX_WARN(logger_, "Incorrect select application is pre_dataConsented"); + return false; + } + + query.Bind(0, app_id); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed select application is pre_dataConsented"); + return false; + } + return query.IsNull(0) ? false : query.GetBoolean(0); +} + +bool SQLPTExtRepresentation::SetIsPredata(const std::string& app_id, + bool is_pre_data) { + LOG4CXX_TRACE(logger_, "Set flag is_predata of application"); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kUpdateIsPredata)) { + LOG4CXX_WARN(logger_, "Incorect statement for updating is_predata"); + return false; + } + + query.Bind(0, is_pre_data); + query.Bind(1, app_id); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed update is_predata"); + return false; + } + return true; +} + +bool SQLPTExtRepresentation::SetUnpairedDevice(const std::string& device_id, + bool unpaired) const { + LOG4CXX_TRACE(logger_, "Set unpaired device: " << device_id); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kUpdateUnpairedDevice)) { + LOG4CXX_WARN(logger_, "Incorect statement for updating unpaired device"); + return false; + } + + query.Bind(0, unpaired); + query.Bind(1, device_id); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed update unpaired device"); + return false; + } + return true; +} + +bool SQLPTExtRepresentation::UnpairedDevicesList(DeviceIds* device_ids) const { + LOG4CXX_TRACE(logger_, "Get list of unpaired devices"); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectUnpairedDevices)) { + LOG4CXX_WARN(logger_, "Incorect statement for selecting unpaired devices"); + return false; + } + + while (query.Next()) { + device_ids->push_back(query.GetString(0)); + } + return true; +} + +bool SQLPTExtRepresentation::SetVINValue(const std::string& value) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kUpdateModuleMetaVinParam)) { + LOG4CXX_WARN(logger_, "Incorect statement for updating module_meta params"); + return false; + } + + query.Bind(0, value); + const bool result = query.Exec(); + + if (!result) { + LOG4CXX_WARN(logger_, "Failed update module_meta"); + } + return result; +} + +bool SQLPTExtRepresentation::SaveExternalConsentStatus( + const ExternalConsentStatus& status) const { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kInsertExternalConsentStatus)) { + LOG4CXX_ERROR(logger_, + "Incorrect statement for saving external consent status."); + return false; + } + + ExternalConsentStatus::const_iterator it = status.begin(); + ExternalConsentStatus::const_iterator end = status.end(); + for (; end != it; ++it) { + query.Bind(0, static_cast<int>(it->entity_type_)); + query.Bind(1, static_cast<int>(it->entity_id_)); + // Due to query structure need to provide that twice + query.Bind(2, static_cast<int>(it->entity_type_)); + query.Bind(3, static_cast<int>(it->entity_id_)); + query.Bind(4, + policy::kStatusOn == it->status_ ? std::string("ON") + : std::string("OFF")); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_ERROR(logger_, "Error during ExternalConsent status saving."); + return false; + } + } + + return true; +} + +ExternalConsentStatus SQLPTExtRepresentation::GetExternalConsentStatus() const { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kSelectExternalConsentStatus)) { + LOG4CXX_ERROR(logger_, + "Incorrect statement for selecting external consent status."); + return ExternalConsentStatus(); + } + + ExternalConsentStatus status; + while (query.Next()) { + const policy::EntityStatus on_off = + query.GetString(2) == "ON" ? policy::kStatusOn : policy::kStatusOff; + ExternalConsentStatusItem item(static_cast<uint32_t>(query.GetInteger(0)), + static_cast<uint32_t>(query.GetInteger(1)), + on_off); + status.insert(item); + } + + return status; +} + +bool SQLPTExtRepresentation::RemoveAppConsentForGroup( + const std::string& policy_app_id, + const std::string& functional_group_name) const { + utils::dbms::SQLQuery query_group_id(db()); + if (!query_group_id.Prepare(sql_pt_ext::kSelectGroupId)) { + LOG4CXX_WARN(logger_, "Incorect statement for select group name."); + return false; + } + + query_group_id.Bind(0, functional_group_name); + + if (!query_group_id.Exec()) { + LOG4CXX_WARN(logger_, "Failed to select group id."); + return false; + } + + const int id = query_group_id.GetInteger(0); + + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kDeleteAppGroupConsent)) { + LOG4CXX_WARN(logger_, "Incorect statement for remove app consent."); + return false; + } + + query.Bind(0, policy_app_id); + query.Bind(1, id); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed to remove app consent."); + return false; + } + + return true; +} + +} // namespace policy diff --git a/src/components/policy/policy_external/src/sql_pt_queries.cc b/src/components/policy/policy_external/src/sql_pt_queries.cc new file mode 100644 index 0000000000..1cd789f00d --- /dev/null +++ b/src/components/policy/policy_external/src/sql_pt_queries.cc @@ -0,0 +1,972 @@ +/* + Copyright (c) 2015, " Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, " with or without + modification, " are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, " this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, " + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, " INCLUDING, " BUT NOT LIMITED TO, " THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, " INDIRECT, " INCIDENTAL, " SPECIAL, " EXEMPLARY, " OR + CONSEQUENTIAL DAMAGES (INCLUDING, " BUT NOT LIMITED TO, " PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, " DATA, " OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, " WHETHER IN + CONTRACT, " STRICT LIABILITY, " OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, " EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include "policy/sql_pt_queries.h" + +namespace policy { +namespace sql_pt { + +const std::string kSelectPriority = + "SELECT `priority_value` FROM `application` WHERE `id` = ? LIMIT 1"; +const std::string kCreateSchema = + "BEGIN; " + "CREATE TABLE IF NOT EXISTS `device`( " + " `id` VARCHAR(100) PRIMARY KEY NOT NULL, " + " `hardware` VARCHAR(45), " + " `firmware_rev` VARCHAR(45), " + " `os` VARCHAR(45), " + " `os_version` VARCHAR(45), " + " `carrier` VARCHAR(45), " + " `max_number_rfcom_ports` INTEGER," + " `connection_type` VARCHAR(45), " + " `unpaired` BOOL " + "); " + "CREATE TABLE IF NOT EXISTS `usage_and_error_count`( " + " `count_of_iap_buffer_full` INTEGER, " + " `count_sync_out_of_memory` INTEGER, " + " `count_of_sync_reboots` INTEGER " + "); " + "CREATE TABLE IF NOT EXISTS `module_meta`( " + " `ccpu_version` VARCHAR(45), " + " `language` VARCHAR(45), " + " `wers_country_code` VARCHAR(45), " + " `pt_exchanged_at_odometer_x` INTEGER NOT NULL DEFAULT 0, " + " `pt_exchanged_x_days_after_epoch` INTEGER NOT NULL DEFAULT 0, " + " `ignition_cycles_since_last_exchange` INTEGER NOT NULL DEFAULT 0, " + " `vin` VARCHAR(45)," + " `flag_update_required` BOOL NOT NULL " + "); " + "CREATE TABLE IF NOT EXISTS `module_config`( " + " `preloaded_pt` BOOL NOT NULL, " + " `is_first_run` BOOL NOT NULL, " + " `exchange_after_x_ignition_cycles` INTEGER NOT NULL, " + " `exchange_after_x_kilometers` INTEGER NOT NULL, " + " `exchange_after_x_days` INTEGER NOT NULL, " + " `timeout_after_x_seconds` INTEGER NOT NULL, " + " `vehicle_make` VARCHAR(45), " + " `vehicle_model` VARCHAR(45), " + " `vehicle_year` VARCHAR(4), " + " `preloaded_date` VARCHAR (10), " + " `certificate` VARCHAR (45), " + " `user_consent_passengersRC` BOOL," + " `country_consent_passengersRC` BOOL " + "); " + "CREATE TABLE IF NOT EXISTS `functional_group`( " + " `id` INTEGER PRIMARY KEY NOT NULL, " + " `user_consent_prompt` TEXT, " + " `name` VARCHAR(100) NOT NULL " + "); " + "CREATE TABLE IF NOT EXISTS `external_consent_entities`( " + " `group_id` INTEGER NOT NULL, " + " `entity_type` INTEGER NOT NULL, " + " `entity_id` INTEGER NOT NULL, " + " `on_off` TEXT NOT NULL, " + " CONSTRAINT `fk_external_consent_entities_group_id` " + " FOREIGN KEY(`group_id`) " + " REFERENCES `functional_group`(`id`) " + "); " + "CREATE TABLE IF NOT EXISTS `priority`( " + " `value` VARCHAR(45) PRIMARY KEY NOT NULL " + "); " + "CREATE TABLE IF NOT EXISTS `hmi_level`( " + " `value` VARCHAR(45) PRIMARY KEY NOT NULL " + "); " + "CREATE TABLE IF NOT EXISTS `notifications_by_priority`( " + " `priority_value` VARCHAR(45) PRIMARY KEY NOT NULL, " + " `value` INTEGER NOT NULL, " + " CONSTRAINT `fk_notifications_by_priority_priority1` " + " FOREIGN KEY(`priority_value`) " + " REFERENCES `priority`(`value`) " + "); " + "CREATE INDEX IF NOT EXISTS " + "`notifications_by_priority.fk_notifications_by_priority_priority1_idx` " + " ON `notifications_by_priority`(`priority_value`); " + "CREATE TABLE IF NOT EXISTS `language`( " + " `code` VARCHAR(25) PRIMARY KEY NOT NULL " + "); " + "CREATE TABLE IF NOT EXISTS `message_type`( " + " `name` VARCHAR(45) PRIMARY KEY NOT NULL " + "); " + "CREATE TABLE IF NOT EXISTS `version`( " + " `number` VARCHAR(45) NOT NULL " + "); " + "CREATE TABLE IF NOT EXISTS `rpc`( " + " `id` INTEGER PRIMARY KEY NOT NULL, " + " `name` VARCHAR(45) NOT NULL, " + " `parameter` VARCHAR(45), " + " `hmi_level_value` VARCHAR(45) NOT NULL, " + " `functional_group_id` INTEGER NOT NULL, " + " CONSTRAINT `fk_rpc_hmi_level1` " + " FOREIGN KEY(`hmi_level_value`) " + " REFERENCES `hmi_level`(`value`), " + " CONSTRAINT `fk_rpc_functional_group1` " + " FOREIGN KEY(`functional_group_id`) " + " REFERENCES `functional_group`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS `rpc.fk_rpc_hmi_level1_idx` " + " ON `rpc`(`hmi_level_value`); " + "CREATE INDEX IF NOT EXISTS `rpc.fk_rpc_functional_group1_idx` " + " ON `rpc`(`functional_group_id`); " + "CREATE INDEX `rpc.select_rpc_name_hmi_level` " + " ON `rpc`(`name`,`hmi_level_value`);" + "CREATE TABLE IF NOT EXISTS `application`( " + " `id` VARCHAR(45) PRIMARY KEY NOT NULL, " + " `keep_context` BOOLEAN, " + " `steal_focus` BOOLEAN, " + " `default_hmi` VARCHAR(45), " + " `priority_value` VARCHAR(45), " + " `is_revoked` BOOLEAN, " + " `is_default` BOOLEAN, " + " `is_predata` BOOLEAN, " + " `memory_kb` INTEGER NOT NULL, " + " `heart_beat_timeout_ms` INTEGER NOT NULL, " + " `remote_control_denied` BOOLEAN NOT NULL DEFAULT 0, " + " CONSTRAINT `fk_application_hmi_level1` " + " FOREIGN KEY(`default_hmi`) " + " REFERENCES `hmi_level`(`value`), " + " CONSTRAINT `fk_application_priorities1` " + " FOREIGN KEY(`priority_value`) " + " REFERENCES `priority`(`value`) " + "); " + "CREATE INDEX IF NOT EXISTS `application.fk_application_hmi_level1_idx` " + " ON `application`(`default_hmi`); " + "CREATE INDEX IF NOT EXISTS `application.fk_application_priorities1_idx` " + " ON `application`(`priority_value`); " + "CREATE TABLE IF NOT EXISTS `app_group`( " + " `application_id` VARCHAR(45) NOT NULL, " + " `functional_group_id` INTEGER NOT NULL, " + " PRIMARY KEY(`application_id`,`functional_group_id`), " + " CONSTRAINT `fk_application_has_functional_group_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`), " + " CONSTRAINT `fk_application_has_functional_group_functional_group1` " + " FOREIGN KEY(`functional_group_id`) " + " REFERENCES `functional_group`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS " + "`app_group.fk_application_has_functional_group_functional_group1_idx` " + " ON `app_group`(`functional_group_id`); " + "CREATE INDEX IF NOT EXISTS " + "`app_group.fk_application_has_functional_group_application1_idx` " + " ON `app_group`(`application_id`); " + "CREATE TABLE IF NOT EXISTS `preconsented_group`( " + " `application_id` VARCHAR(45) NOT NULL, " + " `functional_group_id` INTEGER NOT NULL, " + " PRIMARY KEY(`application_id`,`functional_group_id`), " + " CONSTRAINT `fk_application_has_functional_group_application2` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`), " + " CONSTRAINT `fk_application_has_functional_group_functional_group2` " + " FOREIGN KEY(`functional_group_id`) " + " REFERENCES `functional_group`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS " + "`preconsented_group.fk_application_has_functional_group_functional_group2_" + "idx` " + " ON `preconsented_group`(`functional_group_id`); " + "CREATE INDEX IF NOT EXISTS " + "`preconsented_group.fk_application_has_functional_group_application2_idx` " + " ON `preconsented_group`(`application_id`); " + "CREATE TABLE IF NOT EXISTS `seconds_between_retry`( " + " `index` INTEGER PRIMARY KEY NOT NULL, " + " `value` INTEGER NOT NULL " + "); " + "CREATE TABLE IF NOT EXISTS `device_consent_group`( " + " `device_id` VARCHAR(100) NOT NULL, " + " `functional_group_id` INTEGER NOT NULL, " + " `is_consented` BOOL NOT NULL, " + " `input` VARCHAR(45), " + " `time_stamp` VARCHAR(45), " + " PRIMARY KEY(`device_id`,`functional_group_id`), " + " CONSTRAINT `fk_device_has_functional_group_device1` " + " FOREIGN KEY(`device_id`) " + " REFERENCES `device`(`id`), " + " CONSTRAINT `fk_device_has_functional_group_functional_group1` " + " FOREIGN KEY(`functional_group_id`) " + " REFERENCES `functional_group`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS " + "`device_consent_group.fk_device_has_functional_group_functional_group1_" + "idx` " + " ON `device_consent_group`(`functional_group_id`); " + "CREATE INDEX IF NOT EXISTS " + "`device_consent_group.fk_device_has_functional_group_device1_idx` " + " ON `device_consent_group`(`device_id`); " + "CREATE TABLE IF NOT EXISTS `app_level`( " + " `application_id` VARCHAR(45) PRIMARY KEY NOT NULL, " + " `minutes_in_hmi_full` INTEGER DEFAULT 0, " + " `minutes_in_hmi_limited` INTEGER DEFAULT 0, " + " `minutes_in_hmi_background` INTEGER DEFAULT 0, " + " `minutes_in_hmi_none` INTEGER DEFAULT 0, " + " `count_of_user_selections` INTEGER DEFAULT 0, " + " `count_of_rejections_sync_out_of_memory` INTEGER DEFAULT 0, " + " `count_of_rejections_nickname_mismatch` INTEGER DEFAULT 0, " + " `count_of_rejections_duplicate_name` INTEGER DEFAULT 0, " + " `count_of_rejected_rpcs_calls` INTEGER DEFAULT 0, " + " `count_of_rpcs_sent_in_hmi_none` INTEGER DEFAULT 0, " + " `count_of_removals_for_bad_behavior` INTEGER DEFAULT 0, " + " `count_of_run_attempts_while_revoked` INTEGER DEFAULT 0, " + " `count_of_tls_errors` INTEGER DEFAULT 0, " + " `app_registration_language_gui` VARCHAR(25), " + " `app_registration_language_vui` VARCHAR(25), " + " CONSTRAINT `fk_app_levels_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`), " + " CONSTRAINT `fk_app_level_language1` " + " FOREIGN KEY(`app_registration_language_gui`) " + " REFERENCES `language`(`code`), " + " CONSTRAINT `fk_app_level_language2` " + " FOREIGN KEY(`app_registration_language_vui`) " + " REFERENCES `language`(`code`) " + "); " + "CREATE INDEX IF NOT EXISTS `app_level.fk_app_levels_application1_idx` " + " ON `app_level`(`application_id`); " + "CREATE INDEX IF NOT EXISTS `app_level.fk_app_level_language1_idx` " + " ON `app_level`(`app_registration_language_gui`); " + "CREATE INDEX IF NOT EXISTS `app_level.fk_app_level_language2_idx` " + " ON `app_level`(`app_registration_language_vui`); " + "CREATE TABLE IF NOT EXISTS `nickname`( " + " `name` VARCHAR(100) NOT NULL, " + " `application_id` VARCHAR(45) NOT NULL, " + " PRIMARY KEY(`name`,`application_id`), " + " CONSTRAINT `fk_nickname_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS `nickname.fk_nickname_application1_idx` " + " ON `nickname`(`application_id`); " + "CREATE TABLE IF NOT EXISTS `app_type`( " + " `name` VARCHAR(50) NOT NULL, " + " `application_id` VARCHAR(45) NOT NULL, " + " PRIMARY KEY(`name`,`application_id`), " + " CONSTRAINT `fk_app_type_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`) " + "); " + "CREATE TABLE IF NOT EXISTS `request_type`( " + " `request_type` VARCHAR(50) NOT NULL, " + " `application_id` VARCHAR(45) NOT NULL, " + " PRIMARY KEY(`request_type`,`application_id`), " + " CONSTRAINT `fk_app_type_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS `app_type.fk_app_type_application1_idx` " + " ON `app_type`(`application_id`); " + "CREATE TABLE IF NOT EXISTS `consent_group`( " + " `device_id` VARCHAR(100) NOT NULL, " + " `application_id` VARCHAR(45) NOT NULL, " + " `functional_group_id` INTEGER NOT NULL, " + " `is_consented` BOOL NOT NULL, " + " `input` VARCHAR(45), " + " `time_stamp` VARCHAR(45), " + " `last_updated` INTEGER, " + " PRIMARY KEY(`application_id`,`functional_group_id`,`device_id`), " + " CONSTRAINT `fk_consent_group_device1` " + " FOREIGN KEY(`device_id`) " + " REFERENCES `device`(`id`), " + " CONSTRAINT `fk_consent_group_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`), " + " CONSTRAINT `fk_consent_group_functional_group1` " + " FOREIGN KEY(`functional_group_id`) " + " REFERENCES `functional_group`(`id`) " + "); " + "CREATE TABLE IF NOT EXISTS `external_consent_status_group`( " + " `device_id` VARCHAR(100) NOT NULL, " + " `application_id` VARCHAR(45) NOT NULL, " + " `functional_group_id` INTEGER NOT NULL, " + " `is_consented` BOOL NOT NULL, " + " `input` VARCHAR(45), " + " `time_stamp` VARCHAR(45), " + " `last_updated` INTEGER, " + " PRIMARY KEY(`application_id`,`functional_group_id`,`device_id`), " + " CONSTRAINT `fk_external_consent_status_group_device1` " + " FOREIGN KEY(`device_id`) " + " REFERENCES `device`(`id`), " + " CONSTRAINT `fk_external_consent_status_group_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`), " + " CONSTRAINT `fk_external_consent_status_group_functional_group1` " + " FOREIGN KEY(`functional_group_id`) " + " REFERENCES `functional_group`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS " + "`consent_group.fk_consent_group_device1_idx` " + " ON `device_consent_group`(`device_id`); " + "CREATE INDEX IF NOT EXISTS " + "`consent_group.fk_consent_group_functional_group1_idx` " + " ON `consent_group`(`functional_group_id`); " + "CREATE TABLE IF NOT EXISTS `endpoint`( " + " `service` INTEGER NOT NULL, " + " `url` VARCHAR(100) NOT NULL, " + " `application_id` VARCHAR(45) NOT NULL, " + " CONSTRAINT `fk_endpoint_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS `endpoint.fk_endpoint_application1_idx` " + " ON `endpoint`(`application_id`); " + "CREATE TABLE IF NOT EXISTS `message`( " + " `id` INTEGER PRIMARY KEY NOT NULL, " + " `tts` TEXT, " + " `label` TEXT, " + " `line1` TEXT, " + " `line2` TEXT, " + " `textBody` TEXT, " + " `language_code` VARCHAR(25) NOT NULL, " + " `message_type_name` VARCHAR(45) NOT NULL, " + " CONSTRAINT `fk_messages_languages1` " + " FOREIGN KEY(`language_code`) " + " REFERENCES `language`(`code`), " + " CONSTRAINT `fk_message_consumer_friendly_messages1` " + " FOREIGN KEY(`message_type_name`) " + " REFERENCES `message_type`(`name`) " + "); " + + "CREATE TABLE IF NOT EXISTS `app_group_primary`( " + " `application_id` VARCHAR(45) NOT NULL, " + " `functional_group_id` INTEGER NOT NULL, " + " PRIMARY KEY(`application_id`,`functional_group_id`), " + " CONSTRAINT `fk_application_has_functional_group_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`), " + " CONSTRAINT `fk_application_has_functional_group_functional_group1` " + " FOREIGN KEY(`functional_group_id`) " + " REFERENCES `functional_group`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS " + "`app_group_primary.fk_application_has_functional_group_functional_group1_" + "idx` " + " ON `app_group_primary`(`functional_group_id`); " + "CREATE INDEX IF NOT EXISTS " + "`app_group_primary.fk_application_has_functional_group_application1_idx` " + " ON `app_group_primary`(`application_id`); " + + "CREATE TABLE IF NOT EXISTS `app_group_non_primary`( " + " `application_id` VARCHAR(45) NOT NULL, " + " `functional_group_id` INTEGER NOT NULL, " + " PRIMARY KEY(`application_id`,`functional_group_id`), " + " CONSTRAINT `fk_application_has_functional_group_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`), " + " CONSTRAINT `fk_application_has_functional_group_functional_group1` " + " FOREIGN KEY(`functional_group_id`) " + " REFERENCES `functional_group`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS " + "`app_group_non_primary.fk_application_has_functional_group_functional_" + "group1_idx` " + " ON `app_group_non_primary`(`functional_group_id`); " + "CREATE INDEX IF NOT EXISTS " + "`app_group_non_primary.fk_application_has_functional_group_application1_" + "idx` " + " ON `app_group_non_primary`(`application_id`); " + + /* interior_zone */ + "CREATE TABLE `interior_zone`( " + " `id` INTEGER PRIMARY KEY NOT NULL, " + " `name` VARCHAR(100) NOT NULL, " + " `col` INTEGER NOT NULL, " + " `row` INTEGER NOT NULL, " + " `level` INTEGER NOT NULL " + "); " + "CREATE UNIQUE INDEX `interior_zone.room` ON " + "`interior_zone`(`col`,`row`,`level`); " + + /* access_module */ + "CREATE TABLE `access_module`( " + " `id` INTEGER PRIMARY KEY NOT NULL, " + " `name` VARCHAR(45) NOT NULL, " + " `zone_id` INTEGER NOT NULL, " + " `user_consent_needed` INTEGER NOT NULL, " + "CONSTRAINT `fk_module_1` " + " FOREIGN KEY(`zone_id`) " + " REFERENCES `interior_zone`(`id`) " + "); " + "CREATE INDEX `access_module.zone_module` ON " + "`access_module`(`name`,`zone_id`); " + "CREATE INDEX `access_module.fk_module_1_idx` ON " + "`access_module`(`zone_id`); " + + /* remote_rpc */ + "CREATE TABLE `remote_rpc`( " + " `id` INTEGER PRIMARY KEY NOT NULL, " + " `name` VARCHAR(255) NOT NULL, " + " `parameter` VARCHAR(45), " + " `module_id` INTEGER NOT NULL, " + "CONSTRAINT `fk_remote_rpc_1` " + " FOREIGN KEY(`module_id`) " + " REFERENCES `access_module`(`id`) " + "); " + "CREATE INDEX `remote_rpc.fk_remote_rpc_1_idx` ON " + "`remote_rpc`(`module_id`); " + + /* module type */ + "CREATE TABLE IF NOT EXISTS `module_type`( " + " `name` VARCHAR(50) NOT NULL, " + " `application_id` VARCHAR(45) NOT NULL, " + " PRIMARY KEY(`name`,`application_id`), " + " CONSTRAINT `fk_module_type_application1` " + " FOREIGN KEY(`application_id`) " + " REFERENCES `application`(`id`) " + "); " + "CREATE INDEX IF NOT EXISTS `module_type.fk_module_type_application1_idx` " + " ON `module_type`(`application_id`); " + + "CREATE INDEX IF NOT EXISTS `message.fk_messages_languages1_idx` " + " ON `message`(`language_code`);" + "CREATE INDEX IF NOT EXISTS " + "`message.fk_message_consumer_friendly_messages1_idx` " + " ON `message`(`message_type_name`);" + "CREATE TABLE IF NOT EXISTS `_internal_data`( " + " `db_version_hash` INTEGER " + " ); " + "CREATE TABLE IF NOT EXISTS `_internal_external_consent_status`( " + " `id` INTEGER PRIMARY KEY AUTOINCREMENT, " + " `entity_type` INTEGER NOT NULL, " + " `entity_id` INTEGER NOT NULL, " + " `on_off` TEXT NOT NULL " + " ); " + "COMMIT;"; + +const std::string kInsertInitData = + "INSERT OR IGNORE INTO `usage_and_error_count` ( " + " `count_of_iap_buffer_full`, `count_sync_out_of_memory`, " + " `count_of_sync_reboots`) VALUES (0, 0, 0); " + "INSERT OR IGNORE INTO `module_meta` (`pt_exchanged_at_odometer_x`, " + " `pt_exchanged_x_days_after_epoch`, " + "`ignition_cycles_since_last_exchange`," + " `flag_update_required`) " + " VALUES (0, 0, 0, 0); " + "INSERT OR IGNORE INTO `module_config` (`preloaded_pt`, `is_first_run`," + " `exchange_after_x_ignition_cycles`, `exchange_after_x_kilometers`, " + " `exchange_after_x_days`, `timeout_after_x_seconds`) " + " VALUES(1, 0, 0, 0, 0, 0); " + "INSERT OR IGNORE INTO `priority`(`value`) VALUES ('EMERGENCY'); " + "INSERT OR IGNORE INTO `priority`(`value`) VALUES ('NAVIGATION'); " + "INSERT OR IGNORE INTO `priority`(`value`) VALUES ('VOICECOMMUNICATION'); " + "INSERT OR IGNORE INTO `priority`(`value`) VALUES ('COMMUNICATION'); " + "INSERT OR IGNORE INTO `priority`(`value`) VALUES ('NORMAL'); " + "INSERT OR IGNORE INTO `priority`(`value`) VALUES ('NONE'); " + "INSERT OR IGNORE INTO `hmi_level`(`value`) VALUES ('FULL'); " + "INSERT OR IGNORE INTO `hmi_level`(`value`) VALUES ('LIMITED'); " + "INSERT OR IGNORE INTO `hmi_level`(`value`) VALUES ('BACKGROUND'); " + "INSERT OR IGNORE INTO `hmi_level`(`value`) VALUES ('NONE'); " + "INSERT OR IGNORE INTO `version` (`number`) VALUES('0'); " + "INSERT OR IGNORE INTO `_internal_data` (`db_version_hash`) VALUES(0); " + ""; + +const std::string kDeleteAppGroupPrimary = "DELETE FROM `app_group_primary`"; + +const std::string kDeleteAppGroupNonPrimary = + "DELETE FROM `app_group_non_primary`"; + +const std::string kDeleteModuleTypes = "DELETE FROM `module_type`"; + +const std::string kDeleteAllDevices = "DELETE FROM `device`;"; + +const std::string kSelectAppGroupsPrimary = + "SELECT `f`.`name` FROM `app_group_primary` AS `a`" + " LEFT JOIN `functional_group` AS `f` " + " ON (`f`.`id` = `a`.`functional_group_id`)" + " WHERE `a`.`application_id` = ?"; + +const std::string kSelectAppGroupsNonPrimary = + "SELECT `f`.`name` FROM `app_group_non_primary` AS `a`" + " LEFT JOIN `functional_group` AS `f` " + " ON (`f`.`id` = `a`.`functional_group_id`)" + " WHERE `a`.`application_id` = ?"; + +const std::string kSelectRemoteControlDenied = + "SELECT `remote_control_denied` FROM `application` WHERE `id` = ? LIMIT 1"; + +const std::string kInsertAppGroupPrimary = + "INSERT INTO `app_group_primary` (`application_id`, `functional_group_id`)" + " SELECT ?, `id` FROM `functional_group` WHERE `name` = ? LIMIT 1"; + +const std::string kInsertAppGroupNonPrimary = + "INSERT INTO `app_group_non_primary` (`application_id`, " + "`functional_group_id`)" + " SELECT ?, `id` FROM `functional_group` WHERE `name` = ? LIMIT 1"; + +const std::string kUpdateRemoteControlDenied = + "UPDATE `application` SET `remote_control_denied` = ? WHERE `id` = ?"; + +const std::string kCountInteriorZones = + "SELECT COUNT(`id`) FROM `interior_zone`"; + +const std::string kDeleteInteriorZones = "DELETE FROM `interior_zone`"; + +const std::string kDeleteAccessModules = "DELETE FROM `access_module`"; + +const std::string kDeleteRemoteRpc = "DELETE FROM `remote_rpc`"; + +const std::string kInsertInteriorZone = + "INSERT INTO `interior_zone` (`name`, `col`, `row`, `level`) " + " VALUES(?, ?, ?, ?)"; + +const std::string kSelectInteriorZones = + "SELECT `id`, `name`, `col`, `row`, `level` FROM `interior_zone`"; + +const std::string kInsertAccessModule = + "INSERT INTO `access_module` (`name`, `zone_id`, `user_consent_needed`) " + " VALUES(?, ?, ?)"; + +const std::string kDeleteAppGroupPrimaryByApplicationId = + "DELETE FROM `app_group_primary` WHERE `application_id` = ?"; + +const std::string kDeleteAppGroupNonPrimaryByApplicationId = + "DELETE FROM `app_group_non_primary` WHERE `application_id` = ?"; + +const std::string kSelectAccessModules = + "SELECT `id`, `name` FROM `access_module` " + " WHERE `zone_id` = ? AND `user_consent_needed` = ?"; + +const std::string kInsertRemoteRpc = + "INSERT INTO `remote_rpc` (`module_id`, `name`, `parameter`) " + " VALUES(?, ?, ?)"; + +const std::string kSelectRemoteRpcs = + "SELECT `name`, `parameter` FROM `remote_rpc` " + " WHERE `module_id` = ?"; + +const std::string kInsertModuleType = + "INSERT OR IGNORE INTO `module_type` (`application_id`, `name`) VALUES (?, " + "?)"; + +const std::string kSelectModuleTypes = + "SELECT DISTINCT `name` FROM `module_type` WHERE `application_id` = ?"; + +const std::string kDropSchema = + "BEGIN; " + "DROP INDEX IF EXISTS `module_type.fk_module_type_application1_idx`; " + "DROP TABLE IF EXISTS `module_type`; " + "DROP INDEX IF EXISTS `message.fk_messages_languages1_idx`; " + "DROP INDEX IF EXISTS " + "`message.fk_message_consumer_friendly_messages1_idx`; " + "DROP TABLE IF EXISTS `message`; " + "DROP INDEX IF EXISTS `endpoint.fk_endpoint_application1_idx`; " + "DROP TABLE IF EXISTS `endpoint`; " + "DROP INDEX IF EXISTS `consent_group.fk_consent_group_device1_idx`; " + "DROP INDEX IF EXISTS " + "`consent_group.fk_consent_group_functional_group1_idx`; " + "DROP TABLE IF EXISTS `consent_group`; " + "DROP TABLE IF EXISTS `external_consent_status_group`; " + "DROP TABLE IF EXISTS `external_consent_entities`; " + "DROP INDEX IF EXISTS `app_type.fk_app_type_application1_idx`; " + "DROP TABLE IF EXISTS `app_type`; " + "DROP TABLE IF EXISTS `request_type`; " + "DROP INDEX IF EXISTS `nickname.fk_nickname_application1_idx`; " + "DROP TABLE IF EXISTS `nickname`; " + "DROP INDEX IF EXISTS `app_level.fk_app_level_language2_idx`; " + "DROP INDEX IF EXISTS `app_level.fk_app_level_language1_idx`; " + "DROP INDEX IF EXISTS `app_level.fk_app_levels_application1_idx`; " + "DROP TABLE IF EXISTS `app_level`; " + "DROP INDEX IF EXISTS " + "`device_consent_group.fk_device_has_functional_group_device1_idx`; " + "DROP INDEX IF EXISTS " + "`device_consent_group.fk_device_has_functional_group_functional_group1_" + "idx`; " + "DROP TABLE IF EXISTS `device_consent_group`; " + "DROP TABLE IF EXISTS `seconds_between_retry`; " + "DROP INDEX IF EXISTS " + "`preconsented_group.fk_application_has_functional_group_application2_idx`;" + " " + "DROP INDEX IF EXISTS " + "`preconsented_group.fk_application_has_functional_group_functional_group2_" + "idx`; " + "DROP TABLE IF EXISTS `preconsented_group`; " + "DROP INDEX IF EXISTS " + "`app_group_primary.fk_application_has_functional_group_application1_idx`; " + "DROP INDEX IF EXISTS " + "`app_group_primary.fk_application_has_functional_group_functional_group1_" + "idx`; " + "DROP TABLE IF EXISTS `app_group_primary`; " + "DROP INDEX IF EXISTS " + "`app_group_non_primary.fk_application_has_functional_group_application1_" + "idx`; " + "DROP INDEX IF EXISTS " + "`app_group_non_primary.fk_application_has_functional_group_functional_" + "group1_idx`; " + "DROP TABLE IF EXISTS `app_group_non_primary`; " + "DROP TABLE IF EXISTS `interior_zone`; " + "DROP TABLE IF EXISTS `access_module`; " + "DROP INDEX IF EXISTS `access_module.zone_module`; " + "DROP INDEX IF EXISTS `access_module.fk_module_1_idx`; " + "DROP INDEX IF EXISTS " + "`app_group.fk_application_has_functional_group_application1_idx`; " + "DROP INDEX IF EXISTS " + "`app_group.fk_application_has_functional_group_functional_group1_idx`; " + "DROP TABLE IF EXISTS `app_group`; " + "DROP INDEX IF EXISTS `application.fk_application_priorities1_idx`; " + "DROP INDEX IF EXISTS `application.fk_application_hmi_level1_idx`; " + "DROP TABLE IF EXISTS `application`; " + "DROP INDEX IF EXISTS `rpc.select_rpc_name_hmi_level`; " + "DROP INDEX IF EXISTS `rpc.fk_rpc_functional_group1_idx`; " + "DROP INDEX IF EXISTS `rpc.fk_rpc_hmi_level1_idx`; " + "DROP TABLE IF EXISTS `rpc`; " + "DROP TABLE IF EXISTS `version`; " + "DROP TABLE IF EXISTS `message_type`; " + "DROP TABLE IF EXISTS `language`; " + "DROP INDEX IF EXISTS " + "`notifications_by_priority.fk_notifications_by_priority_priority1_idx`; " + "DROP TABLE IF EXISTS `notifications_by_priority`; " + "DROP TABLE IF EXISTS `hmi_level`; " + "DROP TABLE IF EXISTS `priority`; " + "DROP TABLE IF EXISTS `functional_group`; " + "DROP TABLE IF EXISTS `module_config`; " + "DROP TABLE IF EXISTS `remote_rpc`; " + "DROP INDEX IF EXISTS `remote_rpc.fk_remote_rpc_1_idx`; " + "DROP TABLE IF EXISTS `module_meta`; " + "DROP TABLE IF EXISTS `usage_and_error_count`; " + "DROP TABLE IF EXISTS `device`; " + "DROP TABLE IF EXISTS `_internal_data`; " + "DROP TABLE IF EXISTS `_internal_external_consent_status`; " + "COMMIT; " + "VACUUM;"; + +const std::string kDeleteData = + "BEGIN; " + "DELETE FROM `message`; " + "DELETE FROM `module_type`; " + "DELETE FROM `endpoint`; " + "DELETE FROM `consent_group`; " + "DELETE FROM `external_consent_status_group`; " + "DELETE FROM `external_consent_entities`; " + "DELETE FROM `app_type`; " + "DELETE FROM `nickname`; " + "DELETE FROM `app_level`; " + "DELETE FROM `device_consent_group`; " + "DELETE FROM `seconds_between_retry`; " + "DELETE FROM `preconsented_group`; " + "DELETE FROM `app_group`; " + "DELETE FROM `application`; " + "DELETE FROM `rpc`; " + "DELETE FROM `app_group_primary`; " + "DELETE FROM `app_group_non_primary`; " + "DELETE FROM `interior_zone`; " + "DELETE FROM `access_module`; " + "DELETE FROM `version`; " + "DELETE FROM `message_type`; " + "DELETE FROM `language`; " + "DELETE FROM `notifications_by_priority`; " + "DELETE FROM `hmi_level`; " + "DELETE FROM `priority`; " + "DELETE FROM `functional_group`; " + "DELETE FROM `module_config`; " + "DELETE FROM `module_meta`; " + "DELETE FROM `remote_rpc`; " + "DELETE FROM `usage_and_error_count`; " + "DELETE FROM `device`; " + "DELETE FROM `request_type`; " + "COMMIT; " + "VACUUM;"; + +const std::string kCheckDBIntegrity = "PRAGMA integrity_check"; + +const std::string kCheckPgNumber = "PRAGMA page_count"; + +const std::string kSelectRpc = + "SELECT DISTINCT `rpc`.`parameter` FROM `rpc` " + " JOIN `app_group` AS `g` ON (`g`.`functional_group_id` = " + "`rpc`.`functional_group_id` " + " AND (`g`.`application_id` = ?)) " + "WHERE `rpc`.`hmi_level_value` = ? AND `rpc`.`name` = ?"; + +const std::string kSelectPreloaded = + "SELECT `preloaded_pt` FROM `module_config` " + "WHERE `preloaded_pt` = 1 LIMIT 1"; + +const std::string kUpdatePreloaded = + "UPDATE `module_config` SET `preloaded_pt` = ?"; + +const std::string kIsFirstRun = "SELECT `is_first_run` FROM `module_config` "; + +const std::string kSetNotFirstRun = + "UPDATE `module_config` SET `is_first_run`= 0 "; + +const std::string kSelectEndpoint = + "SELECT `url`, `application_id` FROM `endpoint` WHERE `service` = ? "; + +const std::string kSelectLockScreenIcon = + "SELECT `url` FROM `endpoint` WHERE `service` = ? AND `application_id` = ?"; + +const std::string kInsertFunctionalGroup = + "INSERT INTO `functional_group` (`id`, `name`, `user_consent_prompt`) " + " VALUES (?, ?, ?)"; + +const std::string kInsertRpc = + "INSERT INTO `rpc` (`name`, `hmi_level_value`, `functional_group_id`) " + " VALUES (?, ?, ?)"; + +const std::string kInsertExternalConsentEntity = + "INSERT INTO `external_consent_entities` (`group_id`, `entity_type`, " + "`entity_id`, `on_off`) " + " VALUES (?, ?, ?, ?)"; + +const std::string kInsertRpcWithParameter = + "INSERT INTO `rpc` (`name`, `hmi_level_value`, `parameter`, " + "`functional_group_id`) " + " VALUES (?, ?, ?, ?)"; + +const std::string kInsertApplication = + "INSERT OR IGNORE INTO `application` (`id`, `priority_value`, " + "`is_revoked`, `memory_kb`," + " `heart_beat_timeout_ms`) VALUES (?,?,?,?,?)"; + +const std::string kInsertAppGroup = + "INSERT INTO `app_group` (`application_id`, `functional_group_id`)" + " SELECT ?, `id` FROM `functional_group` WHERE `name` = ? LIMIT 1"; + +const std::string kInsertNickname = + "INSERT OR IGNORE INTO `nickname` (`application_id`, `name`) VALUES (?, ?)"; + +const std::string kInsertAppType = + "INSERT OR IGNORE INTO `app_type` (`application_id`, `name`) VALUES (?, ?)"; + +const std::string kInsertRequestType = + "INSERT OR IGNORE INTO `request_type` (`application_id`, `request_type`) " + "VALUES (?, ?)"; + +const std::string kUpdateVersion = "UPDATE `version` SET `number`= ?"; + +const std::string kInsertMessageType = + "INSERT OR IGNORE INTO `message_type` (`name`) VALUES (?)"; + +const std::string kInsertLanguage = + "INSERT OR IGNORE INTO `language` (`code`) VALUES (?)"; + +const std::string kInsertMessageString = + "INSERT INTO `message` (`tts`, `label`, `line1`, `line2`, `language_code`, " + " `message_type_name`, `textBody`) VALUES (?, ?, ?, ?, ?, ?, ?)"; + +const std::string kUpdateModuleConfig = + "UPDATE `module_config` SET `preloaded_pt` = ?, " + " `exchange_after_x_ignition_cycles` = ?," + " `exchange_after_x_kilometers` = ?, `exchange_after_x_days` = ?, " + " `timeout_after_x_seconds` = ?, `vehicle_make` = ?, " + " `vehicle_model` = ?, `vehicle_year` = ?, `preloaded_date` = ?, " + "`certificate` = ?, `user_consent_passengersRC` = ?, " + "`country_consent_passengersRC` = ?"; + +const std::string kInsertEndpoint = + "INSERT INTO `endpoint` (`service`, `url`, `application_id`) " + " VALUES (?, ?, ?)"; + +const std::string kInsertSecondsBetweenRetry = + "INSERT INTO `seconds_between_retry` (`index`, `value`) VALUES (?, ?)"; + +const std::string kInsertNotificationsByPriority = + "INSERT OR REPLACE INTO `notifications_by_priority` (`priority_value`, " + "`value`) " + " VALUES (?, ?)"; + +const std::string kInsertDeviceData = + "INSERT OR IGNORE INTO `device` (`id`) VALUES (?)"; + +const std::string kInsertAppLevel = + "INSERT INTO `app_level` (`application_id`, `minutes_in_hmi_full`," + "`minutes_in_hmi_limited` ,`minutes_in_hmi_background`," + "`minutes_in_hmi_none`,`count_of_user_selections`," + "`count_of_rejections_sync_out_of_memory`," + "`count_of_rejections_nickname_mismatch`," + "`count_of_rejections_duplicate_name`,`count_of_rejected_rpcs_calls`," + "`count_of_rpcs_sent_in_hmi_none`,`count_of_removals_for_bad_behavior`," + "`count_of_run_attempts_while_revoked`,`app_registration_language_gui`," + "`app_registration_language_vui`, `count_of_tls_errors`) " + "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + +const std::string kDeleteSecondsBetweenRetries = + "DELETE FROM `seconds_between_retry`"; + +const std::string kDeleteEndpoint = "DELETE FROM `endpoint`"; + +const std::string kDeleteAppLevel = "DELETE FROM `app_level`"; + +const std::string kDeleteMessageString = "DELETE FROM `message`"; + +const std::string kDeleteFunctionalGroup = "DELETE FROM `functional_group`"; + +const std::string kDeleteRpc = "DELETE FROM `rpc`"; + +const std::string kDeleteExternalConsentEntities = + "DELETE FROM `external_consent_entities`"; + +const std::string kDeleteAppGroup = "DELETE FROM `app_group`"; + +const std::string kSelectModuleConfig = + "SELECT `preloaded_pt`, `exchange_after_x_ignition_cycles`, " + " `exchange_after_x_kilometers`, `exchange_after_x_days`, " + " `timeout_after_x_seconds`, `vehicle_make`," + " `vehicle_model`, `vehicle_year`, `preloaded_date`, `certificate`, " + " `user_consent_passengersRC` , `country_consent_passengersRC` " + " FROM `module_config`"; + +const std::string kSelectEndpoints = + "SELECT `url`, `service`, `application_id` FROM `endpoint` "; + +const std::string kSelectNotificationsPerMin = + "SELECT `priority_value`, `value` FROM notifications_by_priority"; + +const std::string kSelectNotificationsPerPriority = + "SELECT `value` FROM notifications_by_priority WHERE `priority_value` = ? "; + +const std::string kSelectAppLevels = "SELECT `application_id` FROM `app_level`"; + +const std::string kSelectDeviceData = "SELECT * FROM `device`"; + +const std::string kSelectFunctionalGroups = + "SELECT `id`,`name`, `user_consent_prompt` " + "FROM `functional_group`"; + +const std::string kSelectAllRpcs = + "SELECT `name`, `hmi_level_value`, `parameter` " + "FROM `rpc` WHERE `functional_group_id` = ? "; + +const std::string kSelectExternalConsentEntities = + "SELECT `entity_type`, `entity_id`, `on_off` " + "FROM `external_consent_entities` WHERE `group_id` = ? "; + +const std::string kSelectUserMsgsVersion = + "SELECT DISTINCT `number` FROM `version`"; + +const std::string kSelectAppPolicies = + "SELECT `id`, `priority_value`, `memory_kb`, " + " `heart_beat_timeout_ms` FROM `application`"; + +const std::string kCollectFriendlyMsg = "SELECT * FROM `message`"; + +const std::string kSelectAppGroups = + "SELECT `f`.`name` FROM `app_group` AS `a`" + " LEFT JOIN `functional_group` AS `f` " + " ON (`f`.`id` = `a`.`functional_group_id`)" + " WHERE `a`.`application_id` = ?"; + +const std::string kSelectNicknames = + "SELECT DISTINCT `name` FROM `nickname` " + "WHERE `application_id` = ?"; + +const std::string kSelectAppTypes = + "SELECT DISTINCT `name` FROM `app_type` " + "WHERE `application_id` = ?"; + +const std::string kSelectRequestTypes = + "SELECT DISTINCT `request_type` FROM `request_type` WHERE `application_id` " + "= ?"; + +const std::string kSelectSecondsBetweenRetries = + "SELECT `value` FROM `seconds_between_retry` ORDER BY `index`"; + +const std::string kSelectIgnitionCycles = + "SELECT `c`.`exchange_after_x_ignition_cycles`, " + " `m`.`ignition_cycles_since_last_exchange` " + " FROM `module_config` AS `c`, `module_meta` AS `m` " + "LIMIT 1"; + +const std::string kSelectKilometers = + "SELECT `c`.`exchange_after_x_kilometers`, " + " `m`.`pt_exchanged_at_odometer_x` " + " FROM `module_config` AS `c`, `module_meta` AS `m` " + "LIMIT 1"; + +const std::string kSelectDays = + "SELECT `c`.`exchange_after_x_days`, " + " `m`.`pt_exchanged_x_days_after_epoch` " + " FROM `module_config` AS `c`, `module_meta` AS `m` " + "LIMIT 1"; + +const std::string kIncrementIgnitionCycles = + "UPDATE `module_meta` SET `ignition_cycles_since_last_exchange` = 1 + " + " `ignition_cycles_since_last_exchange`"; + +const std::string kResetIgnitionCycles = + "UPDATE `module_meta` SET `ignition_cycles_since_last_exchange` = 0"; + +const std::string kSelectTimeoutResponse = + "SELECT `timeout_after_x_seconds` FROM `module_config` LIMIT 1"; + +const std::string kUpdateFlagUpdateRequired = + "UPDATE `module_meta` SET `flag_update_required` = ?"; + +const std::string kSelectFlagUpdateRequired = + "SELECT `flag_update_required` FROM `module_meta` LIMIT 1"; + +const std::string kUpdateCountersSuccessfulUpdate = + "UPDATE `module_meta` SET `pt_exchanged_at_odometer_x` = ?," + "`pt_exchanged_x_days_after_epoch` = ?"; + +const std::string kDeleteApplication = "DELETE FROM `application`"; + +const std::string kDeleteRequestType = "DELETE FROM `request_type`"; + +const std::string kSelectApplicationRevoked = + "SELECT `is_revoked` FROM `application` WHERE `id` = ?"; + +const std::string kUpdateApplicationCustomData = + "UPDATE `application` SET `is_revoked` = ?, `is_default` = ?," + "`is_predata` = ? WHERE `id` = ?"; + +const std::string kSelectApplicationRepresented = + "SELECT COUNT(`id`) FROM `application` WHERE `id` = ?"; + +const std::string kSelectApplicationIsDefault = + "SELECT `is_default` FROM `application` WHERE `id` = ?"; + +const std::string kUpdateIsDefault = + "UPDATE `application` SET `is_default` = ? WHERE `id` = ?"; + +const std::string kDeleteDevice = "DELETE FROM `device` WHERE `id` = ?"; + +const std::string kDeleteAppGroupByApplicationId = + "DELETE FROM `app_group` WHERE `application_id` = ?"; + +const std::string kInsertApplicationFull = + "INSERT OR IGNORE INTO `application` (`id`, `keep_context`, `steal_focus`, " + " `default_hmi`, `priority_value`, `is_revoked`, `is_default`, " + "`is_predata`, " + " `memory_kb`, `heart_beat_timeout_ms`) " + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + +const std::string kSelectApplicationFull = + "SELECT `keep_context`, `steal_focus`, `default_hmi`, `priority_value`, " + " `is_revoked`, `is_default`, `is_predata`, `memory_kb`," + " `heart_beat_timeout_ms` FROM `application` WHERE `id` = ?"; + +const std::string kSelectDBVersion = + "SELECT `db_version_hash` from `_internal_data`"; + +const std::string kUpdateDBVersion = + "UPDATE `_internal_data` SET `db_version_hash` = ? "; + +} // namespace sql_pt +} // namespace policy diff --git a/src/components/policy/policy_external/src/sql_pt_representation.cc b/src/components/policy/policy_external/src/sql_pt_representation.cc new file mode 100644 index 0000000000..1732f3c774 --- /dev/null +++ b/src/components/policy/policy_external/src/sql_pt_representation.cc @@ -0,0 +1,1879 @@ +/* + Copyright (c) 2013, Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sstream> +#include <stdlib.h> +#include <stdint.h> +#include <errno.h> +#include <unistd.h> + +#include "utils/logger.h" +#include "utils/date_time.h" +#include "utils/sqlite_wrapper/sql_database.h" +#include "utils/file_system.h" +#include "utils/gen_hash.h" +#include "policy/sql_pt_representation.h" +#include "policy/sql_wrapper.h" +#include "policy/sql_pt_ext_queries.h" +#include "policy/sql_pt_queries.h" +#include "policy/policy_helper.h" +#include "policy/cache_manager.h" +#include "config_profile/profile.h" + +namespace policy { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +namespace dbms = utils::dbms; + +namespace { +template <typename T, typename K> +void InsertUnique(K value, T* array) { + uint32_t i = 0; + for (; i < array->size() && array->at(i) != value; ++i) { + continue; + } + if (array->size() == i) { + array->push_back(value); + } +} + +#ifdef CUSTOMER_PASA +const char* kDatabaseName = "policy.db"; +#else // CUSTOMER_PASA +const char* kDatabaseName = "policy"; +#endif // CUSTOMER_PASA + +const std::string kExternalConsentEntitiesTypeStringOn = "ON"; +const std::string kExternalConsentEntitiesTypeStringOff = "OFF"; + +} // namespace + +SQLPTRepresentation::SQLPTRepresentation() + : db_(new utils::dbms::SQLDatabase(kDatabaseName)) { + is_in_memory = false; +} + +SQLPTRepresentation::SQLPTRepresentation(bool in_memory) { + is_in_memory = in_memory; +#ifdef __QNX__ + db_ = new utils::dbms::SQLDatabase(kDatabaseName); +#else // __QNX__ + if (in_memory) { + db_ = new utils::dbms::SQLDatabase(); + } else { + db_ = new utils::dbms::SQLDatabase(kDatabaseName); + } +#endif // __QNX__ +} + +SQLPTRepresentation::~SQLPTRepresentation() { + db_->Close(); + delete db_; +} + +std::string SQLPTRepresentation::GetLockScreenIconUrl() const { + utils::dbms::SQLQuery query(db()); + std::string ret; + if (query.Prepare(sql_pt::kSelectLockScreenIcon)) { + query.Bind(0, std::string("lock_screen_icon_url")); + query.Bind(1, std::string("default")); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect select from notifications by priority."); + return ret; + } + + if (!query.IsNull(0)) { + ret = query.GetString(0); + } + + } else { + LOG4CXX_WARN(logger_, "Invalid select endpoints statement."); + } + return ret; +} + +void SQLPTRepresentation::CheckPermissions(const PTString& app_id, + const PTString& hmi_level, + const PTString& rpc, + CheckPermissionResult& result) { + utils::dbms::SQLQuery query(db()); + + if (!query.Prepare(sql_pt::kSelectRpc)) { + LOG4CXX_WARN(logger_, + "Incorrect select statement from rpcs" + << query.LastError().text()); + return; + } + query.Bind(0, app_id); + query.Bind(1, hmi_level); + query.Bind(2, rpc); + + bool ret = query.Next(); + result.hmi_level_permitted = ret ? kRpcAllowed : kRpcDisallowed; + LOG4CXX_INFO(logger_, + "Level is " << (result.hmi_level_permitted == kRpcAllowed + ? "permitted" + : "not permitted")); + std::string parameter; + while (ret) { + if (!query.IsNull(0)) { + parameter = query.GetString(0); + result.list_of_allowed_params.insert(parameter); + } + ret = query.Next(); + } +} + +bool SQLPTRepresentation::IsPTPreloaded() { + utils::dbms::SQLQuery query(db()); + return query.Prepare(sql_pt::kSelectPreloaded) && query.Next(); +} + +int SQLPTRepresentation::IgnitionCyclesBeforeExchange() { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectIgnitionCycles) || !query.Exec()) { + LOG4CXX_WARN(logger_, "Can not select ignition cycles"); + return 0; + } + int limit = query.GetInteger(0); + int current = query.GetInteger(1); + + if (limit < 0 || current < 0 || current > limit) { + return 0; + } + + return limit - current; +} + +int SQLPTRepresentation::KilometersBeforeExchange(int current) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectKilometers) || !query.Exec()) { + LOG4CXX_WARN(logger_, "Can not select kilometers"); + return 0; + } + int limit = query.GetInteger(0); + int last = query.GetInteger(1); + + if (limit < 0 || last < 0 || current < 0 || current < last || + limit < (current - last)) { + return 0; + } + + return limit - (current - last); +} + +bool SQLPTRepresentation::SetCountersPassedForSuccessfulUpdate( + int kilometers, int days_after_epoch) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kUpdateCountersSuccessfulUpdate)) { + LOG4CXX_WARN(logger_, + "Wrong update query for counters on successful update."); + return false; + } + query.Bind(0, kilometers); + query.Bind(1, days_after_epoch); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed to update counters on successful update."); + return false; + } + return true; +} + +int SQLPTRepresentation::DaysBeforeExchange(uint16_t current) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectDays) || !query.Exec()) { + LOG4CXX_WARN(logger_, "Can not select days"); + return 0; + } + int limit = query.GetInteger(0); + int last = query.GetInteger(1); + + if (0 == last) { + return limit; + } + + if (limit < 0 || last < 0 || current < last || limit < (current - last)) { + return 0; + } + + return limit - (current - last); +} + +int SQLPTRepresentation::TimeoutResponse() { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectTimeoutResponse) || !query.Exec()) { + LOG4CXX_INFO(logger_, "Can not select timeout response for retry sequence"); + const int defaultTimeout = 30 * date_time::DateTime::MILLISECONDS_IN_SECOND; + return defaultTimeout; + } + return query.GetInteger(0) * date_time::DateTime::MILLISECONDS_IN_SECOND; +} + +bool SQLPTRepresentation::SecondsBetweenRetries(std::vector<int>* seconds) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectSecondsBetweenRetries)) { + LOG4CXX_INFO(logger_, + "Incorrect select statement from seconds between retries"); + return false; + } + while (query.Next()) { + seconds->push_back(query.GetInteger(0)); + } + return true; +} + +std::vector<UserFriendlyMessage> SQLPTRepresentation::GetUserFriendlyMsg( + const std::vector<std::string>& msg_codes, const std::string& language) { + std::vector<UserFriendlyMessage> result; + std::vector<std::string>::const_iterator it = msg_codes.begin(); + std::vector<std::string>::const_iterator it_end = msg_codes.end(); + for (; it != it_end; ++it) { + UserFriendlyMessage msg; + msg.message_code = *it; + result.push_back(msg); + } + return result; +} + +EndpointUrls SQLPTRepresentation::GetUpdateUrls(int service_type) { + LOG4CXX_INFO(logger_, + "SQLPTRepresentation::GetUpdateUrls for " << service_type); + utils::dbms::SQLQuery query(db()); + EndpointUrls ret; + if (query.Prepare(sql_pt::kSelectEndpoint)) { + query.Bind(0, service_type); + while (query.Next()) { + EndpointData data; + + data.url.push_back(query.GetString(0)); + if (!query.IsNull(1)) { + data.app_id = query.GetString(1); + } + ret.push_back(data); + } + } else { + LOG4CXX_WARN(logger_, "Invalid select endpoints statement."); + } + return ret; +} + +int SQLPTRepresentation::GetNotificationsNumber(const std::string& priority) { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectNotificationsPerPriority)) { + LOG4CXX_WARN(logger_, + "Incorrect select statement for priority " + "notification number."); + return 0; + } + query.Bind(0, priority); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect select from notifications by priority."); + return 0; + } + + if (!query.IsNull(0)) { + return query.GetInteger(0); + } + + return 0; +} + +bool SQLPTRepresentation::GetPriority(const std::string& policy_app_id, + std::string* priority) { + LOG4CXX_AUTO_TRACE(logger_); + if (NULL == priority) { + LOG4CXX_WARN(logger_, "Input priority parameter is null."); + return false; + } + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectPriority)) { + LOG4CXX_INFO(logger_, "Incorrect statement for priority."); + return false; + } + + query.Bind(0, policy_app_id); + + if (!query.Exec()) { + LOG4CXX_INFO(logger_, "Error during select priority."); + return false; + } + + if (query.IsNull(0)) { + priority->clear(); + return true; + } + + priority->assign(query.GetString(0)); + + return true; +} + +InitResult SQLPTRepresentation::Init(const PolicySettings* settings) { + settings_ = settings; + LOG4CXX_AUTO_TRACE(logger_); +#ifdef BUILD_TESTS + open_counter_ = 0; +#endif // BUILD_TESTS +#ifndef __QNX__ + if (!is_in_memory) { + const std::string& path = get_settings().app_storage_folder(); + if (!path.empty()) { + db_->set_path(path + "/"); + } + } +#endif // __QNX__ + if (!db_->Open()) { + LOG4CXX_ERROR(logger_, "Failed opening database."); + LOG4CXX_INFO(logger_, "Starting opening retries."); + const uint16_t attempts = get_settings().attempts_to_open_policy_db(); + LOG4CXX_DEBUG(logger_, "Total attempts number is: " << attempts); + bool is_opened = false; + const uint16_t open_attempt_timeout_ms = + get_settings().open_attempt_timeout_ms(); + const useconds_t sleep_interval_mcsec = open_attempt_timeout_ms * 1000; + LOG4CXX_DEBUG(logger_, + "Open attempt timeout(ms) is: " << open_attempt_timeout_ms); + for (int i = 0; i < attempts; ++i) { + usleep(sleep_interval_mcsec); + LOG4CXX_INFO(logger_, "Attempt: " << i + 1); +#ifdef BUILD_TESTS + ++open_counter_; +#endif // BUILD_TESTS + if (db_->Open()) { + LOG4CXX_INFO(logger_, "Database opened."); + is_opened = true; + break; + } + } + if (!is_opened) { + LOG4CXX_ERROR(logger_, + "Open retry sequence failed. Tried " + << attempts << " attempts with " + << open_attempt_timeout_ms + << " open timeout(ms) for each."); + return InitResult::FAIL; + } + } +#ifndef __QNX__ + if (!db_->IsReadWrite()) { + LOG4CXX_ERROR(logger_, "There are no read/write permissions for database"); + return InitResult::FAIL; + } + +#endif // __QNX__ + utils::dbms::SQLQuery check_pages(db()); + if (!check_pages.Prepare(sql_pt::kCheckPgNumber) || !check_pages.Next()) { + LOG4CXX_WARN(logger_, "Incorrect pragma for page counting."); + } else { + if (0 < check_pages.GetInteger(0)) { + utils::dbms::SQLQuery db_check(db()); + if (!db_check.Prepare(sql_pt::kCheckDBIntegrity)) { + LOG4CXX_WARN(logger_, "Incorrect pragma for integrity check."); + } else { + while (db_check.Next()) { + if (db_check.GetString(0).compare("ok") == 0) { + utils::dbms::SQLQuery check_first_run(db()); + if (check_first_run.Prepare(sql_pt::kIsFirstRun) && + check_first_run.Next()) { + LOG4CXX_INFO(logger_, + "Selecting is first run " + << check_first_run.GetBoolean(0)); + if (check_first_run.GetBoolean(0)) { + utils::dbms::SQLQuery set_not_first_run(db()); + set_not_first_run.Exec(sql_pt::kSetNotFirstRun); + return InitResult::SUCCESS; + } + } else { + LOG4CXX_WARN(logger_, "Incorrect select is first run"); + } + return InitResult::EXISTS; + } else { + LOG4CXX_ERROR(logger_, + "Existing policy table representation is invlaid."); + // TODO(PV): add handle + return InitResult::FAIL; + } + } + } + } + } + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kCreateSchema)) { + LOG4CXX_ERROR( + logger_, + "Failed creating schema of database: " << query.LastError().text()); + return InitResult::FAIL; + } + if (!query.Exec(sql_pt::kInsertInitData)) { + LOG4CXX_ERROR( + logger_, + "Failed insert init data to database: " << query.LastError().text()); + return InitResult::FAIL; + } + return InitResult::SUCCESS; +} + +bool SQLPTRepresentation::Close() { + db_->Close(); + return db_->LastError().number() == utils::dbms::OK; +} + +const VehicleInfo SQLPTRepresentation::GetVehicleInfo() const { + policy_table::ModuleConfig module_config; + GatherModuleConfig(&module_config); + VehicleInfo vehicle_info; + vehicle_info.vehicle_make = *module_config.vehicle_make; + vehicle_info.vehicle_model = *module_config.vehicle_model; + vehicle_info.vehicle_year = *module_config.vehicle_year; + return vehicle_info; +} + +bool SQLPTRepresentation::Drop() { + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kDropSchema)) { + LOG4CXX_WARN(logger_, + "Failed dropping database: " << query.LastError().text()); + return false; + } + return true; +} + +void SQLPTRepresentation::WriteDb() { + db_->Backup(); +} + +bool SQLPTRepresentation::Clear() { + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kDeleteData)) { + LOG4CXX_ERROR(logger_, + "Failed clearing database: " << query.LastError().text()); + return false; + } + if (!query.Exec(sql_pt::kInsertInitData)) { + LOG4CXX_ERROR( + logger_, + "Failed insert init data to database: " << query.LastError().text()); + return false; + } + return true; +} + +bool SQLPTRepresentation::RefreshDB() { + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kDropSchema)) { + LOG4CXX_WARN(logger_, + "Failed dropping database: " << query.LastError().text()); + return false; + } + if (!query.Exec(sql_pt::kCreateSchema)) { + LOG4CXX_ERROR( + logger_, + "Failed creating schema of database: " << query.LastError().text()); + return false; + } + if (!query.Exec(sql_pt::kInsertInitData)) { + LOG4CXX_ERROR( + logger_, + "Failed insert init data to database: " << query.LastError().text()); + return false; + } + return true; +} + +utils::SharedPtr<policy_table::Table> SQLPTRepresentation::GenerateSnapshot() + const { + LOG4CXX_AUTO_TRACE(logger_); + utils::SharedPtr<policy_table::Table> table = new policy_table::Table(); + GatherModuleMeta(&*table->policy_table.module_meta); + GatherModuleConfig(&table->policy_table.module_config); + GatherUsageAndErrorCounts(&*table->policy_table.usage_and_error_counts); + GatherDeviceData(&*table->policy_table.device_data); + GatherFunctionalGroupings(&table->policy_table.functional_groupings); + GatherConsumerFriendlyMessages( + &*table->policy_table.consumer_friendly_messages); + GatherApplicationPoliciesSection(&table->policy_table.app_policies_section); + return table; +} + +void SQLPTRepresentation::GatherModuleMeta( + policy_table::ModuleMeta* meta) const { + LOG4CXX_INFO(logger_, "Gather Module Meta Info"); + meta->mark_initialized(); + // Section Module Meta is empty for SDL specific +} + +void SQLPTRepresentation::GatherModuleConfig( + policy_table::ModuleConfig* config) const { + LOG4CXX_INFO(logger_, "Gather Configuration Info"); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectModuleConfig) || !query.Next()) { + LOG4CXX_WARN(logger_, "Incorrect select statement for module config"); + } else { + *config->preloaded_pt = query.GetBoolean(0); + config->exchange_after_x_ignition_cycles = query.GetInteger(1); + config->exchange_after_x_kilometers = query.GetInteger(2); + config->exchange_after_x_days = query.GetInteger(3); + config->timeout_after_x_seconds = query.GetInteger(4); + *config->vehicle_make = query.GetString(5); + *config->vehicle_model = query.GetString(6); + *config->vehicle_year = query.GetString(7); + *config->preloaded_date = query.GetString(8); + *config->certificate = query.GetString(9); + } + + utils::dbms::SQLQuery endpoints(db()); + if (!endpoints.Prepare(sql_pt::kSelectEndpoints)) { + LOG4CXX_WARN(logger_, "Incorrect select statement for endpoints"); + } else { + while (endpoints.Next()) { + std::stringstream stream; + stream << "0x0" << endpoints.GetInteger(1); + config->endpoints[stream.str()][endpoints.GetString(2)].push_back( + endpoints.GetString(0)); + } + } + + utils::dbms::SQLQuery notifications(db()); + if (!notifications.Prepare(sql_pt::kSelectNotificationsPerMin)) { + LOG4CXX_WARN(logger_, "Incorrect select statement for notifications"); + } else { + while (notifications.Next()) { + config->notifications_per_minute_by_priority[notifications.GetString(0)] = + notifications.GetInteger(1); + } + } + utils::dbms::SQLQuery seconds(db()); + if (!seconds.Prepare(sql_pt::kSelectSecondsBetweenRetries)) { + LOG4CXX_INFO(logger_, + "Incorrect select statement from seconds between retries"); + } else { + while (seconds.Next()) { + config->seconds_between_retries.push_back(seconds.GetInteger(0)); + } + } +} + +bool SQLPTRepresentation::GatherUsageAndErrorCounts( + policy_table::UsageAndErrorCounts* counts) const { + LOG4CXX_INFO(logger_, "Gather Usage and Error Counts."); + utils::dbms::SQLQuery query(db()); + if (query.Prepare(sql_pt::kSelectAppLevels)) { + policy_table::AppLevel app_level_empty; + app_level_empty.mark_initialized(); + while (query.Next()) { + (*counts->app_level)[query.GetString(0)] = app_level_empty; + } + } + return true; +} + +void SQLPTRepresentation::GatherDeviceData( + policy_table::DeviceData* data) const { + LOG4CXX_INFO(logger_, "Gather device data."); + data->mark_initialized(); + + utils::dbms::SQLQuery query(db()); + if (query.Prepare(sql_pt::kSelectDeviceData)) { + policy_table::DeviceParams device_data_empty; + device_data_empty.mark_initialized(); + while (query.Next()) { + (*data)[query.GetString(0)] = device_data_empty; + } + } +} + +bool SQLPTRepresentation::GatherFunctionalGroupings( + policy_table::FunctionalGroupings* groups) const { + LOG4CXX_INFO(logger_, "Gather Functional Groupings info"); + utils::dbms::SQLQuery func_group(db()); + if (!func_group.Prepare(sql_pt::kSelectFunctionalGroups)) { + LOG4CXX_WARN(logger_, "Incorrect select from functional_groupings"); + return false; + } + + utils::dbms::SQLQuery rpcs(db()); + if (!rpcs.Prepare(sql_pt::kSelectAllRpcs)) { + LOG4CXX_WARN(logger_, "Incorrect select all from rpc"); + return false; + } + + utils::dbms::SQLQuery external_consent_entities(db()); + if (!external_consent_entities.Prepare( + sql_pt::kSelectExternalConsentEntities)) { + LOG4CXX_WARN(logger_, + "Incorrect select statement for 'external_consent_entities'."); + return false; + } + + while (func_group.Next()) { + policy_table::Rpcs rpcs_tbl; + + if (!func_group.IsNull(2)) { + *rpcs_tbl.user_consent_prompt = func_group.GetString(2); + } + + const int group_id = func_group.GetInteger(0); + + rpcs.Bind(0, group_id); + + while (rpcs.Next()) { + if (!rpcs.IsNull(1)) { + policy_table::HmiLevel level; + if (policy_table::EnumFromJsonString(rpcs.GetString(1), &level)) { + InsertUnique(level, &rpcs_tbl.rpcs[rpcs.GetString(0)].hmi_levels); + } + } + if (!rpcs.IsNull(2)) { + policy_table::Parameter param; + if (policy_table::EnumFromJsonString(rpcs.GetString(2), ¶m)) { + // EMPTY is a special mark to specify that 'parameters' section is + // present, but has no parameters. It is not valid parameter value. + if (policy_table::P_EMPTY == param) { + (*rpcs_tbl.rpcs[rpcs.GetString(0)].parameters).mark_initialized(); + continue; + } + InsertUnique(param, &(*rpcs_tbl.rpcs[rpcs.GetString(0)].parameters)); + } + } + } + + rpcs.Reset(); + + if (!rpcs_tbl.rpcs.is_initialized()) { + rpcs_tbl.rpcs.set_to_null(); + } + + // Collecting entities for disallowed_by_external_consent_entities_on/off + external_consent_entities.Bind(0, group_id); + while (external_consent_entities.Next()) { + policy_table::ExternalConsentEntity external_consent_entity( + external_consent_entities.GetInteger(0), + external_consent_entities.GetInteger(1)); + + policy_table::DisallowedByExternalConsentEntities& + external_consent_entities_container = + kExternalConsentEntitiesTypeStringOn == + external_consent_entities.GetString(2) + ? *rpcs_tbl.disallowed_by_external_consent_entities_on + : *rpcs_tbl.disallowed_by_external_consent_entities_off; + + external_consent_entities_container.push_back(external_consent_entity); + } + external_consent_entities.Reset(); + (*groups)[func_group.GetString(1)] = rpcs_tbl; + } + return true; +} + +bool SQLPTRepresentation::GatherConsumerFriendlyMessages( + policy_table::ConsumerFriendlyMessages* messages) const { + LOG4CXX_INFO(logger_, "Gather Consumer Friendly Messages"); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectUserMsgsVersion) || !query.Next()) { + LOG4CXX_WARN(logger_, "Incorrect select from consumer_friendly_messages"); + return false; + } + + messages->version = query.GetString(0); + + if (query.Prepare(sql_pt::kCollectFriendlyMsg)) { + while (query.Next()) { + UserFriendlyMessage msg; + msg.message_code = query.GetString(7); + std::string language = query.GetString(6); + + (*messages->messages)[msg.message_code].languages[language]; + } + } else { + LOG4CXX_WARN(logger_, "Incorrect statement for select friendly messages."); + } + + return true; +} + +bool SQLPTRepresentation::GatherApplicationPoliciesSection( + policy_table::ApplicationPoliciesSection* policies) const { + LOG4CXX_INFO(logger_, "Gather applications policies"); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectAppPolicies)) { + LOG4CXX_WARN(logger_, "Incorrect select from app_policies"); + return false; + } + + while (query.Next()) { + rpc::Nullable<policy_table::ApplicationParams> params; + const std::string& app_id = query.GetString(0); + if (IsApplicationRevoked(app_id)) { + params.set_to_null(); + (*policies).apps[app_id] = params; + continue; + } + if (IsDefaultPolicy(app_id)) { + (*policies).apps[app_id].set_to_string(kDefaultId); + } + if (IsPredataPolicy(app_id)) { + (*policies).apps[app_id].set_to_string(kPreDataConsentId); + } + if (kDeviceId == app_id) { + // Priority is only SDL-specific item for device + policy_table::Priority priority; + policy_table::EnumFromJsonString(query.GetString(1), &priority); + (*policies).device.priority = priority; + continue; + } + policy_table::Priority priority; + policy_table::EnumFromJsonString(query.GetString(1), &priority); + params.priority = priority; + + *params.memory_kb = query.GetInteger(2); + *params.heart_beat_timeout_ms = query.GetUInteger(3); + + if (!GatherAppGroup(app_id, ¶ms.groups)) { + return false; + } + if (!GatherNickName(app_id, &*params.nicknames)) { + return false; + } + if (!GatherAppType(app_id, &*params.AppHMIType)) { + return false; + } + if (!GatherRequestType(app_id, &*params.RequestType)) { + return false; + } + + (*policies).apps[app_id] = params; + } + return true; +} + +bool SQLPTRepresentation::Save(const policy_table::Table& table) { + LOG4CXX_AUTO_TRACE(logger_); + db_->BeginTransaction(); + if (!SaveFunctionalGroupings(table.policy_table.functional_groupings)) { + db_->RollbackTransaction(); + return false; + } + if (!SaveApplicationPoliciesSection( + table.policy_table.app_policies_section)) { + db_->RollbackTransaction(); + return false; + } + if (!SaveModuleConfig(table.policy_table.module_config)) { + db_->RollbackTransaction(); + return false; + } + if (!SaveConsumerFriendlyMessages( + *table.policy_table.consumer_friendly_messages)) { + db_->RollbackTransaction(); + return false; + } + + if (!SaveDeviceData(*table.policy_table.device_data)) { + db_->RollbackTransaction(); + return false; + } + if (!SaveUsageAndErrorCounts(*table.policy_table.usage_and_error_counts)) { + db_->RollbackTransaction(); + return false; + } + if (!SaveModuleMeta(*table.policy_table.module_meta)) { + db_->RollbackTransaction(); + return false; + } + db_->CommitTransaction(); + return true; +} + +bool SQLPTRepresentation::SaveFunctionalGroupings( + const policy_table::FunctionalGroupings& groups) { + utils::dbms::SQLQuery query_delete(db()); + if (!query_delete.Exec(sql_pt::kDeleteRpc)) { + LOG4CXX_WARN(logger_, "Incorrect delete from rpc."); + return false; + } + + if (!query_delete.Exec(sql_pt::kDeleteExternalConsentEntities)) { + LOG4CXX_WARN(logger_, "Incorrect delete from external consent entities."); + return false; + } + + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kDeleteFunctionalGroup)) { + LOG4CXX_WARN(logger_, "Incorrect delete from seconds between retries."); + return false; + } + + if (!query.Prepare(sql_pt::kInsertFunctionalGroup)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for functional groups"); + return false; + } + + policy_table::FunctionalGroupings::const_iterator groups_it; + + for (groups_it = groups.begin(); groups_it != groups.end(); ++groups_it) { + // Since we uses this id in other tables, we have to be sure + // that id for certain group will be same in case when + // we drop records from the table and add them again. + // That's why we use hash as a primary key insted of + // simple auto incremental index. + const long int id = abs(utils::Djb2HashFromString(groups_it->first)); + // SQLite's Bind doesn support 'long' type + // So we need to explicitly cast it to int64_t + // to avoid ambiguity. + query.Bind(0, static_cast<int64_t>(id)); + query.Bind(1, groups_it->first); + groups_it->second.user_consent_prompt.is_initialized() + ? query.Bind(2, *(groups_it->second.user_consent_prompt)) + : query.Bind(2); + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into functional groups"); + return false; + } + + const int64_t last_group_id = query.LastInsertId(); + + if (!SaveRpcs(last_group_id, groups_it->second.rpcs)) { + return false; + } + + if (!SaveExternalConsentEntities( + last_group_id, + *groups_it->second.disallowed_by_external_consent_entities_on, + kExternalConsentEntitiesTypeOn)) { + return false; + } + + if (!SaveExternalConsentEntities( + last_group_id, + *groups_it->second.disallowed_by_external_consent_entities_off, + kExternalConsentEntitiesTypeOff)) { + return false; + } + } + + return true; +} + +bool SQLPTRepresentation::SaveRpcs(int64_t group_id, + const policy_table::Rpc& rpcs) { + utils::dbms::SQLQuery query(db()); + utils::dbms::SQLQuery query_parameter(db()); + if (!query.Prepare(sql_pt::kInsertRpc) || + !query_parameter.Prepare(sql_pt::kInsertRpcWithParameter)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for rpc"); + return false; + } + + policy_table::Rpc::const_iterator it; + for (it = rpcs.begin(); it != rpcs.end(); ++it) { + const policy_table::HmiLevels& hmi_levels = it->second.hmi_levels; + // TODO(IKozyrenko): Check logic if optional container is missing + const policy_table::Parameters& parameters = *it->second.parameters; + policy_table::HmiLevels::const_iterator hmi_it; + policy_table::Parameters::const_iterator ps_it; + for (hmi_it = hmi_levels.begin(); hmi_it != hmi_levels.end(); ++hmi_it) { + if (!parameters.empty()) { + for (ps_it = parameters.begin(); ps_it != parameters.end(); ++ps_it) { + query_parameter.Bind(0, it->first); + query_parameter.Bind( + 1, std::string(policy_table::EnumToJsonString(*hmi_it))); + query_parameter.Bind( + 2, std::string(policy_table::EnumToJsonString(*ps_it))); + query_parameter.Bind(3, group_id); + if (!query_parameter.Exec() || !query_parameter.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into rpc with parameter"); + return false; + } + } + } else if (parameters.is_initialized()) { + query_parameter.Bind(0, it->first); + query_parameter.Bind( + 1, std::string(policy_table::EnumToJsonString(*hmi_it))); + query_parameter.Bind( + 2, + std::string(policy_table::EnumToJsonString(policy_table::P_EMPTY))); + query_parameter.Bind(3, group_id); + if (!query_parameter.Exec() || !query_parameter.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into rpc with parameter"); + return false; + } + } else { + query.Bind(0, it->first); + query.Bind(1, std::string(policy_table::EnumToJsonString(*hmi_it))); + query.Bind(2, group_id); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into rpc"); + return false; + } + } + } + } + + return true; +} + +bool SQLPTRepresentation::SaveApplicationPoliciesSection( + const policy_table::ApplicationPoliciesSection& policies) { + utils::dbms::SQLQuery query_delete(db()); + if (!query_delete.Exec(sql_pt::kDeleteAppGroup)) { + LOG4CXX_WARN(logger_, "Incorrect delete from app_group."); + return false; + } + if (!query_delete.Exec(sql_pt::kDeleteApplication)) { + LOG4CXX_WARN(logger_, "Incorrect delete from application."); + return false; + } + + if (!query_delete.Exec(sql_pt::kDeleteRequestType)) { + LOG4CXX_WARN(logger_, "Incorrect delete from request type."); + return false; + } + + // All predefined apps (e.g. default, pre_DataConsent) should be saved first, + // otherwise another app with the predefined permissions can get incorrect + // permissions + policy_table::ApplicationPolicies::const_iterator it_default = + policies.apps.find(kDefaultId); + if (policies.apps.end() != it_default) { + if (!SaveSpecificAppPolicy(*it_default)) { + return false; + } + } + policy_table::ApplicationPolicies::const_iterator it_pre_data_consented = + policies.apps.find(kPreDataConsentId); + if (policies.apps.end() != it_pre_data_consented) { + if (!SaveSpecificAppPolicy(*it_pre_data_consented)) { + return false; + } + } + + if (!SaveDevicePolicy(policies.device)) { + return false; + } + + policy_table::ApplicationPolicies::const_iterator it; + for (it = policies.apps.begin(); it != policies.apps.end(); ++it) { + // Skip saving of predefined app, since they should be saved before + if (IsPredefinedApp(*it)) { + continue; + } + if (!SaveSpecificAppPolicy(*it)) { + return false; + } + } + + return true; +} + +bool SQLPTRepresentation::SaveSpecificAppPolicy( + const policy_table::ApplicationPolicies::value_type& app) { + utils::dbms::SQLQuery app_query(db()); + if (!app_query.Prepare(sql_pt::kInsertApplication)) { + LOG4CXX_WARN(logger_, + "Incorrect insert statement into application (device)."); + return false; + } + + app_query.Bind(0, app.first); + app_query.Bind( + 1, std::string(policy_table::EnumToJsonString(app.second.priority))); + app_query.Bind(2, app.second.is_null()); + app_query.Bind(3, *app.second.memory_kb); + app_query.Bind(4, static_cast<int64_t>(*app.second.heart_beat_timeout_ms)); + + if (!app_query.Exec() || !app_query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into application."); + return false; + } + + if (app.second.is_string()) { + if (kDefaultId.compare(app.second.get_string()) == 0) { + if (!SetDefaultPolicy(app.first)) { + return false; + } + // Stop saving other params, since predefined permissions already set + return true; + } + } + + if (!SaveAppGroup(app.first, app.second.groups)) { + return false; + } + if (!SaveNickname(app.first, *app.second.nicknames)) { + return false; + } + if (!SaveAppType(app.first, *app.second.AppHMIType)) { + return false; + } + + if (!SaveRequestType(app.first, *app.second.RequestType)) { + return false; + } + + return true; +} + +bool policy::SQLPTRepresentation::SaveDevicePolicy( + const policy_table::DevicePolicy& device) { + utils::dbms::SQLQuery app_query(db()); + if (!app_query.Prepare(sql_pt::kInsertApplication)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement into application."); + return false; + } + + app_query.Bind(0, kDeviceId); + app_query.Bind(1, + std::string(policy_table::EnumToJsonString(device.priority))); + app_query.Bind(2, false); + app_query.Bind(3, 0); + app_query.Bind(4, 0); + app_query.Bind(5); + + if (!app_query.Exec() || !app_query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into application."); + return false; + } + + if (!SaveAppGroup(kDeviceId, device.groups)) { + return false; + } + + return true; +} + +bool SQLPTRepresentation::SaveAppGroup( + const std::string& app_id, const policy_table::Strings& app_groups) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertAppGroup)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for app group"); + return false; + } + LOG4CXX_INFO(logger_, "SaveAppGroup"); + policy_table::Strings::const_iterator it; + for (it = app_groups.begin(); it != app_groups.end(); ++it) { + std::string ssss = *it; + LOG4CXX_INFO(logger_, "Group: " << ssss); + query.Bind(0, app_id); + query.Bind(1, *it); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, + "Incorrect insert into app group." + << query.LastError().text()); + return false; + } + } + + return true; +} + +bool SQLPTRepresentation::SaveNickname(const std::string& app_id, + const policy_table::Strings& nicknames) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertNickname)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for nickname"); + return false; + } + + policy_table::Strings::const_iterator it; + for (it = nicknames.begin(); it != nicknames.end(); ++it) { + query.Bind(0, app_id); + query.Bind(1, *it); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into nickname."); + return false; + } + } + + return true; +} + +bool SQLPTRepresentation::SaveAppType(const std::string& app_id, + const policy_table::AppHMITypes& types) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertAppType)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for app type"); + return false; + } + + policy_table::AppHMITypes::const_iterator it; + for (it = types.begin(); it != types.end(); ++it) { + query.Bind(0, app_id); + query.Bind(1, std::string(policy_table::EnumToJsonString(*it))); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into app type."); + return false; + } + } + + return true; +} + +bool SQLPTRepresentation::SaveRequestType( + const std::string& app_id, const policy_table::RequestTypes& types) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertRequestType)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for request types."); + return false; + } + + policy_table::RequestTypes::const_iterator it; + for (it = types.begin(); it != types.end(); ++it) { + query.Bind(0, app_id); + query.Bind(1, std::string(policy_table::EnumToJsonString(*it))); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into request types."); + return false; + } + } + + return true; +} + +bool SQLPTRepresentation::SaveModuleMeta(const policy_table::ModuleMeta& meta) { + // Section Module Meta is empty for SDL specific + return true; +} + +bool SQLPTRepresentation::SaveModuleConfig( + const policy_table::ModuleConfig& config) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kUpdateModuleConfig)) { + LOG4CXX_WARN(logger_, "Incorrect update statement for module config"); + return false; + } + + bool is_preloaded = + config.preloaded_pt.is_initialized() && *config.preloaded_pt; + + query.Bind(0, is_preloaded); + query.Bind(1, config.exchange_after_x_ignition_cycles); + query.Bind(2, config.exchange_after_x_kilometers); + query.Bind(3, config.exchange_after_x_days); + query.Bind(4, config.timeout_after_x_seconds); + config.vehicle_make.is_initialized() ? query.Bind(5, *(config.vehicle_make)) + : query.Bind(5); + config.vehicle_model.is_initialized() ? query.Bind(6, *(config.vehicle_model)) + : query.Bind(6); + config.vehicle_year.is_initialized() ? query.Bind(7, *(config.vehicle_year)) + : query.Bind(7); + config.preloaded_date.is_initialized() + ? query.Bind(8, *(config.preloaded_date)) + : query.Bind(8); + config.certificate.is_initialized() ? query.Bind(9, *(config.certificate)) + : query.Bind(9); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect update module config"); + return false; + } + + if (!SaveSecondsBetweenRetries(config.seconds_between_retries)) { + return false; + } + + if (!SaveNumberOfNotificationsPerMinute( + config.notifications_per_minute_by_priority)) { + return false; + } + + if (!SaveServiceEndpoints(config.endpoints)) { + return false; + } + + return true; +} + +bool SQLPTRepresentation::SaveServiceEndpoints( + const policy_table::ServiceEndpoints& endpoints) { + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kDeleteEndpoint)) { + LOG4CXX_WARN(logger_, "Incorrect delete from endpoint."); + return false; + } + + if (!query.Prepare(sql_pt::kInsertEndpoint)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for endpoint"); + return false; + } + + policy_table::ServiceEndpoints::const_iterator it; + for (it = endpoints.begin(); it != endpoints.end(); ++it) { + const policy_table::URLList& apps = it->second; + policy_table::URLList::const_iterator app_it; + for (app_it = apps.begin(); app_it != apps.end(); ++app_it) { + const policy_table::URL& urls = app_it->second; + policy_table::URL::const_iterator url_it; + for (url_it = urls.begin(); url_it != urls.end(); ++url_it) { + std::stringstream temp_stream(it->first); + int service; + temp_stream.seekg(3); + temp_stream >> service; + query.Bind(0, service); + query.Bind(1, *url_it); + query.Bind(2, app_it->first); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into endpoint"); + return false; + } + } + } + } + + return true; +} + +bool SQLPTRepresentation::SaveConsumerFriendlyMessages( + const policy_table::ConsumerFriendlyMessages& messages) { + LOG4CXX_AUTO_TRACE(logger_); + + // According CRS-2419 If there is no “consumer_friendly_messages” key, + // the current local consumer_friendly_messages section shall be maintained in + // the policy table. So it won't be changed/updated + if (messages.messages.is_initialized()) { + utils::dbms::SQLQuery query(db()); + if (!messages.messages->empty()) { + if (!query.Exec(sql_pt::kDeleteMessageString)) { + LOG4CXX_WARN(logger_, "Incorrect delete from message."); + return false; + } + } + + if (query.Prepare(sql_pt::kUpdateVersion)) { + query.Bind(0, messages.version); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect update into version."); + return false; + } + } else { + LOG4CXX_WARN(logger_, "Incorrect update statement for version."); + return false; + } + + policy_table::Messages::const_iterator it; + // TODO(IKozyrenko): Check logic if optional container is missing + for (it = messages.messages->begin(); it != messages.messages->end(); + ++it) { + if (!SaveMessageType(it->first)) { + return false; + } + const policy_table::Languages& langs = it->second.languages; + policy_table::Languages::const_iterator lang_it; + for (lang_it = langs.begin(); lang_it != langs.end(); ++lang_it) { + if (!SaveLanguage(lang_it->first)) { + return false; + } + if (!SaveMessageString(it->first, lang_it->first, lang_it->second)) { + return false; + } + } + } + } else { + LOG4CXX_INFO(logger_, "Messages list is empty"); + } + + return true; +} + +bool SQLPTRepresentation::SaveMessageType(const std::string& type) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertMessageType)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for message type."); + return false; + } + + query.Bind(0, type); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect insert into message type."); + return false; + } + + return true; +} + +bool SQLPTRepresentation::SaveLanguage(const std::string& code) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertLanguage)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for language."); + return false; + } + + query.Bind(0, code); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect insert into language."); + return false; + } + + return true; +} + +bool SQLPTRepresentation::SaveMessageString( + const std::string& type, + const std::string& lang, + const policy_table::MessageString& strings) { + // Section is empty for SDL specific + return true; +} + +bool SQLPTRepresentation::SaveSecondsBetweenRetries( + const policy_table::SecondsBetweenRetries& seconds) { + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kDeleteSecondsBetweenRetries)) { + LOG4CXX_WARN(logger_, "Incorrect delete from seconds between retries."); + return false; + } + if (!query.Prepare(sql_pt::kInsertSecondsBetweenRetry)) { + LOG4CXX_WARN(logger_, + "Incorrect insert statement for seconds between retries."); + return false; + } + + for (uint32_t i = 0; i < seconds.size(); ++i) { + query.Bind(0, static_cast<int>(i)); + query.Bind(1, seconds[i]); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into seconds between retries."); + return false; + } + } + + return true; +} + +bool SQLPTRepresentation::SaveNumberOfNotificationsPerMinute( + const policy_table::NumberOfNotificationsPerMinute& notifications) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertNotificationsByPriority)) { + LOG4CXX_WARN(logger_, + "Incorrect insert statement for notifications by priority."); + return false; + } + + policy_table::NumberOfNotificationsPerMinute::const_iterator it; + for (it = notifications.begin(); it != notifications.end(); ++it) { + query.Bind(0, it->first); + query.Bind(1, it->second); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into notifications by priority."); + return false; + } + } + + return true; +} + +bool SQLPTRepresentation::SaveDeviceData( + const policy_table::DeviceData& devices) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertDeviceData)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for device data."); + return false; + } + + policy_table::DeviceData::const_iterator it; + for (it = devices.begin(); it != devices.end(); ++it) { + query.Bind(0, it->first); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect insert into device data."); + return false; + } + } + + return true; +} + +bool SQLPTRepresentation::SaveUsageAndErrorCounts( + const policy_table::UsageAndErrorCounts& counts) { + const_cast<policy_table::UsageAndErrorCounts&>(counts).mark_initialized(); + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kDeleteAppLevel)) { + LOG4CXX_WARN(logger_, "Incorrect delete from app level."); + return false; + } + if (!query.Prepare(sql_pt::kInsertAppLevel)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for app level."); + return false; + } + + policy_table::AppLevels::const_iterator it; + const policy_table::AppLevels& app_levels = *counts.app_level; + const_cast<policy_table::AppLevels&>(*counts.app_level).mark_initialized(); + for (it = app_levels.begin(); it != app_levels.end(); ++it) { + query.Bind(0, it->first); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect insert into app level."); + return false; + } + } + return true; +} + +void SQLPTRepresentation::IncrementIgnitionCycles() { + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kIncrementIgnitionCycles)) { + LOG4CXX_WARN(logger_, "Failed incrementing ignition cycles"); + } +} + +void SQLPTRepresentation::ResetIgnitionCycles() { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Exec(sql_pt::kResetIgnitionCycles)) { + LOG4CXX_WARN(logger_, "Failed to reset ignition cycles number."); + } +} + +bool SQLPTRepresentation::UpdateRequired() const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectFlagUpdateRequired) || !query.Exec()) { + LOG4CXX_WARN(logger_, + "Failed select update required flag from module meta"); + return false; + } + return query.GetBoolean(0); +} + +void SQLPTRepresentation::SaveUpdateRequired(bool value) { + utils::dbms::SQLQuery query(db()); + // TODO(AOleynik): Quick fix, will be reworked + if (!query.Prepare(/*sql_pt::kUpdateFlagUpdateRequired*/ + "UPDATE `module_meta` SET `flag_update_required` = ?")) { + LOG4CXX_WARN(logger_, + "Incorrect update into module meta (update_required): " + << strerror(errno)); + return; + } + query.Bind(0, value); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed update module meta (update_required)"); + } +} + +bool SQLPTRepresentation::GetInitialAppData(const std::string& app_id, + StringArray* nicknames, + StringArray* app_types) { + LOG4CXX_INFO(logger_, "Getting initial application data."); + utils::dbms::SQLQuery app_names(db()); + if (!app_names.Prepare(sql_pt::kSelectNicknames)) { + LOG4CXX_WARN(logger_, "Incorrect select from app nicknames"); + return false; + } + utils::dbms::SQLQuery app_hmi_types(db()); + if (!app_hmi_types.Prepare(sql_pt::kSelectAppTypes)) { + LOG4CXX_WARN(logger_, "Incorrect select from app types"); + return false; + } + dbms::SQLQuery module_types(db()); + if (!module_types.Prepare(sql_pt::kSelectModuleTypes)) { + LOG4CXX_WARN(logger_, "Incorrect select from module types"); + return false; + } + + app_names.Bind(0, app_id); + while (app_names.Next()) { + nicknames->push_back(app_names.GetString(0)); + } + app_names.Reset(); + app_hmi_types.Bind(0, app_id); + while (app_hmi_types.Next()) { + app_types->push_back(app_hmi_types.GetString(0)); + } + app_hmi_types.Reset(); + module_types.Bind(0, app_id); + while (module_types.Next()) { + app_types->push_back(module_types.GetString(0)); + } + module_types.Reset(); + + return true; +} + +bool SQLPTRepresentation::GetFunctionalGroupings( + policy_table::FunctionalGroupings& groups) { + LOG4CXX_AUTO_TRACE(logger_); + return GatherFunctionalGroupings(&groups); +} + +bool SQLPTRepresentation::GatherAppType( + const std::string& app_id, policy_table::AppHMITypes* app_types) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectAppTypes)) { + LOG4CXX_WARN(logger_, "Incorrect select from app types"); + return false; + } + + query.Bind(0, app_id); + while (query.Next()) { + policy_table::AppHMIType type; + if (!policy_table::EnumFromJsonString(query.GetString(0), &type)) { + return false; + } + app_types->push_back(type); + } + return true; +} + +bool SQLPTRepresentation::GatherRequestType( + const std::string& app_id, + policy_table::RequestTypes* request_types) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectRequestTypes)) { + LOG4CXX_WARN(logger_, "Incorrect select from request types."); + return false; + } + + query.Bind(0, app_id); + while (query.Next()) { + policy_table::RequestType type; + if (!policy_table::EnumFromJsonString(query.GetString(0), &type)) { + return false; + } + request_types->push_back(type); + } + return true; +} + +bool SQLPTRepresentation::GatherNickName( + const std::string& app_id, policy_table::Strings* nicknames) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectNicknames)) { + LOG4CXX_WARN(logger_, "Incorrect select from app nicknames"); + return false; + } + + query.Bind(0, app_id); + while (query.Next()) { + nicknames->push_back(query.GetString(0)); + } + return true; +} + +bool SQLPTRepresentation::GatherAppGroup( + const std::string& app_id, policy_table::Strings* app_groups) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectAppGroups)) { + LOG4CXX_WARN(logger_, "Incorrect select from app groups"); + return false; + } + + query.Bind(0, app_id); + while (query.Next()) { + app_groups->push_back(query.GetString(0)); + } + return true; +} + +bool SQLPTRepresentation::SaveApplicationCustomData(const std::string& app_id, + bool is_revoked, + bool is_default, + bool is_predata) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kUpdateApplicationCustomData)) { + LOG4CXX_WARN(logger_, "Incorrect update in application"); + return false; + } + + query.Bind(0, is_revoked); + query.Bind(1, is_default); + query.Bind(2, is_predata); + query.Bind(3, app_id); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed update in application"); + return false; + } + + return true; +} + +bool SQLPTRepresentation::IsApplicationRevoked( + const std::string& app_id) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectApplicationRevoked)) { + LOG4CXX_WARN(logger_, "Incorrect select from is_revoked of application"); + } + + query.Bind(0, app_id); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed select is_revoked of application"); + return false; + } + return query.IsNull(0) ? false : query.GetBoolean(0); +} +bool SQLPTRepresentation::IsApplicationRepresented( + const std::string& app_id) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectApplicationRepresented)) { + LOG4CXX_WARN(logger_, "Incorrect select application by id"); + return false; + } + + query.Bind(0, app_id); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed select application by id"); + return false; + } + return query.GetInteger(0) != 0; +} + +bool SQLPTRepresentation::IsDefaultPolicy(const std::string& app_id) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectApplicationIsDefault)) { + LOG4CXX_WARN(logger_, "Incorrect select application by id"); + return false; + } + + query.Bind(0, app_id); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed select application by id"); + return false; + } + return query.IsNull(0) ? false : query.GetBoolean(0); +} + +bool SQLPTRepresentation::IsPredataPolicy(const std::string& app_id) const { + return false; +} + +bool SQLPTRepresentation::SetDefaultPolicy(const std::string& app_id) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kDeleteAppGroupByApplicationId)) { + LOG4CXX_ERROR(logger_, "Incorrect statement to delete from app_group."); + return false; + } + query.Bind(0, app_id); + if (!query.Exec()) { + LOG4CXX_ERROR(logger_, "Failed deleting from app_group."); + return false; + } + + if (!CopyApplication(kDefaultId, app_id)) { + return false; + } + + SetPreloaded(false); + + policy_table::RequestTypes request_types; + if (!GatherRequestType(kDefaultId, &request_types) || + !SaveRequestType(app_id, request_types)) { + return false; + } + policy_table::AppHMITypes app_types; + if (!GatherAppType(kDefaultId, &app_types) || + !SaveAppType(app_id, app_types)) { + return false; + } + + policy_table::Strings default_groups; + if (GatherAppGroup(kDefaultId, &default_groups) && + SaveAppGroup(app_id, default_groups)) { + return SetIsDefault(app_id, true); + } + return false; +} + +bool SQLPTRepresentation::SetIsDefault(const std::string& app_id, + bool is_default) const { + LOG4CXX_TRACE(logger_, "Set flag is_default of application"); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kUpdateIsDefault)) { + LOG4CXX_WARN(logger_, "Incorect statement for updating is_default"); + return false; + } + + query.Bind(0, is_default); + query.Bind(1, app_id); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed update is_default"); + return false; + } + return true; +} + +void SQLPTRepresentation::RemoveDB() const { + file_system::DeleteFile(db_->get_path()); +} + +bool SQLPTRepresentation::IsDBVersionActual() const { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kSelectDBVersion) || !query.Exec()) { + LOG4CXX_ERROR(logger_, + "Failed to get DB version: " << query.LastError().text()); + return false; + } + + const int32_t saved_db_version = query.GetInteger(0); + const int32_t current_db_version = GetDBVersion(); + LOG4CXX_DEBUG(logger_, + "Saved DB version is: " << saved_db_version + << ". Current DB vesion is: " + << current_db_version); + + return current_db_version == saved_db_version; +} + +bool SQLPTRepresentation::UpdateDBVersion() const { + LOG4CXX_AUTO_TRACE(logger_); + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kUpdateDBVersion)) { + LOG4CXX_ERROR(logger_, + "Incorrect DB version query: " << query.LastError().text()); + return false; + } + + const int32_t db_version = GetDBVersion(); + LOG4CXX_DEBUG(logger_, "DB version will be updated to: " << db_version); + query.Bind(0, db_version); + + if (!query.Exec()) { + LOG4CXX_ERROR(logger_, + "DB version getting failed: " << query.LastError().text()); + return false; + } + + return true; +} + +const int32_t SQLPTRepresentation::GetDBVersion() const { + return utils::Djb2HashFromString(sql_pt::kCreateSchema); +} + +utils::dbms::SQLDatabase* SQLPTRepresentation::db() const { +#ifdef __QNX__ + utils::dbms::SQLDatabase* db = new utils::dbms::SQLDatabase(kDatabaseName); + db->Open(); + return db; +#else + return db_; +#endif // __QNX__ +} + +bool SQLPTRepresentation::CopyApplication(const std::string& source, + const std::string& destination) { + utils::dbms::SQLQuery source_app(db()); + if (!source_app.Prepare(sql_pt::kSelectApplicationFull)) { + LOG4CXX_WARN(logger_, "Incorrect select statement from application."); + return false; + } + source_app.Bind(0, source); + if (!source_app.Exec()) { + LOG4CXX_WARN(logger_, "Failed selecting from application."); + return false; + } + + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertApplicationFull)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement into application."); + return false; + } + query.Bind(0, destination); + source_app.IsNull(0) ? query.Bind(1) + : query.Bind(1, source_app.GetBoolean(0)); + source_app.IsNull(1) ? query.Bind(2) + : query.Bind(2, source_app.GetBoolean(1)); + source_app.IsNull(2) ? query.Bind(3) : query.Bind(3, source_app.GetString(2)); + source_app.IsNull(3) ? query.Bind(4) : query.Bind(4, source_app.GetString(3)); + source_app.IsNull(4) ? query.Bind(5) + : query.Bind(5, source_app.GetBoolean(4)); + source_app.IsNull(5) ? query.Bind(6) + : query.Bind(6, source_app.GetBoolean(5)); + source_app.IsNull(6) ? query.Bind(7) + : query.Bind(7, source_app.GetBoolean(6)); + query.Bind(8, source_app.GetInteger(7)); + query.Bind(9, source_app.GetInteger(8)); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed inserting into application."); + return false; + } + return true; +} + +void SQLPTRepresentation::SetPreloaded(bool value) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kUpdatePreloaded)) { + LOG4CXX_WARN(logger_, "Incorrect statement of updating preloaded."); + return; + } + + query.Bind(0, value); + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Failed updating preloaded."); + return; + } +} + +bool SQLPTRepresentation::SetVINValue(const std::string& value) { + return true; +} + +bool SQLPTRepresentation::SaveExternalConsentEntities( + const int64_t group_id, + const policy_table::DisallowedByExternalConsentEntities& entities, + ExternalConsentEntitiesType type) const { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt_ext::kInsertExternalConsentEntity)) { + LOG4CXX_WARN(logger_, + "Incorrect insert statement for external consent entities."); + return false; + } + + const std::string external_consent_entity_type = + kExternalConsentEntitiesTypeOn == type + ? kExternalConsentEntitiesTypeStringOn + : kExternalConsentEntitiesTypeStringOff; + + policy_table::DisallowedByExternalConsentEntities::const_iterator it_entity = + entities.begin(); + for (; entities.end() != it_entity; ++it_entity) { + query.Bind(0, group_id); + query.Bind(1, it_entity->entity_type); + query.Bind(2, it_entity->entity_id); + query.Bind(3, external_consent_entity_type); + if (!query.Exec() || !query.Reset()) { + LOG4CXX_ERROR(logger_, + "Can't insert '" << external_consent_entity_type + << "' external consent entity."); + return false; + } + } + + return true; +} + +} // namespace policy diff --git a/src/components/policy/policy_external/src/status.cc b/src/components/policy/policy_external/src/status.cc new file mode 100644 index 0000000000..31fc7f110b --- /dev/null +++ b/src/components/policy/policy_external/src/status.cc @@ -0,0 +1,139 @@ +/* + Copyright (c) 2016, Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include "policy/status.h" +#include "policy/update_status_manager.h" +#include "utils/make_shared.h" + +policy::UpToDateStatus::UpToDateStatus() + : Status(kUpToDate, policy::PolicyTableStatus::StatusUpToDate) {} + +void policy::UpToDateStatus::ProcessEvent(UpdateStatusManager* manager, + policy::UpdateEvent event) { + switch (event) { + case kOnNewAppRegistered: + case kOnResetPolicyTableRequireUpdate: + case kScheduleUpdate: + case kScheduleManualUpdate: + case kOnResetRetrySequence: + manager->SetNextStatus(utils::MakeShared<UpdateNeededStatus>()); + break; + default: + break; + } +} + +policy::UpdateNeededStatus::UpdateNeededStatus() + : Status(kUpdateNeeded, policy::PolicyTableStatus::StatusUpdateRequired) {} + +void policy::UpdateNeededStatus::ProcessEvent( + policy::UpdateStatusManager* manager, policy::UpdateEvent event) { + switch (event) { + case kOnUpdateSentOut: + manager->SetNextStatus(utils::MakeShared<UpdatingStatus>()); + break; + case kOnResetPolicyTableRequireUpdate: + manager->SetNextStatus(utils::MakeShared<UpToDateStatus>()); + manager->SetPostponedStatus(utils::MakeShared<UpdateNeededStatus>()); + break; + case kOnResetPolicyTableNoUpdate: + manager->SetNextStatus(utils::MakeShared<UpToDateStatus>()); + break; + default: + break; + } +} + +bool policy::UpdateNeededStatus::IsUpdateRequired() const { + return true; +} + +policy::UpdatingStatus::UpdatingStatus() + : Status(kUpdating, policy::PolicyTableStatus::StatusUpdatePending) {} + +void policy::UpdatingStatus::ProcessEvent(policy::UpdateStatusManager* manager, + policy::UpdateEvent event) { + switch (event) { + case kOnValidUpdateReceived: + case kOnResetPolicyTableNoUpdate: + manager->SetNextStatus(utils::MakeShared<UpToDateStatus>()); + break; + case kOnNewAppRegistered: + manager->SetPostponedStatus(utils::MakeShared<UpdateNeededStatus>()); + break; + case kOnWrongUpdateReceived: + case kOnUpdateTimeout: + manager->SetNextStatus(utils::MakeShared<UpdateNeededStatus>()); + break; + case kOnResetPolicyTableRequireUpdate: + manager->SetNextStatus(utils::MakeShared<UpToDateStatus>()); + manager->SetPostponedStatus(utils::MakeShared<UpdateNeededStatus>()); + break; + case kScheduleUpdate: + case kScheduleManualUpdate: + case kOnResetRetrySequence: + manager->SetPostponedStatus(utils::MakeShared<UpdateNeededStatus>()); + break; + default: + break; + } +} + +bool policy::UpdatingStatus::IsUpdatePending() const { + return true; +} + +bool policy::UpdatingStatus::IsUpdateRequired() const { + return true; +} + +policy::Status::Status(const std::string& string_status, + const policy::PolicyTableStatus enum_status) + : string_status_(string_status), enum_status_(enum_status) {} + +policy::Status::~Status() {} + +const std::string policy::Status::get_status_string() const { + return string_status_; +} + +policy::PolicyTableStatus policy::Status::get_status() const { + return enum_status_; +} + +bool policy::Status::IsUpdateRequired() const { + return false; +} + +bool policy::Status::IsUpdatePending() const { + return false; +} diff --git a/src/components/policy/policy_external/src/update_status_manager.cc b/src/components/policy/policy_external/src/update_status_manager.cc new file mode 100644 index 0000000000..087db1149b --- /dev/null +++ b/src/components/policy/policy_external/src/update_status_manager.cc @@ -0,0 +1,262 @@ +/* + Copyright (c) 2014, Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include "policy/update_status_manager.h" +#include "policy/policy_listener.h" +#include "utils/logger.h" +#include "utils/make_shared.h" + +namespace policy { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +UpdateStatusManager::UpdateStatusManager() + : listener_(NULL) + , current_status_(utils::MakeShared<UpToDateStatus>()) + , last_processed_event_(kNoEvent) + , apps_search_in_progress_(false) + , app_registered_from_non_consented_device_(true) { + update_status_thread_delegate_ = new UpdateThreadDelegate(this); + thread_ = threads::CreateThread("UpdateStatusThread", + update_status_thread_delegate_); + thread_->start(); +} + +UpdateStatusManager::~UpdateStatusManager() { + LOG4CXX_AUTO_TRACE(logger_); + DCHECK(update_status_thread_delegate_); + DCHECK(thread_); + thread_->join(); + delete update_status_thread_delegate_; + threads::DeleteThread(thread_); +} + +void UpdateStatusManager::ProcessEvent(UpdateEvent event) { + sync_primitives::AutoLock lock(status_lock_); + current_status_->ProcessEvent(this, event); + last_processed_event_ = event; + DoTransition(); +} + +void UpdateStatusManager::SetNextStatus(utils::SharedPtr<Status> status) { + next_status_ = status; +} + +void UpdateStatusManager::SetPostponedStatus(utils::SharedPtr<Status> status) { + postponed_status_ = status; +} + +void UpdateStatusManager::set_listener(PolicyListener* listener) { + listener_ = listener; +} + +void UpdateStatusManager::OnUpdateSentOut(uint32_t update_timeout) { + LOG4CXX_AUTO_TRACE(logger_); + DCHECK(update_status_thread_delegate_); + update_status_thread_delegate_->updateTimeOut(update_timeout); + ProcessEvent(kOnUpdateSentOut); +} + +void UpdateStatusManager::OnUpdateTimeoutOccurs() { + LOG4CXX_AUTO_TRACE(logger_); + ProcessEvent(kOnUpdateTimeout); + DCHECK(update_status_thread_delegate_); + update_status_thread_delegate_->updateTimeOut(0); // Stop Timer +} + +void UpdateStatusManager::OnValidUpdateReceived() { + LOG4CXX_AUTO_TRACE(logger_); + update_status_thread_delegate_->updateTimeOut(0); // Stop Timer + ProcessEvent(kOnValidUpdateReceived); +} + +void UpdateStatusManager::OnWrongUpdateReceived() { + LOG4CXX_AUTO_TRACE(logger_); + update_status_thread_delegate_->updateTimeOut(0); // Stop Timer + ProcessEvent(kOnWrongUpdateReceived); +} + +void UpdateStatusManager::OnResetDefaultPT(bool is_update_required) { + LOG4CXX_AUTO_TRACE(logger_); + if (is_update_required) { + ProcessEvent(kOnResetPolicyTableRequireUpdate); + return; + } + ProcessEvent(kOnResetPolicyTableNoUpdate); +} + +void UpdateStatusManager::OnResetRetrySequence() { + LOG4CXX_AUTO_TRACE(logger_); + ProcessEvent(kOnResetRetrySequence); +} + +void UpdateStatusManager::OnNewApplicationAdded(const DeviceConsent consent) { + LOG4CXX_AUTO_TRACE(logger_); + if (kDeviceAllowed != consent) { + app_registered_from_non_consented_device_ = true; + return; + } + app_registered_from_non_consented_device_ = false; + ProcessEvent(kOnNewAppRegistered); +} + +void UpdateStatusManager::OnPolicyInit(bool is_update_required) { + LOG4CXX_AUTO_TRACE(logger_); + if (is_update_required) { + current_status_.reset(new UpToDateStatus()); + ProcessEvent(kScheduleUpdate); + } +} + +void UpdateStatusManager::OnDeviceConsented() { + LOG4CXX_AUTO_TRACE(logger_); + if (app_registered_from_non_consented_device_) { + ProcessEvent(kOnNewAppRegistered); + } +} + +bool UpdateStatusManager::IsUpdateRequired() const { + return current_status_->IsUpdateRequired(); +} + +bool UpdateStatusManager::IsUpdatePending() const { + return current_status_->IsUpdatePending(); +} + +void UpdateStatusManager::ScheduleUpdate() { + ProcessEvent(kScheduleUpdate); +} + +void UpdateStatusManager::ScheduleManualUpdate() { + ProcessEvent(kScheduleManualUpdate); +} + +std::string UpdateStatusManager::StringifiedUpdateStatus() const { + return current_status_->get_status_string(); +} + +void policy::UpdateStatusManager::OnAppsSearchStarted() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(apps_search_in_progress_lock_); + apps_search_in_progress_ = true; +} + +void policy::UpdateStatusManager::OnAppsSearchCompleted() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(apps_search_in_progress_lock_); + apps_search_in_progress_ = false; +} + +bool policy::UpdateStatusManager::IsAppsSearchInProgress() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(apps_search_in_progress_lock_); + return apps_search_in_progress_; +} + +void UpdateStatusManager::DoTransition() { + DCHECK_OR_RETURN_VOID(listener_); + if (!next_status_) { + return; + } + + current_status_ = next_status_; + next_status_.reset(); + + if (last_processed_event_ != kScheduleManualUpdate) { + listener_->OnUpdateStatusChanged(current_status_->get_status_string()); + } + + if (!postponed_status_) { + return; + } + + current_status_ = postponed_status_; + if (last_processed_event_ != kScheduleManualUpdate) { + listener_->OnUpdateStatusChanged(current_status_->get_status_string()); + } + postponed_status_.reset(); +} + +UpdateStatusManager::UpdateThreadDelegate::UpdateThreadDelegate( + UpdateStatusManager* update_status_manager) + : timeout_(0) + , stop_flag_(false) + , state_lock_(true) + , update_status_manager_(update_status_manager) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Create UpdateThreadDelegate"); +} + +UpdateStatusManager::UpdateThreadDelegate::~UpdateThreadDelegate() { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Delete UpdateThreadDelegate"); +} + +void UpdateStatusManager::UpdateThreadDelegate::threadMain() { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "UpdateStatusManager thread started (started normal)"); + sync_primitives::AutoLock auto_lock(state_lock_); + while (false == stop_flag_) { + if (timeout_ > 0) { + LOG4CXX_DEBUG(logger_, "Timeout is greater then 0"); + sync_primitives::ConditionalVariable::WaitStatus wait_status = + termination_condition_.WaitFor(auto_lock, timeout_); + if (sync_primitives::ConditionalVariable::kTimeout == wait_status) { + if (update_status_manager_) { + update_status_manager_->OnUpdateTimeoutOccurs(); + } + } + } else { + // Time is not active, wait until timeout will be set, + // or UpdateStatusManager will be deleted + termination_condition_.Wait(auto_lock); + } + } +} + +void UpdateStatusManager::UpdateThreadDelegate::exitThreadMain() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(state_lock_); + stop_flag_ = true; + LOG4CXX_DEBUG(logger_, "before notify"); + termination_condition_.NotifyOne(); +} + +void UpdateStatusManager::UpdateThreadDelegate::updateTimeOut( + const uint32_t timeout_ms) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(state_lock_); + timeout_ = timeout_ms; + termination_condition_.NotifyOne(); +} + +} // namespace policy diff --git a/src/components/policy/policy_external/src/usage_statistics/counter.cc b/src/components/policy/policy_external/src/usage_statistics/counter.cc new file mode 100644 index 0000000000..661ea29704 --- /dev/null +++ b/src/components/policy/policy_external/src/usage_statistics/counter.cc @@ -0,0 +1,126 @@ +/* + Copyright (c) 2013, Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_POLICY_INCLUDE_POLICY_STATISTICS_MANAGER_H_ +#define SRC_COMPONENTS_POLICY_INCLUDE_POLICY_STATISTICS_MANAGER_H_ + +#include <cassert> +#include "policy/usage_statistics/counter.h" +#include "utils/date_time.h" +#include "utils/make_shared.h" +#include "utils/timer_task_impl.h" + +namespace usage_statistics { + +GlobalCounter::GlobalCounter( + utils::SharedPtr<usage_statistics::StatisticsManager> statistics_manager, + GlobalCounterId counter_type) + : counter_type_(counter_type), statistics_manager_(statistics_manager) {} + +void GlobalCounter::operator++() const { + if (statistics_manager_) { + statistics_manager_->Increment(counter_type_); + } +} + +AppCounter::AppCounter( + utils::SharedPtr<usage_statistics::StatisticsManager> statistics_manager, + const std::string& app_id, + AppCounterId counter_type) + : app_id_(app_id) + , counter_type_(counter_type) + , statistics_manager_(statistics_manager) {} + +void AppCounter::operator++() const { + if (statistics_manager_) { + statistics_manager_->Increment(app_id_, counter_type_); + } +} + +AppInfo::AppInfo( + utils::SharedPtr<usage_statistics::StatisticsManager> statistics_manager, + const std::string& app_id, + AppInfoId info_type) + : app_id_(app_id) + , info_type_(info_type) + , statistics_manager_(statistics_manager) {} + +void AppInfo::Update(const std::string& new_info) const { + if (statistics_manager_) { + statistics_manager_->Set(app_id_, info_type_, new_info); + } +} + +AppStopwatchImpl::AppStopwatchImpl( + utils::SharedPtr<usage_statistics::StatisticsManager> statistics_manager, + const std::string& app_id) + : app_id_(app_id) + , stopwatch_type_(SECONDS_HMI_NONE) + , statistics_manager_(statistics_manager) + , timer_("HMI levels timer", + new timer::TimerTaskImpl<AppStopwatchImpl>( + this, &AppStopwatchImpl::WriteTime)) + , time_out_(60) {} + +AppStopwatchImpl::AppStopwatchImpl( + utils::SharedPtr<StatisticsManager> statistics_manager, + const std::string& app_id, + uint32_t timeout) + : app_id_(app_id) + , stopwatch_type_(SECONDS_HMI_NONE) + , statistics_manager_(statistics_manager) + , timer_("HMI levels timer", + new timer::TimerTaskImpl<AppStopwatchImpl>( + this, &AppStopwatchImpl::WriteTime)) + , time_out_(timeout) {} + +AppStopwatchImpl::~AppStopwatchImpl() {} + +void AppStopwatchImpl::Start(AppStopwatchId stopwatch_type) { + stopwatch_type_ = stopwatch_type; + timer_.Start(time_out_ * date_time::DateTime::MILLISECONDS_IN_SECOND, + timer::kPeriodic); +} + +void AppStopwatchImpl::Switch(AppStopwatchId stopwatch_type) { + Start(stopwatch_type); +} + +void AppStopwatchImpl::WriteTime() { + if (statistics_manager_) { + statistics_manager_->Add(app_id_, stopwatch_type_, time_out_); + } +} + +} // namespace usage_statistics + +#endif // SRC_COMPONENTS_POLICY_INCLUDE_POLICY_STATISTICS_MANAGER_H_ |