diff options
Diffstat (limited to 'src/components/application_manager/src/resumption/resume_ctrl_impl.cc')
-rw-r--r-- | src/components/application_manager/src/resumption/resume_ctrl_impl.cc | 231 |
1 files changed, 205 insertions, 26 deletions
diff --git a/src/components/application_manager/src/resumption/resume_ctrl_impl.cc b/src/components/application_manager/src/resumption/resume_ctrl_impl.cc index e3fd423970..42dc335878 100644 --- a/src/components/application_manager/src/resumption/resume_ctrl_impl.cc +++ b/src/components/application_manager/src/resumption/resume_ctrl_impl.cc @@ -35,6 +35,7 @@ #include <algorithm> #include "application_manager/application_manager.h" +#include "application_manager/rpc_service.h" #include "utils/file_system.h" #include "connection_handler/connection_handler_impl.h" @@ -47,17 +48,22 @@ #include "utils/helpers.h" #include "application_manager/resumption/resumption_data_db.h" #include "application_manager/resumption/resumption_data_json.h" -#include "utils/make_shared.h" + #include "utils/timer_task_impl.h" namespace resumption { using namespace application_manager; +static mobile_api::HMILevel::eType PickHigherHmiLevel( + mobile_api::HMILevel::eType val1, mobile_api::HMILevel::eType val2); +static mobile_api::HMILevel::eType PickLowerHmiLevel( + mobile_api::HMILevel::eType val1, mobile_api::HMILevel::eType val2); +static mobile_api::HMILevel::eType ConvertHmiLevelString(const std::string str); + CREATE_LOGGERPTR_GLOBAL(logger_, "Resumption") ResumeCtrlImpl::ResumeCtrlImpl(ApplicationManager& application_manager) : event_engine::EventObserver(application_manager.event_dispatcher()) - , queue_lock_(false) , restore_hmi_level_timer_( "RsmCtrlRstore", new timer::TimerTaskImpl<ResumeCtrlImpl>( @@ -72,9 +78,14 @@ ResumeCtrlImpl::ResumeCtrlImpl(ApplicationManager& application_manager) , application_manager_(application_manager) {} #ifdef BUILD_TESTS void ResumeCtrlImpl::set_resumption_storage( - utils::SharedPtr<ResumptionData> mock_storage) { + std::shared_ptr<ResumptionData> mock_storage) { resumption_storage_ = mock_storage; } + +bool ResumeCtrlImpl::get_resumption_active() const { + sync_primitives::AutoLock auto_lock(queue_lock_); + return is_resumption_active_; +} #endif // BUILD_TESTS bool ResumeCtrlImpl::Init(resumption::LastState& last_state) { @@ -157,10 +168,38 @@ bool ResumeCtrlImpl::RestoreAppHMIState(ApplicationSharedPtr application) { if (result) { DCHECK_OR_RETURN(application, false); if (saved_app.keyExists(strings::hmi_level)) { - const HMILevel::eType saved_hmi_level = - static_cast<mobile_apis::HMILevel::eType>( - saved_app[strings::hmi_level].asInt()); - LOG4CXX_DEBUG(logger_, "Saved HMI Level is : " << saved_hmi_level); + HMILevel::eType saved_hmi_level; + if (HMILevel::eType::INVALID_ENUM != + application->deferred_resumption_hmi_level()) { + saved_hmi_level = application->deferred_resumption_hmi_level(); + LOG4CXX_INFO(logger_, + "Retry resuming into HMI level : " << saved_hmi_level); + application->set_deferred_resumption_hmi_level( + HMILevel::eType::INVALID_ENUM); + } else { + saved_hmi_level = static_cast<mobile_apis::HMILevel::eType>( + saved_app[strings::hmi_level].asInt()); + LOG4CXX_DEBUG(logger_, "Saved HMI Level is : " << saved_hmi_level); + } + + // Check one of the high-bandwidth transports (configured through + // smartDeviceLink.ini file) is available. If not, then the HMI level to + // resume into will be modified. + if (!application_manager_.CheckResumptionRequiredTransportAvailable( + application)) { + mobile_apis::HMILevel::eType low_bandwidth_level = + GetHmiLevelOnLowBandwidthTransport(application); + + application->set_deferred_resumption_hmi_level(saved_hmi_level); + + saved_hmi_level = + PickLowerHmiLevel(saved_hmi_level, low_bandwidth_level); + LOG4CXX_DEBUG( + logger_, + "High-bandwidth transport not available, app will resume into : " + << saved_hmi_level); + } + return SetAppHMIState(application, saved_hmi_level, true); } else { result = false; @@ -175,9 +214,23 @@ bool ResumeCtrlImpl::RestoreAppHMIState(ApplicationSharedPtr application) { bool ResumeCtrlImpl::SetupDefaultHMILevel(ApplicationSharedPtr application) { LOG4CXX_AUTO_TRACE(logger_); DCHECK_OR_RETURN(application, false); - mobile_apis::HMILevel::eType default_hmi = + mobile_apis::HMILevel::eType hmi_level = application_manager_.GetDefaultHmiLevel(application); - return SetAppHMIState(application, default_hmi, false); + + // Check one of the high-bandwidth transports (configured through + // smartDeviceLink.ini file) is available. If not, then the HMI level to + // resume into will be modified. + if (!application_manager_.CheckResumptionRequiredTransportAvailable( + application)) { + mobile_apis::HMILevel::eType low_bandwidth_level = + GetHmiLevelOnLowBandwidthTransport(application); + hmi_level = PickLowerHmiLevel(hmi_level, low_bandwidth_level); + LOG4CXX_DEBUG( + logger_, + "High-bandwidth transport not available, default HMI level is set to : " + << hmi_level); + } + return SetAppHMIState(application, hmi_level, false); } void ResumeCtrlImpl::ApplicationResumptiOnTimer() { @@ -352,6 +405,28 @@ bool ResumeCtrlImpl::StartResumptionOnlyHMILevel( return result; } +void ResumeCtrlImpl::RetryResumption(const uint32_t app_id) { + LOG4CXX_AUTO_TRACE(logger_); + + ApplicationSharedPtr app = application_manager_.application(app_id); + if (!app) { + LOG4CXX_WARN(logger_, "Invalid app_id = " << app_id); + return; + } + + { + sync_primitives::AutoLock auto_lock(queue_lock_); + // check and update resumption deferred flag in queue_lock_ + if (mobile_api::HMILevel::eType::INVALID_ENUM == + app->deferred_resumption_hmi_level()) { + LOG4CXX_DEBUG(logger_, "No need to retry resumption for app: " << app_id); + return; + } + } + + AddToResumptionTimerQueue(app_id); +} + void ResumeCtrlImpl::StartAppHmiStateResumption( ApplicationSharedPtr application) { using namespace date_time; @@ -374,6 +449,11 @@ void ResumeCtrlImpl::StartAppHmiStateResumption( LOG4CXX_INFO(logger_, "Resume application " << application->policy_app_id()); RestoreAppHMIState(application); + if (mobile_apis::HMILevel::eType::INVALID_ENUM != + application->deferred_resumption_hmi_level()) { + // the application has not been fully resumed + return; + } RemoveApplicationFromSaved(application); } else { LOG4CXX_INFO(logger_, @@ -544,8 +624,12 @@ void ResumeCtrlImpl::AddCommands(ApplicationSharedPtr application, saved_app[strings::application_commands]; for (size_t i = 0; i < app_commands.length(); ++i) { const smart_objects::SmartObject& command = app_commands[i]; + const uint32_t cmd_id = command[strings::cmd_id].asUInt(); + const bool is_resumption = true; - application->AddCommand(command[strings::cmd_id].asUInt(), command); + application->AddCommand(cmd_id, command); + application->help_prompt_manager().OnVrCommandAdded( + cmd_id, command, is_resumption); } ProcessHMIRequests(MessageHelper::CreateAddCommandRequestToHMI( application, application_manager_)); @@ -623,17 +707,8 @@ void ResumeCtrlImpl::AddSubscriptions( MessageHelper::SendAllOnButtonSubscriptionNotificationsForApp( application, application_manager_); - if (subscriptions.keyExists(strings::application_vehicle_info)) { - const smart_objects::SmartObject& subscriptions_ivi = - subscriptions[strings::application_vehicle_info]; - mobile_apis::VehicleDataType::eType ivi; - for (size_t i = 0; i < subscriptions_ivi.length(); ++i) { - ivi = static_cast<mobile_apis::VehicleDataType::eType>( - (subscriptions_ivi[i]).asInt()); - application->SubscribeToIVI(ivi); - } - ProcessHMIRequests(MessageHelper::GetIVISubscriptionRequests( - application, application_manager_)); + for (auto& extension : application->Extensions()) { + extension->ProcessResumption(subscriptions); } } } @@ -685,8 +760,14 @@ bool ResumeCtrlImpl::CheckAppRestrictions( LOG4CXX_AUTO_TRACE(logger_); DCHECK_OR_RETURN(saved_app.keyExists(strings::hmi_level), false); - const HMILevel::eType hmi_level = - static_cast<HMILevel::eType>(saved_app[strings::hmi_level].asInt()); + HMILevel::eType hmi_level; + if (mobile_api::HMILevel::eType::INVALID_ENUM != + application->deferred_resumption_hmi_level()) { + hmi_level = application->deferred_resumption_hmi_level(); + } else { + hmi_level = + static_cast<HMILevel::eType>(saved_app[strings::hmi_level].asInt()); + } const bool result = Compare<HMILevel::eType, EQ, ONE>( hmi_level, HMILevel::HMI_FULL, HMILevel::HMI_LIMITED) ? true @@ -743,7 +824,7 @@ bool ResumeCtrlImpl::ProcessHMIRequest(smart_objects::SmartObjectSPtr request, (*request)[strings::correlation_id].asInt(); subscribe_on_event(function_id, hmi_correlation_id); } - if (!application_manager_.ManageHMICommand(request)) { + if (!application_manager_.GetRPCService().ManageHMICommand(request)) { LOG4CXX_ERROR(logger_, "Unable to send request"); return false; } @@ -762,14 +843,19 @@ void ResumeCtrlImpl::ProcessHMIRequests( void ResumeCtrlImpl::AddToResumptionTimerQueue(const uint32_t app_id) { LOG4CXX_AUTO_TRACE(logger_); + bool run_resumption = false; queue_lock_.Acquire(); waiting_for_timer_.push_back(app_id); + + if (!is_resumption_active_) { + is_resumption_active_ = true; + run_resumption = true; + } queue_lock_.Release(); LOG4CXX_DEBUG(logger_, "Application ID " << app_id << " have been added" " to resumption queue."); - if (!is_resumption_active_) { - is_resumption_active_ = true; + if (run_resumption) { restore_hmi_level_timer_.Start( application_manager_.get_settings().app_resuming_timeout(), timer::kSingleShot); @@ -834,4 +920,97 @@ bool ResumeCtrlImpl::IsAppDataResumptionExpired( return max_ign_off_count <= application[strings::ign_off_count].asInt(); } +mobile_apis::HMILevel::eType ResumeCtrlImpl::GetHmiLevelOnLowBandwidthTransport( + ApplicationConstSharedPtr application) const { + using namespace mobile_apis; + LOG4CXX_AUTO_TRACE(logger_); + + const ApplicationManagerSettings& settings = + application_manager_.get_settings(); + const std::string& level_for_navi_app = + settings.navigation_lowbandwidth_resumption_level(); + const std::string& level_for_projection_app = + settings.projection_lowbandwidth_resumption_level(); + const std::string& level_for_media_app = + settings.media_lowbandwidth_resumption_level(); + + HMILevel::eType result_level = HMILevel::HMI_NONE; + HMILevel::eType level; + + // NAVIGATION, PROJECTION and media apps have special exceptions. Their HMI + // level can be configured through .ini file. when the app has multiple + // AppHMIType, then the highest level will be applied. + if (application->is_navi()) { + level = ConvertHmiLevelString(level_for_navi_app); + LOG4CXX_DEBUG(logger_, + "NAVIGATION apps may have level " + << level + << " while high-bandwidth transport is not available."); + result_level = PickHigherHmiLevel(level, result_level); + } + if (application->mobile_projection_enabled()) { + level = ConvertHmiLevelString(level_for_projection_app); + LOG4CXX_DEBUG(logger_, + "PROJECTION apps may have level " + << level + << " while high-bandwidth transport is not available."); + result_level = PickHigherHmiLevel(level, result_level); + } + if (application->is_media_application()) { + level = ConvertHmiLevelString(level_for_media_app); + LOG4CXX_DEBUG(logger_, + "media apps may have level " + << level + << " while high-bandwidth transport is not available."); + result_level = PickHigherHmiLevel(level, result_level); + } + + return result_level; +} + +static mobile_api::HMILevel::eType PickHigherHmiLevel( + mobile_api::HMILevel::eType val1, mobile_api::HMILevel::eType val2) { + using namespace mobile_apis; + + if (val1 == HMILevel::INVALID_ENUM) { + return val2; + } else if (val2 == HMILevel::INVALID_ENUM) { + return val1; + } + + // smaller enum value has higher level + return val1 < val2 ? val1 : val2; +} + +static mobile_api::HMILevel::eType PickLowerHmiLevel( + mobile_api::HMILevel::eType val1, mobile_api::HMILevel::eType val2) { + using namespace mobile_apis; + + if (val1 == HMILevel::INVALID_ENUM) { + return val2; + } else if (val2 == HMILevel::INVALID_ENUM) { + return val1; + } + + // bigger enum value has lower level + return val1 > val2 ? val1 : val2; +} + +static mobile_api::HMILevel::eType ConvertHmiLevelString( + const std::string str) { + using namespace mobile_apis; + + if ("BACKGROUND" == str) { + return HMILevel::HMI_BACKGROUND; + } else if ("FULL" == str) { + return HMILevel::HMI_FULL; + } else if ("LIMITED" == str) { + return HMILevel::HMI_LIMITED; + } else if ("NONE" == str) { + return HMILevel::HMI_NONE; + } else { + return HMILevel::HMI_NONE; + } +} + } // namespce resumption |