diff options
19 files changed, 1273 insertions, 181 deletions
diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h index 0166624ef2..ae0466326c 100644 --- a/src/components/application_manager/include/application_manager/application.h +++ b/src/components/application_manager/include/application_manager/application.h @@ -46,6 +46,7 @@ #include "application_manager/message.h" #include "application_manager/hmi_state.h" #include "application_manager/application_state.h" +#include "application_manager/help_prompt_manager.h" #include "protocol_handler/protocol_handler.h" #include "smart_objects/smart_object.h" #include "utils/macro.h" @@ -638,6 +639,11 @@ class Application : public virtual InitialApplicationData, * @return object for recording statistics */ virtual UsageStatistics& usage_report() = 0; + /** + * @brief Access to HelpPromptManager interface + * @return object for Handling VR help + */ + virtual HelpPromptManager& help_prompt_manager() = 0; /** * @brief SetInitialState sets initial HMI state for application on diff --git a/src/components/application_manager/include/application_manager/application_impl.h b/src/components/application_manager/include/application_manager/application_impl.h index 496f591a50..377a97b2b9 100644 --- a/src/components/application_manager/include/application_manager/application_impl.h +++ b/src/components/application_manager/include/application_manager/application_impl.h @@ -44,6 +44,7 @@ #include "utils/date_time.h" #include "application_manager/application_data_impl.h" #include "application_manager/usage_statistics.h" +#include "application_manager/help_prompt_manager_impl.h" #include "application_manager/hmi_state.h" #include "protocol_handler/protocol_handler.h" @@ -246,6 +247,11 @@ class ApplicationImpl : public virtual Application, void SetHashChangedDuringSuspend(const bool state) OVERRIDE; UsageStatistics& usage_report(); + /** + * @brief Access to HelpPromptManager interface + * @return object for Handling VR help + */ + HelpPromptManager& help_prompt_manager() OVERRIDE; bool AreCommandLimitsExceeded(mobile_apis::FunctionID::eType cmd_id, TLimitSource source); @@ -466,6 +472,7 @@ class ApplicationImpl : public virtual Application, AppFilesMap app_files_; std::set<mobile_apis::ButtonName::eType> subscribed_buttons_; UsageStatistics usage_report_; + HelpPromptManagerImpl help_prompt_manager_impl_; protocol_handler::MajorProtocolVersion protocol_version_; bool is_voice_communication_application_; sync_primitives::atomic_bool is_resuming_; diff --git a/src/components/application_manager/include/application_manager/help_prompt_manager.h b/src/components/application_manager/include/application_manager/help_prompt_manager.h new file mode 100644 index 0000000000..e7978949e9 --- /dev/null +++ b/src/components/application_manager/include/application_manager/help_prompt_manager.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_HELP_PROMPT_MANAGER_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_HELP_PROMPT_MANAGER_H_ + +#include "smart_objects/smart_object.h" + +namespace application_manager { +/** + * @brief The HelpPromptManager is a mechanism for handling "help" requests + * by the user when the application does not provide any or such information. + */ +class HelpPromptManager { + public: + /** + * @brief Class destructor + */ + virtual ~HelpPromptManager() {} + /** + * @brief Adds command to constructed values, and sends SetGlobalProperties if + * required + */ + virtual void OnVrCommandAdded(const uint32_t cmd_id, + const smart_objects::SmartObject& command) = 0; + /** + * @brief Removes command from constructed values, and send + * SetGlobalProperties if required + */ + virtual void OnVrCommandDeleted(const uint32_t cmd_id) = 0; + /** + * @brief Send SetGlobalProperties with constructed vrHelp and/or helpPrompt + * parameters + */ + virtual void OnTimeoutExpired() = 0; + /** + * @brief Stop constructing vrHelp and/or helpPrompt if they are present in + * message + * @param msg containing GlobalProperties + * @param is_response determines is the request or response for the for + * the SetGlobalPropertiesRequest + */ + virtual void OnSetGlobalPropertiesReceived( + const smart_objects::SmartObject& msg, const bool is_response) = 0; + /** + * @brief Starts mechanism for handling "help" requests + * @param is_restore determines the need to restore commands + * after resuming + */ + virtual void OnAppActivated(const bool is_restore) = 0; + /** + * @brief Stop mechanism for handling "help" requests + */ + virtual void OnAppUnregistered() = 0; +}; + +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_HELP_PROMPT_MANAGER_H_ diff --git a/src/components/application_manager/include/application_manager/help_prompt_manager_impl.h b/src/components/application_manager/include/application_manager/help_prompt_manager_impl.h new file mode 100644 index 0000000000..9d9f07df19 --- /dev/null +++ b/src/components/application_manager/include/application_manager/help_prompt_manager_impl.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2018, 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_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_HELP_PROMPT_MANAGER_IMPL_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_HELP_PROMPT_MANAGER_IMPL_H_ + +#include "application_manager/help_prompt_manager.h" +#include "utils/timer.h" + +namespace application_manager { + +class Application; +class ApplicationManager; + +/** + * @brief The HelpPromptManagerImpl class implemented interface + * HelpPromptManager + * is a mechanism for handling "help" requests + * by the user when the application does not provide any or such information. + */ +class HelpPromptManagerImpl : public HelpPromptManager { + public: + /** + * @brief Continer for buffering VR help commands + */ + typedef std::map<uint32_t, smart_objects::SmartObjectSPtr> VRCommandsMap; + /** + * @brief Class constructor + * @param app owner for this class + */ + HelpPromptManagerImpl(Application& app, ApplicationManager& app_manager); + /** + * @brief Class destructor + */ + ~HelpPromptManagerImpl(); + /** + * @brief The type sends info to HMI + */ + enum class SendingType { kNoneSend, kSendHelpPromt, kSendVRHelp, kSendBoth }; + + /** + * @brief Adds command to constructed values, and send SetGlobalProperties if + * required + */ + void OnVrCommandAdded(const uint32_t cmd_id, + const smart_objects::SmartObject& command) OVERRIDE; + /** + * @brief Removes command from constructed values, and send + * SetGlobalProperties if required + */ + void OnVrCommandDeleted(const uint32_t cmd_id) OVERRIDE; + /** + * @brief Send SetGlobalProperties with constructed vrHelp and/or helpPrompt + * parameters + */ + void OnTimeoutExpired() OVERRIDE; + /** + * @brief Stop constructing vrHelp and/or helpPrompt if they are present in + * message + * @param msg containing GlobalProperties + * @param is_response determines is the request or response for the for + * the SetGlobalPropertiesRequest + */ + void OnSetGlobalPropertiesReceived(const smart_objects::SmartObject& msg, + const bool is_response) OVERRIDE; + /** + * @brief Starts mechanism for handling "help" requests + * @param is_restore determines the need to restore commands + * after resuming + */ + void OnAppActivated(const bool is_restore) OVERRIDE; + /** + * @brief Stop mechanism for handling "help" requests + */ + void OnAppUnregistered() OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(HelpPromptManagerImpl); + /** + * @brief Run timer to helps buffer the requests. + * @param is_restore determines the need to restore commands + * after resuming + */ + void StartTimer(const bool is_restore); + /** + * @brief Stops the buffering timer. + */ + void StopTimer(); + /** + * @brief Callback for timer to helps buffer the requests. + */ + void OnTimerExpired(); + /** + * @brief Send TTS request to HMI + */ + void SendTTSRequest(); + /** + * @brief Send UI request to HMI + */ + void SendUIRequest(); + /** + * @brief Send TTS and UI requests to HMI + */ + void SendBothRequests(); + /** + * @brief Send TTS or UI or both Requests + */ + void SendRequests(); + /** + * @brief Construct the helpPrompt parameter + */ + void CreatePromtMsg(smart_objects::SmartObject& out_msg_params); + /** + * @brief Construct the vrHelp parameter + */ + void CreateVRMsg(smart_objects::SmartObject& out_msg_params); + /** + * @brief Getting request type to send HMI + * @param msg containing request or response for the + * SetGlobalPropertiesRequest + * @param is_response determines is the request or response for the for + * the SetGlobalPropertiesRequest + * @return SendingType + */ + SendingType GetSendingType(const smart_objects::SmartObject& msg, + const bool is_response); + + Application& app_; + ApplicationManager& app_manager_; + timer::Timer internal_timer_; + VRCommandsMap vr_commands_; + SendingType sending_type_; + std::size_t count_requests_commands_; + bool is_tts_send_; + bool is_ui_send_; +}; + +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_HELP_PROMPT_MANAGER_IMPL_H_ diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_hmi_status_notification.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_hmi_status_notification.cc index a495423bce..9422bec478 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_hmi_status_notification.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_hmi_status_notification.cc @@ -78,17 +78,8 @@ void OnHMIStatusNotification::Run() { mobile_apis::HMILevel::eType hmi_level = static_cast<mobile_apis::HMILevel::eType>( (*message_)[strings::msg_params][strings::hmi_level].asInt()); - if ((mobile_apis::HMILevel::HMI_BACKGROUND == hmi_level) || - (mobile_apis::HMILevel::HMI_NONE == hmi_level)) { - if (!(app->tts_properties_in_none())) { - app->set_tts_properties_in_none(true); - LOG4CXX_INFO(logger_, - "OnHMIStatusNotification::Send TTS GlobalProperties" - " with empty array to HMI"); - MessageHelper::SendTTSGlobalProperties(app, false, application_manager_); - } - } else if ((mobile_apis::HMILevel::HMI_FULL == hmi_level) || - (mobile_apis::HMILevel::HMI_LIMITED == hmi_level)) { + if ((mobile_apis::HMILevel::HMI_FULL == hmi_level) || + (mobile_apis::HMILevel::HMI_LIMITED == hmi_level)) { if (!(app->tts_properties_in_full())) { app->set_tts_properties_in_full(true); LOG4CXX_INFO(logger_, diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_global_properties_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_global_properties_request.cc index 90ec06025e..3123787562 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_global_properties_request.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_global_properties_request.cc @@ -162,6 +162,9 @@ void SetGlobalPropertiesRequest::Run() { params[strings::app_id] = app->app_id(); SendUIRequest(params, true); + + auto& help_prompt_manager = app->help_prompt_manager(); + help_prompt_manager.OnSetGlobalPropertiesReceived(params, false); } else { LOG4CXX_DEBUG(logger_, "VRHelp params does not present"); DCHECK_OR_RETURN_VOID(!is_vr_help_title_present && !is_vr_help_present); @@ -169,15 +172,6 @@ void SetGlobalPropertiesRequest::Run() { smart_objects::SmartObject params = smart_objects::SmartObject(smart_objects::SmartType_Map); - if (ValidateVRHelpTitle(app->vr_help_title())) { - LOG4CXX_DEBUG(logger_, "App already contains VRHelp data"); - } else { - if (!PrepareUIRequestDefaultVRHelpData(app, params)) { - LOG4CXX_ERROR(logger_, "default VRHElp data could not be generated"); - SendResponse(false, mobile_apis::Result::INVALID_DATA); - return; - } - } PrepareUIRequestMenuAndKeyboardData(app, msg_params, params); // Preparing data @@ -247,6 +241,9 @@ void SetGlobalPropertiesRequest::Run() { params[strings::app_id] = app->app_id(); SendTTSRequest(params, true); + + auto& help_prompt_manager = app->help_prompt_manager(); + help_prompt_manager.OnSetGlobalPropertiesReceived(params, false); } } @@ -276,6 +273,9 @@ void SetGlobalPropertiesRequest::on_event(const event_engine::Event& event) { using namespace helpers; const smart_objects::SmartObject& message = event.smart_object(); + ApplicationSharedPtr application = + application_manager_.application(connection_key()); + switch (event.id()) { case hmi_apis::FunctionID::UI_SetGlobalProperties: { LOG4CXX_INFO(logger_, "Received UI_SetGlobalProperties event"); @@ -284,6 +284,10 @@ void SetGlobalPropertiesRequest::on_event(const event_engine::Event& event) { ui_result_ = static_cast<hmi_apis::Common_Result::eType>( message[strings::params][hmi_response::code].asInt()); GetInfo(message, ui_response_info_); + if (application.valid()) { + auto& help_prompt_manager = application->help_prompt_manager(); + help_prompt_manager.OnSetGlobalPropertiesReceived(message, true); + } break; } case hmi_apis::FunctionID::TTS_SetGlobalProperties: { @@ -293,6 +297,10 @@ void SetGlobalPropertiesRequest::on_event(const event_engine::Event& event) { tts_result_ = static_cast<hmi_apis::Common_Result::eType>( message[strings::params][hmi_response::code].asInt()); GetInfo(message, tts_response_info_); + if (application.valid()) { + auto& help_prompt_manager = application->help_prompt_manager(); + help_prompt_manager.OnSetGlobalPropertiesReceived(message, true); + } break; } default: { @@ -309,10 +317,6 @@ void SetGlobalPropertiesRequest::on_event(const event_engine::Event& event) { std::string response_info; const bool result = PrepareResponseParameters(result_code, response_info); - // TODO{ALeshin} APPLINK-15858. connection_key removed during SendResponse - ApplicationSharedPtr application = - application_manager_.application(connection_key()); - SendResponse(result, result_code, response_info.empty() ? NULL : response_info.c_str(), diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_hmi_status_notification_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_hmi_status_notification_test.cc index 034fff73d7..afb1574cbf 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_hmi_status_notification_test.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_hmi_status_notification_test.cc @@ -118,45 +118,6 @@ TEST_F(OnHMIStatusNotificationTest, Run_InvalidEnum_SUCCESS) { VerifySendNotificationData(msg); } -TEST_F(OnHMIStatusNotificationTest, Run_BackgroundAndFalseProperties_SUCCESS) { - MessageSharedPtr msg = CreateMsgParams(mobile_apis::HMILevel::HMI_BACKGROUND); - SetSendNotificationExpectations(msg); - - SharedPtr<OnHMIStatusNotification> command = - CreateCommand<OnHMIStatusNotification>(msg); - - MockAppPtr mock_app = CreateMockApp(); - EXPECT_CALL(app_mngr_, application(kConnectionKey)) - .WillOnce(Return(mock_app)); - - EXPECT_CALL(*mock_app, tts_properties_in_none()).WillOnce(Return(false)); - EXPECT_CALL(*mock_app, set_tts_properties_in_none(true)); - EXPECT_CALL(mock_message_helper_, SendTTSGlobalProperties(_, false, _)); - - command->Run(); - - VerifySendNotificationData(msg); -} - -TEST_F(OnHMIStatusNotificationTest, Run_BackgroundAndTrueProperties_SUCCESS) { - MessageSharedPtr msg = CreateMsgParams(mobile_apis::HMILevel::HMI_BACKGROUND); - - SharedPtr<OnHMIStatusNotification> command = - CreateCommand<OnHMIStatusNotification>(msg); - - MockAppPtr mock_app = CreateMockApp(); - EXPECT_CALL(app_mngr_, application(kConnectionKey)) - .WillOnce(Return(mock_app)); - - EXPECT_CALL(*mock_app, tts_properties_in_none()).WillOnce(Return(true)); - - SetSendNotificationExpectations(msg); - - command->Run(); - - VerifySendNotificationData(msg); -} - TEST_F(OnHMIStatusNotificationTest, Run_FullAndFalseProperties_SUCCESS) { MessageSharedPtr msg = CreateMsgParams(mobile_apis::HMILevel::HMI_FULL); diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/set_global_properties_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/set_global_properties_test.cc index 5d31f48970..4a590e0d91 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/set_global_properties_test.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/set_global_properties_test.cc @@ -39,6 +39,7 @@ #include "gtest/gtest.h" #include "application_manager/commands/command_request_test.h" #include "application_manager/mock_application.h" +#include "application_manager/mock_help_prompt_manager.h" #include "application_manager/mock_application_manager.h" #include "application_manager/mock_message_helper.h" #include "application_manager/event_engine/event.h" @@ -76,7 +77,11 @@ class SetGlobalPropertiesRequestTest public: SetGlobalPropertiesRequestTest() : lock_ptr_(std::make_shared<sync_primitives::Lock>()) - , mock_app_(CreateMockApp()) {} + , mock_app_(CreateMockApp()) { + mock_help_prompt_manager_ = + std::shared_ptr<application_manager_test::MockHelpPromptManager>( + new application_manager_test::MockHelpPromptManager()); + } MessageSharedPtr CreateFullParamsUISO() { MessageSharedPtr msg = CreateMessage(smart_objects::SmartType_Map); @@ -140,6 +145,9 @@ class SetGlobalPropertiesRequestTest EXPECT_CALL(*mock_app_, set_keyboard_props(_)).Times(0); EXPECT_CALL(*mock_app_, app_id()).WillOnce(Return(kAppId)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillRepeatedly(ReturnRef(*mock_help_prompt_manager_.get())); + command->Run(); } @@ -162,14 +170,15 @@ class SetGlobalPropertiesRequestTest .WillOnce(Return(mobile_apis::Result::SUCCESS)); EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); - SmartObject vr_help_title("title"); - EXPECT_CALL(*mock_app_, vr_help_title()).WillOnce(Return(&vr_help_title)); EXPECT_CALL(*mock_app_, set_help_prompt(help_prompt)); EXPECT_CALL(*mock_app_, help_prompt()).WillOnce(Return(&help_prompt)); EXPECT_CALL(*mock_app_, set_timeout_prompt(timeout_prompt)); EXPECT_CALL(*mock_app_, timeout_prompt()).WillOnce(Return(&timeout_prompt)); EXPECT_CALL(*mock_app_, app_id()).WillOnce(Return(kAppId)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillRepeatedly(ReturnRef(*mock_help_prompt_manager_.get())); + command->Run(); } @@ -252,6 +261,8 @@ class SetGlobalPropertiesRequestTest } std::shared_ptr<sync_primitives::Lock> lock_ptr_; MockAppPtr mock_app_; + std::shared_ptr<application_manager_test::MockHelpPromptManager> + mock_help_prompt_manager_; }; TEST_F(SetGlobalPropertiesRequestTest, @@ -293,6 +304,10 @@ TEST_F(SetGlobalPropertiesRequestTest, ON_CALL(mock_message_helper_, VerifyImage(_, _, _)) .WillByDefault(Return(mobile_apis::Result::SUCCESS)); + + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillRepeatedly(ReturnRef(*mock_help_prompt_manager_.get())); + EXPECT_CALL( mock_message_helper_, VerifyTtsFiles( @@ -339,6 +354,10 @@ TEST_F(SetGlobalPropertiesRequestTest, OnEvent_SUCCESS_Expect_MessageNotSend) { MockAppPtr mock_app(CreateMockApp()); ON_CALL(app_mngr_, application(_)).WillByDefault(Return(mock_app)); + + EXPECT_CALL(*mock_app, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); + EXPECT_CALL( mock_rpc_service_, ManageMobileCommand(_, am::commands::Command::CommandSource::SOURCE_SDL)) @@ -367,6 +386,9 @@ TEST_F(SetGlobalPropertiesRequestTest, EXPECT_CALL(mock_hmi_interfaces_, GetInterfaceState(_)) .WillRepeatedly(Return(am::HmiInterfaces::STATE_NOT_AVAILABLE)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillRepeatedly(ReturnRef(*mock_help_prompt_manager_.get())); + MessageSharedPtr response_to_mobile; EXPECT_CALL( mock_rpc_service_, @@ -441,6 +463,9 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_VRWithMenuAndKeyboard_SUCCESS) { GetInterfaceState(am::HmiInterfaces::HMI_INTERFACE_UI)) .WillByDefault(Return(am::HmiInterfaces::STATE_NOT_AVAILABLE)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); + SharedPtr<SetGlobalPropertiesRequest> command( CreateCommand<SetGlobalPropertiesRequest>(msg)); @@ -586,8 +611,6 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_NoVR_SUCCESS) { .WillOnce(Return(mock_app_)); EXPECT_CALL(mock_message_helper_, VerifyImageVrHelpItems(_, _, _)).Times(0); EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); - SmartObject vr_help_title("Menu_Title"); - EXPECT_CALL(*mock_app_, vr_help_title()).WillOnce(Return(&vr_help_title)); EXPECT_CALL(*mock_app_, set_menu_title(menu_title)); EXPECT_CALL(*mock_app_, set_menu_icon(_)).Times(0); EXPECT_CALL(*mock_app_, set_keyboard_props(keyboard_properties)); @@ -607,37 +630,6 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_NoVR_SUCCESS) { command->Run(); } -TEST_F(SetGlobalPropertiesRequestTest, Run_VRCouldNotGenerate_INVALID_DATA) { - MessageSharedPtr msg = CreateMsgParams(); - SmartObject keyboard_properties(smart_objects::SmartType_Map); - (*msg)[am::strings::msg_params][am::hmi_request::keyboard_properties] = - keyboard_properties; - SmartObject menu_title("Menu_Title"); - (*msg)[am::strings::msg_params][am::hmi_request::menu_title] = menu_title; - - EXPECT_CALL(app_mngr_, application(kConnectionKey)) - .WillOnce(Return(mock_app_)); - EXPECT_CALL(mock_message_helper_, VerifyImageVrHelpItems(_, _, _)).Times(0); - EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); - SmartObject* vr_help_title = NULL; - CommandsMap commands_map; - SmartObject empty_msg(smart_objects::SmartType_Map); - commands_map.insert(std::pair<uint32_t, SmartObject*>(1u, &empty_msg)); - DataAccessor<CommandsMap> accessor(commands_map, lock_ptr_); - EXPECT_CALL(*mock_app_, commands_map()).WillOnce(Return(accessor)); - EXPECT_CALL(*mock_app_, vr_help_title()).WillOnce(Return(vr_help_title)); - EXPECT_CALL(*mock_app_, set_menu_title(_)).Times(0); - - SharedPtr<SetGlobalPropertiesRequest> command( - CreateCommand<SetGlobalPropertiesRequest>(msg)); - EXPECT_CALL( - mock_rpc_service_, - ManageMobileCommand(MobileResultCodeIs(mobile_apis::Result::INVALID_DATA), - am::commands::Command::SOURCE_SDL)); - - command->Run(); -} - TEST_F(SetGlobalPropertiesRequestTest, Run_NoVRNoDataNoDefault_Canceled) { MessageSharedPtr msg = CreateMsgParams(); SmartObject keyboard_properties(smart_objects::SmartType_Map); @@ -647,19 +639,7 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_NoVRNoDataNoDefault_Canceled) { EXPECT_CALL(app_mngr_, application(kConnectionKey)) .WillOnce(Return(mock_app_)); EXPECT_CALL(mock_message_helper_, VerifyImageVrHelpItems(_, _, _)).Times(0); - EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); - SmartObject vr_help_title(smart_objects::SmartType_Null); - EXPECT_CALL(*mock_app_, vr_help_title()) - .WillOnce(Return(&vr_help_title)) - .WillOnce(Return(&vr_help_title)); - - CommandsMap commands_map; - DataAccessor<CommandsMap> accessor(commands_map, lock_ptr_); - EXPECT_CALL(*mock_app_, commands_map()).WillOnce(Return(accessor)); - const CustomString name("name"); - EXPECT_CALL(*mock_app_, name()).WillOnce(ReturnRef(name)); - EXPECT_CALL(*mock_app_, set_vr_help_title(SmartObject(name))); - EXPECT_CALL(*mock_app_, set_menu_title(_)).Times(0); + EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); EXPECT_CALL(*mock_app_, set_menu_title(_)).Times(0); EXPECT_CALL(*mock_app_, set_menu_icon(_)).Times(0); EXPECT_CALL(*mock_app_, set_keyboard_props(_)); EXPECT_CALL(*mock_app_, app_id()); @@ -688,23 +668,6 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_NoVRNoDataDefaultCreated_SUCCESS) { .WillOnce(Return(mock_app_)); EXPECT_CALL(mock_message_helper_, VerifyImageVrHelpItems(_, _, _)).Times(0); EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); - SmartObject vr_help_title(smart_objects::SmartType_Null); - EXPECT_CALL(*mock_app_, vr_help_title()) - .Times(2) - .WillRepeatedly(Return(&vr_help_title)); - - CommandsMap commands_map; - SmartObject command_text(smart_objects::SmartType_Map); - commands_map[0] = &command_text; - (*commands_map[0])[am::strings::vr_commands] = SmartObject("one"); - DataAccessor<CommandsMap> accessor(commands_map, lock_ptr_); - EXPECT_CALL(*mock_app_, commands_map()).WillOnce(Return(accessor)); - EXPECT_CALL(*mock_app_, set_vr_help(_)); - const CustomString name("name"); - EXPECT_CALL(*mock_app_, name()).WillOnce(ReturnRef(name)); - EXPECT_CALL(*mock_app_, set_vr_help_title(SmartObject(name))); - SmartObject vr_help_array(smart_objects::SmartType_Array); - EXPECT_CALL(*mock_app_, vr_help()).WillOnce(Return(&vr_help_array)); EXPECT_CALL(*mock_app_, set_menu_title(_)).Times(0); EXPECT_CALL(*mock_app_, set_menu_icon(_)).Times(0); EXPECT_CALL(*mock_app_, set_keyboard_props(keyboard_properties)); @@ -723,50 +686,6 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_NoVRNoDataDefaultCreated_SUCCESS) { command->Run(); } -TEST_F(SetGlobalPropertiesRequestTest, Run_NoVRNoDataFromSynonyms_SUCCESS) { - MessageSharedPtr msg = CreateMsgParams(); - SmartObject keyboard_properties(smart_objects::SmartType_Map); - (*msg)[am::strings::msg_params][am::hmi_request::keyboard_properties] = - keyboard_properties; - - EXPECT_CALL(app_mngr_, application(kConnectionKey)) - .WillOnce(Return(mock_app_)); - EXPECT_CALL(mock_message_helper_, VerifyImageVrHelpItems(_, _, _)).Times(0); - EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); - SmartObject vr_help_title(smart_objects::SmartType_Null); - EXPECT_CALL(*mock_app_, vr_help_title()) - .Times(2) - .WillRepeatedly(Return(&vr_help_title)); - - CommandsMap commands_map; - DataAccessor<CommandsMap> accessor(commands_map, lock_ptr_); - EXPECT_CALL(*mock_app_, commands_map()).WillOnce(Return(accessor)); - SmartObject vr_help_array(smart_objects::SmartType_Array); - vr_help_array[0] = SmartObject(smart_objects::SmartType_Map); - vr_help_array[0][am::strings::text] = kText; - vr_help_array[0][am::strings::position] = kPosition; - SmartObject vr_synonyms(smart_objects::SmartType_Array); - vr_synonyms[0] = vr_help_array; - const CustomString name("name"); - EXPECT_CALL(*mock_app_, name()).WillOnce(ReturnRef(name)); - EXPECT_CALL(*mock_app_, set_vr_help_title(SmartObject(name))); - EXPECT_CALL(*mock_app_, set_menu_title(_)).Times(0); - EXPECT_CALL(*mock_app_, set_menu_icon(_)).Times(0); - EXPECT_CALL(*mock_app_, set_keyboard_props(keyboard_properties)); - EXPECT_CALL(*mock_app_, app_id()).WillOnce(Return(kAppId)); - EXPECT_CALL( - mock_hmi_interfaces_, - GetInterfaceFromFunction(hmi_apis::FunctionID::UI_SetGlobalProperties)) - .WillOnce(Return(am::HmiInterfaces::HMI_INTERFACE_UI)); - ON_CALL(mock_hmi_interfaces_, - GetInterfaceState(am::HmiInterfaces::HMI_INTERFACE_UI)) - .WillByDefault(Return(am::HmiInterfaces::STATE_NOT_AVAILABLE)); - SharedPtr<SetGlobalPropertiesRequest> command( - CreateCommand<SetGlobalPropertiesRequest>(msg)); - - command->Run(); -} - TEST_F(SetGlobalPropertiesRequestTest, Run_TTSHelpAndTimeout_SUCCESS) { MessageSharedPtr msg = CreateMsgParams(); SmartObject help_prompt(smart_objects::SmartType_Array); @@ -784,8 +703,6 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_TTSHelpAndTimeout_SUCCESS) { EXPECT_CALL(mock_message_helper_, VerifyTtsFiles(timeout_prompt, _, _)) .WillOnce(Return(mobile_apis::Result::SUCCESS)); EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); - SmartObject vr_help_title("title"); - EXPECT_CALL(*mock_app_, vr_help_title()).WillOnce(Return(&vr_help_title)); EXPECT_CALL(*mock_app_, set_help_prompt(help_prompt)); EXPECT_CALL(*mock_app_, help_prompt()).WillOnce(Return(&help_prompt)); EXPECT_CALL(*mock_app_, set_timeout_prompt(timeout_prompt)); @@ -800,6 +717,9 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_TTSHelpAndTimeout_SUCCESS) { GetInterfaceState(am::HmiInterfaces::HMI_INTERFACE_TTS)) .WillByDefault(Return(am::HmiInterfaces::STATE_NOT_AVAILABLE)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); + SharedPtr<SetGlobalPropertiesRequest> command( CreateCommand<SetGlobalPropertiesRequest>(msg)); @@ -818,8 +738,6 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_TTSOnlyHelp_SUCCESS) { EXPECT_CALL(mock_message_helper_, VerifyTtsFiles(help_prompt, _, _)) .WillOnce(Return(mobile_apis::Result::SUCCESS)); EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); - SmartObject vr_help_title("title"); - EXPECT_CALL(*mock_app_, vr_help_title()).WillOnce(Return(&vr_help_title)); EXPECT_CALL(*mock_app_, set_help_prompt(help_prompt)); EXPECT_CALL(*mock_app_, help_prompt()).WillOnce(Return(&help_prompt)); EXPECT_CALL(*mock_app_, set_timeout_prompt(_)).Times(0); @@ -832,6 +750,8 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_TTSOnlyHelp_SUCCESS) { ON_CALL(mock_hmi_interfaces_, GetInterfaceState(am::HmiInterfaces::HMI_INTERFACE_TTS)) .WillByDefault(Return(am::HmiInterfaces::STATE_NOT_AVAILABLE)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); SharedPtr<SetGlobalPropertiesRequest> command( CreateCommand<SetGlobalPropertiesRequest>(msg)); @@ -850,8 +770,6 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_TTSOnlyTimeout_SUCCESS) { EXPECT_CALL(mock_message_helper_, VerifyTtsFiles(timeout_prompt, _, _)) .WillOnce(Return(mobile_apis::Result::SUCCESS)); EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); - SmartObject vr_help_title("title"); - EXPECT_CALL(*mock_app_, vr_help_title()).WillOnce(Return(&vr_help_title)); EXPECT_CALL(*mock_app_, set_help_prompt(_)).Times(0); EXPECT_CALL(*mock_app_, help_prompt()).Times(0); EXPECT_CALL(*mock_app_, set_timeout_prompt(timeout_prompt)); @@ -864,6 +782,8 @@ TEST_F(SetGlobalPropertiesRequestTest, Run_TTSOnlyTimeout_SUCCESS) { ON_CALL(mock_hmi_interfaces_, GetInterfaceState(am::HmiInterfaces::HMI_INTERFACE_TTS)) .WillByDefault(Return(am::HmiInterfaces::STATE_NOT_AVAILABLE)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); SharedPtr<SetGlobalPropertiesRequest> command( CreateCommand<SetGlobalPropertiesRequest>(msg)); @@ -1055,6 +975,9 @@ TEST_F(SetGlobalPropertiesRequestTest, OnEvent_PendingRequest_UNSUCCESS) { Event event(hmi_apis::FunctionID::UI_SetGlobalProperties); event.set_smart_object(*msg); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); + command->on_event(event); } @@ -1159,7 +1082,7 @@ TEST_F(SetGlobalPropertiesRequestTest, OnEvent_InvalidEventID_Canceled) { SharedPtr<SetGlobalPropertiesRequest> command( CreateCommand<SetGlobalPropertiesRequest>(msg)); - EXPECT_CALL(app_mngr_, application(kConnectionKey)).Times(0); + EXPECT_CALL(app_mngr_, application(_)).WillOnce(Return(mock_app_)); EXPECT_CALL(*mock_app_, UpdateHash()).Times(0); Event event(hmi_apis::FunctionID::TTS_Stopped); @@ -1221,6 +1144,9 @@ TEST_F(SetGlobalPropertiesRequestTest, EXPECT_CALL(mock_hmi_interfaces_, GetInterfaceState(_)) .WillRepeatedly(Return(am::HmiInterfaces::STATE_NOT_AVAILABLE)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); + MessageSharedPtr ui_command_result; EXPECT_CALL( mock_rpc_service_, diff --git a/src/components/application_manager/src/application_data_impl.cc b/src/components/application_manager/src/application_data_impl.cc index f271b7ff6a..a809112f54 100644 --- a/src/components/application_manager/src/application_data_impl.cc +++ b/src/components/application_manager/src/application_data_impl.cc @@ -479,6 +479,8 @@ void DynamicApplicationDataImpl::AddCommand( if (commands_.end() == it) { commands_[cmd_id] = new smart_objects::SmartObject(command); } + auto& help_prompt_mngr = help_prompt_manager(); + help_prompt_mngr.OnVrCommandAdded(cmd_id, command); } void DynamicApplicationDataImpl::RemoveCommand(uint32_t cmd_id) { @@ -488,6 +490,8 @@ void DynamicApplicationDataImpl::RemoveCommand(uint32_t cmd_id) { delete it->second; commands_.erase(it); } + auto& help_prompt_mngr = help_prompt_manager(); + help_prompt_mngr.OnVrCommandDeleted(cmd_id); } smart_objects::SmartObject* DynamicApplicationDataImpl::FindCommand( diff --git a/src/components/application_manager/src/application_impl.cc b/src/components/application_manager/src/application_impl.cc index 3242dace4d..6efd737f0c 100644 --- a/src/components/application_manager/src/application_impl.cc +++ b/src/components/application_manager/src/application_impl.cc @@ -125,6 +125,7 @@ ApplicationImpl::ApplicationImpl( , mac_address_(mac_address) , device_id_(device_id) , usage_report_(mobile_app_id, statistics_manager) + , help_prompt_manager_impl_(*this, application_manager) , protocol_version_( protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_3) , is_voice_communication_application_(false) @@ -763,6 +764,10 @@ UsageStatistics& ApplicationImpl::usage_report() { return usage_report_; } +HelpPromptManager& ApplicationImpl::help_prompt_manager() { + return help_prompt_manager_impl_; +} + bool ApplicationImpl::AreCommandLimitsExceeded( mobile_apis::FunctionID::eType cmd_id, TLimitSource source) { TimevalStruct current = date_time::DateTime::getCurrentTime(); diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 35deddfc8d..3e44a54bf2 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -662,6 +662,10 @@ bool ApplicationManagerImpl::ActivateApplication(ApplicationSharedPtr app) { LOG4CXX_AUTO_TRACE(logger_); DCHECK_OR_RETURN(app, false); + auto& help_prompt_manager = app->help_prompt_manager(); + const bool is_restore = false; + help_prompt_manager.OnAppActivated(is_restore); + LOG4CXX_DEBUG(logger_, "Activating application with id:" << app->app_id()); // remove from resumption if app was activated by user @@ -2466,6 +2470,9 @@ void ApplicationManagerImpl::UnregisterApplication( } } + auto& help_prompt_manager = app_to_remove->help_prompt_manager(); + help_prompt_manager.OnAppUnregistered(); + commands_holder_->Clear(app_to_remove); if (EndAudioPassThru(app_id)) { diff --git a/src/components/application_manager/src/help_prompt_manager_impl.cc b/src/components/application_manager/src/help_prompt_manager_impl.cc new file mode 100644 index 0000000000..dbd3b49a5d --- /dev/null +++ b/src/components/application_manager/src/help_prompt_manager_impl.cc @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2018, 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 "application_manager/help_prompt_manager_impl.h" +#include "application_manager/application.h" +#include "application_manager/message_helper.h" +#include "application_manager/smart_object_keys.h" +#include "smart_objects/smart_object.h" +#include "application_manager/application_manager.h" +#include "application_manager/commands/command_impl.h" +#include "utils/logger.h" +#include "utils/timer_task_impl.h" +#include "utils/make_shared.h" + +CREATE_LOGGERPTR_GLOBAL(logger_, "HelpPromptManagerImpl") + +namespace { +const std::size_t kLimitCommand = 30; +const uint32_t kBufferingTimeout = 10000; +} + +namespace application_manager { + +HelpPromptManagerImpl::HelpPromptManagerImpl(Application& app, + ApplicationManager& app_manager) + : app_(app) + , app_manager_(app_manager) + , internal_timer_("HelpPromtManagerTimer", + new ::timer::TimerTaskImpl<HelpPromptManagerImpl>( + this, &HelpPromptManagerImpl::OnTimerExpired)) + , sending_type_(SendingType::kNoneSend) + , count_requests_commands_(0) + , is_tts_send_(false) + , is_ui_send_(false) {} + +HelpPromptManagerImpl::~HelpPromptManagerImpl() { + LOG4CXX_AUTO_TRACE(logger_); + StopTimer(); +} + +void HelpPromptManagerImpl::OnVrCommandAdded( + const uint32_t cmd_id, const smart_objects::SmartObject& command) { + LOG4CXX_AUTO_TRACE(logger_); + if (SendingType::kNoneSend == sending_type_) { + LOG4CXX_DEBUG(logger_, + "SendingType::kNoneSend" + << " commands with id:" << cmd_id + << " will not be added"); + return; + } + auto it = vr_commands_.find(cmd_id); + if (vr_commands_.end() != it) { + LOG4CXX_DEBUG(logger_, "Commands with id:" << cmd_id << " alreday exists"); + return; + } + + if (false == command.keyExists(strings::vr_commands)) { + LOG4CXX_DEBUG(logger_, "vr_commands does`t present"); + return; + } + const smart_objects::SmartObject& commands = command[strings::vr_commands]; + /** + * The remaining number of commands for adding + * without taking into account the commands + * added during the timer operation + */ + std::size_t limit = kLimitCommand - count_requests_commands_; + LOG4CXX_DEBUG(logger_, "Remaining number of commands" << limit); + if (0 == limit || limit > kLimitCommand) { + LOG4CXX_DEBUG(logger_, "Commands limit is exceeded"); + return; + } + + if (internal_timer_.is_running() || commands.length() < limit) { + limit = commands.length(); + } + + LOG4CXX_DEBUG(logger_, + "Internal timer is running: " << internal_timer_.is_running() + << " Will be added " << limit + << " commands"); + + vr_commands_[cmd_id] = utils::MakeShared<smart_objects::SmartObject>( + smart_objects::SmartType_Array); + smart_objects::SmartArray& ar_vr_cmd = *(vr_commands_[cmd_id]->asArray()); + smart_objects::SmartArray& ar_cmd = *(commands.asArray()); + ar_vr_cmd.reserve(limit); + ar_vr_cmd.insert(ar_vr_cmd.end(), ar_cmd.begin(), ar_cmd.begin() + limit); + LOG4CXX_DEBUG(logger_, + "VR commands with id: " << cmd_id << " added for appID: " + << app_.app_id()); + if (false == internal_timer_.is_running()) { + count_requests_commands_ += limit; + SendRequests(); + } +} + +void HelpPromptManagerImpl::OnVrCommandDeleted(const uint32_t cmd_id) { + LOG4CXX_AUTO_TRACE(logger_); + if (SendingType::kNoneSend == sending_type_) { + LOG4CXX_DEBUG(logger_, + "SendingType::kNoneSend" + << " commands with id:" << cmd_id + << " will not be deleted"); + return; + } + auto it = vr_commands_.find(cmd_id); + if (vr_commands_.end() != it) { + count_requests_commands_ -= + kLimitCommand == count_requests_commands_ ? 0 : it->second->length(); + + vr_commands_.erase(it); + LOG4CXX_DEBUG(logger_, + "VR command with id: " << cmd_id << " deleted for appID: " + << app_.app_id()); + if (false == internal_timer_.is_running()) { + SendRequests(); + } + } +} + +void HelpPromptManagerImpl::OnTimeoutExpired() { + LOG4CXX_AUTO_TRACE(logger_); + SendRequests(); +} + +void HelpPromptManagerImpl::OnSetGlobalPropertiesReceived( + const smart_objects::SmartObject& msg, const bool is_response) { + LOG4CXX_AUTO_TRACE(logger_); + if (SendingType::kNoneSend == sending_type_) { + LOG4CXX_DEBUG(logger_, + "SendingType::kNoneSend" + " do not track SetGlobalProperties"); + return; + } + sending_type_ = GetSendingType(msg, is_response); + if (SendingType::kNoneSend == sending_type_) { + StopTimer(); + } + LOG4CXX_DEBUG(logger_, "Set sending type to:" << unsigned(sending_type_)); +} + +void HelpPromptManagerImpl::OnAppActivated(const bool is_restore) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Activated for appID:" << app_.app_id()); + if (is_restore) { + LOG4CXX_DEBUG(logger_, "restoring"); + is_tts_send_ = (app_.help_prompt() && app_.help_prompt()->length()); + is_ui_send_ = (app_.vr_help() && app_.vr_help()->length()); + LOG4CXX_DEBUG(logger_, "is_tts_send_:" << is_tts_send_); + LOG4CXX_DEBUG(logger_, "is_ui_send_:" << is_ui_send_); + if (is_tts_send_ && is_ui_send_) { + LOG4CXX_DEBUG(logger_, + "SetGlobalProperties RPC" + " with the vrHelp and helpPrompt" + " has been sent"); + return; + } + } + StartTimer(is_restore); +} + +void HelpPromptManagerImpl::OnAppUnregistered() { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Unregisted for appID:" << app_.app_id()); + StopTimer(); +} + +void HelpPromptManagerImpl::StartTimer(const bool is_restore) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Timer for appID:" << app_.app_id()); + StopTimer(); + sending_type_ = SendingType::kSendBoth; + internal_timer_.Start(kBufferingTimeout, timer::kSingleShot); + if (is_restore) { + sending_type_ = is_tts_send_ ? SendingType::kSendVRHelp : sending_type_; + sending_type_ = is_ui_send_ ? SendingType::kSendHelpPromt : sending_type_; + is_tts_send_ = false; + is_ui_send_ = false; + const DataAccessor<CommandsMap> accessor = app_.commands_map(); + const CommandsMap& commands = accessor.GetData(); + for (auto& command : commands) { + OnVrCommandAdded(command.first, *command.second); + } + } +} + +void HelpPromptManagerImpl::StopTimer() { + LOG4CXX_AUTO_TRACE(logger_); + sending_type_ = SendingType::kNoneSend; + if (internal_timer_.is_running()) { + internal_timer_.Stop(); + } + vr_commands_.clear(); +} + +void HelpPromptManagerImpl::OnTimerExpired() { + LOG4CXX_AUTO_TRACE(logger_); + OnTimeoutExpired(); +} + +void HelpPromptManagerImpl::SendTTSRequest() { + LOG4CXX_AUTO_TRACE(logger_); + if (vr_commands_.empty()) { + LOG4CXX_DEBUG(logger_, "vr_commands_ is empty"); + return; + } + LOG4CXX_DEBUG(logger_, "TTS request for appID:" << app_.app_id()); + smart_objects::SmartObjectSPtr tts_global_properties = + utils::MakeShared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + if (tts_global_properties) { + smart_objects::SmartObject& ref = *tts_global_properties; + + ref[strings::params][strings::message_type] = + hmi_apis::messageType::request; + ref[strings::params][strings::protocol_version] = + commands::CommandImpl::protocol_version_; + ref[strings::params][strings::protocol_type] = + commands::CommandImpl::hmi_protocol_type_; + ref[strings::params][strings::correlation_id] = + app_manager_.GetNextHMICorrelationID(); + + smart_objects::SmartObject& so_to_send = *tts_global_properties; + so_to_send[strings::params][strings::function_id] = + hmi_apis::FunctionID::TTS_SetGlobalProperties; + + smart_objects::SmartObject msg_params = + smart_objects::SmartObject(smart_objects::SmartType_Map); + + CreatePromtMsg(msg_params); + + msg_params[strings::app_id] = app_.app_id(); + so_to_send[strings::msg_params] = msg_params; + app_manager_.ManageHMICommand(tts_global_properties); + } +} + +void HelpPromptManagerImpl::SendUIRequest() { + LOG4CXX_AUTO_TRACE(logger_); + if (vr_commands_.empty()) { + LOG4CXX_DEBUG(logger_, "vr_commands_ is empty"); + return; + } + LOG4CXX_DEBUG(logger_, "UI request for appID:" << app_.app_id()); + smart_objects::SmartObjectSPtr ui_global_properties = + utils::MakeShared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + if (ui_global_properties) { + smart_objects::SmartObject& ref = *ui_global_properties; + + ref[strings::params][strings::message_type] = + hmi_apis::messageType::request; + ref[strings::params][strings::protocol_version] = + commands::CommandImpl::protocol_version_; + ref[strings::params][strings::protocol_type] = + commands::CommandImpl::hmi_protocol_type_; + ref[strings::params][strings::correlation_id] = + app_manager_.GetNextHMICorrelationID(); + + smart_objects::SmartObject& so_to_send = *ui_global_properties; + so_to_send[strings::params][strings::function_id] = + hmi_apis::FunctionID::UI_SetGlobalProperties; + + smart_objects::SmartObject msg_params = + smart_objects::SmartObject(smart_objects::SmartType_Map); + + CreateVRMsg(msg_params); + + msg_params[strings::app_id] = app_.app_id(); + so_to_send[strings::msg_params] = msg_params; + app_manager_.ManageHMICommand(ui_global_properties); + } +} + +void HelpPromptManagerImpl::SendBothRequests() { + LOG4CXX_AUTO_TRACE(logger_); + SendTTSRequest(); + SendUIRequest(); +} + +void HelpPromptManagerImpl::SendRequests() { + LOG4CXX_AUTO_TRACE(logger_); + if (vr_commands_.empty()) { + LOG4CXX_DEBUG(logger_, "vr_commands_ is empty"); + return; + } + + switch (sending_type_) { + case SendingType::kSendHelpPromt: + SendTTSRequest(); + return; + case SendingType::kSendVRHelp: + SendUIRequest(); + return; + case SendingType::kSendBoth: + SendBothRequests(); + return; + case SendingType::kNoneSend: + break; + } + LOG4CXX_DEBUG(logger_, + "SendingType:" << (unsigned)sending_type_ + << " request not sending"); +} + +void HelpPromptManagerImpl::CreatePromtMsg( + smart_objects::SmartObject& out_msg_params) { + LOG4CXX_AUTO_TRACE(logger_); + if (vr_commands_.empty()) { + LOG4CXX_DEBUG(logger_, "vr_commands_ is empty"); + return; + } + out_msg_params[strings::help_prompt] = + smart_objects::SmartObject(smart_objects::SmartType_Array); + uint32_t index = 0; + for (const auto& it : vr_commands_) { + for (std::size_t i = 0; i < it.second->length(); ++i) { + smart_objects::SmartObject item(smart_objects::SmartType_Map); + + item[strings::text] = it.second->getElement(i).asString(); + item[strings::type] = mobile_apis::SpeechCapabilities::SC_TEXT; + + out_msg_params[strings::help_prompt][index++] = item; + } + } + app_.set_help_prompt(out_msg_params[strings::help_prompt]); +} + +void HelpPromptManagerImpl::CreateVRMsg( + smart_objects::SmartObject& out_msg_params) { + LOG4CXX_AUTO_TRACE(logger_); + if (vr_commands_.empty()) { + LOG4CXX_DEBUG(logger_, "vr_commands_ is empty"); + return; + } + if (false == out_msg_params.keyExists(strings::vr_help_title)) { + if (app_.vr_help_title()) { + out_msg_params[strings::vr_help_title] = (*app_.vr_help_title()); + } else { + out_msg_params[strings::vr_help_title] = app_.name(); + } + } + out_msg_params[strings::vr_help] = + smart_objects::SmartObject(smart_objects::SmartType_Array); + uint32_t index = 0; + for (const auto& it : vr_commands_) { + for (std::size_t i = 0; i < it.second->length(); ++i) { + smart_objects::SmartObject item(smart_objects::SmartType_Map); + + item[strings::text] = it.second->getElement(i).asString(); + item[strings::position] = index + 1; + + out_msg_params[strings::vr_help][index++] = item; + } + } + app_.set_vr_help(out_msg_params[strings::vr_help]); +} + +HelpPromptManagerImpl::SendingType HelpPromptManagerImpl::GetSendingType( + const smart_objects::SmartObject& msg, const bool is_response) { + LOG4CXX_AUTO_TRACE(logger_); + if (false == is_response) { + if (msg.keyExists(strings::help_prompt)) { + is_tts_send_ = true; + } + if (msg.keyExists(strings::vr_help)) { + is_ui_send_ = true; + } + LOG4CXX_DEBUG(logger_, "is_tts_send_:" << is_tts_send_); + LOG4CXX_DEBUG(logger_, "is_ui_send_:" << is_ui_send_); + return sending_type_; + } + hmi_apis::Common_Result::eType result = + static_cast<hmi_apis::Common_Result::eType>( + msg[strings::params][hmi_response::code].asInt()); + LOG4CXX_DEBUG(logger_, "HMI response result:" << result); + if (hmi_apis::Common_Result::eType::SUCCESS == result) { + hmi_apis::FunctionID::eType function_id = + static_cast<hmi_apis::FunctionID::eType>( + msg[strings::params][strings::function_id].asUInt()); + LOG4CXX_DEBUG(logger_, "Function id:" << function_id); + switch (function_id) { + case hmi_apis::FunctionID::TTS_SetGlobalProperties: + if (is_tts_send_) { + is_tts_send_ = false; + return (SendingType::kSendHelpPromt == sending_type_) + ? SendingType::kNoneSend + : SendingType::kSendVRHelp; + } + break; + case hmi_apis::FunctionID::UI_SetGlobalProperties: + if (is_ui_send_) { + is_ui_send_ = false; + return (SendingType::kSendVRHelp == sending_type_) + ? SendingType::kNoneSend + : SendingType::kSendHelpPromt; + } + break; + default: + return sending_type_; + } + } + return sending_type_; +} + +} // 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 b7fc9f0b70..d75237e0be 100644 --- a/src/components/application_manager/src/resumption/resume_ctrl_impl.cc +++ b/src/components/application_manager/src/resumption/resume_ctrl_impl.cc @@ -162,7 +162,17 @@ bool ResumeCtrlImpl::RestoreAppHMIState(ApplicationSharedPtr application) { static_cast<mobile_apis::HMILevel::eType>( saved_app[strings::hmi_level].asInt()); LOG4CXX_DEBUG(logger_, "Saved HMI Level is : " << saved_hmi_level); - return SetAppHMIState(application, saved_hmi_level, true); + result = SetAppHMIState(application, saved_hmi_level, true); + if (result) { + const HMILevel::eType def_hmi_level = + application_manager_.GetDefaultHmiLevel(application); + if (def_hmi_level != saved_hmi_level) { + auto& help_prompt_manager = application->help_prompt_manager(); + const bool is_restore = true; + help_prompt_manager.OnAppActivated(is_restore); + } + } + return result; } else { result = false; LOG4CXX_ERROR(logger_, "saved app data corrupted"); diff --git a/src/components/application_manager/test/CMakeLists.txt b/src/components/application_manager/test/CMakeLists.txt index 579ffe8c1b..33fc4a4ebd 100644..100755 --- a/src/components/application_manager/test/CMakeLists.txt +++ b/src/components/application_manager/test/CMakeLists.txt @@ -72,6 +72,10 @@ set(testSourcesMockHmi ${AM_TEST_DIR}/application_manager_impl_mock_hmi_test.cc ) +set(testSourcesHelpPromptManager + ${AM_TEST_DIR}/help_prompt_manager_test.cc + ${AM_TEST_DIR}/mock_message_helper.cc +) set (RequestController_SOURCES ${AM_TEST_DIR}/request_controller/request_controller_test.cc ${AM_TEST_DIR}/mock_message_helper.cc @@ -131,6 +135,8 @@ create_test("application_manager_test" "${testSources}" "${LIBRARIES}") create_test("application_manager_mock_hmi_test" "${testSourcesMockHmi}" "${LIBRARIES}") #add_dependencies("application_manager_test" libbson) +create_test("help_prompt_manager_test" "${testSourcesHelpPromptManager}" "${LIBRARIES}") + create_test("request_controller_test" "${RequestController_SOURCES}" "${LIBRARIES}") set(ResumptionData_SOURCES diff --git a/src/components/application_manager/test/application_manager_impl_test.cc b/src/components/application_manager/test/application_manager_impl_test.cc index c13a47aae5..276c6bb0d5 100644 --- a/src/components/application_manager/test/application_manager_impl_test.cc +++ b/src/components/application_manager/test/application_manager_impl_test.cc @@ -41,6 +41,7 @@ #include "application_manager/application_impl.h" #include "application_manager/application_manager_impl.h" #include "application_manager/mock_application.h" +#include "application_manager/mock_help_prompt_manager.h" #include "application_manager/mock_application_manager_settings.h" #include "application_manager/mock_resumption_data.h" #include "application_manager/mock_rpc_service.h" @@ -151,6 +152,8 @@ class ApplicationManagerImplTest : public ::testing::Test { app_manager_impl_.reset(new am::ApplicationManagerImpl( mock_application_manager_settings_, mock_policy_settings_)); mock_app_ptr_ = utils::SharedPtr<MockApplication>(new MockApplication()); + mock_help_prompt_manager_ = + utils::SharedPtr<MockHelpPromptManager>(new MockHelpPromptManager()); app_manager_impl_->set_protocol_handler(&mock_protocol_handler_); ASSERT_TRUE(app_manager_impl_.get()); ASSERT_TRUE(mock_app_ptr_.get()); @@ -199,6 +202,7 @@ class ApplicationManagerImplTest : public ::testing::Test { application_manager::MockMessageHelper* mock_message_helper_; utils::SharedPtr<MockApplication> mock_app_ptr_; + utils::SharedPtr<MockHelpPromptManager> mock_help_prompt_manager_; NiceMock<protocol_handler_test::MockProtocolHandler> mock_protocol_handler_; }; @@ -807,6 +811,9 @@ TEST_F(ApplicationManagerImplTest, EXPECT_TRUE(app_manager_impl_->IsAppInReconnectMode(policy_app_id_switch)); + EXPECT_CALL(*switching_app_ptr, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); + app_manager_impl_->OnDeviceSwitchingFinish(switching_device_id); EXPECT_FALSE( app_manager_impl_->application_by_policy_id(policy_app_id_switch)); @@ -951,6 +958,9 @@ TEST_F(ApplicationManagerImplTest, UnregisterAnotherAppDuringAudioPassThru) { audio_type); } + EXPECT_CALL(*mock_app_1, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); + // while running APT, app 1 is unregistered app_manager_impl_->UnregisterApplication( app_id_1, mobile_apis::Result::SUCCESS, false, true); diff --git a/src/components/application_manager/test/help_prompt_manager_test.cc b/src/components/application_manager/test/help_prompt_manager_test.cc new file mode 100644 index 0000000000..3b7e68bde7 --- /dev/null +++ b/src/components/application_manager/test/help_prompt_manager_test.cc @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2018, 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 "gtest/gtest.h" +#include "application_manager/mock_application.h" +#include "application_manager/mock_help_prompt_manager.h" +#include "application_manager/mock_message_helper.h" +#include "application_manager/mock_event_dispatcher.h" +#include "application_manager/mock_resumption_data.h" +#include "connection_handler/mock_connection_handler.h" +#include "protocol_handler/mock_session_observer.h" +#include "policy/usage_statistics/mock_statistics_manager.h" +#include "application_manager/application_impl.h" +#include "application_manager/commands/mobile/set_global_properties_request.h" +#include "application_manager/commands/commands_test.h" +#include "application_manager/commands/command_request_test.h" +#include "application_manager/hmi_state.h" +#include "utils/file_system.h" + +namespace test { +namespace components { +namespace application_manager_test { + +namespace { +const uint32_t kConnectionKey = 1u; +const uint32_t kCorrelationKey = 2u; +const uint32_t kAppId = 10u; +const uint32_t kCmdId = 1u; +const std::string kPolicyAppId = "fake_app_id"; +const uint32_t kTimeout = 10000u; +const std::string kText = "one"; +const uint32_t kPosition = 1u; +const std::string kFirstVrCommand = "first"; +const int32_t kGrammarId = 12; +const std::string kDirectoryName = "./test_storage"; +const uint8_t expected_tread_pool_size = 2u; +const uint8_t stop_streaming_timeout = 1u; +const std::vector<std::string> kTimeoutPrompt{"timeoutPrompt"}; +} // namespace + +using namespace application_manager; +using namespace policy; +using namespace test::components::commands_test; +using namespace mobile_apis; + +using testing::Mock; +using testing::NiceMock; +using testing::Return; +using testing::ReturnRef; +using testing::_; +using am::HmiStatePtr; +using am::commands::SetGlobalPropertiesRequest; +using usage_statistics_test::MockStatisticsManager; + +class ApplicationImplTest : public ApplicationImpl { + public: + ApplicationImplTest( + uint32_t application_id, + const std::string& policy_app_id, + const std::string& mac_address, + const connection_handler::DeviceHandle device_id, + const custom_str::CustomString& app_name, + utils::SharedPtr<usage_statistics::StatisticsManager> statistics_manager, + ApplicationManager& application_manager, + MockHelpPromptManager& mock_help_prompt_manager) + : ApplicationImpl(application_id, + policy_app_id, + mac_address, + device_id, + app_name, + statistics_manager, + application_manager) + , mock_help_prompt_manager_(mock_help_prompt_manager) {} + + HelpPromptManager& help_prompt_manager() OVERRIDE { + return mock_help_prompt_manager_; + } + + private: + MockHelpPromptManager& mock_help_prompt_manager_; +}; + +class HelpPromptManagerTest : public ::testing::Test { + public: + HelpPromptManagerTest() + : app_set_(test_app_, app_lock_) + , mock_message_helper_(*MockMessageHelper::message_helper_mock()) {} + void SetUp() OVERRIDE; + void TearDown() OVERRIDE; + MessageSharedPtr CreateMsgParams(); + void VRArraySetupHelper(MessageSharedPtr msg, + SmartObject& vr_help_title, + SmartObject& vr_help_array); + void CreateBasicParamsVRRequest(MessageSharedPtr msg); + void CreateApplication(MockHelpPromptManager& mock_help_prompt_manager); + HmiStatePtr CreateTestHmiState(); + + template <class Command> + SharedPtr<Command> CreateCommand(MessageSharedPtr& msg) { + return ::utils::MakeShared<Command>(msg, app_mngr_); + } + + protected: + typedef CommandsTest<CommandsTestMocks::kIsNice>::MockAppManager + MockAppManager; + MockAppManager app_mngr_; + utils::SharedPtr<ApplicationImplTest> app_impl_; + MockHmiInterfaces mock_hmi_interfaces_; + NiceMock<event_engine_test::MockEventDispatcher> mock_event_dispatcher_; + NiceMock<MockApplicationManagerSettings> app_mngr_settings_; + utils::SharedPtr<application_manager_test::MockApplication> mock_app_; + ApplicationSet test_app_; + sync_primitives::Lock app_lock_; + DataAccessor<ApplicationSet> app_set_; + application_manager::MockMessageHelper& mock_message_helper_; + utils::SharedPtr<MockHelpPromptManager> mock_help_prompt_manager_; +}; + +void HelpPromptManagerTest::SetUp() { + ON_CALL(app_mngr_, hmi_interfaces()) + .WillByDefault(ReturnRef(mock_hmi_interfaces_)); + ON_CALL(mock_hmi_interfaces_, GetInterfaceFromFunction(_)) + .WillByDefault(Return(am::HmiInterfaces::HMI_INTERFACE_SDL)); + ON_CALL(mock_hmi_interfaces_, GetInterfaceState(_)) + .WillByDefault(Return(am::HmiInterfaces::STATE_AVAILABLE)); + + ON_CALL(app_mngr_, get_settings()) + .WillByDefault(ReturnRef(app_mngr_settings_)); + ON_CALL(app_mngr_, event_dispatcher()) + .WillByDefault(ReturnRef(mock_event_dispatcher_)); + ON_CALL(app_mngr_settings_, default_timeout()) + .WillByDefault(ReturnRef(kTimeout)); + ON_CALL(app_mngr_settings_, app_icons_folder()) + .WillByDefault(ReturnRef(kDirectoryName)); + ON_CALL(app_mngr_settings_, app_storage_folder()) + .WillByDefault(ReturnRef(kDirectoryName)); + ON_CALL(app_mngr_settings_, audio_data_stopped_timeout()) + .WillByDefault(Return(0)); + ON_CALL(app_mngr_settings_, video_data_stopped_timeout()) + .WillByDefault(Return(0)); + + mock_help_prompt_manager_ = + utils::SharedPtr<MockHelpPromptManager>(new MockHelpPromptManager()); + + HmiStatePtr state = utils::MakeShared<HmiState>( + static_cast<utils::SharedPtr<Application> >(mock_app_), + app_mngr_, + HmiState::STATE_ID_REGULAR); + + std::string path = file_system::CreateDirectory("storage"); + file_system::CreateFile(path + "/" + "certificate"); + + mock_app_ = utils::MakeShared<application_manager_test::MockApplication>(); +} + +void HelpPromptManagerTest::TearDown() { + Mock::VerifyAndClearExpectations(&mock_message_helper_); +} + +MessageSharedPtr HelpPromptManagerTest::CreateMsgParams() { + MessageSharedPtr msg = + ::utils::MakeShared<SmartObject>(smart_objects::SmartType_Map); + (*msg)[am::strings::params][am::strings::connection_key] = kConnectionKey; + (*msg)[am::strings::msg_params][am::strings::app_id] = kAppId; + return msg; +} + +void HelpPromptManagerTest::VRArraySetupHelper(MessageSharedPtr msg, + SmartObject& vr_help_title, + SmartObject& vr_help_array) { + (*msg)[am::strings::msg_params][am::strings::vr_help_title] = vr_help_title; + vr_help_array[0] = SmartObject(smart_objects::SmartType_Map); + vr_help_array[0][am::strings::text] = kText; + vr_help_array[0][am::strings::position] = kPosition; + (*msg)[am::strings::msg_params][am::strings::vr_help] = vr_help_array; +} + +void HelpPromptManagerTest::CreateBasicParamsVRRequest(MessageSharedPtr msg) { + SmartObject& msg_params = (*msg)[strings::msg_params]; + msg_params[strings::cmd_id] = kCmdId; + msg_params[strings::vr_commands] = + SmartObject(smart_objects::SmartType_Array); + msg_params[strings::vr_commands][0] = kFirstVrCommand; + msg_params[strings::type] = kPosition; + msg_params[strings::grammar_id] = kGrammarId; + msg_params[strings::info] = "VR info"; +} + +HmiStatePtr HelpPromptManagerTest::CreateTestHmiState() { + HmiStatePtr testState = utils::MakeShared<HmiState>( + static_cast<utils::SharedPtr<Application> >(app_impl_), + app_mngr_, + HmiState::STATE_ID_REGULAR); + testState->set_hmi_level(HMILevel::INVALID_ENUM); + testState->set_audio_streaming_state(AudioStreamingState::NOT_AUDIBLE); + testState->set_system_context(SystemContext::SYSCTXT_MAIN); + return testState; +} + +void HelpPromptManagerTest::CreateApplication( + MockHelpPromptManager& mock_help_prompt_manager) { + const std::string policy_app_id = "p_app_id"; + const std::string mac_address = "MA:CA:DD:RE:SS"; + const connection_handler::DeviceHandle device_id = 1; + const custom_str::CustomString app_name(""); + + app_impl_.reset( + new ApplicationImplTest(kAppId, + policy_app_id, + mac_address, + device_id, + app_name, + utils::MakeShared<MockStatisticsManager>(), + app_mngr_, + mock_help_prompt_manager)); + HmiStatePtr initial_state = CreateTestHmiState(); + app_impl_->SetInitialState(initial_state); +} + +TEST_F(HelpPromptManagerTest, AddCommand_OnVrCommandAdded) { + CreateApplication(*mock_help_prompt_manager_.get()); + MessageSharedPtr msg = + ::utils::MakeShared<SmartObject>(smart_objects::SmartType_Map); + CreateBasicParamsVRRequest(msg); + (*msg)[strings::params][hmi_response::code] = + hmi_apis::Common_Result::SUCCESS; + (*msg)[strings::msg_params][strings::cmd_id] = kCmdId; + + EXPECT_CALL(*mock_help_prompt_manager_, + OnVrCommandAdded(kCmdId, (*msg)[strings::msg_params])); + + app_impl_->AddCommand(kCmdId, (*msg)[strings::msg_params]); +} + +TEST_F(HelpPromptManagerTest, RemoveCommand_OnVrCommandDeleted) { + CreateApplication(*mock_help_prompt_manager_.get()); + MessageSharedPtr msg = + ::utils::MakeShared<SmartObject>(smart_objects::SmartType_Map); + CreateBasicParamsVRRequest(msg); + (*msg)[strings::params][hmi_response::code] = + hmi_apis::Common_Result::SUCCESS; + (*msg)[strings::msg_params][strings::cmd_id] = kCmdId; + + EXPECT_CALL(*mock_help_prompt_manager_, + OnVrCommandAdded(kCmdId, (*msg)[strings::msg_params])); + EXPECT_CALL(*mock_help_prompt_manager_, OnVrCommandDeleted(kCmdId)); + + app_impl_->AddCommand(kCmdId, (*msg)[strings::msg_params]); + app_impl_->RemoveCommand(kCmdId); +} + +TEST_F(HelpPromptManagerTest, + Request_OnSetGlobalPropertiesReceived_TTS_SUCCESS) { + MessageSharedPtr msg = CreateMsgParams(); + SmartObject help_prompt(smart_objects::SmartType_Array); + help_prompt[0][am::strings::text] = "Help_Prompt_One"; + (*msg)[am::strings::msg_params][am::strings::help_prompt] = help_prompt; + SmartObject timeout_prompt(smart_objects::SmartType_Array); + timeout_prompt[0][am::strings::text] = "Timeout_Prompt_One"; + (*msg)[am::strings::msg_params][am::strings::timeout_prompt] = timeout_prompt; + + EXPECT_CALL(mock_message_helper_, VerifyImageVrHelpItems(_, _, _)).Times(0); + + EXPECT_CALL(app_mngr_, application(kConnectionKey)) + .WillOnce(Return(mock_app_)); + EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); + + EXPECT_CALL(*mock_app_, app_id()).WillOnce(Return(kAppId)); + EXPECT_CALL(*mock_app_, set_help_prompt(help_prompt)); + EXPECT_CALL(*mock_app_, help_prompt()).WillOnce(Return(&help_prompt)); + EXPECT_CALL(*mock_app_, set_timeout_prompt(timeout_prompt)); + EXPECT_CALL(*mock_app_, timeout_prompt()).WillOnce(Return(&timeout_prompt)); + EXPECT_CALL( + mock_hmi_interfaces_, + GetInterfaceFromFunction(hmi_apis::FunctionID::TTS_SetGlobalProperties)) + .WillOnce(Return(am::HmiInterfaces::HMI_INTERFACE_TTS)); + + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); + EXPECT_CALL(*mock_help_prompt_manager_, + OnSetGlobalPropertiesReceived(_, false)); + + SharedPtr<SetGlobalPropertiesRequest> command( + CreateCommand<SetGlobalPropertiesRequest>(msg)); + + command->Run(); +} + +TEST_F(HelpPromptManagerTest, + Request_OnSetGlobalPropertiesReceived_UI_SUCCESS) { + MessageSharedPtr msg = CreateMsgParams(); + SmartObject vr_help_title("yes"); + SmartObject vr_help_array(smart_objects::SmartType_Array); + VRArraySetupHelper(msg, vr_help_title, vr_help_array); + (*msg)[am::strings::msg_params][am::strings::vr_help] = vr_help_array; + SmartObject menu_title("Menu_Title"); + (*msg)[am::strings::msg_params][am::hmi_request::menu_title] = menu_title; + SmartObject menu_icon(smart_objects::SmartType_Map); + menu_icon[am::strings::value] = "1"; + (*msg)[am::strings::msg_params][am::hmi_request::menu_icon] = menu_icon; + SmartObject keyboard_properties(smart_objects::SmartType_Map); + (*msg)[am::strings::msg_params][am::hmi_request::keyboard_properties] = + keyboard_properties; + + EXPECT_CALL(mock_message_helper_, VerifyImage(menu_icon, _, _)) + .WillOnce((Return(mobile_apis::Result::SUCCESS))); + EXPECT_CALL(mock_message_helper_, VerifyImageVrHelpItems(vr_help_array, _, _)) + .WillOnce((Return(mobile_apis::Result::SUCCESS))); + EXPECT_CALL(app_mngr_, RemoveAppFromTTSGlobalPropertiesList(kConnectionKey)); + EXPECT_CALL(app_mngr_, application(kConnectionKey)) + .WillRepeatedly(Return(mock_app_)); + + EXPECT_CALL(*mock_app_, set_vr_help_title(vr_help_title)); + EXPECT_CALL(*mock_app_, set_vr_help(vr_help_array)); + EXPECT_CALL(*mock_app_, vr_help_title()).WillOnce(Return(&vr_help_title)); + EXPECT_CALL(*mock_app_, vr_help()).WillOnce(Return(&vr_help_array)); + EXPECT_CALL(*mock_app_, set_menu_title(menu_title)); + EXPECT_CALL(*mock_app_, set_menu_icon(menu_icon)); + EXPECT_CALL(*mock_app_, set_keyboard_props(keyboard_properties)); + EXPECT_CALL(*mock_app_, app_id()).WillOnce(Return(kAppId)); + EXPECT_CALL( + mock_hmi_interfaces_, + GetInterfaceFromFunction(hmi_apis::FunctionID::UI_SetGlobalProperties)) + .WillOnce(Return(am::HmiInterfaces::HMI_INTERFACE_UI)); + + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); + EXPECT_CALL(*mock_help_prompt_manager_, + OnSetGlobalPropertiesReceived(_, false)); + + SharedPtr<SetGlobalPropertiesRequest> command( + CreateCommand<SetGlobalPropertiesRequest>(msg)); + + command->Run(); +} + +} // namespace application_manager_test +} // namespace components +} // namespace test diff --git a/src/components/application_manager/test/include/application_manager/mock_application.h b/src/components/application_manager/test/include/application_manager/mock_application.h index 952b485e48..9b6f84ba52 100644 --- a/src/components/application_manager/test/include/application_manager/mock_application.h +++ b/src/components/application_manager/test/include/application_manager/mock_application.h @@ -155,6 +155,8 @@ class MockApplication : public ::application_manager::Application { bool(mobile_apis::FunctionID::eType cmd_id, ::application_manager::TLimitSource source)); MOCK_METHOD0(usage_report, ::application_manager::UsageStatistics&()); + MOCK_METHOD0(help_prompt_manager, + ::application_manager::HelpPromptManager&()); MOCK_METHOD1(SetInitialState, void(::application_manager::HmiStatePtr state)); MOCK_METHOD1(SetRegularState, void(::application_manager::HmiStatePtr state)); MOCK_METHOD1(SetPostponedState, diff --git a/src/components/application_manager/test/include/application_manager/mock_help_prompt_manager.h b/src/components/application_manager/test/include/application_manager/mock_help_prompt_manager.h new file mode 100644 index 0000000000..26eb8f6610 --- /dev/null +++ b/src/components/application_manager/test/include/application_manager/mock_help_prompt_manager.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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_APPLICATION_MANAGER_TEST_INCLUDE_APPLICATION_MANAGER_MOCK_HELP_PROMPT_MANAGER_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_TEST_INCLUDE_APPLICATION_MANAGER_MOCK_HELP_PROMPT_MANAGER_H_ +#include "gmock/gmock.h" + +namespace test { +namespace components { +namespace application_manager_test { + +using namespace application_manager; + +class MockHelpPromptManager : public ::application_manager::HelpPromptManager { + public: + MockHelpPromptManager() {} + MOCK_METHOD2(OnVrCommandAdded, + void(uint32_t cmd_id, + const smart_objects::SmartObject& command)); + MOCK_METHOD1(OnVrCommandDeleted, void(uint32_t cmd_id)); + MOCK_METHOD0(OnTimeoutExpired, void()); + MOCK_METHOD2(OnSetGlobalPropertiesReceived, + void(const smart_objects::SmartObject& msg, bool is_response)); + MOCK_METHOD1(OnAppActivated, void(bool is_restore)); + MOCK_METHOD0(OnAppUnregistered, void()); +}; + +} // namespace application_manager_test +} // namespace components +} // namespace test + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_TEST_INCLUDE_APPLICATION_MANAGER_MOCK_HELP_PROMPT_MANAGER_H_ 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 1a5d070941..26a44826be 100644 --- a/src/components/application_manager/test/resumption/resume_ctrl_test.cc +++ b/src/components/application_manager/test/resumption/resume_ctrl_test.cc @@ -38,6 +38,7 @@ #include "application_manager/usage_statistics.h" #include "application_manager/mock_application.h" #include "application_manager/mock_app_extension.h" +#include "application_manager/mock_help_prompt_manager.h" #include "application_manager/mock_resumption_data.h" #include "interfaces/MOBILE_API.h" #include "application_manager/application_manager_impl.h" @@ -92,6 +93,8 @@ class ResumeCtrlTest : public ::testing::Test { ::utils::MakeShared<NiceMock<resumption_test::MockResumptionData> >( mock_app_mngr_); mock_app_ = utils::MakeShared<NiceMock<MockApplication> >(); + mock_help_prompt_manager_ = + std::shared_ptr<MockHelpPromptManager>(new MockHelpPromptManager()); mock_app_extension_ = utils::MakeShared< NiceMock<application_manager_test::MockAppExtension> >(); const_app_ = @@ -131,6 +134,7 @@ class ResumeCtrlTest : public ::testing::Test { utils::SharedPtr<NiceMock<resumption_test::MockResumptionData> > mock_storage_; utils::SharedPtr<NiceMock<MockApplication> > mock_app_; + std::shared_ptr<MockHelpPromptManager> mock_help_prompt_manager_; application_manager::ApplicationConstSharedPtr const_app_; const uint32_t kTestAppId_; const std::string kTestPolicyAppId_; @@ -551,9 +555,16 @@ TEST_F(ResumeCtrlTest, StartAppHmiStateResumption_AppInFull) { saved_app[application_manager::strings::ign_off_count] = ign_off_count; saved_app[application_manager::strings::hmi_level] = restored_test_type; + application_manager::CommandsMap command; + DataAccessor<application_manager::CommandsMap> data_accessor(command, + app_set_lock_); + EXPECT_CALL(mock_state_controller_, SetRegularState(_, restored_test_type)) .Times(AtLeast(1)); GetInfoFromApp(); + EXPECT_CALL(mock_app_mngr_, GetDefaultHmiLevel(const_app_)) + .WillRepeatedly(Return(kDefaultTestLevel_)); + EXPECT_CALL(*mock_app_, commands_map()).WillRepeatedly(Return(data_accessor)); ON_CALL(*mock_storage_, GetSavedApplication(kTestPolicyAppId_, kMacAddress_, _)) .WillByDefault(DoAll(SetArgReferee<2>(saved_app), Return(true))); @@ -564,6 +575,8 @@ TEST_F(ResumeCtrlTest, StartAppHmiStateResumption_AppInFull) { ON_CALL(mock_app_mngr_, GetUserConsentForDevice("12345")) .WillByDefault(Return(policy::kDeviceAllowed)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); res_ctrl_->StartAppHmiStateResumption(mock_app_); } @@ -591,6 +604,10 @@ TEST_F(ResumeCtrlTest, StartAppHmiStateResumption_AppInBackground) { TEST_F(ResumeCtrlTest, RestoreAppHMIState_RestoreHMILevelFull) { mobile_apis::HMILevel::eType restored_test_type = eType::HMI_FULL; + ::application_manager::CommandsMap command; + DataAccessor<application_manager::CommandsMap> data_accessor(command, + app_set_lock_); + smart_objects::SmartObject saved_app; saved_app[application_manager::strings::hash_id] = kHash_; saved_app[application_manager::strings::grammar_id] = kTestGrammarId_; @@ -599,6 +616,9 @@ TEST_F(ResumeCtrlTest, RestoreAppHMIState_RestoreHMILevelFull) { EXPECT_CALL(mock_state_controller_, SetRegularState(_, restored_test_type)) .Times(AtLeast(1)); GetInfoFromApp(); + EXPECT_CALL(mock_app_mngr_, GetDefaultHmiLevel(const_app_)) + .WillRepeatedly(Return(kDefaultTestLevel_)); + EXPECT_CALL(*mock_app_, commands_map()).WillRepeatedly(Return(data_accessor)); ON_CALL(*mock_storage_, GetSavedApplication(kTestPolicyAppId_, kMacAddress_, _)) .WillByDefault(DoAll(SetArgReferee<2>(saved_app), Return(true))); @@ -606,6 +626,8 @@ TEST_F(ResumeCtrlTest, RestoreAppHMIState_RestoreHMILevelFull) { ON_CALL(mock_app_mngr_, GetUserConsentForDevice("12345")) .WillByDefault(Return(policy::kDeviceAllowed)); EXPECT_CALL(*mock_app_, set_is_resuming(true)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); const bool res = res_ctrl_->RestoreAppHMIState(mock_app_); EXPECT_TRUE(res); @@ -634,6 +656,10 @@ TEST_F(ResumeCtrlTest, ApplicationResumptiOnTimer_AppInFull) { ON_CALL(mock_app_mngr_, application(kTestAppId_)) .WillByDefault(Return(mock_app_)); + ::application_manager::CommandsMap command; + DataAccessor<application_manager::CommandsMap> data_accessor(command, + app_set_lock_); + mobile_apis::HMILevel::eType restored_test_type = eType::HMI_FULL; const uint32_t ign_off_count = 0u; smart_objects::SmartObject saved_app; @@ -646,6 +672,9 @@ TEST_F(ResumeCtrlTest, ApplicationResumptiOnTimer_AppInFull) { EXPECT_CALL(state_controller, SetRegularState(_, restored_test_type)) .Times(AtLeast(1)); GetInfoFromApp(); + EXPECT_CALL(app_mngr_, GetDefaultHmiLevel(const_app_)) + .WillRepeatedly(Return(kDefaultTestLevel_)); + EXPECT_CALL(*app_mock_, commands_map()).WillRepeatedly(Return(data_accessor)); ON_CALL(*mock_storage_, GetSavedApplication(kTestPolicyAppId_, kMacAddress_, _)) .WillByDefault(DoAll(SetArgReferee<2>(saved_app), Return(true))); @@ -656,6 +685,8 @@ TEST_F(ResumeCtrlTest, ApplicationResumptiOnTimer_AppInFull) { ON_CALL(mock_app_mngr_, GetUserConsentForDevice(kMacAddress_)) .WillByDefault(Return(policy::kDeviceAllowed)); + EXPECT_CALL(*mock_app_, help_prompt_manager()) + .WillOnce(ReturnRef(*mock_help_prompt_manager_.get())); res_ctrl_->StartAppHmiStateResumption(mock_app_); } |