diff options
23 files changed, 454 insertions, 42 deletions
diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h index 1ab0ddafec..df6449aa41 100644 --- a/src/components/application_manager/include/application_manager/application.h +++ b/src/components/application_manager/include/application_manager/application.h @@ -62,6 +62,8 @@ typedef int32_t ErrorCode; class UsageStatistics; +class DisplayCapabilitiesBuilder; + enum APIVersion { kUnknownAPI = -1, kAPIV0 = 0, @@ -415,6 +417,11 @@ class DynamicApplicationData { virtual DataAccessor<WindowParamsMap> window_optional_params_map() const = 0; /* + * @brief Retrieves display capabilities builder + */ + virtual DisplayCapabilitiesBuilder& display_capabilities_builder() = 0; + + /* * @brief Retrieve application commands */ virtual DataAccessor<CommandsMap> commands_map() const = 0; diff --git a/src/components/application_manager/include/application_manager/application_data_impl.h b/src/components/application_manager/include/application_manager/application_data_impl.h index ebd2797065..6df1f2b8c5 100644 --- a/src/components/application_manager/include/application_manager/application_data_impl.h +++ b/src/components/application_manager/include/application_manager/application_data_impl.h @@ -35,6 +35,7 @@ #include <string> #include "application_manager/application.h" +#include "application_manager/display_capabilities_builder.h" #include "interfaces/MOBILE_API.h" #include "smart_objects/smart_object.h" #include "utils/lock.h" @@ -251,6 +252,8 @@ class DynamicApplicationDataImpl : public virtual Application { DataAccessor<WindowParamsMap> window_optional_params_map() const; + DisplayCapabilitiesBuilder& display_capabilities_builder(); + /* * @brief Sets perform interaction state * @@ -321,6 +324,7 @@ class DynamicApplicationDataImpl : public virtual Application { uint32_t is_perform_interaction_active_; bool is_reset_global_properties_active_; int32_t perform_interaction_mode_; + DisplayCapabilitiesBuilder display_capabilities_builder_; private: void SetGlobalProperties( diff --git a/src/components/application_manager/include/application_manager/display_capabilities_builder.h b/src/components/application_manager/include/application_manager/display_capabilities_builder.h new file mode 100644 index 0000000000..529c9a32c1 --- /dev/null +++ b/src/components/application_manager/include/application_manager/display_capabilities_builder.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_DISPLAY_CAPABILITIES_BUILDER_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_DISPLAY_CAPABILITIES_BUILDER_H_ +#include "application_manager/application.h" + +namespace application_manager { +/** + * @brief DisplayCapabilitiesBuilder utility class used for building cached + * notification, which is sent to mobile on resumption finish + */ +class DisplayCapabilitiesBuilder { + typedef std::function<void(Application&, const smart_objects::SmartObject)> + ResumeCallback; + + public: + /** + * @brief DisplayCapabilitiesBuilder class constructor + * @param Application reference to application owner + */ + DisplayCapabilitiesBuilder(Application& application); + + /** + * @brief InitBuilder initialize builder with callback and windows to be + * restored + * @param resume_callback callback to be called when notifications for all + * windows have been received + * @param windows_info SO containing data of windows to be restored + */ + void InitBuilder(ResumeCallback resume_callback, + const smart_objects::SmartObject& windows_info); + + /** + * @brief UpdateDisplayCapabilities update cached notification + * @param display_capabilities to update cached notification with + */ + void UpdateDisplayCapabilities( + const smart_objects::SmartObject& display_capabilities); + + /** + * @brief ResetDisplayCapabilities resets stored notification + */ + void ResetDisplayCapabilities(); + + /** + * @brief StopWaitingForWindow stop waiting for window resumption by removing + * window_id from windows pending resumption + * @param window_id window id to be removed + */ + void StopWaitingForWindow(const WindowID window_id); + + /** + * @brief retreives stored notification data + */ + const smart_objects::SmartObjectSPtr display_capabilities() const; + + private: + smart_objects::SmartObjectSPtr display_capabilities_; + typedef std::set<WindowID> WindowIDsToResume; + WindowIDsToResume window_ids_to_resume_; + Application& owner_; + ResumeCallback resume_callback_; + sync_primitives::Lock display_capabilities_lock_; +}; +} // namespace application_manager +#endif diff --git a/src/components/application_manager/include/application_manager/message_helper.h b/src/components/application_manager/include/application_manager/message_helper.h index 93901f03e4..db7b39dfe4 100644 --- a/src/components/application_manager/include/application_manager/message_helper.h +++ b/src/components/application_manager/include/application_manager/message_helper.h @@ -938,6 +938,16 @@ class MessageHelper { static void BroadcastCapabilityUpdate(smart_objects::SmartObject& msg_params, ApplicationManager& app_mngr); + /** + * @brief CreateDisplayCapabilityUpdateToMobile creates notification with + * updated display capabilities acccoring to message type + * @param system_capabilities SO containing notification data + * @param app reference to application + * @return shared ptr to notification SO + */ + static smart_objects::SmartObjectSPtr CreateDisplayCapabilityUpdateToMobile( + const smart_objects::SmartObject& system_capabilities, Application& app); + private: /** * @brief Allows to fill SO according to the current permissions. diff --git a/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h b/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h index 6b64fcdb6e..11b1bcf926 100644 --- a/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h +++ b/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h @@ -250,7 +250,7 @@ class ResumeCtrl { * @param application - application to restore hmi level * and audio streaming state */ - virtual void StartAppHmiStateResumption( + virtual bool StartAppHmiStateResumption( application_manager::ApplicationSharedPtr application) = 0; /** @@ -299,6 +299,9 @@ class ResumeCtrl { virtual int32_t GetSavedAppHmiLevel(const std::string& app_id, const std::string& device_id) const = 0; + virtual void StartWaitingForDisplayCapabilitiesUpdate( + app_mngr::ApplicationSharedPtr application) = 0; + virtual time_t LaunchTime() const = 0; #ifdef BUILD_TESTS diff --git a/src/components/application_manager/include/application_manager/resumption/resume_ctrl_impl.h b/src/components/application_manager/include/application_manager/resumption/resume_ctrl_impl.h index 532e04b828..5e6fb58671 100644 --- a/src/components/application_manager/include/application_manager/resumption/resume_ctrl_impl.h +++ b/src/components/application_manager/include/application_manager/resumption/resume_ctrl_impl.h @@ -261,8 +261,9 @@ class ResumeCtrlImpl : public ResumeCtrl, * @brief Resume HMI Level and audio streaming state if needed * @param application - application to restore hmi level * and audio streaming state + * @return true if success otherwise false */ - void StartAppHmiStateResumption( + bool StartAppHmiStateResumption( app_mngr::ApplicationSharedPtr application) OVERRIDE; /** @@ -307,6 +308,9 @@ class ResumeCtrlImpl : public ResumeCtrl, int32_t GetSavedAppHmiLevel(const std::string& app_id, const std::string& device_id) const OVERRIDE; + void StartWaitingForDisplayCapabilitiesUpdate( + app_mngr::ApplicationSharedPtr application) OVERRIDE; + /** * @brief geter for launch_time_ * @return value of launch_time_ @@ -603,6 +607,16 @@ class ResumeCtrlImpl : public ResumeCtrl, app_mngr::ApplicationConstSharedPtr application) const; /** + * @brief Constructs and sends system capability mobile notification + * + * @param app to send display capabilities updated + * @param display_capabilities SO containing notification data + */ + void ProcessSystemCapabilityUpdated( + app_mngr::Application& app, + const smart_objects::SmartObject& display_capabilities); + + /** *@brief Mapping applications to time_stamps * wait for timer to resume HMI Level * diff --git a/src/components/application_manager/include/application_manager/smart_object_keys.h b/src/components/application_manager/include/application_manager/smart_object_keys.h index a03d6c4931..888cd53c0a 100644 --- a/src/components/application_manager/include/application_manager/smart_object_keys.h +++ b/src/components/application_manager/include/application_manager/smart_object_keys.h @@ -175,6 +175,7 @@ extern const char* video_streaming_state; extern const char* system_context; extern const char* window_name; extern const char* window_type; +extern const char* window_capabilities; extern const char* associated_service_type; extern const char* duplicate_updates_from_window_id; extern const char* speech_capabilities; diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/on_bc_system_capability_updated_notification_from_hmi.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/on_bc_system_capability_updated_notification_from_hmi.h index 00fa8efbf4..39b5c3aee3 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/on_bc_system_capability_updated_notification_from_hmi.h +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/on_bc_system_capability_updated_notification_from_hmi.h @@ -72,6 +72,11 @@ class OnBCSystemCapabilityUpdatedNotificationFromHMI void Run() FINAL; private: + enum ProcessSystemDisplayCapabilitiesResult { + SUCCESS, + FAIL, + CAPABILITIES_CACHED + }; /** * @brief ProcessSystemDisplayCapabilities processes provided display * capabilities according to its structure @@ -79,7 +84,7 @@ class OnBCSystemCapabilityUpdatedNotificationFromHMI * @return true if display capabilities have been processed properly, * otherwise returns false */ - bool ProcessSystemDisplayCapabilities( + ProcessSystemDisplayCapabilitiesResult ProcessSystemDisplayCapabilities( const smart_objects::SmartObject& display_capabilities); DISALLOW_COPY_AND_ASSIGN(OnBCSystemCapabilityUpdatedNotificationFromHMI); diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_bc_system_capability_updated_notification_from_hmi.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_bc_system_capability_updated_notification_from_hmi.cc index d9bb20ceef..863e31bae6 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_bc_system_capability_updated_notification_from_hmi.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_bc_system_capability_updated_notification_from_hmi.cc @@ -32,6 +32,7 @@ #include "sdl_rpc_plugin/commands/hmi/on_bc_system_capability_updated_notification_from_hmi.h" +#include "application_manager/display_capabilities_builder.h" #include "application_manager/message_helper.h" #include "interfaces/HMI_API.h" #include "interfaces/MOBILE_API.h" @@ -57,15 +58,17 @@ OnBCSystemCapabilityUpdatedNotificationFromHMI:: OnBCSystemCapabilityUpdatedNotificationFromHMI:: ~OnBCSystemCapabilityUpdatedNotificationFromHMI() {} -bool OnBCSystemCapabilityUpdatedNotificationFromHMI:: - ProcessSystemDisplayCapabilities( - const smart_objects::SmartObject& display_capabilities) { +OnBCSystemCapabilityUpdatedNotificationFromHMI:: + ProcessSystemDisplayCapabilitiesResult + OnBCSystemCapabilityUpdatedNotificationFromHMI:: + ProcessSystemDisplayCapabilities( + const smart_objects::SmartObject& display_capabilities) { LOG4CXX_AUTO_TRACE(logger_); if (!(*message_)[strings::msg_params].keyExists(strings::app_id)) { LOG4CXX_DEBUG(logger_, "Updating general display capabilities"); hmi_capabilities_.set_system_display_capabilities(display_capabilities); - return true; + return ProcessSystemDisplayCapabilitiesResult::SUCCESS; } const auto app_id = @@ -74,7 +77,7 @@ bool OnBCSystemCapabilityUpdatedNotificationFromHMI:: if (!app) { LOG4CXX_ERROR(logger_, "Application with app_id " << app_id << " is not registered"); - return false; + return ProcessSystemDisplayCapabilitiesResult::FAIL; } LOG4CXX_DEBUG(logger_, "Updating display capabilities for app " << app_id); @@ -84,8 +87,14 @@ bool OnBCSystemCapabilityUpdatedNotificationFromHMI:: (*message_)[strings::params][strings::connection_key] = (*message_)[strings::msg_params][strings::app_id]; (*message_)[strings::msg_params].erase(strings::app_id); + if (app->is_resuming()) { + LOG4CXX_DEBUG(logger_, "Application is resuming"); + app->display_capabilities_builder().UpdateDisplayCapabilities( + display_capabilities); + return ProcessSystemDisplayCapabilitiesResult::CAPABILITIES_CACHED; + } - return true; + return ProcessSystemDisplayCapabilitiesResult::SUCCESS; } void OnBCSystemCapabilityUpdatedNotificationFromHMI::Run() { @@ -100,12 +109,17 @@ void OnBCSystemCapabilityUpdatedNotificationFromHMI::Run() { if (mobile_apis::SystemCapabilityType::DISPLAY == system_capability[strings::system_capability_type].asInt() && system_capability.keyExists(strings::display_capabilities)) { - if (!ProcessSystemDisplayCapabilities( - system_capability[strings::display_capabilities])) { + const auto result = ProcessSystemDisplayCapabilities( + system_capability[strings::display_capabilities]); + if (ProcessSystemDisplayCapabilitiesResult::FAIL == result) { LOG4CXX_ERROR(logger_, "Failed to process display capabilities. Notification will " "be ignored"); return; + } else if (ProcessSystemDisplayCapabilitiesResult::CAPABILITIES_CACHED == + result) { + LOG4CXX_TRACE(logger_, "Capabilities are being cached for resuming app"); + return; } } diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_system_capability_updated_notification.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_system_capability_updated_notification.cc index 20dae7224f..e4951a090a 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_system_capability_updated_notification.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_system_capability_updated_notification.cc @@ -2,6 +2,7 @@ #include "application_manager/app_service_manager.h" #include "application_manager/application_manager.h" +#include "application_manager/display_capabilities_builder.h" #include "application_manager/helpers/application_helper.h" #include "application_manager/message_helper.h" #include "sdl_rpc_plugin/extensions/system_capability_app_extension.h" @@ -207,8 +208,15 @@ void OnSystemCapabilityUpdatedNotification::Run() { if (mobile_apis::SystemCapabilityType::DISPLAY == system_capability_type) { LOG4CXX_DEBUG(logger_, "Using common display capabilities"); auto capabilities = hmi_capabilities_.system_display_capabilities(); - - if (app->display_capabilities()) { + if (app->is_resuming()) { + LOG4CXX_DEBUG(logger_, + "Application " + << app->app_id() + << " is resuming. Providing cached capabilities"); + auto display_caps = + app->display_capabilities_builder().display_capabilities(); + capabilities = display_caps.get(); + } else if (app->display_capabilities()) { LOG4CXX_DEBUG(logger_, "Application " << app->app_id() << " has specific display capabilities"); diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc index a772e24513..499087a42d 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc @@ -164,7 +164,7 @@ struct IsSameNickname { } private: - const custom_str::CustomString app_id_; + const custom_str::CustomString& app_id_; }; } // namespace @@ -244,6 +244,9 @@ void RegisterAppInterfaceRequest::Run() { SendResponse(false, mobile_apis::Result::APPLICATION_REGISTERED_ALREADY); return; } + // cache the original app ID (for legacy behavior) + const std::string policy_app_id = + application_manager_.GetCorrectMobileIDFromMessage(message_); const smart_objects::SmartObject& msg_params = (*message_)[strings::msg_params]; @@ -828,6 +831,10 @@ void RegisterAppInterfaceRequest::SendRegisterAppInterfaceResponseToMobile( application->mac_address()); } + if (resumption) { + resumer.StartWaitingForDisplayCapabilitiesUpdate(application); + } + AppHmiTypes hmi_types; if ((*message_)[strings::msg_params].keyExists(strings::app_hmi_type)) { smart_objects::SmartArray* hmi_types_ptr = @@ -864,13 +871,13 @@ void RegisterAppInterfaceRequest::SendRegisterAppInterfaceResponseToMobile( // Start PTU after successfull registration // Sends OnPermissionChange notification to mobile right after RAI response // and HMI level set-up - GetPolicyHandler().OnAppRegisteredOnMobile(application->mac_address(), - application->policy_app_id()); - - if (result_code != mobile_apis::Result::RESUME_FAILED) { - resumer.StartResumption(application, hash_id); - } else { - resumer.StartResumptionOnlyHMILevel(application); + GetPolicyHandler().OnAppRegisteredOnMobile(application->policy_app_id()); + if (resumption) { + if (result_code != mobile_apis::Result::RESUME_FAILED) { + resumer.StartResumption(application, hash_id); + } else { + resumer.StartResumptionOnlyHMILevel(application); + } } // By default app subscribed to CUSTOM_BUTTON diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_system_capability_updated_notification_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_system_capability_updated_notification_test.cc index bf3eca3e88..37cbe701a3 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_system_capability_updated_notification_test.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/on_system_capability_updated_notification_test.cc @@ -33,6 +33,7 @@ #include "mobile/on_system_capability_updated_notification.h" #include "application_manager/commands/commands_test.h" +#include "application_manager/display_capabilities_builder.h" #include "gtest/gtest.h" #include "sdl_rpc_plugin/extensions/system_capability_app_extension.h" #include "sdl_rpc_plugin/sdl_rpc_plugin.h" @@ -111,6 +112,9 @@ TEST_F( QueryInterface(sdl_rpc_plugin::SystemCapabilityAppExtension:: SystemCapabilityAppExtensionUID)) .WillByDefault(Return(system_capability_app_extension)); + application_manager::DisplayCapabilitiesBuilder builder(*mock_app_); + ON_CALL(*mock_app_, display_capabilities_builder()) + .WillByDefault(ReturnRef(builder)); EXPECT_CALL( mock_rpc_service_, diff --git a/src/components/application_manager/src/application_data_impl.cc b/src/components/application_manager/src/application_data_impl.cc index f63551da33..9872bf15a9 100644 --- a/src/components/application_manager/src/application_data_impl.cc +++ b/src/components/application_manager/src/application_data_impl.cc @@ -196,7 +196,8 @@ DynamicApplicationDataImpl::DynamicApplicationDataImpl() , window_params_map_lock_ptr_(std::make_shared<sync_primitives::Lock>()) , is_perform_interaction_active_(false) , is_reset_global_properties_active_(false) - , perform_interaction_mode_(-1) {} + , perform_interaction_mode_(-1) + , display_capabilities_builder_(*this) {} DynamicApplicationDataImpl::~DynamicApplicationDataImpl() { if (help_prompt_) { @@ -679,6 +680,12 @@ void DynamicApplicationDataImpl::AddWindowInfo( } } +DisplayCapabilitiesBuilder& +DynamicApplicationDataImpl::display_capabilities_builder() { + LOG4CXX_AUTO_TRACE(logger_); + return display_capabilities_builder_; +} + void DynamicApplicationDataImpl::RemoveWindowInfo(const WindowID window_id) { LOG4CXX_AUTO_TRACE(logger_); window_params_map_.erase(window_id); diff --git a/src/components/application_manager/src/display_capabilities_builder.cc b/src/components/application_manager/src/display_capabilities_builder.cc new file mode 100644 index 0000000000..e650d68dcb --- /dev/null +++ b/src/components/application_manager/src/display_capabilities_builder.cc @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2019, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "application_manager/display_capabilities_builder.h" +#include "application_manager/message_helper.h" +#include "application_manager/smart_object_keys.h" +namespace application_manager { + +CREATE_LOGGERPTR_GLOBAL(logger_, "DisplayCapabilitiesBuilder") + +const WindowID kMainWindowID = 0; + +DisplayCapabilitiesBuilder::DisplayCapabilitiesBuilder(Application& application) + : owner_(application) { + LOG4CXX_AUTO_TRACE(logger_); +} + +void DisplayCapabilitiesBuilder::InitBuilder( + DisplayCapabilitiesBuilder::ResumeCallback resume_callback, + const smart_objects::SmartObject& windows_info) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(display_capabilities_lock_); + resume_callback_ = resume_callback; + window_ids_to_resume_.insert(kMainWindowID); + for (size_t i = 0; i < windows_info.length(); ++i) { + auto window_id = windows_info[i][strings::window_id].asInt(); + LOG4CXX_DEBUG(logger_, + "Inserting " << window_id << " to waiting container"); + window_ids_to_resume_.insert(window_id); + } +} + +void DisplayCapabilitiesBuilder::UpdateDisplayCapabilities( + const smart_objects::SmartObject& incoming_display_capabilities) { + LOG4CXX_AUTO_TRACE(logger_); + using namespace smart_objects; + sync_primitives::AutoLock lock(display_capabilities_lock_); + + if (!display_capabilities_) { + display_capabilities_ = std::make_shared<SmartObject>(SmartType_Array); + } + + // As per v6.0, only single display is supported + auto cur_window_caps = + (*display_capabilities_)[0][strings::window_capabilities]; + + const auto& inc_window_caps = + incoming_display_capabilities[0][strings::window_capabilities]; + + for (size_t i = 0; i < inc_window_caps.length(); ++i) { + const WindowID window_id = + inc_window_caps[i].keyExists(strings::window_id) + ? inc_window_caps[i][strings::window_id].asInt() + : kMainWindowID; + if (window_ids_to_resume_.end() != window_ids_to_resume_.find(window_id)) { + cur_window_caps[cur_window_caps.length()] = inc_window_caps[i]; + LOG4CXX_DEBUG(logger_, "Stop waiting for: " << window_id); + window_ids_to_resume_.erase(window_id); + } + } + + *display_capabilities_ = incoming_display_capabilities; + (*display_capabilities_)[0][strings::window_capabilities] = cur_window_caps; + + if (window_ids_to_resume_.empty()) { + LOG4CXX_TRACE(logger_, "Invoking resume callback"); + resume_callback_(owner_, *display_capabilities_); + display_capabilities_.reset(); + } +} // namespace application_manager + +const smart_objects::SmartObjectSPtr +DisplayCapabilitiesBuilder::display_capabilities() const { + LOG4CXX_AUTO_TRACE(logger_); + return display_capabilities_; +} + +void DisplayCapabilitiesBuilder::ResetDisplayCapabilities() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(display_capabilities_lock_); + display_capabilities_.reset(); +} + +void DisplayCapabilitiesBuilder::StopWaitingForWindow( + const WindowID window_id) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(display_capabilities_lock_); + LOG4CXX_DEBUG(logger_, + "Window id " << window_id << " will be erased due to failure"); + window_ids_to_resume_.erase(window_id); + if (window_ids_to_resume_.empty()) { + LOG4CXX_TRACE(logger_, + window_id << " was the last window pending resumption. " + "Invoking resume callback"); + resume_callback_(owner_, *display_capabilities_); + display_capabilities_.reset(); + } +} +} // namespace application_manager diff --git a/src/components/application_manager/src/message_helper/message_helper.cc b/src/components/application_manager/src/message_helper/message_helper.cc index 105e1115a9..d3896115ee 100644 --- a/src/components/application_manager/src/message_helper/message_helper.cc +++ b/src/components/application_manager/src/message_helper/message_helper.cc @@ -357,6 +357,33 @@ smart_objects::SmartObjectSPtr MessageHelper::CreateMessageForHMI( return message; } +smart_objects::SmartObjectSPtr +MessageHelper::CreateDisplayCapabilityUpdateToMobile( + const smart_objects::SmartObject& display_capabilities, Application& app) { + LOG4CXX_AUTO_TRACE(logger_); + auto message = std::make_shared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + + (*message)[strings::params][strings::message_type] = + MessageType::kNotification; + (*message)[strings::params][strings::function_id] = + mobile_apis::FunctionID::OnSystemCapabilityUpdatedID; + (*message)[strings::params][strings::connection_key] = app.app_id(); + (*message)[strings::params][strings::protocol_type] = + commands::CommandImpl::mobile_protocol_type_; + (*message)[strings::params][strings::protocol_version] = + commands::CommandImpl::protocol_version_; + + smart_objects::SmartObject system_capability(smart_objects::SmartType_Map); + system_capability[strings::system_capability_type] = + static_cast<int32_t>(mobile_apis::SystemCapabilityType::DISPLAY); + system_capability[strings::display_capabilities] = display_capabilities; + (*message)[strings::msg_params][strings::system_capability] = + system_capability; + + return message; +} + void MessageHelper::BroadcastCapabilityUpdate( smart_objects::SmartObject& msg_params, ApplicationManager& app_mngr) { LOG4CXX_AUTO_TRACE(logger_); diff --git a/src/components/application_manager/src/resumption/resume_ctrl_impl.cc b/src/components/application_manager/src/resumption/resume_ctrl_impl.cc index 6f4d9d22b6..0e1220edf2 100644 --- a/src/components/application_manager/src/resumption/resume_ctrl_impl.cc +++ b/src/components/application_manager/src/resumption/resume_ctrl_impl.cc @@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "application_manager/resumption/resume_ctrl_impl.h" +#include "application_manager/display_capabilities_builder.h" #include <algorithm> #include <fstream> @@ -241,6 +242,18 @@ void ResumeCtrlImpl::RestoreWidgetsHMIState( << correlation_id << " not found"); return; } + + const auto& msg_params = (*request->second)[strings::msg_params]; + const auto hmi_app_id = msg_params[strings::app_id].asInt(); + auto application = application_manager_.application_by_hmi_app(hmi_app_id); + if (!application) { + LOG4CXX_ERROR(logger_, + "Application is not registered by hmi id: " << hmi_app_id); + requests_msg_.erase(request); + return; + } + const WindowID window_id = msg_params[strings::window_id].asInt(); + const auto result_code = static_cast<hmi_apis::Common_Result::eType>( response_message[strings::params][hmi_response::code].asInt()); if (hmi_apis::Common_Result::SUCCESS != result_code) { @@ -249,18 +262,11 @@ void ResumeCtrlImpl::RestoreWidgetsHMIState( << correlation_id << " failed with code: " << result_code); requests_msg_.erase(request); + auto& builder = application->display_capabilities_builder(); + builder.StopWaitingForWindow(window_id); return; } - const auto& msg_params = (*request->second)[strings::msg_params]; - const auto hmi_app_id = msg_params[strings::app_id].asInt(); - auto application = application_manager_.application_by_hmi_app(hmi_app_id); - if (!application) { - LOG4CXX_ERROR(logger_, - "Application is not registered by hmi id: " << hmi_app_id); - requests_msg_.erase(request); - return; - } smart_objects::SmartObject window_info(smart_objects::SmartType_Map); auto fill_optional_param = [&window_info, &msg_params](const std::string& key) { @@ -273,8 +279,6 @@ void ResumeCtrlImpl::RestoreWidgetsHMIState( const auto window_name = msg_params[strings::window_name].asString(); window_info[strings::window_name] = window_name; - - const WindowID window_id = msg_params[strings::window_id].asUInt(); application->AddWindowInfo(window_id, window_info); const auto window_type = static_cast<mobile_apis::WindowType::eType>( @@ -297,6 +301,18 @@ void ResumeCtrlImpl::RestoreWidgetsHMIState( requests_msg_.erase(request); } +void ResumeCtrlImpl::ProcessSystemCapabilityUpdated( + Application& app, const smart_objects::SmartObject& display_capabilities) { + LOG4CXX_AUTO_TRACE(logger_); + + auto notification = MessageHelper::CreateDisplayCapabilityUpdateToMobile( + display_capabilities, app); + + application_manager_.GetRPCService().ManageMobileCommand( + notification, commands::Command::SOURCE_SDL); + app.set_is_resuming(false); +} + bool ResumeCtrlImpl::SetupDefaultHMILevel(ApplicationSharedPtr application) { LOG4CXX_AUTO_TRACE(logger_); DCHECK_OR_RETURN(application, false); @@ -330,7 +346,9 @@ void ResumeCtrlImpl::ApplicationResumptiOnTimer() { LOG4CXX_ERROR(logger_, "Invalid app_id = " << *it); continue; } - StartAppHmiStateResumption(app); + if (!StartAppHmiStateResumption(app)) { + app->set_is_resuming(false); + } } is_resumption_active_ = false; waiting_for_timer_.clear(); @@ -573,18 +591,18 @@ void ResumeCtrlImpl::RetryResumption(const uint32_t app_id) { AddToResumptionTimerQueue(app_id); } -void ResumeCtrlImpl::StartAppHmiStateResumption( +bool ResumeCtrlImpl::StartAppHmiStateResumption( ApplicationSharedPtr application) { using namespace date_time; LOG4CXX_AUTO_TRACE(logger_); - DCHECK_OR_RETURN_VOID(application); + DCHECK_OR_RETURN(application, false); smart_objects::SmartObject saved_app; const std::string& device_mac = application->mac_address(); const bool result = resumption_storage_->GetSavedApplication( application->policy_app_id(), device_mac, saved_app); if (!result) { LOG4CXX_ERROR(logger_, "Application was not saved"); - return; + return false; } const bool is_hmi_level_applicable_to_resume = @@ -592,7 +610,7 @@ void ResumeCtrlImpl::StartAppHmiStateResumption( if (!is_hmi_level_applicable_to_resume) { LOG4CXX_DEBUG(logger_, "No applicable HMI level found for resuming"); - return; + return false; } const bool is_resume_allowed_by_low_voltage = @@ -607,18 +625,20 @@ void ResumeCtrlImpl::StartAppHmiStateResumption( if (restore_hmi_level_allowed) { LOG4CXX_INFO(logger_, "Resume application " << application->policy_app_id()); - RestoreAppHMIState(application); + bool result = RestoreAppHMIState(application); if (mobile_apis::HMILevel::eType::INVALID_ENUM != application->deferred_resumption_hmi_level()) { // the application has not been fully resumed - return; + return false; } RemoveApplicationFromSaved(application); + return result; } else { LOG4CXX_INFO( logger_, "Do not need to resume application " << application->policy_app_id()); } + return true; } void ResumeCtrlImpl::ResetLaunchTime() { @@ -728,6 +748,28 @@ bool ResumeCtrlImpl::RestoreApplicationData(ApplicationSharedPtr application) { return result; } +void ResumeCtrlImpl::StartWaitingForDisplayCapabilitiesUpdate( + app_mngr::ApplicationSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + smart_objects::SmartObject saved_app(smart_objects::SmartType_Map); + resumption_storage_->GetSavedApplication( + application->policy_app_id(), application->mac_address(), saved_app); + auto resume_callback = + [this](Application& app, + const smart_objects::SmartObject& display_capabilities) -> void { + LOG4CXX_AUTO_TRACE(logger_); + ProcessSystemCapabilityUpdated(app, display_capabilities); + }; + auto& builder = application->display_capabilities_builder(); + + smart_objects::SmartObject windows_info(smart_objects::SmartType_Null); + if (saved_app.keyExists(strings::windows_info)) { + windows_info = saved_app[strings::windows_info]; + } + builder.InitBuilder(resume_callback, windows_info); + application->set_is_resuming(true); +} + void ResumeCtrlImpl::AddFiles(ApplicationSharedPtr application, const smart_objects::SmartObject& saved_app) { LOG4CXX_AUTO_TRACE(logger_); diff --git a/src/components/application_manager/src/smart_object_keys.cc b/src/components/application_manager/src/smart_object_keys.cc index 319b06323d..4074de8486 100644 --- a/src/components/application_manager/src/smart_object_keys.cc +++ b/src/components/application_manager/src/smart_object_keys.cc @@ -142,6 +142,7 @@ const char* video_streaming_state = "videoStreamingState"; const char* system_context = "systemContext"; const char* window_name = "windowName"; const char* window_type = "type"; +const char* window_capabilities = "windowCapabilities"; const char* associated_service_type = "associatedServiceType"; const char* duplicate_updates_from_window_id = "duplicateUpdatesFromWindowID"; const char* speech_capabilities = "speechCapabilities"; diff --git a/src/components/application_manager/src/state_controller_impl.cc b/src/components/application_manager/src/state_controller_impl.cc index b8f9dcf31a..7b9fc72ef9 100644 --- a/src/components/application_manager/src/state_controller_impl.cc +++ b/src/components/application_manager/src/state_controller_impl.cc @@ -626,7 +626,6 @@ void StateControllerImpl::SetupRegularHmiState(ApplicationSharedPtr app, << "Send OnResumeAudioSource notification"); MessageHelper::SendOnResumeAudioSourceToHMI(app->app_id(), app_mngr_); } - app->set_is_resuming(false); HmiStatePtr new_state = app->CurrentHmiState(window_id); OnStateChanged(app, window_id, old_state, new_state); diff --git a/src/components/application_manager/test/include/application_manager/mock_application.h b/src/components/application_manager/test/include/application_manager/mock_application.h index 36c33da0d3..d4d644160b 100644 --- a/src/components/application_manager/test/include/application_manager/mock_application.h +++ b/src/components/application_manager/test/include/application_manager/mock_application.h @@ -34,6 +34,7 @@ #include <string> #include "application_manager/app_extension.h" #include "application_manager/application.h" +#include "application_manager/display_capabilities_builder.h" #include "application_manager/hmi_state.h" #include "application_manager/usage_statistics.h" #include "gmock/gmock.h" @@ -413,6 +414,8 @@ class MockApplication : public ::application_manager::Application { void((const ::application_manager::WindowID window_id))); MOCK_CONST_METHOD0(window_optional_params_map, DataAccessor< ::application_manager::WindowParamsMap>()); + MOCK_METHOD0(display_capabilities_builder, + application_manager::DisplayCapabilitiesBuilder&()); }; } // namespace application_manager_test diff --git a/src/components/application_manager/test/include/application_manager/mock_message_helper.h b/src/components/application_manager/test/include/application_manager/mock_message_helper.h index 4fd331bb3e..dff77009b4 100644 --- a/src/components/application_manager/test/include/application_manager/mock_message_helper.h +++ b/src/components/application_manager/test/include/application_manager/mock_message_helper.h @@ -331,6 +331,10 @@ class MockMessageHelper { ApplicationSharedPtr application, ApplicationManager& app_manager, const smart_objects::SmartObject& windows_info)); + MOCK_METHOD2( + CreateDisplayCapabilityUpdateToMobile, + smart_objects::SmartObjectSPtr(const smart_objects::SmartObject&, + application_manager::Application&)); static MockMessageHelper* message_helper_mock(); }; diff --git a/src/components/application_manager/test/include/application_manager/mock_resume_ctrl.h b/src/components/application_manager/test/include/application_manager/mock_resume_ctrl.h index 01d286e22e..56c2ae3cd4 100644 --- a/src/components/application_manager/test/include/application_manager/mock_resume_ctrl.h +++ b/src/components/application_manager/test/include/application_manager/mock_resume_ctrl.h @@ -94,7 +94,7 @@ class MockResumeCtrl : public resumption::ResumeCtrl { MOCK_METHOD1(SetupDefaultHMILevel, bool(application_manager::ApplicationSharedPtr application)); MOCK_METHOD1(StartAppHmiStateResumption, - void(application_manager::ApplicationSharedPtr application)); + bool(application_manager::ApplicationSharedPtr application)); MOCK_METHOD3(SetAppHMIState, bool(application_manager::ApplicationSharedPtr application, const mobile_apis::HMILevel::eType hmi_level, @@ -108,6 +108,9 @@ class MockResumeCtrl : public resumption::ResumeCtrl { MOCK_METHOD1(RestoreWidgetsHMIState, void(const smart_objects::SmartObject& response_message)); + MOCK_METHOD1(StartWaitingForDisplayCapabilitiesUpdate, + void(application_manager::ApplicationSharedPtr application)); + #ifdef BUILD_TESTS MOCK_METHOD1(set_resumption_storage, void(std::shared_ptr<resumption::ResumptionData> mock_storage)); diff --git a/src/components/application_manager/test/mock_message_helper.cc b/src/components/application_manager/test/mock_message_helper.cc index ecaad48365..54b7e3c5d9 100644 --- a/src/components/application_manager/test/mock_message_helper.cc +++ b/src/components/application_manager/test/mock_message_helper.cc @@ -609,4 +609,11 @@ smart_objects::SmartObjectList MessageHelper::CreateUICreateWindowRequestsToHMI( return MockMessageHelper::message_helper_mock() ->CreateUICreateWindowRequestsToHMI(application, app_mngr, windows_info); } + +smart_objects::SmartObjectSPtr +MessageHelper::CreateDisplayCapabilityUpdateToMobile( + const smart_objects::SmartObject& system_capabilities, Application& app) { + return MockMessageHelper::message_helper_mock() + ->CreateDisplayCapabilityUpdateToMobile(system_capabilities, app); +} } // namespace application_manager diff --git a/src/components/application_manager/test/resumption/resume_ctrl_test.cc b/src/components/application_manager/test/resumption/resume_ctrl_test.cc index ca05e3fce5..899fc00846 100644 --- a/src/components/application_manager/test/resumption/resume_ctrl_test.cc +++ b/src/components/application_manager/test/resumption/resume_ctrl_test.cc @@ -35,6 +35,7 @@ #include "application_manager/application.h" #include "application_manager/application_manager_impl.h" +#include "application_manager/display_capabilities_builder.h" #include "application_manager/mock_app_extension.h" #include "application_manager/mock_application.h" #include "application_manager/mock_help_prompt_manager.h" @@ -664,6 +665,9 @@ TEST_F(ResumeCtrlTest, const auto hmi_requests = smart_objects::SmartObjectList(count_of_widgets, hmi_request); + DisplayCapabilitiesBuilder builder(*mock_app_); + ON_CALL(*mock_app_, display_capabilities_builder()) + .WillByDefault(ReturnRef(builder)); EXPECT_CALL( *application_manager::MockMessageHelper::message_helper_mock(), CreateUICreateWindowRequestsToHMI(_, _, saved_app[strings::windows_info])) @@ -692,6 +696,9 @@ TEST_F(ResumeCtrlTest, ON_CALL(mock_app_mngr_, application_by_hmi_app(kDefaultHmiAppId)) .WillByDefault(Return(mock_app_)); + DisplayCapabilitiesBuilder builder(*mock_app_); + ON_CALL(*mock_app_, display_capabilities_builder()) + .WillByDefault(ReturnRef(builder)); smart_objects::SmartObjectList requests; smart_objects::SmartObjectList responses; @@ -754,6 +761,10 @@ TEST_F(ResumeCtrlTest, RestoreWidgetsHMIState_HMIResponseWith_InvalidCorrId) { ON_CALL(mock_app_mngr_, application_by_hmi_app(kDefaultHmiAppId)) .WillByDefault(Return(mock_app_)); + DisplayCapabilitiesBuilder builder(*mock_app_); + ON_CALL(*mock_app_, display_capabilities_builder()) + .WillByDefault(ReturnRef(builder)); + smart_objects::SmartObjectList requests; const auto window_type = mobile_apis::WindowType::WIDGET; @@ -796,6 +807,13 @@ TEST_F(ResumeCtrlTest, RestoreWidgetsHMIState_HMIResponseWith_Unsuccess) { ON_CALL(mock_app_mngr_, application_by_hmi_app(kDefaultHmiAppId)) .WillByDefault(Return(mock_app_)); + DisplayCapabilitiesBuilder builder(*mock_app_); + smart_objects::SmartObject stub_window_info(smart_objects::SmartType_Null); + auto stub_resume_cb = [](Application&, const smart_objects::SmartObject&) {}; + builder.InitBuilder(stub_resume_cb, stub_window_info); + ON_CALL(*mock_app_, display_capabilities_builder()) + .WillByDefault(ReturnRef(builder)); + smart_objects::SmartObjectList requests; smart_objects::SmartObjectList responses; |