diff options
18 files changed, 689 insertions, 7 deletions
diff --git a/src/components/application_manager/include/application_manager/message_helper.h b/src/components/application_manager/include/application_manager/message_helper.h index 00c365d334..93901f03e4 100644 --- a/src/components/application_manager/include/application_manager/message_helper.h +++ b/src/components/application_manager/include/application_manager/message_helper.h @@ -303,6 +303,30 @@ class MessageHelper { const uint32_t app_id, ApplicationManager& app_mngr); + /** + * @brief Creates UI.CreateWindow request + * @param application application instance + * @param app_mngr reference to application manager + * @param windows_info smart object containing saved windows info + * @return smart object with UI.CreateWindow request + */ + static smart_objects::SmartObjectSPtr CreateUICreateWindowRequestToHMI( + ApplicationSharedPtr application, + ApplicationManager& app_mngr, + const smart_objects::SmartObject& window_info); + + /** + * @brief Creates UI.CreateWindow requests + * @param application application instance + * @param app_mngr reference to application manager + * @param windows_info smart object containing saved windows info + * @return list of smart objects with UI.CreateWindow requests + */ + static smart_objects::SmartObjectList CreateUICreateWindowRequestsToHMI( + application_manager::ApplicationSharedPtr application, + ApplicationManager& app_mngr, + const smart_objects::SmartObject& windows_info); + /* * @brief Create Common.DeviceInfo struct from device handle * @param device_handle device handle of the app @@ -712,6 +736,15 @@ class MessageHelper { */ static bool PrintSmartObject(const smart_objects::SmartObject& object); + /** + * @brief Extract window unique ID from message, this id is used for identify + * the window + * @param s_map contains application's window id + * @return window id from current message + */ + static WindowID ExtractWindowIdFromSmartObject( + const smart_objects::SmartObject& s_map); + template <typename From, typename To> static To ConvertEnumAPINoCheck(const From& input) { return static_cast<To>(input); diff --git a/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h b/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h index 0b744eec7f..6b64fcdb6e 100644 --- a/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h +++ b/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h @@ -81,6 +81,13 @@ class ResumeCtrl { application_manager::ApplicationSharedPtr application) = 0; /** + * @brief Restore widgets HMI level on the resumption response from HMI + * @param response_message smart_object with HMI message + */ + virtual void RestoreWidgetsHMIState( + const smart_objects::SmartObject& response_message) = 0; + + /** * @brief Set application HMI Level as stored in policy * @param application is application witch HMI Level is need to setup * @return true if success, otherwise return false @@ -103,6 +110,16 @@ class ResumeCtrl { bool check_policy = true) = 0; /** + * @brief RestoreAppWidgets add widgets for the application + * @param application application which will be resumed + * @param saved_app application specific section from backup file + * @return true if widgets resumed successfully otherwise - false + */ + virtual void RestoreAppWidgets( + application_manager::ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app) = 0; + + /** * @brief Remove application from list of saved applications * @param application is application which need to be removed * @return return true, if success, otherwise return false diff --git a/src/components/application_manager/include/application_manager/resumption/resume_ctrl_impl.h b/src/components/application_manager/include/application_manager/resumption/resume_ctrl_impl.h index a70e2453de..532e04b828 100644 --- a/src/components/application_manager/include/application_manager/resumption/resume_ctrl_impl.h +++ b/src/components/application_manager/include/application_manager/resumption/resume_ctrl_impl.h @@ -95,6 +95,9 @@ class ResumeCtrlImpl : public ResumeCtrl, */ bool RestoreAppHMIState(app_mngr::ApplicationSharedPtr application) OVERRIDE; + void RestoreWidgetsHMIState( + const smart_objects::SmartObject& response_message) OVERRIDE; + /** * @brief Set application HMI Level as stored in policy * @param application is application witch HMI Level is need to setup @@ -117,6 +120,14 @@ class ResumeCtrlImpl : public ResumeCtrl, bool check_policy = true) OVERRIDE; /** + * @brief RestoreAppWidgets add widgets for the application + * @param application application which will be resumed + * @param saved_app application specific section from backup file + */ + void RestoreAppWidgets(application_manager::ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app) OVERRIDE; + + /** * @brief Remove application from list of saved applications * @param application is application which need to be removed * @return return true, if success, otherwise return false @@ -609,6 +620,13 @@ class ResumeCtrlImpl : public ResumeCtrl, time_t wake_up_time_; std::shared_ptr<ResumptionData> resumption_storage_; application_manager::ApplicationManager& application_manager_; + /** + *@brief Mapping correlation id to request + *wait for on event response from HMI to resume HMI Level + */ + typedef std::map<int32_t, smart_objects::SmartObjectSPtr> + WaitingResponseToRequest; + WaitingResponseToRequest requests_msg_; }; } // namespace resumption diff --git a/src/components/application_manager/include/application_manager/resumption/resumption_data.h b/src/components/application_manager/include/application_manager/resumption/resumption_data.h index 7db7a09cb4..d1dada345c 100644 --- a/src/components/application_manager/include/application_manager/resumption/resumption_data.h +++ b/src/components/application_manager/include/application_manager/resumption/resumption_data.h @@ -1,5 +1,5 @@ -/* - * Copyright (c) 2015, Ford Motor Company +/* + * Copyright (c) 2019, Ford Motor Company * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -256,6 +256,14 @@ class ResumptionData { app_mngr::ApplicationConstSharedPtr application) const; /** + * @brief Retrieves of windows info from list of available window + * @param application contains list of available windows + * @return windows info from list of available window + */ + smart_objects::SmartObject GetApplicationWidgetsInfo( + app_mngr::ApplicationConstSharedPtr application) const; + + /** * @brief checks pointer that it is not equal NULL * @param ptr - contains pointer which need to check * @return smartObject from pointer @@ -264,6 +272,21 @@ class ResumptionData { const smart_objects::SmartObject* ptr) const; /** + * @brief creates smart object containing window info + * @param window_id window id + * @param window_type window type + * @param window_name window name + * @param window_optional_params_map collection containing optional params for + * creating window + * @return smart object with window data + */ + smart_objects::SmartObject CreateWindowInfoSO( + const application_manager::WindowID window_id, + const mobile_apis::WindowType::eType window_type, + const application_manager::WindowParamsMap& window_optional_params_map) + const; + + /** * @brief Creates smart array from received data * @param first - iterator points to beginning of the data * @param last - iterator points to ending of the data diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index cae65959bd..20a53b9780 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -3332,6 +3332,8 @@ void ApplicationManagerImpl::ProcessPostponedMessages(const uint32_t app_id) { const std::string function_id = MessageHelper::StringifiedFunctionID( static_cast<mobile_apis::FunctionID::eType>( (*message)[strings::params][strings::function_id].asUInt())); + const WindowID window_id = MessageHelper::ExtractWindowIdFromSmartObject( + (*message)[strings::msg_params]); const RPCParams params; const mobile_apis::Result::eType check_result = CheckPolicyPermissions(app, window_id, function_id, params); diff --git a/src/components/application_manager/src/message_helper/message_helper.cc b/src/components/application_manager/src/message_helper/message_helper.cc index 97948d9a8c..105e1115a9 100644 --- a/src/components/application_manager/src/message_helper/message_helper.cc +++ b/src/components/application_manager/src/message_helper/message_helper.cc @@ -1564,6 +1564,67 @@ smart_objects::SmartObjectSPtr MessageHelper::CreateAddVRCommandToHMI( return vr_command; } +smart_objects::SmartObjectSPtr MessageHelper::CreateUICreateWindowRequestToHMI( + ApplicationSharedPtr application, + ApplicationManager& app_mngr, + const smart_objects::SmartObject& window_info) { + LOG4CXX_AUTO_TRACE(logger_); + auto ui_request = CreateMessageForHMI(hmi_apis::messageType::request, + app_mngr.GetNextHMICorrelationID()); + + (*ui_request)[strings::params][strings::function_id] = + static_cast<int>(hmi_apis::FunctionID::UI_CreateWindow); + + (*ui_request)[strings::correlation_id] = + (*ui_request)[strings::params][strings::correlation_id]; + (*ui_request)[strings::function_id] = + (*ui_request)[strings::params][strings::function_id]; + + smart_objects::SmartObject msg_params( + smart_objects::SmartObject(smart_objects::SmartType_Map)); + + msg_params[strings::window_id] = window_info[strings::window_id].asInt(); + msg_params[strings::window_type] = window_info[strings::window_type].asInt(); + msg_params[strings::window_name] = + window_info[strings::window_name].asString(); + + if (window_info.keyExists(strings::associated_service_type)) { + msg_params[strings::associated_service_type] = + window_info[strings::associated_service_type].asString(); + } + if (window_info.keyExists(strings::duplicate_updates_from_window_id)) { + msg_params[strings::duplicate_updates_from_window_id] = + window_info[strings::duplicate_updates_from_window_id].asInt(); + } + + msg_params[strings::app_id] = application->hmi_app_id(); + + (*ui_request)[strings::msg_params] = msg_params; + + return ui_request; +} + +smart_objects::SmartObjectList MessageHelper::CreateUICreateWindowRequestsToHMI( + application_manager::ApplicationSharedPtr application, + ApplicationManager& app_mngr, + const smart_objects::SmartObject& windows_info) { + smart_objects::SmartObjectList requests; + DCHECK_OR_RETURN(application, requests); + + for (size_t i = 0; i < windows_info.length(); ++i) { + const auto& info = windows_info[i]; + + const auto ui_request = + CreateUICreateWindowRequestToHMI(application, app_mngr, info); + + DCHECK_OR_RETURN(ui_request, requests); + + requests.push_back(ui_request); + } + + return requests; +} + bool MessageHelper::CreateDeviceInfo( connection_handler::DeviceHandle device_handle, const protocol_handler::SessionObserver& session_observer, @@ -3039,4 +3100,14 @@ bool MessageHelper::PrintSmartObject(const smart_objects::SmartObject& object) { return true; } +WindowID MessageHelper::ExtractWindowIdFromSmartObject( + const smart_objects::SmartObject& s_map) { + if (smart_objects::SmartType_Map == s_map.getType()) { + if (s_map.keyExists(strings::window_id)) { + return s_map[strings::window_id].asUInt(); + } + } + return mobile_apis::PredefinedWindows::DEFAULT_WINDOW; +} + } // namespace application_manager diff --git a/src/components/application_manager/src/resumption/resume_ctrl_impl.cc b/src/components/application_manager/src/resumption/resume_ctrl_impl.cc index bb796e8267..6f4d9d22b6 100644 --- a/src/components/application_manager/src/resumption/resume_ctrl_impl.cc +++ b/src/components/application_manager/src/resumption/resume_ctrl_impl.cc @@ -159,7 +159,13 @@ void ResumeCtrlImpl::SaveApplication(ApplicationSharedPtr application) { } void ResumeCtrlImpl::on_event(const event_engine::Event& event) { - LOG4CXX_DEBUG(logger_, "Event received" << event.id()); + LOG4CXX_DEBUG(logger_, "Event received: " << event.id()); + + if (hmi_apis::FunctionID::UI_CreateWindow == event.id()) { + LOG4CXX_INFO(logger_, "Received UI_CreateWindow event"); + const auto& response_message = event.smart_object(); + RestoreWidgetsHMIState(response_message); + } } bool ResumeCtrlImpl::RestoreAppHMIState(ApplicationSharedPtr application) { @@ -208,7 +214,11 @@ bool ResumeCtrlImpl::RestoreAppHMIState(ApplicationSharedPtr application) { << saved_hmi_level); } - return SetAppHMIState(application, saved_hmi_level, true); + const bool app_hmi_state_is_set = + SetAppHMIState(application, saved_hmi_level, true); + if (app_hmi_state_is_set) { + RestoreAppWidgets(application, saved_app); + } } else { result = false; LOG4CXX_ERROR(logger_, "saved app data corrupted"); @@ -219,6 +229,74 @@ bool ResumeCtrlImpl::RestoreAppHMIState(ApplicationSharedPtr application) { return result; } +void ResumeCtrlImpl::RestoreWidgetsHMIState( + const smart_objects::SmartObject& response_message) { + LOG4CXX_AUTO_TRACE(logger_); + const auto correlation_id = + response_message[strings::params][strings::correlation_id].asInt(); + const auto& request = requests_msg_.find(correlation_id); + if (requests_msg_.end() == request) { + LOG4CXX_ERROR(logger_, + "Request UI_CreateWindow for correlation id: " + << correlation_id << " not found"); + return; + } + const auto result_code = static_cast<hmi_apis::Common_Result::eType>( + response_message[strings::params][hmi_response::code].asInt()); + if (hmi_apis::Common_Result::SUCCESS != result_code) { + LOG4CXX_ERROR(logger_, + "UI_CreateWindow for correlation id: " + << correlation_id + << " failed with code: " << result_code); + requests_msg_.erase(request); + return; + } + + const auto& msg_params = (*request->second)[strings::msg_params]; + const auto hmi_app_id = msg_params[strings::app_id].asInt(); + auto application = application_manager_.application_by_hmi_app(hmi_app_id); + if (!application) { + LOG4CXX_ERROR(logger_, + "Application is not registered by hmi id: " << hmi_app_id); + requests_msg_.erase(request); + return; + } + smart_objects::SmartObject window_info(smart_objects::SmartType_Map); + auto fill_optional_param = [&window_info, + &msg_params](const std::string& key) { + if (msg_params.keyExists(key)) { + window_info[key] = msg_params[key].asString(); + } + }; + fill_optional_param(strings::associated_service_type); + fill_optional_param(strings::duplicate_updates_from_window_id); + + const auto window_name = msg_params[strings::window_name].asString(); + window_info[strings::window_name] = window_name; + + const WindowID window_id = msg_params[strings::window_id].asUInt(); + application->AddWindowInfo(window_id, window_info); + + const auto window_type = static_cast<mobile_apis::WindowType::eType>( + msg_params[strings::window_type].asInt()); + // State should be initialized with INVALID_ENUM value to let state controller + // trigger OnHmiStatus notifiation sending + auto initial_state = application_manager_.CreateRegularState( + application, + window_type, + mobile_apis::HMILevel::INVALID_ENUM, + mobile_apis::AudioStreamingState::INVALID_ENUM, + mobile_apis::VideoStreamingState::INVALID_ENUM, + mobile_api::SystemContext::INVALID_ENUM); + application->SetInitialState(window_id, window_name, initial_state); + + // Default HMI level for all windows except the main one is always NONE + application_manager_.state_controller().OnAppWindowAdded( + application, window_id, window_type, mobile_apis::HMILevel::HMI_NONE); + + requests_msg_.erase(request); +} + bool ResumeCtrlImpl::SetupDefaultHMILevel(ApplicationSharedPtr application) { LOG4CXX_AUTO_TRACE(logger_); DCHECK_OR_RETURN(application, false); @@ -300,6 +378,28 @@ bool ResumeCtrlImpl::SetAppHMIState( return true; } +void ResumeCtrlImpl::RestoreAppWidgets( + application_manager::ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app) { + using namespace mobile_apis; + LOG4CXX_AUTO_TRACE(logger_); + DCHECK(application); + if (!saved_app.keyExists(strings::windows_info)) { + LOG4CXX_ERROR(logger_, "windows_info section does not exist"); + return; + } + const auto& windows_info = saved_app[strings::windows_info]; + auto request_list = MessageHelper::CreateUICreateWindowRequestsToHMI( + application, application_manager_, windows_info); + + requests_msg_.clear(); + for (auto& request : request_list) { + requests_msg_.insert(std::make_pair( + (*request)[strings::params][strings::correlation_id].asInt(), request)); + } + ProcessHMIRequests(request_list); +} + bool ResumeCtrlImpl::IsHMIApplicationIdExist(uint32_t hmi_app_id) { LOG4CXX_DEBUG(logger_, "hmi_app_id :" << hmi_app_id); return resumption_storage_->IsHMIApplicationIdExist(hmi_app_id); @@ -1006,7 +1106,8 @@ bool ResumeCtrlImpl::ProcessHMIRequest(smart_objects::SmartObjectSPtr request, (*request)[strings::correlation_id].asInt(); subscribe_on_event(function_id, hmi_correlation_id); } - if (!application_manager_.GetRPCService().ManageHMICommand(request)) { + if (!application_manager_.GetRPCService().ManageHMICommand( + request, commands::Command::SOURCE_SDL_TO_HMI)) { LOG4CXX_ERROR(logger_, "Unable to send request"); return false; } diff --git a/src/components/application_manager/src/resumption/resumption_data.cc b/src/components/application_manager/src/resumption/resumption_data.cc index b4d39eccc1..9046fe35ad 100644 --- a/src/components/application_manager/src/resumption/resumption_data.cc +++ b/src/components/application_manager/src/resumption/resumption_data.cc @@ -198,6 +198,52 @@ smart_objects::SmartObject ResumptionData::GetApplicationFiles( return files; } +smart_objects::SmartObject ResumptionData::GetApplicationWidgetsInfo( + app_mngr::ApplicationConstSharedPtr application) const { + using namespace app_mngr; + LOG4CXX_AUTO_TRACE(logger_); + smart_objects::SmartObject windows_info = + smart_objects::SmartObject(smart_objects::SmartType_Array); + DCHECK_OR_RETURN(application, windows_info); + const auto window_ids = application->GetWindowIds(); + const auto& window_optional_params_map = + application->window_optional_params_map().GetData(); + for (const auto& window_id : window_ids) { + const HmiStatePtr hmi_state = application->CurrentHmiState(window_id); + if (mobile_apis::WindowType::WIDGET != hmi_state->window_type()) { + continue; + } + auto info = CreateWindowInfoSO( + window_id, hmi_state->window_type(), window_optional_params_map); + + windows_info[windows_info.length()] = info; + } + return windows_info; +} + +smart_objects::SmartObject ResumptionData::CreateWindowInfoSO( + const app_mngr::WindowID window_id, + const mobile_apis::WindowType::eType window_type, + const app_mngr::WindowParamsMap& window_optional_params_map) const { + using namespace app_mngr; + LOG4CXX_AUTO_TRACE(logger_); + auto window_info = smart_objects::SmartObject(smart_objects::SmartType_Map); + + window_info[strings::window_id] = window_id; + window_info[strings::window_type] = window_type; + + const auto& it_info = window_optional_params_map.find(window_id); + if (window_optional_params_map.end() != it_info) { + const auto keys = it_info->second->enumerate(); + + for (const auto& key : keys) { + window_info[key] = (*it_info->second)[key]; + } + } + + return window_info; +} + smart_objects::SmartObject ResumptionData::PointerToSmartObj( const smart_objects::SmartObject* ptr) const { LOG4CXX_AUTO_TRACE(logger_); diff --git a/src/components/application_manager/src/resumption/resumption_data_json.cc b/src/components/application_manager/src/resumption/resumption_data_json.cc index 525d3694d4..5da47d31ce 100644 --- a/src/components/application_manager/src/resumption/resumption_data_json.cc +++ b/src/components/application_manager/src/resumption/resumption_data_json.cc @@ -100,6 +100,9 @@ void ResumptionDataJson::SaveApplication( formatters::CFormatterJsonBase::objToJsonValue( GetApplicationFiles(application), tmp); json_app[strings::application_files] = tmp; + formatters::CFormatterJsonBase::objToJsonValue( + GetApplicationWidgetsInfo(application), tmp); + json_app[strings::windows_info] = tmp; json_app[strings::time_stamp] = time_stamp; json_app[strings::subscribed_for_way_points] = is_subscribed_for_way_points; diff --git a/src/components/application_manager/src/rpc_passing_handler.cc b/src/components/application_manager/src/rpc_passing_handler.cc index 92d6e74698..8d63e9489f 100644 --- a/src/components/application_manager/src/rpc_passing_handler.cc +++ b/src/components/application_manager/src/rpc_passing_handler.cc @@ -108,6 +108,8 @@ bool RPCPassingHandler::ExtractRPCParams( } CommandParametersPermissions parameters_permissions; + const WindowID window_id = + MessageHelper::ExtractWindowIdFromSmartObject(s_map); mobile_apis::Result::eType check_result = app_manager_.CheckPolicyPermissions( app, window_id, function_id_str, params, ¶meters_permissions); diff --git a/src/components/application_manager/src/rpc_service_impl.cc b/src/components/application_manager/src/rpc_service_impl.cc index a20ee8bc38..c7d1bde288 100644 --- a/src/components/application_manager/src/rpc_service_impl.cc +++ b/src/components/application_manager/src/rpc_service_impl.cc @@ -467,9 +467,12 @@ void RPCServiceImpl::SendMessageToMobile( mobile_apis::FunctionID::eType function_id = static_cast<mobile_apis::FunctionID::eType>( (*message)[strings::params][strings::function_id].asUInt()); + RPCParams params; const smart_objects::SmartObject& s_map = (*message)[strings::msg_params]; + const WindowID window_id = + MessageHelper::ExtractWindowIdFromSmartObject(s_map); if (smart_objects::SmartType_Map == s_map.getType()) { smart_objects::SmartMap::iterator iter = s_map.map_begin(); smart_objects::SmartMap::iterator iter_end = s_map.map_end(); diff --git a/src/components/application_manager/test/include/application_manager/mock_message_helper.h b/src/components/application_manager/test/include/application_manager/mock_message_helper.h index c486a420f5..4fd331bb3e 100644 --- a/src/components/application_manager/test/include/application_manager/mock_message_helper.h +++ b/src/components/application_manager/test/include/application_manager/mock_message_helper.h @@ -284,6 +284,10 @@ class MockMessageHelper { MOCK_METHOD1(PrintSmartObject, bool(const smart_objects::SmartObject& object)); + + MOCK_METHOD1(ExtractWindowIdFromSmartObject, + WindowID(const smart_objects::SmartObject& s_map)); + MOCK_METHOD3(SendTTSGlobalProperties, void(ApplicationSharedPtr app, const bool default_help_prompt, @@ -322,6 +326,11 @@ class MockMessageHelper { MOCK_METHOD2(BroadcastCapabilityUpdate, void(smart_objects::SmartObject& msg_params, ApplicationManager& app_mngr)); + MOCK_METHOD3(CreateUICreateWindowRequestsToHMI, + smart_objects::SmartObjectList( + ApplicationSharedPtr application, + ApplicationManager& app_manager, + const smart_objects::SmartObject& windows_info)); static MockMessageHelper* message_helper_mock(); }; diff --git a/src/components/application_manager/test/include/application_manager/mock_resume_ctrl.h b/src/components/application_manager/test/include/application_manager/mock_resume_ctrl.h index 4fd3b7fc5a..01d286e22e 100644 --- a/src/components/application_manager/test/include/application_manager/mock_resume_ctrl.h +++ b/src/components/application_manager/test/include/application_manager/mock_resume_ctrl.h @@ -101,6 +101,13 @@ class MockResumeCtrl : public resumption::ResumeCtrl { bool check_policy)); MOCK_CONST_METHOD0(LaunchTime, time_t()); + MOCK_METHOD2(RestoreAppWidgets, + void(app_mngr::ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app)); + + MOCK_METHOD1(RestoreWidgetsHMIState, + void(const smart_objects::SmartObject& response_message)); + #ifdef BUILD_TESTS MOCK_METHOD1(set_resumption_storage, void(std::shared_ptr<resumption::ResumptionData> mock_storage)); diff --git a/src/components/application_manager/test/include/application_manager/resumption_data_test.h b/src/components/application_manager/test/include/application_manager/resumption_data_test.h index cab3c23253..e313427547 100644 --- a/src/components/application_manager/test/include/application_manager/resumption_data_test.h +++ b/src/components/application_manager/test/include/application_manager/resumption_data_test.h @@ -74,7 +74,9 @@ class ResumptionDataTest : public ::testing::Test { , comlock_ptr_(std::make_shared<sync_primitives::Lock>()) , setlock_ptr_(std::make_shared<sync_primitives::Lock>()) , btnlock_ptr_(std::make_shared<sync_primitives::Lock>()) - , ivilock_ptr_(std::make_shared<sync_primitives::Lock>()) {} + , ivilock_ptr_(std::make_shared<sync_primitives::Lock>()) + , window_params_map_lock_ptr_(std::make_shared<sync_primitives::Lock>()) { + } // Check structure in saved application void CheckSavedApp(sm::SmartObject& saved_data); // Set data for resumption @@ -114,6 +116,9 @@ class ResumptionDataTest : public ::testing::Test { void SetHelpAndTimeoutPrompt(); void SetVRHelpTitle(); void SetSubscriptions(); + void SetWindowsInfo(); + void SetDefaultCurrentHmiState(); + void SetDefaultWindowIds(); void CheckCommands(sm::SmartObject& res_list); void CheckGlobalProporties(sm::SmartObject& res_list); @@ -129,6 +134,7 @@ class ResumptionDataTest : public ::testing::Test { ns_smart_device_link::ns_smart_objects::SmartObject& res_list); void CheckVRTitle(sm::SmartObject& res_list); void CheckSubscriptions(sm::SmartObject& res_list); + void CheckWindowsInfo(sm::SmartObject& res_list); const size_t kCountOfCommands_; const size_t kCountOfChoice_; @@ -145,11 +151,14 @@ class ResumptionDataTest : public ::testing::Test { am::ButtonSubscriptions btn_subscr; + am::WindowParamsMap test_window_params_map_; + std::shared_ptr<sync_primitives::Lock> sublock_ptr_; std::shared_ptr<sync_primitives::Lock> comlock_ptr_; std::shared_ptr<sync_primitives::Lock> setlock_ptr_; std::shared_ptr<sync_primitives::Lock> btnlock_ptr_; std::shared_ptr<sync_primitives::Lock> ivilock_ptr_; + std::shared_ptr<sync_primitives::Lock> window_params_map_lock_ptr_; application_manager_test::MockApplicationManagerSettings mock_application_manager_settings_; application_manager_test::MockApplicationManager mock_application_manager_; diff --git a/src/components/application_manager/test/message_helper/message_helper_test.cc b/src/components/application_manager/test/message_helper/message_helper_test.cc index d0fbe696cd..a174d74d5d 100644 --- a/src/components/application_manager/test/message_helper/message_helper_test.cc +++ b/src/components/application_manager/test/message_helper/message_helper_test.cc @@ -1084,6 +1084,27 @@ TEST_F(MessageHelperTest, SendNaviSetVideoConfigRequest) { EXPECT_EQ(480, msg_params[strings::config][strings::height].asInt()); } +TEST_F(MessageHelperTest, ExtractWindowIdFromSmartObject_SUCCESS) { + const WindowID window_id = 145; + smart_objects::SmartObject message(smart_objects::SmartType_Map); + message[strings::msg_params][strings::window_id] = window_id; + EXPECT_EQ(window_id, + MessageHelper::ExtractWindowIdFromSmartObject( + message[strings::msg_params])); +} + +TEST_F(MessageHelperTest, ExtractWindowIdFromSmartObject_FromEmptyMessage) { + smart_objects::SmartObject message(smart_objects::SmartType_Map); + EXPECT_EQ(mobile_apis::PredefinedWindows::DEFAULT_WINDOW, + MessageHelper::ExtractWindowIdFromSmartObject(message)); +} + +TEST_F(MessageHelperTest, ExtractWindowIdFromSmartObject_FromWrongType) { + smart_objects::SmartObject message(smart_objects::SmartType_Array); + EXPECT_EQ(mobile_apis::PredefinedWindows::DEFAULT_WINDOW, + MessageHelper::ExtractWindowIdFromSmartObject(message)); +} + } // namespace application_manager_test } // namespace components } // namespace test diff --git a/src/components/application_manager/test/mock_message_helper.cc b/src/components/application_manager/test/mock_message_helper.cc index ce022f956b..ecaad48365 100644 --- a/src/components/application_manager/test/mock_message_helper.cc +++ b/src/components/application_manager/test/mock_message_helper.cc @@ -529,6 +529,12 @@ bool MessageHelper::PrintSmartObject(const smart_objects::SmartObject& object) { return MockMessageHelper::message_helper_mock()->PrintSmartObject(object); } +WindowID MessageHelper::ExtractWindowIdFromSmartObject( + const smart_objects::SmartObject& s_map) { + return MockMessageHelper::message_helper_mock() + ->ExtractWindowIdFromSmartObject(s_map); +} + void MessageHelper::SendSetAppIcon(const uint32_t app_id, const std::string& icon_path, ApplicationManager& application_manager) { @@ -596,4 +602,11 @@ void MessageHelper::BroadcastCapabilityUpdate( msg_params, app_mngr); } +smart_objects::SmartObjectList MessageHelper::CreateUICreateWindowRequestsToHMI( + application_manager::ApplicationSharedPtr application, + ApplicationManager& app_mngr, + const smart_objects::SmartObject& windows_info) { + return MockMessageHelper::message_helper_mock() + ->CreateUICreateWindowRequestsToHMI(application, app_mngr, windows_info); +} } // namespace application_manager diff --git a/src/components/application_manager/test/resumption/resume_ctrl_test.cc b/src/components/application_manager/test/resumption/resume_ctrl_test.cc index 19c688c9b4..ca05e3fce5 100644 --- a/src/components/application_manager/test/resumption/resume_ctrl_test.cc +++ b/src/components/application_manager/test/resumption/resume_ctrl_test.cc @@ -39,6 +39,7 @@ #include "application_manager/mock_application.h" #include "application_manager/mock_help_prompt_manager.h" #include "application_manager/mock_resumption_data.h" +#include "application_manager/mock_rpc_service.h" #include "application_manager/resumption/resume_ctrl_impl.h" #include "application_manager/usage_statistics.h" #include "config_profile/profile.h" @@ -76,7 +77,8 @@ using namespace mobile_apis::HMILevel; namespace { const WindowID kDefaultWindowId = mobile_apis::PredefinedWindows::DEFAULT_WINDOW; -} +const int32_t kDefaultHmiAppId = 111; +} // namespace class ResumeCtrlTest : public ::testing::Test { protected: @@ -161,6 +163,43 @@ class ResumeCtrlTest : public ::testing::Test { ON_CALL(*mock_app_, is_cloud_app()).WillByDefault(Return(false)); } + smart_objects::SmartObjectSPtr CreateStubCreateWindowRequest( + const std::string window_name, + const WindowID window_id, + const mobile_apis::WindowType::eType window_type) const { + auto request = std::make_shared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + smart_objects::SmartObject msg_params(smart_objects::SmartType_Map); + smart_objects::SmartObject params(smart_objects::SmartType_Map); + + params[strings::correlation_id] = window_id; + + msg_params[strings::window_name] = window_name; + msg_params[strings::window_id] = window_id; + msg_params[strings::window_type] = window_type; + msg_params[strings::app_id] = kDefaultHmiAppId; + + (*request)[strings::msg_params] = msg_params; + (*request)[strings::params] = params; + + return request; + } + + smart_objects::SmartObjectSPtr CreateStubCreateWindowResponse( + const int32_t correlation_id, + const hmi_apis::Common_Result::eType result_code) const { + auto response = std::make_shared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + smart_objects::SmartObject params(smart_objects::SmartType_Map); + + params[strings::correlation_id] = correlation_id; + params[hmi_response::code] = result_code; + + (*response)[strings::params] = params; + + return response; + } + NiceMock<event_engine_test::MockEventDispatcher> mock_event_dispatcher_; application_manager_test::MockApplicationManagerSettings mock_application_manager_settings_; @@ -190,6 +229,7 @@ class ResumeCtrlTest : public ::testing::Test { const std::string kNaviLowbandwidthLevel_; const std::string kProjectionLowbandwidthLevel_; const std::string kMediaLowbandwidthLevel_; + NiceMock<application_manager_test::MockRPCService> mock_rpc_service_; }; /** @@ -584,6 +624,207 @@ TEST_F(ResumeCtrlTest, StartResumption_AppWithSubscriptionToWayPoints) { EXPECT_TRUE(result); } +TEST_F(ResumeCtrlTest, + RestoreAppWidgets_AppWithWidgets_SendCreateWindowRequests) { + using namespace smart_objects; + using namespace application_manager; + GetInfoFromApp(); + const uint32_t count_of_widgets = 10u; + + auto create_window_info_so = []() -> SmartObject { + SmartObject widgets_info(SmartType_Array); + for (uint32_t i = 0; i < count_of_widgets; ++i) { + SmartObject widget_info(SmartType_Map); + widget_info[strings::associated_service_type] = "ServiceType"; + widget_info[strings::duplicate_updates_from_window_id] = 0; + widget_info[strings::window_name] = + std::string("Widget ") + std::to_string(i + 1); + widget_info[strings::window_type] = + static_cast<int32_t>(mobile_apis::WindowType::WIDGET); + widget_info[strings::window_id] = i + 1; + widgets_info[widgets_info.length()] = widget_info; + } + return widgets_info; + }; + + auto create_saved_app_so = [&create_window_info_so, this]() -> SmartObject { + smart_objects::SmartObject saved_app; + const auto test_app_widgets = create_window_info_so(); + saved_app[strings::hash_id] = kHash_; + saved_app[strings::windows_info] = test_app_widgets; + saved_app[application_manager::strings::grammar_id] = kTestGrammarId_; + saved_app[application_manager::strings::hmi_level] = eType::HMI_FULL; + return saved_app; + }; + + const auto saved_app = create_saved_app_so(); + + const auto hmi_request = std::make_shared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + const auto hmi_requests = + smart_objects::SmartObjectList(count_of_widgets, hmi_request); + + EXPECT_CALL( + *application_manager::MockMessageHelper::message_helper_mock(), + CreateUICreateWindowRequestsToHMI(_, _, saved_app[strings::windows_info])) + .WillOnce(Return(hmi_requests)); + + ON_CALL(mock_app_mngr_, GetRPCService()) + .WillByDefault(ReturnRef(mock_rpc_service_)); + + EXPECT_CALL(mock_rpc_service_, + ManageHMICommand(_, commands::Command::SOURCE_SDL_TO_HMI)) + .Times(count_of_widgets) + .WillRepeatedly(Return(true)); + + res_ctrl_->RestoreAppWidgets(mock_app_, saved_app); +} + +TEST_F(ResumeCtrlTest, + RestoreWidgetsHMIState_AppWithWidgets_AddWidgetsInternally) { + const uint32_t count_of_widgets = 10u; + + smart_objects::SmartObject saved_app; + saved_app[strings::hash_id] = kHash_; + saved_app[strings::windows_info] = smart_objects::SmartObject(); + saved_app[application_manager::strings::grammar_id] = kTestGrammarId_; + saved_app[application_manager::strings::hmi_level] = eType::HMI_FULL; + + ON_CALL(mock_app_mngr_, application_by_hmi_app(kDefaultHmiAppId)) + .WillByDefault(Return(mock_app_)); + + smart_objects::SmartObjectList requests; + smart_objects::SmartObjectList responses; + for (uint32_t i = 0; i < count_of_widgets; ++i) { + const auto window_type = mobile_apis::WindowType::WIDGET; + const WindowID window_id = i + 1; + const auto window_name = std::string("Widget ") + std::to_string(window_id); + requests.push_back( + CreateStubCreateWindowRequest(window_name, window_id, window_type)); + responses.push_back(CreateStubCreateWindowResponse( + window_id, hmi_apis::Common_Result::SUCCESS)); + EXPECT_CALL(mock_app_mngr_, CreateRegularState(_, window_type, _, _, _, _)) + .WillRepeatedly(Return(nullptr)); + EXPECT_CALL(*mock_app_, SetInitialState(window_id, window_name, _)); + EXPECT_CALL(mock_state_controller_, + OnAppWindowAdded(_, window_id, window_type, _)); + } + + EXPECT_CALL(*application_manager::MockMessageHelper::message_helper_mock(), + CreateUICreateWindowRequestsToHMI(_, _, _)) + .WillOnce(Return(requests)); + + ON_CALL(mock_app_mngr_, GetRPCService()) + .WillByDefault(ReturnRef(mock_rpc_service_)); + EXPECT_CALL(mock_rpc_service_, + ManageHMICommand(_, commands::Command::SOURCE_SDL_TO_HMI)) + .Times(count_of_widgets) + .WillRepeatedly(Return(true)); + res_ctrl_->RestoreAppWidgets(mock_app_, saved_app); + for (const auto& response : responses) { + res_ctrl_->RestoreWidgetsHMIState(*response); + } +} + +TEST_F(ResumeCtrlTest, + RestoreAppWidgets_AppWithoutWidgets_NoCreateWindowRqSent) { + smart_objects::SmartObject saved_app; + saved_app[strings::hash_id] = kHash_; + saved_app[application_manager::strings::grammar_id] = kTestGrammarId_; + saved_app[application_manager::strings::hmi_level] = eType::HMI_FULL; + + EXPECT_CALL(*application_manager::MockMessageHelper::message_helper_mock(), + CreateUICreateWindowRequestsToHMI(_, _, _)) + .Times(0); + + res_ctrl_->RestoreAppWidgets(mock_app_, saved_app); +} + +TEST_F(ResumeCtrlTest, RestoreWidgetsHMIState_HMIResponseWith_InvalidCorrId) { + smart_objects::SmartObject saved_app; + saved_app[strings::hash_id] = kHash_; + saved_app[strings::windows_info] = smart_objects::SmartObject(); + saved_app[application_manager::strings::grammar_id] = kTestGrammarId_; + saved_app[application_manager::strings::hmi_level] = eType::HMI_FULL; + + const int32_t invalid_corr_id = -1; + auto response = CreateStubCreateWindowResponse( + invalid_corr_id, hmi_apis::Common_Result::SUCCESS); + + ON_CALL(mock_app_mngr_, application_by_hmi_app(kDefaultHmiAppId)) + .WillByDefault(Return(mock_app_)); + + smart_objects::SmartObjectList requests; + + const auto window_type = mobile_apis::WindowType::WIDGET; + const WindowID window_id = 1; + const auto window_name = std::string("Widget ") + std::to_string(window_id); + requests.push_back( + CreateStubCreateWindowRequest(window_name, window_id, window_type)); + + EXPECT_CALL(mock_app_mngr_, CreateRegularState(_, window_type, _, _, _, _)) + .Times(0); + EXPECT_CALL(*mock_app_, SetInitialState(window_id, window_name, _)).Times(0); + EXPECT_CALL(mock_state_controller_, + OnAppWindowAdded(_, window_id, window_type, _)) + .Times(0); + + EXPECT_CALL(*application_manager::MockMessageHelper::message_helper_mock(), + CreateUICreateWindowRequestsToHMI(_, _, _)) + .WillOnce(Return(requests)); + + ON_CALL(mock_app_mngr_, GetRPCService()) + .WillByDefault(ReturnRef(mock_rpc_service_)); + EXPECT_CALL(mock_rpc_service_, + ManageHMICommand(_, commands::Command::SOURCE_SDL_TO_HMI)) + .WillRepeatedly(Return(true)); + res_ctrl_->RestoreAppWidgets(mock_app_, saved_app); + res_ctrl_->RestoreWidgetsHMIState(*response); +} + +TEST_F(ResumeCtrlTest, RestoreWidgetsHMIState_HMIResponseWith_Unsuccess) { + smart_objects::SmartObject saved_app; + saved_app[strings::hash_id] = kHash_; + saved_app[strings::windows_info] = smart_objects::SmartObject(); + saved_app[application_manager::strings::grammar_id] = kTestGrammarId_; + saved_app[application_manager::strings::hmi_level] = eType::HMI_FULL; + + const int32_t correlation_id = 1; + auto response = CreateStubCreateWindowResponse( + correlation_id, hmi_apis::Common_Result::GENERIC_ERROR); + + ON_CALL(mock_app_mngr_, application_by_hmi_app(kDefaultHmiAppId)) + .WillByDefault(Return(mock_app_)); + + smart_objects::SmartObjectList requests; + smart_objects::SmartObjectList responses; + + const auto window_type = mobile_apis::WindowType::WIDGET; + const WindowID window_id = 1; + const auto window_name = std::string("Widget ") + std::to_string(window_id); + requests.push_back( + CreateStubCreateWindowRequest(window_name, window_id, window_type)); + + EXPECT_CALL(mock_app_mngr_, CreateRegularState(_, window_type, _, _, _, _)) + .Times(0); + EXPECT_CALL(*mock_app_, SetInitialState(window_id, window_name, _)).Times(0); + EXPECT_CALL(mock_state_controller_, + OnAppWindowAdded(_, window_id, window_type, _)) + .Times(0); + + EXPECT_CALL(*application_manager::MockMessageHelper::message_helper_mock(), + CreateUICreateWindowRequestsToHMI(_, _, _)) + .WillOnce(Return(requests)); + + ON_CALL(mock_app_mngr_, GetRPCService()) + .WillByDefault(ReturnRef(mock_rpc_service_)); + EXPECT_CALL(mock_rpc_service_, + ManageHMICommand(_, commands::Command::SOURCE_SDL_TO_HMI)) + .WillRepeatedly(Return(true)); + res_ctrl_->RestoreAppWidgets(mock_app_, saved_app); + res_ctrl_->RestoreWidgetsHMIState(*response); +} + TEST_F(ResumeCtrlTest, StartResumptionOnlyHMILevel) { smart_objects::SmartObject saved_app; diff --git a/src/components/application_manager/test/resumption/resumption_data_test.cc b/src/components/application_manager/test/resumption/resumption_data_test.cc index 516090c032..e362064a78 100644 --- a/src/components/application_manager/test/resumption/resumption_data_test.cc +++ b/src/components/application_manager/test/resumption/resumption_data_test.cc @@ -74,6 +74,7 @@ void ResumptionDataTest::CheckSavedApp(sm::SmartObject& resume_app_list) { CheckGlobalProporties( resume_app_list[am::strings::application_global_properties]); CheckSubscriptions(resume_app_list[am::strings::application_subscriptions]); + CheckWindowsInfo(resume_app_list[am::strings::windows_info]); } void ResumptionDataTest::CheckCommands(sm::SmartObject& res_list) { @@ -327,6 +328,33 @@ void ResumptionDataTest::CheckVRTitle( EXPECT_EQ(vtitle, res_list[am::strings::vr_help_title].asString()); } +void ResumptionDataTest::CheckWindowsInfo(sm::SmartObject& res_list) { + using namespace application_manager; + auto check_window_info = [this]( + const smart_objects::SmartObject& window_info) { + using namespace application_manager; + const WindowID saved_window_id = window_info[strings::window_id].asInt(); + const auto test_window_info = test_window_params_map_[saved_window_id]; + const auto& saved_window_name = + window_info[strings::window_name].asString(); + ASSERT_TRUE(0 != test_window_info.use_count()); + const auto& window_name = + (*test_window_info)[strings::window_name].asString(); + const auto& saved_duplicate_window_id = + window_info[strings::duplicate_updates_from_window_id].asInt(); + const auto& saved_associated_service_type = + window_info[strings::associated_service_type].asString(); + EXPECT_EQ(saved_window_name, window_name); + EXPECT_EQ("ServiceType", saved_associated_service_type); + EXPECT_EQ(0, saved_duplicate_window_id); + }; + + for (size_t i = 0; i < res_list.length(); ++i) { + const auto& saved_window_info = res_list[i]; + check_window_info(saved_window_info); + } +} + void ResumptionDataTest::PrepareData() { mock_app_extension_ = std::make_shared<NiceMock<application_manager_test::MockAppExtension> >(); @@ -341,9 +369,14 @@ void ResumptionDataTest::PrepareData() { DataAccessor<am::SubMenuMap> sub_menu_m(test_submenu_map, sublock_ptr_); DataAccessor<am::CommandsMap> commands_m(test_commands_map, comlock_ptr_); DataAccessor<am::ChoiceSetMap> choice_set_m(test_choiceset_map, setlock_ptr_); + DataAccessor<am::WindowParamsMap> window_params_map( + test_window_params_map_, window_params_map_lock_ptr_); SetSubscriptions(); DataAccessor<am::ButtonSubscriptions> btn_sub(btn_subscr, btnlock_ptr_); + SetWindowsInfo(); + SetDefaultCurrentHmiState(); + SetDefaultWindowIds(); ON_CALL(*app_mock, is_application_data_changed()).WillByDefault(Return(true)); @@ -376,6 +409,21 @@ void ResumptionDataTest::PrepareData() { ON_CALL(*app_mock, SubscribedButtons()).WillByDefault(Return(btn_sub)); ON_CALL(*app_mock, getAppFiles()).WillByDefault(ReturnRef(app_files_map_)); + ON_CALL(*app_mock, window_optional_params_map()) + .WillByDefault(Return(window_params_map)); +} + +void ResumptionDataTest::SetDefaultCurrentHmiState() { + am::HmiStatePtr hmi_state = + std::make_shared<am::HmiState>(app_mock, mock_application_manager_); + hmi_state->set_window_type(mobile_apis::WindowType::WIDGET); + + ON_CALL(*app_mock, CurrentHmiState(_)).WillByDefault(Return(hmi_state)); +} + +void ResumptionDataTest::SetDefaultWindowIds() { + const am::WindowIds window_ids{1, 2, 3, 4, 5}; + ON_CALL(*app_mock, GetWindowIds()).WillByDefault(Return(window_ids)); } void ResumptionDataTest::SetGlobalProporties() { @@ -551,6 +599,21 @@ void ResumptionDataTest::SetSubscriptions() { btn_subscr.insert(ButtonName::eType::OK); } +void ResumptionDataTest::SetWindowsInfo() { + using namespace application_manager; + const uint32_t number_of_widgets = 5; + for (uint32_t i = 0; i < number_of_widgets; ++i) { + auto window_info = std::make_shared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + const WindowID window_id = i + 1; + (*window_info)[strings::window_name] = + std::string("Widget ") + std::to_string(window_id); + (*window_info)[strings::associated_service_type] = "ServiceType"; + (*window_info)[strings::duplicate_updates_from_window_id] = 0; + test_window_params_map_[window_id] = window_info; + } +} + } // namespace resumption_test } // namespace components } // namespace test |