diff options
Diffstat (limited to 'src/components/application_manager/src/application_manager_impl.cc')
-rw-r--r-- | src/components/application_manager/src/application_manager_impl.cc | 637 |
1 files changed, 605 insertions, 32 deletions
diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 24f27af2e2..b0a0514e77 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -73,6 +73,7 @@ #include "policy/usage_statistics/counter.h" #include "utils/custom_string.h" #include <time.h> +#include <boost/filesystem.hpp> namespace { int get_rand_from_range(uint32_t from = 0, int to = RAND_MAX) { @@ -98,7 +99,9 @@ DeviceTypes devicesType = { std::make_pair(std::string("USB_IOS_DEVICE_MODE"), hmi_apis::Common_TransportType::USB_IOS), std::make_pair(std::string("CARPLAY_WIRELESS_IOS"), - hmi_apis::Common_TransportType::WIFI)}; + hmi_apis::Common_TransportType::WIFI), + std::make_pair(std::string("CLOUD_WEBSOCKET"), + hmi_apis::Common_TransportType::CLOUD_WEBSOCKET)}; } /** @@ -130,6 +133,7 @@ bool policy_app_id_comparator(const std::string& policy_app_id, return app->policy_app_id() == policy_app_id; } +uint32_t ApplicationManagerImpl::mobile_corelation_id_ = 0; uint32_t ApplicationManagerImpl::corelation_id_ = 0; const uint32_t ApplicationManagerImpl::max_corelation_id_ = UINT_MAX; @@ -166,6 +170,8 @@ ApplicationManagerImpl::ApplicationManagerImpl( , navi_close_app_timeout_(am_settings.stop_streaming_timeout()) , navi_end_stream_timeout_(am_settings.stop_streaming_timeout()) , state_ctrl_(*this) + , pending_device_map_lock_ptr_( + std::make_shared<sync_primitives::RecursiveLock>()) , application_list_update_timer_( "AM ListUpdater", new TimerTaskImpl<ApplicationManagerImpl>( @@ -236,6 +242,13 @@ DataAccessor<ApplicationSet> ApplicationManagerImpl::applications() const { return accessor; } +DataAccessor<AppsWaitRegistrationSet> +ApplicationManagerImpl::pending_applications() const { + DataAccessor<AppsWaitRegistrationSet> accessor( + apps_to_register_, apps_to_register_list_lock_ptr_); + return accessor; +} + ApplicationSharedPtr ApplicationManagerImpl::application( uint32_t app_id) const { AppIdPredicate finder(app_id); @@ -257,6 +270,20 @@ ApplicationSharedPtr ApplicationManagerImpl::application_by_policy_id( return FindApp(accessor, finder); } +ApplicationSharedPtr ApplicationManagerImpl::application_by_name( + const std::string& app_name) const { + AppNamePredicate finder(app_name); + DataAccessor<ApplicationSet> accessor = applications(); + return FindApp(accessor, finder); +} + +ApplicationSharedPtr ApplicationManagerImpl::pending_application_by_policy_id( + const std::string& policy_app_id) const { + PolicyAppIdPredicate finder(policy_app_id); + DataAccessor<AppsWaitRegistrationSet> accessor = pending_applications(); + return FindPendingApp(accessor, finder); +} + bool ActiveAppPredicate(const ApplicationSharedPtr app) { return app ? app->IsFullscreen() : false; } @@ -379,21 +406,6 @@ void ApplicationManagerImpl::OnApplicationRegistered(ApplicationSharedPtr app) { plugin.OnApplicationEvent(plugin_manager::kApplicationRegistered, app); }; plugin_manager_->ForEachPlugin(on_app_registered); - - // TODO(AOleynik): Is neccessary to be able to know that registration process - // has been completed and default HMI level is set, otherwise policy will - // block all the requests/notifications to mobile - // APPLINK-20764 - introduce usage of internal events or re-implement - event_engine::Event event( - hmi_apis::FunctionID::BasicCommunication_OnAppRegistered); - - smart_objects::SmartObject msg; - msg[strings::params][strings::message_type] = - hmi_apis::messageType::notification; - msg[strings::params][strings::app_id] = app->app_id(); - - event.set_smart_object(msg); - event.raise(event_dispatcher()); } void ApplicationManagerImpl::OnApplicationSwitched(ApplicationSharedPtr app) { @@ -539,6 +551,7 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( app_name, GetPolicyHandler().GetStatisticManager(), *this)); + if (!application) { std::shared_ptr<smart_objects::SmartObject> response( MessageHelper::CreateNegativeResponse( @@ -608,13 +621,48 @@ 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); + bool is_mismatched_cloud_app = false; + + 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; + is_mismatched_cloud_app = found && (*it)->is_cloud_app() && + policy_app_id != (*it)->policy_app_id(); + } 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_auth_token((*it)->auth_token()); + 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(); + // 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(); + } + if (!application->hmi_app_id()) { const bool is_saved = resume_controller().IsApplicationSaved(policy_app_id, device_mac); @@ -650,6 +698,10 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( apps_size_ = applications_.size(); applications_list_lock_ptr_->Release(); + // Update cloud app information, in case any pending apps are unable to be + // registered due to a mobile app taking precedence + RefreshCloudAppInformation(); + // It is possible that secondary transport of this app has been already // established. Make sure that the information is reflected to application // instance. @@ -674,6 +726,8 @@ bool ApplicationManagerImpl::ActivateApplication(ApplicationSharedPtr app) { // remove from resumption if app was activated by user resume_controller().OnAppActivated(app); + // Activate any app services published by the app + GetAppServiceManager().OnAppActivated(app); const HMILevel::eType hmi_level = HMILevel::HMI_FULL; const AudioStreamingState::eType audio_state = app->IsAudioApplication() ? AudioStreamingState::AUDIBLE @@ -779,6 +833,412 @@ void ApplicationManagerImpl::OnHMIStartedCooperation() { *this)); rpc_service_->ManageHMICommand(mixing_audio_supported_request); resume_controller().ResetLaunchTime(); + + RefreshCloudAppInformation(); +} + +std::string ApplicationManagerImpl::PolicyIDByIconUrl(const std::string url) { + sync_primitives::AutoLock lock(app_icon_map_lock_ptr_); + for (auto& x : app_icon_map_) { + auto policy_id = x.first; + std::string icon_url = GetPolicyHandler().GetIconUrl(policy_id); + if (icon_url == url) { + LOG4CXX_DEBUG(logger_, "Matched icon url: " << url); + x.second.pending_request = false; + return policy_id; + } + } + return std::string(""); +} + +void ApplicationManagerImpl::SetIconFileFromSystemRequest( + const std::string policy_id) { + app_icon_map_lock_ptr_.Acquire(); + auto app_icon_it = app_icon_map_.find(policy_id); + if (app_icon_it != app_icon_map_.end()) { + app_icon_map_.erase(app_icon_it); + } + app_icon_map_lock_ptr_.Release(); + + // Find pending application and set icon path + auto app = pending_application_by_policy_id(policy_id); + if (!app) { + return; + } + const std::string app_icon_dir(settings_.app_icons_folder()); + const std::string full_icon_path(app_icon_dir + "/" + policy_id); + if (file_system::FileExists(full_icon_path)) { + LOG4CXX_DEBUG(logger_, "Set Icon Path: " << full_icon_path); + AppFile file; + file.is_persistent = true; + file.is_download_complete = true; + file.file_name = full_icon_path; + + std::string icon_url = GetPolicyHandler().GetIconUrl(policy_id); + std::string extension = boost::filesystem::extension(icon_url); + if (extension == "bmp" || extension == "BMP") { + file.file_type = mobile_apis::FileType::GRAPHIC_BMP; + } else if (extension == "JPEG" || extension == "jpeg" || + extension == "JPG" || extension == "jpg") { + file.file_type = mobile_apis::FileType::GRAPHIC_JPEG; + } else { + file.file_type = mobile_apis::FileType::GRAPHIC_PNG; + } + + app->AddFile(file); + app->set_app_icon_path(full_icon_path); + } + SendUpdateAppList(); +} + +void ApplicationManagerImpl::DisconnectCloudApp(ApplicationSharedPtr app) { + std::string endpoint; + std::string certificate; + std::string auth_token; + std::string cloud_transport_type; + std::string hybrid_app_preference; + bool enabled = true; + std::string policy_app_id = app->policy_app_id(); + GetPolicyHandler().GetCloudAppParameters(policy_app_id, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference); + if (app->IsRegistered() && app->is_cloud_app()) { + LOG4CXX_DEBUG(logger_, "Disabled app is registered, unregistering now"); + GetRPCService().ManageMobileCommand( + MessageHelper::GetOnAppInterfaceUnregisteredNotificationToMobile( + app->app_id(), + mobile_api::AppInterfaceUnregisteredReason::APP_UNAUTHORIZED), + commands::Command::SOURCE_SDL); + + OnAppUnauthorized(app->app_id()); + } + // Delete the cloud device + connection_handler().RemoveCloudAppDevice(app->device()); + + transport_manager::transport_adapter::CloudAppProperties properties{ + endpoint, + certificate, + enabled, + auth_token, + cloud_transport_type, + hybrid_app_preference}; + // Create device in pending state + LOG4CXX_DEBUG(logger_, "Re-adding the cloud app device"); + connection_handler().AddCloudAppDevice(policy_app_id, properties); +} + +void ApplicationManagerImpl::RefreshCloudAppInformation() { + LOG4CXX_AUTO_TRACE(logger_); + if (is_stopping()) { + return; + } + std::vector<std::string> enabled_apps; + GetPolicyHandler().GetEnabledCloudApps(enabled_apps); + std::vector<std::string>::iterator enabled_it = enabled_apps.begin(); + std::vector<std::string>::iterator enabled_end = enabled_apps.end(); + std::string endpoint; + std::string certificate; + std::string auth_token; + std::string cloud_transport_type; + std::string hybrid_app_preference_str; + bool enabled = true; + + // Store old device map and clear the current map + pending_device_map_lock_ptr_->Acquire(); + app_icon_map_lock_ptr_.Acquire(); + std::map<std::string, std::string> old_device_map = pending_device_map_; + pending_device_map_ = std::map<std::string, std::string>(); + // Create a device for each newly enabled cloud app + for (; enabled_it != enabled_end; ++enabled_it) { + GetPolicyHandler().GetCloudAppParameters(*enabled_it, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference_str); + + mobile_apis::HybridAppPreference::eType hybrid_app_preference = + mobile_apis::HybridAppPreference::INVALID_ENUM; + smart_objects::EnumConversionHelper< + mobile_apis::HybridAppPreference::eType>:: + StringToEnum(hybrid_app_preference_str, &hybrid_app_preference); + + auto policy_id = *enabled_it; + policy::StringArray nicknames; + policy::StringArray app_hmi_types; + GetPolicyHandler().GetInitialAppData(policy_id, &nicknames, &app_hmi_types); + + if (nicknames.empty()) { + LOG4CXX_ERROR(logger_, "Cloud App missing nickname"); + continue; + } else if (mobile_apis::HybridAppPreference::MOBILE == + hybrid_app_preference) { + auto nickname_it = nicknames.begin(); + for (; nickname_it != nicknames.end(); ++nickname_it) { + auto app = application_by_name(*nickname_it); + if (app.use_count() != 0) { + LOG4CXX_ERROR( + logger_, + "Mobile app already registered for cloud app: " << *nickname_it); + continue; + } + } + } + + pending_device_map_.insert( + std::pair<std::string, std::string>(endpoint, policy_id)); + // Determine which endpoints were disabled by erasing all enabled apps from + // the old device list + auto old_device_it = old_device_map.find(endpoint); + if (old_device_it != old_device_map.end()) { + old_device_map.erase(old_device_it); + } + + transport_manager::transport_adapter::CloudAppProperties properties{ + endpoint, + certificate, + enabled, + auth_token, + cloud_transport_type, + hybrid_app_preference_str}; + + // If the device was disconnected, this will reinitialize the device + connection_handler().AddCloudAppDevice(policy_id, properties); + + // Look for app icon url data and add to app_icon_url_map + std::string url = GetPolicyHandler().GetIconUrl(policy_id); + + if (url.empty()) { + LOG4CXX_DEBUG(logger_, "No Icon Url for cloud app"); + continue; + } + + auto app_icon_it = app_icon_map_.find(policy_id); + if (app_icon_it != app_icon_map_.end()) { + LOG4CXX_DEBUG(logger_, "Cloud App Already Exists in Icon Map"); + continue; + } + + const std::string app_icon_dir(settings_.app_icons_folder()); + const std::string full_icon_path(app_icon_dir + "/" + policy_id); + if (!file_system::FileExists(full_icon_path)) { + AppIconInfo icon_info(endpoint, false); + LOG4CXX_DEBUG( + logger_, + "Inserting cloud app into icon map: " << app_icon_map_.size()); + app_icon_map_.insert( + std::pair<std::string, AppIconInfo>(policy_id, icon_info)); + } + } + app_icon_map_lock_ptr_.Release(); + pending_device_map_lock_ptr_->Release(); + + int removed_app_count = 0; + // Clear out devices for existing cloud apps that were disabled + for (auto& device : old_device_map) { + std::string policy_app_id = device.second; + // First search for the disabled app within the registered apps + ApplicationSharedPtr app = application_by_policy_id(policy_app_id); + if (app.use_count() == 0) { + sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_); + // If the disabled app is not present in the registered app list, check + // the apps awaiting registration + PolicyAppIdPredicate finder(policy_app_id); + ApplicationSet::iterator it = std::find_if( + apps_to_register_.begin(), apps_to_register_.end(), finder); + if (it == apps_to_register_.end()) { + LOG4CXX_DEBUG(logger_, + "Unable to find app to remove (" << policy_app_id + << "), skipping"); + continue; + } + app = *it; + apps_to_register_.erase(it); + } + // If the disabled app is registered, unregistered it before destroying the + // device + if (app->IsRegistered() && app->is_cloud_app()) { + LOG4CXX_DEBUG(logger_, "Disabled app is registered, unregistering now"); + GetRPCService().ManageMobileCommand( + MessageHelper::GetOnAppInterfaceUnregisteredNotificationToMobile( + app->app_id(), + mobile_api::AppInterfaceUnregisteredReason::APP_UNAUTHORIZED), + commands::Command::SOURCE_SDL); + + OnAppUnauthorized(app->app_id()); + } + // Delete the cloud device + connection_handler().RemoveCloudAppDevice(app->device()); + removed_app_count++; + } + + // Update app list if disabled apps were removed + if (removed_app_count > 0) { + LOG4CXX_DEBUG(logger_, "Removed " << removed_app_count << " disabled apps"); + SendUpdateAppList(); + } +} + +void ApplicationManagerImpl::CreatePendingApplication( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info, + connection_handler::DeviceHandle device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + std::string endpoint; + std::string certificate; + std::string auth_token; + std::string cloud_transport_type; + std::string hybrid_app_preference_str; + bool enabled = true; + std::string name = device_info.name(); + pending_device_map_lock_ptr_->Acquire(); + auto it = pending_device_map_.find(name); + if (it == pending_device_map_.end()) { + pending_device_map_lock_ptr_->Release(); + return; + } + pending_device_map_lock_ptr_->Release(); + + const std::string policy_app_id = it->second; + + policy::StringArray nicknames; + policy::StringArray app_hmi_types; + + GetPolicyHandler().GetInitialAppData( + policy_app_id, &nicknames, &app_hmi_types); + + if (nicknames.empty()) { + LOG4CXX_ERROR(logger_, "Cloud App missing nickname"); + return; + } + + const std::string display_name = nicknames[0]; + + ApplicationSharedPtr application( + new ApplicationImpl(0, + policy_app_id, + device_info.mac_address(), + device_id, + custom_str::CustomString(display_name), + GetPolicyHandler().GetStatisticManager(), + *this)); + + if (!application) { + LOG4CXX_INFO(logger_, "Could not create application"); + return; + } + + const std::string app_icon_dir(settings_.app_icons_folder()); + const std::string full_icon_path(app_icon_dir + "/" + policy_app_id); + if (file_system::FileExists(full_icon_path)) { + application->set_app_icon_path(full_icon_path); + } + + GetPolicyHandler().GetCloudAppParameters(policy_app_id, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference_str); + + mobile_apis::HybridAppPreference::eType hybrid_app_preference_enum; + + bool convert_result = smart_objects::EnumConversionHelper< + mobile_apis::HybridAppPreference::eType>:: + StringToEnum(hybrid_app_preference_str, &hybrid_app_preference_enum); + + if (!hybrid_app_preference_str.empty() && !convert_result) { + LOG4CXX_ERROR( + logger_, + "Could not convert string to enum: " << hybrid_app_preference_str); + return; + } + + application->set_hmi_application_id(GenerateNewHMIAppID()); + application->set_cloud_app_endpoint(endpoint); + application->set_auth_token(auth_token); + application->set_cloud_app_transport_type(cloud_transport_type); + application->set_hybrid_app_preference(hybrid_app_preference_enum); + application->set_cloud_app_certificate(certificate); + + sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_); + LOG4CXX_DEBUG(logger_, + "apps_to_register_ size before: " << apps_to_register_.size()); + apps_to_register_.insert(application); + LOG4CXX_DEBUG(logger_, + "apps_to_register_ size after: " << apps_to_register_.size()); + + SendUpdateAppList(); +} + +void ApplicationManagerImpl::SetPendingApplicationState( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info) { + std::string name = device_info.name(); + pending_device_map_lock_ptr_->Acquire(); + auto it = pending_device_map_.find(name); + if (it == pending_device_map_.end()) { + pending_device_map_lock_ptr_->Release(); + return; + } + pending_device_map_lock_ptr_->Release(); + + const std::string policy_app_id = it->second; + auto app = application_by_policy_id(policy_app_id); + + if (!app) { + return; + } + LOG4CXX_DEBUG(logger_, + "Unregister application and move into apps_to_register"); + + UnregisterApplication( + app->app_id(), mobile_apis::Result::INVALID_ENUM, true, true); + app->MarkUnregistered(); + + { + sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_); + apps_to_register_.insert(app); + } +} + +void ApplicationManagerImpl::OnConnectionStatusUpdated() { + 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::GetNextMobileCorrelationID() { + if (mobile_corelation_id_ < max_corelation_id_) { + mobile_corelation_id_++; + } else { + mobile_corelation_id_ = 0; + } + + return mobile_corelation_id_; } uint32_t ApplicationManagerImpl::GetNextHMICorrelationID() { @@ -1003,6 +1463,7 @@ void ApplicationManagerImpl::OnDeviceListUpdated( so_to_send[jhs::S_PARAMS][jhs::S_CORRELATION_ID] = GetNextHMICorrelationID(); so_to_send[jhs::S_MSG_PARAMS] = *msg_params; rpc_service_->ManageHMICommand(update_list); + RefreshCloudAppInformation(); } void ApplicationManagerImpl::OnFindNewApplicationsRequest() { @@ -1779,6 +2240,9 @@ bool ApplicationManagerImpl::Init(resumption::LastState& last_state, } app_launch_ctrl_.reset(new app_launch::AppLaunchCtrlImpl( *app_launch_dto_.get(), *this, settings_)); + + app_service_manager_.reset( + new application_manager::AppServiceManager(*this, last_state)); return true; } @@ -1806,7 +2270,9 @@ bool ApplicationManagerImpl::Stop() { } bool ApplicationManagerImpl::ConvertSOtoMessage( - const smart_objects::SmartObject& message, Message& output) { + const smart_objects::SmartObject& message, + Message& output, + const bool allow_unknown_parameters) { LOG4CXX_AUTO_TRACE(logger_); if (smart_objects::SmartType_Null == message.getType() || @@ -1831,16 +2297,16 @@ bool ApplicationManagerImpl::ConvertSOtoMessage( switch (protocol_type) { case 0: { if (protocol_version == 1) { - if (!formatters::CFormatterJsonSDLRPCv1::toString(message, - output_string)) { + if (!formatters::CFormatterJsonSDLRPCv1::toString( + message, output_string, !allow_unknown_parameters)) { LOG4CXX_WARN(logger_, "Failed to serialize smart object"); return false; } output.set_protocol_version( protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_1); } else { - if (!formatters::CFormatterJsonSDLRPCv2::toString(message, - output_string)) { + if (!formatters::CFormatterJsonSDLRPCv2::toString( + message, output_string, !allow_unknown_parameters)) { LOG4CXX_WARN(logger_, "Failed to serialize smart object"); return false; } @@ -1852,7 +2318,8 @@ bool ApplicationManagerImpl::ConvertSOtoMessage( break; } case 1: { - if (!formatters::FormatterJsonRpc::ToString(message, output_string)) { + if (!formatters::FormatterJsonRpc::ToString( + message, output_string, !allow_unknown_parameters)) { LOG4CXX_WARN(logger_, "Failed to serialize smart object"); return false; } @@ -2151,6 +2618,17 @@ void ApplicationManagerImpl::updateRequestTimeout( connection_key, mobile_correlation_id, new_timeout_value); } +void ApplicationManagerImpl::IncreaseForwardedRequestTimeout( + uint32_t connection_key, uint32_t mobile_correlation_id) { + LOG4CXX_DEBUG(logger_, + "Increasing Request Timeout by " + << get_settings().rpc_pass_through_timeout()); + uint32_t new_timeout_value = get_settings().default_timeout() + + get_settings().rpc_pass_through_timeout(); + request_ctrl_.updateRequestTimeout( + connection_key, mobile_correlation_id, new_timeout_value); +} + uint32_t ApplicationManagerImpl::application_id(const int32_t correlation_id) { // ykazakov: there is no erase for const iterator for QNX std::map<const int32_t, const uint32_t>::iterator it = @@ -2350,6 +2828,21 @@ void ApplicationManagerImpl::UnregisterAllApplications() { it = accessor.GetData().begin(); } } + + bool send_pending_update_app_list = false; + { + sync_primitives::AutoLock auto_lock(apps_to_register_list_lock_ptr_); + if (!apps_to_register_.empty()) { + send_pending_update_app_list = true; + apps_to_register_.clear(); + } + } + + // Only send update app list if pending apps were removed. + if (send_pending_update_app_list) { + SendUpdateAppList(); + } + if (is_ignition_off) { resume_controller().OnIgnitionOff(); } @@ -2387,6 +2880,8 @@ void ApplicationManagerImpl::UnregisterApplication( << is_unexpected_disconnect); size_t subscribed_for_way_points_app_count = 0; + GetAppServiceManager().UnpublishServices(app_id); + // SDL sends UnsubscribeWayPoints only for last application { sync_primitives::AutoLock lock(subscribed_way_points_apps_lock_); @@ -2449,6 +2944,7 @@ void ApplicationManagerImpl::UnregisterApplication( if (app_id == (*it_app)->app_id()) { app_to_remove = *it_app; applications_.erase(it_app++); + break; } else { ++it_app; } @@ -2472,14 +2968,23 @@ void ApplicationManagerImpl::UnregisterApplication( (hmi_capabilities_->get_hmi_language_handler()) .OnUnregisterApplication(app_id); - AppV4DevicePredicate finder(handle); - ApplicationSharedPtr app = FindApp(applications(), finder); - if (!app) { - LOG4CXX_DEBUG( - logger_, "There is no more SDL4 apps with device handle: " << handle); - RemoveAppsWaitingForRegistration(handle); - SendUpdateAppList(); + if (connection_handler().GetDeviceID(app_to_remove->mac_address(), + &handle)) { + AppV4DevicePredicate finder(handle); + ApplicationSharedPtr app = FindApp(applications(), finder); + if (!app) { + LOG4CXX_DEBUG( + logger_, + "There is no more SDL4 apps with device handle: " << handle); + + RemoveAppsWaitingForRegistration(handle); + RefreshCloudAppInformation(); + SendUpdateAppList(); + } else if (app_to_remove->is_cloud_app()) { + RefreshCloudAppInformation(); + SendUpdateAppList(); + } } } @@ -3363,6 +3868,15 @@ void ApplicationManagerImpl::OnPTUFinished(const bool ptu_result) { if (!ptu_result) { return; } + + RefreshCloudAppInformation(); + + auto app_id = policy_handler_->GetAppIdForSending(); + auto app = application(app_id); + if (app) { + SendGetIconUrlNotifications(app->app_id(), app); + } + auto on_app_policy_updated = [](plugin_manager::RPCPlugin& plugin) { plugin.OnPolicyEvent(plugin_manager::kApplicationPolicyUpdated); }; @@ -3405,6 +3919,58 @@ void ApplicationManagerImpl::SendDriverDistractionState( } } +void ApplicationManagerImpl::SendGetIconUrlNotifications( + const uint32_t connection_key, ApplicationSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + std::vector<std::string> enabled_apps; + GetPolicyHandler().GetEnabledCloudApps(enabled_apps); + std::vector<std::string>::iterator enabled_it = enabled_apps.begin(); + std::vector<std::string>::iterator enabled_end = enabled_apps.end(); + sync_primitives::AutoLock lock(app_icon_map_lock_ptr_); + for (; enabled_it != enabled_end; ++enabled_it) { + auto app_icon_it = app_icon_map_.find(*enabled_it); + if (app_icon_it == app_icon_map_.end()) { + LOG4CXX_WARN(logger_, "Could not find cloud app in icon map"); + continue; + } + + std::string endpoint = app_icon_it->second.endpoint; + bool pending_request = app_icon_it->second.pending_request; + + if (pending_request) { + LOG4CXX_DEBUG(logger_, "Cloud app has already sent request"); + continue; + } + + std::string url = GetPolicyHandler().GetIconUrl(*enabled_it); + + if (url.empty()) { + LOG4CXX_DEBUG(logger_, "No Icon Url for cloud app"); + continue; + } + + LOG4CXX_DEBUG(logger_, "Creating Get Icon Request"); + + smart_objects::SmartObjectSPtr message = + std::make_shared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + (*message)[strings::params][strings::function_id] = + mobile_apis::FunctionID::OnSystemRequestID; + (*message)[strings::params][strings::connection_key] = connection_key; + (*message)[strings::params][strings::message_type] = + mobile_apis::messageType::notification; + (*message)[strings::params][strings::protocol_version] = + application->protocol_version(); + (*message)[strings::msg_params][strings::request_type] = + mobile_apis::RequestType::ICON_URL; + (*message)[strings::msg_params][strings::url] = url; + + app_icon_it->second.pending_request = true; + + rpc_service_->ManageMobileCommand(message, commands::Command::SOURCE_SDL); + } +} + protocol_handler::MajorProtocolVersion ApplicationManagerImpl::SupportedSDLVersion() const { LOG4CXX_AUTO_TRACE(logger_); @@ -3642,6 +4208,13 @@ void ApplicationManagerImpl::AddMockApplication(ApplicationSharedPtr mock_app) { applications_list_lock_ptr_->Release(); } +void ApplicationManagerImpl::AddMockPendingApplication( + ApplicationSharedPtr mock_app) { + apps_to_register_list_lock_ptr_->Acquire(); + apps_to_register_.insert(mock_app); + apps_to_register_list_lock_ptr_->Release(); +} + void ApplicationManagerImpl::SetMockMediaManager( media_manager::MediaManager* mock_media_manager) { media_manager_ = mock_media_manager; |