diff options
30 files changed, 324 insertions, 145 deletions
diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h index 4ddf1e1388..dade5f75c8 100644 --- a/src/components/application_manager/include/application_manager/application.h +++ b/src/components/application_manager/include/application_manager/application.h @@ -980,6 +980,8 @@ class Application : public virtual InitialApplicationData, */ const virtual std::string cloud_app_certificate() = 0; + virtual bool is_cloud_app() const = 0; + /** * @brief Set cloud app endpoint */ 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 26d8cd6159..f2072a9c37 100644 --- a/src/components/application_manager/include/application_manager/application_impl.h +++ b/src/components/application_manager/include/application_manager/application_impl.h @@ -443,6 +443,8 @@ class ApplicationImpl : public virtual Application, */ const std::string cloud_app_certificate() OVERRIDE; + bool is_cloud_app() const OVERRIDE; + /** * @brief Set cloud app endpoint */ diff --git a/src/components/application_manager/include/application_manager/application_manager_impl.h b/src/components/application_manager/include/application_manager/application_manager_impl.h index 20b8c561a3..f235a4e482 100644 --- a/src/components/application_manager/include/application_manager/application_manager_impl.h +++ b/src/components/application_manager/include/application_manager/application_manager_impl.h @@ -367,6 +367,9 @@ class ApplicationManagerImpl const transport_manager::DeviceInfo& device_info, connection_handler::DeviceHandle device_id); + hmi_apis::Common_CloudConnectionStatus::eType GetCloudAppConnectionStatus( + ApplicationConstSharedPtr app) const; + /* * @brief Returns unique correlation ID for HMI request * @@ -492,9 +495,6 @@ class ApplicationManagerImpl // typedef for Applications list const iterator typedef ApplictionSet::const_iterator ApplictionSetConstIt; - DataAccessor<AppsWaitRegistrationSet> apps_waiting_for_registration() const; - ApplicationConstSharedPtr waiting_app(const uint32_t hmi_id) const; - /** * @brief Notification from PolicyHandler about PTU. * Compares AppHMIType between saved in app and received from PTU. If they are diff --git a/src/components/application_manager/include/application_manager/smart_object_keys.h b/src/components/application_manager/include/application_manager/smart_object_keys.h index 62192da391..5e6a3bb377 100644 --- a/src/components/application_manager/include/application_manager/smart_object_keys.h +++ b/src/components/application_manager/include/application_manager/smart_object_keys.h @@ -76,7 +76,7 @@ extern const char* ngn_media_screen_app_name; extern const char* vr_synonyms; extern const char* uses_vehicle_data; extern const char* is_media_application; -extern const char* greyOut; +extern const char* grey_out; extern const char* language_desired; extern const char* auto_activated_id; extern const char* app_type; @@ -192,6 +192,8 @@ extern const char* enabled; extern const char* cloud_app_auth_token; extern const char* cloud_transport_type; extern const char* hybrid_app_preference; +extern const char* is_cloud_application; +extern const char* cloud_connection_status; // PutFile extern const char* sync_file_name; 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 542fdac5f8..d0e70e906a 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 @@ -128,7 +128,7 @@ class RegisterAppInterfaceRequest * **/ void SendOnAppRegisteredNotificationToHMI( - const app_mngr::Application& application_impl, + app_mngr::ApplicationConstSharedPtr app, bool resumption = false, bool need_restore_vr = false); /* diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/sdl_activate_app_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/sdl_activate_app_request.cc index f89ae1f697..bfe7adec11 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/sdl_activate_app_request.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/sdl_activate_app_request.cc @@ -115,6 +115,8 @@ void SDLActivateAppRequest::Run() { LOG4CXX_AUTO_TRACE(logger_); using namespace hmi_apis::FunctionID; + ApplicationConstSharedPtr app = + application_manager_.WaitingApplicationByID(app_id()); if (application_manager_.state_controller().IsStateActive( HmiState::STATE_ID_DEACTIVATE_HMI)) { LOG4CXX_DEBUG(logger_, @@ -124,6 +126,10 @@ void SDLActivateAppRequest::Run() { static_cast<eType>(function_id()), hmi_apis::Common_Result::REJECTED, "HMIDeactivate is active"); + } else if (app && !app->IsRegistered() && app->is_cloud_app()) { + LOG4CXX_DEBUG(logger_, "Starting cloud application."); + subscribe_on_event(BasicCommunication_OnAppRegistered); + application_manager_.connection_handler().ConnectToDevice(app->device()); } else { const uint32_t application_id = app_id(); policy_handler_.OnActivateApp(application_id, correlation_id()); @@ -139,7 +145,7 @@ void SDLActivateAppRequest::Run() { const uint32_t application_id = app_id(); ApplicationConstSharedPtr app_to_activate = - application_manager_.application(application_id); + application_manager_.application_by_hmi_app(application_id); if (!app_to_activate) { LOG4CXX_WARN( @@ -181,6 +187,12 @@ void SDLActivateAppRequest::Run() { LOG4CXX_DEBUG(logger_, "Application is registered. Activating."); policy_handler_.OnActivateApp(application_id, correlation_id()); return; + } else if (app_to_activate->is_cloud_app()) { + LOG4CXX_DEBUG(logger_, "Starting cloud application."); + subscribe_on_event(BasicCommunication_OnAppRegistered); + application_manager_.connection_handler().ConnectToDevice( + app_to_activate->device()); + return; } connection_handler::DeviceHandle device_handle = app_to_activate->device(); @@ -262,7 +274,7 @@ uint32_t SDLActivateAppRequest::hmi_app_id( LOG4CXX_DEBUG(logger_, application << " section is absent in the message."); return 0; } - if (so[msg_params][application].keyExists(strings::app_id)) { + if (!so[msg_params][application].keyExists(strings::app_id)) { LOG4CXX_DEBUG(logger_, strings::app_id << " section is absent in the message."); return 0; 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 7957d9e055..f8d3267441 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 @@ -346,19 +346,6 @@ void RegisterAppInterfaceRequest::Run() { application->set_msg_version(module_version); } - // For resuming application need to restore hmi_app_id from resumeCtrl - resumption::ResumeCtrl& resumer = application_manager_.resume_controller(); - const std::string& device_mac = application->mac_address(); - - // there is side affect with 2 mobile app with the same mobile app_id - if (resumer.IsApplicationSaved(policy_app_id, device_mac)) { - application->set_hmi_application_id( - resumer.GetHMIApplicationID(policy_app_id, device_mac)); - } else { - application->set_hmi_application_id( - application_manager_.GenerateNewHMIAppID()); - } - application->set_is_media_application( msg_params[strings::is_media_application].asBool()); @@ -451,6 +438,8 @@ void RegisterAppInterfaceRequest::Run() { FillDeviceInfo(&device_info); } + const std::string& device_mac = application->mac_address(); + GetPolicyHandler().SetDeviceInfo(device_mac, device_info); SendRegisterAppInterfaceResponseToMobile(ApplicationType::kNewApplication); @@ -817,7 +806,7 @@ void RegisterAppInterfaceRequest::SendRegisterAppInterfaceResponseToMobile( SendResponse(true, result_code, add_info.c_str(), &response_params); SendOnAppRegisteredNotificationToHMI( - *(application.get()), resumption, need_restore_vr); + application, resumption, need_restore_vr); if (msg_params.keyExists(strings::app_hmi_type)) { GetPolicyHandler().SetDefaultHmiTypes(application->policy_app_id(), &(msg_params[strings::app_hmi_type])); @@ -877,9 +866,7 @@ void RegisterAppInterfaceRequest::SendChangeRegistrationOnHMI( } void RegisterAppInterfaceRequest::SendOnAppRegisteredNotificationToHMI( - const app_mngr::Application& application_impl, - bool resumption, - bool need_restore_vr) { + ApplicationConstSharedPtr app, bool resumption, bool need_restore_vr) { using namespace smart_objects; SmartObjectSPtr notification = std::make_shared<SmartObject>(SmartType_Map); if (!notification) { @@ -903,15 +890,15 @@ void RegisterAppInterfaceRequest::SendOnAppRegisteredNotificationToHMI( msg_params[strings::resume_vr_grammars] = need_restore_vr; } - if (application_impl.vr_synonyms()) { - msg_params[strings::vr_synonyms] = *(application_impl.vr_synonyms()); + if (app->vr_synonyms()) { + msg_params[strings::vr_synonyms] = *(app->vr_synonyms()); } - if (application_impl.tts_name()) { - msg_params[strings::tts_name] = *(application_impl.tts_name()); + if (app->tts_name()) { + msg_params[strings::tts_name] = *(app->tts_name()); } - const std::string policy_app_id = application_impl.policy_app_id(); + const std::string policy_app_id = app->policy_app_id(); std::string priority; GetPolicyHandler().GetPriority(policy_app_id, &priority); @@ -921,100 +908,13 @@ void RegisterAppInterfaceRequest::SendOnAppRegisteredNotificationToHMI( msg_params[strings::msg_params] = SmartObject(SmartType_Map); smart_objects::SmartObject& application = msg_params[strings::application]; - application[strings::app_name] = application_impl.name(); - application[strings::app_id] = application_impl.app_id(); - application[hmi_response::policy_app_id] = policy_app_id; - if (file_system::FileExists(application_impl.app_icon_path())) { - application[strings::icon] = application_impl.app_icon_path(); - } - - const smart_objects::SmartObject* ngn_media_screen_name = - application_impl.ngn_media_screen_name(); - if (ngn_media_screen_name) { - application[strings::ngn_media_screen_app_name] = *ngn_media_screen_name; - } - - application[strings::hmi_display_language_desired] = - static_cast<int32_t>(application_impl.ui_language()); - - application[strings::is_media_application] = - application_impl.is_media_application(); - - const smart_objects::SmartObject* app_type = application_impl.app_types(); - if (app_type) { - application[strings::app_type] = *app_type; - } - - const policy::RequestType::State app_request_types_state = - GetPolicyHandler().GetAppRequestTypeState(policy_app_id); - if (policy::RequestType::State::AVAILABLE == app_request_types_state) { - const auto request_types = - GetPolicyHandler().GetAppRequestTypes(policy_app_id); - application[strings::request_type] = SmartObject(SmartType_Array); - smart_objects::SmartObject& request_types_array = - application[strings::request_type]; - - size_t index = 0; - for (auto it : request_types) { - request_types_array[index] = it; - ++index; - } - } else if (policy::RequestType::State::EMPTY == app_request_types_state) { - application[strings::request_type] = SmartObject(SmartType_Array); - } - - const policy::RequestSubType::State app_request_subtypes_state = - GetPolicyHandler().GetAppRequestSubTypeState(policy_app_id); - if (policy::RequestSubType::State::AVAILABLE == app_request_subtypes_state) { - const auto request_subtypes = - GetPolicyHandler().GetAppRequestSubTypes(policy_app_id); - application[strings::request_subtype] = SmartObject(SmartType_Array); - smart_objects::SmartObject& request_subtypes_array = - application[strings::request_subtype]; - - size_t index = 0; - for (auto it : request_subtypes) { - request_subtypes_array[index] = it; - ++index; - } - } else if (policy::RequestSubType::State::EMPTY == - app_request_subtypes_state) { - application[strings::request_subtype] = SmartObject(SmartType_Array); - } - const protocol_handler::SessionObserver& session_observer = application_manager_.connection_handler().get_session_observer(); - - application[strings::device_info] = SmartObject(SmartType_Map); - smart_objects::SmartObject& device_info = application[strings::device_info]; - MessageHelper::CreateDeviceInfo(application_impl.device(), - session_observer, - GetPolicyHandler(), - application_manager_, - &device_info); - - if (application_impl.secondary_device() != 0) { - application[strings::secondary_device_info] = SmartObject(SmartType_Map); - smart_objects::SmartObject& secondary_device_info = - application[strings::secondary_device_info]; - MessageHelper::CreateDeviceInfo(application_impl.secondary_device(), - session_observer, - GetPolicyHandler(), - application_manager_, - &secondary_device_info); - } - - const smart_objects::SmartObject* day_color_scheme = - application_impl.day_color_scheme(); - if (day_color_scheme) { - application[strings::day_color_scheme] = *day_color_scheme; - } - - const smart_objects::SmartObject* night_color_scheme = - application_impl.night_color_scheme(); - if (night_color_scheme) { - application[strings::night_color_scheme] = *night_color_scheme; - } + MessageHelper::CreateHMIApplicationStruct(app, + session_observer, + GetPolicyHandler(), + &application, + application_manager_); DCHECK(rpc_service_.ManageHMICommand(notification)); } diff --git a/src/components/application_manager/src/application_impl.cc b/src/components/application_manager/src/application_impl.cc index 31df4e821b..1f372122c0 100644 --- a/src/components/application_manager/src/application_impl.cc +++ b/src/components/application_manager/src/application_impl.cc @@ -1184,6 +1184,12 @@ const std::string ApplicationImpl::cloud_app_certificate() { return certificate_; } +bool ApplicationImpl::is_cloud_app() const { + return !endpoint_.empty() && + hybrid_app_preference_ != + hmi_apis::Common_CloudConnectionStatus::MOBILE; +} + void ApplicationImpl::set_cloud_app_endpoint(const std::string& endpoint) { endpoint_ = endpoint; } diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 1cec8b5ca2..79bd00b37d 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -541,6 +541,7 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( app_name, GetPolicyHandler().GetStatisticManager(), *this)); + if (!application) { std::shared_ptr<smart_objects::SmartObject> response( MessageHelper::CreateNegativeResponse( @@ -610,10 +611,45 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( // Keep HMI add id in case app is present in "waiting for registration" list apps_to_register_list_lock_ptr_->Acquire(); - AppsWaitRegistrationSet::iterator it = apps_to_register_.find(application); - if (apps_to_register_.end() != it) { + PolicyAppIdPredicate finder(application->policy_app_id()); + ApplicationSet::iterator it = + std::find_if(apps_to_register_.begin(), apps_to_register_.end(), finder); + + if (apps_to_register_.end() == it) { + DevicePredicate finder(application->device()); + it = std::find_if( + apps_to_register_.begin(), apps_to_register_.end(), finder); + + bool found = apps_to_register_.end() != it; + bool is_mismatched_cloud_app = found && (*it)->is_cloud_app() && + policy_app_id != (*it)->policy_app_id(); + + // Reject registration request if a cloud app registers with the incorrect + // appID + if (is_mismatched_cloud_app) { + std::shared_ptr<smart_objects::SmartObject> response( + MessageHelper::CreateNegativeResponse( + connection_key, + mobile_apis::FunctionID::RegisterAppInterfaceID, + message[strings::params][strings::correlation_id].asUInt(), + mobile_apis::Result::DISALLOWED)); + (*response)[strings::msg_params][strings::info] = + "Cloud app registered with incorrect app id"; + rpc_service_->ManageMobileCommand(response, + commands::Command::SOURCE_SDL); + return ApplicationSharedPtr(); + } + } else { application->set_hmi_application_id((*it)->hmi_app_id()); - apps_to_register_.erase(application); + + // Set cloud app parameters + application->set_cloud_app_endpoint((*it)->cloud_app_endpoint()); + application->set_cloud_app_certificate((*it)->cloud_app_certificate()); + application->set_cloud_app_auth_token((*it)->cloud_app_authtoken()); + application->set_cloud_app_transport_type( + (*it)->cloud_app_transport_type()); + application->set_hybrid_app_preference((*it)->hybrid_app_preference()); + apps_to_register_.erase(it); } apps_to_register_list_lock_ptr_->Release(); @@ -853,7 +889,7 @@ void ApplicationManagerImpl::CreatePendingApplication( *this)); if (!application) { - LOG4CXX_INFO(logger_, "Could not streate application"); + LOG4CXX_INFO(logger_, "Could not create application"); return; } @@ -894,6 +930,24 @@ void ApplicationManagerImpl::CreatePendingApplication( SendUpdateAppList(); } +hmi_apis::Common_CloudConnectionStatus::eType +ApplicationManagerImpl::GetCloudAppConnectionStatus( + ApplicationConstSharedPtr app) const { + transport_manager::ConnectionStatus status = + connection_handler().GetConnectionStatus(app->device()); + switch (status) { + case transport_manager::ConnectionStatus::CONNECTED: + return hmi_apis::Common_CloudConnectionStatus::CONNECTED; + case transport_manager::ConnectionStatus::RETRY: + return hmi_apis::Common_CloudConnectionStatus::RETRY; + case transport_manager::ConnectionStatus::PENDING: + case transport_manager::ConnectionStatus::CLOSING: + return hmi_apis::Common_CloudConnectionStatus::NOT_CONNECTED; + default: + return hmi_apis::Common_CloudConnectionStatus::INVALID_ENUM; + } +} + uint32_t ApplicationManagerImpl::GetNextHMICorrelationID() { if (corelation_id_ < max_corelation_id_) { corelation_id_++; diff --git a/src/components/application_manager/src/message_helper/message_helper.cc b/src/components/application_manager/src/message_helper/message_helper.cc index 2f86c50013..58d5171f84 100644 --- a/src/components/application_manager/src/message_helper/message_helper.cc +++ b/src/components/application_manager/src/message_helper/message_helper.cc @@ -1542,15 +1542,19 @@ bool MessageHelper::CreateHMIApplicationStruct( message = smart_objects::SmartObject(smart_objects::SmartType_Map); message[strings::app_name] = app->name(); message[strings::app_id] = app->hmi_app_id(); + + const std::string policy_app_id = app->policy_app_id(); + message[hmi_response::policy_app_id] = policy_app_id; + const std::string icon_path = app->app_icon_path(); - if (!icon_path.empty()) { + if (file_system::FileExists(app->app_icon_path())) { message[strings::icon] = icon_path; } if (app->IsRegistered()) { message[strings::hmi_display_language_desired] = app->ui_language(); message[strings::is_media_application] = app->is_media_application(); } else { - message[strings::greyOut] = app->is_greyed_out(); + message[strings::grey_out] = app->is_greyed_out(); } if (app->tts_name() && !app->tts_name()->empty()) { message[json::ttsName] = *(app->tts_name()); @@ -1566,6 +1570,46 @@ bool MessageHelper::CreateHMIApplicationStruct( message[strings::app_type] = *app_types; } + const policy::RequestType::State app_request_types_state = + policy_handler.GetAppRequestTypeState(policy_app_id); + if (policy::RequestType::State::AVAILABLE == app_request_types_state) { + const auto request_types = policy_handler.GetAppRequestTypes(policy_app_id); + message[strings::request_type] = + SmartObject(smart_objects::SmartType_Array); + smart_objects::SmartObject& request_types_array = + message[strings::request_type]; + + size_t index = 0; + for (auto it : request_types) { + request_types_array[index] = it; + ++index; + } + } else if (policy::RequestType::State::EMPTY == app_request_types_state) { + message[strings::request_type] = + SmartObject(smart_objects::SmartType_Array); + } + + const policy::RequestSubType::State app_request_subtypes_state = + policy_handler.GetAppRequestSubTypeState(policy_app_id); + if (policy::RequestSubType::State::AVAILABLE == app_request_subtypes_state) { + const auto request_subtypes = + policy_handler.GetAppRequestSubTypes(policy_app_id); + message[strings::request_subtype] = + SmartObject(smart_objects::SmartType_Array); + smart_objects::SmartObject& request_subtypes_array = + message[strings::request_subtype]; + + size_t index = 0; + for (auto it : request_subtypes) { + request_subtypes_array[index] = it; + ++index; + } + } else if (policy::RequestSubType::State::EMPTY == + app_request_subtypes_state) { + message[strings::request_subtype] = + SmartObject(smart_objects::SmartType_Array); + } + if (day_color_scheme) { message[strings::day_color_scheme] = *day_color_scheme; } @@ -1592,6 +1636,12 @@ bool MessageHelper::CreateHMIApplicationStruct( &secondary_device_info); } + message[strings::is_cloud_application] = app->is_cloud_app(); + if (app->is_cloud_app()) { + message[strings::cloud_connection_status] = + app_mngr.GetCloudAppConnectionStatus(app); + } + return true; } diff --git a/src/components/application_manager/src/smart_object_keys.cc b/src/components/application_manager/src/smart_object_keys.cc index 3e2951c553..70581466eb 100644 --- a/src/components/application_manager/src/smart_object_keys.cc +++ b/src/components/application_manager/src/smart_object_keys.cc @@ -43,7 +43,7 @@ const char* ngn_media_screen_app_name = "ngnMediaScreenAppName"; const char* vr_synonyms = "vrSynonyms"; const char* uses_vehicle_data = "usesVehicleData"; const char* is_media_application = "isMediaApplication"; -const char* greyOut = "greyOut"; +const char* grey_out = "greyOut"; const char* language_desired = "languageDesired"; const char* auto_activated_id = "autoActivateID"; const char* app_type = "appType"; @@ -159,6 +159,8 @@ const char* enabled = "enabled"; const char* cloud_app_auth_token = "cloudAppAuthToken"; const char* cloud_transport_type = "cloudTransportType"; const char* hybrid_app_preference = "hybridAppPreference"; +const char* is_cloud_application = "isCloudApplication"; +const char* cloud_connection_status = "cloudConnectionStatus"; // PutFile const char* sync_file_name = "syncFileName"; 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 fe16e8ce6e..aaa2a105e4 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 @@ -340,6 +340,7 @@ class MockApplication : public ::application_manager::Application { MOCK_METHOD1(RemoveExtension, bool(application_manager::AppExtensionUID uid)); MOCK_CONST_METHOD0(Extensions, const std::list<application_manager::AppExtensionPtr>&()); + MOCK_CONST_METHOD1(is_cloud_app, bool()); MOCK_CONST_METHOD0(is_remote_control_supported, bool()); MOCK_METHOD1(set_remote_control_supported, void(const bool allow)); }; diff --git a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h index 7be94c5f70..4d4e31f999 100644 --- a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h +++ b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h @@ -106,6 +106,9 @@ class ConnectionHandlerImpl */ void ConnectToDevice(connection_handler::DeviceHandle device_handle) OVERRIDE; + transport_manager::ConnectionStatus GetConnectionStatus( + const DeviceHandle& device_handle) const OVERRIDE; + /** * @brief RunAppOnDevice allows to run specific application on the certain *device. diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc index 318224fcc7..77eb38b8bc 100644 --- a/src/components/connection_handler/src/connection_handler_impl.cc +++ b/src/components/connection_handler/src/connection_handler_impl.cc @@ -1294,6 +1294,11 @@ void ConnectionHandlerImpl::ConnectToDevice( } } +transport_manager::ConnectionStatus ConnectionHandlerImpl::GetConnectionStatus( + const DeviceHandle& device_handle) const { + return transport_manager_.GetConnectionStatus(device_handle); +} + void ConnectionHandlerImpl::RunAppOnDevice(const std::string& device_mac, const std::string& bundle_id) const { for (DeviceMap::const_iterator i = device_list_.begin(); diff --git a/src/components/include/application_manager/application_manager.h b/src/components/include/application_manager/application_manager.h index e6e5c89f45..e1907e25f0 100644 --- a/src/components/include/application_manager/application_manager.h +++ b/src/components/include/application_manager/application_manager.h @@ -427,6 +427,9 @@ class ApplicationManager { virtual void OnHMIStartedCooperation() = 0; + virtual hmi_apis::Common_CloudConnectionStatus::eType + GetCloudAppConnectionStatus(ApplicationConstSharedPtr app) const = 0; + virtual bool IsHMICooperating() const = 0; /** * @brief Notifies all components interested in Vehicle Data update diff --git a/src/components/include/connection_handler/connection_handler.h b/src/components/include/connection_handler/connection_handler.h index 93939fc782..6d1e9e7c97 100644 --- a/src/components/include/connection_handler/connection_handler.h +++ b/src/components/include/connection_handler/connection_handler.h @@ -79,6 +79,9 @@ class ConnectionHandler { virtual void ConnectToDevice( connection_handler::DeviceHandle device_handle) = 0; + virtual transport_manager::ConnectionStatus GetConnectionStatus( + const DeviceHandle& device_handle) const = 0; + /** * @brief RunAppOnDevice allows to run specific application on the certain *device. diff --git a/src/components/include/test/application_manager/mock_application_manager.h b/src/components/include/test/application_manager/mock_application_manager.h index 7f5f17a93d..e18d68cfba 100644 --- a/src/components/include/test/application_manager/mock_application_manager.h +++ b/src/components/include/test/application_manager/mock_application_manager.h @@ -166,6 +166,9 @@ class MockApplicationManager : public application_manager::ApplicationManager { MOCK_METHOD1(EndAudioPassThru, bool(uint32_t app_id)); MOCK_METHOD1(ConnectToDevice, void(const std::string& device_mac)); MOCK_METHOD0(OnHMIStartedCooperation, void()); + MOCK_CONST_METHOD1(GetCloudAppConnectionStatus, + hmi_apis::Common_CloudConnectionStatus::eType( + ApplicationConstSharedPtr app)); MOCK_CONST_METHOD0(IsHMICooperating, bool()); MOCK_METHOD2(IviInfoUpdated, void(mobile_apis::VehicleDataType::eType vehicle_info, diff --git a/src/components/include/test/connection_handler/mock_connection_handler.h b/src/components/include/test/connection_handler/mock_connection_handler.h index 2de3a0f9a7..c8d977b61c 100644 --- a/src/components/include/test/connection_handler/mock_connection_handler.h +++ b/src/components/include/test/connection_handler/mock_connection_handler.h @@ -60,6 +60,8 @@ class MockConnectionHandler : public connection_handler::ConnectionHandler { MOCK_METHOD0(StartTransportManager, void()); MOCK_METHOD1(ConnectToDevice, void(connection_handler::DeviceHandle device_handle)); + MOCK_CONST_METHOD1(GetConnectionStatus, + ConnectionStatus(const DeviceHandle& device_handle)); MOCK_CONST_METHOD2(RunAppOnDevice, void(const std::string&, const std::string&)); MOCK_METHOD0(ConnectToAllDevices, void()); diff --git a/src/components/include/test/transport_manager/mock_transport_manager.h b/src/components/include/test/transport_manager/mock_transport_manager.h index cc8bd5ab85..657aa08fb5 100644 --- a/src/components/include/test/transport_manager/mock_transport_manager.h +++ b/src/components/include/test/transport_manager/mock_transport_manager.h @@ -60,6 +60,8 @@ class MockTransportManager : public ::transport_manager::TransportManager, MOCK_METHOD0(Reinit, int()); MOCK_METHOD0(SearchDevices, int()); MOCK_METHOD1(ConnectDevice, int(const DeviceHandle)); + MOCK_CONST_METHOD1(GetConnectionStatus, + ConnectionStatus(const DeviceHandle& device_handle)); MOCK_METHOD1(DisconnectDevice, int(const DeviceHandle)); MOCK_METHOD1(Disconnect, int(const ConnectionUID)); MOCK_METHOD1(DisconnectForce, int(const ConnectionUID)); diff --git a/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h b/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h index eff0abdcd3..42ccd18e38 100644 --- a/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h +++ b/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h @@ -66,6 +66,8 @@ class MockTransportAdapter MOCK_METHOD1(ConnectDevice, ::transport_manager::transport_adapter::TransportAdapter::Error( const ::transport_manager::DeviceUID& device_handle)); + MOCK_CONST_METHOD1(GetConnectionStatus, + ConnectionStatus(const DeviceUID& device_handle)); MOCK_METHOD2(RunAppOnDevice, void(const std::string&, const std::string&)); MOCK_CONST_METHOD0(IsClientOriginatedConnectSupported, bool()); MOCK_METHOD0( diff --git a/src/components/include/transport_manager/common.h b/src/components/include/transport_manager/common.h index 58bcf6bb17..b36dcde67e 100644 --- a/src/components/include/transport_manager/common.h +++ b/src/components/include/transport_manager/common.h @@ -56,6 +56,8 @@ enum { E_INTERNAL_ERROR }; +enum ConnectionStatus { INVALID = -1, PENDING, RETRY, CONNECTED, CLOSING }; + /** * @brief Type definition for variable that hold handle of device. */ diff --git a/src/components/include/transport_manager/transport_adapter/device.h b/src/components/include/transport_manager/transport_adapter/device.h index 1ac1424477..448df9668a 100644 --- a/src/components/include/transport_manager/transport_adapter/device.h +++ b/src/components/include/transport_manager/transport_adapter/device.h @@ -131,6 +131,26 @@ class Device { keep_on_disconnect_ = keep_on_disconnect; } + inline ConnectionStatus connection_status() const { + return status_; + } + + inline void set_connection_status(ConnectionStatus status) { + status_ = status; + } + + inline uint16_t retry_count() const { + return retry_count_; + } + + inline void next_retry() { + retry_count_++; + } + + inline void reset_retry_count() { + retry_count_ = 0; + } + /** * @brief transport_switch_id Returns id used for transport switching * flow of device. Filled if applicable, otherwise - empty. @@ -160,6 +180,10 @@ class Device { *finished. **/ bool keep_on_disconnect_; + + ConnectionStatus status_; + + uint16_t retry_count_; }; typedef std::shared_ptr<Device> DeviceSptr; typedef std::vector<DeviceSptr> DeviceVector; diff --git a/src/components/include/transport_manager/transport_adapter/transport_adapter.h b/src/components/include/transport_manager/transport_adapter/transport_adapter.h index 4aa6e901ad..c136148936 100644 --- a/src/components/include/transport_manager/transport_adapter/transport_adapter.h +++ b/src/components/include/transport_manager/transport_adapter/transport_adapter.h @@ -217,6 +217,9 @@ class TransportAdapter { */ virtual Error ConnectDevice(const DeviceUID& device_handle) = 0; + virtual ConnectionStatus GetConnectionStatus( + const DeviceUID& device_handle) const = 0; + /** * @brief RunAppOnDevice allows to run specific application on the certain *device. diff --git a/src/components/include/transport_manager/transport_manager.h b/src/components/include/transport_manager/transport_manager.h index b5dfa3671b..8fee6db6a5 100644 --- a/src/components/include/transport_manager/transport_manager.h +++ b/src/components/include/transport_manager/transport_manager.h @@ -87,6 +87,9 @@ class TransportManager { **/ virtual int ConnectDevice(const DeviceHandle device_id) = 0; + virtual ConnectionStatus GetConnectionStatus( + const DeviceHandle& device_handle) const = 0; + /** * @brief Disconnect from all applications connected on device. * diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml index a11cfbfd8a..7adb5fb51e 100644 --- a/src/components/interfaces/HMI_API.xml +++ b/src/components/interfaces/HMI_API.xml @@ -292,6 +292,18 @@ <element name="REMOTE_CONTROL" /> </enum> +<enum name="CloudConnectionStatus"> + <element name="NOT_CONNECTED"> + <description>No active websocket session or ongoing connection attempts</description> + </element> + <element name="CONNECTED"> + <description>Websocket is active</description> + </element> + <element name="RETRY"> + <description>Websocket connection failed and retry attempts are ongoing</description> + </element> +</enum> + <enum name="WayPointType"> <description>Describes what kind of waypoint is requested/provided.</description> <element name="ALL" /> @@ -2620,16 +2632,18 @@ <description>If SDL omits this parameter - none RequestType is allowed for this app</description> <description>(either this is a pre-registered app or such is dictated by policies).</description> </param> - <param name="requestSubType" type="String" maxlength="100" minsize="0" maxsize="100" array="true" mandatory="false"> - <description> - The list of SystemRequest's requestSubTypes allowed by policies for the named application. - If the app sends a requestSubType which is not specified in this list, then that request should be rejected. - An empty array signifies that any value of requestSubType is allowed for this app. - If this parameter is omitted, then a request with any value of requestSubType is now allowed for this app - </description> + <param name="requestSubType" type="String" maxlength="100" minsize="0" maxsize="100" array="true" mandatory="false"> + <description> + The list of SystemRequest's requestSubTypes allowed by policies for the named application. + If the app sends a requestSubType which is not specified in this list, then that request should be rejected. + An empty array signifies that any value of requestSubType is allowed for this app. + If this parameter is omitted, then a request with any value of requestSubType is now allowed for this app + </description> </param> <param name="dayColorScheme" type="Common.TemplateColorScheme" mandatory="false"></param> <param name="nightColorScheme" type="Common.TemplateColorScheme" mandatory="false"></param> + <param name="isCloudApplication" type="Boolean" mandatory="false"></param> + <param name="cloudConnectionStatus" type="Common.CloudConnectionStatus" mandatory="false"></param> </struct> <struct name="MenuParams"> diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h index 0af1f2b614..e06537677a 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h @@ -41,6 +41,7 @@ #include "utils/lock.h" #include "utils/rwlock.h" +#include "utils/timer.h" #include "transport_manager/transport_adapter/transport_adapter.h" #include "transport_manager/transport_adapter/transport_adapter_controller.h" @@ -61,6 +62,8 @@ class DeviceScanner; class ServerConnectionFactory; class ClientConnectionListener; +typedef std::shared_ptr<timer::Timer> TimerSPtr; + /* * @brief Implementation of device adapter class. **/ @@ -146,6 +149,9 @@ class TransportAdapterImpl : public TransportAdapter, TransportAdapter::Error ConnectDevice( const DeviceUID& device_handle) OVERRIDE; + ConnectionStatus GetConnectionStatus( + const DeviceUID& device_handle) const OVERRIDE; + /** * @brief Disconnect from specified session. * @@ -546,6 +552,8 @@ class TransportAdapterImpl : public TransportAdapter, */ TransportAdapter::Error ConnectDevice(DeviceSptr device); + void RetryConnection(); + /** * @brief Remove specified device * @param device_handle Device unique identifier. @@ -578,7 +586,7 @@ class TransportAdapterImpl : public TransportAdapter, ConnectionSPtr connection; DeviceUID device_id; ApplicationHandle app_handle; - enum { NEW, ESTABLISHED, FINALISING, PENDING, RETRY } state; + enum { NEW, ESTABLISHED, FINALISING, PENDING } state; }; /** @@ -607,6 +615,8 @@ class TransportAdapterImpl : public TransportAdapter, **/ ConnectionMap connections_; + std::queue<std::pair<TimerSPtr, DeviceUID> > retry_timer_pool_; + /** * @brief Mutex restricting access to connections map. **/ diff --git a/src/components/transport_manager/include/transport_manager/transport_manager_impl.h b/src/components/transport_manager/include/transport_manager/transport_manager_impl.h index dcb3b6922c..69f38304a7 100644 --- a/src/components/transport_manager/include/transport_manager/transport_manager_impl.h +++ b/src/components/transport_manager/include/transport_manager/transport_manager_impl.h @@ -43,7 +43,6 @@ #include <functional> #include "utils/timer.h" -#include "utils/timer_task_impl.h" #include "utils/rwlock.h" #include "transport_manager/transport_manager.h" @@ -152,6 +151,9 @@ class TransportManagerImpl **/ int ConnectDevice(const DeviceHandle device_id) OVERRIDE; + ConnectionStatus GetConnectionStatus( + const DeviceHandle& device_handle) const OVERRIDE; + /** * @brief Disconnect from all applications connected on device. * @@ -368,7 +370,7 @@ class TransportManagerImpl * @brief Converter variable (Device ID -> Device Handle; Device Handle -> * Device ID) */ - Handle2GUIDConverter converter_; + mutable Handle2GUIDConverter converter_; #ifdef BUILD_TESTS public: @@ -383,7 +385,7 @@ class TransportManagerImpl int connection_id_counter_; sync_primitives::RWLock connections_lock_; std::vector<ConnectionInternal> connections_; - sync_primitives::RWLock device_to_adapter_map_lock_; + mutable sync_primitives::RWLock device_to_adapter_map_lock_; typedef std::map<DeviceUID, TransportAdapter*> DeviceToAdapterMap; DeviceToAdapterMap device_to_adapter_map_; std::vector<TransportAdapter*> transport_adapters_; diff --git a/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc b/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc index 874f158145..2ad1a66126 100644 --- a/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc +++ b/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc @@ -112,4 +112,4 @@ void CloudWebsocketTransportAdapter::CreateDevice(const std::string& uid) { return; } } -}
\ No newline at end of file +} 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 38b9bd3998..b73f3140d3 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 @@ -31,8 +31,9 @@ */ #include "config_profile/profile.h" -#include "utils/logger.h" #include "utils/helpers.h" +#include "utils/logger.h" +#include "utils/timer_task_impl.h" #include "transport_manager/transport_adapter/transport_adapter_impl.h" #include "transport_manager/transport_adapter/transport_adapter_listener.h" @@ -209,17 +210,20 @@ TransportAdapter::Error TransportAdapterImpl::Connect( } connections_lock_.AcquireForWriting(); + + std::pair<DeviceUID, ApplicationHandle> connection_key; const bool already_exists = - connections_.end() != - connections_.find(std::make_pair(device_id, app_handle)); + connections_.end() != connections_.find(connection_key); + ConnectionInfo& info = connections_[connection_key]; if (!already_exists) { - ConnectionInfo& info = connections_[std::make_pair(device_id, app_handle)]; info.app_handle = app_handle; info.device_id = device_id; info.state = ConnectionInfo::NEW; } + const bool pending_app = ConnectionInfo::PENDING == info.state; connections_lock_.Release(); - if (already_exists) { + + if (already_exists && !pending_app) { LOG4CXX_TRACE(logger_, "exit with ALREADY_EXISTS"); return ALREADY_EXISTS; } @@ -235,12 +239,49 @@ TransportAdapter::Error TransportAdapterImpl::Connect( return err; } +void TransportAdapterImpl::RetryConnection() { + if (retry_timer_pool_.empty()) { + LOG4CXX_ERROR(logger_, + "Unable to find timer, ignoring RetryConnection request"); + return; + } + const DeviceUID device_id = retry_timer_pool_.front().second; + retry_timer_pool_.pop(); + ConnectDevice(device_id); +} + TransportAdapter::Error TransportAdapterImpl::ConnectDevice( const DeviceUID& device_handle) { LOG4CXX_TRACE(logger_, "enter with device_handle: " << &device_handle); DeviceSptr device = FindDevice(device_handle); if (device) { TransportAdapter::Error err = ConnectDevice(device); + if (FAIL == err && GetDeviceType() == DeviceType::CLOUD_WEBSOCKET) { + LOG4CXX_TRACE(logger_, + "Error occurred while connecting cloud app: " << err); + if (device->connection_status() == ConnectionStatus::PENDING) { + device->set_connection_status(ConnectionStatus::RETRY); + device->reset_retry_count(); + } + + if (device->retry_count() > + get_settings().cloud_app_max_retry_attempts()) { + device->set_connection_status(ConnectionStatus::PENDING); + device->reset_retry_count(); + return err; + } + + device->next_retry(); + TimerSPtr retry_timer(std::make_shared<timer::Timer>( + "RetryConnectionTimer", + new timer::TimerTaskImpl<TransportAdapterImpl>( + this, &TransportAdapterImpl::RetryConnection))); + retry_timer_pool_.push(std::make_pair(retry_timer, device_handle)); + retry_timer->Start(get_settings().cloud_app_retry_timeout(), + timer::kSingleShot); + } else if (OK == err) { + device->set_connection_status(ConnectionStatus::CONNECTED); + } LOG4CXX_TRACE(logger_, "exit with error: " << err); return err; } else { @@ -249,6 +290,13 @@ TransportAdapter::Error TransportAdapterImpl::ConnectDevice( } } +ConnectionStatus TransportAdapterImpl::GetConnectionStatus( + const DeviceUID& device_handle) const { + DeviceSptr device = FindDevice(device_handle); + return device.use_count() == 0 ? ConnectionStatus::INVALID + : device->connection_status(); +} + TransportAdapter::Error TransportAdapterImpl::Disconnect( const DeviceUID& device_id, const ApplicationHandle& app_handle) { LOG4CXX_TRACE(logger_, @@ -278,6 +326,8 @@ TransportAdapter::Error TransportAdapterImpl::DisconnectDevice( } Error error = OK; + DeviceSptr device = FindDevice(device_id); + device->set_connection_status(ConnectionStatus::CLOSING); std::vector<ConnectionInfo> to_disconnect; connections_lock_.AcquireForReading(); @@ -397,6 +447,7 @@ DeviceSptr TransportAdapterImpl::AddDevice(DeviceSptr device) { LOG4CXX_TRACE(logger_, "exit with TRUE. Condition: same_device_found"); return existing_device; } else { + device->set_connection_status(ConnectionStatus::PENDING); for (TransportAdapterListenerList::iterator it = listeners_.begin(); it != listeners_.end(); ++it) { diff --git a/src/components/transport_manager/src/transport_manager_impl.cc b/src/components/transport_manager/src/transport_manager_impl.cc index 300ed27718..1c5a6dae32 100644 --- a/src/components/transport_manager/src/transport_manager_impl.cc +++ b/src/components/transport_manager/src/transport_manager_impl.cc @@ -177,6 +177,22 @@ int TransportManagerImpl::ConnectDevice(const DeviceHandle device_handle) { return err; } +ConnectionStatus TransportManagerImpl::GetConnectionStatus( + const DeviceHandle& device_handle) const { + DeviceUID device_id = converter_.HandleToUid(device_handle); + + sync_primitives::AutoReadLock lock(device_to_adapter_map_lock_); + DeviceToAdapterMap::const_iterator it = + device_to_adapter_map_.find(device_id); + if (it == device_to_adapter_map_.end()) { + LOG4CXX_ERROR(logger_, "No device adapter found by id " << device_handle); + LOG4CXX_TRACE(logger_, "exit with E_INVALID_HANDLE. Condition: NULL == ta"); + return ConnectionStatus::INVALID; + } + transport_adapter::TransportAdapter* ta = it->second; + return ta->GetConnectionStatus(device_id); +} + int TransportManagerImpl::DisconnectDevice(const DeviceHandle device_handle) { LOG4CXX_TRACE(logger_, "enter. DeviceHandle: " << &device_handle); if (!this->is_initialized_) { |