From 248232e73df96d9579c004ebc41e16fc4133fe19 Mon Sep 17 00:00:00 2001 From: "Igor Gapchuk (GitHub)" <41586842+IGapchuk@users.noreply.github.com> Date: Wed, 3 Feb 2021 01:40:49 +0200 Subject: [PATCH] Fix SDL does not unsubscribe from softbuttons after receiving a response. (#2629) * Fix SDL does not unsubscribe from softbuttons after receiving a response. When SDL recives AlertManeuverResponse, AlertResponse, UpdateTurnListResponse, ScrollableMessageResponse, ShowConstantTBTResponse SDL unsubscribes from soft buttons before sends response to mobile. Added unit test cases for specified responses. * Answer to PR comments. * Answer to PR comments. * Answer to PR comments. * Apply typo fixes from code review * Address comments and fix tests after merge * Address comments * Change keeping of softbuttons according to a WindowID SDL should keep softbuttons subscriptions in pair with a WindowID that related to the softbuttons * Fix regression and style issues * fixup! Fix regression and style issues Co-authored-by: Jacob Keeler Co-authored-by: Andrii Kalinich Co-authored-by: Dmitriy Boltovskiy --- .../include/application_manager/application.h | 15 ++- .../application_manager/application_impl.h | 6 +- .../application_manager_impl.h | 3 + .../mobile/alert_maneuver_response.cc | 2 + .../src/commands/mobile/alert_response.cc | 2 + .../mobile/scrollable_message_response.cc | 10 +- .../mobile/show_constant_tbt_response.cc | 2 + .../mobile/update_turn_list_response.cc | 2 + .../mobile/simple_response_commands_test.cc | 52 +++++---- .../src/application_impl.cc | 100 +++++++++++++----- .../src/application_manager_impl.cc | 17 +++ .../src/message_helper/message_helper.cc | 24 +++-- .../test/application_impl_test.cc | 13 ++- .../test/application_manager_impl_test.cc | 52 +++++++-- .../application_manager/mock_application.h | 7 +- .../message_helper/message_helper_test.cc | 42 ++++++-- .../application_manager/application_manager.h | 8 ++ .../mock_application_manager.h | 3 + 18 files changed, 260 insertions(+), 100 deletions(-) diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h index c08bb370824..2eb4501bcc6 100644 --- a/src/components/application_manager/include/application_manager/application.h +++ b/src/components/application_manager/include/application_manager/application.h @@ -170,9 +170,14 @@ typedef std::map PerformChoice; typedef std::map PerformChoiceSetMap; /** - * @brief Defines id of SoftButton + * @brief Defines id of SoftButtons for specified WindowID */ -typedef std::set > SoftButtonID; +typedef std::pair > WindowSoftButtons; + +/** + * @brief Defines id of SoftButtons related to a specified WindowID + */ +typedef std::set SoftButtonIDs; /** * @brief Defines set of buttons subscription @@ -961,10 +966,10 @@ class Application : public virtual InitialApplicationData, * Alert, Show, ScrollableMessage, ShowConstantTBT, AlertManeuver, * UpdateTurnList * @param cmd_id Unique command id from mobile API - * @param list of softbuttons were created by command. + * @param window_softbuttons list of softbuttons were created by command. */ - virtual void SubscribeToSoftButtons(int32_t cmd_id, - const SoftButtonID& softbuttons_id) = 0; + virtual void SubscribeToSoftButtons( + int32_t cmd_id, const WindowSoftButtons& window_softbuttons) = 0; /** * @brief Retreives window id on which given button is created 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 88668a25059..6d60699a4ee 100644 --- a/src/components/application_manager/include/application_manager/application_impl.h +++ b/src/components/application_manager/include/application_manager/application_impl.h @@ -279,8 +279,8 @@ class ApplicationImpl : public virtual Application, bool AreCommandLimitsExceeded(mobile_apis::FunctionID::eType cmd_id, TLimitSource source); - virtual void SubscribeToSoftButtons(int32_t cmd_id, - const SoftButtonID& softbuttons_id); + virtual void SubscribeToSoftButtons( + int32_t cmd_id, const WindowSoftButtons& window_softbuttons); virtual bool IsSubscribedToSoftButton(const uint32_t softbutton_id); virtual void UnsubscribeFromSoftButtons(int32_t cmd_id); @@ -638,7 +638,7 @@ class ApplicationImpl : public virtual Application, /** * @brief Defines id of SoftButton which is related from name of command */ - typedef std::map CommandSoftButtonID; + typedef std::map CommandSoftButtonID; CommandNumberTimeLimit cmd_number_to_time_limits_; CommandSoftButtonID cmd_softbuttonid_; // Lock for command soft button id diff --git a/src/components/application_manager/include/application_manager/application_manager_impl.h b/src/components/application_manager/include/application_manager/application_manager_impl.h index 5bcea1eac94..320d3df9ce1 100644 --- a/src/components/application_manager/include/application_manager/application_manager_impl.h +++ b/src/components/application_manager/include/application_manager/application_manager_impl.h @@ -1172,6 +1172,9 @@ class ApplicationManagerImpl bool IsSOStructValid(const hmi_apis::StructIdentifiers::eType struct_id, const smart_objects::SmartObject& display_capabilities); + virtual bool UnsubscribeAppFromSoftButtons( + const commands::MessageSharedPtr response) OVERRIDE; + /** * @brief Function returns supported SDL Protocol Version * @return protocol version depends on parameters from smartDeviceLink.ini. diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/alert_maneuver_response.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/alert_maneuver_response.cc index 993dc755482..5661b1df9c7 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/alert_maneuver_response.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/alert_maneuver_response.cc @@ -59,6 +59,8 @@ AlertManeuverResponse::~AlertManeuverResponse() {} void AlertManeuverResponse::Run() { SDL_LOG_AUTO_TRACE(); + application_manager_.UnsubscribeAppFromSoftButtons(message_); + rpc_service_.SendMessageToMobile(message_); } diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/alert_response.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/alert_response.cc index 1b8eebe7d7e..84d23bec466 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/alert_response.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/alert_response.cc @@ -61,6 +61,8 @@ AlertResponse::~AlertResponse() {} void AlertResponse::Run() { SDL_LOG_AUTO_TRACE(); + application_manager_.UnsubscribeAppFromSoftButtons(message_); + rpc_service_.SendMessageToMobile(message_); } diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/scrollable_message_response.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/scrollable_message_response.cc index a6f980b9bad..b7cf0e15ac8 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/scrollable_message_response.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/scrollable_message_response.cc @@ -57,15 +57,7 @@ ScrollableMessageResponse::ScrollableMessageResponse( void ScrollableMessageResponse::Run() { SDL_LOG_AUTO_TRACE(); - mobile_apis::Result::eType result_code = - static_cast( - (*message_)[strings::msg_params][strings::result_code].asInt()); - ApplicationSharedPtr application = application_manager_.application( - (*message_)[strings::params][strings::connection_key].asInt()); - if ((mobile_apis::Result::REJECTED != result_code) && application) { - application->UnsubscribeFromSoftButtons( - (*message_)[strings::params][strings::function_id].asInt()); - } + application_manager_.UnsubscribeAppFromSoftButtons(message_); rpc_service_.SendMessageToMobile(message_); } diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/show_constant_tbt_response.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/show_constant_tbt_response.cc index 7d546079e88..a2362a74bcf 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/show_constant_tbt_response.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/show_constant_tbt_response.cc @@ -60,6 +60,8 @@ ShowConstantTBTResponse::~ShowConstantTBTResponse() {} void ShowConstantTBTResponse::Run() { SDL_LOG_AUTO_TRACE(); + application_manager_.UnsubscribeAppFromSoftButtons(message_); + rpc_service_.SendMessageToMobile(message_); } diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/update_turn_list_response.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/update_turn_list_response.cc index bedf91b45c5..bf2658128d2 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/update_turn_list_response.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/update_turn_list_response.cc @@ -59,6 +59,8 @@ UpdateTurnListResponse::~UpdateTurnListResponse() {} void UpdateTurnListResponse::Run() { SDL_LOG_AUTO_TRACE(); + application_manager_.UnsubscribeAppFromSoftButtons(message_); + rpc_service_.SendMessageToMobile(message_); } diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/simple_response_commands_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/simple_response_commands_test.cc index 0034dcf9162..d091fdc8c57 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/simple_response_commands_test.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/simple_response_commands_test.cc @@ -93,15 +93,12 @@ class MobileResponseCommandsTest typedef TypesRun(); } +template +class MobileResponseWithUnsubscribeCommandsTest + : public CommandsTest { + public: + typedef CommandWithUnsubscribe UnsubscribeCommand; +}; + +typedef Types + ResponseWithUnsubscribeCommandList; + +TYPED_TEST_CASE(MobileResponseWithUnsubscribeCommandsTest, + ResponseWithUnsubscribeCommandList); + +TYPED_TEST(MobileResponseWithUnsubscribeCommandsTest, + RunWithUnsubscribe_SUCCESS) { + std::shared_ptr command = + this->template CreateCommand(); + + EXPECT_CALL(this->app_mngr_, UnsubscribeAppFromSoftButtons(_)); + EXPECT_CALL(this->mock_rpc_service_, SendMessageToMobile(NotNull(), _)); + + command->Init(); + command->Run(); +} + class GenericResponseFromHMICommandsTest : public CommandsTest {}; @@ -145,7 +170,6 @@ MATCHER_P2(CheckMessageParams, success, result, "") { result == static_cast( (*arg)[am::strings::msg_params][am::strings::result_code].asInt()); - using namespace helpers; return Compare( true, is_msg_type_correct, is_success_correct, is_result_code_correct); @@ -164,24 +188,6 @@ TEST_F(GenericResponseFromHMICommandsTest, Run_SUCCESS) { command->Run(); } - -class ScrollableMessageResponseTest - : public CommandsTest {}; - -TEST_F(ScrollableMessageResponseTest, Run_SUCCESS) { - MessageSharedPtr message = CreateMessage(); - (*message)[am::strings::msg_params][am::strings::result_code] = - mobile_apis::Result::SUCCESS; - - MockAppPtr app(CreateMockApp()); - - std::shared_ptr command( - CreateCommand(message)); - EXPECT_CALL(app_mngr_, application(_)).WillOnce(Return(app)); - EXPECT_CALL(*app, UnsubscribeFromSoftButtons(_)); - command->Run(); -} - } // namespace simple_response_commands_test } // namespace mobile_commands_test } // namespace commands_test diff --git a/src/components/application_manager/src/application_impl.cc b/src/components/application_manager/src/application_impl.cc index 6b4500e394d..2e104f73e26 100644 --- a/src/components/application_manager/src/application_impl.cc +++ b/src/components/application_manager/src/application_impl.cc @@ -1147,20 +1147,36 @@ uint32_t ApplicationImpl::GetAvailableDiskSpace() { } void ApplicationImpl::SubscribeToSoftButtons( - int32_t cmd_id, const SoftButtonID& softbuttons_id) { + int32_t cmd_id, const WindowSoftButtons& window_softbuttons) { sync_primitives::AutoLock lock(cmd_softbuttonid_lock_); - if (static_cast(mobile_apis::FunctionID::ScrollableMessageID) == - cmd_id) { - CommandSoftButtonID::iterator it = cmd_softbuttonid_.find(cmd_id); - if (cmd_softbuttonid_.end() == it) { - cmd_softbuttonid_[cmd_id] = softbuttons_id; - } - } else { - auto& soft_button_ids = cmd_softbuttonid_[cmd_id]; - for (auto& softbutton_item : softbuttons_id) { - soft_button_ids.insert(softbutton_item); - } + CommandSoftButtonID::iterator it = cmd_softbuttonid_.find(cmd_id); + + if (cmd_softbuttonid_.end() == it) { + SoftButtonIDs soft_buttons{window_softbuttons}; + cmd_softbuttonid_.insert({cmd_id, soft_buttons}); + return; } + + auto& command_soft_buttons = cmd_softbuttonid_[cmd_id]; + + const auto window_id = window_softbuttons.first; + auto find_window_id = [window_id](const WindowSoftButtons& window_buttons) { + return window_id == window_buttons.first; + }; + + auto subscribed_window_buttons = std::find_if( + command_soft_buttons.begin(), command_soft_buttons.end(), find_window_id); + + if (subscribed_window_buttons == command_soft_buttons.end()) { + command_soft_buttons.insert(window_softbuttons); + return; + } + + WindowSoftButtons new_window_soft_buttons = *subscribed_window_buttons; + new_window_soft_buttons.second.insert(window_softbuttons.second.begin(), + window_softbuttons.second.end()); + command_soft_buttons.erase(subscribed_window_buttons); + command_soft_buttons.insert(new_window_soft_buttons); } struct FindSoftButtonId { @@ -1169,24 +1185,46 @@ struct FindSoftButtonId { explicit FindSoftButtonId(const uint32_t soft_button_id) : soft_button_id_(soft_button_id) {} - bool operator()(const std::pair& element) const { - return soft_button_id_ == element.first; + bool operator()(const uint32_t softbutton_id) { + return soft_button_id_ == softbutton_id; } }; +struct FindWindowSoftButtonId { + public: + FindWindowSoftButtonId(const uint32_t soft_button_id) + : find_softbutton_id_(soft_button_id) {} + + bool operator()(const WindowSoftButtons& window_buttons) { + const auto softbuttons = window_buttons.second; + auto found_softbutton = std::find_if( + softbuttons.begin(), softbuttons.end(), find_softbutton_id_); + + return found_softbutton != softbuttons.end(); + } + + private: + FindSoftButtonId find_softbutton_id_; +}; + bool ApplicationImpl::IsSubscribedToSoftButton(const uint32_t softbutton_id) { SDL_LOG_AUTO_TRACE(); sync_primitives::AutoLock lock(cmd_softbuttonid_lock_); - CommandSoftButtonID::iterator it = cmd_softbuttonid_.begin(); - for (; it != cmd_softbuttonid_.end(); ++it) { - const auto& soft_button_ids = (*it).second; - FindSoftButtonId finder(softbutton_id); - const auto find_res = - std::find_if(soft_button_ids.begin(), soft_button_ids.end(), finder); - if ((soft_button_ids.end() != find_res)) { + + for (const auto& command_soft_buttons : cmd_softbuttonid_) { + FindWindowSoftButtonId find_window_softbutton_id(softbutton_id); + const auto& window_softbuttons = command_soft_buttons.second; + + const auto found_window_softbutton_id = + std::find_if(window_softbuttons.begin(), + window_softbuttons.end(), + find_window_softbutton_id); + + if (found_window_softbutton_id != window_softbuttons.end()) { return true; } } + return false; } @@ -1194,14 +1232,18 @@ WindowID ApplicationImpl::GetSoftButtonWindowID(const uint32_t softbutton_id) { SDL_LOG_AUTO_TRACE(); sync_primitives::AutoLock lock(cmd_softbuttonid_lock_); - CommandSoftButtonID::iterator it = cmd_softbuttonid_.begin(); - for (; it != cmd_softbuttonid_.end(); ++it) { - const auto& soft_button_ids = (*it).second; - FindSoftButtonId finder(softbutton_id); - const auto find_res = - std::find_if(soft_button_ids.begin(), soft_button_ids.end(), finder); - if ((soft_button_ids.end() != find_res)) { - return find_res->second; + + for (const auto& command_soft_buttons : cmd_softbuttonid_) { + FindWindowSoftButtonId find_window_softbutton_id(softbutton_id); + const auto& window_softbuttons = command_soft_buttons.second; + + const auto found_window_softbutton_id = + std::find_if(window_softbuttons.begin(), + window_softbuttons.end(), + find_window_softbutton_id); + + if (found_window_softbutton_id != window_softbuttons.end()) { + return found_window_softbutton_id->first; } } diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index fcaa7c05360..8c5932497a0 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -4898,6 +4898,23 @@ bool ApplicationManagerImpl::IsSOStructValid( return false; } +bool ApplicationManagerImpl::UnsubscribeAppFromSoftButtons( + const commands::MessageSharedPtr response) { + using namespace mobile_apis; + + const uint32_t connection_key = + (*response)[strings::params][strings::connection_key].asUInt(); + const auto function_id = static_cast( + (*response)[strings::params][strings::function_id].asInt()); + + ApplicationSharedPtr app = application(connection_key); + DCHECK_OR_RETURN(app, false); + app->UnsubscribeFromSoftButtons(function_id); + SDL_LOG_DEBUG("Application has unsubscribed from softbuttons. FunctionID: " + << function_id << ", app_id:" << app->app_id()); + return true; +} + #ifdef BUILD_TESTS void ApplicationManagerImpl::AddMockApplication(ApplicationSharedPtr mock_app) { applications_list_lock_ptr_->Acquire(); 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 ba1c726415d..52da15af423 100644 --- a/src/components/application_manager/src/message_helper/message_helper.cc +++ b/src/components/application_manager/src/message_helper/message_helper.cc @@ -3365,16 +3365,20 @@ void MessageHelper::SubscribeApplicationToSoftButton( ApplicationSharedPtr app, int32_t function_id, const WindowID window_id) { - SoftButtonID softbuttons_id; - smart_objects::SmartObject& soft_buttons = - message_params[strings::soft_buttons]; - unsigned int length = soft_buttons.length(); - for (unsigned int i = 0; i < length; ++i) { - const auto button_id = std::make_pair( - soft_buttons[i][strings::soft_button_id].asUInt(), window_id); - softbuttons_id.insert(button_id); - } - app->SubscribeToSoftButtons(function_id, softbuttons_id); + if (!message_params.keyExists(strings::soft_buttons)) { + return; + } + + std::set soft_buttons; + + auto& soft_buttons_so = message_params[strings::soft_buttons]; + for (const auto& softbutton : *(soft_buttons_so.asArray())) { + const auto button_id = softbutton[strings::soft_button_id].asUInt(); + soft_buttons.insert(button_id); + } + + WindowSoftButtons window_buttons{window_id, soft_buttons}; + app->SubscribeToSoftButtons(function_id, window_buttons); } void MessageHelper::SubscribeApplicationToSoftButton( diff --git a/src/components/application_manager/test/application_impl_test.cc b/src/components/application_manager/test/application_impl_test.cc index d468c9790b5..c3d02271cf9 100644 --- a/src/components/application_manager/test/application_impl_test.cc +++ b/src/components/application_manager/test/application_impl_test.cc @@ -571,14 +571,17 @@ TEST_F(ApplicationImplTest, SubscribeToSoftButton_UnsubscribeFromSoftButton) { EXPECT_FALSE(app_impl->IsSubscribedToSoftButton(i)); } - SoftButtonID test_button; + std::set softbuttons_ids; + for (uint i = 0; i < btn_count; i++) { - test_button.insert(std::make_pair( - i, - static_cast(mobile_apis::PredefinedWindows::DEFAULT_WINDOW))); + softbuttons_ids.insert(i); } + + WindowSoftButtons window_softbuttons{ + static_cast(mobile_apis::PredefinedWindows::DEFAULT_WINDOW), + softbuttons_ids}; app_impl->SubscribeToSoftButtons(FunctionID::ScrollableMessageID, - test_button); + window_softbuttons); for (uint i = 0; i < btn_count; i++) { EXPECT_TRUE(app_impl->IsSubscribedToSoftButton(i)); 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 ab49e93e779..48ba75275bf 100644 --- a/src/components/application_manager/test/application_manager_impl_test.cc +++ b/src/components/application_manager/test/application_manager_impl_test.cc @@ -159,9 +159,7 @@ struct ServiceStatus { : service_type_(type), service_event_(event), reason_(reason) {} }; -class ApplicationManagerImplTest - : public ::testing::Test, - public ::testing::WithParamInterface { +class ApplicationManagerImplTest : public ::testing::Test { public: ApplicationManagerImplTest() : app_id_(0u) @@ -406,9 +404,13 @@ MATCHER_P(HMIFunctionIDIs, result_code, "") { .asInt()); } +class ApplicationManagerImplTestWithServiceStatus + : public ::testing::WithParamInterface, + public ApplicationManagerImplTest {}; + INSTANTIATE_TEST_CASE_P( ProcessServiceStatusUpdate_REQUEST_ACCEPTED, - ApplicationManagerImplTest, + ApplicationManagerImplTestWithServiceStatus, ::testing::Values(ServiceStatus(ServiceType::AUDIO, ServiceEvent::REQUEST_ACCEPTED, UpdateReasonOptional::EMPTY), @@ -421,7 +423,7 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P( ProcessServiceStatusUpdate_REQUEST_RECEIVED, - ApplicationManagerImplTest, + ApplicationManagerImplTestWithServiceStatus, ::testing::Values(ServiceStatus(ServiceType::AUDIO, ServiceEvent::REQUEST_RECEIVED, UpdateReasonOptional::EMPTY), @@ -434,7 +436,7 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P( ProcessServiceStatusUpdate_REQUEST_REJECTED, - ApplicationManagerImplTest, + ApplicationManagerImplTestWithServiceStatus, ::testing::Values(ServiceStatus(ServiceType::AUDIO, ServiceEvent::REQUEST_REJECTED, UpdateReasonOptional::EMPTY), @@ -445,7 +447,7 @@ INSTANTIATE_TEST_CASE_P( ServiceEvent::REQUEST_REJECTED, UpdateReasonOptional::EMPTY))); -TEST_P(ApplicationManagerImplTest, +TEST_P(ApplicationManagerImplTestWithServiceStatus, ProcessServiceStatusUpdate_SendMessageToHMI) { smart_objects::SmartObjectSPtr notification_ = std::make_shared( @@ -2294,6 +2296,42 @@ TEST_F( app_manager_impl_->RequestForInterfacesAvailability(); } +class ApplicationManagerImplTestWithFunctionID + : public ::testing::WithParamInterface, + public ApplicationManagerImplTest {}; + +TEST_P(ApplicationManagerImplTestWithFunctionID, + UnsubscribeAppFromSoftButtons_SUCCESS) { + AddMockApplication(); + commands::MessageSharedPtr response_message = + std::make_shared( + smart_objects::SmartType_Map); + + const mobile_apis::FunctionID::eType function_id = GetParam(); + (*response_message)[strings::params][strings::connection_key] = + kConnectionKey; + (*response_message)[strings::msg_params][strings::result_code] = + mobile_apis::Result::SUCCESS; + (*response_message)[strings::params][strings::function_id] = function_id; + + EXPECT_CALL(*mock_app_ptr_, app_id()).WillOnce(Return(kConnectionKey)); + EXPECT_CALL(*mock_app_ptr_, UnsubscribeFromSoftButtons(function_id)); + + const bool unsubscribe_result = + app_manager_impl_->UnsubscribeAppFromSoftButtons(response_message); + + EXPECT_TRUE(unsubscribe_result); +} + +INSTANTIATE_TEST_CASE_P( + UnsubscribeAppFromSoftButtons, + ApplicationManagerImplTestWithFunctionID, + ::testing::Values(mobile_apis::FunctionID::ScrollableMessageID, + mobile_apis::FunctionID::AlertID, + mobile_apis::FunctionID::AlertManeuverID, + mobile_apis::FunctionID::UpdateTurnListID, + mobile_apis::FunctionID::ShowConstantTBTID)); + } // 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 454b43b99f8..9c28d321fac 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 @@ -206,9 +206,10 @@ class MockApplication : public ::application_manager::Application { MOCK_METHOD2(RemoveHMIState, void(const application_manager::WindowID window_id, ::application_manager::HmiState::StateID state_id)); - MOCK_METHOD2(SubscribeToSoftButtons, - void(int32_t cmd_id, - const ::application_manager::SoftButtonID& softbuttons_id)); + MOCK_METHOD2( + SubscribeToSoftButtons, + void(int32_t cmd_id, + const application_manager::WindowSoftButtons& window_softbuttons)); MOCK_METHOD1(IsSubscribedToSoftButton, bool(const uint32_t softbutton_id)); MOCK_METHOD1(UnsubscribeFromSoftButtons, void(int32_t cmd_id)); MOCK_CONST_METHOD0(IsAudioApplication, bool()); 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 c380805bc21..34d1e488b7d 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 @@ -888,16 +888,46 @@ TEST_F(MessageHelperTest, } } -TEST_F(MessageHelperTest, SubscribeApplicationToSoftButton_CallFromApp) { - // Create application mock +TEST_F( + MessageHelperTest, + SubscribeApplicationToSoftButton_SoftbuttonsAreAbsent_DoesntCallFromApp) { MockApplicationSharedPtr appSharedPtr = std::make_shared(); - // Prepare data for method smart_objects::SmartObject message_params; size_t function_id = 1; - // + WindowSoftButtons window_buttons{ + mobile_apis::PredefinedWindows::DEFAULT_WINDOW, {}}; + EXPECT_CALL(*appSharedPtr, - SubscribeToSoftButtons(function_id, SoftButtonID())) - .Times(1); + SubscribeToSoftButtons(function_id, window_buttons)) + .Times(0); + MessageHelper::SubscribeApplicationToSoftButton( + message_params, appSharedPtr, function_id); +} + +TEST_F(MessageHelperTest, + SubscribeApplicationToSoftButton_SoftbuttonsExist_CallFromApp) { + MockApplicationSharedPtr appSharedPtr = std::make_shared(); + smart_objects::SmartObject message_params; + message_params[strings::soft_buttons] = + new smart_objects::SmartObject(smart_objects::SmartType_Array); + const uint32_t softbutton1 = 1u; + const uint32_t softbutton2 = 2u; + const uint32_t softbutton3 = 3u; + message_params[strings::soft_buttons][0][strings::soft_button_id] = + softbutton1; + message_params[strings::soft_buttons][1][strings::soft_button_id] = + softbutton2; + message_params[strings::soft_buttons][2][strings::soft_button_id] = + softbutton3; + + size_t function_id = 1; + WindowSoftButtons window_buttons{ + mobile_apis::PredefinedWindows::DEFAULT_WINDOW, + {softbutton1, softbutton2, softbutton3}}; + + EXPECT_CALL(*appSharedPtr, + SubscribeToSoftButtons(function_id, window_buttons)); + MessageHelper::SubscribeApplicationToSoftButton( message_params, appSharedPtr, function_id); } diff --git a/src/components/include/application_manager/application_manager.h b/src/components/include/application_manager/application_manager.h index dfc8314530c..2bb202c62dc 100644 --- a/src/components/include/application_manager/application_manager.h +++ b/src/components/include/application_manager/application_manager.h @@ -934,6 +934,14 @@ class ApplicationManager { virtual bool IsSOStructValid( const hmi_apis::StructIdentifiers::eType struct_id, const smart_objects::SmartObject& display_capabilities) = 0; + + /** + * @brief Unsubscribe application specified in message from softbuttons. + * @param response_message - Response message received from HMI. + * @return bool - Result of unsubscribing process. + */ + virtual bool UnsubscribeAppFromSoftButtons( + const commands::MessageSharedPtr response_message) = 0; }; } // namespace application_manager diff --git a/src/components/include/test/application_manager/mock_application_manager.h b/src/components/include/test/application_manager/mock_application_manager.h index 70fdb4c4f3d..3b827b1a0df 100644 --- a/src/components/include/test/application_manager/mock_application_manager.h +++ b/src/components/include/test/application_manager/mock_application_manager.h @@ -350,6 +350,9 @@ class MockApplicationManager : public application_manager::ApplicationManager { MOCK_METHOD2(IsSOStructValid, bool(const hmi_apis::StructIdentifiers::eType struct_id, const smart_objects::SmartObject& display_capabilities)); + MOCK_METHOD1(UnsubscribeAppFromSoftButtons, + bool(const application_manager::commands::MessageSharedPtr + response_message)); MOCK_CONST_METHOD1(IsAppSubscribedForWayPoints, bool(uint32_t)); MOCK_CONST_METHOD1(IsAppSubscribedForWayPoints, bool(application_manager::Application& app));