diff options
Diffstat (limited to 'src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/mobile/get_interior_vehicle_data_consent_request.cc')
-rw-r--r-- | src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/mobile/get_interior_vehicle_data_consent_request.cc | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/mobile/get_interior_vehicle_data_consent_request.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/mobile/get_interior_vehicle_data_consent_request.cc new file mode 100644 index 0000000000..477f04bb7c --- /dev/null +++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/mobile/get_interior_vehicle_data_consent_request.cc @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2019, 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 <ctime> +#include <vector> + +#include "rc_rpc_plugin/commands/mobile/get_interior_vehicle_data_consent_request.h" +#include "rc_rpc_plugin/rc_helpers.h" +#include "rc_rpc_plugin/rc_module_constants.h" +#include "rc_rpc_plugin/rc_rpc_types.h" +#include "smart_objects/enum_schema_item.h" + +namespace rc_rpc_plugin { +namespace app_mngr = application_manager; +namespace commands { + +GetInteriorVehicleDataConsentRequest::GetInteriorVehicleDataConsentRequest( + const application_manager::commands::MessageSharedPtr& message, + const RCCommandParams& params) + : RCCommandRequest(message, params) {} + +void GetInteriorVehicleDataConsentRequest::Execute() { + LOG4CXX_AUTO_TRACE(logger_); + + auto& msg_params = (*message_)[app_mngr::strings::msg_params]; + + const bool module_ids_exists = + msg_params.keyExists(message_params::kModuleIds); + if (!module_ids_exists) { + SendResponse(false, + mobile_apis::Result::INVALID_DATA, + "ModuleIds collection is absent in request message"); + return; + } + + if (msg_params[message_params::kModuleIds].empty()) { + LOG4CXX_DEBUG(logger_, + "ModuleIds collection is empty. Will be add default " + "module_id from capabilities"); + + const auto module_id = + rc_capabilities_manager_.GetDefaultModuleIdFromCapabilities( + ModuleType()); + + msg_params[message_params::kModuleIds][0] = module_id; + } + + const std::string module_type = ModuleType(); + for (const auto module_id : + *(msg_params[message_params::kModuleIds].asArray())) { + const ModuleUid module(module_type, module_id.asString()); + if (!rc_capabilities_manager_.CheckIfModuleExistsInCapabilities(module)) { + LOG4CXX_WARN(logger_, + "Accessing not supported module: " << module_type << " " + << module_id.asString()); + SetResourceState(module_type, ResourceState::FREE); + SendResponse(false, + mobile_apis::Result::UNSUPPORTED_RESOURCE, + "Accessing not supported module data"); + return; + } + } + + smart_objects::SmartObject response_params; + if (GetCalculatedVehicleDataConsent(response_params)) { + LOG4CXX_DEBUG( + logger_, + "No need to send response to HMI. Sending cached consents to mobile"); + SendResponse(true, mobile_apis::Result::SUCCESS, nullptr, &response_params); + return; + } + + (*message_)[application_manager::strings::msg_params] + [application_manager::strings::app_id] = connection_key(); + + SendHMIRequest(hmi_apis::FunctionID::RC_GetInteriorVehicleDataConsent, + (&msg_params), + true); +} + +void GetInteriorVehicleDataConsentRequest::on_event( + const app_mngr::event_engine::Event& event) { + LOG4CXX_AUTO_TRACE(logger_); + namespace app_mnrg = application_manager; + + if (event.id() != hmi_apis::FunctionID::RC_GetInteriorVehicleDataConsent) { + LOG4CXX_ERROR(logger_, "Received wrong event. FunctionID: " << event.id()); + return; + } + + const auto& hmi_response = event.smart_object(); + + std::string response_info; + const bool result_of_saving = SaveModuleIdConsents( + response_info, hmi_response[app_mngr::strings::msg_params]); + + if (!result_of_saving) { + LOG4CXX_DEBUG(logger_, "Consent saving failed"); + SendResponse( + false, mobile_apis::Result::GENERIC_ERROR, response_info.c_str()); + return; + } + + auto result_code = + GetMobileResultCode(static_cast<hmi_apis::Common_Result::eType>( + hmi_response[app_mngr::strings::params][app_mngr::hmi_response::code] + .asUInt())); + + const bool success_result = + helpers::Compare<mobile_apis::Result::eType, helpers::EQ, helpers::ONE>( + result_code, + mobile_apis::Result::SUCCESS, + mobile_apis::Result::WARNINGS); + + smart_objects::SmartObject response_params; + response_params = hmi_response[app_mngr::strings::msg_params]; + std::string info; + GetInfo(hmi_response, info); + SendResponse(success_result, + result_code, + info.c_str(), + success_result ? &response_params : nullptr); +} + +std::string GetInteriorVehicleDataConsentRequest::ModuleType() const { + mobile_apis::ModuleType::eType module_type = + static_cast<mobile_apis::ModuleType::eType>( + (*message_)[app_mngr::strings::msg_params] + [message_params::kModuleType] + .asUInt()); + + const char* str; + const bool ok = smart_objects::EnumConversionHelper< + mobile_apis::ModuleType::eType>::EnumToCString(module_type, &str); + return ok ? str : "unknown"; +} + +std::string GetInteriorVehicleDataConsentRequest::ModuleId() const { + return std::string(); +} + +GetInteriorVehicleDataConsentRequest::~GetInteriorVehicleDataConsentRequest() {} + +bool GetInteriorVehicleDataConsentRequest::GetCalculatedVehicleDataConsent( + smart_objects::SmartObject& out_response) const { + LOG4CXX_AUTO_TRACE(logger_); + + out_response = + smart_objects::SmartObject(smart_objects::SmartType::SmartType_Map); + out_response[message_params::kAllowed] = + smart_objects::SmartObject(smart_objects::SmartType::SmartType_Array); + + auto modules_consent_array = out_response[message_params::kAllowed].asArray(); + const auto module_ids = + (*message_)[app_mngr::strings::msg_params][message_params::kModuleIds] + .asArray(); + + if (!MultipleAccessAllowed((*module_ids), (*modules_consent_array))) { + return true; + } + + auto fill_auto_allow_consents = + [&module_ids](smart_objects::SmartArray& out_consents_array) { + for (uint32_t i = 0; i < module_ids->size(); ++i) { + out_consents_array.push_back(smart_objects::SmartObject(true)); + } + }; + + auto fill_auto_deny_consents = + [this, &module_ids](smart_objects::SmartArray& out_consents_array) { + const std::string module_type = ModuleType(); + auto app = application_manager_.application(connection_key()); + const uint32_t app_id = app->app_id(); + for (auto& module_id : (*module_ids)) { + const ModuleUid module_uid(module_type, module_id.asString()); + const bool is_resource_available = + (resource_allocation_manager_.AcquireResource( + module_uid.first, module_uid.second, app_id) == + AcquireResult::ALLOWED); + + out_consents_array.push_back( + smart_objects::SmartObject(is_resource_available)); + } + }; + + auto fill_ask_driver_consents = + [this, &module_ids](smart_objects::SmartArray& out_consents_array) { + auto app = application_manager_.application(connection_key()); + const std::string policy_app_id = app->policy_app_id(); + const std::string mac_address = app->mac_address(); + const std::string module_type = ModuleType(); + + for (auto& module_id : (*module_ids)) { + const ModuleUid module_uid(module_type, module_id.asString()); + auto consent = rc_consent_manager_.GetModuleConsent( + policy_app_id, mac_address, module_uid); + + if (rc_rpc_types::ModuleConsent::NOT_EXISTS == consent) { + const bool is_resource_available = + resource_allocation_manager_.AcquireResource( + module_uid.first, module_uid.second, app->app_id()) == + AcquireResult::ALLOWED; + + const bool is_resource_rejected = + resource_allocation_manager_.AcquireResource( + module_uid.first, module_uid.second, app->app_id()) == + AcquireResult::REJECTED; + + if (!is_resource_available && !is_resource_rejected) { + out_consents_array.clear(); + break; + } + + out_consents_array.push_back(smart_objects::SmartObject( + is_resource_available ? true : false)); + continue; + } + + const bool is_resource_available = + rc_rpc_types::ModuleConsent::CONSENTED == consent; + out_consents_array.push_back( + smart_objects::SmartObject(is_resource_available)); + } + }; + + const auto access_mode = resource_allocation_manager_.GetAccessMode(); + if (hmi_apis::Common_RCAccessMode::AUTO_ALLOW == access_mode) { + LOG4CXX_DEBUG(logger_, + "Current access mode is AUTO_ALLOW - returning successful " + "consents for all"); + fill_auto_allow_consents(*modules_consent_array); + return true; + } + + if (hmi_apis::Common_RCAccessMode::AUTO_DENY == access_mode) { + LOG4CXX_DEBUG(logger_, + "Current access mode is AUTO_DENY - returning true only for " + "FREE resources"); + fill_auto_deny_consents(*modules_consent_array); + return true; + } + + if (hmi_apis::Common_RCAccessMode::ASK_DRIVER == access_mode) { + LOG4CXX_DEBUG( + logger_, + "Current access mode is ASK_DRIVER - returning consents from cache"); + fill_ask_driver_consents(*modules_consent_array); + if (!modules_consent_array->empty()) { + LOG4CXX_DEBUG(logger_, "Returning consents from cache directly"); + return true; + } + } + + LOG4CXX_DEBUG( + logger_, + "Can't provide calculated consents - should send request to HMI"); + return false; +} + +bool GetInteriorVehicleDataConsentRequest::MultipleAccessAllowed( + const smart_objects::SmartArray& module_ids, + smart_objects::SmartArray& out_consents_array) const { + LOG4CXX_AUTO_TRACE(logger_); + for (auto& module_id : module_ids) { + const std::string module_type = ModuleType(); + auto app = application_manager_.application(connection_key()); + const uint32_t app_id = app->app_id(); + const ModuleUid module_uid(module_type, module_id.asString()); + const bool is_multiple_access_allowed = + rc_capabilities_manager_.IsMultipleAccessAllowed(module_uid); + if (!is_multiple_access_allowed) { + const bool is_resource_free = + (resource_allocation_manager_.AcquireResource( + module_uid.first, module_uid.second, app_id) == + AcquireResult::ALLOWED); + + out_consents_array.push_back( + smart_objects::SmartObject(is_resource_free)); + } else { + out_consents_array.clear(); + break; + } + } + + if (!out_consents_array.empty()) { + LOG4CXX_DEBUG(logger_, + "Multiple access disallowed, returning true only for " + "FREE resources"); + return false; + } + return true; +} + +bool GetInteriorVehicleDataConsentRequest::SaveModuleIdConsents( + std::string& info_out, const smart_objects::SmartObject& msg_params) { + LOG4CXX_AUTO_TRACE(logger_); + const bool is_allowed_exists = msg_params.keyExists(message_params::kAllowed); + + if (!is_allowed_exists || msg_params[message_params::kAllowed].empty()) { + info_out = "Collection of consents is absent in HMI response or empty"; + LOG4CXX_ERROR(logger_, info_out); + return false; + } + + const auto& allowed = msg_params[message_params::kAllowed]; + const auto& moduleIds = + (*message_)[app_mngr::strings::msg_params][message_params::kModuleIds]; + + if (allowed.length() != moduleIds.length()) { + info_out = + "The received module_id collection from mobile and received consent " + "collection from HMI are not equal by size."; + LOG4CXX_ERROR(logger_, info_out); + return false; + } + std::string module_type = ModuleType(); + auto module_ids = RCHelpers::RetrieveModuleIds(moduleIds); + auto module_allowed = RCHelpers::RetrieveModuleConsents(allowed); + + auto module_consents = + RCHelpers::FillModuleConsents(module_type, module_ids, module_allowed); + + auto application = application_manager_.application(connection_key()); + if (!application) { + LOG4CXX_ERROR(logger_, + "Application with connection key:" << connection_key() + << " isn't registered"); + return false; + } + std::string policy_app_id = application->policy_app_id(); + const auto mac_address = application->mac_address(); + rc_consent_manager_.SaveModuleConsents( + policy_app_id, mac_address, module_consents); + return true; +} + +} // namespace commands +} // namespace rc_rpc_plugin |