diff options
Diffstat (limited to 'src/components/application_manager/src/state_controller_impl.cc')
-rw-r--r-- | src/components/application_manager/src/state_controller_impl.cc | 560 |
1 files changed, 325 insertions, 235 deletions
diff --git a/src/components/application_manager/src/state_controller_impl.cc b/src/components/application_manager/src/state_controller_impl.cc index 84081a3830..3d44709657 100644 --- a/src/components/application_manager/src/state_controller_impl.cc +++ b/src/components/application_manager/src/state_controller_impl.cc @@ -31,24 +31,29 @@ */ #include "application_manager/state_controller_impl.h" +#include <tuple> #include "application_manager/usage_statistics.h" +#include "application_manager/rpc_service.h" #include "utils/helpers.h" -#include "utils/make_shared.h" + #include "connection_handler/connection_handler.h" namespace application_manager { CREATE_LOGGERPTR_GLOBAL(logger_, "StateControllerImpl") -bool IsStatusChanged(HmiStatePtr old_state, HmiStatePtr new_state) { - if (old_state->hmi_level() != new_state->hmi_level() || - old_state->audio_streaming_state() != - new_state->audio_streaming_state() || - old_state->system_context() != new_state->system_context()) { - return true; - } - return false; +namespace { +bool IsStateChanged(const HmiState& old_state, const HmiState& new_state) { + return std::make_tuple(old_state.hmi_level(), + old_state.audio_streaming_state(), + old_state.video_streaming_state(), + old_state.system_context()) != + std::make_tuple(new_state.hmi_level(), + new_state.audio_streaming_state(), + new_state.video_streaming_state(), + new_state.system_context()); } +} // unnamed namespace StateControllerImpl::StateControllerImpl(ApplicationManager& app_mngr) : EventObserver(app_mngr.event_dispatcher()), app_mngr_(app_mngr) { @@ -64,20 +69,20 @@ StateControllerImpl::StateControllerImpl(ApplicationManager& app_mngr) void StateControllerImpl::SetRegularState(ApplicationSharedPtr app, HmiStatePtr state, const bool send_activate_app) { - CREATE_LOGGERPTR_LOCAL(logger_, "StateControllerImpl"); LOG4CXX_AUTO_TRACE(logger_); - if (!app) { - LOG4CXX_ERROR(logger_, "Invalid application pointer"); - return; - } + DCHECK_OR_RETURN_VOID(app); DCHECK_OR_RETURN_VOID(state); - DCHECK_OR_RETURN_VOID(state->state_id() == HmiState::STATE_ID_REGULAR); + DCHECK_OR_RETURN_VOID(HmiState::STATE_ID_REGULAR == state->state_id()); + + LOG4CXX_DEBUG(logger_, "Set regular state " << *state); if (state->hmi_level() == mobile_apis::HMILevel::INVALID_ENUM || state->audio_streaming_state() == mobile_apis::AudioStreamingState::INVALID_ENUM || + state->video_streaming_state() == + mobile_apis::VideoStreamingState::INVALID_ENUM || state->system_context() == mobile_apis::SystemContext::INVALID_ENUM) { - LOG4CXX_ERROR(logger_, "Get invalid state"); + LOG4CXX_ERROR(logger_, "Got invalid state"); return; } @@ -91,7 +96,8 @@ void StateControllerImpl::SetRegularState(ApplicationSharedPtr app, app->SetPostponedState(state); return; } - hmi_apis::Common_HMILevel::eType hmi_level = + LOG4CXX_DEBUG(logger_, "Resolved state: " << *resolved_state); + const hmi_apis::Common_HMILevel::eType hmi_level = static_cast<hmi_apis::Common_HMILevel::eType>( resolved_state->hmi_level()); @@ -100,7 +106,7 @@ void StateControllerImpl::SetRegularState(ApplicationSharedPtr app, if (-1 != corr_id) { subscribe_on_event(hmi_apis::FunctionID::BasicCommunication_ActivateApp, corr_id); - waiting_for_activate[app->app_id()] = resolved_state; + waiting_for_activate_[app->app_id()] = resolved_state; return; } LOG4CXX_ERROR(logger_, "Unable to send BC.ActivateApp"); @@ -113,13 +119,10 @@ void StateControllerImpl::SetRegularState( ApplicationSharedPtr app, const mobile_apis::HMILevel::eType hmi_level, const mobile_apis::AudioStreamingState::eType audio_state, + const mobile_apis::VideoStreamingState::eType video_state, const bool send_activate_app) { - CREATE_LOGGERPTR_LOCAL(logger_, "StateControllerImpl"); LOG4CXX_AUTO_TRACE(logger_); - if (!app) { - LOG4CXX_ERROR(logger_, "Invalid application pointer"); - return; - } + DCHECK_OR_RETURN_VOID(app); HmiStatePtr prev_regular = app->RegularHmiState(); DCHECK_OR_RETURN_VOID(prev_regular); HmiStatePtr hmi_state = @@ -127,6 +130,7 @@ void StateControllerImpl::SetRegularState( DCHECK_OR_RETURN_VOID(hmi_state); hmi_state->set_hmi_level(hmi_level); hmi_state->set_audio_streaming_state(audio_state); + hmi_state->set_video_streaming_state(video_state); hmi_state->set_system_context(prev_regular->system_context()); SetRegularState(app, hmi_state, send_activate_app); } @@ -136,19 +140,15 @@ void StateControllerImpl::SetRegularState( const mobile_apis::HMILevel::eType hmi_level, const bool send_activate_app) { using namespace mobile_apis; - using namespace helpers; - CREATE_LOGGERPTR_LOCAL(logger_, "StateControllerImpl"); LOG4CXX_AUTO_TRACE(logger_); - if (!app) { - LOG4CXX_ERROR(logger_, "Invalid application pointer"); - return; - } + DCHECK_OR_RETURN_VOID(app); const HmiStatePtr hmi_state = CreateHmiState(app, HmiState::StateID::STATE_ID_REGULAR); DCHECK_OR_RETURN_VOID(hmi_state); hmi_state->set_hmi_level(hmi_level); hmi_state->set_audio_streaming_state(CalcAudioState(app, hmi_level)); + hmi_state->set_video_streaming_state(CalcVideoState(app, hmi_level)); hmi_state->set_system_context(SystemContext::SYSCTXT_MAIN); SetRegularState(app, hmi_state, send_activate_app); } @@ -157,37 +157,32 @@ void StateControllerImpl::SetRegularState( ApplicationSharedPtr app, const mobile_apis::HMILevel::eType hmi_level, const mobile_apis::AudioStreamingState::eType audio_state, + const mobile_apis::VideoStreamingState::eType video_state, const mobile_apis::SystemContext::eType system_context, const bool send_activate_app) { - CREATE_LOGGERPTR_LOCAL(logger_, "StateControllerImpl"); LOG4CXX_AUTO_TRACE(logger_); - if (!app) { - LOG4CXX_ERROR(logger_, "Invalid application pointer"); - return; - } + DCHECK_OR_RETURN_VOID(app); HmiStatePtr hmi_state = CreateHmiState(app, HmiState::StateID::STATE_ID_REGULAR); DCHECK_OR_RETURN_VOID(hmi_state); hmi_state->set_hmi_level(hmi_level); hmi_state->set_audio_streaming_state(audio_state); + hmi_state->set_video_streaming_state(video_state); hmi_state->set_system_context(system_context); SetRegularState(app, hmi_state, send_activate_app); } void StateControllerImpl::SetRegularState( ApplicationSharedPtr app, const mobile_apis::HMILevel::eType hmi_level) { - CREATE_LOGGERPTR_LOCAL(logger_, "StateControllerImpl"); LOG4CXX_AUTO_TRACE(logger_); - if (!app) { - LOG4CXX_ERROR(logger_, "Invalid application pointer"); - return; - } + DCHECK_OR_RETURN_VOID(app); HmiStatePtr prev_state = app->RegularHmiState(); HmiStatePtr hmi_state = CreateHmiState(app, HmiState::StateID::STATE_ID_REGULAR); DCHECK_OR_RETURN_VOID(hmi_state); hmi_state->set_hmi_level(hmi_level); hmi_state->set_audio_streaming_state(CalcAudioState(app, hmi_level)); + hmi_state->set_video_streaming_state(CalcVideoState(app, hmi_level)); hmi_state->set_system_context(prev_state ? prev_state->system_context() : mobile_apis::SystemContext::SYSCTXT_MAIN); @@ -197,12 +192,8 @@ void StateControllerImpl::SetRegularState( void StateControllerImpl::SetRegularState( ApplicationSharedPtr app, const mobile_apis::SystemContext::eType system_context) { - CREATE_LOGGERPTR_LOCAL(logger_, "StateControllerImpl"); LOG4CXX_AUTO_TRACE(logger_); - if (!app) { - LOG4CXX_ERROR(logger_, "Invalid application pointer"); - return; - } + DCHECK_OR_RETURN_VOID(app); HmiStatePtr prev_regular = app->RegularHmiState(); DCHECK_OR_RETURN_VOID(prev_regular); HmiStatePtr hmi_state = @@ -211,19 +202,18 @@ void StateControllerImpl::SetRegularState( hmi_state->set_hmi_level(prev_regular->hmi_level()); hmi_state->set_audio_streaming_state( CalcAudioState(app, prev_regular->hmi_level())); + hmi_state->set_video_streaming_state( + CalcVideoState(app, prev_regular->hmi_level())); hmi_state->set_system_context(system_context); SetRegularState(app, hmi_state, false); } void StateControllerImpl::SetRegularState( ApplicationSharedPtr app, - const mobile_apis::AudioStreamingState::eType audio_state) { - CREATE_LOGGERPTR_LOCAL(logger_, "StateControllerImpl"); + const mobile_apis::AudioStreamingState::eType audio_state, + const mobile_apis::VideoStreamingState::eType video_state) { LOG4CXX_AUTO_TRACE(logger_); - if (!app) { - LOG4CXX_ERROR(logger_, "Invalid application pointer"); - return; - } + DCHECK_OR_RETURN_VOID(app); HmiStatePtr prev_state = app->RegularHmiState(); DCHECK_OR_RETURN_VOID(prev_state); HmiStatePtr hmi_state = @@ -231,18 +221,15 @@ void StateControllerImpl::SetRegularState( DCHECK_OR_RETURN_VOID(hmi_state); hmi_state->set_hmi_level(prev_state->hmi_level()); hmi_state->set_audio_streaming_state(audio_state); + hmi_state->set_video_streaming_state(video_state); hmi_state->set_system_context(prev_state->system_context()); SetRegularState(app, hmi_state, false); } void StateControllerImpl::SetRegularState(ApplicationSharedPtr app, HmiStatePtr state) { - CREATE_LOGGERPTR_LOCAL(logger_, "StateControllerImpl"); LOG4CXX_AUTO_TRACE(logger_); - if (!app) { - LOG4CXX_ERROR(logger_, "Invalid application pointer"); - return; - } + DCHECK_OR_RETURN_VOID(app); DCHECK_OR_RETURN_VOID(state); if (mobile_apis::HMILevel::HMI_FULL == state->hmi_level()) { SetRegularState(app, state, true); @@ -251,84 +238,178 @@ void StateControllerImpl::SetRegularState(ApplicationSharedPtr app, } } -void StateControllerImpl::HmiLevelConflictResolver::operator()( - ApplicationSharedPtr to_resolve) { - using namespace mobile_apis; +namespace { + +/** + * @brief IsStreamableHMILevel checks whether the HMI level + * supports audio/video streaming. + * @param val HMI level + * @return true if streamable, false otherwise + */ +bool IsStreamableHMILevel(mobile_apis::HMILevel::eType val) { using namespace helpers; + return Compare<mobile_apis::HMILevel::eType, EQ, ONE>( + val, mobile_apis::HMILevel::HMI_FULL, mobile_apis::HMILevel::HMI_LIMITED); +} + +/** + * @brief IsSameAudioAppType checks whether the both applications: + * 1) belongs to exact HMI type that may stream audio without + * 'isMediaApplication' parameter set to true ('NAVIGATION', 'COMMUNICATION') + * 2) belongs to other HMI types with parameter 'isMediaApplication' + * is set to true. + * 3) are not media. + * @param app1 1st application + * @param app2 2nd application + * @return true if audio applications have same application HMI type + */ +bool IsSameAudioAppType(const Application& app1, const Application& app2) { + const auto is_only_media_app_type = [](const Application& app) { + return app.is_media_application() && !app.is_navi() && + !app.is_voice_communication_supported(); + }; + + const bool both_navi = app1.is_navi() && app2.is_navi(); + const bool both_vc = app1.is_voice_communication_supported() && + app2.is_voice_communication_supported(); + const bool both_media = + is_only_media_app_type(app1) && is_only_media_app_type(app2); + const bool both_other = + !app1.IsAudioApplication() && !app2.IsAudioApplication(); + const bool same_app_audio_type = + both_navi || both_vc || both_media || both_other; + + return same_app_audio_type; +} +} // unnamed namespace + +void StateControllerImpl::HmiLevelConflictResolver::operator()( + ApplicationSharedPtr app_to_resolve) { + DCHECK_OR_RETURN_VOID(app_to_resolve); DCHECK_OR_RETURN_VOID(state_ctrl_); - if (to_resolve == applied_) + DCHECK_OR_RETURN_VOID(applied_); + DCHECK_OR_RETURN_VOID(state_); + + if (applied_ == app_to_resolve) { + // Same app. Nothing to resolve + return; + } + + const HmiStatePtr state_to_resolve = app_to_resolve->RegularHmiState(); + DCHECK_OR_RETURN_VOID(state_to_resolve); + + // If applied HMI state is FULL: + // - all NOT audio/video applications becomes BACKGROUND + // - all audio/video applications with other app type + // (navi, vc, media, projection) in FULL becomes LIMMITED + // - all audio/video applications with same app type becomes BACKGROUND + // + // If applied HMI state is LIMITED: + // - all NOT audio/video applications saves their's HMI states + // - all applications with other app types saves their's HMI states + // - all audio/video applications with same app type becomes BACKGROUND + + if (!IsStreamableHMILevel(state_->hmi_level())) { + LOG4CXX_DEBUG(logger_, + "Applied for app " << applied_->app_id() << " HMI level " + << state_->hmi_level() + << " is NOT streamable. Exit."); return; - HmiStatePtr cur_state = to_resolve->RegularHmiState(); - - const bool applied_grabs_audio = - Compare<HMILevel::eType, EQ, ONE>( - state_->hmi_level(), HMILevel::HMI_FULL, HMILevel::HMI_LIMITED) && - applied_->IsAudioApplication(); - const bool applied_grabs_full = state_->hmi_level() == HMILevel::HMI_FULL; - const bool to_resolve_handles_full = - cur_state->hmi_level() == HMILevel::HMI_FULL; - const bool to_resolve_handles_audio = - Compare<HMILevel::eType, EQ, ONE>( - cur_state->hmi_level(), HMILevel::HMI_FULL, HMILevel::HMI_LIMITED) && - to_resolve->IsAudioApplication(); - const bool same_app_type = state_ctrl_->IsSameAppType(applied_, to_resolve); - - // If applied Hmi state is FULL: - // all not audio applications will get BACKGROUND - // all applications with same HMI type will get BACKGROUND - // all audio applications with other HMI type(navi, vc, media) in FULL will - // get LIMMITED HMI level - - // If applied Hmi state is LIMITED: - // all applications with other HMI types will save HMI states - // all not audio applications will save HMI states - // all applications with same HMI type will get BACKGROUND - - // If applied Hmi state is BACKGROUND: - // all applications will save HMI states - - HMILevel::eType result_hmi_level = cur_state->hmi_level(); - if (applied_grabs_full && to_resolve_handles_audio && !same_app_type) - result_hmi_level = HMILevel::HMI_LIMITED; - - if ((applied_grabs_full && to_resolve_handles_full && - !to_resolve->IsAudioApplication()) || - (applied_grabs_audio && to_resolve_handles_audio && same_app_type)) - result_hmi_level = HMILevel::HMI_BACKGROUND; - - if (cur_state->hmi_level() != result_hmi_level) { + } + + if (!IsStreamableHMILevel(state_to_resolve->hmi_level())) { LOG4CXX_DEBUG(logger_, - "Application " << to_resolve->app_id() - << " will change HMI level to " - << result_hmi_level); - state_ctrl_->SetupRegularHmiState(to_resolve, + "To resolve app " << app_to_resolve->app_id() << " HMI level " + << state_to_resolve->hmi_level() + << " is NOT streamable. Exit."); + return; + } + + // Applied app constants + const auto applied_hmi_level = state_->hmi_level(); + + const bool applied_grabs_video = + IsStreamableHMILevel(applied_hmi_level) && applied_->IsVideoApplication(); + + // App to resolve constants + const auto to_resolve_hmi_level = state_to_resolve->hmi_level(); + + const bool to_resolve_grabs_audio = + IsStreamableHMILevel(to_resolve_hmi_level) && + app_to_resolve->IsAudioApplication(); + + const bool to_resolve_grabs_video = + IsStreamableHMILevel(to_resolve_hmi_level) && + app_to_resolve->IsVideoApplication(); + + // Compatibility constants + const bool same_app_audio_type = + IsSameAudioAppType(*applied_, *app_to_resolve); + + // Result variables + mobile_apis::VideoStreamingState::eType result_video_state = + mobile_apis::VideoStreamingState::NOT_STREAMABLE; + mobile_apis::AudioStreamingState::eType result_audio_state = + mobile_apis::AudioStreamingState::NOT_AUDIBLE; + + if (to_resolve_grabs_audio && !same_app_audio_type) { + result_audio_state = mobile_apis::AudioStreamingState::AUDIBLE; + } + + if (to_resolve_grabs_video && !applied_grabs_video) { + result_video_state = mobile_apis::VideoStreamingState::STREAMABLE; + } + + mobile_apis::HMILevel::eType result_hmi_level = state_to_resolve->hmi_level(); + + using namespace helpers; + if (mobile_apis::VideoStreamingState::STREAMABLE == result_video_state || + Compare<mobile_apis::AudioStreamingState::eType, EQ, ONE>( + result_audio_state, + mobile_apis::AudioStreamingState::AUDIBLE, + mobile_apis::AudioStreamingState::ATTENUATED)) { + result_hmi_level = mobile_apis::HMILevel::HMI_LIMITED; + } else { + result_hmi_level = mobile_apis::HMILevel::HMI_BACKGROUND; + } + + if (std::make_tuple(to_resolve_hmi_level, + state_to_resolve->audio_streaming_state(), + state_to_resolve->video_streaming_state()) != + std::make_tuple( + result_hmi_level, result_audio_state, result_video_state)) { + LOG4CXX_DEBUG(logger_, + "Application " + << app_to_resolve->app_id() << " will change state to: " + << "HMI level " << to_resolve_hmi_level << " --> " + << result_hmi_level << ", audio " + << state_to_resolve->audio_streaming_state() << " --> " + << result_audio_state << ", video " + << state_to_resolve->video_streaming_state() << " --> " + << result_video_state); + state_ctrl_->SetupRegularHmiState(app_to_resolve, result_hmi_level, - result_hmi_level == HMILevel::HMI_LIMITED - ? AudioStreamingState::AUDIBLE - : AudioStreamingState::NOT_AUDIBLE); + result_audio_state, + result_video_state); } else { LOG4CXX_DEBUG(logger_, - "Application " << to_resolve->app_id() - << " will not change HMI level"); + "Application " << app_to_resolve->app_id() + << " will NOT change HMI level"); } } HmiStatePtr StateControllerImpl::ResolveHmiState(ApplicationSharedPtr app, HmiStatePtr state) const { using namespace mobile_apis; - using namespace helpers; LOG4CXX_AUTO_TRACE(logger_); - LOG4CXX_DEBUG(logger_, - "State to resolve: hmi_level " - << state->hmi_level() << ", audio_state " - << state->audio_streaming_state() << ", system_context " - << state->system_context()); + LOG4CXX_DEBUG(logger_, "State to resolve: " << *state); HmiStatePtr available_state = CreateHmiState(app, HmiState::StateID::STATE_ID_REGULAR); DCHECK_OR_RETURN(available_state, HmiStatePtr()); available_state->set_hmi_level(state->hmi_level()); available_state->set_audio_streaming_state(state->audio_streaming_state()); + available_state->set_video_streaming_state(state->video_streaming_state()); available_state->set_system_context(state->system_context()); if (app->is_resuming()) { @@ -337,6 +418,8 @@ HmiStatePtr StateControllerImpl::ResolveHmiState(ApplicationSharedPtr app, available_state->set_hmi_level(available_level); available_state->set_audio_streaming_state( CalcAudioState(app, available_level)); + available_state->set_video_streaming_state( + CalcVideoState(app, available_level)); } return IsStateAvailable(app, available_state) ? available_state : HmiStatePtr(); @@ -345,11 +428,8 @@ HmiStatePtr StateControllerImpl::ResolveHmiState(ApplicationSharedPtr app, bool StateControllerImpl::IsResumptionAllowed(ApplicationSharedPtr app, HmiStatePtr state) const { LOG4CXX_AUTO_TRACE(logger_); - using namespace helpers; using namespace mobile_apis; - if (!app->is_resuming() || - !Compare<HMILevel::eType, EQ, ONE>( - state->hmi_level(), HMILevel::HMI_FULL, HMILevel::HMI_LIMITED)) { + if (!app->is_resuming() || !IsStreamableHMILevel(state->hmi_level())) { LOG4CXX_DEBUG(logger_, "Application is not in resuming mode."); return true; } @@ -375,27 +455,27 @@ bool StateControllerImpl::IsResumptionAllowed(ApplicationSharedPtr app, mobile_apis::HMILevel::eType StateControllerImpl::GetAvailableHmiLevel( ApplicationSharedPtr app, mobile_apis::HMILevel::eType hmi_level) const { - using namespace mobile_apis; - using namespace helpers; LOG4CXX_AUTO_TRACE(logger_); mobile_apis::HMILevel::eType result = hmi_level; - if (!Compare<HMILevel::eType, EQ, ONE>( - hmi_level, HMILevel::HMI_FULL, HMILevel::HMI_LIMITED)) { + LOG4CXX_DEBUG(logger_, "HMI Level: " << hmi_level); + + if (!IsStreamableHMILevel(hmi_level)) { return result; } const bool is_audio_app = app->IsAudioApplication(); const bool does_audio_app_with_same_type_exist = app_mngr_.IsAppTypeExistsInFullOrLimited(app); - if (HMILevel::HMI_LIMITED == hmi_level) { + + if (mobile_apis::HMILevel::HMI_LIMITED == hmi_level) { if (!is_audio_app || does_audio_app_with_same_type_exist) { result = app_mngr_.GetDefaultHmiLevel(app); } return result; } - const bool is_active_app_exist = app_mngr_.active_application(); + const bool is_active_app_exist = (bool)app_mngr_.active_application(); if (is_audio_app) { if (does_audio_app_with_same_type_exist) { result = app_mngr_.GetDefaultHmiLevel(app); @@ -424,13 +504,8 @@ mobile_apis::HMILevel::eType StateControllerImpl::GetAvailableHmiLevel( bool StateControllerImpl::IsStateAvailable(ApplicationSharedPtr app, HmiStatePtr state) const { using namespace mobile_apis; - using namespace helpers; LOG4CXX_AUTO_TRACE(logger_); - LOG4CXX_DEBUG(logger_, - "Checking state: hmi_level " - << state->hmi_level() << ", audio_state " - << state->audio_streaming_state() << ", system_context " - << state->system_context()); + LOG4CXX_DEBUG(logger_, "Checking state: " << *state); if (app->is_resuming()) { return IsStateAvailableForResumption(app, state); @@ -454,11 +529,8 @@ bool StateControllerImpl::IsStateAvailableForResumption( ApplicationSharedPtr app, HmiStatePtr state) const { LOG4CXX_AUTO_TRACE(logger_); using namespace mobile_apis; - using namespace helpers; - if (!app->is_resuming() || - !Compare<HMILevel::eType, EQ, ONE>( - state->hmi_level(), HMILevel::HMI_FULL, HMILevel::HMI_LIMITED)) { + if (!app->is_resuming() || !IsStreamableHMILevel(state->hmi_level())) { LOG4CXX_DEBUG(logger_, "Application is not in resuming mode." << " Requested state is available"); @@ -492,20 +564,17 @@ bool StateControllerImpl::IsStateAvailableForResumption( void StateControllerImpl::SetupRegularHmiState(ApplicationSharedPtr app, HmiStatePtr state) { - namespace HMILevel = mobile_apis::HMILevel; - namespace AudioStreamingState = mobile_apis::AudioStreamingState; + using namespace mobile_apis; LOG4CXX_AUTO_TRACE(logger_); DCHECK_OR_RETURN_VOID(state); - LOG4CXX_DEBUG(logger_, - "hmi_level " << state->hmi_level() << ", audio_state " - << state->audio_streaming_state() - << ", system_context " << state->system_context()); + LOG4CXX_DEBUG(logger_, "Setup regular state: " << *state); HmiStatePtr curr_state = app->CurrentHmiState(); HmiStatePtr old_state = CreateHmiState(app, HmiState::StateID::STATE_ID_REGULAR); DCHECK_OR_RETURN_VOID(old_state); old_state->set_hmi_level(curr_state->hmi_level()); old_state->set_audio_streaming_state(curr_state->audio_streaming_state()); + old_state->set_video_streaming_state(curr_state->video_streaming_state()); old_state->set_system_context(curr_state->system_context()); app->SetRegularState(state); @@ -524,10 +593,8 @@ void StateControllerImpl::SetupRegularHmiState(ApplicationSharedPtr app, void StateControllerImpl::SetupRegularHmiState( ApplicationSharedPtr app, const mobile_apis::HMILevel::eType hmi_level, - const mobile_apis::AudioStreamingState::eType audio_state) { - namespace HMILevel = mobile_apis::HMILevel; - namespace AudioStreamingState = mobile_apis::AudioStreamingState; - using helpers::Compare; + const mobile_apis::AudioStreamingState::eType audio_state, + const mobile_apis::VideoStreamingState::eType video_state) { LOG4CXX_AUTO_TRACE(logger_); DCHECK_OR_RETURN_VOID(app); HmiStatePtr prev_state = app->RegularHmiState(); @@ -537,6 +604,7 @@ void StateControllerImpl::SetupRegularHmiState( DCHECK_OR_RETURN_VOID(new_state); new_state->set_hmi_level(hmi_level); new_state->set_audio_streaming_state(audio_state); + new_state->set_video_streaming_state(video_state); new_state->set_system_context(prev_state->system_context()); SetupRegularHmiState(app, new_state); } @@ -547,28 +615,12 @@ void StateControllerImpl::ApplyRegularState(ApplicationSharedPtr app, DCHECK_OR_RETURN_VOID(app); DCHECK_OR_RETURN_VOID(state); DCHECK_OR_RETURN_VOID(state->state_id() == HmiState::STATE_ID_REGULAR); + LOG4CXX_DEBUG(logger_, + "Applying to app " << app->app_id() << " state " << *state); SetupRegularHmiState(app, state); - ForEachApplication<HmiLevelConflictResolver>( - HmiLevelConflictResolver(app, state, this)); -} - -bool StateControllerImpl::IsSameAppType(ApplicationConstSharedPtr app1, - ApplicationConstSharedPtr app2) { - const bool both_media = - app1->is_media_application() && app2->is_media_application(); - - const bool both_navi = app1->is_navi() && app2->is_navi(); - - const bool both_vc = app1->is_voice_communication_supported() && - app2->is_voice_communication_supported(); - - const bool both_simple = - !app1->IsAudioApplication() && !app2->IsAudioApplication(); - - const bool both_projection = - app1->mobile_projection_enabled() && app2->mobile_projection_enabled(); - - return both_simple || both_media || both_navi || both_vc || both_projection; + LOG4CXX_DEBUG(logger_, + "Resolving HMI level conflicts for app " << app->app_id()); + ForEachApplication(HmiLevelConflictResolver(app, state, this)); } void StateControllerImpl::on_event(const event_engine::Event& event) { @@ -615,7 +667,7 @@ void StateControllerImpl::on_event(const event_engine::Event& event) { const uint32_t id = message[strings::msg_params][hmi_notification::event_name].asUInt(); // TODO(AOleynik): Add verification/conversion check here - Common_EventTypes::eType state_id = + const Common_EventTypes::eType state_id = static_cast<Common_EventTypes::eType>(id); if (is_active) { if (Common_EventTypes::AUDIO_SOURCE == state_id) { @@ -660,6 +712,9 @@ void StateControllerImpl::on_event(const event_engine::Event& event) { break; } } + + LOG4CXX_WARN(logger_, + "Couldn't recognize state id (val='" << state_id << "')"); break; } default: @@ -674,17 +729,9 @@ void StateControllerImpl::OnStateChanged(ApplicationSharedPtr app, DCHECK_OR_RETURN_VOID(app); DCHECK_OR_RETURN_VOID(old_state); DCHECK_OR_RETURN_VOID(new_state); - LOG4CXX_DEBUG(logger_, - "old: hmi_level " << old_state->hmi_level() << ", audio_state " - << old_state->audio_streaming_state() - << ", system_context " - << old_state->system_context()); - LOG4CXX_DEBUG(logger_, - "new: hmi_level " << new_state->hmi_level() << ", audio_state " - << new_state->audio_streaming_state() - << ", system_context " - << new_state->system_context()); - if (IsStatusChanged(old_state, new_state)) { + LOG4CXX_DEBUG(logger_, "Old state: " << *old_state); + LOG4CXX_DEBUG(logger_, "New state: " << *new_state); + if (IsStateChanged(*old_state, *new_state)) { app_mngr_.SendHMIStatusNotification(app); if (new_state->hmi_level() == mobile_apis::HMILevel::HMI_NONE) { app->ResetDataInNone(); @@ -693,15 +740,13 @@ void StateControllerImpl::OnStateChanged(ApplicationSharedPtr app, app->app_id(), old_state->hmi_level(), new_state->hmi_level()); app->usage_report().RecordHmiStateChanged(new_state->hmi_level()); } else { - LOG4CXX_ERROR(logger_, "Status not changed"); + LOG4CXX_ERROR(logger_, "State has NOT been changed."); } } -bool StateControllerImpl::IsTempStateActive(HmiState::StateID ID) const { +bool StateControllerImpl::IsTempStateActive(HmiState::StateID id) const { sync_primitives::AutoLock autolock(active_states_lock_); - StateIDList::const_iterator itr = - std::find(active_states_.begin(), active_states_.end(), ID); - return active_states_.end() != itr; + return helpers::in_range(active_states_, id); } void StateControllerImpl::OnApplicationRegistered( @@ -713,23 +758,25 @@ void StateControllerImpl::OnApplicationRegistered( LOG4CXX_AUTO_TRACE(logger_); DCHECK_OR_RETURN_VOID(app); - active_states_lock_.Acquire(); - StateIDList::iterator it = active_states_.begin(); - for (; it != active_states_.end(); ++it) { - HmiStatePtr new_state = CreateHmiState(app, *it); - DCHECK_OR_RETURN_VOID(new_state); - DCHECK_OR_RETURN_VOID(new_state->state_id() != HmiState::STATE_ID_REGULAR); - HmiStatePtr old_hmi_state = app->CurrentHmiState(); - new_state->set_parent(old_hmi_state); - app->AddHMIState(new_state); + { + sync_primitives::AutoLock lck(active_states_lock_); + for (const auto state_id : active_states_) { + HmiStatePtr new_state = CreateHmiState(app, state_id); + DCHECK_OR_RETURN_VOID(new_state); + DCHECK_OR_RETURN_VOID(new_state->state_id() != + HmiState::STATE_ID_REGULAR); + HmiStatePtr old_hmi_state = app->CurrentHmiState(); + new_state->set_parent(old_hmi_state); + app->AddHMIState(new_state); + } } - active_states_lock_.Release(); HmiStatePtr default_state = CreateHmiState(app, HmiState::StateID::STATE_ID_REGULAR); DCHECK_OR_RETURN_VOID(default_state); default_state->set_hmi_level(default_level); default_state->set_audio_streaming_state(CalcAudioState(app, default_level)); + default_state->set_video_streaming_state(CalcVideoState(app, default_level)); default_state->set_system_context(SystemContext::SYSCTXT_MAIN); HmiStatePtr initial_state = app->RegularHmiState(); @@ -758,7 +805,7 @@ int64_t StateControllerImpl::SendBCActivateApp( LOG4CXX_ERROR(logger_, "Unable to create BC.ActivateAppRequest"); return -1; } - if (!app_mngr_.ManageHMICommand(bc_activate_app_request)) { + if (!app_mngr_.GetRPCService().ManageHMICommand(bc_activate_app_request)) { LOG4CXX_ERROR(logger_, "Unable to send BC.ActivateAppRequest"); return -1; } @@ -778,16 +825,18 @@ void StateControllerImpl::ApplyPostponedStateForApp(ApplicationSharedPtr app) { } } -void StateControllerImpl::TempStateStarted(HmiState::StateID ID) { +void StateControllerImpl::TempStateStarted(HmiState::StateID id) { LOG4CXX_AUTO_TRACE(logger_); - sync_primitives::AutoLock autolock(active_states_lock_); - StateIDList::iterator it = - std::find(active_states_.begin(), active_states_.end(), ID); - if (it == active_states_.end()) { - active_states_.push_back(ID); - } else { - LOG4CXX_ERROR(logger_, "StateID " << ID << " is already active"); + + { + sync_primitives::AutoLock autolock(active_states_lock_); + if (!helpers::in_range(active_states_, id)) { + active_states_.push_back(id); + return; + } } + + LOG4CXX_ERROR(logger_, "StateID '" << id << "' is already active"); } void StateControllerImpl::TempStateStopped(HmiState::StateID ID) { @@ -805,16 +854,34 @@ void StateControllerImpl::DeactivateApp(ApplicationSharedPtr app) { LOG4CXX_AUTO_TRACE(logger_); DCHECK_OR_RETURN_VOID(app); - HmiStatePtr regular = app->RegularHmiState(); + const HmiStatePtr regular = app->RegularHmiState(); DCHECK_OR_RETURN_VOID(regular); - HmiStatePtr new_regular = utils::MakeShared<HmiState>(*regular); + HmiStatePtr new_regular = std::make_shared<HmiState>(*regular); + + LOG4CXX_DEBUG(logger_, "Current HMI level: '" << app->hmi_level() << "'"); + const bool is_audio_app = app->IsAudioApplication(); + const bool is_video_app = app->IsVideoApplication(); - if (app->IsAudioApplication()) { + if (is_audio_app || is_video_app) { + // audio or video app move to HMI level limited new_regular->set_hmi_level(HMILevel::HMI_LIMITED); - new_regular->set_audio_streaming_state(AudioStreamingState::AUDIBLE); + + if (is_audio_app) { + new_regular->set_audio_streaming_state(AudioStreamingState::AUDIBLE); + } else { + new_regular->set_audio_streaming_state(AudioStreamingState::NOT_AUDIBLE); + } + + if (is_video_app) { + new_regular->set_video_streaming_state(VideoStreamingState::STREAMABLE); + } else { + new_regular->set_video_streaming_state( + VideoStreamingState::NOT_STREAMABLE); + } } else { new_regular->set_hmi_level(HMILevel::HMI_BACKGROUND); new_regular->set_audio_streaming_state(AudioStreamingState::NOT_AUDIBLE); + new_regular->set_video_streaming_state(VideoStreamingState::NOT_STREAMABLE); } SetRegularState(app, new_regular, false); @@ -831,7 +898,7 @@ void StateControllerImpl::OnActivateAppResponse( ApplicationSharedPtr application = app_mngr_.application_by_hmi_app(hmi_app_id); if (application && hmi_apis::Common_Result::SUCCESS == code) { - HmiStatePtr pending_state = waiting_for_activate[application->app_id()]; + HmiStatePtr pending_state = waiting_for_activate_[application->app_id()]; DCHECK_OR_RETURN_VOID(pending_state); ApplyRegularState(application, pending_state); } @@ -854,9 +921,7 @@ void StateControllerImpl::OnAppActivated( void StateControllerImpl::OnAppDeactivated( const smart_objects::SmartObject& message) { - using namespace hmi_apis; using namespace mobile_apis; - using namespace helpers; LOG4CXX_AUTO_TRACE(logger_); uint32_t app_id = message[strings::msg_params][strings::app_id].asUInt(); @@ -875,12 +940,22 @@ void StateControllerImpl::OnAppDeactivated( DeactivateApp(app); } -void StateControllerImpl::OnNaviStreamingStarted() { - ApplyTempState<HmiState::STATE_ID_NAVI_STREAMING>(); +void StateControllerImpl::OnVideoStreamingStarted( + ApplicationConstSharedPtr app) { + if (app->is_navi()) { + ApplyTempState<HmiState::STATE_ID_NAVI_STREAMING>(); + } else { + ApplyTempState<HmiState::STATE_ID_VIDEO_STREAMING>(); + } } -void StateControllerImpl::OnNaviStreamingStopped() { - CancelTempState<HmiState::STATE_ID_NAVI_STREAMING>(); +void StateControllerImpl::OnVideoStreamingStopped( + ApplicationConstSharedPtr app) { + if (app->is_navi()) { + CancelTempState<HmiState::STATE_ID_NAVI_STREAMING>(); + } else { + CancelTempState<HmiState::STATE_ID_VIDEO_STREAMING>(); + } } bool StateControllerImpl::IsStateActive(HmiState::StateID state_id) const { @@ -896,49 +971,53 @@ bool StateControllerImpl::IsStateActive(HmiState::StateID state_id) const { } HmiStatePtr StateControllerImpl::CreateHmiState( - utils::SharedPtr<Application> app, HmiState::StateID state_id) const { + std::shared_ptr<Application> app, HmiState::StateID state_id) const { using namespace utils; LOG4CXX_AUTO_TRACE(logger_); HmiStatePtr new_state; switch (state_id) { case HmiState::STATE_ID_PHONE_CALL: { - new_state = MakeShared<PhoneCallHmiState>(app, app_mngr_); + new_state = std::make_shared<PhoneCallHmiState>(app, app_mngr_); break; } case HmiState::STATE_ID_SAFETY_MODE: { - new_state = MakeShared<SafetyModeHmiState>(app, app_mngr_); + new_state = std::make_shared<SafetyModeHmiState>(app, app_mngr_); break; } case HmiState::STATE_ID_VR_SESSION: { - new_state = MakeShared<VRHmiState>(app, app_mngr_); + new_state = std::make_shared<VRHmiState>(app, app_mngr_); break; } case HmiState::STATE_ID_TTS_SESSION: { - new_state = MakeShared<TTSHmiState>(app, app_mngr_); + new_state = std::make_shared<TTSHmiState>(app, app_mngr_); + break; + } + case HmiState::STATE_ID_VIDEO_STREAMING: { + new_state = std::make_shared<VideoStreamingHmiState>(app, app_mngr_); break; } case HmiState::STATE_ID_NAVI_STREAMING: { - new_state = MakeShared<NaviStreamingHmiState>(app, app_mngr_); + new_state = std::make_shared<NaviStreamingHmiState>(app, app_mngr_); break; } case HmiState::STATE_ID_REGULAR: { - new_state = MakeShared<HmiState>(app, app_mngr_); + new_state = std::make_shared<HmiState>(app, app_mngr_); break; } case HmiState::STATE_ID_POSTPONED: { - new_state = MakeShared<HmiState>(app, app_mngr_, state_id); + new_state = std::make_shared<HmiState>(app, app_mngr_, state_id); break; } case HmiState::STATE_ID_DEACTIVATE_HMI: { - new_state = MakeShared<DeactivateHMI>(app, app_mngr_); + new_state = std::make_shared<DeactivateHMI>(app, app_mngr_); break; } case HmiState::STATE_ID_AUDIO_SOURCE: { - new_state = MakeShared<AudioSource>(app, app_mngr_); + new_state = std::make_shared<AudioSource>(app, app_mngr_); break; } case HmiState::STATE_ID_EMBEDDED_NAVI: { - new_state = MakeShared<EmbeddedNavi>(app, app_mngr_); + new_state = std::make_shared<EmbeddedNavi>(app, app_mngr_); break; } default: @@ -952,20 +1031,31 @@ HmiStatePtr StateControllerImpl::CreateHmiState( mobile_apis::AudioStreamingState::eType StateControllerImpl::CalcAudioState( ApplicationSharedPtr app, const mobile_apis::HMILevel::eType hmi_level) const { - namespace HMILevel = mobile_apis::HMILevel; - namespace AudioStreamingState = mobile_apis::AudioStreamingState; - using helpers::Compare; - using helpers::EQ; - using helpers::ONE; - - AudioStreamingState::eType audio_state = AudioStreamingState::NOT_AUDIBLE; - if (Compare<HMILevel::eType, EQ, ONE>( - hmi_level, HMILevel::HMI_FULL, HMILevel::HMI_LIMITED)) { - if (app->IsAudioApplication()) { - audio_state = AudioStreamingState::AUDIBLE; - } + auto state = mobile_apis::AudioStreamingState::NOT_AUDIBLE; + if (IsStreamableHMILevel(hmi_level) && app->IsAudioApplication()) { + state = mobile_apis::AudioStreamingState::AUDIBLE; } - return audio_state; + + LOG4CXX_DEBUG(logger_, + "Calculated audio state of app " + << app->app_id() << " for " << hmi_level << " HMI level is " + << state); + return state; +} + +mobile_apis::VideoStreamingState::eType StateControllerImpl::CalcVideoState( + ApplicationSharedPtr app, + const mobile_apis::HMILevel::eType hmi_level) const { + auto state = mobile_apis::VideoStreamingState::NOT_STREAMABLE; + if (IsStreamableHMILevel(hmi_level) && app->IsVideoApplication()) { + state = mobile_apis::VideoStreamingState::STREAMABLE; + } + + LOG4CXX_DEBUG(logger_, + "Calculated video state of app " + << app->app_id() << " for " << hmi_level << " HMI level is " + << state); + return state; } } // namespace application_manager |