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 | 1506 |
1 files changed, 981 insertions, 525 deletions
diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 6d7fdeec6..1c4a924c0 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014, Ford Motor Company * All rights reserved. * @@ -35,6 +35,7 @@ #include <climits> #include <string> #include <fstream> +#include <utility> #include "application_manager/application_manager_impl.h" #include "application_manager/mobile_command_factory.h" @@ -51,10 +52,19 @@ #include "config_profile/profile.h" #include "utils/threads/thread.h" #include "utils/file_system.h" +#include "utils/helpers.h" +#include "smart_objects/enum_schema_item.h" +#include "interfaces/HMI_API_schema.h" #include "application_manager/application_impl.h" #include "usage_statistics/counter.h" #include <time.h> +namespace { + int get_rand_from_range(uint32_t from = 0, int to = RAND_MAX) { + return std::rand() % to + from; + } +} + namespace application_manager { CREATE_LOGGERPTR_GLOBAL(logger_, "ApplicationManager") @@ -65,6 +75,8 @@ const uint32_t ApplicationManagerImpl::max_corelation_id_ = UINT_MAX; namespace formatters = NsSmartDeviceLink::NsJSONHandler::Formatters; namespace jhs = NsSmartDeviceLink::NsJSONHandler::strings; +using namespace NsSmartDeviceLink::NsSmartObjects; + ApplicationManagerImpl::ApplicationManagerImpl() : applications_list_lock_(true), audio_pass_thru_active_(false), @@ -83,9 +95,12 @@ ApplicationManagerImpl::ApplicationManagerImpl() messages_to_mobile_("AM ToMobile", this), messages_from_hmi_("AM FromHMI", this), messages_to_hmi_("AM ToHMI", this), + audio_pass_thru_messages_("AudioPassThru", this), hmi_capabilities_(this), - unregister_reason_(mobile_api::AppInterfaceUnregisteredReason::IGNITION_OFF), + unregister_reason_(mobile_api::AppInterfaceUnregisteredReason::INVALID_ENUM), resume_ctrl_(this), + end_services_timer("EndServiceTimer", this, &ApplicationManagerImpl::EndNaviServices), + wait_end_service_timeout_(profile::Profile::instance()->stop_streaming_timeout()), #ifdef TIME_TESTER metric_observer_(NULL), #endif // TIME_TESTER @@ -93,8 +108,10 @@ ApplicationManagerImpl::ApplicationManagerImpl() tts_global_properties_timer_("TTSGLPRTimer", this, &ApplicationManagerImpl::OnTimerSendTTSGlobalProperties, - true) { + true), + is_low_voltage_(false) { std::srand(std::time(0)); + AddPolicyObserver(this); } ApplicationManagerImpl::~ApplicationManagerImpl() { @@ -104,17 +121,18 @@ ApplicationManagerImpl::~ApplicationManagerImpl() { media_manager_ = NULL; hmi_handler_ = NULL; connection_handler_ = NULL; - if (hmi_so_factory_) { + if(hmi_so_factory_) { delete hmi_so_factory_; + hmi_so_factory_ = NULL; } - hmi_so_factory_ = NULL; - if (mobile_so_factory_) { + if(mobile_so_factory_) { delete mobile_so_factory_; + mobile_so_factory_ = NULL; } - mobile_so_factory_ = NULL; protocol_handler_ = NULL; media_manager_ = NULL; LOG4CXX_INFO(logger_, "Destroying Policy Handler"); + RemovePolicyObserver(this); policy::PolicyHandler::destroy(); } @@ -129,7 +147,7 @@ bool ApplicationManagerImpl::Stop() { } - // for PASA customer policy backup should happen OnExitAllApp(SUSPEND) + // for PASA customer policy backup should happen :AllApp(SUSPEND) LOG4CXX_INFO(logger_, "Unloading policy library."); policy::PolicyHandler::instance()->UnloadPolicyLibrary(); @@ -137,103 +155,123 @@ bool ApplicationManagerImpl::Stop() { } ApplicationSharedPtr ApplicationManagerImpl::application(uint32_t app_id) const { - sync_primitives::AutoLock lock(applications_list_lock_); - - std::set<ApplicationSharedPtr>::const_iterator it = - application_list_.begin(); - for (; it != application_list_.end(); ++it) { - if ((*it)->app_id() == app_id) { - return (*it); - } - } - return ApplicationSharedPtr(); + AppIdPredicate finder(app_id); + ApplicationListAccessor accessor; + ApplicationSharedPtr app = accessor.Find(finder); + LOG4CXX_DEBUG(logger_, " app_id << " << app_id << "Found = " << app); + return app; } ApplicationSharedPtr ApplicationManagerImpl::application_by_hmi_app( uint32_t hmi_app_id) const { - sync_primitives::AutoLock lock(applications_list_lock_); - - std::set<ApplicationSharedPtr>::const_iterator it = - application_list_.begin(); - for (; it != application_list_.end(); ++it) { - if ((*it)->hmi_app_id() == hmi_app_id) { - return (*it); - } - } - return ApplicationSharedPtr(); + HmiAppIdPredicate finder(hmi_app_id); + ApplicationListAccessor accessor; + ApplicationSharedPtr app = accessor.Find(finder); + LOG4CXX_DEBUG(logger_, " hmi_app_id << " << hmi_app_id << "Found = " << app); + return app; } ApplicationSharedPtr ApplicationManagerImpl::application_by_policy_id( const std::string& policy_app_id) const { - sync_primitives::AutoLock lock(applications_list_lock_); + MobileAppIdPredicate finder(policy_app_id); + ApplicationListAccessor accessor; + ApplicationSharedPtr app = accessor.Find(finder); + LOG4CXX_DEBUG(logger_, " policy_app_id << " << policy_app_id << "Found = " << app); + return app; +} - std::vector<ApplicationSharedPtr> result; - for (std::set<ApplicationSharedPtr>::iterator it = application_list_.begin(); - application_list_.end() != it; - ++it) { - if (policy_app_id.compare((*it)->mobile_app_id()->asString()) == 0) { - return *it; - } - } - return ApplicationSharedPtr(); +bool ActiveAppPredicate (const ApplicationSharedPtr app) { + return app ? app->IsFullscreen() : false; } ApplicationSharedPtr ApplicationManagerImpl::active_application() const { // TODO(DK) : check driver distraction - for (std::set<ApplicationSharedPtr>::iterator it = application_list_.begin(); - application_list_.end() != it; - ++it) { - if ((*it)->IsFullscreen()) { - return *it; - } - } - return ApplicationSharedPtr(); + ApplicationListAccessor accessor; + ApplicationSharedPtr app = accessor.Find(ActiveAppPredicate); + LOG4CXX_DEBUG(logger_, " Found = " << app); + return app; } +bool LimitedAppPredicate (const ApplicationSharedPtr app) { + return app ? app->hmi_level() == mobile_api::HMILevel::HMI_LIMITED : + false; +} ApplicationSharedPtr ApplicationManagerImpl::get_limited_media_application() const { - sync_primitives::AutoLock lock(applications_list_lock_); - - for (TAppListIt it = application_list_.begin(); - application_list_.end() != it; ++it) { - if ((*it)->is_media_application() && - (mobile_api::HMILevel::HMI_LIMITED == (*it)->hmi_level())) { - return *it; - } - } + ApplicationListAccessor accessor; + ApplicationSharedPtr app = accessor.Find(LimitedAppPredicate); + LOG4CXX_DEBUG(logger_, " Found = " << app); + return app; +} - return ApplicationSharedPtr(); +bool LimitedNaviAppPredicate (const ApplicationSharedPtr app) { + return app ? (app->is_navi() && + app->hmi_level() == mobile_api::HMILevel::HMI_LIMITED) : + false; } ApplicationSharedPtr ApplicationManagerImpl::get_limited_navi_application() const { - sync_primitives::AutoLock lock(applications_list_lock_); - - for (TAppListIt it = application_list_.begin(); - application_list_.end() != it; ++it) { - if ((*it)->allowed_support_navigation() && - (mobile_api::HMILevel::HMI_LIMITED == (*it)->hmi_level())) { - return *it; - } - } + ApplicationListAccessor accessor; + ApplicationSharedPtr app = accessor.Find(LimitedNaviAppPredicate); + LOG4CXX_DEBUG(logger_, " Found = " << app); + return app; +} - return ApplicationSharedPtr(); +bool LimitedVoiceAppPredicate (const ApplicationSharedPtr app) { + return app ? (app->is_voice_communication_supported() && + app->hmi_level() == mobile_api::HMILevel::HMI_LIMITED) : + false; } ApplicationSharedPtr ApplicationManagerImpl::get_limited_voice_application() const { - sync_primitives::AutoLock lock(applications_list_lock_); + ApplicationListAccessor accessor; + ApplicationSharedPtr app = accessor.Find(LimitedVoiceAppPredicate); + LOG4CXX_DEBUG(logger_, " Found = " << app); + return app; +} - for (TAppListIt it = application_list_.begin(); - application_list_.end() != it; ++it) { - if ((*it)->is_voice_communication_supported() && - (mobile_api::HMILevel::HMI_LIMITED == (*it)->hmi_level())) { - return *it; - } +bool NaviAppPredicate (const ApplicationSharedPtr app) { + return app ? app->is_navi() : false; +} + +std::vector<ApplicationSharedPtr> ApplicationManagerImpl::applications_with_navi() { + ApplicationListAccessor accessor; + std::vector<ApplicationSharedPtr> apps = accessor.FindAll(NaviAppPredicate); + LOG4CXX_DEBUG(logger_, " Found count: " << apps.size()); + return apps; +} +std::vector<ApplicationSharedPtr> ApplicationManagerImpl::applications_by_button( + uint32_t button) { + SubscribedToButtonPredicate finder( + static_cast<mobile_apis::ButtonName::eType>(button)); + ApplicationListAccessor accessor; + std::vector<ApplicationSharedPtr> apps = accessor.FindAll(finder); + LOG4CXX_DEBUG(logger_, " Found count: " << apps.size()); + return apps; +} + +std::vector<ApplicationSharedPtr> ApplicationManagerImpl::IviInfoUpdated( + VehicleDataType vehicle_info, int value) { + + // Notify Policy Manager if available about info it's interested in, + // i.e. odometer etc + switch (vehicle_info) { + case ODOMETER: + policy::PolicyHandler::instance()->KmsChanged(value); + break; + default: + break; } - return ApplicationSharedPtr(); + SubscribedToIVIPredicate finder( + static_cast<int32_t>(vehicle_info)); + ApplicationListAccessor accessor; + std::vector<ApplicationSharedPtr> apps = accessor.FindAll(NaviAppPredicate); + LOG4CXX_DEBUG(logger_, " vehicle_info << " << vehicle_info << "Found count: " << apps.size()); + return apps; } bool ApplicationManagerImpl::DoesAudioAppWithSameHMITypeExistInFullOrLimited( @@ -288,58 +326,13 @@ bool ApplicationManagerImpl::DoesAudioAppWithSameHMITypeExistInFullOrLimited( return false; } -std::vector<ApplicationSharedPtr> ApplicationManagerImpl::applications_by_button( - uint32_t button) { - std::vector<ApplicationSharedPtr> result; - for (std::set<ApplicationSharedPtr>::iterator it = application_list_.begin(); - application_list_.end() != it; ++it) { - if ((*it)->IsSubscribedToButton( - static_cast<mobile_apis::ButtonName::eType>(button))) { - result.push_back(*it); - } - } - return result; -} - -std::vector<utils::SharedPtr<Application>> ApplicationManagerImpl::IviInfoUpdated( -VehicleDataType vehicle_info, int value) { - // Notify Policy Manager if available about info it's interested in, - // i.e. odometer etc - switch (vehicle_info) { - case ODOMETER: - policy::PolicyHandler::instance()->KmsChanged(value); - break; - default: - break; - } - - std::vector<utils::SharedPtr<application_manager::Application>> result; - for (std::set<utils::SharedPtr<application_manager::Application>>::iterator it = application_list_.begin(); - application_list_.end() != it; ++it) { - if ((*it)->IsSubscribedToIVI(static_cast<uint32_t>(vehicle_info))) { - result.push_back(*it); - } - } - return result; -} - -std::vector<ApplicationSharedPtr> ApplicationManagerImpl::applications_with_navi() { - std::vector<ApplicationSharedPtr> result; - for (std::set<ApplicationSharedPtr>::iterator it = application_list_.begin(); - application_list_.end() != it; - ++it) { - if ((*it)->allowed_support_navigation()) { - result.push_back(*it); - } - } - return result; -} ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( const utils::SharedPtr<smart_objects::SmartObject>& request_for_registration) { LOG4CXX_DEBUG(logger_, "Restarting application list update timer"); + policy::PolicyHandler::instance()->OnAppsSearchStarted(); uint32_t timeout = profile::Profile::instance()->application_list_update_timeout(); application_list_update_timer_->start(timeout); @@ -409,6 +402,7 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( ManageMobileCommand(response); return ApplicationSharedPtr(); } + application->set_device(device_id); application->set_grammar_id(GenerateGrammarID()); mobile_api::Language::eType launguage_desired = @@ -429,35 +423,11 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( int32_t min_version = message[strings::msg_params][strings::sync_msg_version] [strings::minor_version].asInt(); - - /*if (min_version < APIVersion::kAPIV2) { - LOG4CXX_ERROR(logger_, "UNSUPPORTED_VERSION"); - utils::SharedPtr<smart_objects::SmartObject> response( - MessageHelper::CreateNegativeResponse( - connection_key, mobile_apis::FunctionID::RegisterAppInterfaceID, - message[strings::params][strings::correlation_id], - mobile_apis::Result::UNSUPPORTED_VERSION)); - ManageMobileCommand(response); - delete application; - return NULL; - }*/ version.min_supported_api_version = static_cast<APIVersion>(min_version); int32_t max_version = message[strings::msg_params][strings::sync_msg_version] [strings::major_version].asInt(); - - /*if (max_version > APIVersion::kAPIV2) { - LOG4CXX_ERROR(logger_, "UNSUPPORTED_VERSION"); - utils::SharedPtr<smart_objects::SmartObject> response( - MessageHelper::CreateNegativeResponse( - connection_key, mobile_apis::FunctionID::RegisterAppInterfaceID, - message[strings::params][strings::correlation_id], - mobile_apis::Result::UNSUPPORTED_VERSION)); - ManageMobileCommand(response); - delete application; - return NULL; - }*/ version.max_supported_api_version = static_cast<APIVersion>(max_version); application->set_version(version); @@ -470,14 +440,18 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( connection_handler_->BindProtocolVersionWithSession( connection_key, static_cast<uint8_t>(protocol_version)); } - if (ProtocolVersion::kV3 == protocol_version) { + if (protocol_version >= ProtocolVersion::kV3 && + profile::Profile::instance()->heart_beat_timeout() > 0) { connection_handler_->StartSessionHeartBeat(connection_key); } } - sync_primitives::AutoLock lock(applications_list_lock_); - - application_list_.insert(application); + apps_to_register_list_lock_.Acquire(); + apps_to_register_.erase(application); + apps_to_register_list_lock_.Release(); + ApplicationListAccessor app_list_accesor; + application->MarkRegistered(); + app_list_accesor.Insert(application); return application; } @@ -491,6 +465,7 @@ bool ApplicationManagerImpl::LoadAppDataToHMI(ApplicationSharedPtr app) { } bool ApplicationManagerImpl::ActivateApplication(ApplicationSharedPtr app) { + LOG4CXX_AUTO_TRACE(logger_); if (!app) { LOG4CXX_ERROR(logger_, "Null-pointer application received."); NOTREACHED(); @@ -502,57 +477,52 @@ bool ApplicationManagerImpl::ActivateApplication(ApplicationSharedPtr app) { return false; } + using namespace mobile_api::HMILevel; + bool is_new_app_media = app->is_media_application(); ApplicationSharedPtr current_active_app = active_application(); - if (mobile_api::HMILevel::eType::HMI_LIMITED != app->hmi_level()) { + if (HMI_LIMITED != app->hmi_level()) { if (app->has_been_activated()) { MessageHelper::SendAppDataToHMI(app); } } - if (current_active_app.valid()) { + if (current_active_app) { if (is_new_app_media && current_active_app->is_media_application()) { - current_active_app->MakeNotAudible(); - } else if (!(current_active_app->IsAudioApplication())) { - current_active_app->set_hmi_level(mobile_api::HMILevel::HMI_BACKGROUND); + MakeAppNotAudible(current_active_app->app_id()); } else { - current_active_app->set_hmi_level(mobile_api::HMILevel::HMI_LIMITED); + ChangeAppsHMILevel(current_active_app->app_id(), + current_active_app->IsAudioApplication() ? HMI_LIMITED : + HMI_BACKGROUND); } MessageHelper::SendHMIStatusNotification(*current_active_app); } - app->MakeFullscreen(); + MakeAppFullScreen(app->app_id()); if (is_new_app_media) { ApplicationSharedPtr limited_app = get_limited_media_application(); - if (limited_app.valid()) { - limited_app->MakeNotAudible(); - MessageHelper::SendHMIStatusNotification(*limited_app); - } - } - - if (app->is_voice_communication_supported()) { - ApplicationSharedPtr limited_app = get_limited_voice_application(); - if (limited_app.valid()) { - if (limited_app->is_media_application()) { - limited_app->set_audio_streaming_state( - mobile_api::AudioStreamingState::NOT_AUDIBLE); + if (limited_app ) { + if (!limited_app->is_navi()) { + MakeAppNotAudible(limited_app->app_id()); + MessageHelper::SendHMIStatusNotification(*limited_app); + } else { + app->set_audio_streaming_state(mobile_apis::AudioStreamingState::ATTENUATED); + MessageHelper::SendHMIStatusNotification(*app); } - limited_app->set_hmi_level(mobile_api::HMILevel::HMI_BACKGROUND); - MessageHelper::SendHMIStatusNotification(*limited_app); } } - if (app->allowed_support_navigation()) { - ApplicationSharedPtr limited_app = get_limited_navi_application(); + if (app->is_voice_communication_supported() || app->is_navi()) { + ApplicationSharedPtr limited_app = get_limited_voice_application(); if (limited_app.valid()) { if (limited_app->is_media_application()) { limited_app->set_audio_streaming_state( mobile_api::AudioStreamingState::NOT_AUDIBLE); } - limited_app->set_hmi_level(mobile_api::HMILevel::HMI_BACKGROUND); + ChangeAppsHMILevel(app->app_id(), HMI_BACKGROUND); MessageHelper::SendHMIStatusNotification(*limited_app); } } @@ -560,30 +530,33 @@ bool ApplicationManagerImpl::ActivateApplication(ApplicationSharedPtr app) { return true; } -mobile_api::HMILevel::eType ApplicationManagerImpl::PutApplicationInFull( +mobile_api::HMILevel::eType ApplicationManagerImpl::IsHmiLevelFullAllowed( ApplicationSharedPtr app) { - DCHECK(app.get()) - + LOG4CXX_AUTO_TRACE(logger_); + if (!app) { + LOG4CXX_ERROR(logger_, "Application pointer invalid"); + NOTREACHED(); + return mobile_api::HMILevel::INVALID_ENUM; + } bool is_audio_app = app->IsAudioApplication(); bool does_audio_app_with_same_type_exist = DoesAudioAppWithSameHMITypeExistInFullOrLimited(app); + bool is_active_app_exist = active_application().valid(); - mobile_api::HMILevel::eType result = mobile_api::HMILevel::HMI_FULL; - bool is_active_app_exist = active_application().valid(); + mobile_api::HMILevel::eType result = mobile_api::HMILevel::HMI_FULL; if (is_audio_app && does_audio_app_with_same_type_exist) { - result = mobile_apis::HMILevel::HMI_BACKGROUND; + result = GetDefaultHmiLevel(app); } else if (is_active_app_exist && is_audio_app) { result = mobile_apis::HMILevel::HMI_LIMITED; } else if (is_active_app_exist && (!is_audio_app)) { - result = mobile_apis::HMILevel::HMI_BACKGROUND; - } - - if (mobile_api::HMILevel::HMI_FULL == result) { - app->set_hmi_level(result); - MessageHelper::SendActivateAppToHMI(app->app_id()); + result = GetDefaultHmiLevel(app); } + LOG4CXX_ERROR(logger_, "is_audio_app : " << is_audio_app + << "; does_audio_app_with_same_type_exist : " << does_audio_app_with_same_type_exist + << "; is_active_app_exist : " << is_active_app_exist + << "; result : " << result); return result; } @@ -633,6 +606,7 @@ void ApplicationManagerImpl::OnHMIStartedCooperation() { MessageHelper::CreateModuleInfoSO( hmi_apis::FunctionID::BasicCommunication_MixingAudioSupported)); ManageHMICommand(mixing_audio_supported_request); + resume_controller().ResetLaunchTime(); } uint32_t ApplicationManagerImpl::GetNextHMICorrelationID() { @@ -691,50 +665,23 @@ void ApplicationManagerImpl::StartAudioPassThruThread(int32_t session_key, void ApplicationManagerImpl::SendAudioPassThroughNotification( uint32_t session_key, - std::vector<uint8_t> binaryData) { - LOG4CXX_TRACE_ENTER(logger_); + std::vector<uint8_t>& binary_data) { + LOG4CXX_AUTO_TRACE(logger_); if (!audio_pass_thru_active_) { LOG4CXX_ERROR(logger_, "Trying to send PassThroughNotification" " when PassThrough is not active"); return; } - smart_objects::SmartObject* on_audio_pass = NULL; - on_audio_pass = new smart_objects::SmartObject(); - if (NULL == on_audio_pass) { - LOG4CXX_ERROR_EXT(logger_, "OnAudioPassThru NULL pointer"); - - return; - } - - LOG4CXX_INFO_EXT(logger_, "Fill smart object"); - - (*on_audio_pass)[strings::params][strings::message_type] = - application_manager::MessageType::kNotification; - - (*on_audio_pass)[strings::params][strings::connection_key] = - static_cast<int32_t>(session_key); - (*on_audio_pass)[strings::params][strings::function_id] = - mobile_apis::FunctionID::OnAudioPassThruID; - - LOG4CXX_INFO_EXT(logger_, "Fill binary data"); - // binary data - (*on_audio_pass)[strings::params][strings::binary_data] = - smart_objects::SmartObject(binaryData); - - LOG4CXX_INFO_EXT(logger_, "After fill binary data"); - - LOG4CXX_INFO_EXT(logger_, "Send data"); - CommandSharedPtr command ( - MobileCommandFactory::CreateCommand(&(*on_audio_pass))); - command->Init(); - command->Run(); - command->CleanUp(); + impl::AudioData data; + data.session_key = session_key; + data.binary_data = binary_data; + audio_pass_thru_messages_.PostMessage(data); } void ApplicationManagerImpl::StopAudioPassThru(int32_t application_key) { - LOG4CXX_TRACE_ENTER(logger_); + LOG4CXX_AUTO_TRACE(logger_); sync_primitives::AutoLock lock(audio_pass_thru_lock_); if (NULL != media_manager_) { media_manager_->StopMicrophoneRecording(application_key); @@ -761,7 +708,7 @@ std::string ApplicationManagerImpl::GetDeviceName( void ApplicationManagerImpl::OnMessageReceived( const ::protocol_handler::RawMessagePtr message) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::OnMessageReceived"); + LOG4CXX_AUTO_TRACE(logger_); if (!message) { LOG4CXX_ERROR(logger_, "Null-pointer message received."); @@ -779,12 +726,12 @@ void ApplicationManagerImpl::OnMessageReceived( void ApplicationManagerImpl::OnMobileMessageSent( const ::protocol_handler::RawMessagePtr message) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::OnMobileMessageSent"); + LOG4CXX_AUTO_TRACE(logger_); } void ApplicationManagerImpl::OnMessageReceived( hmi_message_handler::MessageSharedPointer message) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::OnMessageReceived"); + LOG4CXX_AUTO_TRACE(logger_); if (!message) { LOG4CXX_ERROR(logger_, "Null-pointer message received."); @@ -802,9 +749,15 @@ void ApplicationManagerImpl::OnErrorSending( void ApplicationManagerImpl::OnDeviceListUpdated( const connection_handler::DeviceMap& device_list) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::OnDeviceListUpdated"); + LOG4CXX_AUTO_TRACE(logger_); + smart_objects::SmartObjectSPtr msg_params = MessageHelper::CreateDeviceListSO( + device_list); + if (!msg_params) { + LOG4CXX_WARN(logger_, "Failed to create sub-smart object."); + return; + } - smart_objects::SmartObject* update_list = new smart_objects::SmartObject; + smart_objects::SmartObjectSPtr update_list = new smart_objects::SmartObject; smart_objects::SmartObject& so_to_send = *update_list; so_to_send[jhs::S_PARAMS][jhs::S_FUNCTION_ID] = hmi_apis::FunctionID::BasicCommunication_UpdateDeviceList; @@ -813,13 +766,6 @@ void ApplicationManagerImpl::OnDeviceListUpdated( so_to_send[jhs::S_PARAMS][jhs::S_PROTOCOL_VERSION] = 3; so_to_send[jhs::S_PARAMS][jhs::S_PROTOCOL_TYPE] = 1; so_to_send[jhs::S_PARAMS][jhs::S_CORRELATION_ID] = GetNextHMICorrelationID(); - smart_objects::SmartObject* msg_params = MessageHelper::CreateDeviceListSO( - device_list); - if (!msg_params) { - LOG4CXX_WARN(logger_, "Failed to create sub-smart object."); - delete update_list; - return; - } so_to_send[jhs::S_MSG_PARAMS] = *msg_params; ManageHMICommand(update_list); } @@ -829,41 +775,25 @@ void ApplicationManagerImpl::OnFindNewApplicationsRequest() { LOG4CXX_DEBUG(logger_, "Starting application list update timer"); uint32_t timeout = profile::Profile::instance()->application_list_update_timeout(); application_list_update_timer_->start(timeout); + policy::PolicyHandler::instance()->OnAppsSearchStarted(); } -void ApplicationManagerImpl::SendUpdateAppList(const std::list<uint32_t>& applications_ids) { - LOG4CXX_TRACE(logger_, "SendUpdateAppList"); +void ApplicationManagerImpl::SendUpdateAppList() { + LOG4CXX_AUTO_TRACE(logger_); - LOG4CXX_DEBUG(logger_, applications_ids.size() << " applications."); + using namespace smart_objects; + using namespace hmi_apis; - smart_objects::SmartObject* request = MessageHelper::CreateModuleInfoSO( - hmi_apis::FunctionID::BasicCommunication_UpdateAppList); - (*request)[strings::msg_params][strings::applications] = - smart_objects::SmartObject(smart_objects::SmartType_Array); + SmartObjectSPtr request = MessageHelper::CreateModuleInfoSO( + FunctionID::BasicCommunication_UpdateAppList); - smart_objects::SmartObject& applications = - (*request)[strings::msg_params][strings::applications]; + (*request)[strings::msg_params][strings::applications] = SmartObject(SmartType_Array); - uint32_t app_count = 0; - for (std::list<uint32_t>::const_iterator it = applications_ids.begin(); - it != applications_ids.end(); ++it) { - ApplicationSharedPtr app = application(*it); + SmartObject& applications = (*request)[strings::msg_params][strings::applications]; - if (!app.valid()) { - LOG4CXX_ERROR(logger_, "Application not found , id = " << *it); - continue; - } + PrepareApplicationListSO(applications_, applications); + PrepareApplicationListSO(apps_to_register_, applications); - smart_objects::SmartObject hmi_application(smart_objects::SmartType_Map);; - if (!MessageHelper::CreateHMIApplicationStruct(app, hmi_application)) { - LOG4CXX_ERROR(logger_, "Can't CreateHMIApplicationStruct ', id = " << *it); - continue; - } - applications[app_count++] = hmi_application; - } - if (app_count <= 0) { - LOG4CXX_WARN(logger_, "Empty applications list"); - } ManageHMICommand(request); } @@ -875,37 +805,59 @@ void ApplicationManagerImpl::RemoveDevice( bool ApplicationManagerImpl::IsAudioStreamingAllowed(uint32_t application_key) const { ApplicationSharedPtr app = application(application_key); + using namespace mobile_apis::HMILevel; + using namespace helpers; if (!app) { LOG4CXX_WARN(logger_, "An application is not registered."); return false; } - const mobile_api::HMILevel::eType& hmi_level = app->hmi_level(); - - if (mobile_api::HMILevel::HMI_FULL == hmi_level || - mobile_api::HMILevel::HMI_LIMITED == hmi_level) { - return true; - } - - return false; + return Compare<eType, EQ, ONE>( + app->hmi_level(), HMI_FULL, HMI_LIMITED); } bool ApplicationManagerImpl::IsVideoStreamingAllowed(uint32_t application_key) const { ApplicationSharedPtr app = application(application_key); + using namespace mobile_apis::HMILevel; + using namespace helpers; if (!app) { LOG4CXX_WARN(logger_, "An application is not registered."); return false; } - const mobile_api::HMILevel::eType& hmi_level = app->hmi_level(); + LOG4CXX_DEBUG(logger_, "HMILevel: " << app->hmi_level()); + return Compare<eType, EQ, ONE>(app->hmi_level(), HMI_FULL, HMI_LIMITED); +} - if (mobile_api::HMILevel::HMI_FULL == hmi_level && - app->hmi_supports_navi_video_streaming()) { - return true; - } +mobile_apis::HMILevel::eType ApplicationManagerImpl::GetDefaultHmiLevel( + ApplicationSharedPtr application) const { + using namespace mobile_apis; + LOG4CXX_AUTO_TRACE(logger_); + HMILevel::eType default_hmi = HMILevel::HMI_NONE; - return false; + if (policy::PolicyHandler::instance()->PolicyEnabled()) { + const std::string policy_app_id = application->mobile_app_id(); + std::string default_hmi_string = ""; + if (policy::PolicyHandler::instance()->GetDefaultHmi( + policy_app_id, &default_hmi_string)) { + if ("BACKGROUND" == default_hmi_string) { + default_hmi = HMILevel::HMI_BACKGROUND; + } else if ("FULL" == default_hmi_string) { + default_hmi = HMILevel::HMI_FULL; + } else if ("LIMITED" == default_hmi_string) { + default_hmi = HMILevel::HMI_LIMITED; + } else if ("NONE" == default_hmi_string) { + default_hmi = HMILevel::HMI_NONE; + } else { + LOG4CXX_ERROR(logger_, "Unable to convert " + default_hmi_string + " to HMILevel"); + } + } else { + LOG4CXX_ERROR(logger_, "Unable to get default hmi_level for " + << policy_app_id); + } + } + return default_hmi; } uint32_t ApplicationManagerImpl::GenerateGrammarID() { @@ -913,19 +865,23 @@ uint32_t ApplicationManagerImpl::GenerateGrammarID() { } uint32_t ApplicationManagerImpl::GenerateNewHMIAppID() { - uint32_t hmi_app_id = rand(); + LOG4CXX_TRACE(logger_, "ENTER"); + uint32_t hmi_app_id = get_rand_from_range(1); + LOG4CXX_DEBUG(logger_, "GenerateNewHMIAppID value is: " << hmi_app_id); while (resume_ctrl_.IsHMIApplicationIdExist(hmi_app_id)) { - hmi_app_id = rand(); + LOG4CXX_DEBUG(logger_, "HMI appID " << hmi_app_id << " is exists."); + hmi_app_id = get_rand_from_range(1); + LOG4CXX_DEBUG(logger_, "Trying new value: " << hmi_app_id); } + LOG4CXX_TRACE(logger_, "EXIT"); return hmi_app_id; } void ApplicationManagerImpl::ReplaceMobileByHMIAppId( smart_objects::SmartObject& message) { MessageHelper::PrintSmartObject(message); - flush(std::cout); if (message.keyExists(strings::app_id)) { ApplicationSharedPtr application = ApplicationManagerImpl::instance()->application( @@ -998,96 +954,133 @@ void ApplicationManagerImpl::ReplaceHMIByMobileAppId( } } -bool ApplicationManagerImpl::OnServiceStartedCallback( - const connection_handler::DeviceHandle& device_handle, - const int32_t& session_key, - const protocol_handler::ServiceType& type) { - LOG4CXX_INFO(logger_, - "OnServiceStartedCallback " << type << " in session " << session_key); - ApplicationSharedPtr app = application(session_key); +bool ApplicationManagerImpl::ProcessNaviService(protocol_handler::ServiceType type, + uint32_t connection_key) { + LOG4CXX_AUTO_TRACE(logger_); + + if (!media_manager_) { + LOG4CXX_DEBUG(logger_, "The media manager is not initialized."); + return false; + } + bool result = false; switch (type) { - case protocol_handler::kRpc: { - LOG4CXX_INFO(logger_, "RPC service is about to be started."); - break; - } - case protocol_handler::kMobileNav: { - LOG4CXX_INFO(logger_, "Video service is about to be started."); - if (media_manager_) { - if (!app) { - LOG4CXX_ERROR_EXT(logger_, "An application is not registered."); - return false; - } - if (app->allowed_support_navigation()) { - media_manager_->StartVideoStreaming(session_key); - } else { - return false; - } + case protocol_handler::kMobileNav: + LOG4CXX_DEBUG(logger_, "Video service is about to be started."); + if (IsVideoStreamingAllowed(connection_key)) { + media_manager_->StartVideoStreaming(connection_key); + result = true; } break; - } - case protocol_handler::kAudio: { - LOG4CXX_INFO(logger_, "Audio service is about to be started."); - if (media_manager_) { - if (!app) { - LOG4CXX_ERROR_EXT(logger_, "An application is not registered."); - return false; - } - if (app->allowed_support_navigation()) { - media_manager_->StartAudioStreaming(session_key); - } else { - return false; - } + case protocol_handler::kAudio: + LOG4CXX_DEBUG(logger_, "Audio service is about to be started."); + if (IsAudioStreamingAllowed(connection_key)) { + media_manager_->StartAudioStreaming(connection_key); + result = true; } break; - } - default: { - LOG4CXX_WARN(logger_, "Unknown type of service to be started."); + default: + LOG4CXX_DEBUG(logger_, "Unknown type of service to be started."); break; - } } - return true; + service_status_[type] = std::make_pair(result, false); + return result; +} + +bool ApplicationManagerImpl::OnServiceStartedCallback( + const connection_handler::DeviceHandle& device_handle, + const int32_t& session_key, + const protocol_handler::ServiceType& type) { + using namespace protocol_handler; + using namespace helpers; + + LOG4CXX_INFO(logger_, + "OnServiceStartedCallback " << type << " in session " << session_key); + if (type == kRpc) { + LOG4CXX_INFO(logger_, "RPC service is about to be started."); + return true; + } + ApplicationSharedPtr app = application(session_key); + if (!app) { + LOG4CXX_DEBUG(logger_, "The application with id:" << session_key << + " doesn't exists."); + return false; + } + bool result = false; + if (Compare<ServiceType, EQ, ONE>(type, kMobileNav, kAudio)) { + if (app->is_navi()) { + result = ProcessNaviService(type, session_key); + app->set_streaming_allowed(result); + } + } + return result; } void ApplicationManagerImpl::OnServiceEndedCallback(const int32_t& session_key, const protocol_handler::ServiceType& type) { + using namespace protocol_handler; LOG4CXX_INFO_EXT( logger_, "OnServiceEndedCallback " << type << " in session " << session_key); - switch (type) { - case protocol_handler::kRpc: { - LOG4CXX_INFO(logger_, "Remove application."); - /* in case it was unexpected disconnect application will be removed - and we will notify HMI that it was unexpected disconnect, - but in case it was closed by mobile we will be unable to find it in the list - */ - UnregisterApplication(session_key, mobile_apis::Result::INVALID_ENUM, - true, true); - break; - } - case protocol_handler::kMobileNav: { - LOG4CXX_INFO(logger_, "Stop video streaming."); - if (media_manager_) { + if (type == kRpc) { + LOG4CXX_INFO(logger_, "Remove application."); + /* in case it was unexpected disconnect application will be removed + and we will notify HMI that it was unexpected disconnect, + but in case it was closed by mobile we will be unable to find it in the list + */ + UnregisterApplication(session_key, mobile_apis::Result::INVALID_ENUM, + true, true); + return; + } + + if (media_manager_) { + switch (type) { + case protocol_handler::kMobileNav: { + LOG4CXX_INFO(logger_, "Stop video streaming."); media_manager_->StopVideoStreaming(session_key); + break; } - break; - } - case protocol_handler::kAudio: { - LOG4CXX_INFO(logger_, "Stop audio service."); - if (media_manager_) { + case protocol_handler::kAudio: { + LOG4CXX_INFO(logger_, "Stop audio service."); media_manager_->StopAudioStreaming(session_key); + break; } - break; + default: + LOG4CXX_WARN(logger_, "Unknown type of service to be ended." << type); + break; } - default: - LOG4CXX_WARN(logger_, "Unknown type of service to be ended." << - type); - break; + service_status_[type].second = true; + LOG4CXX_DEBUG(logger_, "Ack status: " << service_status_[type].first <<" : " + << service_status_[type].second); } } +void ApplicationManagerImpl::OnApplicationFloodCallBack(const uint32_t &connection_key) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Unregister flooding application " << connection_key); + + MessageHelper::SendOnAppInterfaceUnregisteredNotificationToMobile( + connection_key, + mobile_apis::AppInterfaceUnregisteredReason::TOO_MANY_REQUESTS); + + const bool resuming = true; + const bool unexpected_disconnect = false; + UnregisterApplication(connection_key, mobile_apis::Result::TOO_MANY_PENDING_REQUESTS, + resuming, unexpected_disconnect); + // TODO(EZamakhov): increment "removals_for_bad_behaviour" field in policy table +} + +void ApplicationManagerImpl::OnMalformedMessageCallback(const uint32_t &connection_key) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Unregister malformed messaging application " << connection_key); + + MessageHelper::SendOnAppInterfaceUnregisteredNotificationToMobile( + connection_key, + mobile_apis::AppInterfaceUnregisteredReason::PROTOCOL_VIOLATION); +} + void ApplicationManagerImpl::set_hmi_message_handler( hmi_message_handler::HMIMessageHandler* handler) { hmi_handler_ = handler; @@ -1113,9 +1106,8 @@ void ApplicationManagerImpl::StartDevicesDiscovery() { } void ApplicationManagerImpl::SendMessageToMobile( - const utils::SharedPtr<smart_objects::SmartObject> message, - bool final_message) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::SendMessageToMobile"); + const commands::MessageSharedPtr message, bool final_message) { + LOG4CXX_AUTO_TRACE(logger_); if (!message) { LOG4CXX_ERROR(logger_, "Null-pointer message received."); @@ -1141,7 +1133,7 @@ void ApplicationManagerImpl::SendMessageToMobile( ProtocolVersion::kV1; } else { (*message)[strings::params][strings::protocol_version] = - ProtocolVersion::kV3; + SupportedSDLVersion(); } } else { (*message)[strings::params][strings::protocol_version] = @@ -1166,7 +1158,8 @@ void ApplicationManagerImpl::SendMessageToMobile( // checked against policy permissions if (msg_to_mobile[strings::params].keyExists(strings::correlation_id)) { request_ctrl_.terminateMobileRequest( - msg_to_mobile[strings::params][strings::correlation_id].asInt()); + msg_to_mobile[strings::params][strings::correlation_id].asInt(), + msg_to_mobile[strings::params][strings::connection_key].asInt()); } else if (app) { mobile_apis::FunctionID::eType function_id = static_cast<mobile_apis::FunctionID::eType>( @@ -1179,11 +1172,14 @@ void ApplicationManagerImpl::SendMessageToMobile( smart_objects::SmartMap::iterator iter_end = s_map.map_end(); for (; iter != iter_end; ++iter) { - params.push_back(iter->first); + if (true == iter->second.asBool()) { + LOG4CXX_INFO(logger_, "Request's param: " << iter->first); + params.push_back(iter->first); + } } } const mobile_apis::Result::eType check_result = - CheckPolicyPermissions( app->mobile_app_id()->asString(), + CheckPolicyPermissions( app->mobile_app_id(), app->hmi_level(), function_id, params); if (mobile_apis::Result::SUCCESS != check_result) { const std::string string_functionID = @@ -1194,7 +1190,13 @@ void ApplicationManagerImpl::SendMessageToMobile( } if (function_id == mobile_apis::FunctionID::OnSystemRequestID) { - policy::PolicyHandler::instance()->OnUpdateRequestSentToMobile(); + mobile_apis::RequestType::eType request_type = + static_cast<mobile_apis::RequestType::eType>( + (*message)[strings::msg_params][strings::request_type].asUInt()); + if (mobile_apis::RequestType::PROPRIETARY == request_type || + mobile_apis::RequestType::HTTP == request_type) { + policy::PolicyHandler::instance()->OnUpdateRequestSentToMobile(); + } } } @@ -1203,21 +1205,26 @@ void ApplicationManagerImpl::SendMessageToMobile( } bool ApplicationManagerImpl::ManageMobileCommand( - const utils::SharedPtr<smart_objects::SmartObject> message) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::ManageMobileCommand"); + const commands::MessageSharedPtr message, + commands::Command::CommandOrigin origin) { + LOG4CXX_AUTO_TRACE(logger_); if (!message) { LOG4CXX_WARN(logger_, "RET Null-pointer message received."); - NOTREACHED() return false; } + if (IsLowVoltage()) { + LOG4CXX_WARN(logger_, "Low Voltage is active"); + return false; + } #ifdef DEBUG MessageHelper::PrintSmartObject(*message); #endif LOG4CXX_INFO(logger_, "Trying to create message in mobile factory."); - commands::Command* command = MobileCommandFactory::CreateCommand(message); + utils::SharedPtr<commands::Command> command( + MobileCommandFactory::CreateCommand(message, origin)); if (!command) { LOG4CXX_WARN(logger_, "RET Failed to create mobile command from smart object"); @@ -1249,12 +1256,11 @@ bool ApplicationManagerImpl::ManageMobileCommand( app = ApplicationManagerImpl::instance()->application(connection_key); if (!app) { LOG4CXX_ERROR_EXT(logger_, "RET APPLICATION_NOT_REGISTERED"); - smart_objects::SmartObject* response = - MessageHelper::CreateNegativeResponse( - connection_key, - static_cast<int32_t>(function_id), - correlation_id, - static_cast<int32_t>(mobile_apis::Result::APPLICATION_NOT_REGISTERED)); + smart_objects::SmartObjectSPtr response = + MessageHelper::CreateNegativeResponse(connection_key, + static_cast<int32_t>(function_id), + correlation_id, + static_cast<int32_t>(mobile_apis::Result::APPLICATION_NOT_REGISTERED)); SendMessageToMobile(response); return false; @@ -1270,18 +1276,15 @@ bool ApplicationManagerImpl::ManageMobileCommand( command->Run(); command->CleanUp(); } - delete command; return true; } if (message_type == mobile_apis::messageType::notification) { - commands::CommandNotificationImpl* command_notify = - static_cast<commands::CommandNotificationImpl*>(command); - request_ctrl_.addNotification(command_notify); - if (command_notify->Init()) { - command_notify->Run(); - if (command_notify->CleanUp()) { - request_ctrl_.removeNotification(command_notify); + request_ctrl_.addNotification(command); + if (command->Init()) { + command->Run(); + if (command->CleanUp()) { + request_ctrl_.removeNotification(command.get()); } // If CleanUp returned false notification should remove it self. } @@ -1291,8 +1294,6 @@ bool ApplicationManagerImpl::ManageMobileCommand( if (message_type == mobile_apis::messageType::request) { - commands::CommandRequestImpl* command_request = - static_cast<commands::CommandRequestImpl*>(command); // commands will be launched from requesr_ctrl mobile_apis::HMILevel::eType app_hmi_level = mobile_apis::HMILevel::INVALID_ENUM; if (app) { @@ -1301,8 +1302,8 @@ bool ApplicationManagerImpl::ManageMobileCommand( // commands will be launched from request_ctrl - request_controller::RequestController::TResult result = - request_ctrl_.addMobileRequest(command_request, app_hmi_level); + const request_controller::RequestController::TResult result = + request_ctrl_.addMobileRequest(command, app_hmi_level); if (result == request_controller::RequestController::SUCCESS) { LOG4CXX_INFO(logger_, "Perform request"); @@ -1312,12 +1313,11 @@ bool ApplicationManagerImpl::ManageMobileCommand( LOG4CXX_ERROR_EXT(logger_, "RET Unable top perform request: " << "TOO_MANY_PENDING_REQUESTS"); - smart_objects::SmartObject* response = - MessageHelper::CreateNegativeResponse( - connection_key, - static_cast<int32_t>(function_id), - correlation_id, - static_cast<int32_t>(mobile_apis::Result::TOO_MANY_PENDING_REQUESTS)); + smart_objects::SmartObjectSPtr response = + MessageHelper::CreateNegativeResponse(connection_key, + static_cast<int32_t>(function_id), + correlation_id, + static_cast<int32_t>(mobile_apis::Result::TOO_MANY_PENDING_REQUESTS)); SendMessageToMobile(response); return false; @@ -1344,7 +1344,10 @@ bool ApplicationManagerImpl::ManageMobileCommand( connection_key, mobile_api::AppInterfaceUnregisteredReason:: REQUEST_WHILE_IN_NONE_HMI_LEVEL); - application(connection_key)->usage_report().RecordRemovalsForBadBehavior(); + ApplicationSharedPtr app_ptr = application(connection_key); + if(app_ptr) { + app_ptr->usage_report().RecordRemovalsForBadBehavior(); + } UnregisterApplication(connection_key, mobile_apis::Result::INVALID_ENUM, false); return false; @@ -1360,8 +1363,8 @@ bool ApplicationManagerImpl::ManageMobileCommand( } void ApplicationManagerImpl::SendMessageToHMI( - const utils::SharedPtr<smart_objects::SmartObject> message) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::SendMessageToHMI"); + const commands::MessageSharedPtr message) { + LOG4CXX_AUTO_TRACE(logger_); if (!message) { LOG4CXX_WARN(logger_, "Null-pointer message received."); @@ -1387,7 +1390,6 @@ void ApplicationManagerImpl::SendMessageToHMI( logger_, "Attached schema to message, result if valid: " << message->isValid()); - #ifdef HMI_DBUS_API message_to_send->set_smart_object(*message); #else @@ -1402,15 +1404,18 @@ void ApplicationManagerImpl::SendMessageToHMI( } bool ApplicationManagerImpl::ManageHMICommand( - const utils::SharedPtr<smart_objects::SmartObject> message) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::ManageHMICommand"); + const commands::MessageSharedPtr message) { + LOG4CXX_AUTO_TRACE(logger_); if (!message) { LOG4CXX_WARN(logger_, "Null-pointer message received."); - NOTREACHED(); return false; } + if (IsLowVoltage()) { + LOG4CXX_WARN(logger_, "Low Voltage is active"); + return false; + } MessageHelper::PrintSmartObject(*message); @@ -1440,19 +1445,6 @@ bool ApplicationManagerImpl::ManageHMICommand( bool ApplicationManagerImpl::Init() { LOG4CXX_TRACE(logger_, "Init application manager"); - if (policy::PolicyHandler::instance()->PolicyEnabled()) { - if(!policy::PolicyHandler::instance()->LoadPolicyLibrary()) { - LOG4CXX_ERROR(logger_, "Policy library is not loaded. Check LD_LIBRARY_PATH"); - return false; - } - LOG4CXX_INFO(logger_, "Policy library is loaded, now initing PT"); - if (!policy::PolicyHandler::instance()->InitPolicyTable()) { - LOG4CXX_ERROR(logger_, "Policy table is not initialized."); - return false; - } - } else { - LOG4CXX_WARN(logger_, "System is configured to work without policy functionality."); - } const std::string app_storage_folder = profile::Profile::instance()->app_storage_folder(); if (!file_system::DirectoryExists(app_storage_folder)) { @@ -1488,6 +1480,19 @@ bool ApplicationManagerImpl::Init() { "System directory doesn't have read/write permissions"); return false; } + if (policy::PolicyHandler::instance()->PolicyEnabled()) { + if(!policy::PolicyHandler::instance()->LoadPolicyLibrary()) { + LOG4CXX_ERROR(logger_, "Policy library is not loaded. Check LD_LIBRARY_PATH"); + return false; + } + LOG4CXX_INFO(logger_, "Policy library is loaded, now initing PT"); + if (!policy::PolicyHandler::instance()->InitPolicyTable()) { + LOG4CXX_ERROR(logger_, "Policy table is not initialized."); + return false; + } + } else { + LOG4CXX_WARN(logger_, "System is configured to work without policy functionality."); + } media_manager_ = media_manager::MediaManagerImpl::instance(); return true; } @@ -1500,6 +1505,7 @@ bool ApplicationManagerImpl::ConvertMessageToSO( << "; json " << message.json_message()); switch (message.protocol_version()) { + case ProtocolVersion::kV4: case ProtocolVersion::kV3: case ProtocolVersion::kV2: { const bool conversion_result = @@ -1559,7 +1565,20 @@ bool ApplicationManagerImpl::ConvertMessageToSO( return false; } if (output.validate() != smart_objects::Errors::OK) { - LOG4CXX_WARN(logger_, "Incorrect parameter from HMI"); + LOG4CXX_ERROR(logger_, "Incorrect parameter from HMI"); + + if (application_manager::MessageType::kNotification == + output[strings::params][strings::message_type].asInt()) { + LOG4CXX_ERROR(logger_, "Ignore wrong HMI notification"); + return false; + } + + if (application_manager::MessageType::kRequest == + output[strings::params][strings::message_type].asInt()) { + LOG4CXX_ERROR(logger_, "Ignore wrong HMI request"); + return false; + } + output.erase(strings::msg_params); output[strings::params][hmi_response::code] = hmi_apis::Common_Result::INVALID_DATA; @@ -1595,7 +1614,7 @@ bool ApplicationManagerImpl::ConvertMessageToSO( output[strings::msg_params][strings::result_code] = NsSmartDeviceLinkRPC::V1::Result::UNSUPPORTED_VERSION; - smart_objects::SmartObject* msg_to_send = new smart_objects::SmartObject(output); + smart_objects::SmartObjectSPtr msg_to_send = new smart_objects::SmartObject(output); v1_shema.attachSchema(*msg_to_send); SendMessageToMobile(msg_to_send); return false; @@ -1728,18 +1747,7 @@ utils::SharedPtr<Message> ApplicationManagerImpl::ConvertRawMsgToMessage( return outgoing_message; } - Message* convertion_result = NULL; - if (message->protocol_version() == 1) { - convertion_result = - MobileMessageHandler::HandleIncomingMessageProtocolV1(message); - } else if ((message->protocol_version() == 2) || - (message->protocol_version() == 3)) { - convertion_result = - MobileMessageHandler::HandleIncomingMessageProtocolV2(message); - } else { - LOG4CXX_WARN(logger_, "Unknown protocol version."); - return outgoing_message; - } + Message* convertion_result = MobileMessageHandler::HandleIncomingMessageProtocol(message); if (convertion_result) { outgoing_message = convertion_result; @@ -1756,8 +1764,7 @@ void ApplicationManagerImpl::ProcessMessageFromMobile( AMMetricObserver::MessageMetricSharedPtr metric(new AMMetricObserver::MessageMetric()); metric->begin = date_time::DateTime::getCurrentTime(); #endif // TIME_TESTER - utils::SharedPtr<smart_objects::SmartObject> so_from_mobile( - new smart_objects::SmartObject); + smart_objects::SmartObjectSPtr so_from_mobile(new smart_objects::SmartObject); if (!so_from_mobile) { LOG4CXX_ERROR(logger_, "Null pointer"); @@ -1772,7 +1779,8 @@ void ApplicationManagerImpl::ProcessMessageFromMobile( metric->message = so_from_mobile; #endif // TIME_TESTER - if (!ManageMobileCommand(so_from_mobile)) { + if (!ManageMobileCommand(so_from_mobile, + commands::Command::ORIGIN_MOBILE)) { LOG4CXX_ERROR(logger_, "Received command didn't run successfully"); } #ifdef TIME_TESTER @@ -1786,8 +1794,7 @@ void ApplicationManagerImpl::ProcessMessageFromMobile( void ApplicationManagerImpl::ProcessMessageFromHMI( const utils::SharedPtr<Message> message) { LOG4CXX_INFO(logger_, "ApplicationManagerImpl::ProcessMessageFromHMI()"); - utils::SharedPtr<smart_objects::SmartObject> smart_object( - new smart_objects::SmartObject); + smart_objects::SmartObjectSPtr smart_object(new smart_objects::SmartObject); if (!smart_object) { LOG4CXX_ERROR(logger_, "Null pointer"); @@ -1835,6 +1842,63 @@ HMICapabilities& ApplicationManagerImpl::hmi_capabilities() { return hmi_capabilities_; } +void ApplicationManagerImpl::CreateApplications(SmartArray& obj_array) { + + using namespace policy; + + const std::size_t arr_size(obj_array.size()); + for (std::size_t idx = 0; idx < arr_size; ++idx) { + + const SmartObject& app_data = obj_array[idx]; + if (app_data.isValid()) { + const std::string url_schema(app_data[strings::urlSchema].asString()); + const std::string package_name(app_data[strings::packageName].asString()); + const std::string mobile_app_id(app_data[strings::app_id].asString()); + const std::string appName(app_data[strings::app_name].asString()); + + const uint32_t hmi_app_id(GenerateNewHMIAppID()); + + ApplicationSharedPtr app( + new ApplicationImpl(0, + mobile_app_id, + appName, + PolicyHandler::instance()->GetStatisticManager())); + if (app) { + app->SetShemaUrl(url_schema); + app->SetPackageName(package_name); + app->set_hmi_application_id(hmi_app_id); + + sync_primitives::AutoLock lock(apps_to_register_list_lock_); + apps_to_register_.insert(app); + } + } + } +} + +void ApplicationManagerImpl::ProcessQueryApp( + const smart_objects::SmartObject& sm_object) { + using namespace policy; + using namespace profile; + + if (sm_object.keyExists(strings::application)) { + SmartArray* obj_array = sm_object[strings::application].asArray(); + if (NULL != obj_array) { + const std::string app_icon_dir(Profile::instance()->app_icons_folder()); + CreateApplications(*obj_array); + SendUpdateAppList(); + + AppsWaitRegistrationSet::const_iterator it = apps_to_register_.begin(); + for (; it != apps_to_register_.end(); ++it) { + + const std::string full_icon_path(app_icon_dir + "/" + (*it)->mobile_app_id()); + if (file_system::FileExists(full_icon_path)) { + MessageHelper::SendSetAppIcon((*it)->hmi_app_id(), full_icon_path); + } + } + } + } +} + #ifdef TIME_TESTER void ApplicationManagerImpl::SetTimeMetricObserver(AMMetricObserver* observer) { metric_observer_ = observer; @@ -1852,6 +1916,7 @@ void ApplicationManagerImpl::removeNotification(const commands::Command* notific void ApplicationManagerImpl::updateRequestTimeout(uint32_t connection_key, uint32_t mobile_correlation_id, uint32_t new_timeout_value) { + LOG4CXX_AUTO_TRACE(logger_); request_ctrl_.updateRequestTimeout(connection_key, mobile_correlation_id, new_timeout_value); } @@ -1876,8 +1941,17 @@ void ApplicationManagerImpl::set_application_id(const int32_t correlation_id, (correlation_id, app_id)); } +void ApplicationManagerImpl::AddPolicyObserver( policy::PolicyHandlerObserver* listener) { + policy::PolicyHandler::instance()->add_listener(listener); +} + +void ApplicationManagerImpl::RemovePolicyObserver(policy::PolicyHandlerObserver* listener) { + policy::PolicyHandler::instance()->remove_listener(listener); +} + void ApplicationManagerImpl::SetUnregisterAllApplicationsReason( mobile_api::AppInterfaceUnregisteredReason::eType reason) { + LOG4CXX_TRACE(logger_, "reason = " << reason); unregister_reason_ = reason; } @@ -1885,9 +1959,12 @@ void ApplicationManagerImpl::HeadUnitReset( mobile_api::AppInterfaceUnregisteredReason::eType reason) { switch (reason) { case mobile_api::AppInterfaceUnregisteredReason::MASTER_RESET: { - file_system::remove_directory_content(profile::Profile::instance()->app_storage_folder()); - resume_controller().ClearResumptionInfo(); + UnregisterAllApplications(); policy::PolicyHandler::instance()->ResetPolicyTable(); + policy::PolicyHandler::instance()->UnloadPolicyLibrary(); + + resume_controller().StopSavePersistentDataTimer(); + file_system::remove_directory_content(profile::Profile::instance()->app_storage_folder()); break; } case mobile_api::AppInterfaceUnregisteredReason::FACTORY_DEFAULTS: { @@ -1901,15 +1978,12 @@ void ApplicationManagerImpl::HeadUnitReset( } } -void ApplicationManagerImpl::HeadUnitSuspend() { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::HeadUnitSuspend"); -} void ApplicationManagerImpl::SendOnSDLClose() { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::SendOnSDLClose"); + LOG4CXX_AUTO_TRACE(logger_); // must be sent to PASA HMI on shutdown synchronously - smart_objects::SmartObject* msg = new smart_objects::SmartObject( + smart_objects::SmartObjectSPtr msg = new smart_objects::SmartObject( smart_objects::SmartType_Map); (*msg)[strings::params][strings::function_id] = @@ -1952,39 +2026,38 @@ void ApplicationManagerImpl::SendOnSDLClose() { return; } - delete msg; hmi_handler_->SendMessageToHMI(message_to_send); } -void ApplicationManagerImpl::UnregisterAllApplications(bool generated_by_hmi) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::UnregisterAllApplications " << - unregister_reason_); - hmi_cooperating_ = false; - - bool is_ignition_off = - unregister_reason_ == - mobile_api::AppInterfaceUnregisteredReason::IGNITION_OFF ? true : false; - - bool is_unexpected_disconnect = (generated_by_hmi != true); - - sync_primitives::AutoLock lock(applications_list_lock_); +void ApplicationManagerImpl::UnregisterAllApplications() { + LOG4CXX_DEBUG(logger_, "Unregister reason " << unregister_reason_); - std::set<ApplicationSharedPtr>::iterator it = application_list_.begin(); - while (it != application_list_.end()) { + hmi_cooperating_ = false; + bool is_ignition_off = false; + using namespace mobile_api::AppInterfaceUnregisteredReason; + using namespace helpers; + + is_ignition_off = + Compare<eType, EQ, ONE>(unregister_reason_, IGNITION_OFF, INVALID_ENUM); + + bool is_unexpected_disconnect = + Compare<eType, NEQ, ALL>(unregister_reason_, + IGNITION_OFF, MASTER_RESET, FACTORY_DEFAULTS); + ApplicationListAccessor accessor; + ApplictionSetConstIt it = accessor.begin(); + while (it != accessor.end()) { ApplicationSharedPtr app_to_remove = *it; - MessageHelper::SendOnAppInterfaceUnregisteredNotificationToMobile( - app_to_remove->app_id(), unregister_reason_); + UnregisterApplication(app_to_remove->app_id(), mobile_apis::Result::INVALID_ENUM, is_ignition_off, is_unexpected_disconnect); - - connection_handler_->CloseSession(app_to_remove->app_id()); - it = application_list_.begin(); + connection_handler_->CloseSession(app_to_remove->app_id(), + connection_handler::kCommon); + it = accessor.begin(); } - if (is_ignition_off) { - resume_controller().IgnitionOff(); + resume_controller().Suspend(); } request_ctrl_.terminateAllHMIRequests(); } @@ -1992,12 +2065,15 @@ void ApplicationManagerImpl::UnregisterAllApplications(bool generated_by_hmi) { void ApplicationManagerImpl::UnregisterApplication( const uint32_t& app_id, mobile_apis::Result::eType reason, bool is_resuming, bool is_unexpected_disconnect) { - LOG4CXX_INFO(logger_, - "ApplicationManagerImpl::UnregisterApplication " << app_id); + LOG4CXX_INFO(logger_, "app_id = " << app_id + << "; reason = " << reason + << "; is_resuming = " << is_resuming + << "; is_unexpected_disconnect = " << is_unexpected_disconnect); //remove appID from tts_global_properties_app_list_ - RemoveAppFromTTSGlobalPropertiesList(app_id); + MessageHelper::SendOnAppInterfaceUnregisteredNotificationToMobile( + app_id, unregister_reason_); - sync_primitives::AutoLock lock(applications_list_lock_); + RemoveAppFromTTSGlobalPropertiesList(app_id); switch (reason) { case mobile_apis::Result::SUCCESS:break; @@ -2006,7 +2082,10 @@ void ApplicationManagerImpl::UnregisterApplication( case mobile_apis::Result::INVALID_CERT: break; case mobile_apis::Result::EXPIRED_CERT: break; case mobile_apis::Result::TOO_MANY_PENDING_REQUESTS: { - application(app_id)->usage_report().RecordRemovalsForBadBehavior(); + ApplicationSharedPtr app_ptr = application(app_id); + if(app_ptr) { + app_ptr->usage_report().RecordRemovalsForBadBehavior(); + } break; } default: { @@ -2016,21 +2095,25 @@ void ApplicationManagerImpl::UnregisterApplication( } ApplicationSharedPtr app_to_remove; - std::set<ApplicationSharedPtr>::const_iterator it = application_list_.begin(); - for (; it != application_list_.end(); ++it) { - if ((*it)->app_id() == app_id) { - app_to_remove = *it; - break; + { + ApplicationListAccessor accessor; + ApplictionSetConstIt it = accessor.begin(); + for (; it != accessor.end(); ++it) { + if ((*it)->app_id() == app_id) { + app_to_remove = *it; + break; + } } + if (!app_to_remove) { + LOG4CXX_ERROR(logger_, "Cant find application with app_id = " << app_id); + return; + } + accessor.Erase(app_to_remove); } - if (!app_to_remove) { - LOG4CXX_ERROR(logger_, "Cant find application with app_id = " << app_id); - return; - } - application_list_.erase(app_to_remove); - if (is_resuming) { - resume_ctrl_.SaveApplication(app_to_remove); + resume_ctrl_.SaveApplication(app_to_remove); + } else { + resume_ctrl_.RemoveApplicationFromSaved(app_to_remove->mobile_app_id()); } if (audio_pass_thru_active_) { @@ -2047,15 +2130,8 @@ void ApplicationManagerImpl::UnregisterApplication( } -void ApplicationManagerImpl::UnregisterRevokedApplication( - const uint32_t& app_id, mobile_apis::Result::eType reason) { - UnregisterApplication(app_id, reason); - - connection_handler_->CloseSession(app_id); - - if (application_list_.empty()) { - connection_handler_->CloseRevokedConnection(app_id); - } +void ApplicationManagerImpl::OnAppUnauthorized(const uint32_t& app_id) { + connection_handler_->CloseSession(app_id, connection_handler::kCommon); } void ApplicationManagerImpl::Handle(const impl::MessageFromMobile message) { @@ -2069,26 +2145,19 @@ void ApplicationManagerImpl::Handle(const impl::MessageFromMobile message) { } void ApplicationManagerImpl::Handle(const impl::MessageToMobile message) { - protocol_handler::RawMessage* rawMessage = 0; - if (message->protocol_version() == application_manager::kV1) { - rawMessage = MobileMessageHandler::HandleOutgoingMessageProtocolV1(message); - } else if ((message->protocol_version() == application_manager::kV2) || - (message->protocol_version() == application_manager::kV3)) { - rawMessage = MobileMessageHandler::HandleOutgoingMessageProtocolV2(message); - } else { - return; - } - if (!rawMessage) { - LOG4CXX_ERROR(logger_, "Failed to create raw message."); - return; - } - if (!protocol_handler_) { LOG4CXX_WARN(logger_, "Protocol Handler is not set; cannot send message to mobile."); return; } + utils::SharedPtr<protocol_handler::RawMessage> rawMessage = + MobileMessageHandler::HandleOutgoingMessageProtocol(message); + + if (!rawMessage) { + LOG4CXX_ERROR(logger_, "Failed to create raw message."); + return; + } bool is_final = message.is_final; bool close_session = false; @@ -2103,7 +2172,8 @@ void ApplicationManagerImpl::Handle(const impl::MessageToMobile message) { LOG4CXX_INFO(logger_, "Message for mobile given away"); if (close_session) { - connection_handler_->CloseSession(message->connection_key()); + connection_handler_->CloseSession(message->connection_key(), + connection_handler::kCommon); } } @@ -2129,6 +2199,41 @@ void ApplicationManagerImpl::Handle(const impl::MessageToHmi message) { LOG4CXX_INFO(logger_, "Message to hmi given away."); } +void ApplicationManagerImpl::Handle(const impl::AudioData message) { + LOG4CXX_INFO(logger_, "Send AudioPassThru notification"); + smart_objects::SmartObjectSPtr on_audio_pass = new smart_objects::SmartObject(); + + if (!on_audio_pass) { + LOG4CXX_ERROR_EXT(logger_, "OnAudioPassThru NULL pointer"); + return; + } + + LOG4CXX_INFO_EXT(logger_, "Fill smart object"); + + (*on_audio_pass)[strings::params][strings::message_type] = + application_manager::MessageType::kNotification; + + (*on_audio_pass)[strings::params][strings::connection_key] = + static_cast<int32_t>(message.session_key); + (*on_audio_pass)[strings::params][strings::function_id] = + mobile_apis::FunctionID::OnAudioPassThruID; + + LOG4CXX_INFO_EXT(logger_, "Fill binary data"); + // binary data + (*on_audio_pass)[strings::params][strings::binary_data] = + smart_objects::SmartObject(message.binary_data); + + LOG4CXX_INFO_EXT(logger_, "After fill binary data"); + + LOG4CXX_INFO_EXT(logger_, "Send data"); + CommandSharedPtr command ( + MobileCommandFactory::CreateCommand(on_audio_pass, + commands::Command::ORIGIN_SDL)); + command->Init(); + command->Run(); + command->CleanUp(); +} + mobile_apis::Result::eType ApplicationManagerImpl::CheckPolicyPermissions( const std::string& policy_app_id, mobile_apis::HMILevel::eType hmi_level, @@ -2200,16 +2305,185 @@ mobile_apis::Result::eType ApplicationManagerImpl::CheckPolicyPermissions( return mobile_api::Result::SUCCESS; } + +void ApplicationManagerImpl::OnLowVoltage() { + LOG4CXX_AUTO_TRACE(logger_); + is_low_voltage_ = true; + request_ctrl_.OnLowVoltage(); +} + +bool ApplicationManagerImpl::IsLowVoltage() { + LOG4CXX_TRACE(logger_, "result: " << is_low_voltage_); + return is_low_voltage_; +} + +void ApplicationManagerImpl::NaviAppStreamStatus(bool stream_active) { + ApplicationSharedPtr active_app = active_application(); + using namespace mobile_apis; + if(active_app && active_app->is_media_application()) { + LOG4CXX_DEBUG(logger_, "Stream status: " << active_app->app_id()); + + active_app->set_audio_streaming_state(stream_active ? + AudioStreamingState::ATTENUATED : + AudioStreamingState::AUDIBLE); + MessageHelper::SendHMIStatusNotification(*active_app); + } +} + +void ApplicationManagerImpl::ForbidStreaming(uint32_t app_id) { + LOG4CXX_AUTO_TRACE(logger_); + using namespace protocol_handler; + ApplicationSharedPtr app = application(app_id); + if (!(app && app->is_navi())) { + LOG4CXX_DEBUG(logger_, " There is no application with id: " << app_id); + return; + } + + if (connection_handler_) { + const bool send_end_service = true; + const bool ack_received = false; + if (app->hmi_supports_navi_video_streaming()) { + LOG4CXX_DEBUG(logger_, "Going to end video service"); + connection_handler_->SendEndService(navi_app_to_stop_, kMobileNav); + service_status_[kMobileNav] = std::make_pair(send_end_service, ack_received); + } + if (app->hmi_supports_navi_audio_streaming()) { + LOG4CXX_DEBUG(logger_, "Going to end audio service"); + connection_handler_->SendEndService(navi_app_to_stop_, kAudio); + service_status_[kAudio] = std::make_pair(send_end_service, ack_received); + } + } + // this timer will check if appropriate acks from mobile were received. + // in case no acks, the application will be unregistered. + end_services_timer.start(wait_end_service_timeout_, this, &ApplicationManagerImpl::CloseNaviApp); + bool const allow_streaming = false; + ChangeStreamStatus(app_id, allow_streaming); +} + +bool ApplicationManagerImpl::CanAppStream(uint32_t app_id) const { + LOG4CXX_AUTO_TRACE(logger_); + + ApplicationSharedPtr app = application(app_id); + if (!(app && app->is_navi())) { + LOG4CXX_DEBUG(logger_, " There is no application with id: " << app_id); + return false; + } + + return app->is_streaming_allowed(); +} + +void ApplicationManagerImpl::ChangeStreamStatus(uint32_t app_id, bool can_stream) { + ApplicationSharedPtr app = application(app_id); + if (!app) { + LOG4CXX_DEBUG(logger_, " There is no application with id: " << app_id); + return; + } + + // Change streaming status only in case incoming value is different. + if (can_stream != app->streaming()) { + NaviAppStreamStatus(can_stream); + app->set_streaming(can_stream); + } +} + +void ApplicationManagerImpl::StreamingEnded(uint32_t app_id) { + LOG4CXX_DEBUG(logger_, "Streaming has been stoped."); + ChangeStreamStatus(app_id, false); +} + +void ApplicationManagerImpl::OnHMILevelChanged(uint32_t app_id, + mobile_apis::HMILevel::eType from, + mobile_apis::HMILevel::eType to) { + using namespace mobile_apis::HMILevel; + using namespace helpers; + + ApplicationSharedPtr app = application(app_id); + if (!(app && app->is_navi())) { + return; + } + + if (Compare<eType, EQ, ONE>(from, HMI_FULL, HMI_LIMITED)) { + navi_app_to_stop_ = app_id; + NaviAppChangeLevel(to); + } else if (Compare<eType, EQ, ONE>(to, HMI_FULL, HMI_LIMITED)) { + LOG4CXX_DEBUG(logger_, "Restore streaming ability"); + app->set_streaming_allowed(true); + } +} + +void ApplicationManagerImpl::EndNaviServices() { + LOG4CXX_AUTO_TRACE(logger_); + ApplicationSharedPtr app = application(navi_app_to_stop_); + if (!app) { + LOG4CXX_DEBUG(logger_, "The application doesn't exists anymore."); + return; + } + app->set_streaming_allowed(false); +} + +void ApplicationManagerImpl::CloseNaviApp() { + LOG4CXX_AUTO_TRACE(logger_); + using namespace mobile_apis::AppInterfaceUnregisteredReason; + using namespace mobile_apis::Result; + using namespace protocol_handler; + const bool is_ack_received = AckReceived(kAudio) && AckReceived(kMobileNav); + if (!is_ack_received) { + SetUnregisterAllApplicationsReason(PROTOCOL_VIOLATION); + UnregisterApplication(navi_app_to_stop_, ABORTED); + } +} + +bool ApplicationManagerImpl::AckReceived(protocol_handler::ServiceType type) { + LOG4CXX_AUTO_TRACE(logger_); + using namespace protocol_handler; + + const bool sent = service_status_[type].first; + const bool received = service_status_[type].second; + + LOG4CXX_DEBUG(logger_, "Ack for services type " << type + << " is send: " << sent + << " is received: " << received); + + return sent == received; +} + +void ApplicationManagerImpl::NaviAppChangeLevel(mobile_apis::HMILevel::eType new_level) { + LOG4CXX_AUTO_TRACE(logger_); + using namespace mobile_apis; + if (new_level == HMILevel::HMI_BACKGROUND) { + end_services_timer.start(wait_end_service_timeout_, this, &ApplicationManagerImpl::EndNaviServices); + } else if (new_level == HMILevel::HMI_NONE) { + EndNaviServices(); + LOG4CXX_DEBUG(logger_, "Send end services start close app timer"); + end_services_timer.start(wait_end_service_timeout_, this, &ApplicationManagerImpl::CloseNaviApp); + } else { + LOG4CXX_DEBUG(logger_, "There is no defined behavior for hmi " << + "levels that are differen from NONE or BACKGROUND"); + } +} + +void ApplicationManagerImpl::OnWakeUp() { + LOG4CXX_AUTO_TRACE(logger_); + is_low_voltage_ = false; + request_ctrl_.OnWakeUp(); +} + void ApplicationManagerImpl::Mute(VRTTSSessionChanging changing_state) { mobile_apis::AudioStreamingState::eType state = - hmi_capabilities_.attenuated_supported() - ? mobile_apis::AudioStreamingState::ATTENUATED - : mobile_apis::AudioStreamingState::NOT_AUDIBLE; + mobile_apis::AudioStreamingState::NOT_AUDIBLE; + + // ATTENUATED state applicable only for TTS + if ((kTTSSessionChanging == changing_state) && + hmi_capabilities_.attenuated_supported()) { + state = mobile_apis::AudioStreamingState::ATTENUATED; + } + ApplicationManagerImpl::ApplicationListAccessor accessor; - ApplicationManagerImpl::TAppList local_app_list = accessor.applications(); - ApplicationManagerImpl::TAppListConstIt it = local_app_list.begin(); - ApplicationManagerImpl::TAppListConstIt itEnd = local_app_list.end(); + ApplicationManagerImpl::ApplictionSetConstIt it = + accessor.begin(); + ApplicationManagerImpl::ApplictionSetConstIt + itEnd = accessor.end(); for (; it != itEnd; ++it) { if ((*it).valid()) { if ((*it)->is_media_application()) { @@ -2230,9 +2504,8 @@ void ApplicationManagerImpl::Mute(VRTTSSessionChanging changing_state) { void ApplicationManagerImpl::Unmute(VRTTSSessionChanging changing_state) { ApplicationManagerImpl::ApplicationListAccessor accessor; - ApplicationManagerImpl::TAppList local_app_list = application_list_; - ApplicationManagerImpl::TAppListConstIt it = local_app_list.begin(); - ApplicationManagerImpl::TAppListConstIt itEnd = local_app_list.end(); + ApplicationManagerImpl::ApplictionSetConstIt it = accessor.begin(); + ApplicationManagerImpl::ApplictionSetConstIt itEnd = accessor.end(); for (; it != itEnd; ++it) { if ((*it).valid()) { @@ -2332,19 +2605,8 @@ bool ApplicationManagerImpl::IsHMICooperating() const { void ApplicationManagerImpl::OnApplicationListUpdateTimer() { LOG4CXX_DEBUG(logger_, "Application list update timer finished"); - - std::list <uint32_t> applications_ids; - - applications_list_lock_.Acquire(); - for (std::set<ApplicationSharedPtr>::const_iterator i = application_list_.begin(); - i != application_list_.end(); ++i) { - ApplicationSharedPtr application = *i; - uint32_t app_id = application->app_id(); - applications_ids.push_back(app_id); - } - applications_list_lock_.Release(); - - SendUpdateAppList(applications_ids); + SendUpdateAppList(); + policy::PolicyHandler::instance()->OnAppsSearchCompleted(); } void ApplicationManagerImpl::OnTimerSendTTSGlobalProperties() { @@ -2375,11 +2637,12 @@ void ApplicationManagerImpl::OnTimerSendTTSGlobalProperties() { void ApplicationManagerImpl::AddAppToTTSGlobalPropertiesList( const uint32_t app_id) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::AddAppToTTSGlobalPropertiesList"); + LOG4CXX_AUTO_TRACE(logger_); uint16_t timeout = profile::Profile::instance()->tts_global_properties_timeout(); TimevalStruct current_time = date_time::DateTime::getCurrentTime(); current_time.tv_sec += timeout; - sync_primitives::AutoLock lock(tts_global_properties_app_list_lock_); + // please avoid AutoLock usage to avoid deadlock + tts_global_properties_app_list_lock_.Acquire(); if (tts_global_properties_app_list_.end() == tts_global_properties_app_list_.find(app_id)) { tts_global_properties_app_list_[app_id] = current_time; @@ -2387,38 +2650,45 @@ void ApplicationManagerImpl::AddAppToTTSGlobalPropertiesList( //if add first item need to start timer on one second if (1 == tts_global_properties_app_list_.size()) { LOG4CXX_INFO(logger_, "Start tts_global_properties_timer_"); + tts_global_properties_app_list_lock_.Release(); tts_global_properties_timer_.start(1); + return; } + tts_global_properties_app_list_lock_.Release(); } void ApplicationManagerImpl::RemoveAppFromTTSGlobalPropertiesList( const uint32_t app_id) { - LOG4CXX_INFO(logger_, "ApplicationManagerImpl::RemoveAppFromTTSGlobalPropertiesList"); - sync_primitives::AutoLock lock(tts_global_properties_app_list_lock_); + LOG4CXX_AUTO_TRACE(logger_); + // please avoid AutoLock usage to avoid deadlock + tts_global_properties_app_list_lock_.Acquire(); std::map<uint32_t, TimevalStruct>::iterator it = tts_global_properties_app_list_.find(app_id); if (tts_global_properties_app_list_.end() != it) { tts_global_properties_app_list_.erase(it); - if (!(tts_global_properties_app_list_.size())) { + if (tts_global_properties_app_list_.empty()) { LOG4CXX_INFO(logger_, "Stop tts_global_properties_timer_"); - //if container is empty need to stop timer - tts_global_properties_timer_.stop(); + // if container is empty need to stop timer + tts_global_properties_app_list_lock_.Release(); + tts_global_properties_timer_.pause(); + return; } } + tts_global_properties_app_list_lock_.Release(); } void ApplicationManagerImpl::CreatePhoneCallAppList() { - LOG4CXX_TRACE_ENTER(logger_); + LOG4CXX_AUTO_TRACE(logger_); ApplicationManagerImpl::ApplicationListAccessor accessor; - ApplicationManagerImpl::TAppList local_app_list = accessor.applications(); - ApplicationManagerImpl::TAppListIt it = local_app_list.begin(); - ApplicationManagerImpl::TAppListIt itEnd = local_app_list.end(); + ApplicationManagerImpl::ApplictionSetIt it = accessor.begin(); + ApplicationManagerImpl::ApplictionSetIt itEnd = accessor.end(); + using namespace mobile_apis::HMILevel; + using namespace helpers; for (; it != itEnd; ++it) { - if (mobile_api::HMILevel::HMI_FULL == (*it)->hmi_level() || - mobile_api::HMILevel::HMI_LIMITED == (*it)->hmi_level()) { + if (Compare<eType, EQ, ONE>((*it)->hmi_level(), HMI_FULL, HMI_LIMITED)) { // back up app state on_phone_call_app_list_.insert(std::pair<uint32_t, AppState>( @@ -2426,8 +2696,9 @@ void ApplicationManagerImpl::CreatePhoneCallAppList() { (*it)->audio_streaming_state(), (*it)->system_context()))); + ChangeAppsHMILevel((*it)->app_id() , (*it)->is_navi() ? HMI_LIMITED : HMI_BACKGROUND); + // app state during phone call - (*it)->set_hmi_level(mobile_api::HMILevel::HMI_BACKGROUND); (*it)->set_audio_streaming_state(mobile_api::AudioStreamingState::NOT_AUDIBLE); (*it)->set_system_context(mobile_api::SystemContext::SYSCTXT_MAIN); MessageHelper::SendHMIStatusNotification(*(*it)); @@ -2436,10 +2707,7 @@ void ApplicationManagerImpl::CreatePhoneCallAppList() { } void ApplicationManagerImpl::ResetPhoneCallAppList() { - LOG4CXX_TRACE_ENTER(logger_); - - ApplicationManagerImpl::ApplicationListAccessor accessor; - ApplicationManagerImpl::TAppList local_app_list = accessor.applications(); + LOG4CXX_AUTO_TRACE(logger_); std::map<uint32_t, AppState>::iterator it = on_phone_call_app_list_.begin(); @@ -2448,7 +2716,8 @@ void ApplicationManagerImpl::ResetPhoneCallAppList() { for (; it != it_end; ++it) { ApplicationSharedPtr app = application(it->first); if (app) { - app->set_hmi_level(it->second.hmi_level); + ChangeAppsHMILevel(app->app_id(), it->second.hmi_level); + app->set_audio_streaming_state(it->second.audio_streaming_state); app->set_system_context(it->second.system_context); MessageHelper::SendHMIStatusNotification(*app); @@ -2458,4 +2727,191 @@ void ApplicationManagerImpl::ResetPhoneCallAppList() { on_phone_call_app_list_.clear(); } +void ApplicationManagerImpl::ChangeAppsHMILevel(uint32_t app_id, + mobile_apis::HMILevel::eType level) { + using namespace mobile_apis::HMILevel; + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "AppID to change: " << app_id << " -> " + << level); + ApplicationSharedPtr app = application(app_id); + if (!app) { + LOG4CXX_DEBUG(logger_, "There is no app with id: " << app_id); + return; + } + eType old_level = app->hmi_level(); + if (old_level != level) { + app->set_hmi_level(level); + OnHMILevelChanged(app_id, old_level, level); + } else { + LOG4CXX_WARN(logger_, "Redudant changing HMI level : " << level); + } + +} + +void ApplicationManagerImpl::MakeAppNotAudible(uint32_t app_id) { + using namespace mobile_apis; + ApplicationSharedPtr app = application(app_id); + if (!app) { + LOG4CXX_DEBUG(logger_, "There is no app with id: " << app_id); + return; + } + ChangeAppsHMILevel(app_id, HMILevel::HMI_BACKGROUND); + app->set_audio_streaming_state(AudioStreamingState::NOT_AUDIBLE); +} + +bool ApplicationManagerImpl::MakeAppFullScreen(uint32_t app_id) { + using namespace mobile_apis; + ApplicationSharedPtr app = application(app_id); + if (!app) { + LOG4CXX_DEBUG(logger_, "There is no app with id: " << app_id); + return false; + } + + ChangeAppsHMILevel(app_id, HMILevel::HMI_FULL); + if (app->is_media_application() || app->is_navi()) { + app->set_audio_streaming_state(AudioStreamingState::AUDIBLE); + } + app->set_system_context(SystemContext::SYSCTXT_MAIN); + + if(!app->has_been_activated()) { + app->set_activated(true); + } + + return true; +} + + +mobile_apis::AppHMIType::eType ApplicationManagerImpl::StringToAppHMIType(std::string str) { + LOG4CXX_AUTO_TRACE(logger_); + if ("DEFAULT" == str) { + return mobile_apis::AppHMIType::DEFAULT; + } else if ("COMMUNICATION" == str) { + return mobile_apis::AppHMIType::COMMUNICATION; + } else if ("MEDIA" == str) { + return mobile_apis::AppHMIType::MEDIA; + } else if ("MESSAGING" == str) { + return mobile_apis::AppHMIType::MESSAGING; + } else if ("NAVIGATION" == str) { + return mobile_apis::AppHMIType::NAVIGATION; + } else if ("INFORMATION" == str) { + return mobile_apis::AppHMIType::INFORMATION; + } else if ("SOCIAL" == str) { + return mobile_apis::AppHMIType::SOCIAL; + } else if ("BACKGROUND_PROCESS" == str) { + return mobile_apis::AppHMIType::BACKGROUND_PROCESS; + } else if ("TESTING" == str) { + return mobile_apis::AppHMIType::TESTING; + } else if ("SYSTEM" == str) { + return mobile_apis::AppHMIType::SYSTEM; + } else { + return mobile_apis::AppHMIType::INVALID_ENUM; + } +} + +bool ApplicationManagerImpl::CompareAppHMIType (const smart_objects::SmartObject& from_policy, + const smart_objects::SmartObject& from_application) { + LOG4CXX_AUTO_TRACE(logger_); + bool equal = false; + uint32_t lenght_policy_app_types = from_policy.length(); + uint32_t lenght_application_app_types = from_application.length(); + + for(uint32_t i = 0; i < lenght_application_app_types; ++i) { + for(uint32_t k = 0; k < lenght_policy_app_types; ++k) { + if (from_application[i] == from_policy[k]) { + equal = true; + break; + } + } + if(!equal) { + return false; + } + equal = false; + } + return true; +} + +void ApplicationManagerImpl::OnUpdateHMIAppType( + std::map<std::string, std::vector<std::string> > app_hmi_types) { + LOG4CXX_AUTO_TRACE(logger_); + + std::map<std::string, std::vector<std::string> >::iterator it_app_hmi_types_from_policy; + std::vector<std::string> hmi_types_from_policy; + smart_objects::SmartObject transform_app_hmi_types(smart_objects::SmartType_Array); + bool flag_diffirence_app_hmi_type = false; + ApplicationListAccessor accessor; + for (ApplictionSetIt it = accessor.begin(); + it != accessor.end(); ++it) { + + it_app_hmi_types_from_policy = + app_hmi_types.find(((*it)->mobile_app_id())); + + if (it_app_hmi_types_from_policy != app_hmi_types.end() && + ((it_app_hmi_types_from_policy->second).size())) { + flag_diffirence_app_hmi_type = false; + hmi_types_from_policy = (it_app_hmi_types_from_policy->second); + + if(transform_app_hmi_types.length()) { + transform_app_hmi_types = + smart_objects::SmartObject(smart_objects::SmartType_Array); + } + + for(uint32_t i = 0; i < hmi_types_from_policy.size(); ++i) { + transform_app_hmi_types[i] = StringToAppHMIType(hmi_types_from_policy[i]); + } + + ApplicationConstSharedPtr app = *it; + const smart_objects::SmartObject* save_application_hmi_type = app->app_types(); + + if (save_application_hmi_type == NULL || + ((*save_application_hmi_type).length() != transform_app_hmi_types.length())) { + flag_diffirence_app_hmi_type = true; + } else { + flag_diffirence_app_hmi_type = !(CompareAppHMIType(transform_app_hmi_types, + *save_application_hmi_type)); + } + + if (flag_diffirence_app_hmi_type) { + (*it)->set_app_types(transform_app_hmi_types); + (*it)->ChangeSupportingAppHMIType(); + if ((*it)->hmi_level() == mobile_api::HMILevel::HMI_BACKGROUND) { + + MessageHelper::SendUIChangeRegistrationRequestToHMI(*it); + } else if (((*it)->hmi_level() == mobile_api::HMILevel::HMI_FULL) || + ((*it)->hmi_level() == mobile_api::HMILevel::HMI_LIMITED)) { + + MessageHelper::SendActivateAppToHMI((*it)->app_id(), + hmi_apis::Common_HMILevel::BACKGROUND, + false); + MessageHelper::SendUIChangeRegistrationRequestToHMI(*it); + ChangeAppsHMILevel((*it)->app_id(), mobile_api::HMILevel::HMI_BACKGROUND); + MessageHelper::SendHMIStatusNotification(*(*it)); + } + } + } + } +} + +ProtocolVersion ApplicationManagerImpl::SupportedSDLVersion() const { + LOG4CXX_AUTO_TRACE(logger_); + bool heart_beat_support = + profile::Profile::instance()->heart_beat_timeout(); + bool sdl4_support = profile::Profile::instance()->enable_protocol_4(); + + if (sdl4_support) { + LOG4CXX_DEBUG(logger_, "SDL Supported protocol version "<<ProtocolVersion::kV4); + return ProtocolVersion::kV4; + } + if (heart_beat_support) { + LOG4CXX_DEBUG(logger_, "SDL Supported protocol version "<<ProtocolVersion::kV3); + return ProtocolVersion::kV3; + } + + LOG4CXX_DEBUG(logger_, "SDL Supported protocol version "<<ProtocolVersion::kV2); + return ProtocolVersion::kV2; +} + + +ApplicationManagerImpl::ApplicationListAccessor::~ApplicationListAccessor() { +} + } // namespace application_manager |