summaryrefslogtreecommitdiff
path: root/src/components/application_manager/src/resumption/resume_ctrl_impl.cc
diff options
context:
space:
mode:
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.cc473
1 files changed, 412 insertions, 61 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 72f2246e7c..3e77078ee5 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>(
@@ -68,13 +74,20 @@ ResumeCtrlImpl::ResumeCtrlImpl(ApplicationManager& application_manager)
, is_resumption_active_(false)
, is_data_saved_(false)
, is_suspended_(false)
- , launch_time_(time(NULL))
+ , launch_time_(time(nullptr))
+ , low_voltage_time_(0)
+ , wake_up_time_(0)
, 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) {
@@ -117,6 +130,8 @@ bool ResumeCtrlImpl::Init(resumption::LastState& last_state) {
application_manager_.get_settings()
.app_resumption_save_persistent_data_timeout(),
timer::kPeriodic);
+
+ resumption_storage_->IncrementGlobalIgnOnCounter();
return true;
}
@@ -133,9 +148,13 @@ void ResumeCtrlImpl::SaveAllApplications() {
void ResumeCtrlImpl::SaveApplication(ApplicationSharedPtr application) {
LOG4CXX_AUTO_TRACE(logger_);
DCHECK_OR_RETURN_VOID(application);
- LOG4CXX_INFO(logger_,
- "application with appID " << application->app_id()
- << " will be saved");
+ if (application_manager_.IsLowVoltage()) {
+ LOG4CXX_DEBUG(logger_, "Low Voltage state is active");
+ return;
+ }
+ LOG4CXX_DEBUG(logger_,
+ "application with appID " << application->app_id()
+ << " will be saved");
resumption_storage_->SaveApplication(application);
}
@@ -157,10 +176,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 +222,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() {
@@ -257,6 +318,10 @@ uint32_t ResumeCtrlImpl::GetHMIApplicationID(
bool ResumeCtrlImpl::RemoveApplicationFromSaved(
ApplicationConstSharedPtr application) {
+ if (application_manager_.IsLowVoltage()) {
+ LOG4CXX_DEBUG(logger_, "Low Voltage state is active");
+ return false;
+ }
const std::string& device_mac = application->mac_address();
return resumption_storage_->RemoveApplicationFromSaved(
application->policy_app_id(), device_mac);
@@ -270,8 +335,11 @@ void ResumeCtrlImpl::OnSuspend() {
void ResumeCtrlImpl::OnIgnitionOff() {
LOG4CXX_AUTO_TRACE(logger_);
- resumption_storage_->IncrementIgnOffCount();
- FinalPersistData();
+ if (!application_manager_.IsLowVoltage()) {
+ resumption_storage_->IncrementIgnOffCount();
+ resumption_storage_->ResetGlobalIgnOnCount();
+ FinalPersistData();
+ }
}
void ResumeCtrlImpl::OnAwake() {
@@ -281,6 +349,25 @@ void ResumeCtrlImpl::OnAwake() {
StartSavePersistentDataTimer();
}
+void ResumeCtrlImpl::SaveLowVoltageTime() {
+ low_voltage_time_ = time(nullptr);
+ LOG4CXX_DEBUG(logger_,
+ "Low Voltage timestamp : " << low_voltage_time_ << " saved");
+}
+
+void ResumeCtrlImpl::SaveWakeUpTime() {
+ wake_up_time_ = std::time(nullptr);
+ LOG4CXX_DEBUG(logger_, "Wake Up timestamp : " << wake_up_time_ << " saved");
+}
+
+time_t ResumeCtrlImpl::LowVoltageTime() const {
+ return low_voltage_time_;
+}
+
+time_t ResumeCtrlImpl::WakeUpTime() const {
+ return wake_up_time_;
+}
+
bool ResumeCtrlImpl::is_suspended() const {
return is_suspended_;
}
@@ -352,6 +439,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;
@@ -365,15 +474,33 @@ void ResumeCtrlImpl::StartAppHmiStateResumption(
LOG4CXX_ERROR(logger_, "Application was not saved");
return;
}
- const uint32_t ign_off_count = saved_app[strings::ign_off_count].asUInt();
- bool restore_data_allowed = false;
- restore_data_allowed =
- CheckAppRestrictions(application, saved_app) &&
- ((0 == ign_off_count) || CheckIgnCycleRestrictions(saved_app));
- if (restore_data_allowed) {
+
+ const bool is_hmi_level_applicable_to_resume =
+ CheckAppRestrictions(application, saved_app);
+
+ if (!is_hmi_level_applicable_to_resume) {
+ LOG4CXX_DEBUG(logger_, "No applicable HMI level found for resuming");
+ return;
+ }
+
+ const bool is_resume_allowed_by_low_voltage =
+ CheckLowVoltageRestrictions(saved_app);
+
+ const bool is_hmi_level_allowed_by_ign_cycle =
+ CheckIgnCycleRestrictions(saved_app);
+
+ const bool restore_hmi_level_allowed =
+ is_resume_allowed_by_low_voltage && is_hmi_level_allowed_by_ign_cycle;
+
+ if (restore_hmi_level_allowed) {
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 +671,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_));
@@ -606,34 +737,25 @@ void ResumeCtrlImpl::AddSubscriptions(
ApplicationSharedPtr application,
const smart_objects::SmartObject& saved_app) {
LOG4CXX_AUTO_TRACE(logger_);
- if (saved_app.keyExists(strings::application_subscribtions)) {
- const smart_objects::SmartObject& subscribtions =
- saved_app[strings::application_subscribtions];
+ if (saved_app.keyExists(strings::application_subscriptions)) {
+ const smart_objects::SmartObject& subscriptions =
+ saved_app[strings::application_subscriptions];
- if (subscribtions.keyExists(strings::application_buttons)) {
- const smart_objects::SmartObject& subscribtions_buttons =
- subscribtions[strings::application_buttons];
+ if (subscriptions.keyExists(strings::application_buttons)) {
+ const smart_objects::SmartObject& subscriptions_buttons =
+ subscriptions[strings::application_buttons];
mobile_apis::ButtonName::eType btn;
- for (size_t i = 0; i < subscribtions_buttons.length(); ++i) {
+ for (size_t i = 0; i < subscriptions_buttons.length(); ++i) {
btn = static_cast<mobile_apis::ButtonName::eType>(
- (subscribtions_buttons[i]).asInt());
+ (subscriptions_buttons[i]).asInt());
application->SubscribeToButton(btn);
}
}
MessageHelper::SendAllOnButtonSubscriptionNotificationsForApp(
application, application_manager_);
- if (subscribtions.keyExists(strings::application_vehicle_info)) {
- const smart_objects::SmartObject& subscribtions_ivi =
- subscribtions[strings::application_vehicle_info];
- mobile_apis::VehicleDataType::eType ivi;
- for (size_t i = 0; i < subscribtions_ivi.length(); ++i) {
- ivi = static_cast<mobile_apis::VehicleDataType::eType>(
- (subscribtions_ivi[i]).asInt());
- application->SubscribeToIVI(ivi);
- }
- ProcessHMIRequests(MessageHelper::GetIVISubscriptionRequests(
- application, application_manager_));
+ for (auto& extension : application->Extensions()) {
+ extension->ProcessResumption(subscriptions);
}
}
}
@@ -641,30 +763,62 @@ void ResumeCtrlImpl::AddSubscriptions(
bool ResumeCtrlImpl::CheckIgnCycleRestrictions(
const smart_objects::SmartObject& saved_app) {
LOG4CXX_AUTO_TRACE(logger_);
- bool result = true;
if (!CheckDelayAfterIgnOn()) {
- LOG4CXX_INFO(logger_, "Application was connected long after ign on");
- result = false;
+ LOG4CXX_DEBUG(logger_, "Application was connected long after ign on");
+ return false;
}
- if (!DisconnectedJustBeforeIgnOff(saved_app)) {
- LOG4CXX_INFO(logger_, "Application was dissconnected long before ign off");
- result = false;
+ if (!CheckDelayBeforeIgnOff(saved_app)) {
+ LOG4CXX_DEBUG(logger_, "Application was disconnected long before ign off");
+ return false;
}
- return result;
+ return true;
}
-bool ResumeCtrlImpl::DisconnectedJustBeforeIgnOff(
+bool ResumeCtrlImpl::CheckLowVoltageRestrictions(
const smart_objects::SmartObject& saved_app) {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ if (!CheckDelayBeforeLowVoltage(saved_app)) {
+ LOG4CXX_DEBUG(logger_,
+ "Application was disconnected long before low voltage");
+ return false;
+ }
+
+ if (!CheckDelayAfterWakeUp()) {
+ LOG4CXX_DEBUG(logger_, "Application was connected long after wake up");
+ return false;
+ }
+
+ LOG4CXX_DEBUG(logger_, "HMI Level resuming in not restricted by Low Voltage");
+ return true;
+}
+
+bool ResumeCtrlImpl::CheckDelayBeforeIgnOff(
+ const smart_objects::SmartObject& saved_app) const {
using namespace date_time;
LOG4CXX_AUTO_TRACE(logger_);
DCHECK_OR_RETURN(saved_app.keyExists(strings::time_stamp), false);
const time_t time_stamp =
static_cast<time_t>(saved_app[strings::time_stamp].asInt());
- time_t ign_off_time =
+ const time_t ign_off_time =
static_cast<time_t>(resumption_storage_->GetIgnOffTime());
+
+ if (CheckIgnCyclesData() && 0 == ign_off_time) {
+ LOG4CXX_DEBUG(
+ logger_, "No IGNITION OFF records found: This is first Ignition cycle");
+ return true;
+ }
+
+ // This means that ignition off timestamp was not saved
+ // Possible reasons: Low Voltage event, core crash etc.
+ if (ign_off_time < time_stamp) {
+ LOG4CXX_DEBUG(logger_, "Last IGNITION OFF record missed");
+ return true;
+ }
+
const uint32_t sec_spent_before_ign = labs(ign_off_time - time_stamp);
LOG4CXX_DEBUG(
logger_,
@@ -677,6 +831,71 @@ bool ResumeCtrlImpl::DisconnectedJustBeforeIgnOff(
application_manager_.get_settings().resumption_delay_before_ign();
}
+bool ResumeCtrlImpl::CheckDelayBeforeLowVoltage(
+ const smart_objects::SmartObject& saved_app) const {
+ using namespace date_time;
+ LOG4CXX_AUTO_TRACE(logger_);
+ DCHECK_OR_RETURN(saved_app.keyExists(strings::time_stamp), false);
+
+ if (0 == LowVoltageTime()) {
+ LOG4CXX_DEBUG(logger_, "No Low Voltage signal timestamp saved");
+ return true;
+ }
+
+ const time_t unregistration_time_stamp =
+ static_cast<time_t>(saved_app[strings::time_stamp].asInt());
+ const time_t low_voltage_timestamp = static_cast<time_t>(LowVoltageTime());
+ const int32_t sec_spent_before_low_voltage =
+ (low_voltage_timestamp - unregistration_time_stamp);
+ if (0 > sec_spent_before_low_voltage) {
+ LOG4CXX_DEBUG(logger_,
+ "Low Voltage time: "
+ << low_voltage_timestamp
+ << "; App disconnect time: " << unregistration_time_stamp
+ << "; Secs between app disconnect and low voltage event "
+ << sec_spent_before_low_voltage);
+ return true;
+ }
+
+ const uint32_t secs_between_app_disconnect_and_low_voltage =
+ static_cast<uint32_t>(sec_spent_before_low_voltage);
+ const uint32_t wait_time =
+ application_manager_.get_settings().resumption_delay_before_ign();
+ LOG4CXX_DEBUG(logger_,
+ "Low Voltage time: "
+ << low_voltage_timestamp
+ << "; App disconnect time: " << unregistration_time_stamp
+ << "; Secs between app disconnect and low voltage event "
+ << secs_between_app_disconnect_and_low_voltage
+ << "; Timeout for HMI level resuming: " << wait_time);
+ return secs_between_app_disconnect_and_low_voltage <= wait_time;
+}
+
+bool ResumeCtrlImpl::CheckDelayAfterWakeUp() const {
+ using namespace date_time;
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ if (0 == WakeUpTime()) {
+ LOG4CXX_DEBUG(logger_, "No WakeUp signal timestamp saved");
+ return true;
+ }
+
+ const time_t current_time = time(nullptr);
+ const time_t wake_up_timestamp = static_cast<time_t>(WakeUpTime());
+
+ const uint32_t seconds_from_wake_up_signal =
+ labs(current_time - wake_up_timestamp);
+ const uint32_t wait_time =
+ application_manager_.get_settings().resumption_delay_after_ign();
+ LOG4CXX_DEBUG(
+ logger_,
+ "Current time: " << current_time << "; WakeUp Signal time: "
+ << wake_up_timestamp << "; Seconds passed from wake up: "
+ << seconds_from_wake_up_signal
+ << "; Timeout for HMI level resuming: " << wait_time);
+ return seconds_from_wake_up_signal <= wait_time;
+}
+
bool ResumeCtrlImpl::CheckAppRestrictions(
ApplicationConstSharedPtr application,
const smart_objects::SmartObject& saved_app) {
@@ -685,16 +904,23 @@ 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
: false;
LOG4CXX_DEBUG(logger_,
- "is_media_app " << application->is_media_application()
- << "; hmi_level " << hmi_level << " result "
- << result);
+ "is_media_app: " << application->is_media_application()
+ << "; hmi_level: " << hmi_level << "; result: "
+ << (result ? "Applicable for resume"
+ : "Non-applicable for resume"));
return result;
}
@@ -707,11 +933,36 @@ bool ResumeCtrlImpl::CheckIcons(ApplicationSharedPtr application,
return mobile_apis::Result::INVALID_DATA != verify_images;
}
-bool ResumeCtrlImpl::CheckDelayAfterIgnOn() {
+bool ResumeCtrlImpl::CheckIgnCyclesData() const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ const uint32_t global_ign_on_count =
+ resumption_storage_->GetGlobalIgnOnCounter();
+ const uint32_t the_first_ignition = 1;
+ const bool is_emergency_ign_off_occurred =
+ global_ign_on_count > the_first_ignition;
+ // global_ign_on_count is reseting to 0 at ignition off
+ // global_ign_on_count is incrementing at ignition on
+ // global_ign_on_count > 1 means that correct ignition off was not present.
+ if (is_emergency_ign_off_occurred) {
+ LOG4CXX_WARN(logger_,
+ "Emergency IGN OFF occurred. Possibly after Low Voltage");
+ return false;
+ }
+ return true;
+}
+
+bool ResumeCtrlImpl::CheckDelayAfterIgnOn() const {
using namespace date_time;
LOG4CXX_AUTO_TRACE(logger_);
- const time_t curr_time = time(NULL);
+ const time_t ign_off_time = GetIgnOffTime();
+
+ if (CheckIgnCyclesData() && 0 == ign_off_time) {
+ LOG4CXX_DEBUG(logger_, "This is first Ignition cycle");
+ return true;
+ }
+ const time_t curr_time = time(nullptr);
const time_t sdl_launch_time = LaunchTime();
+
const uint32_t seconds_from_sdl_start = labs(curr_time - sdl_launch_time);
const uint32_t wait_time =
application_manager_.get_settings().resumption_delay_after_ign();
@@ -727,7 +978,7 @@ time_t ResumeCtrlImpl::LaunchTime() const {
return launch_time_;
}
-time_t ResumeCtrlImpl::GetIgnOffTime() {
+time_t ResumeCtrlImpl::GetIgnOffTime() const {
return resumption_storage_->GetIgnOffTime();
}
@@ -743,7 +994,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 +1013,21 @@ 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) {
+ LOG4CXX_DEBUG(logger_,
+ "Application ID " << app_id << " will be restored by timer");
restore_hmi_level_timer_.Start(
application_manager_.get_settings().app_resuming_timeout(),
timer::kSingleShot);
@@ -834,4 +1092,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