diff options
37 files changed, 1351 insertions, 236 deletions
diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h index a595fc7379..082bb10ce3 100644 --- a/src/components/application_manager/include/application_manager/application.h +++ b/src/components/application_manager/include/application_manager/application.h @@ -610,6 +610,9 @@ class Application : public virtual InitialApplicationData, virtual void set_mobile_projection_enabled(bool option) = 0; virtual bool mobile_projection_enabled() const = 0; + virtual void set_webengine_projection_enabled(const bool option) = 0; + virtual bool webengine_projection_enabled() const = 0; + virtual bool video_streaming_approved() const = 0; virtual void set_video_streaming_approved(bool state) = 0; virtual bool audio_streaming_approved() const = 0; 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 185d700d58..1e24addf4a 100644 --- a/src/components/application_manager/include/application_manager/application_impl.h +++ b/src/components/application_manager/include/application_manager/application_impl.h @@ -113,7 +113,7 @@ class ApplicationImpl : public virtual Application, inline bool is_navi() const { return is_navi_; } - void set_is_navi(bool allow); + void set_is_navi(bool option); virtual bool is_remote_control_supported() const; @@ -123,6 +123,9 @@ class ApplicationImpl : public virtual Application, bool mobile_projection_enabled() const; + void set_webengine_projection_enabled(const bool option) OVERRIDE; + bool webengine_projection_enabled() const OVERRIDE; + bool video_streaming_approved() const; void set_video_streaming_approved(bool state); bool audio_streaming_approved() const; @@ -143,8 +146,7 @@ class ApplicationImpl : public virtual Application, uint32_t timer_len = 0); virtual bool is_voice_communication_supported() const; - virtual void set_voice_communication_supported( - bool is_voice_communication_supported); + virtual void set_voice_communication_supported(bool option); inline bool app_allowed() const; bool has_been_activated() const; bool set_activated(bool is_active); @@ -184,7 +186,7 @@ class ApplicationImpl : public virtual Application, bool keep_context(); void set_version(const Version& ver); void set_name(const custom_str::CustomString& name); - void set_is_media_application(bool is_media); + void set_is_media_application(bool option); void increment_put_file_in_none_count(); void increment_delete_file_in_none_count(); void increment_list_files_in_none_count(); @@ -565,6 +567,7 @@ class ApplicationImpl : public virtual Application, bool is_navi_; bool is_remote_control_supported_; bool mobile_projection_enabled_; + bool webengine_projection_enabled_; bool video_streaming_approved_; bool audio_streaming_approved_; diff --git a/src/components/application_manager/include/application_manager/commands/command_notification_impl.h b/src/components/application_manager/include/application_manager/commands/command_notification_impl.h index 2274bc5f3b..2f6db37eb8 100644 --- a/src/components/application_manager/include/application_manager/commands/command_notification_impl.h +++ b/src/components/application_manager/include/application_manager/commands/command_notification_impl.h @@ -51,7 +51,14 @@ class CommandNotificationImpl : public CommandImpl { virtual bool Init(); virtual bool CleanUp(); virtual void Run(); - void SendNotification(); + + /** + * @brief SendNotification Constructs the message with Message Type + * Notification and send it to mobile. + * @param final_message if true - connection to mobile will be closed + * after processing this message + */ + void SendNotification(const bool final_message = false); private: DISALLOW_COPY_AND_ASSIGN(CommandNotificationImpl); diff --git a/src/components/application_manager/include/application_manager/state_controller_impl.h b/src/components/application_manager/include/application_manager/state_controller_impl.h index c6121f5d1d..04851d66ab 100644 --- a/src/components/application_manager/include/application_manager/state_controller_impl.h +++ b/src/components/application_manager/include/application_manager/state_controller_impl.h @@ -125,6 +125,8 @@ class StateControllerImpl : public event_engine::EventObserver, void ActivateDefaultWindow(ApplicationSharedPtr app) OVERRIDE; void ExitDefaultWindow(ApplicationSharedPtr app) OVERRIDE; + void DeactivateApp(ApplicationSharedPtr app, + const WindowID window_id) OVERRIDE; private: int64_t RequestHMIStateChange(ApplicationConstSharedPtr app, @@ -274,13 +276,6 @@ class StateControllerImpl : public event_engine::EventObserver, void TempStateStopped(HmiState::StateID ID); /** - * @brief Sets BACKGROUND or LIMITED hmi level to application - * depends on application type - * @param app Application to deactivate - */ - void DeactivateApp(ApplicationSharedPtr app, const WindowID window_id); - - /** * Function to remove temporary HmiState for application */ template <HmiState::StateID ID> diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/on_app_interface_unregistered_notification.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/on_app_interface_unregistered_notification.h index 28508d386c..3f61631948 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/on_app_interface_unregistered_notification.h +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/on_app_interface_unregistered_notification.h @@ -71,6 +71,12 @@ class OnAppInterfaceUnregisteredNotification virtual void Run(); private: + /** + * @brief Check whether a connection to mobile must be closed after sending + * this message + **/ + bool IsFinalMessage() const; + DISALLOW_COPY_AND_ASSIGN(OnAppInterfaceUnregisteredNotification); }; diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/register_app_interface_request.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/register_app_interface_request.h index d59964bbc7..07c32ea5af 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/register_app_interface_request.h +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/register_app_interface_request.h @@ -236,6 +236,30 @@ class RegisterAppInterfaceRequest connection_handler::DeviceHandle* device_id = nullptr, std::string* mac_address = nullptr) const; + /** + * @brief Processes AppHMITypes in the received message from mobile and in the + * policy table + * @param message A message from mobile that could contain AppHMIType + * collection + * @param app_hmi_types_in_policy AppHMITypes that describes in the policy + * table for the app that sent the message + * @return Result of processing + */ + mobile_apis::Result::eType ProcessingAppHMITypesPolicies( + smart_objects::SmartObject& message, + policy::StringArray& app_hmi_types_in_policy); + + /** + * @brief Processes AppHMITypes in the received message + * @param message A message received from the mobile + * @param info Info in a string representation that should be added to the + * response info + * @param log A log in a string represenation that could contain the + * AppHMITypes that are absent in the policy table. + */ + mobile_apis::Result::eType ProcessingAppHMITypesInMessage( + const smart_objects::SmartObject& message); + private: std::string response_info_; mobile_apis::Result::eType result_code_; diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_exit_application_notification.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_exit_application_notification.cc index 3eec6c5d1a..34365c12e5 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_exit_application_notification.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_exit_application_notification.cc @@ -112,6 +112,14 @@ void OnExitApplicationNotification::Run() { break; } #endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT + case Common_ApplicationExitReason::RESOURCE_CONSTRAINT: { + const auto message = + MessageHelper::GetOnAppInterfaceUnregisteredNotificationToMobile( + app_id, AppInterfaceUnregisteredReason::RESOURCE_CONSTRAINT); + SendNotificationToMobile(message); + application_manager_.UnregisterApplication(app_id, Result::SUCCESS); + return; + } default: { LOG4CXX_WARN(logger_, "Unhandled reason"); diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_app_interface_unregistered_notification.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_app_interface_unregistered_notification.cc index 5714043a51..30d9853d97 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_app_interface_unregistered_notification.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_app_interface_unregistered_notification.cc @@ -57,7 +57,15 @@ OnAppInterfaceUnregisteredNotification:: void OnAppInterfaceUnregisteredNotification::Run() { LOG4CXX_AUTO_TRACE(logger_); - SendNotification(); + const bool final_message = IsFinalMessage(); + SendNotification(final_message); +} + +bool OnAppInterfaceUnregisteredNotification::IsFinalMessage() const { + using Reason = mobile_apis::AppInterfaceUnregisteredReason::eType; + const auto reason = static_cast<Reason>( + (*message_)[strings::msg_params][strings::reason].asInt()); + return Reason::RESOURCE_CONSTRAINT == reason; } } // namespace commands } // namespace sdl_rpc_plugin diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc index 70bd47e232..bd36f060ed 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc @@ -81,6 +81,8 @@ mobile_apis::AppHMIType::eType StringToAppHMIType(const std::string& str) { return mobile_apis::AppHMIType::PROJECTION; } else if ("REMOTE_CONTROL" == str) { return mobile_apis::AppHMIType::REMOTE_CONTROL; + } else if ("WEB_VIEW" == str) { + return mobile_apis::AppHMIType::WEB_VIEW; } else { return mobile_apis::AppHMIType::INVALID_ENUM; } @@ -99,7 +101,8 @@ std::string AppHMITypeToString(mobile_apis::AppHMIType::eType type) { {mobile_apis::AppHMIType::BACKGROUND_PROCESS, "BACKGROUND_PROCESS"}, {mobile_apis::AppHMIType::TESTING, "TESTING"}, {mobile_apis::AppHMIType::SYSTEM, "SYSTEM"}, - {mobile_apis::AppHMIType::PROJECTION, "PROJECTION"}}; + {mobile_apis::AppHMIType::PROJECTION, "PROJECTION"}, + {mobile_apis::AppHMIType::WEB_VIEW, "WEB_VIEW"}}; std::map<mobile_apis::AppHMIType::eType, std::string>::const_iterator iter = app_hmi_type_map.find(type); @@ -293,7 +296,7 @@ void RegisterAppInterfaceRequest::Run() { policy_result, mobile_apis::Result::SUCCESS, mobile_apis::Result::WARNINGS)) { - SendResponse(false, policy_result); + SendResponse(false, policy_result, response_info_.c_str()); return; } @@ -481,6 +484,10 @@ void RegisterAppInterfaceRequest::Run() { application->set_remote_control_supported(true); break; } + case mobile_apis::AppHMIType::WEB_VIEW: { + application->set_webengine_projection_enabled(true); + break; + } default: {} } } @@ -1140,14 +1147,14 @@ mobile_apis::Result::eType RegisterAppInterfaceRequest::CheckWithPolicyData() { return mobile_apis::Result::WARNINGS; } - smart_objects::SmartObject& message = *message_; + auto& message = *message_; policy::StringArray app_nicknames; - policy::StringArray app_hmi_types; + policy::StringArray app_hmi_types_in_policy; const std::string mobile_app_id = application_manager_.GetCorrectMobileIDFromMessage(message_); const bool init_result = GetPolicyHandler().GetInitialAppData( - mobile_app_id, &app_nicknames, &app_hmi_types); + mobile_app_id, &app_nicknames, &app_hmi_types_in_policy); if (!init_result) { LOG4CXX_ERROR(logger_, "Error during initial application data check."); @@ -1173,36 +1180,20 @@ mobile_apis::Result::eType RegisterAppInterfaceRequest::CheckWithPolicyData() { } } - mobile_apis::Result::eType result = mobile_apis::Result::SUCCESS; + auto result = mobile_apis::Result::SUCCESS; // If AppHMIType is not included in policy - allow any type - if (!app_hmi_types.empty()) { - if (message[strings::msg_params].keyExists(strings::app_hmi_type)) { - // If AppHmiTypes are partially same, the system should allow those listed - // in the policy table and send warning info on missed values - smart_objects::SmartArray app_types = - *(message[strings::msg_params][strings::app_hmi_type].asArray()); - - std::string log; - CheckMissedTypes checker(app_hmi_types, log); - std::for_each(app_types.begin(), app_types.end(), checker); - if (!log.empty()) { - response_info_ = - "Following AppHmiTypes are not present in policy " - "table:" + - log; - result_code_ = mobile_apis::Result::WARNINGS; - } + if (!app_hmi_types_in_policy.empty()) { + result = ProcessingAppHMITypesPolicies(message, app_hmi_types_in_policy); + } else { + result = ProcessingAppHMITypesInMessage(message); + if (mobile_apis::Result::DISALLOWED == result) { + response_info_ = + "WEB_VIEW AppHmiType is absent in application policies, because they " + "are empty"; + LOG4CXX_DEBUG(logger_, response_info_); + return result; } - // Replace AppHmiTypes in request with values allowed by policy table - message[strings::msg_params][strings::app_hmi_type] = - smart_objects::SmartObject(smart_objects::SmartType_Array); - - smart_objects::SmartObject& app_hmi_type = - message[strings::msg_params][strings::app_hmi_type]; - - AppHMITypeInserter inserter(app_hmi_type); - std::for_each(app_hmi_types.begin(), app_hmi_types.end(), inserter); } return result; @@ -1540,6 +1531,81 @@ bool RegisterAppInterfaceRequest::GetDataOnSessionKey( return true; } +mobile_apis::Result::eType +RegisterAppInterfaceRequest::ProcessingAppHMITypesInMessage( + const smart_objects::SmartObject& message) { + const bool app_hmi_types_exist = + message[strings::msg_params].keyExists(strings::app_hmi_type); + + const auto result = mobile_apis::Result::SUCCESS; + + if (!app_hmi_types_exist) { + return result; + } + + auto app_types_in_message = + *(message[strings::msg_params][strings::app_hmi_type].asArray()); + + auto it = std::find(app_types_in_message.begin(), + app_types_in_message.end(), + mobile_apis::AppHMIType::WEB_VIEW); + if (app_types_in_message.end() != it) { + return mobile_apis::Result::DISALLOWED; + } + + return result; +} + +mobile_apis::Result::eType +RegisterAppInterfaceRequest::ProcessingAppHMITypesPolicies( + smart_objects::SmartObject& message, + policy::StringArray& app_hmi_types_in_policy) { + auto result = mobile_apis::Result::SUCCESS; + const bool app_hmi_types_exist = + message[strings::msg_params].keyExists(strings::app_hmi_type); + + if (app_hmi_types_exist) { + // If AppHmiTypes are partially same, the system should allow those listed + // in the policy table and send warning info on missed values + auto app_types_in_message = + *(message[strings::msg_params][strings::app_hmi_type].asArray()); + + std::string log; + CheckMissedTypes checker(app_hmi_types_in_policy, log); + std::for_each( + app_types_in_message.begin(), app_types_in_message.end(), checker); + if (!log.empty()) { + result = log.find("WEB_VIEW") != std::string::npos + ? mobile_apis::Result::DISALLOWED + : mobile_apis::Result::WARNINGS; + + if (mobile_apis::Result::DISALLOWED == result) { + response_info_ = + "WEB_VIEW AppHmiType is absent in application policies"; + LOG4CXX_DEBUG(logger_, response_info_); + return result; + } + + response_info_ = + "Following AppHmiTypes are not present in policy " + "table:" + + log; + result_code_ = mobile_apis::Result::WARNINGS; + } + } + // Replace AppHmiTypes in request with values allowed by policy table + message[strings::msg_params][strings::app_hmi_type] = + smart_objects::SmartObject(smart_objects::SmartType_Array); + + auto& app_hmi_type = message[strings::msg_params][strings::app_hmi_type]; + + AppHMITypeInserter inserter(app_hmi_type); + std::for_each( + app_hmi_types_in_policy.begin(), app_hmi_types_in_policy.end(), inserter); + + return result; +} + policy::PolicyHandlerInterface& RegisterAppInterfaceRequest::GetPolicyHandler() { return policy_handler_; diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/hmi_notifications_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/hmi_notifications_test.cc index cbb27bffb2..634f0d0ef2 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/hmi_notifications_test.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/hmi_notifications_test.cc @@ -257,6 +257,8 @@ class HMICommandsNotificationsTest ON_CALL(app_mngr_, application(kConnectionKey)).WillByDefault(Return(app_)); ON_CALL(mock_message_helper_, MobileLanguageToString(kMobileLanguage)) .WillByDefault(Return(kDefaultLanguage)); + ON_CALL(app_mngr_, connection_handler()) + .WillByDefault(ReturnRef(mock_connection_handler_)); } am::ApplicationSharedPtr ConfigureApp(NiceMock<MockApplication>** app_mock, @@ -1025,18 +1027,17 @@ TEST_F(HMICommandsNotificationsTest, static_cast<int32_t>(am::MessageType::kNotification); (*notification)[am::strings::params][am::strings::connection_key] = kAppId_; - std::vector<hmi_apis::Common_ApplicationExitReason::eType> reason_list; - reason_list.push_back(hmi_apis::Common_ApplicationExitReason:: - UNAUTHORIZED_TRANSPORT_REGISTRATION); - reason_list.push_back( - hmi_apis::Common_ApplicationExitReason::UNSUPPORTED_HMI_RESOURCE); - - std::vector<mobile_apis::AppInterfaceUnregisteredReason::eType> - mobile_reason_list; - mobile_reason_list.push_back( - mobile_apis::AppInterfaceUnregisteredReason::APP_UNAUTHORIZED); - mobile_reason_list.push_back( - mobile_apis::AppInterfaceUnregisteredReason::UNSUPPORTED_HMI_RESOURCE); + using ExitReason = hmi_apis::Common_ApplicationExitReason::eType; + std::vector<ExitReason> reason_list = { + ExitReason::UNAUTHORIZED_TRANSPORT_REGISTRATION, + ExitReason::UNSUPPORTED_HMI_RESOURCE, + ExitReason::RESOURCE_CONSTRAINT}; + + using UnregisteredReason = mobile_apis::AppInterfaceUnregisteredReason::eType; + std::vector<UnregisteredReason> mobile_reason_list = { + UnregisteredReason::APP_UNAUTHORIZED, + UnregisteredReason::UNSUPPORTED_HMI_RESOURCE, + UnregisteredReason::RESOURCE_CONSTRAINT}; std::vector<mobile_apis::AppInterfaceUnregisteredReason::eType>::iterator it_mobile_reason = mobile_reason_list.begin(); diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_app_interface_unregistered_notification_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_app_interface_unregistered_notification_test.cc new file mode 100644 index 0000000000..64dcec2e0a --- /dev/null +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_app_interface_unregistered_notification_test.cc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2020, 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 "mobile/on_app_interface_unregistered_notification.h" + +#include <utility> + +#include "gtest/gtest.h" + +#include "application_manager/commands/commands_test.h" +#include "application_manager/smart_object_keys.h" +#include "interfaces/MOBILE_API.h" +#include "smart_objects/smart_object.h" + +namespace test { +namespace components { +namespace commands_test { +namespace mobile_commands_test { +namespace on_app_interface_unregistered_notification_test { + +namespace am = ::application_manager; + +using sdl_rpc_plugin::commands::OnAppInterfaceUnregisteredNotification; +using Reason = mobile_apis::AppInterfaceUnregisteredReason::eType; +using ::testing::Return; + +namespace { +const uint32_t kAppId = 1u; +typedef std::shared_ptr<MockApplication> MockAppPtr; +} // namespace + +const auto retrieve_data_to_check = [](const smart_objects::SmartObject& so) { + return std::make_pair( + so[am::strings::params][am::strings::connection_key].asUInt(), + so[am::strings::msg_params][am::strings::reason].asInt()); +}; + +MATCHER_P(CheckMessageData, initial_data, "") { + return retrieve_data_to_check(*arg) == initial_data; +} + +class OnAppInterfaceUnregisteredNotificationTest + : public CommandsTest<CommandsTestMocks::kIsNice> { + public: + OnAppInterfaceUnregisteredNotificationTest() + : message_(CreateMessage()), command_(), mock_app_(CreateMockApp()) { + (*message_)[am::strings::params][am::strings::connection_key] = kAppId; + ON_CALL(app_mngr_, application(kAppId)).WillByDefault(Return(mock_app_)); + CommandsTest<CommandsTestMocks::kIsNice>::InitCommand(kDefaultTimeout_); + command_.reset( + new OnAppInterfaceUnregisteredNotification(message_, + app_mngr_, + mock_rpc_service_, + mock_hmi_capabilities_, + mock_policy_handler_)); + } + + void CheckResponseParameters(const bool is_wep_mode_enabled, + const bool is_final_message) { + ON_CALL(*mock_app_, webengine_projection_enabled()) + .WillByDefault(Return(is_wep_mode_enabled)); + + const auto initial_data = retrieve_data_to_check(*message_); + EXPECT_CALL( + mock_rpc_service_, + SendMessageToMobile(CheckMessageData(initial_data), is_final_message)); + } + + am::commands::MessageSharedPtr message_; + std::unique_ptr<OnAppInterfaceUnregisteredNotification> command_; + MockAppPtr mock_app_; +}; + +TEST_F(OnAppInterfaceUnregisteredNotificationTest, + Run_AnyReasonButResourceConstraint_NonFinalMessageSent) { + (*message_)[am::strings::msg_params][am::strings::reason] = + Reason::IGNITION_OFF; + + CheckResponseParameters(true, false); + + ASSERT_TRUE(command_->Init()); + command_->Run(); +} + +TEST_F(OnAppInterfaceUnregisteredNotificationTest, + Run_ResourceConstraintForNonWebApp_NonFinalMessageSent) { + (*message_)[am::strings::msg_params][am::strings::reason] = + Reason::RESOURCE_CONSTRAINT; + + CheckResponseParameters(false, true); + + ASSERT_TRUE(command_->Init()); + command_->Run(); +} + +TEST_F(OnAppInterfaceUnregisteredNotificationTest, + Run_ResourceConstraintForWebApp_FinalMessageSent) { + (*message_)[am::strings::msg_params][am::strings::reason] = + Reason::RESOURCE_CONSTRAINT; + + CheckResponseParameters(true, true); + + ASSERT_TRUE(command_->Init()); + command_->Run(); +} + +} // namespace on_app_interface_unregistered_notification_test +} // namespace mobile_commands_test +} // namespace commands_test +} // namespace components +} // namespace test diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/register_app_interface_request_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/register_app_interface_request_test.cc index a42aa61400..1be3243cc2 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/register_app_interface_request_test.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/register_app_interface_request_test.cc @@ -93,6 +93,7 @@ const std::string kFullAppId = "test_app_id_long"; const std::string kDummyString = "test_string"; const std::vector<uint32_t> kDummyDiagModes; const utils::SemanticVersion mock_semantic_version(1, 0, 0); +const connection_handler::DeviceHandle kHandle = 1; } // namespace class RegisterAppInterfaceRequestTest @@ -107,7 +108,8 @@ class RegisterAppInterfaceRequestTest , pending_lock_ptr_(std::make_shared<sync_primitives::Lock>()) , mock_application_helper_( application_manager_test::MockApplicationHelper:: - application_helper_mock()) { + application_helper_mock()) + , notify_upd_manager_(std::make_shared<utils::CallNothing>()) { InitGetters(); InitLanguage(); } @@ -285,6 +287,51 @@ class RegisterAppInterfaceRequestTest mock_app))); } + void SetCommonPreconditionsToRegisterApplication() { + ON_CALL(app_mngr_, IsApplicationForbidden(_, _)) + .WillByDefault(Return(false)); + ON_CALL(mock_connection_handler_, + GetDataOnSessionKey(kConnectionKey, _, _, _)) + .WillByDefault(DoAll(SetArgPointee<3>(kDeviceHandle), Return(0))); + ON_CALL(mock_session_observer_, + GetDataOnDeviceID(kDeviceHandle, _, _, _, _)) + .WillByDefault(DoAll(SetArgPointee<3>(kMacAddress1), Return(0))); + ON_CALL(app_mngr_, reregister_application_by_policy_id(kAppId1)) + .WillByDefault(Return(ApplicationSharedPtr())); + ON_CALL(app_mngr_, application(kMacAddress1, kAppId1)) + .WillByDefault(Return(ApplicationSharedPtr())); + ON_CALL(app_mngr_, applications()) + .WillByDefault( + Return(DataAccessor<am::ApplicationSet>(app_set_, lock_ptr_))); + ON_CALL(app_mngr_, pending_applications()) + .WillByDefault(Return(DataAccessor<am::AppsWaitRegistrationSet>( + pending_app_set_, pending_lock_ptr_))); + ON_CALL(mock_policy_handler_, PolicyEnabled()).WillByDefault(Return(true)); + ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) + .WillByDefault(Return(true)); + ON_CALL(mock_rpc_service_, + ManageHMICommand( + HMIResultCodeIs( + hmi_apis::FunctionID::BasicCommunication_OnAppRegistered), + _)) + .WillByDefault(Return(true)); + ON_CALL( + mock_rpc_service_, + ManageHMICommand( + HMIResultCodeIs(hmi_apis::FunctionID::Buttons_OnButtonSubscription), + _)) + .WillByDefault(Return(true)); + } + + void SetCommonPreconditionsToCheckWithPolicyData(MockAppPtr mock_app) { + ON_CALL(mock_policy_handler_, AddApplication(kMacAddress1, kAppId1, _)) + .WillByDefault(Return(notify_upd_manager_)); + ON_CALL(app_mngr_, application(kConnectionKey)) + .WillByDefault(Return(mock_app)); + ON_CALL(app_mngr_, RegisterApplication(msg_)) + .WillByDefault(Return(mock_app)); + } + MessageSharedPtr msg_; std::shared_ptr<RegisterAppInterfaceRequest> command_; @@ -314,6 +361,7 @@ class RegisterAppInterfaceRequestTest MockConnectionHandler mock_connection_handler_; MockSessionObserver mock_session_observer_; application_manager_test::MockApplicationHelper& mock_application_helper_; + policy::StatusNotifier notify_upd_manager_; }; TEST_F(RegisterAppInterfaceRequestTest, Init_SUCCESS) { @@ -331,11 +379,10 @@ TEST_F(RegisterAppInterfaceRequestTest, Run_MinimalData_SUCCESS) { EXPECT_CALL(app_mngr_, updateRequestTimeout(_, _, _)); EXPECT_CALL(app_mngr_, IsApplicationForbidden(_, _)).WillOnce(Return(false)); - connection_handler::DeviceHandle handle = 1; ON_CALL(mock_connection_handler_, GetDataOnSessionKey(kConnectionKey, _, _, _)) - .WillByDefault(DoAll(SetArgPointee<3>(handle), Return(0))); - ON_CALL(mock_session_observer_, GetDataOnDeviceID(handle, _, _, _, _)) + .WillByDefault(DoAll(SetArgPointee<3>(kHandle), Return(0))); + ON_CALL(mock_session_observer_, GetDataOnDeviceID(kHandle, _, _, _, _)) .WillByDefault(DoAll(SetArgPointee<3>(kMacAddress1), Return(0))); MockAppPtr mock_app = CreateBasicMockedApp(); @@ -357,10 +404,8 @@ TEST_F(RegisterAppInterfaceRequestTest, Run_MinimalData_SUCCESS) { ON_CALL(mock_policy_handler_, PolicyEnabled()).WillByDefault(Return(true)); ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) .WillByDefault(Return(true)); - policy::StatusNotifier notify_upd_manager = - std::make_shared<utils::CallNothing>(); ON_CALL(mock_policy_handler_, AddApplication(kMacAddress1, kAppId1, _)) - .WillByDefault(Return(notify_upd_manager)); + .WillByDefault(Return(notify_upd_manager_)); EXPECT_CALL(app_mngr_, RegisterApplication(msg_)).WillOnce(Return(mock_app)); @@ -418,10 +463,9 @@ TEST_F(RegisterAppInterfaceRequestTest, EXPECT_CALL(app_mngr_, updateRequestTimeout(_, _, _)); EXPECT_CALL(app_mngr_, IsApplicationForbidden(_, _)).WillOnce(Return(false)); - connection_handler::DeviceHandle handle = 1; ON_CALL(mock_connection_handler_, GetDataOnSessionKey(kConnectionKey, _, _, _)) - .WillByDefault(DoAll(SetArgPointee<3>(handle), Return(0))); + .WillByDefault(DoAll(SetArgPointee<3>(kHandle), Return(0))); ON_CALL(mock_session_observer_, GetDataOnDeviceID(_, _, _, _, _)) .WillByDefault(DoAll(SetArgPointee<3>(kMacAddress1), Return(0))); @@ -480,10 +524,8 @@ TEST_F(RegisterAppInterfaceRequestTest, ON_CALL(mock_policy_handler_, PolicyEnabled()).WillByDefault(Return(true)); ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) .WillByDefault(Return(true)); - policy::StatusNotifier notify_upd_manager = - std::make_shared<utils::CallNothing>(); ON_CALL(mock_policy_handler_, AddApplication(kMacAddress1, kAppId1, _)) - .WillByDefault(Return(notify_upd_manager)); + .WillByDefault(Return(notify_upd_manager_)); EXPECT_CALL(app_mngr_, RegisterApplication(msg_)).WillOnce(Return(mock_app)); @@ -745,10 +787,8 @@ TEST_F(RegisterAppInterfaceRequestTest, ON_CALL(mock_policy_handler_, PolicyEnabled()).WillByDefault(Return(true)); ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) .WillByDefault(Return(true)); - policy::StatusNotifier notify_upd_manager = - std::make_shared<utils::CallNothing>(); ON_CALL(mock_policy_handler_, AddApplication(kMacAddress2, kAppId1, _)) - .WillByDefault(Return(notify_upd_manager)); + .WillByDefault(Return(notify_upd_manager_)); EXPECT_CALL(app_mngr_, RegisterApplication(msg_)).WillOnce(Return(mock_app2)); @@ -791,6 +831,264 @@ TEST_F(RegisterAppInterfaceRequestTest, command_->Run(); } +TEST_F(RegisterAppInterfaceRequestTest, + RegisterAppWith_WEB_VIEW_HMITypeSuccess) { + SetCommonPreconditionsToRegisterApplication(); + + InitBasicMessage(); + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][0] = + mobile_apis::AppHMIType::WEB_VIEW; + + MockAppPtr mock_app = CreateBasicMockedApp(); + SetCommonPreconditionsToCheckWithPolicyData(mock_app); + std::vector<std::string> present_hmi_types_in_policy{"WEB_VIEW"}; + ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) + .WillByDefault( + DoAll(SetArgPointee<2>(present_hmi_types_in_policy), Return(true))); + + auto app = std::static_pointer_cast<am::Application>(mock_app); + + EXPECT_CALL(*mock_app, set_webengine_projection_enabled(true)); + EXPECT_CALL(app_mngr_, OnApplicationRegistered(app)); + EXPECT_CALL(mock_policy_handler_, + OnAppRegisteredOnMobile(kMacAddress1, kAppId1)); + EXPECT_CALL(mock_rpc_service_, + ManageMobileCommand(_, am::commands::Command::SOURCE_SDL)) + .Times(2); + EXPECT_CALL(app_mngr_, SendDriverDistractionState(app)); + + ASSERT_TRUE(command_->Init()); + command_->Run(); +} + +TEST_F(RegisterAppInterfaceRequestTest, + RegisterApp_WithoutAppHMITypes_SuccessfulRegistration) { + SetCommonPreconditionsToRegisterApplication(); + InitBasicMessage(); + + MockAppPtr mock_app = CreateBasicMockedApp(); + SetCommonPreconditionsToCheckWithPolicyData(mock_app); + std::vector<std::string> present_hmi_types_in_policy{"NAVIGATION"}; + ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) + .WillByDefault( + DoAll(SetArgPointee<2>(present_hmi_types_in_policy), Return(true))); + + auto response_to_mobile = CreateMessage(); + EXPECT_CALL( + mock_rpc_service_, + ManageMobileCommand(_, am::commands::Command::CommandSource::SOURCE_SDL)) + .WillOnce(DoAll(SaveArg<0>(&response_to_mobile), Return(true))) + .WillOnce(Return(true)); + + ASSERT_TRUE(command_->Init()); + command_->Run(); + + const auto result_code = static_cast<mobile_apis::Result::eType>( + (*response_to_mobile)[am::strings::msg_params][am::strings::result_code] + .asUInt()); + + EXPECT_EQ(mobile_apis::Result::SUCCESS, result_code); +} + +TEST_F( + RegisterAppInterfaceRequestTest, + RegisterAppInterface_AppHMITypesDontExistInPTForSpecifiedApp_SuccessfulRegistration) { + SetCommonPreconditionsToRegisterApplication(); + InitBasicMessage(); + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][0] = + mobile_apis::AppHMIType::PROJECTION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][1] = + mobile_apis::AppHMIType::INFORMATION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][2] = + mobile_apis::AppHMIType::COMMUNICATION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][3] = + mobile_apis::AppHMIType::NAVIGATION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][4] = + mobile_apis::AppHMIType::MESSAGING; + + MockAppPtr mock_app = CreateBasicMockedApp(); + SetCommonPreconditionsToCheckWithPolicyData(mock_app); + std::vector<std::string> present_hmi_types_in_policy; + ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) + .WillByDefault( + DoAll(SetArgPointee<2>(present_hmi_types_in_policy), Return(true))); + + auto response_to_mobile = CreateMessage(); + EXPECT_CALL( + mock_rpc_service_, + ManageMobileCommand(_, am::commands::Command::CommandSource::SOURCE_SDL)) + .WillOnce(DoAll(SaveArg<0>(&response_to_mobile), Return(true))) + .WillOnce(Return(true)); + + ASSERT_TRUE(command_->Init()); + command_->Run(); + + const auto result_code = static_cast<mobile_apis::Result::eType>( + (*response_to_mobile)[am::strings::msg_params][am::strings::result_code] + .asUInt()); + EXPECT_EQ(mobile_apis::Result::SUCCESS, result_code); +} + +TEST_F( + RegisterAppInterfaceRequestTest, + RegisterApp_AppHMITypeNotCoincidedWithCurrentNonEmptyDataStoredInPT_SuccessfulRegistrationWithWarning) { + SetCommonPreconditionsToRegisterApplication(); + InitBasicMessage(); + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][0] = + mobile_apis::AppHMIType::PROJECTION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][1] = + mobile_apis::AppHMIType::INFORMATION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][2] = + mobile_apis::AppHMIType::COMMUNICATION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][3] = + mobile_apis::AppHMIType::NAVIGATION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][4] = + mobile_apis::AppHMIType::MESSAGING; + + MockAppPtr mock_app = CreateBasicMockedApp(); + SetCommonPreconditionsToCheckWithPolicyData(mock_app); + std::vector<std::string> present_hmi_types_in_policy{"NAVIGATION"}; + ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) + .WillByDefault( + DoAll(SetArgPointee<2>(present_hmi_types_in_policy), Return(true))); + + auto response_to_mobile = CreateMessage(); + EXPECT_CALL( + mock_rpc_service_, + ManageMobileCommand(_, am::commands::Command::CommandSource::SOURCE_SDL)) + .WillOnce(DoAll(SaveArg<0>(&response_to_mobile), Return(true))) + .WillOnce(Return(true)); + + ASSERT_TRUE(command_->Init()); + command_->Run(); + + const auto result_code = static_cast<mobile_apis::Result::eType>( + (*response_to_mobile)[am::strings::msg_params][am::strings::result_code] + .asUInt()); + EXPECT_EQ(mobile_apis::Result::WARNINGS, result_code); + + // Regarding to requairements, response info string should contain all + // AppHMITypes that are not contained in the policy table. + std::vector<std::string> expected_app_hmi_types_in_info_string{ + "PROJECTION", "INFORMATION", "COMMUNICATION", "MESSAGING"}; + + const std::string info_string_in_response = + (*response_to_mobile)[am::strings::msg_params][am::strings::info] + .asString(); + + for (const auto& app_hmi_type : expected_app_hmi_types_in_info_string) { + EXPECT_TRUE(info_string_in_response.find(app_hmi_type) != std::string::npos) + << "AppHMItype absent in the response string: " << app_hmi_type; + } +} + +TEST_F(RegisterAppInterfaceRequestTest, + RegisterAppWithWebView_WebViewNotAllowedInPT_RejectRegistration) { + SetCommonPreconditionsToRegisterApplication(); + InitBasicMessage(); + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][0] = + mobile_apis::AppHMIType::WEB_VIEW; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][1] = + mobile_apis::AppHMIType::INFORMATION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][2] = + mobile_apis::AppHMIType::COMMUNICATION; + + MockAppPtr mock_app = CreateBasicMockedApp(); + SetCommonPreconditionsToCheckWithPolicyData(mock_app); + std::vector<std::string> present_hmi_types_in_policy{"INFORMATION", + "COMMUNICATION"}; + ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) + .WillByDefault( + DoAll(SetArgPointee<2>(present_hmi_types_in_policy), Return(true))); + + EXPECT_CALL(*mock_app, set_webengine_projection_enabled(true)).Times(0); + + auto response_to_mobile = CreateMessage(); + EXPECT_CALL( + mock_rpc_service_, + ManageMobileCommand(_, am::commands::Command::CommandSource::SOURCE_SDL)) + .WillOnce(DoAll(SaveArg<0>(&response_to_mobile), Return(true))); + + ASSERT_TRUE(command_->Init()); + command_->Run(); + + const auto result_code = static_cast<mobile_apis::Result::eType>( + (*response_to_mobile)[am::strings::msg_params][am::strings::result_code] + .asUInt()); + + EXPECT_EQ(mobile_apis::Result::DISALLOWED, result_code); +} + +TEST_F(RegisterAppInterfaceRequestTest, + RegisterAppWithWebView_EmptyPT_RejectRegistration) { + SetCommonPreconditionsToRegisterApplication(); + InitBasicMessage(); + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][0] = + mobile_apis::AppHMIType::PROJECTION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][1] = + mobile_apis::AppHMIType::INFORMATION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][2] = + mobile_apis::AppHMIType::WEB_VIEW; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][3] = + mobile_apis::AppHMIType::NAVIGATION; + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][4] = + mobile_apis::AppHMIType::MESSAGING; + + MockAppPtr mock_app = CreateBasicMockedApp(); + SetCommonPreconditionsToCheckWithPolicyData(mock_app); + std::vector<std::string> present_hmi_types_in_policy; + ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) + .WillByDefault( + DoAll(SetArgPointee<2>(present_hmi_types_in_policy), Return(true))); + + auto response_to_mobile = CreateMessage(); + EXPECT_CALL( + mock_rpc_service_, + ManageMobileCommand(_, am::commands::Command::CommandSource::SOURCE_SDL)) + .WillOnce(DoAll(SaveArg<0>(&response_to_mobile), Return(true))); + + ASSERT_TRUE(command_->Init()); + command_->Run(); + + const auto result_code = static_cast<mobile_apis::Result::eType>( + (*response_to_mobile)[am::strings::msg_params][am::strings::result_code] + .asUInt()); + EXPECT_EQ(mobile_apis::Result::DISALLOWED, result_code); +} + +TEST_F(RegisterAppInterfaceRequestTest, + RegisterAppWithWebViewOnly_WebViewNotAllowedInPT_RejectRegistration) { + SetCommonPreconditionsToRegisterApplication(); + InitBasicMessage(); + (*msg_)[am::strings::msg_params][am::strings::app_hmi_type][0] = + mobile_apis::AppHMIType::WEB_VIEW; + + MockAppPtr mock_app = CreateBasicMockedApp(); + SetCommonPreconditionsToCheckWithPolicyData(mock_app); + std::vector<std::string> present_hmi_types_in_policy{"INFORMATION", + "COMMUNICATION"}; + ON_CALL(mock_policy_handler_, GetInitialAppData(kAppId1, _, _)) + .WillByDefault( + DoAll(SetArgPointee<2>(present_hmi_types_in_policy), Return(true))); + + EXPECT_CALL(*mock_app, set_webengine_projection_enabled(true)).Times(0); + + auto response_to_mobile = CreateMessage(); + EXPECT_CALL( + mock_rpc_service_, + ManageMobileCommand(_, am::commands::Command::CommandSource::SOURCE_SDL)) + .WillOnce(DoAll(SaveArg<0>(&response_to_mobile), Return(true))); + + ASSERT_TRUE(command_->Init()); + command_->Run(); + + const auto result_code = static_cast<mobile_apis::Result::eType>( + (*response_to_mobile)[am::strings::msg_params][am::strings::result_code] + .asUInt()); + + EXPECT_EQ(mobile_apis::Result::DISALLOWED, result_code); +} + } // namespace register_app_interface_request } // namespace mobile_commands_test } // namespace commands_test diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/simple_notification_commands_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/simple_notification_commands_test.cc index 6e85aff281..e31f6d209d 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/simple_notification_commands_test.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/simple_notification_commands_test.cc @@ -39,7 +39,6 @@ #include "application_manager/commands/commands_test.h" #include "application_manager/mock_message_helper.h" #include "application_manager/smart_object_keys.h" -#include "mobile/on_app_interface_unregistered_notification.h" #include "mobile/on_audio_pass_thru_notification.h" #include "mobile/on_driver_distraction_notification.h" #include "mobile/on_language_change_notification.h" @@ -66,8 +65,7 @@ class MobileNotificationCommandsTest typedef Command CommandType; }; -typedef Types<commands::OnAppInterfaceUnregisteredNotification, - commands::OnAudioPassThruNotification, +typedef Types<commands::OnAudioPassThruNotification, commands::OnLanguageChangeNotification, commands::OnPermissionsChangeNotification, commands::mobile::OnDriverDistractionNotification> diff --git a/src/components/application_manager/src/application_impl.cc b/src/components/application_manager/src/application_impl.cc index c595f8ecf9..27c7411d15 100644 --- a/src/components/application_manager/src/application_impl.cc +++ b/src/components/application_manager/src/application_impl.cc @@ -106,6 +106,7 @@ ApplicationImpl::ApplicationImpl( , is_navi_(false) , is_remote_control_supported_(false) , mobile_projection_enabled_(false) + , webengine_projection_enabled_(false) , video_streaming_approved_(false) , audio_streaming_approved_(false) , video_streaming_allowed_(false) @@ -199,33 +200,39 @@ bool ApplicationImpl::is_audio() const { } void ApplicationImpl::ChangeSupportingAppHMIType() { - is_navi_ = false; - is_voice_communication_application_ = false; - mobile_projection_enabled_ = false; + set_is_navi(false); + set_voice_communication_supported(false); + set_mobile_projection_enabled(false); + set_webengine_projection_enabled(false); const smart_objects::SmartObject& array_app_types = *app_types_; uint32_t lenght_app_types = array_app_types.length(); for (uint32_t i = 0; i < lenght_app_types; ++i) { - if (mobile_apis::AppHMIType::NAVIGATION == - static_cast<mobile_apis::AppHMIType::eType>( - array_app_types[i].asUInt())) { - is_navi_ = true; - } - if (mobile_apis::AppHMIType::COMMUNICATION == - static_cast<mobile_apis::AppHMIType::eType>( - array_app_types[i].asUInt())) { - is_voice_communication_application_ = true; - } - if (mobile_apis::AppHMIType::PROJECTION == - static_cast<mobile_apis::AppHMIType::eType>( - array_app_types[i].asUInt())) { - mobile_projection_enabled_ = true; + const auto app_hmi_type = static_cast<mobile_apis::AppHMIType::eType>( + array_app_types[i].asUInt()); + + switch (app_hmi_type) { + case mobile_apis::AppHMIType::NAVIGATION: + set_is_navi(true); + break; + case mobile_apis::AppHMIType::COMMUNICATION: + set_voice_communication_supported(true); + break; + case mobile_apis::AppHMIType::PROJECTION: + set_mobile_projection_enabled(true); + break; + case mobile_apis::AppHMIType::WEB_VIEW: + set_webengine_projection_enabled(true); + break; + default: + break; } } } -void ApplicationImpl::set_is_navi(bool allow) { - is_navi_ = allow; +void ApplicationImpl::set_is_navi(bool option) { + LOG4CXX_TRACE(logger_, "option " << std::boolalpha << option); + is_navi_ = option; } bool ApplicationImpl::is_remote_control_supported() const { @@ -240,9 +247,9 @@ bool ApplicationImpl::is_voice_communication_supported() const { return is_voice_communication_application_; } -void ApplicationImpl::set_voice_communication_supported( - bool is_voice_communication_supported) { - is_voice_communication_application_ = is_voice_communication_supported; +void ApplicationImpl::set_voice_communication_supported(bool option) { + LOG4CXX_TRACE(logger_, "option " << std::boolalpha << option); + is_voice_communication_application_ = option; } bool ApplicationImpl::IsAudioApplication() const { @@ -286,7 +293,7 @@ void ApplicationImpl::SetPostponedState(const WindowID window_id, } void ApplicationImpl::set_mobile_projection_enabled(bool option) { - LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_TRACE(logger_, "option " << std::boolalpha << option); mobile_projection_enabled_ = option; } @@ -294,6 +301,15 @@ bool ApplicationImpl::mobile_projection_enabled() const { return mobile_projection_enabled_; } +void ApplicationImpl::set_webengine_projection_enabled(const bool option) { + LOG4CXX_TRACE(logger_, "option " << std::boolalpha << option); + webengine_projection_enabled_ = option; +} + +bool ApplicationImpl::webengine_projection_enabled() const { + return webengine_projection_enabled_; +} + struct StateIDComparator { HmiState::StateID state_id_; StateIDComparator(HmiState::StateID state_id) : state_id_(state_id) {} @@ -457,8 +473,9 @@ void ApplicationImpl::set_name(const custom_str::CustomString& name) { app_name_ = name; } -void ApplicationImpl::set_is_media_application(bool is_media) { - is_media_ = is_media; +void ApplicationImpl::set_is_media_application(bool option) { + LOG4CXX_TRACE(logger_, "option " << std::boolalpha << option); + is_media_ = option; } bool IsTTSState(const HmiStatePtr state) { diff --git a/src/components/application_manager/src/commands/command_notification_impl.cc b/src/components/application_manager/src/commands/command_notification_impl.cc index cc2606ab6f..31bea114ec 100644 --- a/src/components/application_manager/src/commands/command_notification_impl.cc +++ b/src/components/application_manager/src/commands/command_notification_impl.cc @@ -63,16 +63,18 @@ bool CommandNotificationImpl::CleanUp() { void CommandNotificationImpl::Run() {} -void CommandNotificationImpl::SendNotification() { +void CommandNotificationImpl::SendNotification(const bool final_message) { (*message_)[strings::params][strings::protocol_type] = mobile_protocol_type_; (*message_)[strings::params][strings::protocol_version] = protocol_version_; (*message_)[strings::params][strings::message_type] = static_cast<int32_t>(application_manager::MessageType::kNotification); - LOG4CXX_INFO(logger_, "SendNotification"); + LOG4CXX_INFO( + logger_, + "SendNotification: final_message = " << std::boolalpha << final_message); MessageHelper::PrintSmartObject(*message_); - rpc_service_.SendMessageToMobile(message_); + rpc_service_.SendMessageToMobile(message_, final_message); } } // namespace commands diff --git a/src/components/application_manager/src/state_controller_impl.cc b/src/components/application_manager/src/state_controller_impl.cc index b07a5bcc13..ffff294664 100644 --- a/src/components/application_manager/src/state_controller_impl.cc +++ b/src/components/application_manager/src/state_controller_impl.cc @@ -88,7 +88,10 @@ void StateControllerImpl::SetRegularState(ApplicationSharedPtr app, return; } - if (app->is_resuming() && !IsResumptionAllowed(app, state)) { + const bool app_is_resuming = app->is_resuming(); + const bool is_resumption_allowed = IsResumptionAllowed(app, state); + + if (app_is_resuming && !is_resumption_allowed) { return; } @@ -333,15 +336,15 @@ void StateControllerImpl::HmiLevelConflictResolver::operator()( DCHECK_OR_RETURN_VOID(state_to_resolve); // If applied HMI state is FULL: - // - all NOT audio/video applications becomes BACKGROUND + // - all NOT audio/video applications become BACKGROUND // - all audio/video applications with other app type - // (navi, vc, media, projection) in FULL becomes LIMMITED - // - all audio/video applications with same app type becomes BACKGROUND + // (navi, vc, media, projection) in FULL become LIMITED + // - all audio/video applications with the same app type become BACKGROUND // // If applied HMI state is LIMITED: - // - all NOT audio/video applications saves their's HMI states - // - all applications with other app types saves their's HMI states - // - all audio/video applications with same app type becomes BACKGROUND + // - all NOT audio/video applications saves their HMI states + // - all applications with the other app types saves their HMI states + // - all audio/video applications with the same app type become BACKGROUND if (!IsStreamableHMILevel(state_->hmi_level())) { LOG4CXX_DEBUG(logger_, @@ -478,10 +481,14 @@ bool StateControllerImpl::IsResumptionAllowed(ApplicationSharedPtr app, return false; } + const bool is_navi_app = app->is_navi(); + const bool is_mob_projection_app = app->mobile_projection_enabled(); + const bool is_wep_app = app->webengine_projection_enabled(); + if (IsTempStateActive(HmiState::StateID::STATE_ID_EMBEDDED_NAVI) && - (app->is_navi() || app->mobile_projection_enabled())) { + (is_navi_app || is_mob_projection_app || is_wep_app)) { LOG4CXX_DEBUG(logger_, - "Resumption for navi or projection app is not allowed. " + "Resumption for navi and projection apps is not allowed. " << "EMBEDDED_NAVI event is active"); return false; } @@ -895,7 +902,7 @@ void StateControllerImpl::OnApplicationRegistered( const mobile_apis::HMILevel::eType default_level) { LOG4CXX_AUTO_TRACE(logger_); - // After app registration HMI level should be set for DEFAUL_WINDOW only + // After app registration HMI level should be set for DEFAULT_WINDOW only OnAppWindowAdded(app, mobile_apis::PredefinedWindows::DEFAULT_WINDOW, mobile_apis::WindowType::MAIN, @@ -1268,7 +1275,8 @@ mobile_apis::VideoStreamingState::eType StateControllerImpl::CalcVideoState( ApplicationSharedPtr app, const mobile_apis::HMILevel::eType hmi_level) const { auto state = mobile_apis::VideoStreamingState::NOT_STREAMABLE; - if (IsStreamableHMILevel(hmi_level) && app->IsVideoApplication()) { + + if (app->IsVideoApplication() && IsStreamableHMILevel(hmi_level)) { state = mobile_apis::VideoStreamingState::STREAMABLE; } diff --git a/src/components/application_manager/test/application_impl_test.cc b/src/components/application_manager/test/application_impl_test.cc index 485f0f3b5b..1977044ce3 100644 --- a/src/components/application_manager/test/application_impl_test.cc +++ b/src/components/application_manager/test/application_impl_test.cc @@ -597,6 +597,7 @@ TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeNotNaviNotVoice) { EXPECT_FALSE(app_impl->is_navi()); EXPECT_FALSE(app_impl->is_voice_communication_supported()); EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); app_impl->set_app_types(type_media); app_impl->ChangeSupportingAppHMIType(); @@ -604,6 +605,7 @@ TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeNotNaviNotVoice) { EXPECT_FALSE(app_impl->is_navi()); EXPECT_FALSE(app_impl->is_voice_communication_supported()); EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); } TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeIsVoice) { @@ -613,6 +615,7 @@ TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeIsVoice) { EXPECT_FALSE(app_impl->is_navi()); EXPECT_FALSE(app_impl->is_voice_communication_supported()); EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); app_impl->set_app_types(type_comm); app_impl->ChangeSupportingAppHMIType(); @@ -620,6 +623,7 @@ TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeIsVoice) { EXPECT_FALSE(app_impl->is_navi()); EXPECT_TRUE(app_impl->is_voice_communication_supported()); EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); } TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeIsNavi) { @@ -629,6 +633,7 @@ TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeIsNavi) { EXPECT_FALSE(app_impl->is_navi()); EXPECT_FALSE(app_impl->is_voice_communication_supported()); EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); app_impl->set_app_types(type_navi); app_impl->ChangeSupportingAppHMIType(); @@ -636,6 +641,71 @@ TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeIsNavi) { EXPECT_TRUE(app_impl->is_navi()); EXPECT_FALSE(app_impl->is_voice_communication_supported()); EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); +} + +TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeIsWebView) { + smart_objects::SmartObject app_types; + app_types[0] = mobile_apis::AppHMIType::WEB_VIEW; + + EXPECT_FALSE(app_impl->is_navi()); + EXPECT_FALSE(app_impl->is_voice_communication_supported()); + EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); + + app_impl->set_app_types(app_types); + app_impl->ChangeSupportingAppHMIType(); + + EXPECT_FALSE(app_impl->is_navi()); + EXPECT_FALSE(app_impl->is_voice_communication_supported()); + EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_TRUE(app_impl->webengine_projection_enabled()); +} + +TEST_F(ApplicationImplTest, + ChangeSupportingAppHMIType_TypeFromWebViewToProjection) { + smart_objects::SmartObject app_types; + app_types[0] = mobile_apis::AppHMIType::WEB_VIEW; + + EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); + + app_impl->set_app_types(app_types); + app_impl->ChangeSupportingAppHMIType(); + + EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_TRUE(app_impl->webengine_projection_enabled()); + + app_types[0] = mobile_apis::AppHMIType::PROJECTION; + + app_impl->set_app_types(app_types); + app_impl->ChangeSupportingAppHMIType(); + + EXPECT_FALSE(app_impl->webengine_projection_enabled()); + EXPECT_TRUE(app_impl->mobile_projection_enabled()); +} + +TEST_F(ApplicationImplTest, + ChangeSupportingAppHMIType_TypeFromProjectionToWebView) { + smart_objects::SmartObject app_types; + app_types[0] = mobile_apis::AppHMIType::PROJECTION; + + EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); + + app_impl->set_app_types(app_types); + app_impl->ChangeSupportingAppHMIType(); + + EXPECT_FALSE(app_impl->webengine_projection_enabled()); + EXPECT_TRUE(app_impl->mobile_projection_enabled()); + + app_types[0] = mobile_apis::AppHMIType::WEB_VIEW; + + app_impl->set_app_types(app_types); + app_impl->ChangeSupportingAppHMIType(); + + EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_TRUE(app_impl->webengine_projection_enabled()); } TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeIsNaviAndVoice) { @@ -647,6 +717,7 @@ TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeIsNaviAndVoice) { EXPECT_FALSE(app_impl->is_navi()); EXPECT_FALSE(app_impl->is_voice_communication_supported()); EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); app_impl->set_app_types(app_types); app_impl->ChangeSupportingAppHMIType(); @@ -654,6 +725,7 @@ TEST_F(ApplicationImplTest, ChangeSupportingAppHMIType_TypeIsNaviAndVoice) { EXPECT_TRUE(app_impl->is_navi()); EXPECT_TRUE(app_impl->is_voice_communication_supported()); EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); } TEST_F(ApplicationImplTest, @@ -667,6 +739,7 @@ TEST_F(ApplicationImplTest, EXPECT_FALSE(app_impl->is_navi()); EXPECT_FALSE(app_impl->is_voice_communication_supported()); EXPECT_FALSE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); app_impl->set_app_types(app_types); app_impl->ChangeSupportingAppHMIType(); @@ -674,6 +747,7 @@ TEST_F(ApplicationImplTest, EXPECT_TRUE(app_impl->is_navi()); EXPECT_TRUE(app_impl->is_voice_communication_supported()); EXPECT_TRUE(app_impl->mobile_projection_enabled()); + EXPECT_FALSE(app_impl->webengine_projection_enabled()); } TEST_F(ApplicationImplTest, UpdateHash_AppMngrNotSuspended) { 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 d19cbbad22..9ff2a49686 100644 --- a/src/components/application_manager/test/application_manager_impl_test.cc +++ b/src/components/application_manager/test/application_manager_impl_test.cc @@ -338,6 +338,44 @@ class ApplicationManagerImplTest void CreatePendingApplication(); #endif + void ExpectedHmiState( + const ApplicationSharedPtr wep_app, + const WindowID main_window_id, + const mobile_apis::HMILevel::eType hmi_level, + const mobile_apis::VideoStreamingState::eType vss, + const mobile_apis::AudioStreamingState::eType audio_str_st, + const mobile_apis::SystemContext::eType system_ctx) { + EXPECT_EQ(hmi_level, wep_app->hmi_level(main_window_id)); + EXPECT_EQ(vss, wep_app->video_streaming_state()); + EXPECT_EQ(audio_str_st, wep_app->audio_streaming_state()); + EXPECT_EQ(system_ctx, wep_app->system_context(main_window_id)); + } + + smart_objects::SmartObjectSPtr CreateRAI(const std::string app_hmi_type, + const bool is_media_application) { + smart_objects::SmartObject rai(smart_objects::SmartType_Map); + smart_objects::SmartObject& params = rai[strings::msg_params]; + params[strings::app_id] = kAppId; + params[strings::language_desired] = mobile_api::Language::EN_US; + params[strings::hmi_display_language_desired] = mobile_api::Language::EN_US; + + rai[strings::params][strings::connection_key] = kConnectionKey; + rai[strings::msg_params][strings::app_name] = kAppName; + rai[strings::msg_params][strings::app_hmi_type] = app_hmi_type; + rai[strings::msg_params][strings::is_media_application] = + is_media_application; + rai[strings::msg_params][strings::sync_msg_version] + [strings::minor_version] = APIVersion::kAPIV2; + rai[strings::msg_params][strings::sync_msg_version] + [strings::major_version] = APIVersion::kAPIV6; + + rai[strings::params][strings::protocol_version] = + protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_2; + + const auto rai_ptr = std::make_shared<smart_objects::SmartObject>(rai); + return rai_ptr; + } + void CreatePendingLocalApplication(const std::string& policy_app_id); uint32_t app_id_; @@ -2046,6 +2084,173 @@ TEST_F( EXPECT_EQ(1u, app_list.size()); } +TEST_F( + ApplicationManagerImplTest, + RegisterApplication_WEPNonMediaAppRegisterActivateDeactivateExit_EXPECT_CORRECT_HMI_STATES) { + using namespace mobile_apis; + EXPECT_CALL( + mock_session_observer_, + GetDataOnSessionKey(kConnectionKey, + _, + _, + testing::An<connection_handler::DeviceHandle*>())) + .WillOnce(DoAll(SetArgPointee<3u>(kDeviceId), Return(0))); + + const std::string app_hmi_type{"WEB_VIEW"}; + const bool is_media_app = false; + const auto rai_ptr = CreateRAI(app_hmi_type, is_media_app); + + std::unique_ptr<plugin_manager::RPCPluginManager> rpc_plugin_manager( + new MockRPCPluginManager()); + app_manager_impl_->SetPluginManager(rpc_plugin_manager); + auto wep_nonmedia_app = app_manager_impl_->RegisterApplication(rai_ptr); + wep_nonmedia_app->set_is_media_application(false); + + EXPECT_EQ(protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_2, + wep_nonmedia_app->protocol_version()); + EXPECT_EQ(APIVersion::kAPIV2, + wep_nonmedia_app->version().min_supported_api_version); + EXPECT_EQ(APIVersion::kAPIV6, + wep_nonmedia_app->version().max_supported_api_version); + + // Initial HMI level, audio, video streaming states and system context + // set after app registration + ExpectedHmiState(wep_nonmedia_app, + kDefaultWindowId, + HMILevel::INVALID_ENUM, + VideoStreamingState::INVALID_ENUM, + AudioStreamingState::INVALID_ENUM, + SystemContext::SYSCTXT_MAIN); + + // Const shared ptr is required for OnAppActivated due to its signature + ApplicationConstSharedPtr const_wep_app = wep_nonmedia_app; + EXPECT_CALL(*mock_app_service_manager_, OnAppActivated(const_wep_app)); + + // Activate Webengine projection non-media app + // to check its audio & video streaming states in FULL Hmi level + app_manager_impl_->ActivateApplication(wep_nonmedia_app); + + // WEP non-media app should be always not_streamable + // and not_audible even in FULL HMI Level + ExpectedHmiState(wep_nonmedia_app, + kDefaultWindowId, + HMILevel::HMI_FULL, + VideoStreamingState::NOT_STREAMABLE, + AudioStreamingState::NOT_AUDIBLE, + SystemContext::SYSCTXT_MAIN); + + // Deactivate Webengine projection non-media app + // to check its new HMI level and audio & video streaming states + app_manager_impl_->state_controller().DeactivateApp(wep_nonmedia_app, + kDefaultWindowId); + + // WEP non-media app should be deactivated to BACKGROUND + // WEP non-media app should be not audible and not streamable + // in BACKGROUND HMI Level + + ExpectedHmiState(wep_nonmedia_app, + kDefaultWindowId, + HMILevel::HMI_BACKGROUND, + VideoStreamingState::NOT_STREAMABLE, + AudioStreamingState::NOT_AUDIBLE, + SystemContext::SYSCTXT_MAIN); + + // Exit of Webengine projection non-media app + // to check its new HMI level and audio & video streaming states + app_manager_impl_->state_controller().ExitDefaultWindow(wep_nonmedia_app); + // WEP non-media app should be deactivated to NONE + // WEP non-media app should be not audible and not streamable + // in NONE HMI Level + ExpectedHmiState(wep_nonmedia_app, + kDefaultWindowId, + HMILevel::HMI_NONE, + VideoStreamingState::NOT_STREAMABLE, + AudioStreamingState::NOT_AUDIBLE, + SystemContext::SYSCTXT_MAIN); +} + +TEST_F( + ApplicationManagerImplTest, + RegisterApplication_WEPMediaAppRegisterActivateDeactivateExit_EXPECT_CORRECT_HMI_STATES) { + using namespace mobile_apis; + + EXPECT_CALL( + mock_session_observer_, + GetDataOnSessionKey(kConnectionKey, + _, + _, + testing::An<connection_handler::DeviceHandle*>())) + .WillOnce(DoAll(SetArgPointee<3u>(kDeviceId), Return(0))); + + const std::string app_hmi_type{"WEB_VIEW"}; + const bool is_media_app = true; + const auto rai_ptr = CreateRAI(app_hmi_type, is_media_app); + + std::unique_ptr<plugin_manager::RPCPluginManager> rpc_plugin_manager( + new MockRPCPluginManager()); + app_manager_impl_->SetPluginManager(rpc_plugin_manager); + auto wep_media_app = app_manager_impl_->RegisterApplication(rai_ptr); + wep_media_app->set_is_media_application(true); + + EXPECT_EQ(protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_2, + wep_media_app->protocol_version()); + EXPECT_EQ(APIVersion::kAPIV2, + wep_media_app->version().min_supported_api_version); + EXPECT_EQ(APIVersion::kAPIV6, + wep_media_app->version().max_supported_api_version); + + // Initial HMI level, audio, video streaming states and system context + // set after app registration + ExpectedHmiState(wep_media_app, + kDefaultWindowId, + HMILevel::INVALID_ENUM, + VideoStreamingState::INVALID_ENUM, + AudioStreamingState::INVALID_ENUM, + SystemContext::SYSCTXT_MAIN); + + // Const shared ptr is required for OnAppActivated due to its signature + ApplicationConstSharedPtr const_wep_app = wep_media_app; + EXPECT_CALL(*mock_app_service_manager_, OnAppActivated(const_wep_app)); + + // Activate Webengine projection media app + // to check its audio & video streaming states in FULL Hmi level + app_manager_impl_->ActivateApplication(wep_media_app); + + // WEP media app should be always not_streamable + // but audible even in FULL HMI Level + ExpectedHmiState(wep_media_app, + kDefaultWindowId, + HMILevel::HMI_FULL, + VideoStreamingState::NOT_STREAMABLE, + AudioStreamingState::AUDIBLE, + SystemContext::SYSCTXT_MAIN); + + // Deactivate Webengine projection media app + // to check its new HMI level and audio & video streaming states + app_manager_impl_->state_controller().DeactivateApp(wep_media_app, + kDefaultWindowId); + + // WEP media app should be deactivated to LIMITED + // WEP media app should be audible but not streamable in LIMITED HMI Level + ExpectedHmiState(wep_media_app, + kDefaultWindowId, + HMILevel::HMI_LIMITED, + VideoStreamingState::NOT_STREAMABLE, + AudioStreamingState::AUDIBLE, + SystemContext::SYSCTXT_MAIN); + + // Exit of Webengine projection media app + // to check its new HMI level and audio & video streaming states + app_manager_impl_->state_controller().ExitDefaultWindow(wep_media_app); + // WEP media app should be exited to NONE + ExpectedHmiState(wep_media_app, + kDefaultWindowId, + HMILevel::HMI_NONE, + VideoStreamingState::NOT_STREAMABLE, + AudioStreamingState::NOT_AUDIBLE, + SystemContext::SYSCTXT_MAIN); +} + TEST_F(ApplicationManagerImplTest, AddAndRemoveQueryAppDevice_SUCCESS) { const connection_handler::DeviceHandle device_handle = 1u; ASSERT_FALSE(app_manager_impl_->IsAppsQueriedFrom(device_handle)); 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 175c39513e..224fea0456 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 @@ -67,6 +67,8 @@ class MockApplication : public ::application_manager::Application { MOCK_METHOD1(set_is_navi, void(bool allow)); MOCK_CONST_METHOD0(mobile_projection_enabled, bool()); MOCK_METHOD1(set_mobile_projection_enabled, void(bool allow)); + MOCK_CONST_METHOD0(webengine_projection_enabled, bool()); + MOCK_METHOD1(set_webengine_projection_enabled, void(const bool allow)); MOCK_CONST_METHOD0(video_streaming_approved, bool()); MOCK_METHOD1(set_video_streaming_approved, void(bool state)); MOCK_CONST_METHOD0(audio_streaming_approved, bool()); diff --git a/src/components/application_manager/test/state_controller/state_controller_test.cc b/src/components/application_manager/test/state_controller/state_controller_test.cc index 93565b8719..e9bce76fc5 100644 --- a/src/components/application_manager/test/state_controller/state_controller_test.cc +++ b/src/components/application_manager/test/state_controller/state_controller_test.cc @@ -83,6 +83,15 @@ const uint32_t kHMIAppID = 2718u; const am::WindowID kDefaultWindowId = mobile_apis::PredefinedWindows::DEFAULT_WINDOW; const am::WindowID kCustomWindowId = 2; + +const uint32_t kAppIdInFull = 1761; +const uint32_t kHMIAppIdInFull = 15685; +const uint32_t kAppIdMovedToFull = 1796; +const uint32_t kHMIAppIdMovedToFull = 30093; +const uint32_t kAppIdLimited = 1762; +const uint32_t kHMIAppIdLimited = 17559; +const uint32_t kAppIDMovedToLimited = 1763; +const uint32_t kHMIAppIdMovedToLimited = 17663; } // namespace struct HmiStatesComparator { @@ -131,6 +140,8 @@ struct HmiStatesIDComparator { #define NOT_VC false #define NAVI true #define NOT_NAVI false +#define WEP true +#define NOT_WEP false enum ApplicationType { APP_TYPE_NON_MEDIA, @@ -211,6 +222,16 @@ class StateControllerImplTest : public ::testing::Test { uint32_t media_navi_vc_app_id_ = 1922; uint32_t media_navi_vc_hmi_app_id_ = 21419; + am::ApplicationSharedPtr media_wep_app_; + NiceMock<application_manager_test::MockApplication>* media_wep_app_ptr_; + uint32_t media_wep_app_id_ = 1977; + uint32_t media_wep_app_hmi_app_id_ = 21491; + + am::ApplicationSharedPtr non_media_wep_app_; + NiceMock<application_manager_test::MockApplication>* non_media_wep_app_ptr_; + uint32_t non_media_wep_app_id_ = 1979; + uint32_t non_media_wep_app_hmi_app_id_ = 21599; + std::vector<am::HmiStatePtr> valid_states_for_audio_app_; std::vector<am::HmiStatePtr> valid_states_for_not_audio_app_; std::vector<am::HmiStatePtr> common_invalid_states_; @@ -557,7 +578,7 @@ class StateControllerImplTest : public ::testing::Test { } } - ApplicationType AppType(uint32_t app_id) { + ApplicationType AppType(const uint32_t app_id) { // TODO(AOleynik): Currently there is ongoing discussion regarding mixed // application properties, i.e. is_media_application flag from RAI and // AppHmiTypes (NAVIGATION, etc.). Most likely logic should be changed @@ -573,7 +594,7 @@ class StateControllerImplTest : public ::testing::Test { return APP_TYPE_NON_MEDIA; } - auto app = it->first; + const auto app = it->first; if (app->is_navi()) { return APP_TYPE_NAVI; } @@ -682,18 +703,21 @@ class StateControllerImplTest : public ::testing::Test { NiceMock<application_manager_test::MockApplication>** app_mock, uint32_t app_id, uint32_t hmi_app_id, - bool media, - bool navi, - bool vc) { + const bool media, + const bool navi, + const bool vc, + const bool wep) { *app_mock = new NiceMock<application_manager_test::MockApplication>; - Mock::AllowLeak(*app_mock); // WorkAround for gogletest bug + Mock::AllowLeak(*app_mock); // WorkAround for googletest bug am::ApplicationSharedPtr app(*app_mock); ON_CALL(**app_mock, app_id()).WillByDefault(Return(app_id)); ON_CALL(**app_mock, hmi_app_id()).WillByDefault(Return(hmi_app_id)); ON_CALL(**app_mock, is_media_application()).WillByDefault(Return(media)); ON_CALL(**app_mock, is_navi()).WillByDefault(Return(navi)); + ON_CALL(**app_mock, webengine_projection_enabled()) + .WillByDefault(Return(wep)); ON_CALL(**app_mock, is_voice_communication_supported()) .WillByDefault(Return(vc)); ON_CALL(**app_mock, IsAudioApplication()) @@ -898,45 +922,72 @@ class StateControllerImplTest : public ::testing::Test { simple_hmi_app_id_, NOT_MEDIA, NOT_NAVI, - NOT_VC); + NOT_VC, + NOT_WEP); media_app_ = ConfigureApp(&media_app_ptr_, media_app_id_, media_hmi_app_id_, MEDIA, NOT_NAVI, - NOT_VC); + NOT_VC, + NOT_WEP); navi_app_ = ConfigureApp(&navi_app_ptr_, navi_app_id_, navi_hmi_app_id_, NOT_MEDIA, NAVI, - NOT_VC); - vc_app_ = ConfigureApp( - &vc_app_ptr_, vc_app_id_, vc_hmi_app_id_, NOT_MEDIA, NOT_NAVI, VC); + NOT_VC, + NOT_WEP); + vc_app_ = ConfigureApp(&vc_app_ptr_, + vc_app_id_, + vc_hmi_app_id_, + NOT_MEDIA, + NOT_NAVI, + VC, + NOT_WEP); media_navi_app_ = ConfigureApp(&media_navi_app_ptr_, media_navi_app_id_, media_navi_hmi_app_id_, MEDIA, NAVI, - NOT_VC); + NOT_VC, + NOT_WEP); media_vc_app_ = ConfigureApp(&media_vc_app_ptr_, media_vc_app_id_, media_vc_hmi_app_id_, MEDIA, NOT_NAVI, - VC); + VC, + NOT_WEP); navi_vc_app_ = ConfigureApp(&navi_vc_app_ptr_, navi_vc_app_id_, navi_vc_hmi_app_id_, NOT_MEDIA, NAVI, - VC); + VC, + NOT_WEP); media_navi_vc_app_ = ConfigureApp(&media_navi_vc_app_ptr_, media_navi_vc_app_id_, media_navi_vc_hmi_app_id_, MEDIA, NAVI, - VC); + VC, + NOT_WEP); + media_wep_app_ = ConfigureApp(&media_wep_app_ptr_, + media_wep_app_id_, + media_wep_app_hmi_app_id_, + MEDIA, + NOT_NAVI, + NOT_VC, + WEP); + non_media_wep_app_ = ConfigureApp(&non_media_wep_app_ptr_, + non_media_wep_app_id_, + non_media_wep_app_hmi_app_id_, + NOT_MEDIA, + NOT_NAVI, + NOT_VC, + WEP); + applications_list_[simple_app_] = simple_app_ptr_; applications_list_[media_app_] = media_app_ptr_; applications_list_[navi_app_] = navi_app_ptr_; @@ -945,7 +996,10 @@ class StateControllerImplTest : public ::testing::Test { applications_list_[media_vc_app_] = media_vc_app_ptr_; applications_list_[navi_vc_app_] = navi_vc_app_ptr_; applications_list_[media_navi_vc_app_] = media_navi_vc_app_ptr_; + applications_list_[media_wep_app_] = media_wep_app_ptr_; + applications_list_[non_media_wep_app_] = non_media_wep_app_ptr_; } + void CheckAppConfiguration() { ASSERT_EQ(simple_app_.get(), simple_app_ptr_); ASSERT_EQ(media_app_.get(), media_app_ptr_); @@ -955,6 +1009,8 @@ class StateControllerImplTest : public ::testing::Test { ASSERT_EQ(media_vc_app_.get(), media_vc_app_ptr_); ASSERT_EQ(navi_vc_app_.get(), navi_vc_app_ptr_); ASSERT_EQ(media_navi_vc_app_.get(), media_navi_vc_app_ptr_); + ASSERT_EQ(media_wep_app_.get(), media_wep_app_ptr_); + ASSERT_EQ(non_media_wep_app_.get(), non_media_wep_app_ptr_); ASSERT_EQ(simple_app_->app_id(), simple_app_id_); ASSERT_EQ(media_app_->app_id(), media_app_id_); @@ -964,6 +1020,8 @@ class StateControllerImplTest : public ::testing::Test { ASSERT_EQ(media_vc_app_->app_id(), media_vc_app_id_); ASSERT_EQ(navi_vc_app_->app_id(), navi_vc_app_id_); ASSERT_EQ(media_navi_vc_app_->app_id(), media_navi_vc_app_id_); + ASSERT_EQ(media_wep_app_->app_id(), media_wep_app_id_); + ASSERT_EQ(non_media_wep_app_->app_id(), non_media_wep_app_id_); ASSERT_EQ(simple_app_->hmi_app_id(), simple_hmi_app_id_); ASSERT_EQ(media_app_->hmi_app_id(), media_hmi_app_id_); @@ -973,6 +1031,8 @@ class StateControllerImplTest : public ::testing::Test { ASSERT_EQ(media_vc_app_->hmi_app_id(), media_vc_hmi_app_id_); ASSERT_EQ(navi_vc_app_->hmi_app_id(), navi_vc_hmi_app_id_); ASSERT_EQ(media_navi_vc_app_->hmi_app_id(), media_navi_vc_hmi_app_id_); + ASSERT_EQ(media_wep_app_->hmi_app_id(), media_wep_app_hmi_app_id_); + ASSERT_EQ(non_media_wep_app_->hmi_app_id(), non_media_wep_app_hmi_app_id_); ASSERT_FALSE(simple_app_->IsAudioApplication()); ASSERT_TRUE(media_app_->IsAudioApplication()); @@ -982,6 +1042,8 @@ class StateControllerImplTest : public ::testing::Test { ASSERT_TRUE(media_vc_app_->IsAudioApplication()); ASSERT_TRUE(navi_vc_app_->IsAudioApplication()); ASSERT_TRUE(media_navi_vc_app_->IsAudioApplication()); + ASSERT_TRUE(media_wep_app_->IsAudioApplication()); + ASSERT_FALSE(non_media_wep_app_->IsAudioApplication()); ASSERT_FALSE(simple_app_->is_media_application()); ASSERT_TRUE(media_app_->is_media_application()); @@ -991,6 +1053,8 @@ class StateControllerImplTest : public ::testing::Test { ASSERT_TRUE(media_vc_app_->is_media_application()); ASSERT_FALSE(navi_vc_app_->is_media_application()); ASSERT_TRUE(media_navi_vc_app_->is_media_application()); + ASSERT_TRUE(media_wep_app_->is_media_application()); + ASSERT_FALSE(non_media_wep_app_->is_media_application()); ASSERT_FALSE(simple_app_->is_navi()); ASSERT_TRUE(navi_app_->is_navi()); @@ -1000,6 +1064,8 @@ class StateControllerImplTest : public ::testing::Test { ASSERT_FALSE(media_vc_app_->is_navi()); ASSERT_TRUE(navi_vc_app_->is_navi()); ASSERT_TRUE(media_navi_vc_app_->is_navi()); + ASSERT_FALSE(media_wep_app_->is_navi()); + ASSERT_FALSE(non_media_wep_app_->is_navi()); ASSERT_FALSE(simple_app_->is_voice_communication_supported()); ASSERT_FALSE(navi_app_->is_voice_communication_supported()); @@ -1009,6 +1075,8 @@ class StateControllerImplTest : public ::testing::Test { ASSERT_TRUE(media_vc_app_->is_voice_communication_supported()); ASSERT_TRUE(navi_vc_app_->is_voice_communication_supported()); ASSERT_TRUE(media_navi_vc_app_->is_voice_communication_supported()); + ASSERT_FALSE(media_wep_app_->is_voice_communication_supported()); + ASSERT_FALSE(non_media_wep_app_->is_voice_communication_supported()); } virtual void SetUp() OVERRIDE { @@ -1601,10 +1669,21 @@ TEST_F(StateControllerImplTest, am::ApplicationSharedPtr app_moved_to_full; NiceMock<application_manager_test::MockApplication>* app_moved_to_full_mock; - app_in_full = - ConfigureApp(&app_in_full_mock, 1761, 15685, NOT_MEDIA, NOT_NAVI, NOT_VC); - app_moved_to_full = ConfigureApp( - &app_moved_to_full_mock, 1796, 30093, NOT_MEDIA, NOT_NAVI, NOT_VC); + app_in_full = ConfigureApp(&app_in_full_mock, + kAppIdInFull, + kHMIAppIdInFull, + NOT_MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); + + app_moved_to_full = ConfigureApp(&app_moved_to_full_mock, + kAppIdMovedToFull, + kHMIAppIdMovedToFull, + NOT_MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); InsertApplication(app_in_full); InsertApplication(app_moved_to_full); @@ -1678,12 +1757,23 @@ TEST_F(StateControllerImplTest, namespace HMILevel = mobile_apis::HMILevel; namespace SystemContext = mobile_apis::SystemContext; NiceMock<application_manager_test::MockApplication>* app_in_full_mock; - am::ApplicationSharedPtr app_in_full = - ConfigureApp(&app_in_full_mock, 1761, 15685, MEDIA, NOT_NAVI, NOT_VC); + am::ApplicationSharedPtr app_in_full = ConfigureApp(&app_in_full_mock, + kAppIdInFull, + kHMIAppIdInFull, + MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); NiceMock<application_manager_test::MockApplication>* app_moved_to_full_mock; - am::ApplicationSharedPtr app_moved_to_full = ConfigureApp( - &app_moved_to_full_mock, 1796, 30093, MEDIA, NOT_NAVI, NOT_VC); + am::ApplicationSharedPtr app_moved_to_full = + ConfigureApp(&app_moved_to_full_mock, + kAppIdMovedToFull, + kHMIAppIdMovedToFull, + MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); InsertApplication(app_in_full); InsertApplication(app_moved_to_full); @@ -1705,12 +1795,23 @@ TEST_F(StateControllerImplTest, namespace SystemContext = mobile_apis::SystemContext; NiceMock<application_manager_test::MockApplication>* app_in_limited_mock; - am::ApplicationSharedPtr app_in_limited = - ConfigureApp(&app_in_limited_mock, 1761, 15685, NOT_MEDIA, NAVI, NOT_VC); + am::ApplicationSharedPtr app_in_limited = ConfigureApp(&app_in_limited_mock, + kAppIdLimited, + kHMIAppIdLimited, + NOT_MEDIA, + NAVI, + NOT_VC, + NOT_WEP); NiceMock<application_manager_test::MockApplication>* app_moved_to_full_mock; am::ApplicationSharedPtr app_moved_to_full = - ConfigureApp(&app_moved_to_full_mock, 1796, 30093, NOT_MEDIA, NAVI, VC); + ConfigureApp(&app_moved_to_full_mock, + kAppIdMovedToFull, + kHMIAppIdMovedToFull, + NOT_MEDIA, + NAVI, + VC, + NOT_WEP); InsertApplication(app_in_limited); InsertApplication(app_moved_to_full); @@ -1731,13 +1832,24 @@ TEST_F(StateControllerImplTest, namespace HMILevel = mobile_apis::HMILevel; namespace SystemContext = mobile_apis::SystemContext; NiceMock<application_manager_test::MockApplication>* app_in_limited_mock; - am::ApplicationSharedPtr app_in_limited = - ConfigureApp(&app_in_limited_mock, 1761, 15685, NOT_MEDIA, NOT_NAVI, VC); + am::ApplicationSharedPtr app_in_limited = ConfigureApp(&app_in_limited_mock, + kAppIdLimited, + kHMIAppIdLimited, + NOT_MEDIA, + NOT_NAVI, + VC, + NOT_WEP); NiceMock<application_manager_test::MockApplication>* app_moved_to_limited_mock; - am::ApplicationSharedPtr app_moved_to_limited = ConfigureApp( - &app_moved_to_limited_mock, 1796, 30093, NOT_MEDIA, NOT_NAVI, VC); + am::ApplicationSharedPtr app_moved_to_limited = + ConfigureApp(&app_moved_to_limited_mock, + kAppIDMovedToLimited, + kHMIAppIdMovedToLimited, + NOT_MEDIA, + NOT_NAVI, + VC, + NOT_WEP); InsertApplication(app_in_limited); InsertApplication(app_moved_to_limited); @@ -1886,16 +1998,27 @@ TEST_F(StateControllerImplTest, namespace SystemContext = mobile_apis::SystemContext; NiceMock<application_manager_test::MockApplication>* app_moved_to_full_mock; - am::ApplicationSharedPtr app_moved_to_full = ConfigureApp( - &app_moved_to_full_mock, 1761, 15685, NOT_MEDIA, NOT_NAVI, NOT_VC); + am::ApplicationSharedPtr app_moved_to_full = + ConfigureApp(&app_moved_to_full_mock, + kAppIdMovedToFull, + kHMIAppIdMovedToFull, + NOT_MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); am::ApplicationSharedPtr limited_app = media_app_; NiceMock<application_manager_test::MockApplication>* limited_app_mock = media_app_ptr_; NiceMock<application_manager_test::MockApplication>* full_app_mock; - am::ApplicationSharedPtr full_app = - ConfigureApp(&full_app_mock, 1796, 30093, NOT_MEDIA, NOT_NAVI, NOT_VC); + am::ApplicationSharedPtr full_app = ConfigureApp(&full_app_mock, + kAppIdInFull, + kHMIAppIdInFull, + NOT_MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); InsertApplication(app_moved_to_full); InsertApplication(limited_app); @@ -1924,16 +2047,32 @@ TEST_F( namespace SystemContext = mobile_apis::SystemContext; NiceMock<application_manager_test::MockApplication>* app_moved_to_full_mock; - am::ApplicationSharedPtr app_moved_to_full = ConfigureApp( - &app_moved_to_full_mock, 1761, 15685, MEDIA, NOT_NAVI, NOT_VC); + am::ApplicationSharedPtr app_moved_to_full = + ConfigureApp(&app_moved_to_full_mock, + kAppIdMovedToFull, + kHMIAppIdMovedToFull, + MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); NiceMock<application_manager_test::MockApplication>* limited_app_mock; - am::ApplicationSharedPtr limited_app = - ConfigureApp(&limited_app_mock, 1762, 17559, MEDIA, NOT_NAVI, NOT_VC); + am::ApplicationSharedPtr limited_app = ConfigureApp(&limited_app_mock, + kAppIdLimited, + kHMIAppIdLimited, + MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); NiceMock<application_manager_test::MockApplication>* full_app_mock; - am::ApplicationSharedPtr full_app = - ConfigureApp(&full_app_mock, 1796, 30093, NOT_MEDIA, NOT_NAVI, NOT_VC); + am::ApplicationSharedPtr full_app = ConfigureApp(&full_app_mock, + kAppIdInFull, + kHMIAppIdInFull, + NOT_MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); InsertApplication(app_moved_to_full); InsertApplication(limited_app); @@ -1962,16 +2101,32 @@ TEST_F( namespace SystemContext = mobile_apis::SystemContext; NiceMock<application_manager_test::MockApplication>* app_moved_to_full_mock; - am::ApplicationSharedPtr app_moved_to_full = ConfigureApp( - &app_moved_to_full_mock, 1761, 15685, MEDIA, NOT_NAVI, NOT_VC); + am::ApplicationSharedPtr app_moved_to_full = + ConfigureApp(&app_moved_to_full_mock, + kAppIdMovedToFull, + kHMIAppIdMovedToFull, + MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); NiceMock<application_manager_test::MockApplication>* limited_app_mock; - am::ApplicationSharedPtr limited_app = - ConfigureApp(&limited_app_mock, 1762, 17559, MEDIA, NOT_NAVI, NOT_VC); + am::ApplicationSharedPtr limited_app = ConfigureApp(&limited_app_mock, + kAppIdLimited, + kHMIAppIdLimited, + MEDIA, + NOT_NAVI, + NOT_VC, + NOT_WEP); NiceMock<application_manager_test::MockApplication>* full_app_mock; - am::ApplicationSharedPtr full_app = - ConfigureApp(&full_app_mock, 1796, 30093, NOT_MEDIA, NAVI, NOT_VC); + am::ApplicationSharedPtr full_app = ConfigureApp(&full_app_mock, + kAppIdInFull, + kHMIAppIdInFull, + NOT_MEDIA, + NAVI, + NOT_VC, + NOT_WEP); InsertApplication(app_moved_to_full); InsertApplication(limited_app); @@ -3388,6 +3543,29 @@ TEST_F( media_app_, kDefaultWindowId, new_state, send_activate_app); } +TEST_F( + StateControllerImplTest, + SetRegularState_WEPAppIsInResumingModeEmbeddedNaviIsActive_HmiStateIsNotChanged) { + am::event_engine::Event embedded_navi_event( + hmi_apis::FunctionID::BasicCommunication_OnEventChanged); + smart_objects::SmartObject message; + message[am::strings::msg_params][am::hmi_notification::is_active] = true; + message[am::strings::msg_params][am::hmi_notification::event_name] = + hmi_apis::Common_EventTypes::EMBEDDED_NAVI; + embedded_navi_event.set_smart_object(message); + state_ctrl_->on_event(embedded_navi_event); + + EXPECT_CALL(*media_wep_app_ptr_, is_resuming()) + .Times(2) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*media_wep_app_ptr_, SetRegularState(_, _)).Times(0); + + const auto new_state = FullAudibleState(); + const bool send_activate_app = true; + state_ctrl_->SetRegularState( + media_wep_app_, kDefaultWindowId, new_state, send_activate_app); +} + TEST_F(StateControllerImplTest, SetRegularState_BcActivateAppSendFailed_HmiLevelIsNotChanged) { const am::HmiStatePtr new_state = FullAudibleState(); diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc index 1ad938332a..d2b00448e3 100644 --- a/src/components/connection_handler/src/connection_handler_impl.cc +++ b/src/components/connection_handler/src/connection_handler_impl.cc @@ -1605,6 +1605,7 @@ void ConnectionHandlerImpl::CloseConnectionSessions( } void ConnectionHandlerImpl::SendEndService(uint32_t key, uint8_t service_type) { + LOG4CXX_AUTO_TRACE(logger_); if (protocol_handler_) { uint32_t connection_handle = 0; uint8_t session_id = 0; diff --git a/src/components/include/application_manager/state_controller.h b/src/components/include/application_manager/state_controller.h index 2fa4b0c218..93d4c4fc39 100644 --- a/src/components/include/application_manager/state_controller.h +++ b/src/components/include/application_manager/state_controller.h @@ -223,6 +223,15 @@ class StateController { * @param app pointer to application to be exited */ virtual void ExitDefaultWindow(ApplicationSharedPtr app) = 0; + + /** + * @brief Sets BACKGROUND or LIMITED hmi level to application + * depends on application type + * @param window_id ID of app window to deactivate + * @param app Application to deactivate + */ + virtual void DeactivateApp(ApplicationSharedPtr app, + const WindowID window_id) = 0; }; } // namespace application_manager diff --git a/src/components/include/test/application_manager/mock_state_controller.h b/src/components/include/test/application_manager/mock_state_controller.h index 545090bf30..26d403ba75 100644 --- a/src/components/include/test/application_manager/mock_state_controller.h +++ b/src/components/include/test/application_manager/mock_state_controller.h @@ -108,6 +108,9 @@ class MockStateController : public am::StateController { MOCK_CONST_METHOD1(IsStateActive, bool(am::HmiState::StateID state_id)); MOCK_METHOD1(ActivateDefaultWindow, void(am::ApplicationSharedPtr app)); MOCK_METHOD1(ExitDefaultWindow, void(am::ApplicationSharedPtr app)); + MOCK_METHOD2(DeactivateApp, + void(am::ApplicationSharedPtr app, + const am::WindowID window_id)); }; } // namespace application_manager_test diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml index c84f9367e9..8e906a7bbb 100644 --- a/src/components/interfaces/HMI_API.xml +++ b/src/components/interfaces/HMI_API.xml @@ -340,6 +340,7 @@ <element name="SYSTEM" /> <element name="PROJECTION" /> <element name="REMOTE_CONTROL" /> + <element name="WEB_VIEW" /> </enum> <enum name="CloudConnectionStatus"> @@ -540,6 +541,9 @@ <element name="CLOSE_CLOUD_CONNECTION"> <description>By getting this value, SDL puts the named app to NONE HMILevel. Used by the HMI to close a cloud app connection.</description> </element> + <element name="RESOURCE_CONSTRAINT"> + <description>By getting this value, SDL should unregister the application to allow the HMI to close the application.</description> + </element> </enum> <enum name="TextFieldName"> diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc index 7769696a76..9b7305d48a 100644 --- a/src/components/protocol_handler/src/protocol_handler_impl.cc +++ b/src/components/protocol_handler/src/protocol_handler_impl.cc @@ -652,6 +652,7 @@ void ProtocolHandlerImpl::SendEndServicePrivate(int32_t primary_connection_id, void ProtocolHandlerImpl::SendEndSession(int32_t connection_id, uint8_t session_id) { + LOG4CXX_AUTO_TRACE(logger_); // A session is always associated with a primary connection ID SendEndServicePrivate( connection_id, connection_id, session_id, SERVICE_TYPE_RPC); @@ -661,6 +662,7 @@ void ProtocolHandlerImpl::SendEndService(int32_t primary_connection_id, int32_t connection_id, uint8_t session_id, uint8_t service_type) { + LOG4CXX_AUTO_TRACE(logger_); SendEndServicePrivate( primary_connection_id, connection_id, session_id, service_type); } @@ -1106,6 +1108,24 @@ void ProtocolHandlerImpl::OnTMMessageSendFailed( << "bytes failed, connection_key " << message->connection_key() << "Error_text: " << error.text()); + + uint32_t connection_handle = 0; + uint8_t session_id = 0; + + session_observer_.PairFromKey( + message->connection_key(), &connection_handle, &session_id); + + const auto connection_it = std::find(ready_to_close_connections_.begin(), + ready_to_close_connections_.end(), + connection_handle); + if (ready_to_close_connections_.end() != connection_it) { + ready_to_close_connections_.erase(connection_it); + } + + const auto last_message_it = sessions_last_message_id_.find(session_id); + if (sessions_last_message_id_.end() != last_message_it) { + sessions_last_message_id_.erase(last_message_it); + } } void ProtocolHandlerImpl::OnConnectionPending( diff --git a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_connection.h b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_connection.h index fb904d645e..b3dc04a897 100644 --- a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_connection.h +++ b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_connection.h @@ -48,7 +48,6 @@ namespace transport_adapter { using ::utils::MessageQueue; -typedef ::protocol_handler::RawMessagePtr Message; typedef std::queue<Message> AsyncQueue; class TransportAdapterController; @@ -75,10 +74,11 @@ class WebSocketConnection TransportAdapter::Error Disconnect() OVERRIDE; - TransportAdapter::Error SendData( - protocol_handler::RawMessagePtr message) OVERRIDE; + TransportAdapter::Error SendData(Message message) OVERRIDE; - void DataReceive(protocol_handler::RawMessagePtr frame); + void DataReceive(Message frame); + void DataSendDone(Message frame); + void DataSendFailed(Message frame); void Run(); bool IsShuttingDown(); @@ -99,21 +99,17 @@ class WebSocketConnection class LoopThreadDelegate : public threads::ThreadDelegate { public: LoopThreadDelegate(MessageQueue<Message, AsyncQueue>* message_queue, - DataWriteCallback data_write, - OnIOErrorCallback on_io_error); + DataWriteCallback data_write); virtual void threadMain() OVERRIDE; virtual void exitThreadMain() OVERRIDE; - void OnWrite(); - void SetShutdown(); private: void DrainQueue(); MessageQueue<Message, AsyncQueue>& message_queue_; DataWriteCallback data_write_; - OnIOErrorCallback on_io_error_; }; LoopThreadDelegate* thread_delegate_; diff --git a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_secure_session.h b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_secure_session.h index a3ead8e5a5..cfeedd16fc 100644 --- a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_secure_session.h +++ b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_secure_session.h @@ -45,7 +45,9 @@ class WebSocketSecureSession : public WebSocketSession<ExecutorType> { WebSocketSecureSession(tcp::socket, ssl::context& ctx, DataReceiveCallback data_receive, - OnIOErrorCallback on_errror); + DataSendDoneCallback data_send_done, + DataSendFailedCallback data_send_failed, + OnIOErrorCallback on_error); void AsyncAccept() OVERRIDE; virtual void AsyncHandshake(boost::system::error_code ec); diff --git a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_session.h b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_session.h index a8dadc9831..53dd6a366a 100644 --- a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_session.h +++ b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_session.h @@ -35,6 +35,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <boost/asio/strand.hpp> #include <boost/beast/core.hpp> #include <boost/beast/websocket.hpp> +#include <functional> + #include "protocol/raw_message.h" #include "transport_manager/transport_adapter/transport_adapter.h" #include "utils/logger.h" @@ -46,10 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace transport_manager { namespace transport_adapter { -using DataReceiveCallback = - std::function<void(protocol_handler::RawMessagePtr)>; -using DataWriteCallback = std::function<TransportAdapter::Error( - protocol_handler::RawMessagePtr message)>; +using Message = ::protocol_handler::RawMessagePtr; +using DataReceiveCallback = std::function<void(Message)>; +using DataSendDoneCallback = DataReceiveCallback; +using DataSendFailedCallback = DataReceiveCallback; +using DataWriteCallback = DataReceiveCallback; using OnIOErrorCallback = std::function<void()>; using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> @@ -69,12 +72,16 @@ class WebSocketSession public: WebSocketSession(boost::asio::ip::tcp::socket socket, DataReceiveCallback data_receive, + DataSendDoneCallback data_send_done, + DataSendFailedCallback data_send_failed, OnIOErrorCallback on_error); #ifdef ENABLE_SECURITY WebSocketSession(boost::asio::ip::tcp::socket socket, ssl::context& ctx, DataReceiveCallback data_receive, + DataSendDoneCallback data_send_done, + DataSendFailedCallback data_send_failed, OnIOErrorCallback on_error); #endif // ENABLE_SECURITY @@ -84,8 +91,7 @@ class WebSocketSession virtual void AsyncRead(boost::system::error_code ec); - virtual TransportAdapter::Error WriteDown( - ::protocol_handler::RawMessagePtr message); + virtual void WriteDown(Message message); virtual void Read(boost::system::error_code ec, std::size_t bytes_transferred); @@ -98,6 +104,8 @@ class WebSocketSession boost::asio::strand<boost::asio::io_context::executor_type> strand_; boost::beast::flat_buffer buffer_; DataReceiveCallback data_receive_; + DataSendDoneCallback data_send_done_; + DataSendFailedCallback data_send_failed_; OnIOErrorCallback on_io_error_; }; diff --git a/src/components/transport_manager/src/cloud/websocket_client_connection.cc b/src/components/transport_manager/src/cloud/websocket_client_connection.cc index 794cf57208..955ce17f67 100644 --- a/src/components/transport_manager/src/cloud/websocket_client_connection.cc +++ b/src/components/transport_manager/src/cloud/websocket_client_connection.cc @@ -284,6 +284,7 @@ TransportAdapter::Error WebsocketClientConnection::Disconnect() { } void WebsocketClientConnection::Shutdown() { + LOG4CXX_AUTO_TRACE(logger_); shutdown_ = true; if (thread_delegate_) { diff --git a/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc b/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc index 36f6dd98d0..8301c50a4e 100644 --- a/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc +++ b/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc @@ -521,6 +521,7 @@ DeviceSptr TransportAdapterImpl::GetWebEngineDevice() const { } DeviceSptr TransportAdapterImpl::AddDevice(DeviceSptr device) { + LOG4CXX_AUTO_TRACE(logger_); LOG4CXX_TRACE(logger_, "enter. device: " << device); DeviceSptr existing_device; bool same_device_found = false; @@ -530,7 +531,7 @@ DeviceSptr TransportAdapterImpl::AddDevice(DeviceSptr device) { existing_device = i->second; if (device->IsSameAs(existing_device.get())) { same_device_found = true; - LOG4CXX_DEBUG(logger_, "device " << device << "already exists"); + LOG4CXX_DEBUG(logger_, "Device " << device << " already exists"); break; } } @@ -539,7 +540,7 @@ DeviceSptr TransportAdapterImpl::AddDevice(DeviceSptr device) { } devices_mutex_.Release(); if (same_device_found) { - LOG4CXX_TRACE(logger_, "exit with TRUE. Condition: same_device_found"); + LOG4CXX_TRACE(logger_, "Exit with TRUE. Condition: same_device_found"); return existing_device; } else { device->set_connection_status(ConnectionStatus::PENDING); @@ -677,6 +678,7 @@ void TransportAdapterImpl::ConnectionCreated( ConnectionSPtr connection, const DeviceUID& device_id, const ApplicationHandle& app_handle) { + LOG4CXX_AUTO_TRACE(logger_); LOG4CXX_TRACE(logger_, "enter connection:" << connection << ", device_id: " << &device_id @@ -692,6 +694,7 @@ void TransportAdapterImpl::ConnectionCreated( void TransportAdapterImpl::DeviceDisconnected( const DeviceUID& device_handle, const DisconnectDeviceError& error) { + LOG4CXX_AUTO_TRACE(logger_); const DeviceUID device_uid = device_handle; LOG4CXX_TRACE( logger_, @@ -730,6 +733,7 @@ void TransportAdapterImpl::DeviceDisconnected( bool TransportAdapterImpl::IsSingleApplication( const DeviceUID& device_uid, const ApplicationHandle& app_uid) { + LOG4CXX_AUTO_TRACE(logger_); sync_primitives::AutoReadLock locker(connections_lock_); for (ConnectionMap::const_iterator it = connections_.begin(); it != connections_.end(); @@ -749,6 +753,7 @@ bool TransportAdapterImpl::IsSingleApplication( void TransportAdapterImpl::DisconnectDone(const DeviceUID& device_handle, const ApplicationHandle& app_handle) { + LOG4CXX_AUTO_TRACE(logger_); const DeviceUID device_uid = device_handle; const ApplicationHandle app_uid = app_handle; LOG4CXX_TRACE( @@ -775,6 +780,7 @@ void TransportAdapterImpl::DisconnectDone(const DeviceUID& device_handle, RemoveConnection(device_uid, app_uid); if (device_disconnected) { + LOG4CXX_DEBUG(logger_, "Removing device..."); RemoveDevice(device_uid); } @@ -1026,6 +1032,7 @@ void TransportAdapterImpl::RemoveFinalizedConnection( void TransportAdapterImpl::RemoveConnection( const DeviceUID& device_id, const ApplicationHandle& app_handle) { + LOG4CXX_AUTO_TRACE(logger_); ConnectionSPtr connection; connections_lock_.AcquireForWriting(); ConnectionMap::const_iterator it = @@ -1071,6 +1078,7 @@ ApplicationList TransportAdapterImpl::GetApplicationList( void TransportAdapterImpl::ConnectionFinished( const DeviceUID& device_id, const ApplicationHandle& app_handle) { + LOG4CXX_AUTO_TRACE(logger_); LOG4CXX_TRACE( logger_, "enter. device_id: " << &device_id << ", app_handle: " << &app_handle); @@ -1088,6 +1096,7 @@ void TransportAdapterImpl::ConnectionAborted( const DeviceUID& device_id, const ApplicationHandle& app_handle, const CommunicationError& error) { + LOG4CXX_AUTO_TRACE(logger_); ConnectionFinished(device_id, app_handle); for (TransportAdapterListenerList::iterator it = listeners_.begin(); it != listeners_.end(); @@ -1192,6 +1201,7 @@ bool TransportAdapterImpl::ToBeAutoConnected(DeviceSptr device) const { } bool TransportAdapterImpl::ToBeAutoDisconnected(DeviceSptr device) const { + LOG4CXX_AUTO_TRACE(logger_); return true; } diff --git a/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc b/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc index bf2d3dbdf4..2e411a4f87 100644 --- a/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc +++ b/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc @@ -203,6 +203,7 @@ void TransportAdapterListenerImpl::OnDisconnectDone( const TransportAdapter* adapter, const DeviceUID& device, const ApplicationHandle& app_id) { + LOG4CXX_AUTO_TRACE(logger_); LOG4CXX_TRACE(logger_, "enter. adapter: " << adapter << ", device: " << &device << ", application_id: " << &app_id); @@ -245,7 +246,9 @@ void TransportAdapterListenerImpl::OnDisconnectFailed( } void TransportAdapterListenerImpl::OnDisconnectDeviceDone( - const TransportAdapter* adapter, const DeviceUID& device) {} + const TransportAdapter* adapter, const DeviceUID& device) { + LOG4CXX_AUTO_TRACE(logger_); +} void TransportAdapterListenerImpl::OnDisconnectDeviceFailed( const TransportAdapter* adapter, diff --git a/src/components/transport_manager/src/transport_manager_impl.cc b/src/components/transport_manager/src/transport_manager_impl.cc index ddff4f3780..c8e5e431fd 100644 --- a/src/components/transport_manager/src/transport_manager_impl.cc +++ b/src/components/transport_manager/src/transport_manager_impl.cc @@ -1305,14 +1305,10 @@ void TransportManagerImpl::Handle(TransportAdapterEvent event) { // TODO(YK): start timer here to wait before notify caller // and remove unsent messages LOG4CXX_ERROR(logger_, "Transport adapter failed to send data"); - // TODO(YK): potential error case -> thread unsafe - // update of message content - if (event.event_data.use_count() != 0) { - event.event_data->set_waiting(true); - } else { - LOG4CXX_DEBUG(logger_, "Data is invalid"); - } - LOG4CXX_DEBUG(logger_, "eevent_type = ON_SEND_FAIL"); + RaiseEvent(&TransportManagerListener::OnTMMessageSendFailed, + DataSendError(), + event.event_data); + LOG4CXX_DEBUG(logger_, "event_type = ON_SEND_FAIL"); break; } case EventTypeEnum::ON_RECEIVED_DONE: { @@ -1423,11 +1419,6 @@ void TransportManagerImpl::Handle(::protocol_handler::RawMessagePtr msg) { } TransportAdapter* transport_adapter = connection->transport_adapter; - LOG4CXX_DEBUG(logger_, - "Got adapter " << transport_adapter << "[" - << transport_adapter->GetDeviceType() << "]" - << " by session id " << msg->connection_key()); - if (NULL == transport_adapter) { std::string error_text = "Transport adapter is not found"; LOG4CXX_ERROR(logger_, error_text); @@ -1435,6 +1426,10 @@ void TransportManagerImpl::Handle(::protocol_handler::RawMessagePtr msg) { DataSendError(error_text), msg); } else { + LOG4CXX_DEBUG(logger_, + "Got adapter " << transport_adapter << "[" + << transport_adapter->GetDeviceType() << "]" + << " by session id " << msg->connection_key()); if (TransportAdapter::OK == transport_adapter->SendData( connection->device, connection->application, msg)) { diff --git a/src/components/transport_manager/src/websocket_server/websocket_connection.cc b/src/components/transport_manager/src/websocket_server/websocket_connection.cc index 7bcc4baef2..601110af2f 100644 --- a/src/components/transport_manager/src/websocket_server/websocket_connection.cc +++ b/src/components/transport_manager/src/websocket_server/websocket_connection.cc @@ -49,17 +49,15 @@ WebSocketConnection<WebSocketSession<> >::WebSocketConnection( , app_handle_(app_handle) , session_(new WebSocketSession<>( std::move(socket), - std::bind( - &WebSocketConnection::DataReceive, this, std::placeholders::_1), - std::bind(&WebSocketConnection::OnError, this))) + [this](Message frame) { DataReceive(frame); }, + [this](Message frame) { DataSendDone(frame); }, + [this](Message frame) { DataSendFailed(frame); }, + [this]() { OnError(); })) , controller_(controller) , shutdown_(false) , thread_delegate_(new LoopThreadDelegate( &message_queue_, - std::bind(&WebSocketSession<>::WriteDown, - session_.get(), - std::placeholders::_1), - std::bind(&WebSocketConnection::OnError, this))) + [this](Message frame) { session_->WriteDown(frame); })) , thread_(threads::CreateThread("WS Async Send", thread_delegate_)) { thread_->start(threads::ThreadOptions()); } @@ -77,17 +75,15 @@ WebSocketConnection<WebSocketSecureSession<> >::WebSocketConnection( , session_(new WebSocketSecureSession<>( std::move(socket), ctx, - std::bind( - &WebSocketConnection::DataReceive, this, std::placeholders::_1), - std::bind(&WebSocketConnection::OnError, this))) + [this](Message frame) { DataReceive(frame); }, + [this](Message frame) { DataSendDone(frame); }, + [this](Message frame) { DataSendFailed(frame); }, + [this]() { OnError(); })) , controller_(controller) , shutdown_(false) , thread_delegate_(new LoopThreadDelegate( &message_queue_, - std::bind(&WebSocketSecureSession<>::WriteDown, - session_.get(), - std::placeholders::_1), - std::bind(&WebSocketConnection::OnError, this))) + [this](Message frame) { session_->WriteDown(frame); })) , thread_(threads::CreateThread("WS Async Send", thread_delegate_)) { thread_->start(threads::ThreadOptions()); } @@ -105,6 +101,16 @@ template <typename Session> void WebSocketConnection<Session>::OnError() { LOG4CXX_AUTO_TRACE(wsc_logger_); + if (IsShuttingDown()) { + LOG4CXX_DEBUG(wsc_logger_, "Session is shutting down..."); + return; + } + + Message message_ptr; + while (message_queue_.pop(message_ptr)) { + DataSendFailed(message_ptr); + } + controller_->ConnectionAborted( device_uid_, app_handle_, CommunicationError()); @@ -124,7 +130,7 @@ TransportAdapter::Error WebSocketConnection<Session>::Disconnect() { template <typename Session> TransportAdapter::Error WebSocketConnection<Session>::SendData( - ::protocol_handler::RawMessagePtr message) { + Message message) { if (IsShuttingDown()) { return TransportAdapter::BAD_STATE; } @@ -135,12 +141,21 @@ TransportAdapter::Error WebSocketConnection<Session>::SendData( } template <typename Session> -void WebSocketConnection<Session>::DataReceive( - protocol_handler::RawMessagePtr frame) { +void WebSocketConnection<Session>::DataReceive(Message frame) { controller_->DataReceiveDone(device_uid_, app_handle_, frame); } template <typename Session> +void WebSocketConnection<Session>::DataSendDone(Message frame) { + controller_->DataSendDone(device_uid_, app_handle_, frame); +} + +template <typename Session> +void WebSocketConnection<Session>::DataSendFailed(Message frame) { + controller_->DataSendFailed(device_uid_, app_handle_, frame, DataSendError()); +} + +template <typename Session> void WebSocketConnection<Session>::Run() { LOG4CXX_AUTO_TRACE(wsc_logger_); session_->AsyncAccept(); @@ -169,11 +184,8 @@ bool WebSocketConnection<Session>::IsShuttingDown() { template <typename Session> WebSocketConnection<Session>::LoopThreadDelegate::LoopThreadDelegate( MessageQueue<Message, AsyncQueue>* message_queue, - DataWriteCallback data_write, - OnIOErrorCallback on_io_error) - : message_queue_(*message_queue) - , data_write_(data_write) - , on_io_error_(on_io_error) {} + DataWriteCallback data_write) + : message_queue_(*message_queue), data_write_(data_write) {} template <typename Session> void WebSocketConnection<Session>::LoopThreadDelegate::threadMain() { @@ -186,22 +198,14 @@ void WebSocketConnection<Session>::LoopThreadDelegate::threadMain() { template <typename Session> void WebSocketConnection<Session>::LoopThreadDelegate::exitThreadMain() { - if (!message_queue_.IsShuttingDown()) { - message_queue_.Shutdown(); - } + SetShutdown(); } template <typename Session> void WebSocketConnection<Session>::LoopThreadDelegate::DrainQueue() { Message message_ptr; while (!message_queue_.IsShuttingDown() && message_queue_.pop(message_ptr)) { - auto res = data_write_(message_ptr); - if (TransportAdapter::FAIL == res) { - LOG4CXX_WARN(wsc_logger_, - "Writing to websocket stream failed. Will now close " - "websocket connection."); - on_io_error_(); - } + data_write_(message_ptr); } } diff --git a/src/components/transport_manager/src/websocket_server/websocket_secure_session.cc b/src/components/transport_manager/src/websocket_server/websocket_secure_session.cc index 9be94119b6..46a1267cab 100644 --- a/src/components/transport_manager/src/websocket_server/websocket_secure_session.cc +++ b/src/components/transport_manager/src/websocket_server/websocket_secure_session.cc @@ -42,9 +42,15 @@ WebSocketSecureSession<ExecutorType>::WebSocketSecureSession( tcp::socket socket, ssl::context& ctx, DataReceiveCallback data_receive, + DataSendDoneCallback data_send_done, + DataSendFailedCallback data_send_failed, OnIOErrorCallback on_error) - : WebSocketSession<ExecutorType>( - std::move(socket), ctx, data_receive, on_error) {} + : WebSocketSession<ExecutorType>(std::move(socket), + ctx, + data_receive, + data_send_done, + data_send_failed, + on_error) {} template <typename ExecutorType> void WebSocketSecureSession<ExecutorType>::AsyncAccept() { diff --git a/src/components/transport_manager/src/websocket_server/websocket_session.cc b/src/components/transport_manager/src/websocket_server/websocket_session.cc index ab62530963..8826243777 100644 --- a/src/components/transport_manager/src/websocket_server/websocket_session.cc +++ b/src/components/transport_manager/src/websocket_server/websocket_session.cc @@ -41,11 +41,15 @@ template <> WebSocketSession<tcp::socket&>::WebSocketSession( boost::asio::ip::tcp::socket socket, DataReceiveCallback data_receive, + DataSendDoneCallback data_send_done, + DataSendFailedCallback data_send_failed, OnIOErrorCallback on_error) : socket_(std::move(socket)) , ws_(socket_) , strand_(ws_.get_executor()) , data_receive_(data_receive) + , data_send_done_(data_send_done) + , data_send_failed_(data_send_failed) , on_io_error_(on_error) { ws_.binary(true); } @@ -56,11 +60,15 @@ WebSocketSession<ssl::stream<tcp::socket&> >::WebSocketSession( boost::asio::ip::tcp::socket socket, ssl::context& ctx, DataReceiveCallback data_receive, + DataSendDoneCallback data_send_done, + DataSendFailedCallback data_send_failed, OnIOErrorCallback on_error) : socket_(std::move(socket)) , ws_(socket_, ctx) , strand_(ws_.get_executor()) , data_receive_(data_receive) + , data_send_done_(data_send_done) + , data_send_failed_(data_send_failed) , on_io_error_(on_error) { ws_.binary(true); } @@ -98,17 +106,17 @@ void WebSocketSession<ExecutorType>::AsyncRead(boost::system::error_code ec) { } template <typename ExecutorType> -TransportAdapter::Error WebSocketSession<ExecutorType>::WriteDown( - ::protocol_handler::RawMessagePtr message) { +void WebSocketSession<ExecutorType>::WriteDown(Message message) { boost::system::error_code ec; ws_.write(boost::asio::buffer(message->data(), message->data_size()), ec); if (ec) { LOG4CXX_ERROR(ws_logger_, "A system error has occurred: " << ec.message()); - return TransportAdapter::FAIL; + data_send_failed_(message); + on_io_error_(); + return; } - - return TransportAdapter::OK; + data_send_done_(message); } template <typename ExecutorType> @@ -131,8 +139,8 @@ void WebSocketSession<ExecutorType>::Read(boost::system::error_code ec, "Msg: " << boost::beast::buffers_to_string(buffer_.data()) << " Size: " << size;); - ::protocol_handler::RawMessagePtr frame( - new protocol_handler::RawMessage(0, 0, data, size, false)); + auto frame = + std::make_shared<protocol_handler::RawMessage>(0, 0, data, size, false); data_receive_(frame); diff --git a/src/components/transport_manager/test/transport_manager_impl_test.cc b/src/components/transport_manager/test/transport_manager_impl_test.cc index db4813be9a..227367e750 100644 --- a/src/components/transport_manager/test/transport_manager_impl_test.cc +++ b/src/components/transport_manager/test/transport_manager_impl_test.cc @@ -633,15 +633,17 @@ TEST_F(TransportManagerImplTest, SendMessageToDevice_SendDone) { EXPECT_TRUE(waiter.WaitFor(1, kAsyncExpectationsTimeout)); } -TEST_F(TransportManagerImplTest, SendMessageFailed_GetHandleSendFailed) { +TEST_F( + TransportManagerImplTest, + SendMessageToDevice_AdapterSendDataOkAndOnSendFailEvent_OnTMMessageSendFailed) { // Arrange HandleConnection(); TestAsyncWaiter waiter; EXPECT_CALL(*mock_adapter_, SendData(mac_address_, application_id_, test_message_)) - .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), - Return(TransportAdapter::FAIL))); + .WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), Return(TransportAdapter::OK))); #ifdef TELEMETRY_MONITOR EXPECT_CALL(mock_metric_observer_, StartRawMsg(test_message_.get())); diff --git a/tools/rpc_spec b/tools/rpc_spec -Subproject 754845ae77411a4b1db5c6dfbafd1c5164d2b29 +Subproject 0d7185781f4dd1a316137a052e1126cdb6e3f47 |