diff options
author | Artem Nosach (GitHub) <ANosach@luxoft.com> | 2016-07-18 15:44:47 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-18 15:44:47 +0300 |
commit | 3dc74d9071cdb44840a74bef8353109623b7923c (patch) | |
tree | 0ba50b1a141c499e8a4e3fc7bc5bc42f11212572 | |
parent | 7ae459d489ba7a6f3ea2c9517c5673ca26159481 (diff) | |
parent | d2f17e8efe863ef4998d8f4dc0385ccb3c747dc5 (diff) | |
download | sdl_core-3dc74d9071cdb44840a74bef8353109623b7923c.tar.gz |
Merge pull request #694 from dev-gh/fix/Fixes_LAUNCH_APP_flow
Fixes SDL4.0 LAUNCH_APP flow
6 files changed, 223 insertions, 88 deletions
diff --git a/src/components/application_manager/include/application_manager/application_manager.h b/src/components/application_manager/include/application_manager/application_manager.h index 411ecec092..97c38cd134 100644 --- a/src/components/application_manager/include/application_manager/application_manager.h +++ b/src/components/application_manager/include/application_manager/application_manager.h @@ -87,8 +87,22 @@ struct ApplicationsAppIdSorter { return lhs->app_id() < rhs->app_id(); } }; + +struct ApplicationsPolicyAppIdSorter { + bool operator()(const ApplicationSharedPtr lhs, + const ApplicationSharedPtr rhs) { + if (lhs->policy_app_id() == rhs->policy_app_id()) { + return lhs->device() < rhs->device(); + } + return lhs->policy_app_id() < rhs->policy_app_id(); + } +}; + typedef std::set<ApplicationSharedPtr, ApplicationsAppIdSorter> ApplicationSet; +typedef std::set<ApplicationSharedPtr, ApplicationsPolicyAppIdSorter> + AppsWaitRegistrationSet; + // typedef for Applications list iterator typedef ApplicationSet::iterator ApplicationSetIt; @@ -326,6 +340,23 @@ class ApplicationManager { virtual void MarkAppsGreyOut(const connection_handler::DeviceHandle handle, bool is_greyed_out) = 0; + + /** + * @brief Returns pointer to application-to-be-registered (from QUERY_APP + * list) + * @param hmi_id HMI application id + * @return Pointer to application or uninitialized shared pointer + */ + virtual ApplicationConstSharedPtr WaitingApplicationByID( + const uint32_t hmi_id) const = 0; + + /** + * @brief Returns list of applications-to-be-registered (QUERY_APP list) + * @return Locked list of applications + */ + virtual DataAccessor<AppsWaitRegistrationSet> AppsWaitingForRegistration() + const = 0; + virtual bool IsAppsQueriedFrom( const connection_handler::DeviceHandle handle) const = 0; diff --git a/src/components/application_manager/include/application_manager/application_manager_impl.h b/src/components/application_manager/include/application_manager/application_manager_impl.h index 91b0f3f86f..dda192f8b0 100644 --- a/src/components/application_manager/include/application_manager/application_manager_impl.h +++ b/src/components/application_manager/include/application_manager/application_manager_impl.h @@ -835,9 +835,9 @@ class ApplicationManagerImpl ApplicationConstSharedPtr application) const; /** - * Getter for resume_controller - * @return Resume Controller - */ + * Getter for resume_controller + * @return Resume Controller + */ resumption::ResumeCtrl& resume_controller() OVERRIDE { return resume_ctrl_; } @@ -991,20 +991,7 @@ class ApplicationManagerImpl } }; - struct ApplicationsPolicyAppIdSorter { - bool operator()(const ApplicationSharedPtr lhs, - const ApplicationSharedPtr rhs) { - if (lhs->policy_app_id() == rhs->policy_app_id()) { - return lhs->device() < rhs->device(); - } - return lhs->policy_app_id() < rhs->policy_app_id(); - } - }; - // typedef for Applications list - typedef std::set<ApplicationSharedPtr, ApplicationsPolicyAppIdSorter> - AppsWaitRegistrationSet; - typedef std::set<std::string> ForbiddenApps; struct AppIdPredicate { @@ -1093,6 +1080,12 @@ class ApplicationManagerImpl void MarkAppsGreyOut(const connection_handler::DeviceHandle handle, bool is_greyed_out) OVERRIDE; + ApplicationConstSharedPtr WaitingApplicationByID( + const uint32_t hmi_id) const OVERRIDE; + + DataAccessor<AppsWaitRegistrationSet> AppsWaitingForRegistration() + const OVERRIDE; + /** * @brief Checks, if apps list had been queried already from certain device * @param handle, Device handle diff --git a/src/components/application_manager/include/application_manager/commands/hmi/sdl_activate_app_request.h b/src/components/application_manager/include/application_manager/commands/hmi/sdl_activate_app_request.h index ce86ea2df3..0dff904955 100644 --- a/src/components/application_manager/include/application_manager/commands/hmi/sdl_activate_app_request.h +++ b/src/components/application_manager/include/application_manager/commands/hmi/sdl_activate_app_request.h @@ -40,14 +40,17 @@ namespace application_manager { namespace commands { -typedef std::pair<ApplicationSharedPtr, std::vector<ApplicationSharedPtr> > - DevicesApps; /** * @brief SDLActivateAppRequest command class **/ class SDLActivateAppRequest : public RequestFromHMI { public: /** + * @brief Applications registered over protocol v4 + */ + typedef std::vector<application_manager::ApplicationSharedPtr> V4ProtoApps; + + /** * @brief SDLActivateAppRequest class constructor * * @param message Incoming SmartObject message @@ -58,32 +61,46 @@ class SDLActivateAppRequest : public RequestFromHMI { /** * @brief SDLActivateAppRequest class destructor **/ - virtual ~SDLActivateAppRequest(); + ~SDLActivateAppRequest() OVERRIDE; /** * @brief Execute command **/ - virtual void Run(); + void Run() OVERRIDE; /** * @brief onTimeOut allows to process case when timeout has appeared * during request execution. */ - virtual void onTimeOut(); + void onTimeOut() OVERRIDE; /** * @brief on_event allows to handle events * * @param event event type that current request subscribed on. */ - virtual void on_event(const event_engine::Event& event); + void on_event(const event_engine::Event& event) OVERRIDE; private: uint32_t app_id() const; uint32_t hmi_app_id(const smart_objects::SmartObject& so) const; - DevicesApps FindAllAppOnParticularDevice( - const connection_handler::DeviceHandle handle); + /** + * @brief Retrieves all v4 protocol applications for particular device + * @param handle Device handle + * @return List of applications registered over v4 protocol + */ + V4ProtoApps get_v4_proto_apps( + const connection_handler::DeviceHandle handle) const; + + /** + * @brief Get v4 protocol application reported as forgrounded on device + * @param handle Device + * @return Pointer to application or empty pointer + */ + ApplicationSharedPtr get_foreground_app( + const connection_handler::DeviceHandle handle) const; + DISALLOW_COPY_AND_ASSIGN(SDLActivateAppRequest); }; diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 7aa1bd550d..f525165827 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -835,6 +835,27 @@ void ApplicationManagerImpl::OnMessageReceived( messages_from_hmi_.PostMessage(impl::MessageFromHmi(message)); } +ApplicationConstSharedPtr ApplicationManagerImpl::WaitingApplicationByID( + const uint32_t hmi_id) const { + AppsWaitRegistrationSet app_list = AppsWaitingForRegistration().GetData(); + + AppsWaitRegistrationSet::const_iterator it_end = app_list.end(); + + HmiAppIdPredicate finder(hmi_id); + ApplicationSharedPtr result; + ApplicationSetConstIt it_app = std::find_if(app_list.begin(), it_end, finder); + if (it_app != it_end) { + result = *it_app; + } + return result; +} + +DataAccessor<AppsWaitRegistrationSet> +ApplicationManagerImpl::AppsWaitingForRegistration() const { + return DataAccessor<AppsWaitRegistrationSet>(apps_to_register_, + apps_to_register_list_lock_); +} + bool ApplicationManagerImpl::IsAppsQueriedFrom( const connection_handler::DeviceHandle handle) const { sync_primitives::AutoLock lock(apps_to_register_list_lock_); diff --git a/src/components/application_manager/src/commands/hmi/sdl_activate_app_request.cc b/src/components/application_manager/src/commands/hmi/sdl_activate_app_request.cc index 9c4ff8c41e..30ea41e0b0 100644 --- a/src/components/application_manager/src/commands/hmi/sdl_activate_app_request.cc +++ b/src/components/application_manager/src/commands/hmi/sdl_activate_app_request.cc @@ -38,6 +38,46 @@ namespace application_manager { namespace commands { +namespace { +struct ProtoV4AppsOnDevice : std::unary_function<ApplicationSharedPtr, bool> { + connection_handler::DeviceHandle handle_; + ProtoV4AppsOnDevice(const connection_handler::DeviceHandle handle) + : handle_(handle) {} + bool operator()(const ApplicationSharedPtr app) const { + return app + ? handle_ == app->device() && + ProtocolVersion::kV4 == app->protocol_version() + : false; + } +}; + +struct ForegroundApp + : std::unary_function<SDLActivateAppRequest::V4ProtoApps::value_type, + bool> { + bool operator()( + const SDLActivateAppRequest::V4ProtoApps::value_type ptr) const { + return ptr ? ptr->is_foreground() : false; + } +}; + +struct SendLaunchApp + : std::unary_function<SDLActivateAppRequest::V4ProtoApps::value_type, + void> { + ApplicationConstSharedPtr app_to_launch_; + ApplicationManager& application_manager_; + SendLaunchApp(ApplicationConstSharedPtr app_to_launch, ApplicationManager& am) + : app_to_launch_(app_to_launch), application_manager_(am) {} + void operator()( + const SDLActivateAppRequest::V4ProtoApps::value_type ptr) const { + MessageHelper::SendLaunchApp((*ptr).app_id(), + app_to_launch_->SchemaUrl(), + app_to_launch_->PackageName(), + application_manager_); + return; + } +}; +} + SDLActivateAppRequest::SDLActivateAppRequest( const MessageSharedPtr& message, ApplicationManager& application_manager) : RequestFromHMI(message, application_manager) {} @@ -51,55 +91,73 @@ void SDLActivateAppRequest::Run() { const uint32_t application_id = app_id(); - ApplicationConstSharedPtr app = + ApplicationConstSharedPtr app_to_activate = application_manager_.application(application_id); - if (!app) { - LOG4CXX_ERROR( + if (!app_to_activate) { + LOG4CXX_WARN( logger_, "Can't find application within regular apps: " << application_id); + + // Here is the hack - in fact SDL gets hmi_app_id in appID field and + // replaces it with connection_key only for normally registered apps, but + // for apps_to_be_registered (waiting) it keeps original value (hmi_app_id) + // so method does lookup for hmi_app_id + app_to_activate = + application_manager_.WaitingApplicationByID(application_id); + + if (!app_to_activate) { + LOG4CXX_WARN( + logger_, + "Can't find application within waiting apps: " << application_id); + return; + } + } + + LOG4CXX_DEBUG(logger_, + "Found application to activate. Application id is " + << app_to_activate->app_id()); + + if (app_to_activate->IsRegistered()) { + LOG4CXX_DEBUG(logger_, "Application is registered. Activating."); + application_manager_.GetPolicyHandler().OnActivateApp(application_id, + correlation_id()); return; } - DevicesApps devices_apps = FindAllAppOnParticularDevice(app->device()); - if (!devices_apps.first && devices_apps.second.empty()) { + connection_handler::DeviceHandle device_handle = app_to_activate->device(); + ApplicationSharedPtr foreground_v4_app = get_foreground_app(device_handle); + V4ProtoApps v4_proto_apps = get_v4_proto_apps(device_handle); + + if (!foreground_v4_app && v4_proto_apps.empty()) { LOG4CXX_ERROR(logger_, "Can't find regular foreground app with the same " "connection id:" - << app->device()); + << device_handle); SendResponse(false, correlation_id(), SDL_ActivateApp, NO_APPS_REGISTERED); return; } - if (!app->IsRegistered()) { - if (devices_apps.first) { - MessageHelper::SendLaunchApp(devices_apps.first->app_id(), - app->SchemaUrl(), - app->PackageName(), - application_manager_); - } else { - std::vector<ApplicationSharedPtr>::const_iterator it = - devices_apps.second.begin(); - for (; it != devices_apps.second.end(); ++it) { - MessageHelper::SendLaunchApp((*it)->app_id(), - app->SchemaUrl(), - app->PackageName(), - application_manager_); - } - } - subscribe_on_event(BasicCommunication_OnAppRegistered); + LOG4CXX_DEBUG(logger_, + "Application is not registered yet. " + "Sending launch request."); + + if (foreground_v4_app) { + LOG4CXX_DEBUG(logger_, "Sending request to foreground application."); + MessageHelper::SendLaunchApp(foreground_v4_app->app_id(), + app_to_activate->SchemaUrl(), + app_to_activate->PackageName(), + application_manager_); } else { - if (devices_apps.first) { - MessageHelper::SendLaunchApp(devices_apps.first->app_id(), - app->SchemaUrl(), - app->PackageName(), - application_manager_); - } else { - const uint32_t application_id = app_id(); - application_manager_.GetPolicyHandler().OnActivateApp(application_id, - correlation_id()); - } + LOG4CXX_DEBUG(logger_, + "No preffered (foreground) application is found. " + "Sending request to all v4 applications."); + std::for_each(v4_proto_apps.begin(), + v4_proto_apps.end(), + SendLaunchApp(app_to_activate, application_manager_)); } + + subscribe_on_event(BasicCommunication_OnAppRegistered); } void SDLActivateAppRequest::onTimeOut() { @@ -135,47 +193,56 @@ void SDLActivateAppRequest::on_event(const event_engine::Event& event) { } uint32_t SDLActivateAppRequest::app_id() const { - if ((*message_).keyExists(strings::msg_params)) { - if ((*message_)[strings::msg_params].keyExists(strings::app_id)) { - return (*message_)[strings::msg_params][strings::app_id].asUInt(); - } + using namespace strings; + if (!(*message_).keyExists(msg_params)) { + LOG4CXX_DEBUG(logger_, msg_params << " section is absent in the message."); + return 0; + } + if (!(*message_)[msg_params].keyExists(strings::app_id)) { + LOG4CXX_DEBUG(logger_, + strings::app_id << " section is absent in the message."); + return 0; } - LOG4CXX_DEBUG(logger_, "app_id section is absent in the message."); - return 0; + return (*message_)[msg_params][strings::app_id].asUInt(); } uint32_t SDLActivateAppRequest::hmi_app_id( const smart_objects::SmartObject& so) const { - if (so.keyExists(strings::params)) { - if (so[strings::msg_params].keyExists(strings::application)) { - if (so[strings::msg_params][strings::application].keyExists( - strings::app_id)) { - return so[strings::msg_params][strings::application][strings::app_id] - .asUInt(); - } - } + using namespace strings; + if (!so.keyExists(params)) { + LOG4CXX_DEBUG(logger_, params << " section is absent in the message."); + return 0; } - LOG4CXX_DEBUG(logger_, "Can't find app_id section is absent in the message."); - return 0; + if (!so[msg_params].keyExists(application)) { + LOG4CXX_DEBUG(logger_, application << " section is absent in the message."); + return 0; + } + if (so[msg_params][application].keyExists(strings::app_id)) { + LOG4CXX_DEBUG(logger_, + strings::app_id << " section is absent in the message."); + return 0; + } + return so[msg_params][application][strings::app_id].asUInt(); } -DevicesApps SDLActivateAppRequest::FindAllAppOnParticularDevice( - const connection_handler::DeviceHandle handle) { - DevicesApps apps; +SDLActivateAppRequest::V4ProtoApps SDLActivateAppRequest::get_v4_proto_apps( + const connection_handler::DeviceHandle handle) const { const ApplicationSet app_list = application_manager_.applications().GetData(); + V4ProtoApps v4_proto_apps; + std::copy_if(app_list.begin(), + app_list.end(), + std::back_inserter(v4_proto_apps), + ProtoV4AppsOnDevice(handle)); + return v4_proto_apps; +} - ApplicationSetIt it = app_list.begin(); - ApplicationSetIt it_end = app_list.end(); - - for (; it != it_end; ++it) { - if (handle == (*it)->device()) { - if ((*it)->is_foreground()) { - apps.first = *it; - } - apps.second.push_back(*it); - } - } - return apps; +ApplicationSharedPtr SDLActivateAppRequest::get_foreground_app( + const connection_handler::DeviceHandle handle) const { + V4ProtoApps v4_proto_apps = get_v4_proto_apps(handle); + V4ProtoApps::iterator foreground_app = + std::find_if(v4_proto_apps.begin(), v4_proto_apps.end(), ForegroundApp()); + return foreground_app != v4_proto_apps.end() ? *foreground_app + : ApplicationSharedPtr(); } } // namespace commands diff --git a/src/components/application_manager/test/include/application_manager/mock_application_manager.h b/src/components/application_manager/test/include/application_manager/mock_application_manager.h index ff21958404..6ad8aeb250 100644 --- a/src/components/application_manager/test/include/application_manager/mock_application_manager.h +++ b/src/components/application_manager/test/include/application_manager/mock_application_manager.h @@ -233,6 +233,12 @@ class MockApplicationManager : public application_manager::ApplicationManager { MOCK_METHOD1(UnsubscribeAppFromWayPoints, void(const uint32_t)); MOCK_CONST_METHOD0(IsAnyAppSubscribedForWayPoints, bool()); MOCK_CONST_METHOD0(GetAppsSubscribedForWayPoints, const std::set<int32_t>()); + MOCK_CONST_METHOD1( + WaitingApplicationByID, + application_manager::ApplicationConstSharedPtr(const uint32_t)); + MOCK_CONST_METHOD0( + AppsWaitingForRegistration, + DataAccessor<application_manager::AppsWaitRegistrationSet>()); }; } // namespace application_manager_test |