diff options
Diffstat (limited to 'src/components/policy/policy_regular/src')
14 files changed, 10781 insertions, 0 deletions
diff --git a/src/components/policy/policy_regular/src/cache_manager.cc b/src/components/policy/policy_regular/src/cache_manager.cc new file mode 100644 index 0000000000..6184320306 --- /dev/null +++ b/src/components/policy/policy_regular/src/cache_manager.cc @@ -0,0 +1,1636 @@ +/* + * 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 "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/macro.h" +#include "utils/threads/thread.h" +#include "utils/threads/thread_delegate.h" + +#include "policy/sql_pt_representation.h" + +namespace policy_table = rpc::policy_table_interface_base; + +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 { + 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_; +}; + +CacheManager::CacheManager() + : CacheManagerInterface() + , pt_(new policy_table::Table) + , backup_(new SQLPTRepresentation()) + , update_required(false) { + LOG4CXX_AUTO_TRACE(logger_); + backuper_ = new BackgroundBackuper(this); + backup_thread_ = threads::CreateThread("Backup thread", backuper_); + backup_thread_->start(); +} + +CacheManager::~CacheManager() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(backuper_locker_); + backup_thread_->join(); + delete backup_thread_->delegate(); + threads::DeleteThread(backup_thread_); +} + +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 = true; + return result; +} + +uint32_t CacheManager::HeartBeatTimeout(const std::string& app_id) const { + CACHE_MANAGER_CHECK(0); + uint32_t result = 0; + if (!AppExists(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; +} + +bool CacheManager::CanAppStealFocus(const std::string& app_id) const { + CACHE_MANAGER_CHECK(false); + bool result = true; + return result; +} + +bool CacheManager::GetDefaultHMI(const std::string& app_id, + std::string& default_hmi) const { + CACHE_MANAGER_CHECK(false); + bool result = true; + return result; +} + +bool CacheManager::ResetUserConsent() { + CACHE_MANAGER_CHECK(false); + sync_primitives::AutoLock lock(cache_lock_); + 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); + 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) { + LOG4CXX_INFO(logger_, "Devices doesn't have groups"); + 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>((GenerateHash(*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(); +} + +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(); +} + +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(); +} + +void CacheManager::RemoveAppConsentForGroup(const std::string& app_id, + const std::string& group_name) { + CACHE_MANAGER_CHECK_VOID(); +} + +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].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; + } + pt_->policy_table.app_policies_section.apps[iter->first] = + iter_default->second; + } else { + pt_->policy_table.app_policies_section.apps[iter->first] = iter->second; + } + } + + 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(); + 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]); + return true; +} + +bool CacheManager::GetDeviceGroupsFromPolicies( + policy_table::Strings& groups, + policy_table::Strings& preconsented_groups) const { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK(false); + return true; +} + +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]; + + // Open SDL stored just device id in policy + UNUSED(params); + + // 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); + 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); + 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; + 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 = GenerateHash((*fg_iter).first); + if (group_id == id) { + group_name = (*fg_iter).first; + } + } +} + +bool CacheManager::SetUserPermissionsForApp( + const PermissionConsent& permissions) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(cache_lock_); + CACHE_MANAGER_CHECK(false); + 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); + bool is_revoked = false; + if (pt_->policy_table.app_policies_section.apps.end() != + pt_->policy_table.app_policies_section.apps.find(app_id)) { + is_revoked = pt_->policy_table.app_policies_section.apps[app_id].is_null(); + } + + return is_revoked; +} + +void CacheManager::CheckPermissions(const policy_table::Strings& groups, + const PTString& hmi_level, + const PTString& rpc, + CheckPermissionResult& result) { + LOG4CXX_AUTO_TRACE(logger_); + CACHE_MANAGER_CHECK_VOID(); + + policy_table::Strings::const_iterator app_groups_iter = groups.begin(); + policy_table::Strings::const_iterator app_groups_iter_end = 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:" << 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(int 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) { + 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]; + + policy_table::MessageString message_string; + + // If message has no records with required language, fallback language + // should be used instead. + LanguageFinder finder(language); + policy_table::Languages::const_iterator it_language = std::find_if( + msg_languages.languages.begin(), msg_languages.languages.end(), finder); + + if (msg_languages.languages.end() == it_language) { + LOG4CXX_WARN(logger_, + "Language " + << language + << " haven't been found for message code: " << *it); + + LanguageFinder fallback_language_finder("en-us"); + + policy_table::Languages::const_iterator it_fallback_language = + std::find_if(msg_languages.languages.begin(), + msg_languages.languages.end(), + fallback_language_finder); + + if (msg_languages.languages.end() == it_fallback_language) { + LOG4CXX_ERROR(logger_, + "No fallback language found for message code: " << *it); + continue; + } + + message_string = it_fallback_language->second; + } else { + message_string = it_language->second; + } + + UserFriendlyMessage msg; + msg.message_code = *it; + 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 rpc::policy_table_interface_base::NumberOfNotificationsType result = + (nnpm.end() != priority_iter ? (*priority_iter).second : 0u); + 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> >(); + + 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; + } + + /* consumer_friendly_messages are required for the snapshot; + * consumer_friendly_messages->version is required always, but + * consumer_friendly_messages->messages must be omitted in PTS */ + if (snapshot_->policy_table.consumer_friendly_messages->is_initialized()) { + snapshot_->policy_table.consumer_friendly_messages->messages = + rpc::Optional<policy_table::Messages>(); + } else { + LOG4CXX_WARN(logger_, + "policy_table.consumer_friendly_messages is not initialized"); + } + + /* policy_table.usage_and_error_counts are required for PTS and + * policy_table.usage_and_error_counts->app_level is optional */ + rpc::Optional<policy_table::UsageAndErrorCounts>& usage_and_error_counts = + snapshot_->policy_table.usage_and_error_counts; + + 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; + } + } + } else { + LOG4CXX_WARN(logger_, "app_level is not initialized"); + } +} + +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; + bool is_default_policy; + bool is_predata_policy; + + for (; app_policy_iter != app_policy_iter_end; ++app_policy_iter) { + const std::string app_id = (*app_policy_iter).first; + + if (copy_pt.policy_table.app_policies_section.apps.end() != + copy_pt.policy_table.app_policies_section.apps.find(app_id)) { + is_revoked = + copy_pt.policy_table.app_policies_section.apps[app_id].is_null(); + } + + is_default_policy = + copy_pt.policy_table.app_policies_section.apps.end() != + copy_pt.policy_table.app_policies_section.apps.find(app_id) && + policy::kDefaultId == + copy_pt.policy_table.app_policies_section.apps[app_id] + .get_string(); + + // TODO(AOleynik): Remove this field from DB + is_predata_policy = + copy_pt.policy_table.app_policies_section.apps.end() != + copy_pt.policy_table.app_policies_section.apps.find(app_id) && + policy::kPreDataConsentId == + copy_pt.policy_table.app_policies_section.apps[app_id] + .get_string(); + + backup_->SaveApplicationCustomData( + app_id, is_revoked, is_default_policy, is_predata_policy); + is_revoked = false; + } + + // In case of extended policy the meta info should be backuped as well. + backup_->WriteDb(); + } + } +} + +void CacheManager::ResetCalculatedPermissions() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(calculated_permissions_lock_); + calculated_permissions_.clear(); +} + +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(); + + // Copy all members of policy table except messages in consumer friendly + // messages + snapshot_->policy_table.app_policies_section = + pt_->policy_table.app_policies_section; + snapshot_->policy_table.functional_groupings = + pt_->policy_table.functional_groupings; + snapshot_->policy_table.consumer_friendly_messages->version = + pt_->policy_table.consumer_friendly_messages->version; + snapshot_->policy_table.consumer_friendly_messages->mark_initialized(); + snapshot_->policy_table.module_config = pt_->policy_table.module_config; + snapshot_->policy_table.module_meta = pt_->policy_table.module_meta; + snapshot_->policy_table.usage_and_error_counts = + pt_->policy_table.usage_and_error_counts; + snapshot_->policy_table.device_data = pt_->policy_table.device_data; + + // Set policy table type to Snapshot + snapshot_->SetPolicyTableType( + rpc::policy_table_interface_base::PolicyTableType::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; + return result; +} + +bool CacheManager::SetMetaInfo(const std::string& ccpu_version, + const std::string& wers_country_code, + const std::string& language) { + CACHE_MANAGER_CHECK(false); + + // 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; + return result; +} + +bool CacheManager::SetSystemLanguage(const std::string& language) { + CACHE_MANAGER_CHECK(false); + 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 = GenerateHash((*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); + Backup(); + return true; +} + +void CacheManager::Increment(usage_statistics::GlobalCounterId type) { + CACHE_MANAGER_CHECK_VOID(); + 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_); + policy_table::ApplicationPolicies::const_iterator iter = + pt_->policy_table.app_policies_section.apps.find(kDefaultId); + if (pt_->policy_table.app_policies_section.apps.end() != iter) { + pt_->policy_table.app_policies_section.apps[app_id] = + pt_->policy_table.app_policies_section.apps[kDefaultId]; + + SetIsDefault(app_id); + } + Backup(); + return true; +} + +bool CacheManager::IsDefaultPolicy(const std::string& app_id) const { + CACHE_MANAGER_CHECK(false); + const bool result = + pt_->policy_table.app_policies_section.apps.end() != + pt_->policy_table.app_policies_section.apps.find(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); + policy_table::ApplicationPolicies::const_iterator iter = + pt_->policy_table.app_policies_section.apps.find(app_id); + if (pt_->policy_table.app_policies_section.apps.end() != iter) { + pt_->policy_table.app_policies_section.apps[app_id].set_to_string( + kDefaultId); + } + 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 { + // TODO(AOleynik): Maybe change for comparison with pre_DataConsent + // permissions or check string value from get_string() + if (!IsApplicationRepresented(app_id)) { + return false; + } + + policy_table::ApplicationPolicies& apps = + pt_->policy_table.app_policies_section.apps; + const policy_table::ApplicationPolicies::mapped_type& pre_data_app = + apps[kPreDataConsentId]; + const policy_table::ApplicationPolicies::mapped_type& specific_app = + apps[app_id]; + + policy_table::Strings res; + std::set_intersection(pre_data_app.groups.begin(), + pre_data_app.groups.end(), + specific_app.groups.begin(), + specific_app.groups.end(), + std::back_inserter(res)); + + const bool is_marked_as_predata = + (kPreDataConsentId == specific_app.get_string()); + + return !res.empty() && is_marked_as_predata; +} + +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); + Backup(); + return true; +} + +bool CacheManager::IsApplicationRepresented(const std::string& app_id) const { + CACHE_MANAGER_CHECK(false); + if (kDeviceId == app_id) { + return true; + } + 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); + + 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()) { + LOG4CXX_INFO(logger_, "DB version is NOT actual"); + if (!backup_->RefreshDB()) { + LOG4CXX_ERROR(logger_, "RefreshDB() failed"); + 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 is valid: " << std::boolalpha << result); + if (!result) { + rpc::ValidationReport report("policy_table"); + snapshot->ReportErrors(&report); + return result; + } + + backup_->UpdateDBVersion(); + Backup(); + } break; + default: { + result = false; + LOG4CXX_ERROR(logger_, "Failed to init policy table."); + } break; + } + + return result; +} + +void CacheManager::FillDeviceSpecificData() {} + +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_); + BinaryMessage json_string; + if (!file_system::ReadBinaryFile(file_name, json_string)) { + LOG4CXX_FATAL(logger_, "Failed to read pt 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_TRACE(logger_, "Start create PT"); + sync_primitives::AutoLock locker(cache_lock_); + + table = policy_table::Table(&value); + + Json::StyledWriter s_writer; + LOG4CXX_DEBUG(logger_, "PT out:"); + LOG4CXX_DEBUG(logger_, s_writer.write(table.ToJsonValue())); + + 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) { + bool result = true; + Backup(); + return result; +} + +bool CacheManager::AppExists(const std::string& app_id) const { + CACHE_MANAGER_CHECK(false); + policy_table::ApplicationPolicies::iterator policy_iter = + pt_->policy_table.app_policies_section.apps.find(app_id); + return pt_->policy_table.app_policies_section.apps.end() != policy_iter; +} + +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; +} + +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; + } + 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; +} + +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(""); +} + +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; + } + } + } +} + +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_regular/src/policy_helper.cc b/src/components/policy/policy_regular/src/policy_helper.cc new file mode 100644 index 0000000000..b72a041a83 --- /dev/null +++ b/src/components/policy/policy_regular/src/policy_helper.cc @@ -0,0 +1,805 @@ +/* + 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 { + CheckGroupName(const policy::StringsValueType& value) : value_(value) {} + + bool operator()(const FunctionalGroupNames::value_type& value) { + 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) + : pm_(pm), update_(update), snapshot_(snapshot) {} + +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)); +} + +void policy::CheckAppPolicy::NotifySystem( + const policy::AppPoliciesValueType& app_policy) const { + pm_->listener()->OnPendingPermissionChange(app_policy.first); +} + +void CheckAppPolicy::SendPermissionsToApp( + const AppPoliciesValueType& app_policy) const { + const std::string app_id = app_policy.first; + + const std::string device_id = pm_->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; + pm_->GetPermissionsForApp(device_id, app_id, group_permissons); + + Permissions notification_data; + pm_->PrepareNotificationData(update_->policy_table.functional_groupings, + app_policy.second.groups, + group_permissons, + notification_data); + + LOG4CXX_INFO(logger_, "Send notification for application_id: " << app_id); + // Default_hmi is Ford-specific and should not be used with basic policy + const std::string default_hmi; + pm_->listener()->OnPermissionsUpdated(app_id, notification_data, default_hmi); +} + +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; +} + +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); + NotifySystem(app_policy); + return true; + } + + if (!IsPredefinedApp(app_policy) && !NicknamesMatch(app_policy)) { + SetPendingPermissions(app_policy, RESULT_NICKNAME_MISMATCH); + NotifySystem(app_policy); + return true; + } + + PermissionsCheckResult result = CheckPermissionsChanges(app_policy); + if (!IsPredefinedApp(app_policy) && IsRequestTypeChanged(app_policy)) { + SetPendingPermissions(app_policy, RESULT_REQUEST_TYPE_CHANGED); + NotifySystem(app_policy); + } + if (RESULT_NO_CHANGES == result) { + LOG4CXX_INFO(logger_, + "Permissions for application:" << app_id + << " wasn't changed."); + return true; + } + + LOG4CXX_INFO(logger_, + "Permissions for application:" << app_id + << " have been changed."); + + if (!IsPredefinedApp(app_policy) && RESULT_CONSENT_NOT_REQIURED != result) { + SetPendingPermissions(app_policy, result); + NotifySystem(app_policy); + } + + // Don't sent notification for predefined apps (e.g. default, device etc.) + if (!IsPredefinedApp(app_policy)) { + SendPermissionsToApp(app_policy); + } + return true; +} + +void policy::CheckAppPolicy::SetPendingPermissions( + const AppPoliciesValueType& app_policy, + PermissionsCheckResult result) const { + const std::string app_id = app_policy.first; + AppPermissions permissions_diff(app_id); + permissions_diff.priority = + policy_table::EnumToJsonString(app_policy.second.priority); + + switch (result) { + case RESULT_APP_REVOKED: + permissions_diff.appRevoked = true; + break; + case RESULT_NICKNAME_MISMATCH: + permissions_diff.appUnauthorized = true; + break; + case RESULT_PERMISSIONS_REVOKED: + permissions_diff.isAppPermissionsRevoked = true; + permissions_diff.appRevokedPermissions = GetRevokedGroups(app_policy); + RemoveRevokedConsents(app_policy, permissions_diff.appRevokedPermissions); + break; + case RESULT_CONSENT_NEEDED: + permissions_diff.appPermissionsConsentNeeded = true; + break; + case RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED: + 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.priority.clear(); + 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; + } + pm_->app_permissions_diff_lock_.Acquire(); + pm_->app_permissions_diff_.insert(std::make_pair(app_id, permissions_diff)); + pm_->app_permissions_diff_lock_.Release(); +} + +policy::CheckAppPolicy::PermissionsCheckResult +policy::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; + 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) + : data_(data) { + 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[current_key_]); + // TODO(IKozyrenko): Check logic if optional container is missing + UpdateParameters(*rpc.second.parameters, + (*it).second.parameter_permissions[current_key_]); + ExcludeSame(); + } 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[current_key_]); + // TODO(IKozyrenko): Check logic if optional container is missing + UpdateParameters(*rpc.second.parameters, + data_[rpc.first].parameter_permissions[current_key_]); + ExcludeSame(); + } + return true; +} + +void FillNotificationData::UpdateHMILevels( + const policy_table::HmiLevels& in_hmi, std::set<HMILevel>& 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.insert(policy_table::EnumToJsonString(*it_hmi_levels)); + } +} + +void FillNotificationData::UpdateParameters( + const policy_table::Parameters& in_parameters, + std::set<Parameter>& out_parameter) { + ParametersConstItr it_parameters = in_parameters.begin(); + ParametersConstItr it_parameters_end = in_parameters.end(); + + for (; it_parameters != it_parameters_end; ++it_parameters) { + out_parameter.insert(policy_table::EnumToJsonString(*it_parameters)); + } +} + +void FillNotificationData::ExcludeSame() { + Permissions::iterator it = data_.begin(); + Permissions::const_iterator it_end = data_.end(); + // Groups + for (; it != it_end; ++it) { + HMIPermissions& rpc_hmi_permissions = (*it).second.hmi_permissions; + HMIPermissions::const_iterator it_hmi_allowed = + (*it).second.hmi_permissions.find(kAllowedKey); + HMIPermissions::const_iterator it_hmi_undefined = + (*it).second.hmi_permissions.find(kUndefinedKey); + HMIPermissions::const_iterator it_hmi_user_disallowed = + (*it).second.hmi_permissions.find(kUserDisallowedKey); + + ParameterPermissions& rpc_parameter_permissions = + (*it).second.parameter_permissions; + ParameterPermissions::const_iterator it_parameter_allowed = + (*it).second.parameter_permissions.find(kAllowedKey); + ParameterPermissions::const_iterator it_parameter_undefined = + (*it).second.parameter_permissions.find(kUndefinedKey); + ParameterPermissions::const_iterator it_parameter_user_disallowed = + (*it).second.parameter_permissions.find(kUserDisallowedKey); + + // 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]); + } + } + + 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]); + } + } + + // 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]); + } + } + + 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]; +} + +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); + + if (fg_.end() != it) { + const policy_table::Rpc& rpcs = (*it).second.rpcs; + FillNotificationData filler( + data_, GetGroupState(group_name_str), undefined_group_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 = app_policies.begin(); + policy_table::ApplicationPolicies::iterator it_default = + app_policies.find(kDefaultId); + 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) { + if (it != app_policies.end()) { + (*it).second = (*it_default).second; + it->second.set_to_string(kDefaultId); + } else { + LOG4CXX_ERROR(logger_, + "There is no default application policy was " + "found in PTU."); + return false; + } + } + } + + return true; +} +} diff --git a/src/components/policy/policy_regular/src/policy_manager_impl.cc b/src/components/policy/policy_regular/src/policy_manager_impl.cc new file mode 100644 index 0000000000..f05ac9cb67 --- /dev/null +++ b/src/components/policy/policy_regular/src/policy_manager_impl.cc @@ -0,0 +1,1130 @@ +/* + 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/policy_manager_impl.h" + +#include <algorithm> +#include <set> +#include <queue> +#include <iterator> +#include <limits> +#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 "utils/make_shared.h" +#include "policy/cache_manager.h" +#include "policy/update_status_manager.h" +#include "config_profile/profile.h" +#include "utils/timer_task_impl.h" +#include "utils/make_shared.h" + +policy::PolicyManager* CreateManager() { + return new policy::PolicyManagerImpl(); +} +void DeleteManager(policy::PolicyManager* pm) { + delete pm; +} + +namespace { +const uint32_t kDefaultRetryTimeoutInMSec = + 60u * date_time::DateTime::MILLISECONDS_IN_SECOND; +} // namespace + +namespace policy { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +PolicyManagerImpl::PolicyManagerImpl() + : PolicyManager() + , listener_(NULL) + , cache_(new CacheManager) + , retry_sequence_timeout_(kDefaultRetryTimeoutInMSec) + , retry_sequence_index_(0) + , timer_retry_sequence_("Retry sequence timer", + new timer::TimerTaskImpl<PolicyManagerImpl>( + this, &PolicyManagerImpl::RetrySequence)) + , 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); +} + +#ifdef USE_HMI_PTU_DECRYPTION + +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>(); + } +} + +#else + +utils::SharedPtr<policy_table::Table> PolicyManagerImpl::ParseArray( + 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)) { + // For PT Update received from SDL Server. + if (value["data"].size() != 0) { + Json::Value data = value["data"]; + return new policy_table::Table(&data[0]); + } else { + return new policy_table::Table(&value); + } + } else { + return utils::SharedPtr<policy_table::Table>(); + } +} + +#endif + +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(); + } +} + +bool PolicyManagerImpl::LoadPT(const std::string& file, + const BinaryMessage& pt_content) { + LOG4CXX_INFO(logger_, "LoadPT of size " << pt_content.size()); + +#ifdef USE_HMI_PTU_DECRYPTION + // Assuemes Policy Table was parsed, formatted, and/or decrypted by + // the HMI after system request before calling OnReceivedPolicyUpdate + // Parse message into table struct + utils::SharedPtr<policy_table::Table> pt_update = Parse(pt_content); +#else + // Message Received from server unecnrypted with PTU in first element + // of 'data' array. No Parsing was done by HMI. + utils::SharedPtr<policy_table::Table> pt_update = ParseArray(pt_content); +#endif + if (!pt_update) { + LOG4CXX_WARN(logger_, "Parsed table pointer is 0."); + 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); + + // Update finished, no need retry + if (timer_retry_sequence_.is_running()) { + LOG4CXX_INFO(logger_, "Stop retry sequence"); + timer_retry_sequence_.Stop(); + } + + { + 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. + 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; + } + + if (pt_update->policy_table.module_config.certificate.is_initialized()) { + 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" << pt_content.size()); + } + } + + // 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; +} + +void 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); + + 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)); +} + +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); +} + +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); +} + +bool 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 false; + } + + 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); + return true; +} + +std::string PolicyManagerImpl::GetLockScreenIconUrl() const { + return cache_->GetLockScreenIconUrl(); +} + +void PolicyManagerImpl::StartPTExchange() { + LOG4CXX_AUTO_TRACE(logger_); + + const bool update_required = update_status_manager_.IsUpdateRequired(); + + if (update_status_manager_.IsAppsSearchInProgress() && update_required) { + update_status_manager_.ScheduleUpdate(); + LOG4CXX_INFO(logger_, + "Starting exchange skipped, since applications " + "search is in progress."); + return; + } + + if (update_status_manager_.IsUpdatePending() && update_required) { + if (trigger_ptu_) + update_status_manager_.ScheduleUpdate(); + LOG4CXX_INFO(logger_, + "Starting exchange skipped, since another exchange " + "is in progress."); + return; + } + + if (listener_ && listener_->CanUpdate()) { + if (ignition_check) { + CheckTriggers(); + ignition_check = false; + } + + if (update_status_manager_.IsUpdateRequired()) { + if (RequestPTUpdate() && !timer_retry_sequence_.is_running()) { + // Start retry sequency + const uint32_t timeout_msec = NextRetryTimeout(); + + if (timeout_msec) { + LOG4CXX_DEBUG(logger_, + "Start retry sequence timeout = " << timeout_msec); + timer_retry_sequence_.Start(timeout_msec, timer::kPeriodic); + } + } + } + } +} + +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(); + } +} + +void PolicyManagerImpl::OnAppRegisteredOnMobile( + const std::string& application_id) { + StartPTExchange(); + SendNotificationOnPermissionsUpdated(application_id); +} + +const std::vector<std::string> PolicyManagerImpl::GetAppRequestTypes( + const std::string policy_app_id) const { + std::vector<std::string> request_types; + cache_->GetAppRequestTypes(policy_app_id, request_types); + return request_types; +} + +const VehicleInfo PolicyManagerImpl::GetVehicleInfo() const { + return cache_->GetVehicleInfo(); +} + +void PolicyManagerImpl::CheckPermissions(const PTString& device_id, + const PTString& app_id, + const PTString& hmi_level, + const PTString& rpc, + const RPCParams& rpc_params, + CheckPermissionResult& result) { + LOG4CXX_AUTO_TRACE(logger_); + + if (!cache_->IsApplicationRepresented(app_id)) { + LOG4CXX_WARN(logger_, "Application " << app_id << " isn't exist"); + return; + } + + LOG4CXX_INFO(logger_, + "CheckPermissions for " << app_id << " and rpc " << rpc + << " for " << hmi_level << " level."); + + const policy_table::Strings& groups = cache_->GetGroups(app_id); + cache_->CheckPermissions(groups, hmi_level, rpc, result); + 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; + } + } +} + +bool PolicyManagerImpl::ResetUserConsent() { + bool result = true; + + return result; +} + +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; + std::vector<FunctionalGroupPermission>::const_iterator it = + app_group_permissions.begin(); + std::vector<FunctionalGroupPermission>::const_iterator it_end = + app_group_permissions.end(); + for (; it != it_end; ++it) { + app_groups.push_back((*it).group_name); + } + + 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; + default_hmi = "NONE"; + + listener()->OnPermissionsUpdated( + application_id, notification_data, default_hmi); +} + +bool PolicyManagerImpl::CleanupUnpairedDevices() { + LOG4CXX_AUTO_TRACE(logger_); + // For SDL-specific it doesn't matter + return true; +} + +DeviceConsent PolicyManagerImpl::GetUserConsentForDevice( + const std::string& device_id) const { + LOG4CXX_AUTO_TRACE(logger_); + return kDeviceAllowed; +} + +void PolicyManagerImpl::SetUserConsentForDevice(const std::string& device_id, + bool is_allowed) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Device :" << device_id); + DeviceConsent current_consent = GetUserConsentForDevice(device_id); + bool is_current_device_allowed = + DeviceConsent::kDeviceAllowed == current_consent ? true : false; + if (DeviceConsent::kDeviceHasNoConsent != current_consent && + is_current_device_allowed == is_allowed) { + const std::string consent = is_allowed ? "allowed" : "disallowed"; + LOG4CXX_INFO(logger_, "Device is already " << consent << "."); + return; + } +} + +bool PolicyManagerImpl::ReactOnUserDevConsentForApp(const std::string app_id, + bool is_device_allowed) { + return true; +} + +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); +} + +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_); + std::map<std::string, AppPermissions>::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::SetUserConsentForApp( + const PermissionConsent& permissions) { + LOG4CXX_AUTO_TRACE(logger_); +} + +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) { + return cache_->GetUserFriendlyMsg(message_code, 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); + } + } + + // For basic policy + FunctionalGroupIDs all_groups = group_types[kTypeGeneral]; + FunctionalGroupIDs default_groups = group_types[kTypeDefault]; + FunctionalGroupIDs predataconsented_groups = + group_types[kTypePreDataConsented]; + + FunctionalGroupIDs allowed_groups; + FunctionalGroupIDs no_auto = ExcludeSame(all_groups, auto_allowed_groups); + + if (cache_->IsDefaultPolicy(policy_app_id)) { + allowed_groups = ExcludeSame(no_auto, default_groups); + } else if (cache_->IsPredataPolicy(policy_app_id)) { + allowed_groups = ExcludeSame(no_auto, predataconsented_groups); + } + FillFunctionalGroupPermissions( + allowed_groups, group_names, kGroupAllowed, 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; + + 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]; + + // In case of GENIVI all groups are allowed + FunctionalGroupIDs common_allowed = all_groups; + FillFunctionalGroupPermissions( + common_allowed, group_names, kGroupAllowed, 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) {} + +void PolicyManagerImpl::SetSystemInfo(const std::string& ccpu_version, + const std::string& wers_country_code, + const std::string& language) { + LOG4CXX_AUTO_TRACE(logger_); +} + +void PolicyManagerImpl::OnSystemReady() { + // Update policy table for the first time with system information + if (cache_->IsPTPreloaded()) { + listener()->OnSystemInfoUpdateRequired(); + return; + } +} + +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_; +} + +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; + + return 0 == cache_->DaysBeforeExchange(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(); + } +} + +void PolicyManagerImpl::IncrementIgnitionCycles() { + cache_->IncrementIgnitionCycles(); +} + +std::string PolicyManagerImpl::ForcePTExchange() { + update_status_manager_.ScheduleUpdate(); + StartPTExchange(); + return update_status_manager_.StringifiedUpdateStatus(); +} + +std::string PolicyManagerImpl::ForcePTExchangeAtUserRequest() { + update_status_manager_.ScheduleManualUpdate(); + StartPTExchange(); + return update_status_manager_.StringifiedUpdateStatus(); +} + +std::string PolicyManagerImpl::GetPolicyTableStatus() const { + return update_status_manager_.StringifiedUpdateStatus(); +} + +uint32_t PolicyManagerImpl::NextRetryTimeout() { + sync_primitives::AutoLock auto_lock(retry_sequence_lock_); + LOG4CXX_DEBUG(logger_, "Index: " << retry_sequence_index_); + uint32_t next = 0u; + if (retry_sequence_seconds_.empty() || + retry_sequence_index_ > retry_sequence_seconds_.size()) { + return next; + } + + if (0 == retry_sequence_index_) { + ++retry_sequence_index_; + // Return miliseconds + return retry_sequence_timeout_; + } + + for (uint32_t i = 0u; i < retry_sequence_index_; ++i) { + next += retry_sequence_seconds_[i] * + date_time::DateTime::MILLISECONDS_IN_SECOND; + next += retry_sequence_timeout_; + } + ++retry_sequence_index_; + + // Return miliseconds + 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() { + update_status_manager_.OnUpdateSentOut(); + 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_); + return false; +} + +void PolicyManagerImpl::SetVINValue(const std::string& value) {} + +AppPermissions PolicyManagerImpl::GetAppPermissionsChanges( + const std::string& policy_app_id) { + typedef std::map<std::string, AppPermissions>::iterator PermissionsIt; + PermissionsIt 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) {} + +std::string PolicyManagerImpl::RetrieveCertificate() const { + LOG4CXX_AUTO_TRACE(logger_); + return cache_->GetCertificate(); +} + +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; +} + +bool PolicyManagerImpl::HasCertificate() const { + return !cache_->GetCertificate().empty(); +} + +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); + const policy_table::AppHMIType type = policy_table::AHT_NAVIGATION; + if (helpers::in_range(hmi_types, + (rpc::Enum<policy_table::AppHMIType>)type) && + !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::AddNewApplication(const std::string& application_id, + DeviceConsent device_consent) { + LOG4CXX_AUTO_TRACE(logger_); + + cache_->SetDefaultPolicy(application_id); +} + +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); + } +} + +bool PolicyManagerImpl::IsNewApplication( + const std::string& application_id) const { + return false == cache_->IsApplicationRepresented(application_id); +} + +bool PolicyManagerImpl::ResetPT(const std::string& file_name) { + 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; +} + +void PolicyManagerImpl::RetrySequence() { + LOG4CXX_INFO(logger_, "Start new retry sequence"); + update_status_manager_.OnUpdateTimeoutOccurs(); + + const uint32_t timeout_msec = NextRetryTimeout(); + LOG4CXX_DEBUG(logger_, "New retry sequence timeout = " << timeout_msec); + if (!timeout_msec) { + if (timer_retry_sequence_.is_running()) { + timer_retry_sequence_.Stop(); + } + return; + } + + RequestPTUpdate(); + timer_retry_sequence_.Start(timeout_msec, timer::kPeriodic); +} + +} // namespace policy diff --git a/src/components/policy/policy_regular/src/policy_table.cc b/src/components/policy/policy_regular/src/policy_table.cc new file mode 100644 index 0000000000..c5c6e3e132 --- /dev/null +++ b/src/components/policy/policy_regular/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_representation.h" + +#include "utils/logger.h" + +namespace policy { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +PolicyTable::PolicyTable() : pt_data_(new SQLPTRepresentation()) {} + +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_regular/src/policy_table/enums.cc b/src/components/policy/policy_regular/src/policy_table/enums.cc new file mode 100644 index 0000000000..26c7b96b32 --- /dev/null +++ b/src/components/policy/policy_regular/src/policy_table/enums.cc @@ -0,0 +1,577 @@ +// 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; + 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"; + 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 { + 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(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_regular/src/policy_table/types.cc b/src/components/policy/policy_regular/src/policy_table/types.cc new file mode 100644 index 0000000000..7928973919 --- /dev/null +++ b/src/components/policy/policy_regular/src/policy_table/types.cc @@ -0,0 +1,1389 @@ +// This file is generated, do not edit +#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(Priority priority) + : CompositeType(kUninitialized), priority(priority) {} + +PolicyBase::~PolicyBase() {} + +PolicyBase::PolicyBase(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , priority(impl::ValueMember(value__, "priority")) {} + +Json::Value PolicyBase::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("priority", priority, &result__); + return result__; +} + +bool PolicyBase::is_valid() const { + if (!priority.is_valid()) { + return false; + } + return Validate(); +} + +bool PolicyBase::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} + +bool PolicyBase::struct_empty() const { + if (priority.is_initialized()) { + return false; + } + return true; +} + +void PolicyBase::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + if (!priority.is_valid()) { + priority.ReportErrors(&report__->ReportSubobject("priority")); + } +} + +void PolicyBase::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + priority.SetPolicyTableType(pt_type); +} + +// DevicePolicy methods +DevicePolicy::DevicePolicy() : PolicyBase() {} + +DevicePolicy::DevicePolicy(Priority priority) : PolicyBase(priority) {} + +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(), groups() {} + +ApplicationParams::ApplicationParams(const Strings& groups, Priority priority) + : PolicyBase(priority), groups(groups) {} + +ApplicationParams::~ApplicationParams() {} + +ApplicationParams::ApplicationParams(const Json::Value* value__) + : PolicyBase(value__) + , groups(impl::ValueMember(value__, "groups")) + , 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")) + , certificate(impl::ValueMember(value__, "certificate"), "not_specified") {} + +Json::Value ApplicationParams::ToJsonValue() const { + Json::Value result__(PolicyBase::ToJsonValue()); + impl::WriteJsonField("groups", groups, &result__); + 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 (!groups.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; + } + if (!certificate.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 (groups.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; + } + if (certificate.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 (!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 (!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")); + } + if (!certificate.is_valid()) { + certificate.ReportErrors(&report__->ReportSubobject("certificate")); + } +} + +void ApplicationParams::SetPolicyTableType(PolicyTableType pt_type) { + PolicyBase::SetPolicyTableType(pt_type); + groups.SetPolicyTableType(pt_type); + AppHMIType.SetPolicyTableType(pt_type); + RequestType.SetPolicyTableType(pt_type); + memory_kb.SetPolicyTableType(pt_type); + heart_beat_timeout_ms.SetPolicyTableType(pt_type); + certificate.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")) {} +Json::Value Rpcs::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("user_consent_prompt", user_consent_prompt, &result__); + impl::WriteJsonField("rpcs", rpcs, &result__); + return result__; +} +bool Rpcs::is_valid() const { + if (!user_consent_prompt.is_valid()) { + return false; + } + if (!rpcs.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; + } + + 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")); + } +} + +void Rpcs::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + user_consent_prompt.SetPolicyTableType(pt_type); + rpcs.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)) + , device_certificates(impl::ValueMember(value__, "device_certificates")) + , preloaded_pt(impl::ValueMember(value__, "preloaded_pt")) + , 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")) {} + +void ModuleConfig::SafeCopyFrom(const ModuleConfig& from) { + // device_certificates = from.device_certificates; // According to the + // requirements this is optional. + exchange_after_x_ignition_cycles = from.exchange_after_x_ignition_cycles; + exchange_after_x_kilometers = from.exchange_after_x_kilometers; + exchange_after_x_days = from.exchange_after_x_days; + 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; + + vehicle_make.assign_if_valid(from.vehicle_make); + vehicle_model.assign_if_valid(from.vehicle_model); + vehicle_year.assign_if_valid(from.vehicle_year); + certificate.assign_if_valid(from.certificate); +} + +Json::Value ModuleConfig::ToJsonValue() const { + Json::Value result__(Json::objectValue); + 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 (!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 (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 (!device_certificates.is_valid()) { + device_certificates.ReportErrors( + &report__->ReportSubobject("device_certificates")); + } + 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")); + } + if (PT_PRELOADED == GetPolicyTableType()) { + std::string validation_info = + omitted_validation_info + PolicyTableTypeToString(GetPolicyTableType()); + rpc::ValidationReport* omitted_field_report; + 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); + } + } +} + +void ModuleConfig::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::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 +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; + } + 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")); + } +} + +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__); + 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)) + , 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")) {} +Json::Value ModuleMeta::ToJsonValue() const { + Json::Value result__(Json::objectValue); + 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__); + return result__; +} +bool ModuleMeta::is_valid() const { + if (struct_empty()) { + return initialization_state__ == kInitialized && Validate(); + } + 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; + } + return Validate(); +} +bool ModuleMeta::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} +bool ModuleMeta::struct_empty() const { + 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; + } + return true; +} +void ModuleMeta::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } + 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")); + } +} + +void ModuleMeta::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::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); +} + +// 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("count_of_TLS_errors", count_of_tls_errors, &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 (PT_PRELOADED == GetPolicyTableType() || + PT_UPDATE == GetPolicyTableType()) { + std::string validation_info = + omitted_validation_info + PolicyTableTypeToString(GetPolicyTableType()); + report__->set_validation_info(validation_info); + } +} + +// UsageAndErrorCounts methods +UsageAndErrorCounts::UsageAndErrorCounts() : CompositeType(kUninitialized) {} + +UsageAndErrorCounts::~UsageAndErrorCounts() {} +UsageAndErrorCounts::UsageAndErrorCounts(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) + , app_level(impl::ValueMember(value__, "app_level")) {} +Json::Value UsageAndErrorCounts::ToJsonValue() const { + Json::Value result__(Json::objectValue); + impl::WriteJsonField("app_level", app_level, &result__); + return result__; +} +bool UsageAndErrorCounts::is_valid() const { + if (struct_empty()) { + return initialization_state__ == kInitialized && Validate(); + } + 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 (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 (!app_level.is_valid()) { + app_level.ReportErrors(&report__->ReportSubobject("app_level")); + } +} + +void UsageAndErrorCounts::SetPolicyTableType(PolicyTableType pt_type) { + CompositeType::SetPolicyTableType(pt_type); + app_level.SetPolicyTableType(pt_type); +} + +// DeviceParams methods +DeviceParams::DeviceParams() : CompositeType(kUninitialized) {} +DeviceParams::~DeviceParams() {} +DeviceParams::DeviceParams(const Json::Value* value__) + : CompositeType(InitHelper(value__, &Json::Value::isObject)) {} +Json::Value DeviceParams::ToJsonValue() const { + Json::Value result__(Json::objectValue); + return result__; +} +bool DeviceParams::is_valid() const { + if (struct_empty()) { + return initialization_state__ == kInitialized && Validate(); + } + return Validate(); +} +bool DeviceParams::is_initialized() const { + return (initialization_state__ != kUninitialized) || (!struct_empty()); +} +bool DeviceParams::struct_empty() const { + return true; +} +void DeviceParams::ReportErrors(rpc::ValidationReport* report__) const { + if (struct_empty()) { + rpc::CompositeType::ReportErrors(report__); + } +} + +// 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); +} + +} // namespace policy_table_interface_base +} // namespace rpc diff --git a/src/components/policy/policy_regular/src/policy_table/validation.cc b/src/components/policy/policy_regular/src/policy_table/validation.cc new file mode 100644 index 0000000000..e7a981e559 --- /dev/null +++ b/src/components/policy/policy_regular/src/policy_table/validation.cc @@ -0,0 +1,197 @@ +#include <algorithm> +#include "policy/policy_table/types.h" +#include "utils/logger.h" + +namespace { +bool IsTypeInvalid( + rpc::Enum<rpc::policy_table_interface_base::RequestType> request) { + return !request.is_valid(); +} +} + +namespace rpc { +namespace policy_table_interface_base { + +CREATE_LOGGERPTR_GLOBAL(logger_, "Policy") + +void RemoveInvalidTypes(RequestTypes& types) { + types.erase(std::remove_if(types.begin(), types.end(), &IsTypeInvalid), + types.end()); +} + +bool PolicyBase::Validate() const { + 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 (!it_default_policy->second.RequestType.is_valid()) { + LOG4CXX_WARN(logger_, + "Default policy RequestTypes are not valid. Will be cleaned."); + RemoveInvalidTypes(*it_default_policy->second.RequestType); + // If preloaded does not have valid default types - validation fails + // Otherwise default will be empty, i.e. all types allowed + if (PT_PRELOADED == pt_type) { + if (it_default_policy->second.RequestType->empty()) { + LOG4CXX_ERROR( + logger_, + "Default policy RequestTypes empty after clean-up. Exiting."); + return false; + } + } + } + + ApplicationPolicies::iterator iter = apps.begin(); + ApplicationPolicies::iterator end_iter = apps.end(); + + while (iter != end_iter) { + ApplicationParams& app_params = (*iter).second; + bool is_request_type_omitted = !app_params.RequestType.is_initialized(); + bool is_request_type_valid = app_params.RequestType.is_valid(); + bool is_request_type_empty = app_params.RequestType->empty(); + + if (PT_PRELOADED == pt_type) { + if (!is_request_type_valid) { + LOG4CXX_WARN(logger_, + "App policy RequestTypes are not valid. Will be cleaned."); + RemoveInvalidTypes(*app_params.RequestType); + if (app_params.RequestType->empty()) { + LOG4CXX_ERROR( + logger_, + "App policy RequestTypes empty after clean-up. Exiting."); + return false; + } + } + } else { + if (is_request_type_omitted) { + LOG4CXX_WARN(logger_, + "App policy RequestTypes omitted." + " Will be replaced with default."); + app_params.RequestType = apps[kDefaultApp].RequestType; + ++iter; + continue; + } + if (!is_request_type_valid) { + LOG4CXX_WARN(logger_, + "App policy RequestTypes are invalid. Will be cleaned."); + RemoveInvalidTypes(*app_params.RequestType); + if (app_params.RequestType->empty()) { + LOG4CXX_WARN(logger_, + "App policy RequestTypes empty after clean-up." + " Will be replaced with default."); + app_params.RequestType = apps[kDefaultApp].RequestType; + ++iter; + continue; + } + } + if (is_request_type_empty) { + LOG4CXX_WARN(logger_, "App policy RequestTypes empty."); + } + } + ++iter; + } + + return true; +} + +bool ApplicationParams::Validate() const { + return true; +} +bool RpcParameters::Validate() const { + return true; +} +bool Rpcs::Validate() const { + return true; +} + +bool ModuleConfig::Validate() const { + if (PT_PRELOADED == GetPolicyTableType()) { + if (vehicle_make.is_initialized()) { + return false; + } + if (vehicle_year.is_initialized()) { + return false; + } + if (vehicle_model.is_initialized()) { + return false; + } + } + return true; +} + +bool MessageString::Validate() const { + return true; +} + +bool MessageLanguages::Validate() const { + if (PT_SNAPSHOT == GetPolicyTableType()) { + return false; + } + return true; +} + +bool ConsumerFriendlyMessages::Validate() const { + /* According to requirements consumer_friendly_messages are optional for PTU + and required for PTP and PTS. So, they are allowed always */ + if (PT_SNAPSHOT == GetPolicyTableType() && messages.is_initialized()) { + return false; + } + return true; +} + +bool ModuleMeta::Validate() const { + 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 DeviceParams::Validate() const { + return true; +} +bool PolicyTable::Validate() const { + if (PT_PRELOADED == GetPolicyTableType() || + PT_UPDATE == GetPolicyTableType()) { + if (device_data.is_initialized()) { + return false; + } + } + return true; +} +bool Table::Validate() const { + return true; +} +} // namespace policy_table_interface_base +} // namespace rpc diff --git a/src/components/policy/policy_regular/src/sql_pt_ext_queries.cc b/src/components/policy/policy_regular/src/sql_pt_ext_queries.cc new file mode 100644 index 0000000000..3fde462a32 --- /dev/null +++ b/src/components/policy/policy_regular/src/sql_pt_ext_queries.cc @@ -0,0 +1,268 @@ +/* + 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 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`) " + "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`, `certificate`) 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`, `certificate` 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` = ?"; + +} // namespace sql_pt_ext +} // namespace policy diff --git a/src/components/policy/policy_regular/src/sql_pt_ext_representation.cc b/src/components/policy/policy_regular/src/sql_pt_ext_representation.cc new file mode 100644 index 0000000000..c64efaaede --- /dev/null +++ b/src/components/policy/policy_regular/src/sql_pt_ext_representation.cc @@ -0,0 +1,1807 @@ +/* + 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") + +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() || !query.Reset()) { + 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); + + *(*messages->messages)[msg.message_code].languages[language].tts = + msg.tts; + *(*messages->messages)[msg.message_code].languages[language].label = + msg.label; + *(*messages->messages)[msg.message_code].languages[language].line1 = + msg.line1; + *(*messages->messages)[msg.message_code].languages[language].line2 = + msg.line2; + *(*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)); + app.second.certificate.is_initialized() + ? app_query.Bind(8, *app.second.certificate) + : app_query.Bind(8, std::string()); + + 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; + } + // TODO(IKozyrenko): Check logic if optional container is missing + if (!SaveNickname(app.first, *app.second.nicknames)) { + return false; + } + // TODO(IKozyrenko): Check logic if optional container is missing + if (!SaveAppType(app.first, *app.second.AppHMIType)) { + return false; + } + // TODO(IKozyrenko): Check logic if optional container is missing + if (!SavePreconsentedGroup(app.first, *app.second.preconsented_groups)) { + return false; + } + + return true; +} + +bool policy::SQLPTExtRepresentation::SaveDevicePolicy( + const policy_table::DevicePolicy& device) { + 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); + app_query.Bind(8, std::string()); + + 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 (!query.IsNull(7)) { + *params.certificate = query.GetString(7); + } + 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); + } +} + +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))); + 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; + } + } + } + + 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; + } + + query.Bind(0, *strings.tts); + query.Bind(1, *strings.label); + query.Bind(2, *strings.line1); + query.Bind(3, *strings.line2); + query.Bind(4, lang); + query.Bind(5, type); + 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::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_regular/src/sql_pt_queries.cc b/src/components/policy/policy_regular/src/sql_pt_queries.cc new file mode 100644 index 0000000000..df4bc74cc2 --- /dev/null +++ b/src/components/policy/policy_regular/src/sql_pt_queries.cc @@ -0,0 +1,712 @@ +/* + 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`( " + " `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, " + " `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, " + " `certificate` TEXT, " + " `vehicle_make` VARCHAR(45), " + " `vehicle_model` VARCHAR(45), " + " `vehicle_year` VARCHAR(4) " + "); " + "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 `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, " + " `certificate` VARCHAR(45), " + " 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), " + " 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 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` VARCHAR(100) 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 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 " + " ); " + "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 kDropSchema = + "BEGIN; " + "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 INDEX IF EXISTS `app_type.fk_app_type_application1_idx`; " + "DROP TABLE IF EXISTS `app_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.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 `module_meta`; " + "DROP TABLE IF EXISTS `usage_and_error_count`; " + "DROP TABLE IF EXISTS `device`; " + "DROP TABLE IF EXISTS `_internal_data`; " + "COMMIT; " + "VACUUM;"; + +const std::string kDeleteData = + "BEGIN; " + "DELETE FROM `message`; " + "DELETE FROM `endpoint`; " + "DELETE FROM `consent_group`; " + "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 `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 `usage_and_error_count`; " + "DELETE FROM `device`; " + "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 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`, `certificate`) 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` (`language_code`, `message_type_name`) " + "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` = ?, `certificate` = ?, `vehicle_make` = ?, " + " `vehicle_model` = ?, `vehicle_year` = ?"; + +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`, `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 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`, `certificate`, `vehicle_make`," + " `vehicle_model`, `vehicle_year` " + " 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`, `count_of_tls_errors` " + "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 kSelectUserMsgsVersion = + "SELECT DISTINCT `number` FROM `version`"; + +const std::string kSelectAppPolicies = + "SELECT `id`, `priority_value`, `memory_kb`, " + " `heart_beat_timeout_ms`, `certificate` 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`, `certificate`) " + " 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`, `certificate` 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` = ? "; + +const std::string kSaveModuleMeta = + "UPDATE `module_meta` SET " + "`pt_exchanged_at_odometer_x` = ?, " + "`pt_exchanged_x_days_after_epoch` = ?, " + "`ignition_cycles_since_last_exchange` = ? "; + +const std::string kSelectModuleMeta = "SELECT* FROM `module_meta`"; + +} // namespace sql_pt +} // namespace policy diff --git a/src/components/policy/policy_regular/src/sql_pt_representation.cc b/src/components/policy/policy_regular/src/sql_pt_representation.cc new file mode 100644 index 0000000000..e94c853414 --- /dev/null +++ b/src/components/policy/policy_regular/src/sql_pt_representation.cc @@ -0,0 +1,1755 @@ +/* + 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/file_system.h" +#include "utils/gen_hash.h" +#include "policy/sql_pt_representation.h" +#include "policy/sql_wrapper.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 { +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); + } +} +} // namespace + +const std::string SQLPTRepresentation::kDatabaseName = "policy"; + +SQLPTRepresentation::SQLPTRepresentation() + : db_(new utils::dbms::SQLDatabase(kDatabaseName)) {} + +SQLPTRepresentation::~SQLPTRepresentation() { + db_->Close(); + delete db_; +} + +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(int 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 < 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; +} + +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; +} + +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 + std::string path = get_settings().app_storage_folder(); + if (!path.empty()) { + db_->set_path(path + "/"); + } + 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"); + utils::dbms::SQLQuery query(db()); + if (query.Prepare(sql_pt::kSelectModuleMeta) && query.Next()) { + *meta->pt_exchanged_at_odometer_x = query.GetInteger(0); + *meta->pt_exchanged_x_days_after_epoch = query.GetInteger(1); + *meta->ignition_cycles_since_last_exchange = query.GetInteger(2); + } +} + +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->certificate = query.GetString(5); + *config->vehicle_make = query.GetString(6); + *config->vehicle_model = query.GetString(7); + *config->vehicle_year = query.GetString(8); + *config->preloaded_date = 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()) { + const std::string& url = endpoints.GetString(0); + const std::string& service = endpoints.GetString(1); + const std::string& app_id = endpoints.GetString(2); + config->endpoints[service][app_id].push_back(url); + } + } + + 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; + app_level.mark_initialized(); + while (query.Next()) { + app_level.count_of_tls_errors = query.GetInteger(1); + const std::string app_id = query.GetString(0); + (*counts->app_level)[app_id] = app_level; + } + return true; + } + return false; +} + +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; + device_data.mark_initialized(); + while (query.Next()) { + const std::string device_id = query.GetString(0); + (*data)[device_id] = device_data; + } + } +} + +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; + } + while (func_group.Next()) { + policy_table::Rpcs rpcs_tbl; + if (!func_group.IsNull(2)) { + *rpcs_tbl.user_consent_prompt = func_group.GetString(2); + } + int func_id = func_group.GetInteger(0); + rpcs.Bind(0, func_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)) { + InsertUnique(param, &(*rpcs_tbl.rpcs[rpcs.GetString(0)].parameters)); + } + } + } + if (!rpcs_tbl.rpcs.is_initialized()) { + rpcs_tbl.rpcs.set_to_null(); + } + rpcs.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 (!query.IsNull(3)) { + *params.certificate = query.GetString(4); + } + 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; + } + + 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 it; + + for (it = groups.begin(); it != groups.end(); ++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(CacheManager::GenerateHash(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, it->first); + it->second.user_consent_prompt.is_initialized() + ? query.Bind(2, *(it->second.user_consent_prompt)) + : query.Bind(2); + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into functional groups"); + return false; + } + + if (!SaveRpcs(query.LastInsertId(), it->second.rpcs)) { + 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 { + 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)); + app.second.certificate.is_initialized() + ? app_query.Bind(5, *app.second.certificate) + : app_query.Bind(5); + 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; + } + + 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) { + utils::dbms::SQLQuery query(db()); + + if (!query.Prepare(sql_pt::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, odometer); + query.Bind(1, *(meta.pt_exchanged_x_days_after_epoch)); + query.Bind(2, *(meta.ignition_cycles_since_last_exchange)); + + if (!query.Exec()) { + LOG4CXX_WARN(logger_, "Incorrect update for module_meta."); + return false; + } + + 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); + query.Bind(5, (*config.certificate)); + config.vehicle_make.is_initialized() ? query.Bind(6, *(config.vehicle_make)) + : query.Bind(6); + config.vehicle_model.is_initialized() ? query.Bind(7, *(config.vehicle_model)) + : query.Bind(7); + config.vehicle_year.is_initialized() ? query.Bind(8, *(config.vehicle_year)) + : query.Bind(8); + + 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) { + query.Bind(0, it->first); + 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 (!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; + 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) { + utils::dbms::SQLQuery query(db()); + if (!query.Prepare(sql_pt::kInsertMessageString)) { + LOG4CXX_WARN(logger_, "Incorrect insert statement for message."); + return false; + } + + query.Bind(0, lang); + query.Bind(1, type); + + if (!query.Exec() || !query.Reset()) { + LOG4CXX_WARN(logger_, "Incorrect insert into message."); + return false; + } + 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() || !query.Reset()) { + 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); + query.Bind(1, it->second.count_of_tls_errors); + if (!query.Exec() || !query.Reset()) { + 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; + } + 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(); + 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::Strings default_groups; + if (!GatherAppGroup(kDefaultId, &default_groups) || + !SaveAppGroup(app_id, default_groups)) { + return 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; + } + return SetIsDefault(app_id, true); +} + +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 +} + +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)); + source_app.IsNull(9) ? query.Bind(10) + : query.Bind(10, source_app.GetString(9)); + 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; +} + +} // namespace policy diff --git a/src/components/policy/policy_regular/src/status.cc b/src/components/policy/policy_regular/src/status.cc new file mode 100644 index 0000000000..8d65c606d0 --- /dev/null +++ b/src/components/policy/policy_regular/src/status.cc @@ -0,0 +1,141 @@ +/* + 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_interface.h" +#include "utils/make_shared.h" + +policy::UpToDateStatus::UpToDateStatus() + : Status("UP_TO_DATE", policy::PolicyTableStatus::StatusUpToDate) {} + +void policy::UpToDateStatus::ProcessEvent(UpdateStatusManagerInterface* manager, + policy::UpdateEvent event) { + switch (event) { + case kOnNewAppRegistered: + case kOnResetPolicyTableRequireUpdate: + case kScheduleUpdate: + case kOnResetRetrySequence: + manager->SetNextStatus(utils::MakeShared<UpdateNeededStatus>()); + break; + default: + break; + } +} + +policy::UpdateNeededStatus::UpdateNeededStatus() + : Status("UPDATE_NEEDED", policy::PolicyTableStatus::StatusUpdateRequired) { +} + +void policy::UpdateNeededStatus::ProcessEvent( + policy::UpdateStatusManagerInterface* 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; + case kOnNewAppRegistered: + manager->SetNextStatus(utils::MakeShared<UpdateNeededStatus>()); + break; + default: + break; + } +} + +bool policy::UpdateNeededStatus::IsUpdateRequired() const { + return true; +} + +policy::UpdatingStatus::UpdatingStatus() + : Status("UPDATING", policy::PolicyTableStatus::StatusUpdatePending) {} + +void policy::UpdatingStatus::ProcessEvent( + policy::UpdateStatusManagerInterface* 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 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_regular/src/update_status_manager.cc b/src/components/policy/policy_regular/src/update_status_manager.cc new file mode 100644 index 0000000000..941113c753 --- /dev/null +++ b/src/components/policy/policy_regular/src/update_status_manager.cc @@ -0,0 +1,190 @@ +/* + 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) {} + +UpdateStatusManager::~UpdateStatusManager() {} + +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() { + LOG4CXX_AUTO_TRACE(logger_); + ProcessEvent(kOnUpdateSentOut); +} + +void UpdateStatusManager::OnUpdateTimeoutOccurs() { + LOG4CXX_AUTO_TRACE(logger_); + ProcessEvent(kOnUpdateTimeout); +} + +void UpdateStatusManager::OnValidUpdateReceived() { + LOG4CXX_AUTO_TRACE(logger_); + ProcessEvent(kOnValidUpdateReceived); +} + +void UpdateStatusManager::OnWrongUpdateReceived() { + LOG4CXX_AUTO_TRACE(logger_); + 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(); + LOG4CXX_DEBUG(logger_, "last_processed_event_ = " << last_processed_event_); + 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(); +} + +} // namespace policy diff --git a/src/components/policy/policy_regular/src/usage_statistics/counter.cc b/src/components/policy/policy_regular/src/usage_statistics/counter.cc new file mode 100644 index 0000000000..60e34a929d --- /dev/null +++ b/src/components/policy/policy_regular/src/usage_statistics/counter.cc @@ -0,0 +1,122 @@ +/* + 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<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<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<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<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) {} + +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_ |