diff options
Diffstat (limited to 'src/components')
170 files changed, 6356 insertions, 296 deletions
diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h index ad7570955e..b4d8ca857e 100644 --- a/src/components/application_manager/include/application_manager/application.h +++ b/src/components/application_manager/include/application_manager/application.h @@ -946,6 +946,73 @@ class Application : public virtual InitialApplicationData, */ virtual const std::list<AppExtensionPtr>& Extensions() const = 0; + /** + * @brief Get cloud app endpoint for websocket connection + * @return cloud app endpoint + */ + virtual const std::string& cloud_app_endpoint() const = 0; + + /** + * @brief Get cloud app auth token to be used in connection handshake after + * websocket open. + * @return cloud app auth token + */ + virtual const std::string& auth_token() const = 0; + + /** + * @brief Get cloud app transport type. Defines the type of websocket + * connection used. + * @return cloud app transport type + */ + virtual const std::string& cloud_app_transport_type() const = 0; + + /** + * @brief Get hybrid app preference. Defines behaviour for when a similar + * mobile and cloud app are connected simultaneously. + * @return hybrid app preference + */ + virtual const mobile_apis::HybridAppPreference::eType& hybrid_app_preference() + const = 0; + + /** + * @brief Get cloud app certificate. Used for secured websocket connections. + * @return cloud app certificate. + */ + virtual const std::string& cloud_app_certificate() const = 0; + + /** + * @brief Check whether the given application is a cloud app. + * @return true if the application is a cloud application, false otherwise. + */ + virtual bool is_cloud_app() const = 0; + + /** + * @brief Set cloud app endpoint + */ + virtual void set_cloud_app_endpoint(const std::string& endpoint) = 0; + + /** + * @brief Set cloud app auth token + */ + virtual void set_auth_token(const std::string& auth_token) = 0; + + /** + * @brief Set cloud app transport type + */ + virtual void set_cloud_app_transport_type( + const std::string& transport_type) = 0; + + /** + * @brief Set hybrid app preference + */ + virtual void set_hybrid_app_preference( + const mobile_apis::HybridAppPreference::eType& hybrid_app_preference) = 0; + + /** + * @brief Set cloud app certificate + */ + virtual void set_cloud_app_certificate(const std::string& certificate) = 0; + protected: mutable sync_primitives::Lock hmi_states_lock_; diff --git a/src/components/application_manager/include/application_manager/application_impl.h b/src/components/application_manager/include/application_manager/application_impl.h index 8dc3b2da20..ff34d2a96a 100644 --- a/src/components/application_manager/include/application_manager/application_impl.h +++ b/src/components/application_manager/include/application_manager/application_impl.h @@ -409,6 +409,72 @@ class ApplicationImpl : public virtual Application, void SwapMobileMessageQueue(MobileMessageQueue& mobile_messages) OVERRIDE; + /** + * @brief Get cloud app endpoint for websocket connection + * @return cloud app endpoint + */ + const std::string& cloud_app_endpoint() const OVERRIDE; + + /** + * @brief Get cloud app auth token to be used in connection handshake after + * websocket open. + * @return cloud app auth token + */ + const std::string& auth_token() const OVERRIDE; + + /** + * @brief Get cloud app transport type. Defines the type of websocket + * connection used. + * @return cloud app transport type + */ + const std::string& cloud_app_transport_type() const OVERRIDE; + + /** + * @brief Get hybrid app preference. Defines behaviour for when a similar + * mobile and cloud app are connected simultaneously. + * @return hybrid app preference + */ + const mobile_apis::HybridAppPreference::eType& hybrid_app_preference() + const OVERRIDE; + + /** + * @brief Get cloud app certificate. Used for secured websocket connections. + * @return cloud app certificate. + */ + const std::string& cloud_app_certificate() const OVERRIDE; + + /** + * @brief Check whether the given application is a cloud app. + * @return true if the application is a cloud application, false otherwise. + */ + bool is_cloud_app() const OVERRIDE; + + /** + * @brief Set cloud app endpoint + */ + void set_cloud_app_endpoint(const std::string& endpoint) OVERRIDE; + + /** + * @brief Set cloud app auth token + */ + void set_auth_token(const std::string& auth_token) OVERRIDE; + + /** + * @brief Set cloud app transport type + */ + void set_cloud_app_transport_type(const std::string& transport_type) OVERRIDE; + + /** + * @brief Set hybrid app preference + */ + void set_hybrid_app_preference(const mobile_apis::HybridAppPreference::eType& + hybrid_app_preference) OVERRIDE; + + /** + * @brief Set cloud app certificate + */ + void set_cloud_app_certificate(const std::string& certificate) OVERRIDE; + protected: /** * @brief Clean up application folder. Persistent files will stay @@ -513,6 +579,13 @@ class ApplicationImpl : public virtual Application, std::list<AppExtensionPtr> extensions_; + // Cloud app properties + std::string endpoint_; + std::string auth_token_; + std::string cloud_transport_type_; + mobile_apis::HybridAppPreference::eType hybrid_app_preference_; + std::string certificate_; + /** * @brief Defines number per time in seconds limits */ 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 6c111dbbb3..d72d03fa53 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 @@ -117,6 +117,14 @@ struct CommandParametersPermissions; typedef std::map<std::string, hmi_apis::Common_TransportType::eType> DeviceTypes; +struct AppIconInfo { + std::string endpoint; + bool pending_request; + AppIconInfo(); + AppIconInfo(std::string ws_endpoint, bool pending) + : endpoint(ws_endpoint), pending_request(pending) {} +}; + CREATE_LOGGERPTR_GLOBAL(logger_, "ApplicationManager") typedef std::shared_ptr<timer::Timer> TimerSPtr; @@ -156,6 +164,7 @@ class ApplicationManagerImpl bool Stop() OVERRIDE; DataAccessor<ApplicationSet> applications() const OVERRIDE; + DataAccessor<AppsWaitRegistrationSet> pending_applications() const OVERRIDE; ApplicationSharedPtr application(uint32_t app_id) const OVERRIDE; ApplicationSharedPtr active_application() const OVERRIDE; @@ -164,6 +173,10 @@ class ApplicationManagerImpl uint32_t hmi_app_id) const OVERRIDE; ApplicationSharedPtr application_by_policy_id( const std::string& policy_app_id) const OVERRIDE; + ApplicationSharedPtr application_by_name( + const std::string& app_name) const OVERRIDE; + ApplicationSharedPtr pending_application_by_policy_id( + const std::string& policy_app_id) const OVERRIDE; std::vector<ApplicationSharedPtr> applications_by_button( uint32_t button) OVERRIDE; @@ -194,6 +207,9 @@ class ApplicationManagerImpl void SendDriverDistractionState(ApplicationSharedPtr application); + void SendGetIconUrlNotifications(const uint32_t connection_key, + ApplicationSharedPtr application); + ApplicationSharedPtr application( const std::string& device_id, const std::string& policy_app_id) const OVERRIDE; @@ -360,6 +376,37 @@ class ApplicationManagerImpl void ConnectToDevice(const std::string& device_mac) OVERRIDE; void OnHMIStartedCooperation() OVERRIDE; + void DisconnectCloudApp(ApplicationSharedPtr app) OVERRIDE; + + void RefreshCloudAppInformation() OVERRIDE; + + void CreatePendingApplication( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info, + connection_handler::DeviceHandle device_id); + + void SetPendingApplicationState( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info); + + std::string PolicyIDByIconUrl(const std::string url) OVERRIDE; + + void SetIconFileFromSystemRequest(const std::string policy_id) OVERRIDE; + + /** + * @brief Notifies the applicaiton manager that a cloud connection status has + * updated and should trigger an UpdateAppList RPC to the HMI + */ + void OnConnectionStatusUpdated(); + + /** + * @brief Retrieve the current connection status of a cloud app + * @param app A cloud application + * @return The current CloudConnectionStatus of app + */ + hmi_apis::Common_CloudConnectionStatus::eType GetCloudAppConnectionStatus( + ApplicationConstSharedPtr app) const; + /* * @brief Returns unique correlation ID for HMI request * @@ -476,18 +523,12 @@ class ApplicationManagerImpl // typedef for Applications list typedef std::set<ApplicationSharedPtr, ApplicationsAppIdSorter> ApplictionSet; - typedef std::set<ApplicationSharedPtr, ApplicationsPolicyAppIdSorter> - AppsWaitRegistrationSet; - // typedef for Applications list iterator typedef ApplictionSet::iterator ApplictionSetIt; // typedef for Applications list const iterator typedef ApplictionSet::const_iterator ApplictionSetConstIt; - DataAccessor<AppsWaitRegistrationSet> apps_waiting_for_registration() const; - ApplicationConstSharedPtr waiting_app(const uint32_t hmi_id) const; - /** * @brief Notification from PolicyHandler about PTU. * Compares AppHMIType between saved in app and received from PTU. If they are @@ -962,6 +1003,14 @@ class ApplicationManagerImpl } }; + struct AppNamePredicate { + std::string app_name_; + AppNamePredicate(const std::string& app_name) : app_name_(app_name) {} + bool operator()(const ApplicationSharedPtr app) const { + return app ? app->name() == app_name_ : false; + } + }; + /** * @brief Sends UpdateAppList notification to HMI */ @@ -1449,6 +1498,13 @@ class ApplicationManagerImpl DeviceMap secondary_transport_devices_cache_; + mutable std::shared_ptr<sync_primitives::RecursiveLock> + pending_device_map_lock_ptr_; + std::map<std::string, std::string> pending_device_map_; + + sync_primitives::Lock app_icon_map_lock_ptr_; + std::map<std::string, AppIconInfo> app_icon_map_; + #ifdef TELEMETRY_MONITOR AMTelemetryObserver* metric_observer_; #endif // TELEMETRY_MONITOR @@ -1478,12 +1534,28 @@ class ApplicationManagerImpl void AddMockApplication(ApplicationSharedPtr mock_app); /** + * @brief Add a mock application to the pending application list without going + * through the formal registration process. Only for unit testing. + * @param mock_app the mock app to be added to the pending application list + */ + void AddMockPendingApplication(ApplicationSharedPtr mock_app); + + /** * @brief set a mock media manager without running Init(). Only for unit * testing. - * @param mock_app the mock app to be registered + * @param mock_media_manager the mock media manager to be assigned */ void SetMockMediaManager(media_manager::MediaManager* mock_media_manager); + /** + * @brief set a mock rpc service directly. Only for unit + * testing. + * @param mock_app the mock rpc service to be assigned + */ + void SetMockRPCService(rpc_service::RPCService* rpc_service) { + rpc_service_.reset(rpc_service); + } + virtual void SetPluginManager( std::unique_ptr<plugin_manager::RPCPluginManager>& plugin_manager) OVERRIDE { diff --git a/src/components/application_manager/include/application_manager/helpers/application_helper.h b/src/components/application_manager/include/application_manager/helpers/application_helper.h index 145bef659e..18267c9e7f 100644 --- a/src/components/application_manager/include/application_manager/helpers/application_helper.h +++ b/src/components/application_manager/include/application_manager/helpers/application_helper.h @@ -57,6 +57,18 @@ ApplicationSharedPtr FindApp(DataAccessor<ApplicationSet> accessor, return app; } +template <class UnaryPredicate> +ApplicationSharedPtr FindPendingApp( + DataAccessor<AppsWaitRegistrationSet> accessor, UnaryPredicate finder) { + AppsWaitRegistrationSet::iterator it = std::find_if( + accessor.GetData().begin(), accessor.GetData().end(), finder); + if (accessor.GetData().end() == it) { + return ApplicationSharedPtr(); + } + ApplicationSharedPtr app = *it; + return app; +} + /** * Helper function for lookup through applications list and returning all * applications satisfying predicate logic diff --git a/src/components/application_manager/include/application_manager/policies/policy_handler.h b/src/components/application_manager/include/application_manager/policies/policy_handler.h index c8f3bcf888..2b6919eac0 100644 --- a/src/components/application_manager/include/application_manager/policies/policy_handler.h +++ b/src/components/application_manager/include/application_manager/policies/policy_handler.h @@ -187,6 +187,8 @@ class PolicyHandler : public PolicyHandlerInterface, void GetUpdateUrls(const uint32_t service_type, EndpointUrls& out_end_points) OVERRIDE; virtual std::string GetLockScreenIconUrl() const OVERRIDE; + virtual std::string GetIconUrl( + const std::string& policy_app_id) const OVERRIDE; uint32_t NextRetryTimeout() OVERRIDE; /** @@ -398,6 +400,55 @@ class PolicyHandler : public PolicyHandlerInterface, custom_str::CustomString GetAppName( const std::string& policy_app_id) OVERRIDE; + /** + * @brief Get a list of enabled cloud applications + * @param enabled_apps List filled with the policy app id of each enabled + * cloud application + */ + void GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const OVERRIDE; + + /** + * @brief Checks if a given application is an enabled cloud application + * @param policy_app_id Unique application id + * @return true, if the application is an enabled cloud application, + * otherwise - false + */ + const bool CheckCloudAppEnabled( + const std::string& policy_app_id) const OVERRIDE; + + /** + * @brief Get cloud app policy information, all fields that aren't set for a + * given app will be filled with empty strings + * @param policy_app_id Unique application id + * @param enabled Whether or not the app is enabled + * @param endpoint Filled with the endpoint used to connect to the cloud + * application + * @param certificate Filled with the certificate used to for creating a + * secure connection to the cloud application + * @param auth_token Filled with the token used for authentication when + * reconnecting to the cloud app + * @param cloud_transport_type Filled with the transport type used by the + * cloud application (ex. "WSS") + * @param hybrid_app_preference Filled with the hybrid app preference for the + * cloud application set by the user + */ + bool GetCloudAppParameters(const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const OVERRIDE; + + /** + * @brief Callback for when a SetCloudAppProperties message is received from a + * mobile app + * @param message The SetCloudAppProperties message + */ + void OnSetCloudAppProperties( + const smart_objects::SmartObject& message) OVERRIDE; + virtual void OnUpdateHMIAppType( std::map<std::string, StringArray> app_hmi_types) OVERRIDE; @@ -406,6 +457,9 @@ class PolicyHandler : public PolicyHandlerInterface, #ifdef EXTERNAL_PROPRIETARY_MODE void OnCertificateDecrypted(bool is_succeeded) OVERRIDE; #endif // EXTERNAL_PROPRIETARY_MODE + void OnAuthTokenUpdated(const std::string& policy_app_id, + const std::string& auth_token); + virtual bool CanUpdate() OVERRIDE; virtual void OnDeviceConsentChanged(const std::string& device_id, diff --git a/src/components/application_manager/include/application_manager/policies/regular/policy_handler_observer.h b/src/components/application_manager/include/application_manager/policies/regular/policy_handler_observer.h index 07d234f036..68e7511b43 100644 --- a/src/components/application_manager/include/application_manager/policies/regular/policy_handler_observer.h +++ b/src/components/application_manager/include/application_manager/policies/regular/policy_handler_observer.h @@ -48,6 +48,9 @@ class PolicyHandlerObserver { return false; } + virtual void OnAuthTokenUpdated(const std::string& policy_app_id, + const std::string& auth_token) {} + virtual void OnPTUFinished(const bool ptu_result) {} virtual ~PolicyHandlerObserver() {} 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 6e32853a3d..2e8b02d06b 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 @@ -76,7 +76,7 @@ extern const char* ngn_media_screen_app_name; extern const char* vr_synonyms; extern const char* uses_vehicle_data; extern const char* is_media_application; -extern const char* greyOut; +extern const char* grey_out; extern const char* language_desired; extern const char* auto_activated_id; extern const char* app_type; @@ -188,6 +188,14 @@ extern const char* green; extern const char* blue; extern const char* display_layout; extern const char* icon_resumed; +extern const char* nicknames; +extern const char* enabled; +extern const char* auth_token; +extern const char* cloud_transport_type; +extern const char* hybrid_app_preference; +extern const char* is_cloud_application; +extern const char* cloud_connection_status; +extern const char* endpoint; // PutFile extern const char* sync_file_name; @@ -253,6 +261,7 @@ extern const char* fuel_level; extern const char* fuel_level_state; extern const char* instant_fuel_consumption; extern const char* fuel_range; +extern const char* cloud_app_vehicle_id; extern const char* external_temp; extern const char* turn_signal; extern const char* vin; diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/get_cloud_app_properties_request.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/get_cloud_app_properties_request.h new file mode 100644 index 0000000000..3d74a80dc2 --- /dev/null +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/get_cloud_app_properties_request.h @@ -0,0 +1,31 @@ +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_GET_CLOUD_APP_PROPERTIES_REQUEST_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_GET_CLOUD_APP_PROPERTIES_REQUEST_H_ + +#include "application_manager/commands/command_request_impl.h" + +namespace sdl_rpc_plugin { +namespace app_mngr = application_manager; + +namespace commands { + +class GetCloudAppPropertiesRequest + : public app_mngr::commands::CommandRequestImpl { + public: + GetCloudAppPropertiesRequest( + const app_mngr::commands::MessageSharedPtr& message, + app_mngr::ApplicationManager& application_manager, + app_mngr::rpc_service::RPCService& rpc_service, + app_mngr::HMICapabilities& hmi_capabilities, + policy::PolicyHandlerInterface& policy_handler); + virtual ~GetCloudAppPropertiesRequest(); + virtual void Run(); + virtual void on_event(const app_mngr::event_engine::Event& event); + + private: + DISALLOW_COPY_AND_ASSIGN(GetCloudAppPropertiesRequest); +}; // GetCloudAppPropertiesRequest + +} // namespace commands +} // namespace sdl_rpc_plugin + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_GET_CLOUD_APP_PROPERTIES_REQUEST_H_ diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/get_cloud_app_properties_response.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/get_cloud_app_properties_response.h new file mode 100644 index 0000000000..f716c7dcb5 --- /dev/null +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/get_cloud_app_properties_response.h @@ -0,0 +1,31 @@ +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_GET_CLOUD_APP_PROPERTIES_RESPONSE_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_GET_CLOUD_APP_PROPERTIES_RESPONSE_H_ + +#include "application_manager/commands/command_response_impl.h" + +namespace sdl_rpc_plugin { +namespace app_mngr = application_manager; + +namespace commands { + +class GetCloudAppPropertiesResponse + : public app_mngr::commands::CommandResponseImpl { + public: + GetCloudAppPropertiesResponse( + const app_mngr::commands::MessageSharedPtr& message, + app_mngr::ApplicationManager& application_manager, + app_mngr::rpc_service::RPCService& rpc_service, + app_mngr::HMICapabilities& hmi_capabilities, + policy::PolicyHandlerInterface& policy_handler); + virtual ~GetCloudAppPropertiesResponse(); + virtual void Run(); + + private: + DISALLOW_COPY_AND_ASSIGN(GetCloudAppPropertiesResponse); + +}; // GetCloudAppPropertiesResponse + +} // namespace commands +} // namespace sdl_rpc_plugin + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_GET_CLOUD_APP_PROPERTIES_RESPONSE_H_ diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/register_app_interface_request.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/register_app_interface_request.h index 542fdac5f8..91ee8ea813 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/register_app_interface_request.h +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/register_app_interface_request.h @@ -124,11 +124,14 @@ class RegisterAppInterfaceRequest /** * @brief Sends OnAppRegistered notification to HMI * - *@param application_impl application with changed HMI status - * + * @param app application with changed HMI status + * @param resumption If true, resumption-related parameters will be sent to + *the HMI + * @param need_restore_vr If resumption is true, whether or not VR commands + *should be resumed **/ void SendOnAppRegisteredNotificationToHMI( - const app_mngr::Application& application_impl, + app_mngr::ApplicationConstSharedPtr app, bool resumption = false, bool need_restore_vr = false); /* @@ -141,11 +144,14 @@ class RegisterAppInterfaceRequest /* * @brief Check new application parameters (name, tts, vr) for * coincidence with already known parameters of registered applications + * @param out_duplicate_apps In the case other apps was found with duplicate + * names, this field will be filled with a list of said apps * * return SUCCESS if there is no coincidence of app.name/TTS/VR synonyms, * otherwise appropriate error code returns - */ - mobile_apis::Result::eType CheckCoincidence(); + */ + mobile_apis::Result::eType CheckCoincidence( + std::vector<app_mngr::ApplicationSharedPtr>& out_duplicate_apps); /* * @brief Predicate for using with CheckCoincidence method to compare with VR diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_request.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_request.h new file mode 100644 index 0000000000..a3a3ea12f9 --- /dev/null +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_request.h @@ -0,0 +1,31 @@ +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_SET_CLOUD_APP_PROPERTIES_REQUEST_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_SET_CLOUD_APP_PROPERTIES_REQUEST_H_ + +#include "application_manager/commands/command_request_impl.h" + +namespace sdl_rpc_plugin { +namespace app_mngr = application_manager; + +namespace commands { + +class SetCloudAppPropertiesRequest + : public app_mngr::commands::CommandRequestImpl { + public: + SetCloudAppPropertiesRequest( + const app_mngr::commands::MessageSharedPtr& message, + app_mngr::ApplicationManager& application_manager, + app_mngr::rpc_service::RPCService& rpc_service, + app_mngr::HMICapabilities& hmi_capabilities, + policy::PolicyHandlerInterface& policy_handler); + virtual ~SetCloudAppPropertiesRequest(); + virtual void Run(); + virtual void on_event(const app_mngr::event_engine::Event& event); + + private: + DISALLOW_COPY_AND_ASSIGN(SetCloudAppPropertiesRequest); +}; // SetCloudAppPropertiesRequest + +} // namespace commands +} // namespace sdl_rpc_plugin + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_SET_CLOUD_APP_PROPERTIES_REQUEST_H_
\ No newline at end of file diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_response.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_response.h new file mode 100644 index 0000000000..df71a2aaf5 --- /dev/null +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_response.h @@ -0,0 +1,31 @@ +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_SET_CLOUD_APP_PROPERTIES_RESPONSE_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_SET_CLOUD_APP_PROPERTIES_RESPONSE_H_ + +#include "application_manager/commands/command_response_impl.h" + +namespace sdl_rpc_plugin { +namespace app_mngr = application_manager; + +namespace commands { + +class SetCloudAppPropertiesResponse + : public app_mngr::commands::CommandResponseImpl { + public: + SetCloudAppPropertiesResponse( + const app_mngr::commands::MessageSharedPtr& message, + app_mngr::ApplicationManager& application_manager, + app_mngr::rpc_service::RPCService& rpc_service, + app_mngr::HMICapabilities& hmi_capabilities, + policy::PolicyHandlerInterface& policy_handler); + virtual ~SetCloudAppPropertiesResponse(); + virtual void Run(); + + private: + DISALLOW_COPY_AND_ASSIGN(SetCloudAppPropertiesResponse); + +}; // SetCloudAppPropertiesResponse + +} // namespace commands +} // namespace sdl_rpc_plugin + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_MOBILE_SET_CLOUD_APP_PROPERTIES_RESPONSE_H_
\ No newline at end of file diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_exit_application_notification.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_exit_application_notification.cc index 681390fbf4..b6d44a4511 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_exit_application_notification.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_exit_application_notification.cc @@ -106,6 +106,10 @@ void OnExitApplicationNotification::Run() { application_manager_.UnregisterApplication(app_id, Result::SUCCESS); return; } + case Common_ApplicationExitReason::CLOSE_CLOUD_CONNECTION: { + application_manager_.DisconnectCloudApp(app_impl); + break; + } default: { LOG4CXX_WARN(logger_, "Unhandled reason"); return; diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/sdl_activate_app_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/sdl_activate_app_request.cc index f89ae1f697..92a7020208 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/sdl_activate_app_request.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/sdl_activate_app_request.cc @@ -115,6 +115,8 @@ void SDLActivateAppRequest::Run() { LOG4CXX_AUTO_TRACE(logger_); using namespace hmi_apis::FunctionID; + ApplicationConstSharedPtr app = + application_manager_.WaitingApplicationByID(app_id()); if (application_manager_.state_controller().IsStateActive( HmiState::STATE_ID_DEACTIVATE_HMI)) { LOG4CXX_DEBUG(logger_, @@ -124,6 +126,16 @@ void SDLActivateAppRequest::Run() { static_cast<eType>(function_id()), hmi_apis::Common_Result::REJECTED, "HMIDeactivate is active"); + } else if (app && !app->IsRegistered() && app->is_cloud_app()) { + LOG4CXX_DEBUG(logger_, "Starting cloud application."); + const ApplicationManagerSettings& settings = + application_manager_.get_settings(); + uint32_t total_retry_timeout = (settings.cloud_app_retry_timeout() * + settings.cloud_app_max_retry_attempts()); + application_manager_.updateRequestTimeout( + 0, correlation_id(), default_timeout_ + total_retry_timeout); + subscribe_on_event(BasicCommunication_OnAppRegistered); + application_manager_.connection_handler().ConnectToDevice(app->device()); } else { const uint32_t application_id = app_id(); policy_handler_.OnActivateApp(application_id, correlation_id()); @@ -181,6 +193,18 @@ void SDLActivateAppRequest::Run() { LOG4CXX_DEBUG(logger_, "Application is registered. Activating."); policy_handler_.OnActivateApp(application_id, correlation_id()); return; + } else if (app_to_activate->is_cloud_app()) { + LOG4CXX_DEBUG(logger_, "Starting cloud application."); + const ApplicationManagerSettings& settings = + application_manager_.get_settings(); + uint32_t total_retry_timeout = (settings.cloud_app_retry_timeout() * + settings.cloud_app_max_retry_attempts()); + application_manager_.updateRequestTimeout( + 0, correlation_id(), default_timeout_ + total_retry_timeout); + subscribe_on_event(BasicCommunication_OnAppRegistered); + application_manager_.connection_handler().ConnectToDevice( + app_to_activate->device()); + return; } connection_handler::DeviceHandle device_handle = app_to_activate->device(); @@ -225,8 +249,10 @@ void SDLActivateAppRequest::onTimeOut() { using namespace hmi_apis::Common_Result; using namespace application_manager; unsubscribe_from_event(BasicCommunication_OnAppRegistered); - SendErrorResponse( - correlation_id(), SDL_ActivateApp, APPLICATION_NOT_REGISTERED, ""); + SendErrorResponse(correlation_id(), + SDL_ActivateApp, + APPLICATION_NOT_REGISTERED, + "App registration timed out"); } void SDLActivateAppRequest::on_event(const event_engine::Event& event) { @@ -262,7 +288,7 @@ uint32_t SDLActivateAppRequest::hmi_app_id( LOG4CXX_DEBUG(logger_, application << " section is absent in the message."); return 0; } - if (so[msg_params][application].keyExists(strings::app_id)) { + if (!so[msg_params][application].keyExists(strings::app_id)) { LOG4CXX_DEBUG(logger_, strings::app_id << " section is absent in the message."); return 0; diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_request.cc new file mode 100644 index 0000000000..34ed30c243 --- /dev/null +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_request.cc @@ -0,0 +1,98 @@ +#include "sdl_rpc_plugin/commands/mobile/get_cloud_app_properties_request.h" + +namespace sdl_rpc_plugin { +using namespace application_manager; + +namespace commands { + +GetCloudAppPropertiesRequest::GetCloudAppPropertiesRequest( + const app_mngr::commands::MessageSharedPtr& message, + app_mngr::ApplicationManager& application_manager, + app_mngr::rpc_service::RPCService& rpc_service, + app_mngr::HMICapabilities& hmi_capabilities, + policy::PolicyHandlerInterface& policy_handler) + : CommandRequestImpl(message, + application_manager, + rpc_service, + hmi_capabilities, + policy_handler) {} + +GetCloudAppPropertiesRequest::~GetCloudAppPropertiesRequest() {} + +void GetCloudAppPropertiesRequest::Run() { + LOG4CXX_AUTO_TRACE(logger_); + ApplicationSharedPtr app = application_manager_.application(connection_key()); + + if (!app) { + LOG4CXX_ERROR(logger_, "Application is not registered"); + SendResponse(false, mobile_apis::Result::APPLICATION_NOT_REGISTERED); + return; + } + + std::string policy_app_id = + (*message_)[strings::msg_params][strings::app_id].asString(); + + bool enabled = true; + std::string endpoint; + std::string auth_token; + std::string certificate; + std::string cloud_transport_type; + std::string hybrid_app_preference; + + bool result = policy_handler_.GetCloudAppParameters(policy_app_id, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference); + + if (!result) { + SendResponse(false, + mobile_apis::Result::DATA_NOT_AVAILABLE, + "Cloud app does not exist on module"); + return; + } + + policy::StringArray nicknames; + policy::StringArray app_hmi_types; + + policy_handler_.GetInitialAppData(policy_app_id, &nicknames, &app_hmi_types); + + smart_objects::SmartObject response_params(smart_objects::SmartType_Map); + smart_objects::SmartObject properties(smart_objects::SmartType_Map); + smart_objects::SmartObject nicknames_array(smart_objects::SmartType_Array); + size_t i = 0; + for (std::string nickname : nicknames) { + nicknames_array[i] = nickname; + ++i; + } + properties[strings::nicknames] = nicknames_array; + properties[strings::app_id] = policy_app_id; + properties[strings::enabled] = enabled; + + if (!auth_token.empty()) { + properties[strings::auth_token] = auth_token; + } + if (!cloud_transport_type.empty()) { + properties[strings::cloud_transport_type] = cloud_transport_type; + } + if (!hybrid_app_preference.empty()) { + properties[strings::hybrid_app_preference] = hybrid_app_preference; + } + if (!endpoint.empty()) { + properties[strings::endpoint] = endpoint; + } + + response_params[strings::properties] = properties; + + SendResponse(true, mobile_apis::Result::SUCCESS, NULL, &response_params); +} + +void GetCloudAppPropertiesRequest::on_event( + const app_mngr::event_engine::Event& event) { + LOG4CXX_INFO(logger_, "GetCloudAppPropertiesRequest on_event"); +} + +} // namespace commands +} // namespace sdl_rpc_plugin diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_response.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_response.cc new file mode 100644 index 0000000000..813a9e7006 --- /dev/null +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_response.cc @@ -0,0 +1,31 @@ +#include "application_manager/application_manager.h" +#include "application_manager/rpc_service.h" +#include "sdl_rpc_plugin/commands/mobile/get_cloud_app_properties_response.h" + +namespace sdl_rpc_plugin { +using namespace application_manager; + +namespace commands { + +GetCloudAppPropertiesResponse::GetCloudAppPropertiesResponse( + const app_mngr::commands::MessageSharedPtr& message, + app_mngr::ApplicationManager& application_manager, + app_mngr::rpc_service::RPCService& rpc_service, + app_mngr::HMICapabilities& hmi_capabilities, + policy::PolicyHandlerInterface& policy_handler) + : CommandResponseImpl(message, + application_manager, + rpc_service, + hmi_capabilities, + policy_handler) {} + +GetCloudAppPropertiesResponse::~GetCloudAppPropertiesResponse() {} + +void GetCloudAppPropertiesResponse::Run() { + LOG4CXX_AUTO_TRACE(logger_); + + rpc_service_.SendMessageToMobile(message_); +} + +} // namespace commands +} // namespace sdl_rpc_plugins 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 7957d9e055..924705f82b 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 @@ -281,17 +281,51 @@ void RegisterAppInterfaceRequest::Run() { return; } - mobile_apis::Result::eType coincidence_result = CheckCoincidence(); + std::vector<ApplicationSharedPtr> duplicate_apps; + mobile_apis::Result::eType coincidence_result = + CheckCoincidence(duplicate_apps); + + if (mobile_apis::Result::DUPLICATE_NAME == coincidence_result && + duplicate_apps.size() == 1) { + ApplicationSharedPtr duplicate_app = duplicate_apps.front(); + bool error_response = true; + if (duplicate_app->is_cloud_app()) { + if (duplicate_app->hybrid_app_preference() == + mobile_apis::HybridAppPreference::MOBILE) { + // Unregister cloud application and allow mobile application to register + // in it's place + application_manager_.UnregisterApplication( + duplicate_app->app_id(), mobile_apis::Result::USER_DISALLOWED); + error_response = false; + } + } else { + ApplicationSharedPtr cloud_app = + application_manager_.pending_application_by_policy_id(policy_app_id); + // If the duplicate name was not because of a mobile/cloud app pair, go + // through the normal process for handling duplicate names + if (cloud_app.use_count() == 0 || !cloud_app->is_cloud_app()) { + usage_statistics::AppCounter count_of_rejections_duplicate_name( + GetPolicyHandler().GetStatisticManager(), + policy_app_id, + usage_statistics::REJECTIONS_DUPLICATE_NAME); + ++count_of_rejections_duplicate_name; + } else if (cloud_app->hybrid_app_preference() == + mobile_apis::HybridAppPreference::CLOUD) { + // Unregister mobile application and allow cloud application to + // register in it's place + application_manager_.UnregisterApplication( + duplicate_app->app_id(), mobile_apis::Result::USER_DISALLOWED); + error_response = false; + } + } - if (mobile_apis::Result::SUCCESS != coincidence_result) { - LOG4CXX_ERROR(logger_, "Coincidence check failed."); - if (mobile_apis::Result::DUPLICATE_NAME == coincidence_result) { - usage_statistics::AppCounter count_of_rejections_duplicate_name( - GetPolicyHandler().GetStatisticManager(), - policy_app_id, - usage_statistics::REJECTIONS_DUPLICATE_NAME); - ++count_of_rejections_duplicate_name; + if (error_response) { + LOG4CXX_ERROR(logger_, "Coincidence check failed."); + SendResponse(false, coincidence_result); + return; } + } else if (mobile_apis::Result::SUCCESS != coincidence_result) { + LOG4CXX_ERROR(logger_, "Coincidence check failed."); SendResponse(false, coincidence_result); return; } @@ -346,19 +380,6 @@ void RegisterAppInterfaceRequest::Run() { application->set_msg_version(module_version); } - // For resuming application need to restore hmi_app_id from resumeCtrl - resumption::ResumeCtrl& resumer = application_manager_.resume_controller(); - const std::string& device_mac = application->mac_address(); - - // there is side affect with 2 mobile app with the same mobile app_id - if (resumer.IsApplicationSaved(policy_app_id, device_mac)) { - application->set_hmi_application_id( - resumer.GetHMIApplicationID(policy_app_id, device_mac)); - } else { - application->set_hmi_application_id( - application_manager_.GenerateNewHMIAppID()); - } - application->set_is_media_application( msg_params[strings::is_media_application].asBool()); @@ -451,6 +472,8 @@ void RegisterAppInterfaceRequest::Run() { FillDeviceInfo(&device_info); } + const std::string& device_mac = application->mac_address(); + GetPolicyHandler().SetDeviceInfo(device_mac, device_info); SendRegisterAppInterfaceResponseToMobile(ApplicationType::kNewApplication); @@ -458,6 +481,9 @@ void RegisterAppInterfaceRequest::Run() { GetLockScreenIconUrlNotification(connection_key(), application); rpc_service_.ManageMobileCommand(so, SOURCE_SDL); application_manager_.SendDriverDistractionState(application); + // Create onSystemRequest to mobile to obtain cloud app icons + application_manager_.SendGetIconUrlNotifications(connection_key(), + application); } smart_objects::SmartObjectSPtr @@ -816,8 +842,6 @@ void RegisterAppInterfaceRequest::SendRegisterAppInterfaceResponseToMobile( file_system::FileExists(application->app_icon_path()); SendResponse(true, result_code, add_info.c_str(), &response_params); - SendOnAppRegisteredNotificationToHMI( - *(application.get()), resumption, need_restore_vr); if (msg_params.keyExists(strings::app_hmi_type)) { GetPolicyHandler().SetDefaultHmiTypes(application->policy_app_id(), &(msg_params[strings::app_hmi_type])); @@ -826,6 +850,8 @@ void RegisterAppInterfaceRequest::SendRegisterAppInterfaceResponseToMobile( // Default HMI level should be set before any permissions validation, since it // relies on HMI level. application_manager_.OnApplicationRegistered(application); + SendOnAppRegisteredNotificationToHMI( + application, resumption, need_restore_vr); (*notify_upd_manager)(); // Start PTU after successfull registration @@ -877,9 +903,7 @@ void RegisterAppInterfaceRequest::SendChangeRegistrationOnHMI( } void RegisterAppInterfaceRequest::SendOnAppRegisteredNotificationToHMI( - const app_mngr::Application& application_impl, - bool resumption, - bool need_restore_vr) { + ApplicationConstSharedPtr app, bool resumption, bool need_restore_vr) { using namespace smart_objects; SmartObjectSPtr notification = std::make_shared<SmartObject>(SmartType_Map); if (!notification) { @@ -903,15 +927,15 @@ void RegisterAppInterfaceRequest::SendOnAppRegisteredNotificationToHMI( msg_params[strings::resume_vr_grammars] = need_restore_vr; } - if (application_impl.vr_synonyms()) { - msg_params[strings::vr_synonyms] = *(application_impl.vr_synonyms()); + if (app->vr_synonyms()) { + msg_params[strings::vr_synonyms] = *(app->vr_synonyms()); } - if (application_impl.tts_name()) { - msg_params[strings::tts_name] = *(application_impl.tts_name()); + if (app->tts_name()) { + msg_params[strings::tts_name] = *(app->tts_name()); } - const std::string policy_app_id = application_impl.policy_app_id(); + const std::string policy_app_id = app->policy_app_id(); std::string priority; GetPolicyHandler().GetPriority(policy_app_id, &priority); @@ -921,105 +945,19 @@ void RegisterAppInterfaceRequest::SendOnAppRegisteredNotificationToHMI( msg_params[strings::msg_params] = SmartObject(SmartType_Map); smart_objects::SmartObject& application = msg_params[strings::application]; - application[strings::app_name] = application_impl.name(); - application[strings::app_id] = application_impl.app_id(); - application[hmi_response::policy_app_id] = policy_app_id; - if (file_system::FileExists(application_impl.app_icon_path())) { - application[strings::icon] = application_impl.app_icon_path(); - } - - const smart_objects::SmartObject* ngn_media_screen_name = - application_impl.ngn_media_screen_name(); - if (ngn_media_screen_name) { - application[strings::ngn_media_screen_app_name] = *ngn_media_screen_name; - } - - application[strings::hmi_display_language_desired] = - static_cast<int32_t>(application_impl.ui_language()); - - application[strings::is_media_application] = - application_impl.is_media_application(); - - const smart_objects::SmartObject* app_type = application_impl.app_types(); - if (app_type) { - application[strings::app_type] = *app_type; - } - - const policy::RequestType::State app_request_types_state = - GetPolicyHandler().GetAppRequestTypeState(policy_app_id); - if (policy::RequestType::State::AVAILABLE == app_request_types_state) { - const auto request_types = - GetPolicyHandler().GetAppRequestTypes(policy_app_id); - application[strings::request_type] = SmartObject(SmartType_Array); - smart_objects::SmartObject& request_types_array = - application[strings::request_type]; - - size_t index = 0; - for (auto it : request_types) { - request_types_array[index] = it; - ++index; - } - } else if (policy::RequestType::State::EMPTY == app_request_types_state) { - application[strings::request_type] = SmartObject(SmartType_Array); - } - - const policy::RequestSubType::State app_request_subtypes_state = - GetPolicyHandler().GetAppRequestSubTypeState(policy_app_id); - if (policy::RequestSubType::State::AVAILABLE == app_request_subtypes_state) { - const auto request_subtypes = - GetPolicyHandler().GetAppRequestSubTypes(policy_app_id); - application[strings::request_subtype] = SmartObject(SmartType_Array); - smart_objects::SmartObject& request_subtypes_array = - application[strings::request_subtype]; - - size_t index = 0; - for (auto it : request_subtypes) { - request_subtypes_array[index] = it; - ++index; - } - } else if (policy::RequestSubType::State::EMPTY == - app_request_subtypes_state) { - application[strings::request_subtype] = SmartObject(SmartType_Array); - } - const protocol_handler::SessionObserver& session_observer = application_manager_.connection_handler().get_session_observer(); - - application[strings::device_info] = SmartObject(SmartType_Map); - smart_objects::SmartObject& device_info = application[strings::device_info]; - MessageHelper::CreateDeviceInfo(application_impl.device(), - session_observer, - GetPolicyHandler(), - application_manager_, - &device_info); - - if (application_impl.secondary_device() != 0) { - application[strings::secondary_device_info] = SmartObject(SmartType_Map); - smart_objects::SmartObject& secondary_device_info = - application[strings::secondary_device_info]; - MessageHelper::CreateDeviceInfo(application_impl.secondary_device(), - session_observer, - GetPolicyHandler(), - application_manager_, - &secondary_device_info); - } - - const smart_objects::SmartObject* day_color_scheme = - application_impl.day_color_scheme(); - if (day_color_scheme) { - application[strings::day_color_scheme] = *day_color_scheme; - } - - const smart_objects::SmartObject* night_color_scheme = - application_impl.night_color_scheme(); - if (night_color_scheme) { - application[strings::night_color_scheme] = *night_color_scheme; - } + MessageHelper::CreateHMIApplicationStruct(app, + session_observer, + GetPolicyHandler(), + &application, + application_manager_); DCHECK(rpc_service_.ManageHMICommand(notification)); } -mobile_apis::Result::eType RegisterAppInterfaceRequest::CheckCoincidence() { +mobile_apis::Result::eType RegisterAppInterfaceRequest::CheckCoincidence( + std::vector<ApplicationSharedPtr>& out_duplicate_apps) { LOG4CXX_AUTO_TRACE(logger_); const smart_objects::SmartObject& msg_params = (*message_)[strings::msg_params]; @@ -1035,7 +973,8 @@ mobile_apis::Result::eType RegisterAppInterfaceRequest::CheckCoincidence() { const custom_str::CustomString& cur_name = (*it)->name(); if (app_name.CompareIgnoreCase(cur_name)) { LOG4CXX_ERROR(logger_, "Application name is known already."); - return mobile_apis::Result::DUPLICATE_NAME; + out_duplicate_apps.push_back(*it); + continue; } const smart_objects::SmartObject* vr = (*it)->vr_synonyms(); @@ -1046,7 +985,8 @@ mobile_apis::Result::eType RegisterAppInterfaceRequest::CheckCoincidence() { if (0 != std::count_if(curr_vr->begin(), curr_vr->end(), v)) { LOG4CXX_ERROR(logger_, "Application name is known already."); - return mobile_apis::Result::DUPLICATE_NAME; + out_duplicate_apps.push_back(*it); + continue; } } @@ -1058,12 +998,16 @@ mobile_apis::Result::eType RegisterAppInterfaceRequest::CheckCoincidence() { CoincidencePredicateVR v(cur_name); if (0 != std::count_if(new_vr->begin(), new_vr->end(), v)) { LOG4CXX_ERROR(logger_, "vr_synonyms duplicated with app_name ."); - return mobile_apis::Result::DUPLICATE_NAME; + out_duplicate_apps.push_back(*it); + continue; } } // end vr check } // application for end + if (!out_duplicate_apps.empty()) { + return mobile_apis::Result::DUPLICATE_NAME; + } return mobile_apis::Result::SUCCESS; } // method end diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_request.cc new file mode 100644 index 0000000000..5173be56d6 --- /dev/null +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_request.cc @@ -0,0 +1,43 @@ +#include "sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_request.h" + +namespace sdl_rpc_plugin { +using namespace application_manager; + +namespace commands { + +SetCloudAppPropertiesRequest::SetCloudAppPropertiesRequest( + const app_mngr::commands::MessageSharedPtr& message, + app_mngr::ApplicationManager& application_manager, + app_mngr::rpc_service::RPCService& rpc_service, + app_mngr::HMICapabilities& hmi_capabilities, + policy::PolicyHandlerInterface& policy_handler) + : CommandRequestImpl(message, + application_manager, + rpc_service, + hmi_capabilities, + policy_handler) {} + +SetCloudAppPropertiesRequest::~SetCloudAppPropertiesRequest() {} + +void SetCloudAppPropertiesRequest::Run() { + LOG4CXX_AUTO_TRACE(logger_); + ApplicationSharedPtr app = application_manager_.application(connection_key()); + + if (!app) { + LOG4CXX_ERROR(logger_, "Application is not registered"); + SendResponse(false, mobile_apis::Result::APPLICATION_NOT_REGISTERED); + return; + } + + policy_handler_.OnSetCloudAppProperties(*message_); + + SendResponse(true, mobile_apis::Result::SUCCESS); +} + +void SetCloudAppPropertiesRequest::on_event( + const app_mngr::event_engine::Event& event) { + LOG4CXX_INFO(logger_, "SetCloudAppPropertiesRequest on_event"); +} + +} // namespace commands +} // namespace sdl_rpc_plugin
\ No newline at end of file diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_response.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_response.cc new file mode 100644 index 0000000000..6d27ce8b3e --- /dev/null +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_response.cc @@ -0,0 +1,31 @@ +#include "application_manager/application_manager.h" +#include "application_manager/rpc_service.h" +#include "sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_response.h" + +namespace sdl_rpc_plugin { +using namespace application_manager; + +namespace commands { + +SetCloudAppPropertiesResponse::SetCloudAppPropertiesResponse( + const app_mngr::commands::MessageSharedPtr& message, + app_mngr::ApplicationManager& application_manager, + app_mngr::rpc_service::RPCService& rpc_service, + app_mngr::HMICapabilities& hmi_capabilities, + policy::PolicyHandlerInterface& policy_handler) + : CommandResponseImpl(message, + application_manager, + rpc_service, + hmi_capabilities, + policy_handler) {} + +SetCloudAppPropertiesResponse::~SetCloudAppPropertiesResponse() {} + +void SetCloudAppPropertiesResponse::Run() { + LOG4CXX_AUTO_TRACE(logger_); + + rpc_service_.SendMessageToMobile(message_); +} + +} // namespace commands +} // namespace sdl_rpc_plugins diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/system_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/system_request.cc index cea00a9d5e..da39aefd6a 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/system_request.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/system_request.cc @@ -511,7 +511,8 @@ void SystemRequest::Run() { return; } - if (!file_system::IsFileNameValid(file_name)) { + if (!file_system::IsFileNameValid(file_name) && + mobile_apis::RequestType::ICON_URL != request_type) { const std::string err_msg = "Sync file name contains forbidden symbols."; LOG4CXX_ERROR(logger_, err_msg); SendResponse(false, mobile_apis::Result::INVALID_DATA, err_msg.c_str()); @@ -533,8 +534,21 @@ void SystemRequest::Run() { std::string binary_data_folder; if ((*message_)[strings::params].keyExists(strings::binary_data)) { binary_data = (*message_)[strings::params][strings::binary_data].asBinary(); - binary_data_folder = - application_manager_.get_settings().system_files_path(); + if (mobile_apis::RequestType::ICON_URL == request_type) { + binary_data_folder = + application_manager_.get_settings().app_icons_folder(); + // Use the URL file name to identify the policy id. + // Save the icon file with the policy id as the name. + file_name = application_manager_.PolicyIDByIconUrl(file_name); + if (file_name.empty()) { + const std::string err_msg = "Invalid file name"; + SendResponse(false, mobile_apis::Result::INVALID_DATA, err_msg.c_str()); + } + LOG4CXX_DEBUG(logger_, "Got ICON_URL Request. File name: " << file_name); + } else { + binary_data_folder = + application_manager_.get_settings().system_files_path(); + } } else { binary_data_folder = application_manager_.get_settings().app_storage_folder(); @@ -581,6 +595,12 @@ void SystemRequest::Run() { LOG4CXX_DEBUG(logger_, "Binary data ok."); + if (mobile_apis::RequestType::ICON_URL == request_type) { + application_manager_.SetIconFileFromSystemRequest(file_name); + SendResponse(true, mobile_apis::Result::SUCCESS); + return; + } + if (mobile_apis::RequestType::HTTP == request_type && (*message_)[strings::msg_params].keyExists(strings::file_name)) { const std::string& file = diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/mobile_command_factory.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/mobile_command_factory.cc index 5207c7e432..5ef76b59ef 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/mobile_command_factory.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/mobile_command_factory.cc @@ -124,6 +124,10 @@ #include "sdl_rpc_plugin/commands/mobile/dial_number_response.h" #include "sdl_rpc_plugin/commands/mobile/send_haptic_data_request.h" #include "sdl_rpc_plugin/commands/mobile/send_haptic_data_response.h" +#include "sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_request.h" +#include "sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_response.h" +#include "sdl_rpc_plugin/commands/mobile/get_cloud_app_properties_request.h" +#include "sdl_rpc_plugin/commands/mobile/get_cloud_app_properties_response.h" #include "interfaces/MOBILE_API.h" CREATE_LOGGERPTR_GLOBAL(logger_, "ApplicationManager") @@ -337,6 +341,18 @@ CommandCreator& MobileCommandFactory::get_creator_factory( ? factory.GetCreator<commands::SendHapticDataRequest>() : factory.GetCreator<commands::SendHapticDataResponse>(); } + case mobile_apis::FunctionID::SetCloudAppPropertiesID: { + return mobile_api::messageType::request == message_type + ? factory.GetCreator<commands::SetCloudAppPropertiesRequest>() + : factory + .GetCreator<commands::SetCloudAppPropertiesResponse>(); + } + case mobile_apis::FunctionID::GetCloudAppPropertiesID: { + return mobile_api::messageType::request == message_type + ? factory.GetCreator<commands::GetCloudAppPropertiesRequest>() + : factory + .GetCreator<commands::GetCloudAppPropertiesResponse>(); + } case mobile_apis::FunctionID::OnButtonEventID: { return factory.GetCreator<commands::mobile::OnButtonEventNotification>(); } diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/sdl_activate_app_request_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/sdl_activate_app_request_test.cc index 38cbc7b069..8543a201bf 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/sdl_activate_app_request_test.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/sdl_activate_app_request_test.cc @@ -44,6 +44,7 @@ #include "application_manager/event_engine/event.h" #include "application_manager/mock_event_dispatcher.h" #include "application_manager/mock_state_controller.h" +#include "connection_handler/mock_connection_handler.h" namespace test { namespace components { @@ -61,8 +62,10 @@ using testing::Mock; using testing::Return; using testing::ReturnRef; using testing::Mock; +using testing::Gt; using ::testing::NiceMock; using policy_test::MockPolicyHandlerInterface; +using connection_handler_test::MockConnectionHandler; using am::event_engine::Event; namespace { @@ -148,7 +151,7 @@ TEST_F(SDLActivateAppRequestTest, Run_ActivateApp_SUCCESS) { command->Run(); } -TEST_F(SDLActivateAppRequestTest, DISABLED_Run_DactivateApp_REJECTED) { +TEST_F(SDLActivateAppRequestTest, DISABLED_Run_DeactivateApp_REJECTED) { MessageSharedPtr msg = CreateMessage(); SetCorrelationAndAppID(msg); (*msg)[strings::msg_params][strings::function_id] = @@ -189,6 +192,7 @@ TEST_F(SDLActivateAppRequestTest, FindAppToRegister_SUCCESS) { .WillOnce(Return(false)); EXPECT_CALL(*mock_app, IsRegistered()).WillOnce(Return(false)); + EXPECT_CALL(*mock_app, is_cloud_app()).WillOnce(Return(false)); ON_CALL(*mock_app, device()).WillByDefault(Return(kHandle)); MockAppPtr mock_app_first(CreateMockApp()); @@ -250,6 +254,7 @@ TEST_F(SDLActivateAppRequestTest, DevicesAppsEmpty_SUCCESS) { .WillOnce(Return(false)); EXPECT_CALL(*mock_app, IsRegistered()).WillOnce(Return(false)); + EXPECT_CALL(*mock_app, is_cloud_app()).WillOnce(Return(false)); ON_CALL(*mock_app, device()).WillByDefault(Return(kHandle)); DataAccessor<ApplicationSet> accessor(app_list_, lock_); @@ -336,6 +341,7 @@ TEST_F(SDLActivateAppRequestTest, FirstAppIsForeground_SUCCESS) { EXPECT_CALL(*mock_app, device()).WillOnce(Return(kHandle)); EXPECT_CALL(*mock_app, IsRegistered()).WillOnce(Return(false)); + EXPECT_CALL(*mock_app, is_cloud_app()).WillOnce(Return(false)); EXPECT_CALL(app_mngr_, state_controller()) .WillOnce(ReturnRef(mock_state_controller_)); EXPECT_CALL(mock_state_controller_, @@ -427,6 +433,53 @@ TEST_F(SDLActivateAppRequestTest, FirstAppNotRegistered_SUCCESS) { } #endif +TEST_F(SDLActivateAppRequestTest, WaitingCloudApplication_ConnectDevice) { + MessageSharedPtr msg = CreateMessage(); + SetCorrelationAndAppID(msg); + + std::shared_ptr<SDLActivateAppRequest> command( + CreateCommand<SDLActivateAppRequest>(msg)); + + MockAppPtr mock_app(CreateMockApp()); + + EXPECT_CALL(*mock_app, device()).WillOnce(Return(kHandle)); + EXPECT_CALL(*mock_app, IsRegistered()).WillOnce(Return(false)); + EXPECT_CALL(*mock_app, is_cloud_app()).WillOnce(Return(true)); + + EXPECT_CALL(app_mngr_, application(kAppID)) + .WillOnce(Return(ApplicationSharedPtr())); + EXPECT_CALL(app_mngr_, WaitingApplicationByID(kAppID)) + .WillOnce(Return(mock_app)); + + EXPECT_CALL(app_mngr_, state_controller()) + .WillOnce(ReturnRef(mock_state_controller_)); + EXPECT_CALL(mock_state_controller_, + IsStateActive(am::HmiState::StateID::STATE_ID_DEACTIVATE_HMI)) + .WillOnce(Return(false)); + + const uint16_t kRetries = 3; + const uint32_t kRetryTimeout = 2000; + const uint32_t kMinimumTimeout = kRetries * kRetryTimeout; + + MockApplicationManagerSettings settings; + EXPECT_CALL(settings, cloud_app_max_retry_attempts()) + .WillOnce(Return(kRetries)); + EXPECT_CALL(settings, cloud_app_retry_timeout()) + .WillOnce(Return(kRetryTimeout)); + EXPECT_CALL(app_mngr_, get_settings()).WillOnce(ReturnRef(settings)); + + EXPECT_CALL(app_mngr_, + updateRequestTimeout(0, kCorrelationID, Gt(kMinimumTimeout))); + + MockConnectionHandler connection_handler; + EXPECT_CALL(connection_handler, ConnectToDevice(kHandle)); + + EXPECT_CALL(app_mngr_, connection_handler()) + .WillOnce(ReturnRef(connection_handler)); + + command->Run(); +} + TEST_F(SDLActivateAppRequestTest, OnTimeout_SUCCESS) { MessageSharedPtr msg = CreateMessage(); SetCorrelationAndAppID(msg); diff --git a/src/components/application_manager/src/application_impl.cc b/src/components/application_manager/src/application_impl.cc index 8a611195c7..3d17da51ce 100644 --- a/src/components/application_manager/src/application_impl.cc +++ b/src/components/application_manager/src/application_impl.cc @@ -964,7 +964,7 @@ void ApplicationImpl::CleanupFiles() { application_manager_.get_settings().app_storage_folder(); directory_name += "/" + folder_name(); - if (file_system::DirectoryExists(directory_name)) { + if (file_system::DirectoryExists(directory_name) && !folder_name().empty()) { std::vector<std::string> files = file_system::ListFiles(directory_name); AppFilesMap::const_iterator app_files_it; @@ -1163,6 +1163,54 @@ const std::list<AppExtensionPtr>& ApplicationImpl::Extensions() const { return extensions_; } +const std::string& ApplicationImpl::cloud_app_endpoint() const { + return endpoint_; +} + +const std::string& ApplicationImpl::auth_token() const { + return auth_token_; +} + +const std::string& ApplicationImpl::cloud_app_transport_type() const { + return cloud_transport_type_; +} + +const mobile_apis::HybridAppPreference::eType& +ApplicationImpl::hybrid_app_preference() const { + return hybrid_app_preference_; +} + +const std::string& ApplicationImpl::cloud_app_certificate() const { + return certificate_; +} + +bool ApplicationImpl::is_cloud_app() const { + return !endpoint_.empty(); +} + +void ApplicationImpl::set_cloud_app_endpoint(const std::string& endpoint) { + endpoint_ = endpoint; +} + +void ApplicationImpl::set_auth_token(const std::string& auth_token) { + auth_token_ = auth_token; +} + +void ApplicationImpl::set_cloud_app_transport_type( + const std::string& transport_type) { + cloud_transport_type_ = transport_type; +} + +void ApplicationImpl::set_hybrid_app_preference( + const mobile_apis::HybridAppPreference::eType& hybrid_app_preference) { + hybrid_app_preference_ = hybrid_app_preference; +} + +void ApplicationImpl::set_cloud_app_certificate( + const std::string& certificate) { + certificate_ = certificate; +} + void ApplicationImpl::PushMobileMessage( smart_objects::SmartObjectSPtr mobile_message) { sync_primitives::AutoLock lock(mobile_message_lock_); diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 24f27af2e2..61c0f41524 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -73,6 +73,7 @@ #include "policy/usage_statistics/counter.h" #include "utils/custom_string.h" #include <time.h> +#include <boost/filesystem.hpp> namespace { int get_rand_from_range(uint32_t from = 0, int to = RAND_MAX) { @@ -98,7 +99,9 @@ DeviceTypes devicesType = { std::make_pair(std::string("USB_IOS_DEVICE_MODE"), hmi_apis::Common_TransportType::USB_IOS), std::make_pair(std::string("CARPLAY_WIRELESS_IOS"), - hmi_apis::Common_TransportType::WIFI)}; + hmi_apis::Common_TransportType::WIFI), + std::make_pair(std::string("CLOUD_WEBSOCKET"), + hmi_apis::Common_TransportType::CLOUD_WEBSOCKET)}; } /** @@ -166,6 +169,8 @@ ApplicationManagerImpl::ApplicationManagerImpl( , navi_close_app_timeout_(am_settings.stop_streaming_timeout()) , navi_end_stream_timeout_(am_settings.stop_streaming_timeout()) , state_ctrl_(*this) + , pending_device_map_lock_ptr_( + std::make_shared<sync_primitives::RecursiveLock>()) , application_list_update_timer_( "AM ListUpdater", new TimerTaskImpl<ApplicationManagerImpl>( @@ -236,6 +241,13 @@ DataAccessor<ApplicationSet> ApplicationManagerImpl::applications() const { return accessor; } +DataAccessor<AppsWaitRegistrationSet> +ApplicationManagerImpl::pending_applications() const { + DataAccessor<AppsWaitRegistrationSet> accessor( + apps_to_register_, apps_to_register_list_lock_ptr_); + return accessor; +} + ApplicationSharedPtr ApplicationManagerImpl::application( uint32_t app_id) const { AppIdPredicate finder(app_id); @@ -257,6 +269,20 @@ ApplicationSharedPtr ApplicationManagerImpl::application_by_policy_id( return FindApp(accessor, finder); } +ApplicationSharedPtr ApplicationManagerImpl::application_by_name( + const std::string& app_name) const { + AppNamePredicate finder(app_name); + DataAccessor<ApplicationSet> accessor = applications(); + return FindApp(accessor, finder); +} + +ApplicationSharedPtr ApplicationManagerImpl::pending_application_by_policy_id( + const std::string& policy_app_id) const { + PolicyAppIdPredicate finder(policy_app_id); + DataAccessor<AppsWaitRegistrationSet> accessor = pending_applications(); + return FindPendingApp(accessor, finder); +} + bool ActiveAppPredicate(const ApplicationSharedPtr app) { return app ? app->IsFullscreen() : false; } @@ -379,21 +405,6 @@ void ApplicationManagerImpl::OnApplicationRegistered(ApplicationSharedPtr app) { plugin.OnApplicationEvent(plugin_manager::kApplicationRegistered, app); }; plugin_manager_->ForEachPlugin(on_app_registered); - - // TODO(AOleynik): Is neccessary to be able to know that registration process - // has been completed and default HMI level is set, otherwise policy will - // block all the requests/notifications to mobile - // APPLINK-20764 - introduce usage of internal events or re-implement - event_engine::Event event( - hmi_apis::FunctionID::BasicCommunication_OnAppRegistered); - - smart_objects::SmartObject msg; - msg[strings::params][strings::message_type] = - hmi_apis::messageType::notification; - msg[strings::params][strings::app_id] = app->app_id(); - - event.set_smart_object(msg); - event.raise(event_dispatcher()); } void ApplicationManagerImpl::OnApplicationSwitched(ApplicationSharedPtr app) { @@ -539,6 +550,7 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( app_name, GetPolicyHandler().GetStatisticManager(), *this)); + if (!application) { std::shared_ptr<smart_objects::SmartObject> response( MessageHelper::CreateNegativeResponse( @@ -608,13 +620,48 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( // Keep HMI add id in case app is present in "waiting for registration" list apps_to_register_list_lock_ptr_->Acquire(); - AppsWaitRegistrationSet::iterator it = apps_to_register_.find(application); - if (apps_to_register_.end() != it) { + PolicyAppIdPredicate finder(application->policy_app_id()); + ApplicationSet::iterator it = + std::find_if(apps_to_register_.begin(), apps_to_register_.end(), finder); + bool is_mismatched_cloud_app = false; + + if (apps_to_register_.end() == it) { + DevicePredicate finder(application->device()); + it = std::find_if( + apps_to_register_.begin(), apps_to_register_.end(), finder); + + bool found = apps_to_register_.end() != it; + is_mismatched_cloud_app = found && (*it)->is_cloud_app() && + policy_app_id != (*it)->policy_app_id(); + } else { application->set_hmi_application_id((*it)->hmi_app_id()); - apps_to_register_.erase(application); + + // Set cloud app parameters + application->set_cloud_app_endpoint((*it)->cloud_app_endpoint()); + application->set_cloud_app_certificate((*it)->cloud_app_certificate()); + application->set_auth_token((*it)->auth_token()); + application->set_cloud_app_transport_type( + (*it)->cloud_app_transport_type()); + application->set_hybrid_app_preference((*it)->hybrid_app_preference()); + apps_to_register_.erase(it); } apps_to_register_list_lock_ptr_->Release(); + // Reject registration request if a cloud app registers with the incorrect + // appID + if (is_mismatched_cloud_app) { + std::shared_ptr<smart_objects::SmartObject> response( + MessageHelper::CreateNegativeResponse( + connection_key, + mobile_apis::FunctionID::RegisterAppInterfaceID, + message[strings::params][strings::correlation_id].asUInt(), + mobile_apis::Result::DISALLOWED)); + (*response)[strings::msg_params][strings::info] = + "Cloud app registered with incorrect app id"; + rpc_service_->ManageMobileCommand(response, commands::Command::SOURCE_SDL); + return ApplicationSharedPtr(); + } + if (!application->hmi_app_id()) { const bool is_saved = resume_controller().IsApplicationSaved(policy_app_id, device_mac); @@ -650,6 +697,10 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication( apps_size_ = applications_.size(); applications_list_lock_ptr_->Release(); + // Update cloud app information, in case any pending apps are unable to be + // registered due to a mobile app taking precedence + RefreshCloudAppInformation(); + // It is possible that secondary transport of this app has been already // established. Make sure that the information is reflected to application // instance. @@ -779,6 +830,398 @@ void ApplicationManagerImpl::OnHMIStartedCooperation() { *this)); rpc_service_->ManageHMICommand(mixing_audio_supported_request); resume_controller().ResetLaunchTime(); + + RefreshCloudAppInformation(); +} + +std::string ApplicationManagerImpl::PolicyIDByIconUrl(const std::string url) { + sync_primitives::AutoLock lock(app_icon_map_lock_ptr_); + for (auto& x : app_icon_map_) { + auto policy_id = x.first; + std::string icon_url = GetPolicyHandler().GetIconUrl(policy_id); + if (icon_url == url) { + LOG4CXX_DEBUG(logger_, "Matched icon url: " << url); + x.second.pending_request = false; + return policy_id; + } + } + return std::string(""); +} + +void ApplicationManagerImpl::SetIconFileFromSystemRequest( + const std::string policy_id) { + app_icon_map_lock_ptr_.Acquire(); + auto app_icon_it = app_icon_map_.find(policy_id); + if (app_icon_it != app_icon_map_.end()) { + app_icon_map_.erase(app_icon_it); + } + app_icon_map_lock_ptr_.Release(); + + // Find pending application and set icon path + auto app = pending_application_by_policy_id(policy_id); + if (!app) { + return; + } + const std::string app_icon_dir(settings_.app_icons_folder()); + const std::string full_icon_path(app_icon_dir + "/" + policy_id); + if (file_system::FileExists(full_icon_path)) { + LOG4CXX_DEBUG(logger_, "Set Icon Path: " << full_icon_path); + AppFile file; + file.is_persistent = true; + file.is_download_complete = true; + file.file_name = full_icon_path; + + std::string icon_url = GetPolicyHandler().GetIconUrl(policy_id); + std::string extension = boost::filesystem::extension(icon_url); + if (extension == "bmp" || extension == "BMP") { + file.file_type = mobile_apis::FileType::GRAPHIC_BMP; + } else if (extension == "JPEG" || extension == "jpeg" || + extension == "JPG" || extension == "jpg") { + file.file_type = mobile_apis::FileType::GRAPHIC_JPEG; + } else { + file.file_type = mobile_apis::FileType::GRAPHIC_PNG; + } + + app->AddFile(file); + app->set_app_icon_path(full_icon_path); + } + SendUpdateAppList(); +} + +void ApplicationManagerImpl::DisconnectCloudApp(ApplicationSharedPtr app) { + std::string endpoint; + std::string certificate; + std::string auth_token; + std::string cloud_transport_type; + std::string hybrid_app_preference; + bool enabled = true; + std::string policy_app_id = app->policy_app_id(); + GetPolicyHandler().GetCloudAppParameters(policy_app_id, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference); + if (app->IsRegistered() && app->is_cloud_app()) { + LOG4CXX_DEBUG(logger_, "Disabled app is registered, unregistering now"); + GetRPCService().ManageMobileCommand( + MessageHelper::GetOnAppInterfaceUnregisteredNotificationToMobile( + app->app_id(), + mobile_api::AppInterfaceUnregisteredReason::APP_UNAUTHORIZED), + commands::Command::SOURCE_SDL); + + OnAppUnauthorized(app->app_id()); + } + // Delete the cloud device + connection_handler().RemoveCloudAppDevice(app->device()); + + transport_manager::transport_adapter::CloudAppProperties properties{ + endpoint, + certificate, + enabled, + auth_token, + cloud_transport_type, + hybrid_app_preference}; + // Create device in pending state + LOG4CXX_DEBUG(logger_, "Re-adding the cloud app device"); + connection_handler().AddCloudAppDevice(policy_app_id, properties); +} + +void ApplicationManagerImpl::RefreshCloudAppInformation() { + LOG4CXX_AUTO_TRACE(logger_); + std::vector<std::string> enabled_apps; + GetPolicyHandler().GetEnabledCloudApps(enabled_apps); + std::vector<std::string>::iterator enabled_it = enabled_apps.begin(); + std::vector<std::string>::iterator enabled_end = enabled_apps.end(); + std::string endpoint; + std::string certificate; + std::string auth_token; + std::string cloud_transport_type; + std::string hybrid_app_preference_str; + bool enabled = true; + + // Store old device map and clear the current map + pending_device_map_lock_ptr_->Acquire(); + app_icon_map_lock_ptr_.Acquire(); + std::map<std::string, std::string> old_device_map = pending_device_map_; + pending_device_map_ = std::map<std::string, std::string>(); + // Create a device for each newly enabled cloud app + for (; enabled_it != enabled_end; ++enabled_it) { + GetPolicyHandler().GetCloudAppParameters(*enabled_it, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference_str); + + mobile_apis::HybridAppPreference::eType hybrid_app_preference = + mobile_apis::HybridAppPreference::INVALID_ENUM; + smart_objects::EnumConversionHelper< + mobile_apis::HybridAppPreference::eType>:: + StringToEnum(hybrid_app_preference_str, &hybrid_app_preference); + + auto policy_id = *enabled_it; + policy::StringArray nicknames; + policy::StringArray app_hmi_types; + GetPolicyHandler().GetInitialAppData(policy_id, &nicknames, &app_hmi_types); + + if (nicknames.empty()) { + LOG4CXX_ERROR(logger_, "Cloud App missing nickname"); + continue; + } else if (mobile_apis::HybridAppPreference::MOBILE == + hybrid_app_preference) { + auto nickname_it = nicknames.begin(); + for (; nickname_it != nicknames.end(); ++nickname_it) { + auto app = application_by_name(*nickname_it); + if (app.use_count() != 0) { + LOG4CXX_ERROR( + logger_, + "Mobile app already registered for cloud app: " << *nickname_it); + continue; + } + } + } + + pending_device_map_.insert( + std::pair<std::string, std::string>(endpoint, policy_id)); + // Determine which endpoints were disabled by erasing all enabled apps from + // the old device list + auto old_device_it = old_device_map.find(endpoint); + if (old_device_it != old_device_map.end()) { + old_device_map.erase(old_device_it); + } + + transport_manager::transport_adapter::CloudAppProperties properties{ + endpoint, + certificate, + enabled, + auth_token, + cloud_transport_type, + hybrid_app_preference_str}; + + // If the device was disconnected, this will reinitialize the device + connection_handler().AddCloudAppDevice(policy_id, properties); + + // Look for app icon url data and add to app_icon_url_map + std::string url = GetPolicyHandler().GetIconUrl(policy_id); + + if (url.empty()) { + LOG4CXX_DEBUG(logger_, "No Icon Url for cloud app"); + continue; + } + + auto app_icon_it = app_icon_map_.find(policy_id); + if (app_icon_it != app_icon_map_.end()) { + LOG4CXX_DEBUG(logger_, "Cloud App Already Exists in Icon Map"); + continue; + } + + const std::string app_icon_dir(settings_.app_icons_folder()); + const std::string full_icon_path(app_icon_dir + "/" + policy_id); + if (!file_system::FileExists(full_icon_path)) { + int icon_map_size = app_icon_map_.size(); + AppIconInfo icon_info(endpoint, false); + LOG4CXX_DEBUG(logger_, + "Inserting cloud app into icon map: " << icon_map_size); + app_icon_map_.insert( + std::pair<std::string, AppIconInfo>(policy_id, icon_info)); + } + } + app_icon_map_lock_ptr_.Release(); + pending_device_map_lock_ptr_->Release(); + + int removed_app_count = 0; + // Clear out devices for existing cloud apps that were disabled + for (auto& device : old_device_map) { + std::string policy_app_id = device.second; + // First search for the disabled app within the registered apps + ApplicationSharedPtr app = application_by_policy_id(policy_app_id); + if (app.use_count() == 0) { + sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_); + // If the disabled app is not present in the registered app list, check + // the apps awaiting registration + PolicyAppIdPredicate finder(policy_app_id); + ApplicationSet::iterator it = std::find_if( + apps_to_register_.begin(), apps_to_register_.end(), finder); + if (it == apps_to_register_.end()) { + LOG4CXX_DEBUG(logger_, + "Unable to find app to remove (" << policy_app_id + << "), skipping"); + continue; + } + app = *it; + apps_to_register_.erase(it); + } + // If the disabled app is registered, unregistered it before destroying the + // device + if (app->IsRegistered() && app->is_cloud_app()) { + LOG4CXX_DEBUG(logger_, "Disabled app is registered, unregistering now"); + GetRPCService().ManageMobileCommand( + MessageHelper::GetOnAppInterfaceUnregisteredNotificationToMobile( + app->app_id(), + mobile_api::AppInterfaceUnregisteredReason::APP_UNAUTHORIZED), + commands::Command::SOURCE_SDL); + + OnAppUnauthorized(app->app_id()); + } + // Delete the cloud device + connection_handler().RemoveCloudAppDevice(app->device()); + removed_app_count++; + } + + // Update app list if disabled apps were removed + if (removed_app_count > 0) { + LOG4CXX_DEBUG(logger_, "Removed " << removed_app_count << " disabled apps"); + SendUpdateAppList(); + } +} + +void ApplicationManagerImpl::CreatePendingApplication( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info, + connection_handler::DeviceHandle device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + std::string endpoint; + std::string certificate; + std::string auth_token; + std::string cloud_transport_type; + std::string hybrid_app_preference_str; + bool enabled = true; + std::string name = device_info.name(); + pending_device_map_lock_ptr_->Acquire(); + auto it = pending_device_map_.find(name); + if (it == pending_device_map_.end()) { + pending_device_map_lock_ptr_->Release(); + return; + } + pending_device_map_lock_ptr_->Release(); + + const std::string policy_app_id = it->second; + + policy::StringArray nicknames; + policy::StringArray app_hmi_types; + + GetPolicyHandler().GetInitialAppData( + policy_app_id, &nicknames, &app_hmi_types); + + if (nicknames.empty()) { + LOG4CXX_ERROR(logger_, "Cloud App missing nickname"); + return; + } + + const std::string display_name = nicknames[0]; + + ApplicationSharedPtr application( + new ApplicationImpl(0, + policy_app_id, + device_info.mac_address(), + device_id, + custom_str::CustomString(display_name), + GetPolicyHandler().GetStatisticManager(), + *this)); + + if (!application) { + LOG4CXX_INFO(logger_, "Could not create application"); + return; + } + + const std::string app_icon_dir(settings_.app_icons_folder()); + const std::string full_icon_path(app_icon_dir + "/" + policy_app_id); + if (file_system::FileExists(full_icon_path)) { + application->set_app_icon_path(full_icon_path); + } + + GetPolicyHandler().GetCloudAppParameters(policy_app_id, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference_str); + + mobile_apis::HybridAppPreference::eType hybrid_app_preference_enum; + + bool convert_result = smart_objects::EnumConversionHelper< + mobile_apis::HybridAppPreference::eType>:: + StringToEnum(hybrid_app_preference_str, &hybrid_app_preference_enum); + + if (!hybrid_app_preference_str.empty() && !convert_result) { + LOG4CXX_ERROR( + logger_, + "Could not convert string to enum: " << hybrid_app_preference_str); + return; + } + + application->set_hmi_application_id(GenerateNewHMIAppID()); + application->set_cloud_app_endpoint(endpoint); + application->set_auth_token(auth_token); + application->set_cloud_app_transport_type(cloud_transport_type); + application->set_hybrid_app_preference(hybrid_app_preference_enum); + application->set_cloud_app_certificate(certificate); + + sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_); + LOG4CXX_DEBUG(logger_, + "apps_to_register_ size before: " << apps_to_register_.size()); + apps_to_register_.insert(application); + LOG4CXX_DEBUG(logger_, + "apps_to_register_ size after: " << apps_to_register_.size()); + + SendUpdateAppList(); +} + +void ApplicationManagerImpl::SetPendingApplicationState( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info) { + std::string name = device_info.name(); + pending_device_map_lock_ptr_->Acquire(); + auto it = pending_device_map_.find(name); + if (it == pending_device_map_.end()) { + pending_device_map_lock_ptr_->Release(); + return; + } + pending_device_map_lock_ptr_->Release(); + + const std::string policy_app_id = it->second; + auto app = application_by_policy_id(policy_app_id); + + if (!app) { + return; + } + LOG4CXX_DEBUG(logger_, + "Unregister application and move into apps_to_register"); + { + sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_); + apps_to_register_.insert(app); + } + + UnregisterApplication( + app->app_id(), mobile_apis::Result::INVALID_ENUM, true, true); + app->MarkUnregistered(); +} + +void ApplicationManagerImpl::OnConnectionStatusUpdated() { + SendUpdateAppList(); +} + +hmi_apis::Common_CloudConnectionStatus::eType +ApplicationManagerImpl::GetCloudAppConnectionStatus( + ApplicationConstSharedPtr app) const { + transport_manager::ConnectionStatus status = + connection_handler().GetConnectionStatus(app->device()); + switch (status) { + case transport_manager::ConnectionStatus::CONNECTED: + return hmi_apis::Common_CloudConnectionStatus::CONNECTED; + case transport_manager::ConnectionStatus::RETRY: + return hmi_apis::Common_CloudConnectionStatus::RETRY; + case transport_manager::ConnectionStatus::PENDING: + case transport_manager::ConnectionStatus::CLOSING: + return hmi_apis::Common_CloudConnectionStatus::NOT_CONNECTED; + default: + return hmi_apis::Common_CloudConnectionStatus::INVALID_ENUM; + } } uint32_t ApplicationManagerImpl::GetNextHMICorrelationID() { @@ -1003,6 +1446,7 @@ void ApplicationManagerImpl::OnDeviceListUpdated( so_to_send[jhs::S_PARAMS][jhs::S_CORRELATION_ID] = GetNextHMICorrelationID(); so_to_send[jhs::S_MSG_PARAMS] = *msg_params; rpc_service_->ManageHMICommand(update_list); + RefreshCloudAppInformation(); } void ApplicationManagerImpl::OnFindNewApplicationsRequest() { @@ -2479,6 +2923,7 @@ void ApplicationManagerImpl::UnregisterApplication( logger_, "There is no more SDL4 apps with device handle: " << handle); RemoveAppsWaitingForRegistration(handle); + RefreshCloudAppInformation(); SendUpdateAppList(); } } @@ -3363,6 +3808,15 @@ void ApplicationManagerImpl::OnPTUFinished(const bool ptu_result) { if (!ptu_result) { return; } + + RefreshCloudAppInformation(); + + auto app_id = policy_handler_->GetAppIdForSending(); + auto app = application(app_id); + if (app) { + SendGetIconUrlNotifications(app->app_id(), app); + } + auto on_app_policy_updated = [](plugin_manager::RPCPlugin& plugin) { plugin.OnPolicyEvent(plugin_manager::kApplicationPolicyUpdated); }; @@ -3405,6 +3859,58 @@ void ApplicationManagerImpl::SendDriverDistractionState( } } +void ApplicationManagerImpl::SendGetIconUrlNotifications( + const uint32_t connection_key, ApplicationSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + std::vector<std::string> enabled_apps; + GetPolicyHandler().GetEnabledCloudApps(enabled_apps); + std::vector<std::string>::iterator enabled_it = enabled_apps.begin(); + std::vector<std::string>::iterator enabled_end = enabled_apps.end(); + sync_primitives::AutoLock lock(app_icon_map_lock_ptr_); + for (; enabled_it != enabled_end; ++enabled_it) { + auto app_icon_it = app_icon_map_.find(*enabled_it); + if (app_icon_it == app_icon_map_.end()) { + LOG4CXX_WARN(logger_, "Could not find cloud app in icon map"); + continue; + } + + std::string endpoint = app_icon_it->second.endpoint; + bool pending_request = app_icon_it->second.pending_request; + + if (pending_request) { + LOG4CXX_DEBUG(logger_, "Cloud app has already sent request"); + continue; + } + + std::string url = GetPolicyHandler().GetIconUrl(*enabled_it); + + if (url.empty()) { + LOG4CXX_DEBUG(logger_, "No Icon Url for cloud app"); + continue; + } + + LOG4CXX_DEBUG(logger_, "Creating Get Icon Request"); + + smart_objects::SmartObjectSPtr message = + std::make_shared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + (*message)[strings::params][strings::function_id] = + mobile_apis::FunctionID::OnSystemRequestID; + (*message)[strings::params][strings::connection_key] = connection_key; + (*message)[strings::params][strings::message_type] = + mobile_apis::messageType::notification; + (*message)[strings::params][strings::protocol_version] = + application->protocol_version(); + (*message)[strings::msg_params][strings::request_type] = + mobile_apis::RequestType::ICON_URL; + (*message)[strings::msg_params][strings::url] = url; + + app_icon_it->second.pending_request = true; + + rpc_service_->ManageMobileCommand(message, commands::Command::SOURCE_SDL); + } +} + protocol_handler::MajorProtocolVersion ApplicationManagerImpl::SupportedSDLVersion() const { LOG4CXX_AUTO_TRACE(logger_); @@ -3642,6 +4148,13 @@ void ApplicationManagerImpl::AddMockApplication(ApplicationSharedPtr mock_app) { applications_list_lock_ptr_->Release(); } +void ApplicationManagerImpl::AddMockPendingApplication( + ApplicationSharedPtr mock_app) { + apps_to_register_list_lock_ptr_->Acquire(); + apps_to_register_.insert(mock_app); + apps_to_register_list_lock_ptr_->Release(); +} + void ApplicationManagerImpl::SetMockMediaManager( media_manager::MediaManager* mock_media_manager) { media_manager_ = mock_media_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 d2f338c3ce..cc291bbfe3 100644 --- a/src/components/application_manager/src/message_helper/message_helper.cc +++ b/src/components/application_manager/src/message_helper/message_helper.cc @@ -176,6 +176,8 @@ std::pair<std::string, mobile_apis::VehicleDataType::VEHICLEDATA_FUELCONSUMPTION), std::make_pair(strings::fuel_range, mobile_apis::VehicleDataType::VEHICLEDATA_FUELRANGE), + std::make_pair(strings::cloud_app_vehicle_id, + mobile_apis::VehicleDataType::VEHICLEDATA_CLOUDAPPVEHICLEID), std::make_pair(strings::external_temp, mobile_apis::VehicleDataType::VEHICLEDATA_EXTERNTEMP), std::make_pair(strings::turn_signal, @@ -1551,15 +1553,20 @@ bool MessageHelper::CreateHMIApplicationStruct( message = smart_objects::SmartObject(smart_objects::SmartType_Map); message[strings::app_name] = app->name(); message[strings::app_id] = app->hmi_app_id(); + + const std::string policy_app_id = app->policy_app_id(); + message[hmi_response::policy_app_id] = policy_app_id; + const std::string icon_path = app->app_icon_path(); - if (!icon_path.empty()) { + + if (file_system::FileExists(app->app_icon_path())) { message[strings::icon] = icon_path; } if (app->IsRegistered()) { message[strings::hmi_display_language_desired] = app->ui_language(); message[strings::is_media_application] = app->is_media_application(); } else { - message[strings::greyOut] = app->is_greyed_out(); + message[strings::grey_out] = app->is_greyed_out(); } if (app->tts_name() && !app->tts_name()->empty()) { message[json::ttsName] = *(app->tts_name()); @@ -1575,6 +1582,46 @@ bool MessageHelper::CreateHMIApplicationStruct( message[strings::app_type] = *app_types; } + const policy::RequestType::State app_request_types_state = + policy_handler.GetAppRequestTypeState(policy_app_id); + if (policy::RequestType::State::AVAILABLE == app_request_types_state) { + const auto request_types = policy_handler.GetAppRequestTypes(policy_app_id); + message[strings::request_type] = + SmartObject(smart_objects::SmartType_Array); + smart_objects::SmartObject& request_types_array = + message[strings::request_type]; + + size_t index = 0; + for (auto it : request_types) { + request_types_array[index] = it; + ++index; + } + } else if (policy::RequestType::State::EMPTY == app_request_types_state) { + message[strings::request_type] = + SmartObject(smart_objects::SmartType_Array); + } + + const policy::RequestSubType::State app_request_subtypes_state = + policy_handler.GetAppRequestSubTypeState(policy_app_id); + if (policy::RequestSubType::State::AVAILABLE == app_request_subtypes_state) { + const auto request_subtypes = + policy_handler.GetAppRequestSubTypes(policy_app_id); + message[strings::request_subtype] = + SmartObject(smart_objects::SmartType_Array); + smart_objects::SmartObject& request_subtypes_array = + message[strings::request_subtype]; + + size_t index = 0; + for (auto it : request_subtypes) { + request_subtypes_array[index] = it; + ++index; + } + } else if (policy::RequestSubType::State::EMPTY == + app_request_subtypes_state) { + message[strings::request_subtype] = + SmartObject(smart_objects::SmartType_Array); + } + if (day_color_scheme) { message[strings::day_color_scheme] = *day_color_scheme; } @@ -1601,6 +1648,12 @@ bool MessageHelper::CreateHMIApplicationStruct( &secondary_device_info); } + message[strings::is_cloud_application] = app->is_cloud_app(); + if (app->is_cloud_app()) { + message[strings::cloud_connection_status] = + app_mngr.GetCloudAppConnectionStatus(app); + } + return true; } diff --git a/src/components/application_manager/src/policies/policy_handler.cc b/src/components/application_manager/src/policies/policy_handler.cc index 1b64c5d7b4..691ac21040 100644 --- a/src/components/application_manager/src/policies/policy_handler.cc +++ b/src/components/application_manager/src/policies/policy_handler.cc @@ -54,6 +54,7 @@ #include "interfaces/MOBILE_API.h" #include "utils/file_system.h" #include "utils/scope_guard.h" +#include "smart_objects/enum_schema_item.h" #include "utils/helpers.h" #include "policy/policy_manager.h" @@ -90,7 +91,8 @@ RequestTypeMap TypeToString = { {mobile_apis::RequestType::EMERGENCY, "EMERGENCY"}, {mobile_apis::RequestType::MEDIA, "MEDIA"}, {mobile_apis::RequestType::FOTA, "FOTA"}, - {mobile_apis::RequestType::OEM_SPECIFIC, "OEM_SPECIFIC"}}; + {mobile_apis::RequestType::OEM_SPECIFIC, "OEM_SPECIFIC"}, + {mobile_apis::RequestType::ICON_URL, "ICON_URL"}}; const std::string RequestTypeToString(mobile_apis::RequestType::eType type) { RequestTypeMap::const_iterator it = TypeToString.find(type); @@ -1575,6 +1577,11 @@ std::string PolicyHandler::GetLockScreenIconUrl() const { return policy_manager_->GetLockScreenIconUrl(); } +std::string PolicyHandler::GetIconUrl(const std::string& policy_app_id) const { + POLICY_LIB_CHECK(std::string("")); + return policy_manager_->GetIconUrl(policy_app_id); +} + uint32_t PolicyHandler::NextRetryTimeout() { POLICY_LIB_CHECK(0); LOG4CXX_AUTO_TRACE(logger_); @@ -1770,6 +1777,17 @@ void PolicyHandler::OnCertificateUpdated(const std::string& certificate_data) { } #endif // EXTERNAL_PROPRIETARY_MODE +void PolicyHandler::OnAuthTokenUpdated(const std::string& policy_app_id, + const std::string& auth_token) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(listeners_lock_); + HandlersCollection::const_iterator it = listeners_.begin(); + for (; it != listeners_.end(); ++it) { + PolicyHandlerObserver* observer = *it; + observer->OnAuthTokenUpdated(policy_app_id, auth_token); + } +} + void PolicyHandler::OnPTUFinished(const bool ptu_result) { LOG4CXX_AUTO_TRACE(logger_); sync_primitives::AutoLock lock(listeners_lock_); @@ -1845,6 +1863,130 @@ bool PolicyHandler::CheckSystemAction( return false; } +void PolicyHandler::GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const { + POLICY_LIB_CHECK_VOID(); + policy_manager_->GetEnabledCloudApps(enabled_apps); +} + +bool PolicyHandler::GetCloudAppParameters( + const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const { + POLICY_LIB_CHECK(false); + return policy_manager_->GetCloudAppParameters(policy_app_id, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference); +} + +const bool PolicyHandler::CheckCloudAppEnabled( + const std::string& policy_app_id) const { + POLICY_LIB_CHECK(false); + bool enabled = false; + std::string endpoint; + std::string auth_token; + std::string certificate; + std::string cloud_transport_type; + std::string hybrid_app_preference; + policy_manager_->GetCloudAppParameters(policy_app_id, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference); + return enabled; +} + +void PolicyHandler::OnSetCloudAppProperties( + const smart_objects::SmartObject& message) { + POLICY_LIB_CHECK_VOID(); + if (!message.keyExists(strings::msg_params)) { + LOG4CXX_ERROR(logger_, + "Message does not contain mandatory section " + << strings::msg_params); + return; + } + if (!message[strings::msg_params].keyExists(strings::properties)) { + LOG4CXX_ERROR(logger_, + "Message does not contain app properties " + << strings::msg_params); + return; + } + + const smart_objects::SmartObject& properties = + message[strings::msg_params][strings::properties]; + if (!properties.keyExists(strings::app_id)) { + LOG4CXX_ERROR(logger_, + "Message does not contain mandatory parameter " + << strings::app_id); + return; + } + std::string policy_app_id(properties[strings::app_id].asString()); + + policy_manager_->InitCloudApp(policy_app_id); + + bool auth_token_update = false; + if (properties.keyExists(strings::enabled)) { + bool enabled = properties[strings::enabled].asBool(); + policy_manager_->SetCloudAppEnabled(policy_app_id, enabled); + auth_token_update = enabled; + application_manager_.RefreshCloudAppInformation(); + } + if (properties.keyExists(strings::auth_token)) { + std::string auth_token = properties[strings::auth_token].asString(); + policy_manager_->SetAppAuthToken(policy_app_id, auth_token); + auth_token_update = true; + } + if (properties.keyExists(strings::cloud_transport_type)) { + policy_manager_->SetAppCloudTransportType( + policy_app_id, properties[strings::cloud_transport_type].asString()); + } + if (properties.keyExists(strings::endpoint)) { + policy_manager_->SetAppEndpoint(policy_app_id, + properties[strings::endpoint].asString()); + } + if (properties.keyExists(strings::nicknames)) { + StringArray nicknames; + const smart_objects::SmartObject& nicknames_array = + properties[strings::nicknames]; + for (size_t i = 0; i < nicknames_array.length(); ++i) { + nicknames.push_back(nicknames_array[i].asString()); + } + policy_manager_->SetAppNicknames(policy_app_id, nicknames); + } + if (properties.keyExists(strings::hybrid_app_preference)) { + std::string hybrid_app_preference; + + mobile_apis::HybridAppPreference::eType value = + static_cast<mobile_apis::HybridAppPreference::eType>( + properties[strings::hybrid_app_preference].asUInt()); + smart_objects::EnumConversionHelper< + mobile_apis::HybridAppPreference::eType>:: + EnumToString(value, &hybrid_app_preference); + policy_manager_->SetHybridAppPreference(policy_app_id, + hybrid_app_preference); + } + + if (auth_token_update) { + bool enabled; + std::string end, cert, ctt, hap; + std::string auth_token; + + policy_manager_->GetCloudAppParameters( + policy_app_id, enabled, end, cert, auth_token, ctt, hap); + OnAuthTokenUpdated(policy_app_id, auth_token); + } +} + uint32_t PolicyHandler::HeartBeatTimeout(const std::string& app_id) const { POLICY_LIB_CHECK(0); return policy_manager_->HeartBeatTimeout(app_id); 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 3e77078ee5..6af8826491 100644 --- a/src/components/application_manager/src/resumption/resume_ctrl_impl.cc +++ b/src/components/application_manager/src/resumption/resume_ctrl_impl.cc @@ -399,7 +399,13 @@ bool ResumeCtrlImpl::StartResumption(ApplicationSharedPtr application, << " hmi_app_id = " << application->hmi_app_id() << " policy_id = " << application->policy_app_id() << " received hash = " << hash); - SetupDefaultHMILevel(application); + if (!application->is_cloud_app()) { + // Default HMI Level is already set before resumption in + // ApplicationManager::OnApplicationRegistered, and handling low bandwidth + // transports doesn't apply to cloud apps, so this step can be skipped for + // such apps + SetupDefaultHMILevel(application); + } smart_objects::SmartObject saved_app; const std::string& device_mac = application->mac_address(); bool result = resumption_storage_->GetSavedApplication( @@ -426,7 +432,13 @@ bool ResumeCtrlImpl::StartResumptionOnlyHMILevel( << application->app_id() << "with hmi_app_id " << application->hmi_app_id() << ", policy_app_id " << application->policy_app_id()); - SetupDefaultHMILevel(application); + if (!application->is_cloud_app()) { + // Default HMI Level is already set before resumption in + // ApplicationManager::OnApplicationRegistered, and handling low bandwidth + // transports doesn't apply to cloud apps, so this step can be skipped for + // such apps + SetupDefaultHMILevel(application); + } const std::string& device_mac = application->mac_address(); smart_objects::SmartObject saved_app; bool result = resumption_storage_->GetSavedApplication( diff --git a/src/components/application_manager/src/smart_object_keys.cc b/src/components/application_manager/src/smart_object_keys.cc index ff9ebb6208..485b59c520 100644 --- a/src/components/application_manager/src/smart_object_keys.cc +++ b/src/components/application_manager/src/smart_object_keys.cc @@ -43,7 +43,7 @@ const char* ngn_media_screen_app_name = "ngnMediaScreenAppName"; const char* vr_synonyms = "vrSynonyms"; const char* uses_vehicle_data = "usesVehicleData"; const char* is_media_application = "isMediaApplication"; -const char* greyOut = "greyOut"; +const char* grey_out = "greyOut"; const char* language_desired = "languageDesired"; const char* auto_activated_id = "autoActivateID"; const char* app_type = "appType"; @@ -155,6 +155,14 @@ const char* green = "green"; const char* blue = "blue"; const char* display_layout = "displayLayout"; const char* icon_resumed = "iconResumed"; +const char* nicknames = "nicknames"; +const char* enabled = "enabled"; +const char* auth_token = "authToken"; +const char* cloud_transport_type = "cloudTransportType"; +const char* hybrid_app_preference = "hybridAppPreference"; +const char* is_cloud_application = "isCloudApplication"; +const char* cloud_connection_status = "cloudConnectionStatus"; +const char* endpoint = "endpoint"; // PutFile const char* sync_file_name = "syncFileName"; @@ -220,6 +228,7 @@ const char* fuel_level = "fuelLevel"; const char* fuel_level_state = "fuelLevel_State"; const char* instant_fuel_consumption = "instantFuelConsumption"; const char* fuel_range = "fuelRange"; +const char* cloud_app_vehicle_id = "cloudAppVehicleID"; const char* external_temp = "externalTemperature"; const char* turn_signal = "turnSignal"; const char* vin = "vin"; diff --git a/src/components/application_manager/src/state_controller_impl.cc b/src/components/application_manager/src/state_controller_impl.cc index 3d44709657..5e912ca3be 100644 --- a/src/components/application_manager/src/state_controller_impl.cc +++ b/src/components/application_manager/src/state_controller_impl.cc @@ -475,7 +475,9 @@ mobile_apis::HMILevel::eType StateControllerImpl::GetAvailableHmiLevel( return result; } - const bool is_active_app_exist = (bool)app_mngr_.active_application(); + ApplicationConstSharedPtr active_app = app_mngr_.active_application(); + const bool is_active_app_exist = + (active_app.use_count() != 0) && active_app->app_id() != app->app_id(); if (is_audio_app) { if (does_audio_app_with_same_type_exist) { result = app_mngr_.GetDefaultHmiLevel(app); diff --git a/src/components/application_manager/test/application_manager_impl_test.cc b/src/components/application_manager/test/application_manager_impl_test.cc index 7e57b51329..d4e73ef492 100644 --- a/src/components/application_manager/test/application_manager_impl_test.cc +++ b/src/components/application_manager/test/application_manager_impl_test.cc @@ -96,6 +96,14 @@ connection_handler::DeviceHandle kDeviceId = 12345u; const std::string kAppId = "someID"; const uint32_t kConnectionKey = 1232u; const std::string kAppName = "appName"; + +// Cloud application params +const std::string kEndpoint = "endpoint"; +const std::string kAuthToken = "auth_token"; +const std::string kCertificate = "cert"; +const std::string kTransportType = "WS"; +const mobile_api::HybridAppPreference::eType kHybridAppPreference = + mobile_api::HybridAppPreference::CLOUD; } // namespace class ApplicationManagerImplTest : public ::testing::Test { @@ -122,11 +130,11 @@ class ApplicationManagerImplTest : public ::testing::Test { protected: void SetUp() OVERRIDE { CreateAppManager(); - ON_CALL(mock_connection_handler_, GetDataOnSessionKey(_, _, _, &kDeviceId)) - .WillByDefault(DoAll(SetArgPointee<3u>(app_id_), Return(0))); + ON_CALL(mock_session_observer_, GetDataOnSessionKey(_, _, _, _)) + .WillByDefault(DoAll(SetArgPointee<3u>(kDeviceId), Return(0))); ON_CALL(mock_connection_handler_, get_session_observer()) .WillByDefault(ReturnRef(mock_session_observer_)); - app_manager_impl_->SetRPCService(mock_rpc_service_); + app_manager_impl_->SetMockRPCService(mock_rpc_service_); app_manager_impl_->resume_controller().set_resumption_storage( mock_storage_); app_manager_impl_->set_connection_handler(&mock_connection_handler_); @@ -200,7 +208,7 @@ class ApplicationManagerImplTest : public ::testing::Test { NiceMock<policy_test::MockPolicySettings> mock_policy_settings_; std::shared_ptr<NiceMock<resumption_test::MockResumptionData> > mock_storage_; - std::unique_ptr<rpc_service::RPCService> mock_rpc_service_; + MockRPCService* mock_rpc_service_; NiceMock<con_test::MockConnectionHandler> mock_connection_handler_; NiceMock<protocol_handler_test::MockSessionObserver> mock_session_observer_; NiceMock<MockApplicationManagerSettings> mock_application_manager_settings_; @@ -1413,6 +1421,120 @@ TEST_F(ApplicationManagerImplTest, EXPECT_TRUE(file_system::RemoveDirectory(kDirectoryName, true)); } +TEST_F(ApplicationManagerImplTest, + RegisterApplication_CloudAppRegisterSuccess) { + std::shared_ptr<MockApplication> waiting_app = + std::make_shared<MockApplication>(); + ON_CALL(*waiting_app, device()).WillByDefault(Return(kDeviceId)); + EXPECT_CALL(*waiting_app, cloud_app_endpoint()) + .WillOnce(ReturnRef(kEndpoint)); + EXPECT_CALL(*waiting_app, auth_token()).WillOnce(ReturnRef(kAuthToken)); + EXPECT_CALL(*waiting_app, cloud_app_certificate()) + .WillOnce(ReturnRef(kCertificate)); + EXPECT_CALL(*waiting_app, cloud_app_transport_type()) + .WillOnce(ReturnRef(kTransportType)); + EXPECT_CALL(*waiting_app, hybrid_app_preference()) + .WillOnce(ReturnRef(kHybridAppPreference)); + ON_CALL(*waiting_app, is_cloud_app()).WillByDefault(Return(true)); + EXPECT_CALL(*waiting_app, policy_app_id()).WillRepeatedly(Return(kAppId)); + app_manager_impl_->AddMockPendingApplication(waiting_app); + + EXPECT_CALL( + mock_session_observer_, + GetDataOnSessionKey(kConnectionKey, + _, + _, + testing::An<connection_handler::DeviceHandle*>())) + .WillOnce(DoAll(SetArgPointee<3u>(kDeviceId), Return(0))); + EXPECT_CALL(*mock_rpc_service_, + ManageMobileCommand(_, commands::Command::SOURCE_SDL)).Times(0); + smart_objects::SmartObject request_for_registration( + smart_objects::SmartType_Map); + + smart_objects::SmartObject& params = + request_for_registration[strings::msg_params]; + params[strings::app_id] = kAppId; + params[strings::language_desired] = mobile_api::Language::EN_US; + params[strings::hmi_display_language_desired] = mobile_api::Language::EN_US; + + request_for_registration[strings::params][strings::connection_key] = + kConnectionKey; + request_for_registration[strings::msg_params][strings::app_name] = kAppName; + request_for_registration[strings::msg_params][strings::sync_msg_version] + [strings::minor_version] = APIVersion::kAPIV2; + request_for_registration[strings::msg_params][strings::sync_msg_version] + [strings::major_version] = APIVersion::kAPIV3; + + request_for_registration[strings::params][strings::protocol_version] = + protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_2; + + smart_objects::SmartObjectSPtr request_for_registration_ptr = + std::make_shared<smart_objects::SmartObject>(request_for_registration); + + ApplicationSharedPtr application = + app_manager_impl_->RegisterApplication(request_for_registration_ptr); + + EXPECT_EQ(protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_2, + application->protocol_version()); + EXPECT_EQ(APIVersion::kAPIV2, + application->version().min_supported_api_version); + EXPECT_EQ(APIVersion::kAPIV3, + application->version().max_supported_api_version); + EXPECT_EQ(kEndpoint, application->cloud_app_endpoint()); + EXPECT_EQ(kAuthToken, application->auth_token()); + EXPECT_EQ(kCertificate, application->cloud_app_certificate()); + EXPECT_EQ(kTransportType, application->cloud_app_transport_type()); + EXPECT_EQ(kHybridAppPreference, application->hybrid_app_preference()); +} + +TEST_F(ApplicationManagerImplTest, + RegisterApplication_CloudAppRegisterFailed_DISALLOWED) { + std::shared_ptr<MockApplication> waiting_app = + std::make_shared<MockApplication>(); + EXPECT_CALL(*waiting_app, device()).WillRepeatedly(Return(kDeviceId)); + EXPECT_CALL(*waiting_app, is_cloud_app()).WillRepeatedly(Return(true)); + EXPECT_CALL(*waiting_app, policy_app_id()) + .WillRepeatedly(Return("Fake" + kAppId)); + app_manager_impl_->AddMockPendingApplication(waiting_app); + + EXPECT_CALL( + mock_session_observer_, + GetDataOnSessionKey(kConnectionKey, + _, + _, + testing::An<connection_handler::DeviceHandle*>())) + .WillOnce(DoAll(SetArgPointee<3u>(kDeviceId), Return(0))); + EXPECT_CALL(*mock_rpc_service_, + ManageMobileCommand(_, commands::Command::SOURCE_SDL)) + .WillOnce(Return(true)); + smart_objects::SmartObject request_for_registration( + smart_objects::SmartType_Map); + + smart_objects::SmartObject& params = + request_for_registration[strings::msg_params]; + params[strings::app_id] = kAppId; + params[strings::language_desired] = mobile_api::Language::EN_US; + params[strings::hmi_display_language_desired] = mobile_api::Language::EN_US; + + request_for_registration[strings::params][strings::connection_key] = + kConnectionKey; + request_for_registration[strings::msg_params][strings::app_name] = kAppName; + request_for_registration[strings::msg_params][strings::sync_msg_version] + [strings::minor_version] = APIVersion::kAPIV2; + request_for_registration[strings::msg_params][strings::sync_msg_version] + [strings::major_version] = APIVersion::kAPIV3; + + request_for_registration[strings::params][strings::protocol_version] = + protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_2; + + smart_objects::SmartObjectSPtr request_for_registration_ptr = + std::make_shared<smart_objects::SmartObject>(request_for_registration); + + ApplicationSharedPtr application = + app_manager_impl_->RegisterApplication(request_for_registration_ptr); + EXPECT_EQ(0, application.use_count()); +} + } // application_manager_test } // namespace components } // namespace test 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 fe16e8ce6e..36d20f227d 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 @@ -342,6 +342,21 @@ class MockApplication : public ::application_manager::Application { const std::list<application_manager::AppExtensionPtr>&()); MOCK_CONST_METHOD0(is_remote_control_supported, bool()); MOCK_METHOD1(set_remote_control_supported, void(const bool allow)); + MOCK_CONST_METHOD0(cloud_app_endpoint, const std::string&()); + MOCK_CONST_METHOD0(auth_token, const std::string&()); + MOCK_CONST_METHOD0(cloud_app_transport_type, const std::string&()); + MOCK_CONST_METHOD0(hybrid_app_preference, + const mobile_apis::HybridAppPreference::eType&()); + MOCK_CONST_METHOD0(cloud_app_certificate, const std::string&()); + MOCK_CONST_METHOD0(is_cloud_app, bool()); + MOCK_METHOD1(set_cloud_app_endpoint, void(const std::string& endpoint)); + MOCK_METHOD1(set_auth_token, void(const std::string& auth_token)); + MOCK_METHOD1(set_cloud_app_transport_type, + void(const std::string& transport_type)); + MOCK_METHOD1(set_hybrid_app_preference, + void(const mobile_apis::HybridAppPreference::eType& + hybrid_app_preference)); + MOCK_METHOD1(set_cloud_app_certificate, void(const std::string& certificate)); }; } // namespace application_manager_test 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 1c2339096c..2413421c7f 100644 --- a/src/components/application_manager/test/resumption/resume_ctrl_test.cc +++ b/src/components/application_manager/test/resumption/resume_ctrl_test.cc @@ -153,6 +153,7 @@ class ResumeCtrlTest : public ::testing::Test { ON_CALL(*mock_app_, mac_address()).WillByDefault(ReturnRef(kMacAddress_)); ON_CALL(*mock_app_, device()).WillByDefault(Return(kTestDevId_)); ON_CALL(*mock_app_, app_id()).WillByDefault(Return(kTestAppId_)); + ON_CALL(*mock_app_, is_cloud_app()).WillByDefault(Return(false)); } NiceMock<event_engine_test::MockEventDispatcher> mock_event_dispatcher_; diff --git a/src/components/application_manager/test/sdl_preloaded_pt.json b/src/components/application_manager/test/sdl_preloaded_pt.json index 59e3f947c3..ad264c8518 100644 --- a/src/components/application_manager/test/sdl_preloaded_pt.json +++ b/src/components/application_manager/test/sdl_preloaded_pt.json @@ -363,6 +363,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -383,6 +384,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -403,6 +405,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] @@ -422,6 +425,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] diff --git a/src/components/application_manager/test/sdl_pt_update.json b/src/components/application_manager/test/sdl_pt_update.json index 23c75e8475..17b07f797f 100644 --- a/src/components/application_manager/test/sdl_pt_update.json +++ b/src/components/application_manager/test/sdl_pt_update.json @@ -1600,6 +1600,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1618,6 +1619,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1636,6 +1638,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1653,6 +1656,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/config_profile/include/config_profile/profile.h b/src/components/config_profile/include/config_profile/profile.h index 57e925cd43..4846648b2b 100644 --- a/src/components/config_profile/include/config_profile/profile.h +++ b/src/components/config_profile/include/config_profile/profile.h @@ -413,6 +413,16 @@ class Profile : public protocol_handler::ProtocolHandlerSettings, const std::string& transport_manager_tcp_adapter_network_interface() const OVERRIDE; + /** + * @brief Returns retry timeout for cloud app connections + */ + uint32_t cloud_app_retry_timeout() const OVERRIDE; + + /** + * @brief Returns maximum retry attempts for cloud app connections + */ + uint16_t cloud_app_max_retry_attempts() const OVERRIDE; + // TransportManageMMESettings interface const std::string& event_mq_name() const OVERRIDE; @@ -960,6 +970,8 @@ class Profile : public protocol_handler::ProtocolHandlerSettings, std::string system_files_path_; uint16_t transport_manager_tcp_adapter_port_; std::string transport_manager_tcp_adapter_network_interface_; + uint32_t cloud_app_retry_timeout_; + uint16_t cloud_app_max_retry_attempts_; std::string tts_delimiter_; uint32_t audio_data_stopped_timeout_; uint32_t video_data_stopped_timeout_; diff --git a/src/components/config_profile/src/profile.cc b/src/components/config_profile/src/profile.cc index 57984324aa..38afdbf35b 100644 --- a/src/components/config_profile/src/profile.cc +++ b/src/components/config_profile/src/profile.cc @@ -81,6 +81,7 @@ const char* kMediaManagerSection = "MEDIA MANAGER"; const char* kGlobalPropertiesSection = "GLOBAL PROPERTIES"; const char* kVrCommandsSection = "VR COMMANDS"; const char* kTransportManagerSection = "TransportManager"; +const char* kCloudAppTransportSection = "CloudAppConnections"; const char* kApplicationManagerSection = "ApplicationManager"; const char* kFilesystemRestrictionsSection = "FILESYSTEM RESTRICTIONS"; const char* kIAPSection = "IAP"; @@ -154,6 +155,8 @@ const char* kMaxSupportedProtocolVersionKey = "MaxSupportedProtocolVersion"; const char* kUseLastStateKey = "UseLastState"; const char* kTCPAdapterPortKey = "TCPAdapterPort"; const char* kTCPAdapterNetworkInterfaceKey = "TCPAdapterNetworkInterface"; +const char* kCloudAppRetryTimeoutKey = "CloudAppRetryTimeout"; +const char* kCloudAppMaxRetryAttemptsKey = "CloudAppMaxRetryAttempts"; const char* kServerPortKey = "ServerPort"; const char* kVideoStreamingPortKey = "VideoStreamingPort"; const char* kAudioStreamingPortKey = "AudioStreamingPort"; @@ -318,6 +321,8 @@ const uint32_t kDefaultHubProtocolIndex = 0; const uint32_t kDefaultHeartBeatTimeout = 0; const uint16_t kDefaultMaxSupportedProtocolVersion = 5; const uint16_t kDefautTransportManagerTCPPort = 12345; +const uint16_t kDefaultCloudAppRetryTimeout = 1000; +const uint16_t kDefaultCloudAppMaxRetryAttempts = 5; const uint16_t kDefaultServerPort = 8087; const uint16_t kDefaultVideoStreamingPort = 5050; const uint16_t kDefaultAudioStreamingPort = 5080; @@ -452,6 +457,8 @@ Profile::Profile() , supported_diag_modes_() , system_files_path_(kDefaultSystemFilesPath) , transport_manager_tcp_adapter_port_(kDefautTransportManagerTCPPort) + , cloud_app_retry_timeout_(kDefaultCloudAppRetryTimeout) + , cloud_app_max_retry_attempts_(kDefaultCloudAppMaxRetryAttempts) , tts_delimiter_(kDefaultTtsDelimiter) , audio_data_stopped_timeout_(kDefaultAudioDataStoppedTimeout) , video_data_stopped_timeout_(kDefaultVideoDataStoppedTimeout) @@ -784,6 +791,14 @@ const std::string& Profile::transport_manager_tcp_adapter_network_interface() return transport_manager_tcp_adapter_network_interface_; } +uint32_t Profile::cloud_app_retry_timeout() const { + return cloud_app_retry_timeout_; +} + +uint16_t Profile::cloud_app_max_retry_attempts() const { + return cloud_app_max_retry_attempts_; +} + const std::string& Profile::tts_delimiter() const { return tts_delimiter_; } @@ -1769,6 +1784,24 @@ void Profile::UpdateValues() { kTCPAdapterNetworkInterfaceKey, kTransportManagerSection); + ReadUIntValue(&cloud_app_retry_timeout_, + kDefaultCloudAppRetryTimeout, + kCloudAppTransportSection, + kCloudAppRetryTimeoutKey); + + LOG_UPDATED_VALUE(cloud_app_retry_timeout_, + kCloudAppRetryTimeoutKey, + kCloudAppTransportSection); + + ReadUIntValue(&cloud_app_max_retry_attempts_, + kDefaultCloudAppMaxRetryAttempts, + kCloudAppTransportSection, + kCloudAppMaxRetryAttemptsKey); + + LOG_UPDATED_VALUE(cloud_app_max_retry_attempts_, + kCloudAppMaxRetryAttemptsKey, + kCloudAppTransportSection); + // Event MQ ReadStringValue( &event_mq_name_, kDefaultEventMQ, kTransportManagerSection, kEventMQKey); diff --git a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h index 1ab70ce702..06eb4f232d 100644 --- a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h +++ b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h @@ -81,7 +81,7 @@ class ConnectionHandlerImpl ConnectionHandlerImpl(const ConnectionHandlerSettings& settings, transport_manager::TransportManager& tm); /** - * \brief Destructor + * @brief Destructor */ ~ConnectionHandlerImpl(); @@ -102,11 +102,21 @@ class ConnectionHandlerImpl /** * \brief Connects to all services of device - * \param deviceHandle Handle of device to connect to + * \param device_handle Handle of device to connect to */ void ConnectToDevice(connection_handler::DeviceHandle device_handle) OVERRIDE; /** + * @brief Retrieves the connection status of a given device + * + * @param device_handle Handle of device to query + * + * @return The connection status of the given device + */ + transport_manager::ConnectionStatus GetConnectionStatus( + const DeviceHandle& device_handle) const OVERRIDE; + + /** * @brief RunAppOnDevice allows to run specific application on the certain *device. * @@ -120,6 +130,13 @@ class ConnectionHandlerImpl void ConnectToAllDevices() OVERRIDE; + void AddCloudAppDevice( + const std::string& policy_app_id, + const transport_manager::transport_adapter::CloudAppProperties& + cloud_properties) OVERRIDE; + + void RemoveCloudAppDevice(const DeviceHandle device_id) OVERRIDE; + void StartTransportManager() OVERRIDE; void OnDeviceListUpdated( @@ -162,6 +179,16 @@ class ConnectionHandlerImpl void OnScanDevicesFailed( const transport_manager::SearchDeviceError& error) OVERRIDE; + void OnConnectionStatusUpdated() OVERRIDE; + + /** + * \brief Notifies about pending connection. + * + * \param connection_id ID of new connection. + **/ + void OnConnectionPending( + const transport_manager::DeviceInfo& device_info, + const transport_manager::ConnectionUID connection_id) OVERRIDE; /** * \brief Notifies about established connection. * @@ -352,6 +379,15 @@ class ConnectionHandlerImpl const protocol_handler::ServiceType& service_type) const OVERRIDE; /** + * @brief Get cloud app id by connection id + * @param connection_id unique connection id + * @return the policy app id of the cloud app if the connection is tied to a + * cloud app, an empty string otherwise. + */ + std::string GetCloudAppID( + const transport_manager::ConnectionUID connection_id) const OVERRIDE; + + /** * \brief Get device handle by mac address * \param mac_address uniq address * \param device_handle @@ -629,6 +665,12 @@ class ConnectionHandlerImpl std::map<uint32_t, protocol_handler::SessionContext> start_service_context_map_; + // Map app id -> (cloud_app_endpoint, connection_uid) + mutable sync_primitives::Lock cloud_app_id_map_lock_; + std::map<std::string, + std::pair<std::string, transport_manager::ConnectionUID> > + cloud_app_id_map_; + /** * @brief connection object as it's being closed */ diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc index 478127c42a..7e93e04047 100644 --- a/src/components/connection_handler/src/connection_handler_impl.cc +++ b/src/components/connection_handler/src/connection_handler_impl.cc @@ -142,6 +142,11 @@ void ConnectionHandlerImpl::OnDeviceAdded( LOG4CXX_AUTO_TRACE(logger_); auto handle = device_info.device_handle(); + LOG4CXX_DEBUG(logger_, + "OnDeviceAdded!!!: " << handle << " " << device_info.name() + << " " << device_info.mac_address() << " " + << device_info.connection_type()); + Device device(handle, device_info.name(), device_info.mac_address(), @@ -244,11 +249,69 @@ void ConnectionHandlerImpl::OnScanDevicesFailed( LOG4CXX_WARN(logger_, "Scan devices failed. " << error.text()); } -void ConnectionHandlerImpl::OnConnectionEstablished( +void ConnectionHandlerImpl::OnConnectionStatusUpdated() { + connection_handler_observer_->OnConnectionStatusUpdated(); +} + +void ConnectionHandlerImpl::OnConnectionPending( const transport_manager::DeviceInfo& device_info, const transport_manager::ConnectionUID connection_id) { LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, + "OnConnectionEstablished!!!: " + << device_info.device_handle() << " " << device_info.name() + << " " << device_info.mac_address() << " " + << device_info.connection_type()); + DeviceMap::iterator it = device_list_.find(device_info.device_handle()); + if (device_list_.end() == it) { + LOG4CXX_ERROR(logger_, "Unknown device!"); + return; + } + LOG4CXX_DEBUG(logger_, + "Add Pending Connection #" << connection_id << " to the list."); + + std::string endpoint = device_info.mac_address(); + cloud_app_id_map_lock_.Acquire(); + for (auto it = cloud_app_id_map_.begin(); it != cloud_app_id_map_.end(); + ++it) { + if (endpoint == it->second.first) { + it->second.second = connection_id; + break; + } + } + cloud_app_id_map_lock_.Release(); + + sync_primitives::AutoWriteLock lock(connection_list_lock_); + if (connection_list_.find(connection_id) == connection_list_.end()) { + Connection* connection = + new Connection(connection_id, + device_info.device_handle(), + this, + get_settings().heart_beat_timeout()); + + connection_list_.insert( + ConnectionList::value_type(connection_id, connection)); + + connection_handler::DeviceHandle device_id = + connection->connection_device_handle(); + connection_handler_observer_->CreatePendingApplication( + connection_id, device_info, device_id); + } else { + connection_handler_observer_->SetPendingApplicationState(connection_id, + device_info); + } +} + +void ConnectionHandlerImpl::OnConnectionEstablished( + const transport_manager::DeviceInfo& device_info, + const transport_manager::ConnectionUID connection_id) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, + "OnConnectionEstablished!!!: " + << device_info.device_handle() << " " << device_info.name() + << " " << device_info.mac_address() << " " + << device_info.connection_type()); DeviceMap::iterator it = device_list_.find(device_info.device_handle()); if (device_list_.end() == it) { LOG4CXX_ERROR(logger_, "Unknown device!"); @@ -257,12 +320,14 @@ void ConnectionHandlerImpl::OnConnectionEstablished( LOG4CXX_DEBUG(logger_, "Add Connection #" << connection_id << " to the list."); sync_primitives::AutoWriteLock lock(connection_list_lock_); - connection_list_.insert(ConnectionList::value_type( - connection_id, - new Connection(connection_id, - device_info.device_handle(), - this, - get_settings().heart_beat_timeout()))); + if (connection_list_.find(connection_id) == connection_list_.end()) { + connection_list_.insert(ConnectionList::value_type( + connection_id, + new Connection(connection_id, + device_info.device_handle(), + this, + get_settings().heart_beat_timeout()))); + } } void ConnectionHandlerImpl::OnConnectionFailed( @@ -1057,6 +1122,18 @@ const uint8_t ConnectionHandlerImpl::GetSessionIdFromSecondaryTransport( return 0; } +std::string ConnectionHandlerImpl::GetCloudAppID( + const transport_manager::ConnectionUID connection_id) const { + sync_primitives::AutoLock auto_lock(cloud_app_id_map_lock_); + for (auto it = cloud_app_id_map_.begin(); it != cloud_app_id_map_.end(); + ++it) { + if (connection_id == it->second.second) { + return it->first; + } + } + return std::string(); +} + struct CompareMAC { explicit CompareMAC(const std::string& mac) : mac_(mac) {} bool operator()(const DeviceMap::value_type& device) { @@ -1245,6 +1322,11 @@ void ConnectionHandlerImpl::ConnectToDevice( } } +transport_manager::ConnectionStatus ConnectionHandlerImpl::GetConnectionStatus( + const DeviceHandle& device_handle) const { + return transport_manager_.GetConnectionStatus(device_handle); +} + void ConnectionHandlerImpl::RunAppOnDevice(const std::string& device_mac, const std::string& bundle_id) const { for (DeviceMap::const_iterator i = device_list_.begin(); @@ -1267,6 +1349,21 @@ void ConnectionHandlerImpl::ConnectToAllDevices() { } } +void ConnectionHandlerImpl::AddCloudAppDevice( + const std::string& policy_app_id, + const transport_manager::transport_adapter::CloudAppProperties& + cloud_properties) { + cloud_app_id_map_lock_.Acquire(); + cloud_app_id_map_[policy_app_id] = + std::make_pair(cloud_properties.endpoint, 0); + cloud_app_id_map_lock_.Release(); + transport_manager_.AddCloudDevice(cloud_properties); +} + +void ConnectionHandlerImpl::RemoveCloudAppDevice(const DeviceHandle device_id) { + transport_manager_.RemoveCloudDevice(device_id); +} + void ConnectionHandlerImpl::StartTransportManager() { LOG4CXX_AUTO_TRACE(logger_); transport_manager_.Visibility(true); diff --git a/src/components/include/application_manager/application_manager.h b/src/components/include/application_manager/application_manager.h index e6e5c89f45..67be49a224 100644 --- a/src/components/include/application_manager/application_manager.h +++ b/src/components/include/application_manager/application_manager.h @@ -152,6 +152,8 @@ class ApplicationManager { connection_handler::ConnectionHandler* handler) = 0; virtual DataAccessor<ApplicationSet> applications() const = 0; + virtual DataAccessor<AppsWaitRegistrationSet> pending_applications() + const = 0; virtual ApplicationSharedPtr application(uint32_t app_id) const = 0; virtual ApplicationSharedPtr active_application() const = 0; @@ -167,6 +169,12 @@ class ApplicationManager { virtual ApplicationSharedPtr application_by_policy_id( const std::string& policy_app_id) const = 0; + virtual ApplicationSharedPtr application_by_name( + const std::string& app_name) const = 0; + + virtual ApplicationSharedPtr pending_application_by_policy_id( + const std::string& policy_app_id) const = 0; + virtual AppSharedPtrs applications_by_button(uint32_t button) = 0; virtual AppSharedPtrs applications_with_navi() = 0; @@ -283,6 +291,9 @@ class ApplicationManager { */ virtual void SendDriverDistractionState(ApplicationSharedPtr application) = 0; + virtual void SendGetIconUrlNotifications( + const uint32_t connection_key, ApplicationSharedPtr application) = 0; + /** * @brief Checks if Application is subscribed for way points * @param Application pointer @@ -427,6 +438,22 @@ class ApplicationManager { virtual void OnHMIStartedCooperation() = 0; + virtual void DisconnectCloudApp(ApplicationSharedPtr app) = 0; + + virtual void RefreshCloudAppInformation() = 0; + + virtual std::string PolicyIDByIconUrl(const std::string url) = 0; + + virtual void SetIconFileFromSystemRequest(const std::string policy_id) = 0; + + /** + * @brief Retrieve the current connection status of a cloud app + * @param app A cloud application + * @return The current CloudConnectionStatus of app + */ + virtual hmi_apis::Common_CloudConnectionStatus::eType + GetCloudAppConnectionStatus(ApplicationConstSharedPtr app) const = 0; + virtual bool IsHMICooperating() const = 0; /** * @brief Notifies all components interested in Vehicle Data update diff --git a/src/components/include/application_manager/application_manager_settings.h b/src/components/include/application_manager/application_manager_settings.h index 8fdca4125f..fc16f1f1ed 100644 --- a/src/components/include/application_manager/application_manager_settings.h +++ b/src/components/include/application_manager/application_manager_settings.h @@ -85,6 +85,8 @@ class ApplicationManagerSettings : public RequestControlerSettings, virtual const std::string& audio_stream_file() const = 0; virtual bool use_full_app_id() const = 0; + virtual uint32_t cloud_app_retry_timeout() const = 0; + virtual uint16_t cloud_app_max_retry_attempts() const = 0; virtual bool use_db_for_resumption() const = 0; virtual const uint32_t& app_resumption_save_persistent_data_timeout() const = 0; diff --git a/src/components/include/application_manager/policies/policy_handler_interface.h b/src/components/include/application_manager/policies/policy_handler_interface.h index ee9274ead7..8dfa1b133a 100644 --- a/src/components/include/application_manager/policies/policy_handler_interface.h +++ b/src/components/include/application_manager/policies/policy_handler_interface.h @@ -105,6 +105,7 @@ class PolicyHandlerInterface { virtual void GetUpdateUrls(const uint32_t service_type, EndpointUrls& out_end_points) = 0; virtual std::string GetLockScreenIconUrl() const = 0; + virtual std::string GetIconUrl(const std::string& policy_app_id) const = 0; virtual uint32_t NextRetryTimeout() = 0; /** @@ -437,6 +438,57 @@ class PolicyHandlerInterface { * @return Structure with vehicle information */ virtual const VehicleInfo GetVehicleInfo() const = 0; + + /** + * @brief Get a list of enabled cloud applications + * @param enabled_apps List filled with the policy app id of each enabled + * cloud application + */ + virtual void GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const = 0; + + /** + * @brief Checks if a given application is an enabled cloud application + * @param policy_app_id Unique application id + * @return true if the application is an enabled cloud application, + * false otherwise + */ + virtual const bool CheckCloudAppEnabled( + const std::string& policy_app_id) const = 0; + + /** + * @brief Get cloud app policy information, all fields that aren't set for a + * given app will be filled with empty strings + * @param policy_app_id Unique application id + * @param enabled Whether or not the app is enabled + * @param endpoint Filled with the endpoint used to connect to the cloud + * application + * @param certificate Filled with the certificate used to for creating a + * secure connection to the cloud application + * @param auth_token Filled with the token used for authentication when + * reconnecting to the cloud app + * @param cloud_transport_type Filled with the transport type used by the + * cloud application (ex. "WSS") + * @param hybrid_app_preference Filled with the hybrid app preference for the + * cloud application set by the user + */ + virtual bool GetCloudAppParameters( + const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const = 0; + + /** + * @brief Callback for when a SetCloudAppProperties message is received from a + * mobile app + * @param message The SetCloudAppProperties message + */ + virtual void OnSetCloudAppProperties( + const smart_objects::SmartObject& message) = 0; + #ifdef EXTERNAL_PROPRIETARY_MODE /** * @brief Gets meta information diff --git a/src/components/include/application_manager/policies/policy_handler_observer.h b/src/components/include/application_manager/policies/policy_handler_observer.h index 1c32102184..c13846dff2 100644 --- a/src/components/include/application_manager/policies/policy_handler_observer.h +++ b/src/components/include/application_manager/policies/policy_handler_observer.h @@ -48,6 +48,9 @@ class PolicyHandlerObserver { return false; } + virtual void OnAuthTokenUpdated(const std::string& policy_app_id, + const std::string& auth_token) {} + virtual void OnPTUFinished(const bool ptu_result) {} virtual ~PolicyHandlerObserver() {} diff --git a/src/components/include/connection_handler/connection_handler.h b/src/components/include/connection_handler/connection_handler.h index a50760b547..ea9cc6c039 100644 --- a/src/components/include/connection_handler/connection_handler.h +++ b/src/components/include/connection_handler/connection_handler.h @@ -80,6 +80,16 @@ class ConnectionHandler { connection_handler::DeviceHandle device_handle) = 0; /** + * @brief Retrieves the connection status of a given device + * + * @param device_handle Handle of device to query + * + * @return The connection status of the given device + */ + virtual transport_manager::ConnectionStatus GetConnectionStatus( + const DeviceHandle& device_handle) const = 0; + + /** * @brief RunAppOnDevice allows to run specific application on the certain *device. * @@ -93,6 +103,13 @@ class ConnectionHandler { virtual void ConnectToAllDevices() = 0; + virtual void AddCloudAppDevice( + const std::string& policy_app_id, + const transport_manager::transport_adapter::CloudAppProperties& + cloud_properties) = 0; + + virtual void RemoveCloudAppDevice(const DeviceHandle device_id) = 0; + /** * @brief Close the connection revoked by Policy * @param connection_key pair of connection and session id @@ -112,6 +129,15 @@ class ConnectionHandler { virtual uint32_t GetConnectionSessionsCount(uint32_t connection_key) = 0; /** + * @brief Get cloud app id by connection id + * @param connection_id unique connection id + * @return the policy app id of the cloud app if the connection is tied to a + * cloud app, an empty string otherwise. + */ + virtual std::string GetCloudAppID( + const transport_manager::ConnectionUID connection_id) const = 0; + + /** * Gets device id by mac address * @param mac_address * @return true if successfully diff --git a/src/components/include/connection_handler/connection_handler_observer.h b/src/components/include/connection_handler/connection_handler_observer.h index 154a2a8e34..b9d6a18926 100644 --- a/src/components/include/connection_handler/connection_handler_observer.h +++ b/src/components/include/connection_handler/connection_handler_observer.h @@ -161,6 +161,17 @@ class ConnectionHandlerObserver { */ virtual void OnSecondaryTransportEndedCallback(const int32_t session_key) = 0; + virtual void OnConnectionStatusUpdated() = 0; + + virtual void CreatePendingApplication( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info, + connection_handler::DeviceHandle device_id) = 0; + + virtual void SetPendingApplicationState( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info) = 0; + protected: /** * \brief Destructor diff --git a/src/components/include/policy/policy_external/policy/policy_listener.h b/src/components/include/policy/policy_external/policy/policy_listener.h index c446c87d1b..8299d019f5 100644 --- a/src/components/include/policy/policy_external/policy/policy_listener.h +++ b/src/components/include/policy/policy_external/policy/policy_listener.h @@ -115,6 +115,16 @@ class PolicyListener { virtual void OnCertificateUpdated(const std::string& certificate_data) = 0; /** + * @brief OnAuthTokenUpdated the callback which signals if an app's auth token + * field has been updated during a PTU + * + * @param policy_app_id the policy app id tied to the updated field. + * @param auth_token the value of the updated field. + */ + virtual void OnAuthTokenUpdated(const std::string& policy_app_id, + const std::string& auth_token) = 0; + + /** * @brief OnPTUFinishedd the callback which signals PTU has finished * * @param ptu_result the result from the PTU - true if successful, diff --git a/src/components/include/policy/policy_external/policy/policy_manager.h b/src/components/include/policy/policy_external/policy/policy_manager.h index 57f6d2f802..64306d7e0a 100644 --- a/src/components/include/policy/policy_external/policy/policy_manager.h +++ b/src/components/include/policy/policy_external/policy/policy_manager.h @@ -109,12 +109,21 @@ class PolicyManager : public usage_statistics::StatisticsManager { /** * @brief GetLockScreenIcon allows to obtain lock screen icon url; - * @return url which point to the resourse where lock screen icon could be + * @return url which point to the resource where lock screen icon could be *obtained. */ virtual std::string GetLockScreenIconUrl() const = 0; /** + * @brief Get Icon Url used for showing a cloud apps icon before the initial + *registration + * + * @return url which point to the resource where icon could be + *obtained. + */ + virtual std::string GetIconUrl(const std::string& policy_app_id) const = 0; + + /** * @brief PTU is needed, for this PTS has to be formed and sent. */ virtual void RequestPTUpdate() = 0; @@ -523,6 +532,90 @@ class PolicyManager : public usage_statistics::StatisticsManager { virtual const VehicleInfo GetVehicleInfo() const = 0; /** + * @brief Get a list of enabled cloud applications + * @param enabled_apps List filled with the policy app id of each enabled + * cloud application + */ + virtual void GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const = 0; + + /** + * @brief Get cloud app policy information, all fields that aren't set for a + * given app will be filled with empty strings + * @param policy_app_id Unique application id + * @param enabled Whether or not the app is enabled + * @param endpoint Filled with the endpoint used to connect to the cloud + * application + * @param certificate Filled with the certificate used to for creating a + * secure connection to the cloud application + * @param auth_token Filled with the token used for authentication when + * reconnecting to the cloud app + * @param cloud_transport_type Filled with the transport type used by the + * cloud application (ex. "WSS") + * @param hybrid_app_preference Filled with the hybrid app preference for the + * cloud application set by the user + */ + virtual bool GetCloudAppParameters( + const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const = 0; + + /** + * @ brief Initialize new cloud app in the policy table + * @ param policy_app_id Application ID + */ + virtual void InitCloudApp(const std::string& policy_app_id) = 0; + + /** + * @brief Enable or disable a cloud application in the HMI + * @param enabled Cloud app enabled state + */ + virtual void SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled) = 0; + + /** + * @brief Set an app's auth token + * @param auth_token Cloud app authentication token + */ + virtual void SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token) = 0; + + /** + * @brief Set a cloud app's transport type + * @param cloud_transport_type Cloud app transport type + */ + virtual void SetAppCloudTransportType( + const std::string& policy_app_id, + const std::string& cloud_transport_type) = 0; + + /** + * @brief Set a cloud app's endpoint url + * @param endpoint URL for websocket connection + */ + virtual void SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint) = 0; + + /** + * @brief Set a cloud app's nicknames + * @param nicknames Nicknames for cloud app + */ + virtual void SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames) = 0; + + /** + * @brief Set the user preference for how a hybrid (cloud and mobile) app + * should be used + * @param hybrid_app_preference Hybrid app user preference + */ + virtual void SetHybridAppPreference( + const std::string& policy_app_id, + const std::string& hybrid_app_preference) = 0; + + /** * @brief Gets meta information * @return meta information */ diff --git a/src/components/include/policy/policy_regular/policy/policy_listener.h b/src/components/include/policy/policy_regular/policy/policy_listener.h index 3f6f555bcc..56e674e81b 100644 --- a/src/components/include/policy/policy_regular/policy/policy_listener.h +++ b/src/components/include/policy/policy_regular/policy/policy_listener.h @@ -113,6 +113,16 @@ class PolicyListener { virtual void OnCertificateUpdated(const std::string& certificate_data) = 0; /** + * @brief OnAuthTokenUpdated the callback which signals if an app's auth token + * field has been updated during a PTU + * + * @param policy_app_id the policy app id tied to the updated field. + * @param auth_token the value of the updated field. + */ + virtual void OnAuthTokenUpdated(const std::string& policy_app_id, + const std::string& auth_token) = 0; + + /** * Gets devices ids by policy application id * @param policy_app_id * @return list devices ids diff --git a/src/components/include/policy/policy_regular/policy/policy_manager.h b/src/components/include/policy/policy_regular/policy/policy_manager.h index ee0bae7118..0528dc9f36 100644 --- a/src/components/include/policy/policy_regular/policy/policy_manager.h +++ b/src/components/include/policy/policy_regular/policy/policy_manager.h @@ -87,12 +87,21 @@ class PolicyManager : public usage_statistics::StatisticsManager { /** * @brief GetLockScreenIcon allows to obtain lock screen icon url; - * @return url which point to the resourse where lock screen icon could be + * @return url which point to the resource where lock screen icon could be *obtained. */ virtual std::string GetLockScreenIconUrl() const = 0; /** + * @brief Get Icon Url used for showing a cloud apps icon before the initial + *registration + * + * @return url which point to the resource where icon could be + *obtained. + */ + virtual std::string GetIconUrl(const std::string& policy_app_id) const = 0; + + /** * @brief Gets all URLs for sending PTS to from PT itself. * @param service_type Service specifies user of URL * @param out_end_points output vector of urls @@ -503,6 +512,91 @@ class PolicyManager : public usage_statistics::StatisticsManager { virtual const VehicleInfo GetVehicleInfo() const = 0; /** + * @brief Get a list of enabled cloud applications + * @param enabled_apps List filled with the policy app id of each enabled + * cloud application + */ + virtual void GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const = 0; + + /** + * @brief Get cloud app policy information, all fields that aren't set for a + * given app will be filled with empty strings + * @param policy_app_id Unique application id + * @param enabled Whether or not the app is enabled + * @param endpoint Filled with the endpoint used to connect to the cloud + * application + * @param certificate Filled with the certificate used to for creating a + * secure connection to the cloud application + * @param auth_token Filled with the token used for authentication when + * reconnecting to the cloud app + * @param cloud_transport_type Filled with the transport type used by the + * cloud application (ex. "WSS") + * @param hybrid_app_preference Filled with the hybrid app preference for the + * cloud application set by the user + */ + virtual bool GetCloudAppParameters( + const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const = 0; + + /** + * @ brief Initialize new cloud app in the policy table + * @ param policy_app_id Application ID + */ + + virtual void InitCloudApp(const std::string& policy_app_id) = 0; + + /** + * @brief Enable or disable a cloud application in the HMI + * @param enabled Cloud app enabled state + */ + virtual void SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled) = 0; + + /** + * @brief Set an app's auth token + * @param auth_token Cloud app authentication token + */ + virtual void SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token) = 0; + + /** + * @brief Set a cloud app's transport type + * @param cloud_transport_type Cloud app transport type + */ + virtual void SetAppCloudTransportType( + const std::string& policy_app_id, + const std::string& cloud_transport_type) = 0; + + /** + * @brief Set a cloud app's endpoint url + * @param endpoint URL for websocket connection + */ + virtual void SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint) = 0; + + /** + * @brief Set a cloud app's nicknames + * @param nicknames Nicknames for cloud app + */ + virtual void SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames) = 0; + + /** + * @brief Set the user preference for how a hybrid (cloud and mobile) app + * should be used + * @param hybrid_app_preference Hybrid app user preference + */ + virtual void SetHybridAppPreference( + const std::string& policy_app_id, + const std::string& hybrid_app_preference) = 0; + + /** * @brief OnAppRegisteredOnMobile allows to handle event when application were * succesfully registered on mobile device. * It will send OnAppPermissionSend notification and will try to start PTU. * diff --git a/src/components/include/protocol/bson_object_keys.h b/src/components/include/protocol/bson_object_keys.h index 56bd5cebd6..f81de4cc81 100644 --- a/src/components/include/protocol/bson_object_keys.h +++ b/src/components/include/protocol/bson_object_keys.h @@ -48,6 +48,7 @@ extern const char* video_service_transports; extern const char* tcp_ip_address; extern const char* tcp_port; extern const char* reason; +extern const char* auth_token; } // namespace strings diff --git a/src/components/include/test/application_manager/mock_application_manager.h b/src/components/include/test/application_manager/mock_application_manager.h index 7f5f17a93d..daf4a23925 100644 --- a/src/components/include/test/application_manager/mock_application_manager.h +++ b/src/components/include/test/application_manager/mock_application_manager.h @@ -74,6 +74,9 @@ class MockApplicationManager : public application_manager::ApplicationManager { void(connection_handler::ConnectionHandler* handler)); MOCK_CONST_METHOD0(applications, DataAccessor<application_manager::ApplicationSet>()); + MOCK_CONST_METHOD0( + pending_applications, + DataAccessor<application_manager::AppsWaitRegistrationSet>()); MOCK_CONST_METHOD1( application, application_manager::ApplicationSharedPtr(uint32_t app_id)); MOCK_CONST_METHOD0(active_application, @@ -97,6 +100,12 @@ class MockApplicationManager : public application_manager::ApplicationManager { MOCK_CONST_METHOD1(application_by_policy_id, application_manager::ApplicationSharedPtr( const std::string& policy_app_id)); + MOCK_CONST_METHOD1( + application_by_name, + application_manager::ApplicationSharedPtr(const std::string& app_name)); + MOCK_CONST_METHOD1(pending_application_by_policy_id, + application_manager::ApplicationSharedPtr( + const std::string& policy_app_id)); MOCK_METHOD1( applications_by_button, std::vector<application_manager::ApplicationSharedPtr>(uint32_t button)); @@ -124,6 +133,9 @@ class MockApplicationManager : public application_manager::ApplicationManager { void(const std::shared_ptr<application_manager::Application> app)); MOCK_METHOD1(SendDriverDistractionState, void(application_manager::ApplicationSharedPtr app)); + MOCK_METHOD2(SendGetIconUrlNotifications, + void(const uint32_t connection_key, + application_manager::ApplicationSharedPtr application)); MOCK_METHOD2(RemoveHMIFakeParameters, void(application_manager::commands::MessageSharedPtr& message, const hmi_apis::FunctionID::eType& function_id)); @@ -166,6 +178,14 @@ class MockApplicationManager : public application_manager::ApplicationManager { MOCK_METHOD1(EndAudioPassThru, bool(uint32_t app_id)); MOCK_METHOD1(ConnectToDevice, void(const std::string& device_mac)); MOCK_METHOD0(OnHMIStartedCooperation, void()); + MOCK_METHOD1(DisconnectCloudApp, + void(application_manager::ApplicationSharedPtr app)); + MOCK_METHOD0(RefreshCloudAppInformation, void()); + MOCK_CONST_METHOD1(GetCloudAppConnectionStatus, + hmi_apis::Common_CloudConnectionStatus::eType( + application_manager::ApplicationConstSharedPtr app)); + MOCK_METHOD1(PolicyIDByIconUrl, std::string(const std::string url)); + MOCK_METHOD1(SetIconFileFromSystemRequest, void(const std::string policy_id)); MOCK_CONST_METHOD0(IsHMICooperating, bool()); MOCK_METHOD2(IviInfoUpdated, void(mobile_apis::VehicleDataType::eType vehicle_info, diff --git a/src/components/include/test/application_manager/mock_application_manager_settings.h b/src/components/include/test/application_manager/mock_application_manager_settings.h index cfabf41b91..0f9ca194b1 100644 --- a/src/components/include/test/application_manager/mock_application_manager_settings.h +++ b/src/components/include/test/application_manager/mock_application_manager_settings.h @@ -90,6 +90,8 @@ class MockApplicationManagerSettings MOCK_CONST_METHOD0(video_stream_file, const std::string&()); MOCK_CONST_METHOD0(audio_stream_file, const std::string&()); MOCK_CONST_METHOD0(use_full_app_id, bool()); + MOCK_CONST_METHOD0(cloud_app_retry_timeout, uint32_t()); + MOCK_CONST_METHOD0(cloud_app_max_retry_attempts, uint16_t()); MOCK_CONST_METHOD0(use_db_for_resumption, bool()); MOCK_CONST_METHOD0(app_resumption_save_persistent_data_timeout, const uint32_t&()); diff --git a/src/components/include/test/application_manager/policies/mock_policy_handler_interface.h b/src/components/include/test/application_manager/policies/mock_policy_handler_interface.h index cb47147074..0983e8eedb 100644 --- a/src/components/include/test/application_manager/policies/mock_policy_handler_interface.h +++ b/src/components/include/test/application_manager/policies/mock_policy_handler_interface.h @@ -102,6 +102,7 @@ class MockPolicyHandlerInterface : public policy::PolicyHandlerInterface { void(const uint32_t service_type, policy::EndpointUrls& end_points)); MOCK_CONST_METHOD0(GetLockScreenIconUrl, std::string()); + MOCK_CONST_METHOD1(GetIconUrl, std::string(const std::string& policy_app_id)); MOCK_METHOD0(ResetRetrySequence, void()); MOCK_METHOD0(NextRetryTimeout, uint32_t()); MOCK_CONST_METHOD0(TimeoutExchangeSec, uint32_t()); @@ -213,6 +214,20 @@ class MockPolicyHandlerInterface : public policy::PolicyHandlerInterface { GetAppRequestTypes, const std::vector<std::string>(const std::string& policy_app_id)); MOCK_CONST_METHOD0(GetVehicleInfo, const policy::VehicleInfo()); + MOCK_CONST_METHOD1(GetEnabledCloudApps, + void(std::vector<std::string>& enabled_apps)); + MOCK_CONST_METHOD1(CheckCloudAppEnabled, + const bool(const std::string& policy_app_id)); + MOCK_CONST_METHOD7(GetCloudAppParameters, + bool(const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference)); + MOCK_METHOD1(OnSetCloudAppProperties, + void(const smart_objects::SmartObject& message)); #ifdef EXTERNAL_PROPRIETARY_MODE MOCK_CONST_METHOD0(GetMetaInfo, const policy::MetaInfo()); diff --git a/src/components/include/test/connection_handler/mock_connection_handler.h b/src/components/include/test/connection_handler/mock_connection_handler.h index 2de3a0f9a7..8cc439c78a 100644 --- a/src/components/include/test/connection_handler/mock_connection_handler.h +++ b/src/components/include/test/connection_handler/mock_connection_handler.h @@ -60,12 +60,23 @@ class MockConnectionHandler : public connection_handler::ConnectionHandler { MOCK_METHOD0(StartTransportManager, void()); MOCK_METHOD1(ConnectToDevice, void(connection_handler::DeviceHandle device_handle)); + MOCK_CONST_METHOD1( + GetConnectionStatus, + transport_manager::ConnectionStatus(const DeviceHandle& device_handle)); MOCK_CONST_METHOD2(RunAppOnDevice, void(const std::string&, const std::string&)); MOCK_METHOD0(ConnectToAllDevices, void()); + MOCK_METHOD2( + AddCloudAppDevice, + void(const std::string& policy_app_id, + const transport_manager::transport_adapter::CloudAppProperties&)); + MOCK_METHOD1(RemoveCloudAppDevice, void(const DeviceHandle device_id)); MOCK_METHOD1(CloseRevokedConnection, void(uint32_t connection_key)); MOCK_METHOD1(CloseConnection, void(ConnectionHandle connection_handle)); MOCK_METHOD1(GetConnectionSessionsCount, uint32_t(uint32_t connection_key)); + MOCK_CONST_METHOD1( + GetCloudAppID, + std::string(const transport_manager::ConnectionUID connection_id)); MOCK_METHOD2(GetDeviceID, bool(const std::string& mac_address, DeviceHandle* device_handle)); diff --git a/src/components/include/test/connection_handler/mock_connection_handler_observer.h b/src/components/include/test/connection_handler/mock_connection_handler_observer.h index a9e4349bec..552be4bee0 100644 --- a/src/components/include/test/connection_handler/mock_connection_handler_observer.h +++ b/src/components/include/test/connection_handler/mock_connection_handler_observer.h @@ -74,6 +74,14 @@ class MockConnectionHandlerObserver const int32_t session_key)); MOCK_METHOD1(OnSecondaryTransportEndedCallback, void(const int32_t session_key)); + MOCK_METHOD0(OnConnectionStatusUpdated, void()); + MOCK_METHOD3(CreatePendingApplication, + void(const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info, + connection_handler::DeviceHandle device_id)); + MOCK_METHOD2(SetPendingApplicationState, + void(const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info)); }; } // namespace connection_handler_test diff --git a/src/components/include/test/policy/policy_external/policy/mock_cache_manager.h b/src/components/include/test/policy/policy_external/policy/mock_cache_manager.h index a4d50d7cc2..2885126fd1 100644 --- a/src/components/include/test/policy/policy_external/policy/mock_cache_manager.h +++ b/src/components/include/test/policy/policy_external/policy/mock_cache_manager.h @@ -76,6 +76,34 @@ class MockCacheManagerInterface : public ::policy::CacheManagerInterface { MOCK_METHOD1(SecondsBetweenRetries, bool(std::vector<int>& seconds)); MOCK_CONST_METHOD1(IsDeviceConsentCached, bool(const std::string& device_id)); MOCK_CONST_METHOD0(GetVehicleInfo, const VehicleInfo()); + MOCK_CONST_METHOD1(GetEnabledCloudApps, + void(std::vector<std::string>& enabled_apps)); + MOCK_CONST_METHOD7(GetCloudAppParameters, + bool(const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference)); + MOCK_METHOD1(InitCloudApp, void(const std::string& policy_app_id)); + MOCK_METHOD2(SetCloudAppEnabled, + void(const std::string& policy_app_id, const bool enabled)); + MOCK_METHOD2(SetAppAuthToken, + void(const std::string& policy_app_id, + const std::string& auth_token)); + MOCK_METHOD2(SetAppCloudTransportType, + void(const std::string& policy_app_id, + const std::string& cloud_transport_type)); + MOCK_METHOD2(SetAppEndpoint, + void(const std::string& policy_app_id, + const std::string& endpoint)); + MOCK_METHOD2(SetAppNicknames, + void(const std::string& policy_app_id, + const StringArray& nicknames)); + MOCK_METHOD2(SetHybridAppPreference, + void(const std::string& policy_app_id, + const std::string& hybrid_app_preference)); MOCK_CONST_METHOD1(GetDeviceConsent, DeviceConsent(const std::string& device_id)); MOCK_METHOD2(SetDeviceConsent, @@ -97,6 +125,7 @@ class MockCacheManagerInterface : public ::policy::CacheManagerInterface { MOCK_METHOD2(GetUpdateUrls, void(const uint32_t service_type, EndpointUrls& out_end_points)); MOCK_CONST_METHOD0(GetLockScreenIconUrl, std::string()); + MOCK_CONST_METHOD1(GetIconUrl, std::string(const std::string& policy_app_id)); MOCK_METHOD1( GetNotificationsNumber, policy_table::NumberOfNotificationsType(const std::string& priority)); diff --git a/src/components/include/test/policy/policy_external/policy/mock_policy_listener.h b/src/components/include/test/policy/policy_external/policy/mock_policy_listener.h index 1f570d8699..720a81862a 100644 --- a/src/components/include/test/policy/policy_external/policy/mock_policy_listener.h +++ b/src/components/include/test/policy/policy_external/policy/mock_policy_listener.h @@ -81,6 +81,9 @@ class MockPolicyListener : public ::policy::PolicyListener { uint32_t timeout_exceed)); MOCK_METHOD0(CanUpdate, bool()); MOCK_METHOD1(OnCertificateUpdated, void(const std::string&)); + MOCK_METHOD2(OnAuthTokenUpdated, + void(const std::string& policy_app_id, + const std::string& auth_token)); MOCK_METHOD1(OnPTUFinished, void(const bool ptu_result)); MOCK_CONST_METHOD2(SendOnAppPermissionsChanged, void(const policy::AppPermissions&, const std::string&)); diff --git a/src/components/include/test/policy/policy_external/policy/mock_policy_manager.h b/src/components/include/test/policy/policy_external/policy/mock_policy_manager.h index aeabf8fdcb..d7d81b3476 100644 --- a/src/components/include/test/policy/policy_external/policy/mock_policy_manager.h +++ b/src/components/include/test/policy/policy_external/policy/mock_policy_manager.h @@ -180,10 +180,39 @@ class MockPolicyManager : public PolicyManager { MOCK_METHOD1(OnAppRegisteredOnMobile, void(const std::string& application_id)); MOCK_CONST_METHOD0(GetLockScreenIconUrl, std::string()); + MOCK_CONST_METHOD1(GetIconUrl, std::string(const std::string& policy_app_id)); MOCK_CONST_METHOD1( GetAppRequestTypes, const std::vector<std::string>(const std::string policy_app_id)); MOCK_CONST_METHOD0(GetVehicleInfo, const policy::VehicleInfo()); + MOCK_CONST_METHOD1(GetEnabledCloudApps, + void(std::vector<std::string>& enabled_apps)); + MOCK_CONST_METHOD7(GetCloudAppParameters, + void(const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference)); + MOCK_METHOD1(InitCloudApp, void(const std::string& policy_app_id)); + MOCK_METHOD2(SetCloudAppEnabled, + void(const std::string& policy_app_id, const bool enabled)); + MOCK_METHOD2(SetAppAuthToken, + void(const std::string& policy_app_id, + const std::string& auth_token)); + MOCK_METHOD2(SetAppCloudTransportType, + void(const std::string& policy_app_id, + const std::string& cloud_transport_type)); + MOCK_METHOD2(SetAppEndpoint, + void(const std::string& policy_app_id, + const std::string& endpoint)); + MOCK_METHOD2(SetAppNicknames, + void(const std::string& policy_app_id, + const StringArray& nicknames)); + MOCK_METHOD2(SetHybridAppPreference, + void(const std::string& policy_app_id, + const std::string& hybrid_app_preference)); MOCK_CONST_METHOD0(GetMetaInfo, const policy::MetaInfo()); MOCK_CONST_METHOD0(RetrieveCertificate, std::string()); MOCK_CONST_METHOD0(HasCertificate, bool()); diff --git a/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h b/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h index 440000dbff..ff186b5ab4 100644 --- a/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h +++ b/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h @@ -63,6 +63,34 @@ class MockCacheManagerInterface : public CacheManagerInterface { MOCK_METHOD0(TimeoutResponse, int()); MOCK_METHOD1(SecondsBetweenRetries, bool(std::vector<int>& seconds)); MOCK_CONST_METHOD0(GetVehicleInfo, const VehicleInfo()); + MOCK_CONST_METHOD1(GetEnabledCloudApps, + void(std::vector<std::string>& enabled_apps)); + MOCK_CONST_METHOD7(GetCloudAppParameters, + bool(const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference)); + MOCK_METHOD1(InitCloudApp, void(const std::string& policy_app_id)); + MOCK_METHOD2(SetCloudAppEnabled, + void(const std::string& policy_app_id, const bool enabled)); + MOCK_METHOD2(SetAppAuthToken, + void(const std::string& policy_app_id, + const std::string& auth_token)); + MOCK_METHOD2(SetAppCloudTransportType, + void(const std::string& policy_app_id, + const std::string& cloud_transport_type)); + MOCK_METHOD2(SetAppEndpoint, + void(const std::string& policy_app_id, + const std::string& endpoint)); + MOCK_METHOD2(SetAppNicknames, + void(const std::string& policy_app_id, + const StringArray& nicknames)); + MOCK_METHOD2(SetHybridAppPreference, + void(const std::string& policy_app_id, + const std::string& hybrid_app_preference)); MOCK_METHOD1(SetVINValue, bool(const std::string& value)); MOCK_METHOD2(GetUserFriendlyMsg, std::vector<UserFriendlyMessage>( @@ -81,6 +109,7 @@ class MockCacheManagerInterface : public CacheManagerInterface { MOCK_METHOD2(GetUpdateUrls, void(const uint32_t service_type, EndpointUrls& out_end_points)); MOCK_CONST_METHOD0(GetLockScreenIconUrl, std::string()); + MOCK_CONST_METHOD1(GetIconUrl, std::string(const std::string& policy_app_id)); MOCK_METHOD2(Init, bool(const std::string& file_name, const PolicySettings* settings)); diff --git a/src/components/include/test/policy/policy_regular/policy/mock_policy_listener.h b/src/components/include/test/policy/policy_regular/policy/mock_policy_listener.h index 3b0c1a925e..045d4f4e4f 100644 --- a/src/components/include/test/policy/policy_regular/policy/mock_policy_listener.h +++ b/src/components/include/test/policy/policy_regular/policy/mock_policy_listener.h @@ -75,6 +75,9 @@ class MockPolicyListener : public ::policy::PolicyListener { MOCK_METHOD1(OnSnapshotCreated, void(const policy::BinaryMessage& pt_string)); MOCK_METHOD0(CanUpdate, bool()); MOCK_METHOD1(OnCertificateUpdated, void(const std::string&)); + MOCK_METHOD2(OnAuthTokenUpdated, + void(const std::string& policy_app_id, + const std::string& auth_token)); MOCK_CONST_METHOD2(SendOnAppPermissionsChanged, void(const policy::AppPermissions&, const std::string&)); MOCK_METHOD3(OnUpdateHMILevel, diff --git a/src/components/include/test/policy/policy_regular/policy/mock_policy_manager.h b/src/components/include/test/policy/policy_regular/policy/mock_policy_manager.h index 0e06e9c1a3..4e3121397f 100644 --- a/src/components/include/test/policy/policy_regular/policy/mock_policy_manager.h +++ b/src/components/include/test/policy/policy_regular/policy/mock_policy_manager.h @@ -181,6 +181,34 @@ class MockPolicyManager : public PolicyManager { GetAppRequestTypes, const std::vector<std::string>(const std::string policy_app_id)); MOCK_CONST_METHOD0(GetVehicleInfo, const policy::VehicleInfo()); + MOCK_CONST_METHOD1(GetEnabledCloudApps, + void(std::vector<std::string>& enabled_apps)); + MOCK_CONST_METHOD7(GetCloudAppParameters, + bool(const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference)); + MOCK_METHOD1(InitCloudApp, void(const std::string& policy_app_id)); + MOCK_METHOD2(SetCloudAppEnabled, + void(const std::string& policy_app_id, const bool enabled)); + MOCK_METHOD2(SetAppAuthToken, + void(const std::string& policy_app_id, + const std::string& auth_token)); + MOCK_METHOD2(SetAppCloudTransportType, + void(const std::string& policy_app_id, + const std::string& cloud_transport_type)); + MOCK_METHOD2(SetAppEndpoint, + void(const std::string& policy_app_id, + const std::string& endpoint)); + MOCK_METHOD2(SetAppNicknames, + void(const std::string& policy_app_id, + const StringArray& nicknames)); + MOCK_METHOD2(SetHybridAppPreference, + void(const std::string& policy_app_id, + const std::string& hybrid_app_preference)); MOCK_CONST_METHOD0(GetMetaInfo, const policy::MetaInfo()); MOCK_CONST_METHOD0(RetrieveCertificate, std::string()); MOCK_CONST_METHOD0(HasCertificate, bool()); @@ -204,6 +232,7 @@ class MockPolicyManager : public PolicyManager { MOCK_CONST_METHOD0(get_settings, const PolicySettings&()); MOCK_METHOD1(set_settings, void(const PolicySettings* get_settings)); MOCK_CONST_METHOD0(GetLockScreenIconUrl, std::string()); + MOCK_CONST_METHOD1(GetIconUrl, std::string(const std::string& policy_app_id)); MOCK_METHOD1(GetNextUpdateUrl, AppIdURL(const EndpointUrls& urls)); MOCK_CONST_METHOD2(RetrySequenceUrl, AppIdURL(const struct RetrySequenceURL&, diff --git a/src/components/include/test/transport_manager/mock_transport_manager.h b/src/components/include/test/transport_manager/mock_transport_manager.h index cc8bd5ab85..0581d4f375 100644 --- a/src/components/include/test/transport_manager/mock_transport_manager.h +++ b/src/components/include/test/transport_manager/mock_transport_manager.h @@ -59,7 +59,14 @@ class MockTransportManager : public ::transport_manager::TransportManager, MOCK_METHOD1(Init, int(resumption::LastState& last_state)); MOCK_METHOD0(Reinit, int()); MOCK_METHOD0(SearchDevices, int()); + MOCK_METHOD1( + AddCloudDevice, + void(const transport_manager::transport_adapter::CloudAppProperties)); + MOCK_METHOD1(RemoveCloudDevice, void(const DeviceHandle device_id)); MOCK_METHOD1(ConnectDevice, int(const DeviceHandle)); + MOCK_CONST_METHOD1( + GetConnectionStatus, + transport_manager::ConnectionStatus(const DeviceHandle& device_handle)); MOCK_METHOD1(DisconnectDevice, int(const DeviceHandle)); MOCK_METHOD1(Disconnect, int(const ConnectionUID)); MOCK_METHOD1(DisconnectForce, int(const ConnectionUID)); diff --git a/src/components/include/test/transport_manager/mock_transport_manager_listener.h b/src/components/include/test/transport_manager/mock_transport_manager_listener.h index 133dabe732..04408f945b 100644 --- a/src/components/include/test/transport_manager/mock_transport_manager_listener.h +++ b/src/components/include/test/transport_manager/mock_transport_manager_listener.h @@ -55,6 +55,10 @@ class MockTransportManagerListener : public TransportManagerListener { MOCK_METHOD1(OnDeviceRemoved, void(const DeviceInfo& device_info)); MOCK_METHOD0(OnScanDevicesFinished, void()); MOCK_METHOD1(OnScanDevicesFailed, void(const SearchDeviceError& error)); + MOCK_METHOD0(OnConnectionStatusUpdated, void()); + MOCK_METHOD2(OnConnectionPending, + void(const DeviceInfo& device_info, + const ConnectionUID connection_id)); MOCK_METHOD2(OnConnectionEstablished, void(const DeviceInfo& device_info, const ConnectionUID connection_id)); diff --git a/src/components/include/test/transport_manager/mock_transport_manager_settings.h b/src/components/include/test/transport_manager/mock_transport_manager_settings.h index 3e7c8f36f7..bed0d5e6e6 100644 --- a/src/components/include/test/transport_manager/mock_transport_manager_settings.h +++ b/src/components/include/test/transport_manager/mock_transport_manager_settings.h @@ -63,6 +63,8 @@ class MockTransportManagerSettings MOCK_CONST_METHOD0(app_transport_change_timer_addition, uint32_t()); MOCK_CONST_METHOD0(transport_manager_tcp_adapter_network_interface, std::string&()); + MOCK_CONST_METHOD0(cloud_app_retry_timeout, uint32_t()); + MOCK_CONST_METHOD0(cloud_app_max_retry_attempts, uint16_t()); }; } // namespace transport_manager_test diff --git a/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h b/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h index eff0abdcd3..3864c3f6f9 100644 --- a/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h +++ b/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h @@ -35,6 +35,7 @@ #include "gmock/gmock.h" #include "transport_manager/transport_adapter/transport_adapter.h" +#include "transport_manager/transport_adapter/device.h" namespace test { namespace components { @@ -66,6 +67,9 @@ class MockTransportAdapter MOCK_METHOD1(ConnectDevice, ::transport_manager::transport_adapter::TransportAdapter::Error( const ::transport_manager::DeviceUID& device_handle)); + MOCK_CONST_METHOD1(GetConnectionStatus, + ::transport_manager::ConnectionStatus( + const ::transport_manager::DeviceUID& device_handle)); MOCK_METHOD2(RunAppOnDevice, void(const std::string&, const std::string&)); MOCK_CONST_METHOD0(IsClientOriginatedConnectSupported, bool()); MOCK_METHOD0( @@ -105,6 +109,8 @@ class MockTransportAdapter transport_manager::SwitchableDevices()); MOCK_CONST_METHOD0(GetTransportConfiguration, transport_manager::transport_adapter::TransportConfig()); + MOCK_METHOD1(CreateDevice, void(const std::string& uid)); + #ifdef TELEMETRY_MONITOR MOCK_METHOD0(GetTelemetryObserver, ::transport_manager::TMTelemetryObserver*()); diff --git a/src/components/include/transport_manager/common.h b/src/components/include/transport_manager/common.h index 58bcf6bb17..b36dcde67e 100644 --- a/src/components/include/transport_manager/common.h +++ b/src/components/include/transport_manager/common.h @@ -56,6 +56,8 @@ enum { E_INTERNAL_ERROR }; +enum ConnectionStatus { INVALID = -1, PENDING, RETRY, CONNECTED, CLOSING }; + /** * @brief Type definition for variable that hold handle of device. */ diff --git a/src/components/include/transport_manager/transport_adapter/device.h b/src/components/include/transport_manager/transport_adapter/device.h index 1ac1424477..ad035245d8 100644 --- a/src/components/include/transport_manager/transport_adapter/device.h +++ b/src/components/include/transport_manager/transport_adapter/device.h @@ -58,7 +58,9 @@ class Device { Device(const std::string& name, const DeviceUID& unique_device_id) : name_(name) , unique_device_id_(unique_device_id) - , keep_on_disconnect_(false) {} + , keep_on_disconnect_(false) + , status_(ConnectionStatus::PENDING) + , retry_count_(0) {} /** * Constructor for creating device supporting transport switch @@ -73,7 +75,9 @@ class Device { : name_(name) , unique_device_id_(unique_device_id) , transport_switch_id_(transport_switch_id) - , keep_on_disconnect_(false) {} + , keep_on_disconnect_(false) + , status_(ConnectionStatus::PENDING) + , retry_count_(0) {} /** * @brief Destructor. @@ -132,6 +136,44 @@ class Device { } /** + * @brief Get @link status_ @endlink value + * @return current value + */ + inline ConnectionStatus connection_status() const { + return status_; + } + + /** + * @brief Set @link status_ @endlink value + * @param status new value + */ + inline void set_connection_status(ConnectionStatus status) { + status_ = status; + } + + /** + * @brief Get @link retry_count_ @endlink value + * @return current value + */ + inline uint16_t retry_count() const { + return retry_count_; + } + + /** + * @brief Increment @link retry_count_ @endlink value + */ + inline void next_retry() { + retry_count_++; + } + + /** + * @brief Reset @link retry_count_ @endlink value to 0 + */ + inline void reset_retry_count() { + retry_count_ = 0; + } + + /** * @brief transport_switch_id Returns id used for transport switching * flow of device. Filled if applicable, otherwise - empty. */ @@ -160,6 +202,10 @@ class Device { *finished. **/ bool keep_on_disconnect_; + + ConnectionStatus status_; + + uint16_t retry_count_; }; typedef std::shared_ptr<Device> DeviceSptr; typedef std::vector<DeviceSptr> DeviceVector; diff --git a/src/components/include/transport_manager/transport_adapter/transport_adapter.h b/src/components/include/transport_manager/transport_adapter/transport_adapter.h index ebbf7dae28..eaa1fa9955 100644 --- a/src/components/include/transport_manager/transport_adapter/transport_adapter.h +++ b/src/components/include/transport_manager/transport_adapter/transport_adapter.h @@ -64,12 +64,22 @@ enum DeviceType { IOS_BT, IOS_USB, TCP, + CLOUD_WEBSOCKET, IOS_USB_HOST_MODE, IOS_USB_DEVICE_MODE, IOS_CARPLAY_WIRELESS, // running on iAP over Carplay wireless transport UNKNOWN }; +struct CloudAppProperties { + std::string endpoint; + std::string certificate; + bool enabled; + std::string auth_token; + std::string cloud_transport_type; + std::string hybrid_app_preference; +}; + typedef std::map<DeviceType, std::string> DeviceTypes; /** @@ -88,6 +98,7 @@ typedef std::list<TransportAdapterListener*> TransportAdapterListenerList; */ typedef std::map<std::string, std::string> TransportConfig; +typedef std::map<std::string, CloudAppProperties> CloudAppTransportConfig; /** * @brief TransportConfig keys */ @@ -196,6 +207,16 @@ class TransportAdapter { virtual Error ConnectDevice(const DeviceUID& device_handle) = 0; /** + * @brief Retrieves the connection status of a given device + * + * @param device_handle Handle of device to query + * + * @return The connection status of the given device + */ + virtual ConnectionStatus GetConnectionStatus( + const DeviceUID& device_handle) const = 0; + + /** * @brief RunAppOnDevice allows to run specific application on the certain *device. * @@ -327,6 +348,8 @@ class TransportAdapter { */ virtual TransportConfig GetTransportConfiguration() const = 0; + virtual void CreateDevice(const std::string& uid) = 0; + #ifdef TELEMETRY_MONITOR /** * @brief Return Time metric observer diff --git a/src/components/include/transport_manager/transport_adapter/transport_adapter_event.h b/src/components/include/transport_manager/transport_adapter/transport_adapter_event.h index fd1d693067..63d1678ed0 100644 --- a/src/components/include/transport_manager/transport_adapter/transport_adapter_event.h +++ b/src/components/include/transport_manager/transport_adapter/transport_adapter_event.h @@ -58,7 +58,9 @@ enum class EventTypeEnum { ON_COMMUNICATION_ERROR, ON_UNEXPECTED_DISCONNECT, ON_TRANSPORT_SWITCH_REQUESTED, - ON_TRANSPORT_CONFIG_UPDATED + ON_TRANSPORT_CONFIG_UPDATED, + ON_CONNECT_PENDING, + ON_CONNECTION_STATUS_UPDATED }; class TransportAdapterEvent { diff --git a/src/components/include/transport_manager/transport_manager.h b/src/components/include/transport_manager/transport_manager.h index 0847886c46..4ccc78cd1b 100644 --- a/src/components/include/transport_manager/transport_manager.h +++ b/src/components/include/transport_manager/transport_manager.h @@ -75,6 +75,12 @@ class TransportManager { **/ virtual int SearchDevices() = 0; + virtual void AddCloudDevice( + const transport_manager::transport_adapter::CloudAppProperties + cloud_properties) = 0; + + virtual void RemoveCloudDevice(const DeviceHandle device_id) = 0; + /** * @brief Connect to all applications discovered on device. * @@ -85,6 +91,16 @@ class TransportManager { virtual int ConnectDevice(const DeviceHandle device_id) = 0; /** + * @brief Retrieves the connection status of a given device + * + * @param device_handle Handle of device to query + * + * @return The connection status of the given device + */ + virtual ConnectionStatus GetConnectionStatus( + const DeviceHandle& device_handle) const = 0; + + /** * @brief Disconnect from all applications connected on device. * * @param device_id Handle of device to Disconnect from. diff --git a/src/components/include/transport_manager/transport_manager_listener.h b/src/components/include/transport_manager/transport_manager_listener.h index 6c3f6e2eaa..22ee519a67 100644 --- a/src/components/include/transport_manager/transport_manager_listener.h +++ b/src/components/include/transport_manager/transport_manager_listener.h @@ -101,6 +101,19 @@ class TransportManagerListener { virtual void OnScanDevicesFailed(const SearchDeviceError& error) = 0; /** + * @brief Reaction to the event, when the cloud connection status is updated. + */ + virtual void OnConnectionStatusUpdated() = 0; + + /** + * @brief Reaction to the event, when connection is pending. + * + * @param devcie_info Variable that hold information about device. + * @param connection_id connection unique identifier. + */ + virtual void OnConnectionPending(const DeviceInfo& device_info, + const ConnectionUID connection_id) = 0; + /** * @brief Reaction to the event, when connection is established. * * @param devcie_info Variable that hold information about device. diff --git a/src/components/include/transport_manager/transport_manager_listener_empty.h b/src/components/include/transport_manager/transport_manager_listener_empty.h index 08b2b77c30..193a86819c 100644 --- a/src/components/include/transport_manager/transport_manager_listener_empty.h +++ b/src/components/include/transport_manager/transport_manager_listener_empty.h @@ -59,6 +59,8 @@ class TransportManagerListenerEmpty : public TransportManagerListener { void OnFindNewApplicationsRequest() OVERRIDE {} + void OnConnectionStatusUpdated() OVERRIDE {} + /** * @brief Reaction to the event, when the device is found. * @@ -99,6 +101,15 @@ class TransportManagerListenerEmpty : public TransportManagerListener { void OnScanDevicesFailed(const SearchDeviceError& error) OVERRIDE {} /** + * @brief Reaction to the event, when connection is pending. + * + * @param devcie_info Variable that hold information about device. + * @param connection_id connection unique identifier. + */ + void OnConnectionPending(const DeviceInfo& device_info, + const ConnectionUID connection_id) OVERRIDE {} + + /** * @brief Reaction to the event, when connection is established. * * @param devcie_info Variable that hold information about device. diff --git a/src/components/include/transport_manager/transport_manager_settings.h b/src/components/include/transport_manager/transport_manager_settings.h index 3912bbe747..cbc1516c29 100644 --- a/src/components/include/transport_manager/transport_manager_settings.h +++ b/src/components/include/transport_manager/transport_manager_settings.h @@ -69,6 +69,16 @@ class TransportManagerSettings : public TransportManagerMMESettings { */ virtual const std::string& transport_manager_tcp_adapter_network_interface() const = 0; + + /** + * @brief Returns retry timeout for cloud app connections + */ + virtual uint32_t cloud_app_retry_timeout() const = 0; + + /** + * @brief Returns maximum retry attempts for cloud app connections + */ + virtual uint16_t cloud_app_max_retry_attempts() const = 0; }; } // namespace transport_manager #endif // SRC_COMPONENTS_INCLUDE_TRANSPORT_MANAGER_TRANSPORT_MANAGER_SETTINGS_H_ diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml index 97df559ef5..b056ae3910 100644 --- a/src/components/interfaces/HMI_API.xml +++ b/src/components/interfaces/HMI_API.xml @@ -72,6 +72,7 @@ <element name="USB_IOS"/> <element name="USB_AOA"/> <element name="WIFI"/> + <element name="CLOUD_WEBSOCKET"/> </enum> <enum name="ButtonName"> @@ -291,6 +292,18 @@ <element name="REMOTE_CONTROL" /> </enum> +<enum name="CloudConnectionStatus"> + <element name="NOT_CONNECTED"> + <description>No active websocket session or ongoing connection attempts</description> + </element> + <element name="CONNECTED"> + <description>Websocket is active</description> + </element> + <element name="RETRY"> + <description>Websocket connection failed and retry attempts are ongoing</description> + </element> +</enum> + <enum name="WayPointType"> <description>Describes what kind of waypoint is requested/provided.</description> <element name="ALL" /> @@ -474,6 +487,9 @@ <element name="UNSUPPORTED_HMI_RESOURCE"> <description>By getting this value, SDL unregisters the named application</description> </element> + <element name="CLOSE_CLOUD_CONNECTION"> + <description>By getting this value, SDL puts the named app to NONE HMILevel. Used by the HMI to close a cloud app connection.</description> + </element> </enum> <enum name="TextFieldName"> @@ -1094,6 +1110,7 @@ <element name="VEHICLEDATA_FUELRANGE" /> <element name="VEHICLEDATA_ENGINEOILLIFE" /> <element name="VEHICLEDATA_ELECTRONICPARKBRAKESTATUS" /> + <element name="VEHICLEDATA_CLOUDAPPVEHICLEID" /> </enum> <enum name="WiperStatus"> @@ -1254,6 +1271,7 @@ <element name="MEDIA" /> <element name="FOTA" /> <element name="OEM_SPECIFIC"/> + <element name="ICON_URL"/> </enum> <enum name="ECallConfirmationStatus"> @@ -2618,16 +2636,18 @@ <description>If SDL omits this parameter - none RequestType is allowed for this app</description> <description>(either this is a pre-registered app or such is dictated by policies).</description> </param> - <param name="requestSubType" type="String" maxlength="100" minsize="0" maxsize="100" array="true" mandatory="false"> - <description> - The list of SystemRequest's requestSubTypes allowed by policies for the named application. - If the app sends a requestSubType which is not specified in this list, then that request should be rejected. - An empty array signifies that any value of requestSubType is allowed for this app. - If this parameter is omitted, then a request with any value of requestSubType is now allowed for this app - </description> + <param name="requestSubType" type="String" maxlength="100" minsize="0" maxsize="100" array="true" mandatory="false"> + <description> + The list of SystemRequest's requestSubTypes allowed by policies for the named application. + If the app sends a requestSubType which is not specified in this list, then that request should be rejected. + An empty array signifies that any value of requestSubType is allowed for this app. + If this parameter is omitted, then a request with any value of requestSubType is now allowed for this app + </description> </param> <param name="dayColorScheme" type="Common.TemplateColorScheme" mandatory="false"></param> <param name="nightColorScheme" type="Common.TemplateColorScheme" mandatory="false"></param> + <param name="isCloudApplication" type="Boolean" mandatory="false"></param> + <param name="cloudConnectionStatus" type="Common.CloudConnectionStatus" mandatory="false"></param> </struct> <struct name="MenuParams"> @@ -4950,6 +4970,10 @@ <param name="electronicParkBrakeStatus" type="Boolean" mandatory="false"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="Boolean" mandatory="false"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> + <!-- Ford Specific Data Items --> <param name="eCallInfo" type="Boolean" mandatory="false"> <description>Emergency Call notification and confirmation data</description> @@ -4967,6 +4991,7 @@ <description>Information related to the MyKey feature</description> </param> <!-- / Ford Specific Data Items --> + </function> <function name="SubscribeVehicleData" messagetype="response"> <param name="gps" type="Common.VehicleDataResult" mandatory="false"> @@ -5038,6 +5063,10 @@ <param name="electronicParkBrakeStatus" type="Common.VehicleDataResult" mandatory="false"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="Common.VehicleDataResult" mandatory="false"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> + <!-- Ford Specific Data Items --> <param name="eCallInfo" type="Common.VehicleDataResult" mandatory="false"> <description>Emergency Call notification and confirmation data</description> @@ -5055,6 +5084,7 @@ <description>Information related to the MyKey feature</description> </param> <!-- / Ford Specific Data Items --> + </function> <function name="UnsubscribeVehicleData" messagetype="request"> <description> @@ -5132,6 +5162,10 @@ <param name="electronicParkBrakeStatus" type="Boolean" mandatory="false"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="Boolean" mandatory="false"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> + <!-- Ford Specific Data Items --> <param name="eCallInfo" type="Boolean" mandatory="false"> <description>Emergency Call notification and confirmation data</description> @@ -5149,6 +5183,7 @@ <description>Information related to the MyKey feature</description> </param> <!-- / Ford Specific Data Items --> + </function> <function name="UnsubscribeVehicleData" messagetype="response"> <param name="gps" type="Common.VehicleDataResult" mandatory="false"> @@ -5220,6 +5255,10 @@ <param name="electronicParkBrakeStatus" type="Common.VehicleDataResult" mandatory="false"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="Common.VehicleDataResult" mandatory="false"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> + <!-- Ford Specific Data Items --> <param name="eCallInfo" type="Common.VehicleDataResult" mandatory="false"> <description>Emergency Call notification and confirmation data</description> @@ -5237,6 +5276,7 @@ <description>Information related to the MyKey feature</description> </param> <!-- / Ford Specific Data Items --> + </function> <function name="GetVehicleData" messagetype="request"> <description>Non periodic vehicle data read request.</description> @@ -5312,6 +5352,11 @@ <param name="electronicParkBrakeStatus" type="Boolean" mandatory="false"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="Boolean" mandatory="false"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> + + <!-- Ford Specific Data Items --> <param name="eCallInfo" type="Boolean" mandatory="false"> <description>Emergency Call notification and confirmation data</description> </param> @@ -5327,6 +5372,8 @@ <param name="myKey" type="Boolean" mandatory="false"> <description>Information related to the MyKey feature</description> </param> + <!-- / Ford Specific Data Items --> + </function> <function name="GetVehicleData" messagetype="response"> <param name="gps" type="Common.GPSData" mandatory="false"> @@ -5401,6 +5448,11 @@ <param name="electronicParkBrakeStatus" type="Common.ElectronicParkBrakeStatus" mandatory="false"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="String" mandatory="false"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> + + <!-- Ford Specific Data Items --> <param name="eCallInfo" type="Common.ECallInfo" mandatory="false"> <description>Emergency Call notification and confirmation data</description> </param> @@ -5416,6 +5468,8 @@ <param name="myKey" type="Common.MyKey" mandatory="false"> <description>Information related to the MyKey feature</description> </param> + <!-- / Ford Specific Data Items --> + </function> <function name="OnVehicleData" messagetype="notification"> <description>Callback for the periodic and non periodic vehicle data read function.</description> @@ -5488,6 +5542,11 @@ <param name="steeringWheelAngle" type="Float" minvalue="-2000" maxvalue="2000" mandatory="false"> <description>Current angle of the steering wheel (in deg)</description> </param> + <param name="cloudAppVehicleID" type="String" mandatory="false"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> + + <!-- Ford Specific Data Items --> <param name="eCallInfo" type="Common.ECallInfo" mandatory="false"> <description>Emergency Call notification and confirmation data</description> </param> @@ -5503,6 +5562,8 @@ <param name="myKey" type="Common.MyKey" mandatory="false"> <description>Information related to the MyKey feature</description> </param> + <!-- / Ford Specific Data Items --> + </function> </interface> diff --git a/src/components/interfaces/MOBILE_API.xml b/src/components/interfaces/MOBILE_API.xml index 76fc6ef2d1..e7dbc1e089 100644 --- a/src/components/interfaces/MOBILE_API.xml +++ b/src/components/interfaces/MOBILE_API.xml @@ -1,7 +1,7 @@ <?xml version="1.0" standalone="no"?> <?xml-stylesheet type="text/xml" href="protocol2html.xsl"?> -<interface name="SmartDeviceLink RAPI" version="5.0.0" minVersion="1.0" date="2018-10-03"> +<interface name="SmartDeviceLink RAPI" version="5.1.0" minVersion="1.0" date="2018-10-03"> <enum name="Result" internal_scope="base" since="1.0"> <element name="SUCCESS"> <description>The request succeeded</description> @@ -542,8 +542,36 @@ <element name="VEHICLEDATA_FUELRANGE" since="5.0" /> <element name="VEHICLEDATA_ENGINEOILLIFE" since="5.0" /> <element name="VEHICLEDATA_ELECTRONICPARKBRAKESTATUS" since="5.0" /> + <element name="VEHICLEDATA_CLOUDAPPVEHICLEID" since="5.1"/> </enum> + <enum name="HybridAppPreference" since="5.1"> + <description>Enumeration for the user's preference of which app type to use when both are available</description> + <element name="MOBILE" /> + <element name="CLOUD" /> + <element name="BOTH" /> + </enum> + + <struct name="CloudAppProperties" since="5.1"> + <param name="nicknames" type="String" minlength="0" maxlength="100" array="true" minsize="0" maxsize="100" mandatory="false"> + <description>An array of app names a cloud app is allowed to register with. If included in a SetCloudAppProperties request, this value will overwrite the existing "nicknames" field in the app policies section of the policy table.</description> + </param> + <param name="appID" type="String" maxlength="100" mandatory="true"></param> + <param name="enabled" type="Boolean" mandatory="false"> + <description>If true, cloud app will be included in HMI RPC UpdateAppList</description> + </param> + <param name="authToken" type="String" maxlength="65535" mandatory="false"> + <description>Used to authenticate websocket connection on app activation</description> + </param> + <param name="cloudTransportType" type="String" maxlength="100" mandatory="false"> + <description>Specifies the connection type Core should use</description> + </param> + <param name="hybridAppPreference" type="HybridAppPreference" mandatory="false"> + <description>Specifies the user preference to use the cloud app version or mobile app version when both are available</description> + </param> + <param name="endpoint" type="String" maxlength="65535" mandatory="false"></param> + </struct> + <enum name="ButtonName" since="1.0"> <description>Defines the hard (physical) and soft (touchscreen) buttons available from the module</description> <element name="OK" /> @@ -937,7 +965,7 @@ <description>Similar to VP8, but VP9 is customized for video resolutions beyond high-definition video (UHD) and also enables lossless compression.</description> </element> </enum> - + <enum name="AudioStreamingIndicator" since="5.0"> <element name="PLAY_PAUSE"> <description> @@ -2411,6 +2439,7 @@ <element name="MEDIA" /> <element name="FOTA" /> <element name="OEM_SPECIFIC" since="5.0" /> + <element name="ICON_URL" since="5.1" /> </enum> <enum name="AppHMIType" since="2.0"> @@ -2608,6 +2637,8 @@ <element name="UnsubscribeWayPointsID" value="47" hexvalue="2F" since="4.1" /> <element name="GetSystemCapabilityID" value="48" hexvalue="30" since="4.5" /> <element name="SendHapticDataID" value="49" hexvalue="31" since="4.5" /> + <element name="SetCloudAppPropertiesID" value="50" hexvalue="32" since="5.1" /> + <element name="GetCloudAppPropertiesID" value="51" hexvalue="33" since="5.1" /> <!-- Base Notifications @@ -4939,7 +4970,10 @@ <param name="electronicParkBrakeStatus" type="Boolean" mandatory="false" since="5.0"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> - + <param name="cloudAppVehicleID" type="Boolean" mandatory="false" since="5.1"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> + <!-- Ford Specific Data Items --> <param name="eCallInfo" type="Boolean" mandatory="false"> <description>Emergency Call notification and confirmation data</description> @@ -5054,7 +5088,10 @@ <param name="electronicParkBrakeStatus" type="VehicleDataResult" mandatory="false" since="5.0"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> - + <param name="cloudAppVehicleID" type="VehicleDataResult" mandatory="false" since="5.1"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> + <!-- Ford Specific Data Items --> <param name="eCallInfo" type="VehicleDataResult" mandatory="false"> <description>Emergency Call notification and confirmation data</description> @@ -5147,6 +5184,9 @@ <param name="electronicParkBrakeStatus" type="Boolean" mandatory="false" since="5.0"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="Boolean" mandatory="false" since="5.1"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> <!-- Ford Specific Data Items --> <param name="eCallInfo" type="Boolean" mandatory="false"> @@ -5260,6 +5300,9 @@ <param name="electronicParkBrakeStatus" type="VehicleDataResult" mandatory="false" since="5.0"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="VehicleDataResult" mandatory="false" since="5.1"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> <!-- Ford Specific Data Items --> <param name="eCallInfo" type="VehicleDataResult" mandatory="false"> @@ -5356,6 +5399,9 @@ <param name="electronicParkBrakeStatus" type="Boolean" mandatory="false" since="5.0"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="Boolean" mandatory="false" since="5.1"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> <!-- Ford Specific Data Items --> <param name="eCallInfo" type="Boolean" mandatory="false"> @@ -5473,6 +5519,9 @@ <param name="electronicParkBrakeStatus" type="ElectronicParkBrakeStatus" mandatory="false" since="5.0"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="String" mandatory="false" since="5.1"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> <!-- Ford Specific Data Items --> <param name="eCallInfo" type="ECallInfo" mandatory="false"> @@ -6607,6 +6656,74 @@ </param> </function> + <function name="SetCloudAppProperties" functionID="SetCloudAppPropertiesID" messagetype="request" since="5.1"> + <description> + RPC used to enable/disable a cloud application and set authentication data + </description> + <param name="properties" type="CloudAppProperties" mandatory="true"> + <description> The requested cloud application properties </description> + </param> + </function> + + <function name="SetCloudAppProperties" functionID="SetCloudAppPropertiesID" messagetype="response" since="5.1"> + <description> + The response to registerAppInterface + </description> + <param name="success" type="Boolean" platform="documentation" mandatory="true"> + <description> true if successful; false if failed </description> + </param> + <param name="resultCode" type="Result" platform="documentation" mandatory="true"> + <description>See Result</description> + <element name="SUCCESS" /> + <element name="INVALID_DATA" /> + <element name="OUT_OF_MEMORY" /> + <element name="TOO_MANY_PENDING_REQUESTS" /> + <element name="GENERIC_ERROR" /> + <element name="DUPLICATE_NAME" /> + <element name="TOO_MANY_APPLICATIONS" /> + <element name="APPLICATION_REGISTERED_ALREADY" /> + <element name="UNSUPPORTED_VERSION" /> + <element name="WRONG_LANGUAGE" /> + <element name="DISALLOWED" /> + <element name="WARNINGS" /> + <element name="RESUME_FAILED" /> + </param> + </function> + + <function name="GetCloudAppProperties" functionID="GetCloudAppPropertiesID" messagetype="request" since="5.1"> + <description> + RPC used to get the current properties of a cloud application + </description> + <param name="appID" type="String" maxlength="100" mandatory="true"></param> + </function> + + <function name="GetCloudAppProperties" functionID="GetCloudAppPropertiesID" messagetype="response" since="5.1"> + <description>The response to GetCloudAppProperties</description> + <param name="properties" type="CloudAppProperties" mandatory="false"> + <description> The requested cloud application properties </description> + </param> + <param name="success" type="Boolean" platform="documentation" mandatory="true"> + <description> true if successful; false if failed </description> + </param> + <param name="resultCode" type="Result" platform="documentation" mandatory="true"> + <description>See Result</description> + <element name="SUCCESS"/> + <element name="INVALID_DATA"/> + <element name="OUT_OF_MEMORY"/> + <element name="TOO_MANY_PENDING_REQUESTS"/> + <element name="GENERIC_ERROR"/> + <element name="DUPLICATE_NAME"/> + <element name="TOO_MANY_APPLICATIONS"/> + <element name="APPLICATION_REGISTERED_ALREADY"/> + <element name="UNSUPPORTED_VERSION"/> + <element name="WRONG_LANGUAGE"/> + <element name="DISALLOWED"/> + <element name="WARNINGS"/> + <element name="RESUME_FAILED"/> + </param> + </function> + + <!-- Notifications --> <function name="OnHMIStatus" functionID="OnHMIStatusID" messagetype="notification" since="1.0"> @@ -6732,6 +6849,9 @@ <param name="electronicParkBrakeStatus" type="ElectronicParkBrakeStatus" mandatory="false" since="5.0"> <description>The status of the park brake as provided by Electric Park Brake (EPB) system.</description> </param> + <param name="cloudAppVehicleID" type="String" mandatory="false" since="5.1"> + <description>Parameter used by cloud apps to identify a head unit</description> + </param> <!-- Ford Specific Vehicle Data --> <param name="eCallInfo" type="ECallInfo" mandatory="false"> diff --git a/src/components/policy/policy_external/include/policy/cache_manager.h b/src/components/policy/policy_external/include/policy/cache_manager.h index d30e7cea24..a1db3536c2 100644 --- a/src/components/policy/policy_external/include/policy/cache_manager.h +++ b/src/components/policy/policy_external/include/policy/cache_manager.h @@ -159,6 +159,90 @@ class CacheManager : public CacheManagerInterface { virtual const VehicleInfo GetVehicleInfo() const; /** + * @brief Get a list of enabled cloud applications + * @param enabled_apps List filled with the policy app id of each enabled + * cloud application + */ + virtual void GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const; + + /** + * @brief Get cloud app policy information, all fields that aren't set for a + * given app will be filled with empty strings + * @param policy_app_id Unique application id + * @param enabled Whether or not the app is enabled + * @param endpoint Filled with the endpoint used to connect to the cloud + * application + * @param certificate Filled with the certificate used to for creating a + * secure connection to the cloud application + * @param auth_token Filled with the token used for authentication when + * reconnecting to the cloud app + * @param cloud_transport_type Filled with the transport type used by the + * cloud application (ex. "WSS") + * @param hybrid_app_preference Filled with the hybrid app preference for the + * cloud application set by the user + */ + virtual bool GetCloudAppParameters(const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const; + + /** + * Initializes a new cloud application with default policies + * Then adds cloud specific policies + * @param app_id application id + * @return true if success + */ + virtual void InitCloudApp(const std::string& policy_app_id); + + /** + * @brief Enable or disable a cloud application in the HMI + * @param enabled Cloud app enabled state + */ + virtual void SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled); + + /** + * @brief Set an app's auth token + * @param auth_token Cloud app authentication token + */ + virtual void SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token); + + /** + * @brief Set a cloud app's transport type + * @param cloud_transport_type Cloud app transport type + */ + virtual void SetAppCloudTransportType( + const std::string& policy_app_id, + const std::string& cloud_transport_type); + + /** + * @brief Set a cloud app's endpoint url + * @param endpoint URL for websocket connection + */ + virtual void SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint); + + /** + * @brief Set a cloud app's nicknames + * @param nicknames Nicknames for cloud app + */ + virtual void SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames); + + /** + * @brief Set the user preference for how a hybrid (cloud and mobile) app + * should be used + * @param hybrid_app_preference Hybrid app user preference + */ + virtual void SetHybridAppPreference(const std::string& policy_app_id, + const std::string& hybrid_app_preference); + + /** * @brief Allows to update 'vin' field in module_meta table. * * @param new 'vin' value. @@ -192,6 +276,15 @@ class CacheManager : public CacheManagerInterface { virtual std::string GetLockScreenIconUrl() const; /** + * @brief Get Icon Url used for showing a cloud apps icon before the intial + *registration + * + * @return url which point to the resourse where icon could be + *obtained. + */ + virtual std::string GetIconUrl(const std::string& policy_app_id) const; + + /** * @brief Gets list of URL to send PTS to * @param service_type If URLs for specific service are preset, * return them otherwise default URLs. diff --git a/src/components/policy/policy_external/include/policy/cache_manager_interface.h b/src/components/policy/policy_external/include/policy/cache_manager_interface.h index bb9ce14c7f..78546823c4 100644 --- a/src/components/policy/policy_external/include/policy/cache_manager_interface.h +++ b/src/components/policy/policy_external/include/policy/cache_manager_interface.h @@ -166,6 +166,92 @@ class CacheManagerInterface { virtual const VehicleInfo GetVehicleInfo() const = 0; /** + * @brief Get a list of enabled cloud applications + * @param enabled_apps List filled with the policy app id of each enabled + * cloud application + */ + virtual void GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const = 0; + + /** + * @brief Get cloud app policy information, all fields that aren't set for a + * given app will be filled with empty strings + * @param policy_app_id Unique application id + * @param enabled Whether or not the app is enabled + * @param endpoint Filled with the endpoint used to connect to the cloud + * application + * @param certificate Filled with the certificate used to for creating a + * secure connection to the cloud application + * @param auth_token Filled with the token used for authentication when + * reconnecting to the cloud app + * @param cloud_transport_type Filled with the transport type used by the + * cloud application (ex. "WSS") + * @param hybrid_app_preference Filled with the hybrid app preference for the + * cloud application set by the user + */ + virtual bool GetCloudAppParameters( + const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const = 0; + + /** + * Initializes a new cloud application with default policies + * Then adds cloud specific policies + * @param app_id application id + * @return true if success + */ + virtual void InitCloudApp(const std::string& policy_app_id) = 0; + + /** + * @brief Enable or disable a cloud application in the HMI + * @param enabled Cloud app enabled state + */ + virtual void SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled) = 0; + + /** + * @brief Set an app's auth token + * @param auth_token Cloud app authentication token + */ + virtual void SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token) = 0; + + /** + * @brief Set a cloud app's transport type + * @param cloud_transport_type Cloud app transport type + */ + virtual void SetAppCloudTransportType( + const std::string& policy_app_id, + const std::string& cloud_transport_type) = 0; + + /** + * @brief Set a cloud app's endpoint url + * @param endpoint URL for websocket connection + */ + virtual void SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint) = 0; + + /** + * @brief Set a cloud app's nicknames + * @param nicknames Nicknames for cloud app + */ + virtual void SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames) = 0; + + /** + * @brief Set the user preference for how a hybrid (cloud and mobile) app + * should be used + * @param hybrid_app_preference Hybrid app user preference + */ + virtual void SetHybridAppPreference( + const std::string& policy_app_id, + const std::string& hybrid_app_preference) = 0; + + /** * @brief Allows to update 'vin' field in module_meta table. * * @param new 'vin' value. @@ -208,6 +294,15 @@ class CacheManagerInterface { virtual std::string GetLockScreenIconUrl() const = 0; /** + * @brief Get Icon Url used for showing a cloud apps icon before the intial + *registration + * + * @return url which point to the resourse where icon could be + *obtained. + */ + virtual std::string GetIconUrl(const std::string& policy_app_id) const = 0; + + /** * @brief Get allowed number of notifications * depending on application priority. * @param priority Priority of application diff --git a/src/components/policy/policy_external/include/policy/policy_manager_impl.h b/src/components/policy/policy_external/include/policy/policy_manager_impl.h index 3837dda1fa..8ba0aafacc 100644 --- a/src/components/policy/policy_external/include/policy/policy_manager_impl.h +++ b/src/components/policy/policy_external/include/policy/policy_manager_impl.h @@ -209,6 +209,15 @@ class PolicyManagerImpl : public PolicyManager { std::string GetLockScreenIconUrl() const OVERRIDE; /** + * @brief Get Icon Url used for showing a cloud apps icon before the intial + *registration + * + * @return url which point to the resourse where icon could be + *obtained. + */ + std::string GetIconUrl(const std::string& policy_app_id) const OVERRIDE; + + /** * @brief Handler of PTS sending out */ void OnUpdateStarted() OVERRIDE; @@ -571,6 +580,89 @@ class PolicyManagerImpl : public PolicyManager { const VehicleInfo GetVehicleInfo() const OVERRIDE; /** + * @brief Get a list of enabled cloud applications + * @param enabled_apps List filled with the policy app id of each enabled + * cloud application + */ + void GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const OVERRIDE; + + /** + * @brief Get cloud app policy information, all fields that aren't set for a + * given app will be filled with empty strings + * @param policy_app_id Unique application id + * @param enabled Whether or not the app is enabled + * @param endpoint Filled with the endpoint used to connect to the cloud + * application + * @param certificate Filled with the certificate used to for creating a + * secure connection to the cloud application + * @param auth_token Filled with the token used for authentication when + * reconnecting to the cloud app + * @param cloud_transport_type Filled with the transport type used by the + * cloud application (ex. "WSS") + * @param hybrid_app_preference Filled with the hybrid app preference for the + * cloud application set by the user + */ + bool GetCloudAppParameters(const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const OVERRIDE; + + /** + * @ brief Initialize new cloud app in the policy table + * @ param policy_app_id Application ID + */ + void InitCloudApp(const std::string& policy_app_id) OVERRIDE; + + /** + * @brief Enable or disable a cloud application in the HMI + * @param enabled Cloud app enabled state + */ + void SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled) OVERRIDE; + + /** + * @brief Set an app's auth token + * @param auth_token Cloud app authentication token + */ + void SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token) OVERRIDE; + + /** + * @brief Set a cloud app's transport type + * @param cloud_transport_type Cloud app transport type + */ + void SetAppCloudTransportType( + const std::string& policy_app_id, + const std::string& cloud_transport_type) OVERRIDE; + + /** + * @brief Set a cloud app's endpoint url + * @param endpoint URL for websocket connection + */ + void SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint) OVERRIDE; + + /** + * @brief Set a cloud app's nicknames + * @param nicknames Nicknames for cloud app + */ + void SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames) OVERRIDE; + + /** + * @brief Set the user preference for how a hybrid (cloud and mobile) app + * should be used + * @param hybrid_app_preference Hybrid app user preference + */ + void SetHybridAppPreference( + const std::string& policy_app_id, + const std::string& hybrid_app_preference) OVERRIDE; + + /** * @brief OnAppRegisteredOnMobile allows to handle event when application were * succesfully registered on mobile device. * It will send OnAppPermissionSend notification and will try to start PTU. * @@ -892,6 +984,12 @@ class PolicyManagerImpl : public PolicyManager { const std::string& application_id) OVERRIDE; /** + * @brief notify listener of updated auth token for a given policy id + * @param policy_app_id the app id that has an updated auth token + */ + void SendAuthTokenUpdated(const std::string policy_app_id); + + /** * @brief Gets all allowed module types * @param policy_app_id unique identifier of application * @param modules list of allowed module types diff --git a/src/components/policy/policy_external/include/policy/policy_table/enums.h b/src/components/policy/policy_external/include/policy/policy_table/enums.h index 34864c5602..a37a9d6b5e 100644 --- a/src/components/policy/policy_external/include/policy/policy_table/enums.h +++ b/src/components/policy/policy_external/include/policy/policy_table/enums.h @@ -96,6 +96,7 @@ enum Parameter { P_FUEL_RANGE, P_TIRE_PRESSURE_VALUE, P_TPMS, + P_CLOUD_APP_VEHICLE_ID, P_LONGTITUDE_DEGREES, P_LATITUDE_DEGREES, P_LOCATION_NAME, @@ -153,6 +154,7 @@ enum RequestType { RT_MEDIA, RT_FOTA, RT_OEM_SPECIFIC, + RT_ICON_URL, RT_EMPTY // Added to allow empty Request Types handling }; @@ -181,6 +183,12 @@ bool IsValidEnum(ModuleType val); const char* EnumToJsonString(ModuleType val); bool EnumFromJsonString(const std::string& literal, ModuleType* result); +enum HybridAppPreference { HAP_MOBILE, HAP_CLOUD, HAP_BOTH }; +bool IsValidEnum(HybridAppPreference val); +const char* EnumToJsonString(HybridAppPreference val); +bool EnumFromJsonString(const std::string& literal, + HybridAppPreference* result); + /** * @brief Enumeration FunctionID. * @@ -434,6 +442,16 @@ enum FunctionID { SendHapticDataID = 49, /** + * @brief SetCloudAppPropertiesID. + */ + SetCloudAppPropertiesID = 50, + + /** + * @brief GetCloudAppPropertiesID. + */ + GetCloudAppPropertiesID = 51, + + /** * @brief OnHMIStatusID. */ OnHMIStatusID = 32768, diff --git a/src/components/policy/policy_external/include/policy/policy_table/types.h b/src/components/policy/policy_external/include/policy/policy_table/types.h index 68e29a97ee..e844381707 100644 --- a/src/components/policy/policy_external/include/policy/policy_table/types.h +++ b/src/components/policy/policy_external/include/policy/policy_table/types.h @@ -177,6 +177,14 @@ struct ApplicationParams : PolicyBase { Optional<Integer<uint16_t, 0, 65225> > memory_kb; Optional<Integer<uint32_t, 0, UINT_MAX> > heart_beat_timeout_ms; mutable Optional<ModuleTypes> moduleType; + Optional<String<0, 65535> > certificate; + // Cloud application params + Optional<Enum<HybridAppPreference> > hybrid_app_preference; + Optional<String<0, 255> > endpoint; + Optional<Boolean> enabled; + Optional<String<0, 65535> > auth_token; + Optional<String<0, 255> > cloud_transport_type; + Optional<String<0, 65535> > icon_url; public: ApplicationParams(); diff --git a/src/components/policy/policy_external/include/policy/policy_table_interface_ext.xml b/src/components/policy/policy_external/include/policy/policy_table_interface_ext.xml index 26af165506..f90edca8aa 100644 --- a/src/components/policy/policy_external/include/policy/policy_table_interface_ext.xml +++ b/src/components/policy/policy_external/include/policy/policy_table_interface_ext.xml @@ -56,6 +56,7 @@ <element name="fuelRange" /> <element name="tirePressureValue" /> <element name="tpms" /> + <element name="cloudAppVehicleID" /> </enum> <enum name="AppHMIType"> @@ -70,6 +71,12 @@ <element name="TESTING" /> <element name="SYSTEM" /> </enum> + + <enum name="HybridAppPreference"> + <element name="MOBILE" /> + <element name="CLOUD" /> + <element name="BOTH" /> + </enum> <!-- Common parameters end --> <!-- app_policies section start --> @@ -92,7 +99,16 @@ <param name="memory_kb" type="Integer" minvalue="1" maxvalue="65225" mandatory="false"/> <param name="watchdog_timer_ms" type="Integer" minvalue="1" maxvalue="65225" mandatory="false"/> - <param name="certificate" type="String" minlength="0" maxlength="255" + <param name="certificate" type="String" minlength="0" maxlength="65535" + mandatory="false" /> + <param name="endpoint" type="String" minlength="0" maxlength="255" mandatory="false" /> + <param name="enabled" type="Boolean" mandatory="false" /> + <param name="auth_token" type="String" minlength="0" maxlength="65535" + mandatory="false" /> + <param name="cloud_transport_type" type="String" minlength="0" maxlength="255" + mandatory="false" /> + <param name="hybrid_app_preference" type="HybridAppPreference" mandatory="false" /> + <param name="icon_url" type="String" minlength="0" maxlength="65535" mandatory="false" /> </struct> diff --git a/src/components/policy/policy_external/src/cache_manager.cc b/src/components/policy/policy_external/src/cache_manager.cc index c2c2e91257..c105a9161d 100644 --- a/src/components/policy/policy_external/src/cache_manager.cc +++ b/src/components/policy/policy_external/src/cache_manager.cc @@ -1389,6 +1389,142 @@ const policy::VehicleInfo CacheManager::GetVehicleInfo() const { return vehicle_info; } +void CacheManager::GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const { + const policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + for (policy_table::ApplicationPolicies::const_iterator it = policies.begin(); + it != policies.end(); + ++it) { + auto app_policy = (*it).second; + if (app_policy.enabled.is_initialized() && *app_policy.enabled) { + enabled_apps.push_back((*it).first); + } + } +} + +bool CacheManager::GetCloudAppParameters( + const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const { + const policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::const_iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + auto app_policy = (*policy_iter).second; + endpoint = app_policy.endpoint.is_initialized() ? *app_policy.endpoint + : std::string(); + auth_token = app_policy.auth_token.is_initialized() ? *app_policy.auth_token + : std::string(); + cloud_transport_type = app_policy.cloud_transport_type.is_initialized() + ? *app_policy.cloud_transport_type + : std::string(); + certificate = app_policy.certificate.is_initialized() + ? *app_policy.certificate + : std::string(); + hybrid_app_preference = + app_policy.hybrid_app_preference.is_initialized() + ? EnumToJsonString(*app_policy.hybrid_app_preference) + : std::string(); + enabled = app_policy.enabled.is_initialized() && *app_policy.enabled; + return true; + } + return false; +} + +void CacheManager::InitCloudApp(const std::string& policy_app_id) { + CACHE_MANAGER_CHECK_VOID(); + sync_primitives::AutoLock auto_lock(cache_lock_); + + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::const_iterator default_iter = + policies.find(kDefaultId); + policy_table::ApplicationPolicies::const_iterator app_iter = + policies.find(policy_app_id); + if (default_iter != policies.end()) { + if (app_iter == policies.end()) { + policies[policy_app_id] = policies[kDefaultId]; + } + } + // Add cloud app specific policies + Backup(); +} + +void CacheManager::SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled) { + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + *(*policy_iter).second.enabled = enabled; + } +} + +void CacheManager::SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token) { + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + *(*policy_iter).second.auth_token = auth_token; + } +} + +void CacheManager::SetAppCloudTransportType( + const std::string& policy_app_id, const std::string& cloud_transport_type) { + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + *(*policy_iter).second.cloud_transport_type = cloud_transport_type; + } +} + +void CacheManager::SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint) { + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + *(*policy_iter).second.endpoint = endpoint; + } +} + +void CacheManager::SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames) { + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + (*(*policy_iter).second.nicknames) = nicknames; + } +} + +void CacheManager::SetHybridAppPreference( + const std::string& policy_app_id, + const std::string& hybrid_app_preference) { + policy_table::HybridAppPreference value; + bool valid = EnumFromJsonString(hybrid_app_preference, &value); + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter && valid) { + *(*policy_iter).second.hybrid_app_preference = value; + } +} + std::vector<UserFriendlyMessage> CacheManager::GetUserFriendlyMsg( const std::vector<std::string>& msg_codes, const std::string& language, @@ -1491,6 +1627,21 @@ std::string CacheManager::GetLockScreenIconUrl() const { return std::string(""); } +std::string CacheManager::GetIconUrl(const std::string& policy_app_id) const { + CACHE_MANAGER_CHECK(std::string()); + std::string url; + const policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::const_iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + auto app_policy = (*policy_iter).second; + url = app_policy.icon_url.is_initialized() ? *app_policy.icon_url + : std::string(); + } + return url; +} + rpc::policy_table_interface_base::NumberOfNotificationsType CacheManager::GetNotificationsNumber(const std::string& priority) { CACHE_MANAGER_CHECK(0); diff --git a/src/components/policy/policy_external/src/policy_manager_impl.cc b/src/components/policy/policy_external/src/policy_manager_impl.cc index a603f122e2..28e493c115 100644 --- a/src/components/policy/policy_external/src/policy_manager_impl.cc +++ b/src/components/policy/policy_external/src/policy_manager_impl.cc @@ -271,6 +271,11 @@ std::string PolicyManagerImpl::GetLockScreenIconUrl() const { return cache_->GetLockScreenIconUrl(); } +std::string PolicyManagerImpl::GetIconUrl( + const std::string& policy_app_id) const { + return cache_->GetIconUrl(policy_app_id); +} + /** * @brief FilterInvalidFunctions filter functions that are absent in schema * @param rpcs list of functions to filter @@ -497,6 +502,12 @@ bool PolicyManagerImpl::LoadPT(const std::string& file, } else { LOG4CXX_INFO(logger_, "app_hmi_types empty"); } + + std::vector<std::string> enabled_apps; + cache_->GetEnabledCloudApps(enabled_apps); + for (auto it = enabled_apps.begin(); it != enabled_apps.end(); ++it) { + SendAuthTokenUpdated(*it); + } } // If there was a user request for policy table update, it should be started @@ -725,6 +736,63 @@ const VehicleInfo PolicyManagerImpl::GetVehicleInfo() const { return cache_->GetVehicleInfo(); } +void PolicyManagerImpl::GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const { + cache_->GetEnabledCloudApps(enabled_apps); +} + +bool PolicyManagerImpl::GetCloudAppParameters( + const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const { + return cache_->GetCloudAppParameters(policy_app_id, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference); +} + +void PolicyManagerImpl::InitCloudApp(const std::string& policy_app_id) { + cache_->InitCloudApp(policy_app_id); +} + +void PolicyManagerImpl::SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled) { + cache_->SetCloudAppEnabled(policy_app_id, enabled); +} + +void PolicyManagerImpl::SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token) { + cache_->SetAppAuthToken(policy_app_id, auth_token); +} + +void PolicyManagerImpl::SetAppCloudTransportType( + const std::string& policy_app_id, const std::string& cloud_transport_type) { + cache_->SetAppCloudTransportType(policy_app_id, cloud_transport_type); +} + +void PolicyManagerImpl::SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint) { + cache_->SetAppEndpoint(policy_app_id, endpoint); +} + +void PolicyManagerImpl::SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames) { + cache_->SetAppNicknames(policy_app_id, nicknames); +} + +void PolicyManagerImpl::SetHybridAppPreference( + const std::string& policy_app_id, + const std::string& hybrid_app_preference) { + cache_->SetHybridAppPreference(policy_app_id, hybrid_app_preference); +} + void PolicyManagerImpl::CheckPermissions(const PTString& app_id, const PTString& hmi_level, const PTString& rpc, @@ -2033,6 +2101,11 @@ bool PolicyManagerImpl::InitPT(const std::string& file_name, const bool ret = cache_->Init(file_name, settings); if (ret) { RefreshRetrySequence(); + std::vector<std::string> enabled_apps; + cache_->GetEnabledCloudApps(enabled_apps); + for (auto it = enabled_apps.begin(); it != enabled_apps.end(); ++it) { + SendAuthTokenUpdated(*it); + } } return ret; } @@ -2141,6 +2214,15 @@ void PolicyManagerImpl::SendAppPermissionsChanged( listener()->OnPermissionsUpdated(application_id, notification_data); } +void PolicyManagerImpl::SendAuthTokenUpdated(const std::string policy_app_id) { + bool enabled = false; + std::string end, cert, ctt, hap; + std::string auth_token; + cache_->GetCloudAppParameters( + policy_app_id, enabled, end, cert, auth_token, ctt, hap); + listener_->OnAuthTokenUpdated(policy_app_id, auth_token); +} + void PolicyManagerImpl::OnPrimaryGroupsChanged( const std::string& application_id) { const std::vector<std::string> devices = diff --git a/src/components/policy/policy_external/src/policy_table/enums.cc b/src/components/policy/policy_external/src/policy_table/enums.cc index 27db505e3f..aa4b8e55d1 100644 --- a/src/components/policy/policy_external/src/policy_table/enums.cc +++ b/src/components/policy/policy_external/src/policy_table/enums.cc @@ -1,4 +1,5 @@ #include "policy/policy_table/enums.h" +#include <cstring> namespace rpc { namespace policy_table_interface_base { @@ -137,6 +138,8 @@ bool IsValidEnum(Parameter val) { return true; case P_FUELRANGE: return true; + case P_CLOUD_APP_VEHICLE_ID: + return true; case P_ODOMETER: return true; case P_TIREPRESSURE: @@ -232,6 +235,8 @@ const char* EnumToJsonString(Parameter val) { return "instantFuelConsumption"; case P_FUELRANGE: return "fuelRange"; + case P_CLOUD_APP_VEHICLE_ID: + return "cloudAppVehicleID"; case P_ODOMETER: return "odometer"; case P_TIREPRESSURE: @@ -336,6 +341,9 @@ bool EnumFromJsonString(const std::string& literal, Parameter* result) { } else if ("fuelRange" == literal) { *result = P_FUELRANGE; return true; + } else if ("cloudAppVehicleID" == literal) { + *result = P_CLOUD_APP_VEHICLE_ID; + return true; } else if ("odometer" == literal) { *result = P_ODOMETER; return true; @@ -621,6 +629,8 @@ bool IsValidEnum(RequestType val) { return true; case RT_OEM_SPECIFIC: return true; + case RT_ICON_URL: + return true; case RT_EMPTY: return true; default: @@ -672,6 +682,8 @@ const char* EnumToJsonString(RequestType val) { return "FOTA"; case RT_OEM_SPECIFIC: return "OEM_SPECIFIC"; + case RT_ICON_URL: + return "ICON_URL"; case RT_EMPTY: return "EMPTY"; default: @@ -764,6 +776,10 @@ bool EnumFromJsonString(const std::string& literal, RequestType* result) { *result = RT_OEM_SPECIFIC; return true; } + if ("ICON_URL" == literal) { + *result = RT_ICON_URL; + return true; + } if ("EMPTY" == literal) { *result = RT_EMPTY; return true; @@ -840,6 +856,38 @@ bool EnumFromJsonString(const std::string& literal, ModuleType* result) { } } +bool IsValidEnum(HybridAppPreference val) { + return strlen(EnumToJsonString(val)) > 0; +} + +const char* EnumToJsonString(HybridAppPreference val) { + switch (val) { + case HAP_MOBILE: + return "MOBILE"; + case HAP_CLOUD: + return "CLOUD"; + case HAP_BOTH: + return "BOTH"; + default: + return ""; + } +} + +bool EnumFromJsonString(const std::string& literal, + HybridAppPreference* result) { + if ("MOBILE" == literal) { + *result = HAP_MOBILE; + return true; + } else if ("CLOUD" == literal) { + *result = HAP_CLOUD; + return true; + } else if ("BOTH" == literal) { + *result = HAP_BOTH; + return true; + } + return false; +} + bool EnumFromJsonString(const std::string& literal, FunctionID* result) { if ("RegisterAppInterface" == literal) { *result = RegisterAppInterfaceID; @@ -1081,6 +1129,16 @@ bool EnumFromJsonString(const std::string& literal, FunctionID* result) { return true; } + if ("SetCloudAppProperties" == literal) { + *result = SetCloudAppPropertiesID; + return true; + } + + if ("GetCloudAppProperties" == literal) { + *result = GetCloudAppPropertiesID; + return true; + } + if ("OnHMIStatus" == literal) { *result = OnHMIStatusID; return true; diff --git a/src/components/policy/policy_external/src/policy_table/types.cc b/src/components/policy/policy_external/src/policy_table/types.cc index 5922a020e6..12de0cc62b 100644 --- a/src/components/policy/policy_external/src/policy_table/types.cc +++ b/src/components/policy/policy_external/src/policy_table/types.cc @@ -241,7 +241,14 @@ ApplicationParams::ApplicationParams(const Json::Value* value__) , RequestSubType(impl::ValueMember(value__, "RequestSubType")) , memory_kb(impl::ValueMember(value__, "memory_kb"), 0) , heart_beat_timeout_ms(impl::ValueMember(value__, "heart_beat_timeout_ms")) - , moduleType(impl::ValueMember(value__, "moduleType")) {} + , moduleType(impl::ValueMember(value__, "moduleType")) + , certificate(impl::ValueMember(value__, "certificate")) + , hybrid_app_preference(impl::ValueMember(value__, "hybrid_app_preference")) + , endpoint(impl::ValueMember(value__, "endpoint")) + , enabled(impl::ValueMember(value__, "enabled")) + , auth_token(impl::ValueMember(value__, "auth_token")) + , cloud_transport_type(impl::ValueMember(value__, "cloud_transport_type")) + , icon_url(impl::ValueMember(value__, "icon_url")) {} Json::Value ApplicationParams::ToJsonValue() const { Json::Value result__(PolicyBase::ToJsonValue()); @@ -253,6 +260,14 @@ Json::Value ApplicationParams::ToJsonValue() const { impl::WriteJsonField( "heart_beat_timeout_ms", heart_beat_timeout_ms, &result__); impl::WriteJsonField("moduleType", moduleType, &result__); + impl::WriteJsonField("certificate", certificate, &result__); + impl::WriteJsonField( + "hybrid_app_preference", hybrid_app_preference, &result__); + impl::WriteJsonField("endpoint", endpoint, &result__); + impl::WriteJsonField("enabled", enabled, &result__); + impl::WriteJsonField("auth_token", auth_token, &result__); + impl::WriteJsonField("cloud_transport_type", cloud_transport_type, &result__); + impl::WriteJsonField("icon_url", auth_token, &result__); return result__; } @@ -277,6 +292,27 @@ bool ApplicationParams::is_valid() const { if (!moduleType.is_valid()) { return false; } + if (!certificate.is_valid()) { + return false; + } + if (!endpoint.is_valid()) { + return false; + } + if (!enabled.is_valid()) { + return false; + } + if (!auth_token.is_valid()) { + return false; + } + if (!cloud_transport_type.is_valid()) { + return false; + } + if (!hybrid_app_preference.is_valid()) { + return false; + } + if (!icon_url.is_valid()) { + return false; + } return Validate(); } @@ -309,6 +345,27 @@ bool ApplicationParams::struct_empty() const { if (moduleType.is_initialized()) { return false; } + if (certificate.is_initialized()) { + return false; + } + if (endpoint.is_initialized()) { + return false; + } + if (enabled.is_initialized()) { + return false; + } + if (auth_token.is_initialized()) { + return false; + } + if (cloud_transport_type.is_initialized()) { + return false; + } + if (hybrid_app_preference.is_initialized()) { + return false; + } + if (icon_url.is_initialized()) { + return false; + } return true; } @@ -357,6 +414,28 @@ void ApplicationParams::ReportErrors(rpc::ValidationReport* report__) const { if (!moduleType.is_valid()) { moduleType.ReportErrors(&report__->ReportSubobject("moduleType")); } + if (!certificate.is_valid()) { + certificate.ReportErrors(&report__->ReportSubobject("certificate")); + } + if (!endpoint.is_valid()) { + moduleType.ReportErrors(&report__->ReportSubobject("endpoint")); + } + if (!enabled.is_valid()) { + moduleType.ReportErrors(&report__->ReportSubobject("enabled")); + } + if (!auth_token.is_valid()) { + moduleType.ReportErrors(&report__->ReportSubobject("auth_token")); + } + if (!cloud_transport_type.is_valid()) { + moduleType.ReportErrors(&report__->ReportSubobject("cloud_transport_type")); + } + if (!hybrid_app_preference.is_valid()) { + moduleType.ReportErrors( + &report__->ReportSubobject("hybrid_app_preference")); + } + if (!icon_url.is_valid()) { + moduleType.ReportErrors(&report__->ReportSubobject("icon_url")); + } } void ApplicationParams::SetPolicyTableType(PolicyTableType pt_type) { @@ -367,6 +446,12 @@ void ApplicationParams::SetPolicyTableType(PolicyTableType pt_type) { memory_kb.SetPolicyTableType(pt_type); heart_beat_timeout_ms.SetPolicyTableType(pt_type); moduleType.SetPolicyTableType(pt_type); + certificate.SetPolicyTableType(pt_type); + endpoint.SetPolicyTableType(pt_type); + enabled.SetPolicyTableType(pt_type); + cloud_transport_type.SetPolicyTableType(pt_type); + hybrid_app_preference.SetPolicyTableType(pt_type); + icon_url.SetPolicyTableType(pt_type); } // RpcParameters methods diff --git a/src/components/policy/policy_external/src/sql_pt_ext_queries.cc b/src/components/policy/policy_external/src/sql_pt_ext_queries.cc index afb1180692..58206e2c69 100644 --- a/src/components/policy/policy_external/src/sql_pt_ext_queries.cc +++ b/src/components/policy/policy_external/src/sql_pt_ext_queries.cc @@ -205,7 +205,10 @@ const std::string kUpdateGroupPermissions = const std::string kInsertApplication = "INSERT OR IGNORE INTO `application`(`id`, `keep_context`, `steal_focus`, " " `default_hmi`, `priority_value`, `is_revoked`, `memory_kb`, " - " `heart_beat_timeout_ms`) VALUES( ?, ?, ?, ?, ?, ?, ?, ?) "; + " `heart_beat_timeout_ms`, `certificate`, `hybrid_app_preference_value`, " + " `endpoint`, `enabled`, `auth_token`, " + " `cloud_transport_type`, `icon_url`) VALUES " + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; const std::string kCollectFriendlyMsg = "SELECT * FROM `message`"; @@ -232,8 +235,9 @@ const std::string kSelectPreconsentedGroupsId = const std::string kSelectAppPolicies = "SELECT `id`, `priority_value`, `default_hmi`, `keep_context`, " - "`steal_focus`, " - " `memory_kb`, `heart_beat_timeout_ms` FROM `application`"; + " `steal_focus`, `memory_kb`, `heart_beat_timeout_ms`, `certificate`, " + " `hybrid_app_preference_value`, `endpoint`, `enabled`, `auth_token` " + " `cloud_transport_type`, `icon_url` FROM `application`"; const std::string kSelectFunctionalGroupNames = "SELECT `id`, `user_consent_prompt`, `name`" diff --git a/src/components/policy/policy_external/src/sql_pt_ext_representation.cc b/src/components/policy/policy_external/src/sql_pt_ext_representation.cc index a43b22a3b8..c0214f087f 100644 --- a/src/components/policy/policy_external/src/sql_pt_ext_representation.cc +++ b/src/components/policy/policy_external/src/sql_pt_ext_representation.cc @@ -752,6 +752,28 @@ bool SQLPTExtRepresentation::SaveSpecificAppPolicy( app_query.Bind(5, app.second.is_null()); app_query.Bind(6, *app.second.memory_kb); app_query.Bind(7, static_cast<int64_t>(*app.second.heart_beat_timeout_ms)); + app.second.certificate.is_initialized() + ? app_query.Bind(8, *app.second.certificate) + : app_query.Bind(8); + app.second.hybrid_app_preference.is_initialized() + ? app_query.Bind(9, + std::string(policy_table::EnumToJsonString( + *app.second.hybrid_app_preference))) + : app_query.Bind(9); + app.second.endpoint.is_initialized() + ? app_query.Bind(10, *app.second.endpoint) + : app_query.Bind(10); + app.second.enabled.is_initialized() ? app_query.Bind(11, *app.second.enabled) + : app_query.Bind(11); + app.second.auth_token.is_initialized() + ? app_query.Bind(12, *app.second.auth_token) + : app_query.Bind(12); + app.second.cloud_transport_type.is_initialized() + ? app_query.Bind(13, *app.second.cloud_transport_type) + : app_query.Bind(13); + app.second.icon_url.is_initialized() + ? app_query.Bind(14, *app.second.icon_url) + : app_query.Bind(14); if (!app_query.Exec() || !app_query.Reset()) { LOG4CXX_WARN(logger_, "Incorrect insert into application."); @@ -873,6 +895,23 @@ bool SQLPTExtRepresentation::GatherApplicationPoliciesSection( params.steal_focus = query.GetBoolean(4); *params.memory_kb = query.GetInteger(5); *params.heart_beat_timeout_ms = query.GetUInteger(6); + if (!query.IsNull(7)) { + *params.certificate = query.GetString(7); + } + + // Read cloud app properties + policy_table::HybridAppPreference hap; + bool valid = policy_table::EnumFromJsonString(query.GetString(8), &hap); + if (valid) { + *params.hybrid_app_preference = hap; + } + *params.endpoint = query.GetString(9); + if (!query.IsNull(10)) { + *params.enabled = query.GetBoolean(10); + } + *params.auth_token = query.GetString(11); + *params.cloud_transport_type = query.GetString(12); + *params.icon_url = query.GetString(13); const auto& gather_app_id = ((*policies).apps[app_id].is_string()) ? (*policies).apps[app_id].get_string() diff --git a/src/components/policy/policy_external/src/sql_pt_queries.cc b/src/components/policy/policy_external/src/sql_pt_queries.cc index 97d75731ea..66f7ef65be 100644 --- a/src/components/policy/policy_external/src/sql_pt_queries.cc +++ b/src/components/policy/policy_external/src/sql_pt_queries.cc @@ -98,6 +98,9 @@ const std::string kCreateSchema = "CREATE TABLE IF NOT EXISTS `hmi_level`( " " `value` VARCHAR(45) PRIMARY KEY NOT NULL " "); " + "CREATE TABLE IF NOT EXISTS `hybrid_app_preference`( " + " `value` VARCHAR(45) PRIMARY KEY NOT NULL " + "); " "CREATE TABLE IF NOT EXISTS `notifications_by_priority`( " " `priority_value` VARCHAR(45) PRIMARY KEY NOT NULL, " " `value` INTEGER NOT NULL, " @@ -147,6 +150,13 @@ const std::string kCreateSchema = " `is_predata` BOOLEAN, " " `memory_kb` INTEGER NOT NULL, " " `heart_beat_timeout_ms` INTEGER NOT NULL, " + " `certificate` VARCHAR(65535), " + " `hybrid_app_preference_value` VARCHAR(255), " + " `endpoint` VARCHAR(255), " + " `enabled` BOOLEAN, " + " `auth_token` VARCHAR(65535), " + " `cloud_transport_type` VARCHAR(255), " + " `icon_url` VARCHAR(65535), " " `remote_control_denied` BOOLEAN NOT NULL DEFAULT 0, " " CONSTRAINT `fk_application_hmi_level1` " " FOREIGN KEY(`default_hmi`) " @@ -154,11 +164,17 @@ const std::string kCreateSchema = " CONSTRAINT `fk_application_priorities1` " " FOREIGN KEY(`priority_value`) " " REFERENCES `priority`(`value`) " + " CONSTRAINT `fk_application_hybrid_app_preference1` " + " FOREIGN KEY(`hybrid_app_preference_value`) " + " REFERENCES `hybrid_app_preference`(`value`) " "); " "CREATE INDEX IF NOT EXISTS `application.fk_application_hmi_level1_idx` " " ON `application`(`default_hmi`); " "CREATE INDEX IF NOT EXISTS `application.fk_application_priorities1_idx` " " ON `application`(`priority_value`); " + "CREATE INDEX IF NOT EXISTS " + "`application.fk_application_hybrid_app_preference1` " + " ON `application`(`hybrid_app_preference_value`); " "CREATE TABLE IF NOT EXISTS `app_group`( " " `application_id` VARCHAR(45) NOT NULL COLLATE NOCASE, " " `functional_group_id` INTEGER NOT NULL, " @@ -430,6 +446,9 @@ const std::string kInsertInitData = "INSERT OR IGNORE INTO `hmi_level`(`value`) VALUES ('LIMITED'); " "INSERT OR IGNORE INTO `hmi_level`(`value`) VALUES ('BACKGROUND'); " "INSERT OR IGNORE INTO `hmi_level`(`value`) VALUES ('NONE'); " + "INSERT OR IGNORE INTO `hybrid_app_preference`(`value`) VALUES ('MOBILE'); " + "INSERT OR IGNORE INTO `hybrid_app_preference`(`value`) VALUES ('CLOUD'); " + "INSERT OR IGNORE INTO `hybrid_app_preference`(`value`) VALUES ('BOTH'); " "INSERT OR IGNORE INTO `version` (`number`) VALUES('0'); " "INSERT OR IGNORE INTO `_internal_data` (`db_version_hash`) VALUES(0); " ""; @@ -532,6 +551,7 @@ const std::string kDropSchema = "`notifications_by_priority.fk_notifications_by_priority_priority1_idx`; " "DROP TABLE IF EXISTS `notifications_by_priority`; " "DROP TABLE IF EXISTS `hmi_level`; " + "DROP TABLE IF EXISTS `hybrid_app_preference`; " "DROP TABLE IF EXISTS `priority`; " "DROP TABLE IF EXISTS `functional_group`; " "DROP TABLE IF EXISTS `module_config`; " @@ -628,8 +648,10 @@ const std::string kInsertRpcWithParameter = const std::string kInsertApplication = "INSERT OR IGNORE INTO `application` (`id`, `priority_value`, " - "`is_revoked`, `memory_kb`," - " `heart_beat_timeout_ms`) VALUES (?,?,?,?,?)"; + "`is_revoked`, `memory_kb`, `heart_beat_timeout_ms`, `certificate`, " + "`hybrid_app_preference_value`, `endpoint`, `enabled`, `auth_token`, " + "`cloud_transport_type`, `icon_url`) VALUES " + "(?,?,?,?,?,?,?,?,?,?,?,?)"; const std::string kInsertAppGroup = "INSERT INTO `app_group` (`application_id`, `functional_group_id`)" @@ -752,7 +774,10 @@ const std::string kSelectUserMsgsVersion = const std::string kSelectAppPolicies = "SELECT `id`, `priority_value`, `memory_kb`, " - " `heart_beat_timeout_ms` FROM `application`"; + " `heart_beat_timeout_ms`, `certificate`, `hybrid_app_preference_value`, " + " `endpoint`, `enabled`, `auth_token`, `cloud_transport_type`, `icon_url` " + "FROM " + " `application`"; const std::string kCollectFriendlyMsg = "SELECT * FROM `message`"; @@ -849,15 +874,19 @@ const std::string kDeleteAppGroupByApplicationId = const std::string kInsertApplicationFull = "INSERT OR IGNORE INTO `application` (`id`, `keep_context`, `steal_focus`, " - " `default_hmi`, `priority_value`, `is_revoked`, `is_default`, " - "`is_predata`, " - " `memory_kb`, `heart_beat_timeout_ms`) " - " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + " `default_hmi`, `priority_value`, `is_revoked`, `is_default`, " + " `is_predata`, `memory_kb`, `heart_beat_timeout_ms`, " + " `certificate`, `hybrid_app_preference_value`, `endpoint`, `enabled`, " + " `auth_token`, `cloud_transport_type`, `icon_url`) " + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; const std::string kSelectApplicationFull = "SELECT `keep_context`, `steal_focus`, `default_hmi`, `priority_value`, " " `is_revoked`, `is_default`, `is_predata`, `memory_kb`," - " `heart_beat_timeout_ms` FROM `application` WHERE `id` = ?"; + " `heart_beat_timeout_ms`, `certificate`, `hybrid_app_preference_value`, " + " `endpoint`, `enabled`, `auth_token`, `cloud_transport_type`, `icon_url` " + "FROM `application` " + "WHERE `id` = ?"; const std::string kSelectDBVersion = "SELECT `db_version_hash` from `_internal_data`"; diff --git a/src/components/policy/policy_external/src/sql_pt_representation.cc b/src/components/policy/policy_external/src/sql_pt_representation.cc index c8b367c8ec..885a59ba36 100644 --- a/src/components/policy/policy_external/src/sql_pt_representation.cc +++ b/src/components/policy/policy_external/src/sql_pt_representation.cc @@ -761,6 +761,24 @@ bool SQLPTRepresentation::GatherApplicationPoliciesSection( *params.memory_kb = query.GetInteger(2); *params.heart_beat_timeout_ms = query.GetUInteger(3); + if (!query.IsNull(4)) { + *params.certificate = query.GetString(4); + } + + // Read cloud app properties + policy_table::HybridAppPreference hap; + bool valid = policy_table::EnumFromJsonString(query.GetString(5), &hap); + if (valid) { + *params.hybrid_app_preference = hap; + } + *params.endpoint = query.GetString(6); + if (!query.IsNull(7)) { + *params.enabled = query.GetBoolean(7); + } + *params.auth_token = query.GetString(8); + *params.cloud_transport_type = query.GetString(9); + *params.icon_url = query.GetString(10); + const auto& gather_app_id = ((*policies).apps[app_id].is_string()) ? (*policies).apps[app_id].get_string() : app_id; @@ -1035,6 +1053,27 @@ bool SQLPTRepresentation::SaveSpecificAppPolicy( app_query.Bind(2, app.second.is_null()); app_query.Bind(3, *app.second.memory_kb); app_query.Bind(4, static_cast<int64_t>(*app.second.heart_beat_timeout_ms)); + app.second.certificate.is_initialized() + ? app_query.Bind(5, *app.second.certificate) + : app_query.Bind(5); + app.second.hybrid_app_preference.is_initialized() + ? app_query.Bind(6, + std::string(policy_table::EnumToJsonString( + *app.second.hybrid_app_preference))) + : app_query.Bind(6); + app.second.endpoint.is_initialized() ? app_query.Bind(7, *app.second.endpoint) + : app_query.Bind(7); + app.second.enabled.is_initialized() ? app_query.Bind(8, *app.second.enabled) + : app_query.Bind(8); + app.second.auth_token.is_initialized() + ? app_query.Bind(9, *app.second.auth_token) + : app_query.Bind(9); + app.second.cloud_transport_type.is_initialized() + ? app_query.Bind(10, *app.second.cloud_transport_type) + : app_query.Bind(10); + app.second.icon_url.is_initialized() + ? app_query.Bind(11, *app.second.icon_url) + : app_query.Bind(11); if (!app_query.Exec() || !app_query.Reset()) { LOG4CXX_WARN(logger_, "Incorrect insert into application."); @@ -2125,6 +2164,20 @@ bool SQLPTRepresentation::CopyApplication(const std::string& source, : query.Bind(7, source_app.GetBoolean(6)); query.Bind(8, source_app.GetInteger(7)); query.Bind(9, source_app.GetInteger(8)); + source_app.IsNull(9) ? query.Bind(10) + : query.Bind(10, source_app.GetString(9)); + source_app.IsNull(10) ? query.Bind(11) + : query.Bind(11, source_app.GetString(10)); + source_app.IsNull(11) ? query.Bind(12) + : query.Bind(12, source_app.GetString(11)); + source_app.IsNull(12) ? query.Bind(13) + : query.Bind(13, source_app.GetBoolean(12)); + source_app.IsNull(13) ? query.Bind(14) + : query.Bind(14, source_app.GetString(13)); + source_app.IsNull(14) ? query.Bind(15) + : query.Bind(15, source_app.GetString(14)); + source_app.IsNull(15) ? query.Bind(16) + : query.Bind(16, source_app.GetString(15)); if (!query.Exec()) { LOG4CXX_WARN(logger_, "Failed inserting into application."); diff --git a/src/components/policy/policy_external/test/json/PTU.json b/src/components/policy/policy_external/test/json/PTU.json index 4cd71d6004..c5f4b90120 100644 --- a/src/components/policy/policy_external/test/json/PTU.json +++ b/src/components/policy/policy_external/test/json/PTU.json @@ -485,6 +485,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -509,6 +510,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -533,6 +535,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -556,6 +559,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/PTU2.json b/src/components/policy/policy_external/test/json/PTU2.json index 9c9436144e..01cca4a6fd 100644 --- a/src/components/policy/policy_external/test/json/PTU2.json +++ b/src/components/policy/policy_external/test/json/PTU2.json @@ -485,6 +485,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -509,6 +510,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -533,6 +535,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -556,6 +559,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/PTU3.json b/src/components/policy/policy_external/test/json/PTU3.json index 279051e7bf..f48f246114 100644 --- a/src/components/policy/policy_external/test/json/PTU3.json +++ b/src/components/policy/policy_external/test/json/PTU3.json @@ -485,6 +485,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -509,6 +510,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -533,6 +535,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -556,6 +559,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/PTU_with_empty_requestType_array.json b/src/components/policy/policy_external/test/json/PTU_with_empty_requestType_array.json index 08027f2786..1e99e7442c 100644 --- a/src/components/policy/policy_external/test/json/PTU_with_empty_requestType_array.json +++ b/src/components/policy/policy_external/test/json/PTU_with_empty_requestType_array.json @@ -1605,6 +1605,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1623,6 +1624,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1641,6 +1643,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1658,6 +1661,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/PTU_with_invalid_requestType_between_correct.json b/src/components/policy/policy_external/test/json/PTU_with_invalid_requestType_between_correct.json index a88bcfbd08..dc40c3a182 100644 --- a/src/components/policy/policy_external/test/json/PTU_with_invalid_requestType_between_correct.json +++ b/src/components/policy/policy_external/test/json/PTU_with_invalid_requestType_between_correct.json @@ -1608,6 +1608,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1626,6 +1627,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1644,6 +1646,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1661,6 +1664,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/PTU_with_one_invalid_requestType.json b/src/components/policy/policy_external/test/json/PTU_with_one_invalid_requestType.json index 250bfb21f2..3fcc71ca72 100644 --- a/src/components/policy/policy_external/test/json/PTU_with_one_invalid_requestType.json +++ b/src/components/policy/policy_external/test/json/PTU_with_one_invalid_requestType.json @@ -1605,6 +1605,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1623,6 +1624,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1641,6 +1643,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1658,6 +1661,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/PTU_without_requestType_field.json b/src/components/policy/policy_external/test/json/PTU_without_requestType_field.json index 85910c098c..03a5e8d203 100644 --- a/src/components/policy/policy_external/test/json/PTU_without_requestType_field.json +++ b/src/components/policy/policy_external/test/json/PTU_without_requestType_field.json @@ -1604,6 +1604,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1622,6 +1623,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1640,6 +1642,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1657,6 +1660,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/preloadedPT_with_invalid_default_reqestType_between_valid.json b/src/components/policy/policy_external/test/json/preloadedPT_with_invalid_default_reqestType_between_valid.json index 1c1b04ca2b..b5dd0bfff5 100644 --- a/src/components/policy/policy_external/test/json/preloadedPT_with_invalid_default_reqestType_between_valid.json +++ b/src/components/policy/policy_external/test/json/preloadedPT_with_invalid_default_reqestType_between_valid.json @@ -362,6 +362,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -382,6 +383,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -402,6 +404,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] @@ -421,6 +424,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] diff --git a/src/components/policy/policy_external/test/json/preloadedPT_with_invalid_default_requestType.json b/src/components/policy/policy_external/test/json/preloadedPT_with_invalid_default_requestType.json index 51690d7b8e..8fa8e6f3d0 100644 --- a/src/components/policy/policy_external/test/json/preloadedPT_with_invalid_default_requestType.json +++ b/src/components/policy/policy_external/test/json/preloadedPT_with_invalid_default_requestType.json @@ -362,6 +362,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -382,6 +383,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -402,6 +404,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] @@ -421,6 +424,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] diff --git a/src/components/policy/policy_external/test/json/preloadedPT_with_several_invalid_default_requestTypes.json b/src/components/policy/policy_external/test/json/preloadedPT_with_several_invalid_default_requestTypes.json index cfa6c4010c..589cdc7a81 100644 --- a/src/components/policy/policy_external/test/json/preloadedPT_with_several_invalid_default_requestTypes.json +++ b/src/components/policy/policy_external/test/json/preloadedPT_with_several_invalid_default_requestTypes.json @@ -362,6 +362,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -382,6 +383,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -402,6 +404,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] @@ -421,6 +424,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] diff --git a/src/components/policy/policy_external/test/json/ptu2_requestType.json b/src/components/policy/policy_external/test/json/ptu2_requestType.json index d7177f2251..9b580b2a08 100644 --- a/src/components/policy/policy_external/test/json/ptu2_requestType.json +++ b/src/components/policy/policy_external/test/json/ptu2_requestType.json @@ -497,6 +497,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -521,6 +522,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -545,6 +547,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -568,6 +571,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/ptu_requestType.json b/src/components/policy/policy_external/test/json/ptu_requestType.json index 6a531dd2ad..8d18a9e336 100644 --- a/src/components/policy/policy_external/test/json/ptu_requestType.json +++ b/src/components/policy/policy_external/test/json/ptu_requestType.json @@ -496,6 +496,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -520,6 +521,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -544,6 +546,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -567,6 +570,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_preloaded_pt.json b/src/components/policy/policy_external/test/json/sdl_preloaded_pt.json index 59e3f947c3..ad264c8518 100644 --- a/src/components/policy/policy_external/test/json/sdl_preloaded_pt.json +++ b/src/components/policy/policy_external/test/json/sdl_preloaded_pt.json @@ -363,6 +363,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -383,6 +384,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -403,6 +405,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] @@ -422,6 +425,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] diff --git a/src/components/policy/policy_external/test/json/sdl_preloaded_pt1.json b/src/components/policy/policy_external/test/json/sdl_preloaded_pt1.json index a4491fd449..909fd2cb2f 100644 --- a/src/components/policy/policy_external/test/json/sdl_preloaded_pt1.json +++ b/src/components/policy/policy_external/test/json/sdl_preloaded_pt1.json @@ -2321,6 +2321,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -2343,6 +2344,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -2365,6 +2367,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -2386,6 +2389,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_preloaded_pt_send_location.json b/src/components/policy/policy_external/test/json/sdl_preloaded_pt_send_location.json index 83c4ccf15c..87fac7c76c 100644 --- a/src/components/policy/policy_external/test/json/sdl_preloaded_pt_send_location.json +++ b/src/components/policy/policy_external/test/json/sdl_preloaded_pt_send_location.json @@ -497,6 +497,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -521,6 +522,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -545,6 +547,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -568,6 +571,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_pt_first_update.json b/src/components/policy/policy_external/test/json/sdl_pt_first_update.json index 7b882c6ceb..440963ba48 100644 --- a/src/components/policy/policy_external/test/json/sdl_pt_first_update.json +++ b/src/components/policy/policy_external/test/json/sdl_pt_first_update.json @@ -1622,6 +1622,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1640,6 +1641,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1658,6 +1660,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1675,6 +1678,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_pt_second_update.json b/src/components/policy/policy_external/test/json/sdl_pt_second_update.json index 7d90275328..5900acbcfb 100644 --- a/src/components/policy/policy_external/test/json/sdl_pt_second_update.json +++ b/src/components/policy/policy_external/test/json/sdl_pt_second_update.json @@ -1622,6 +1622,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1640,6 +1641,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1658,6 +1660,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1675,6 +1678,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_pt_update.json b/src/components/policy/policy_external/test/json/sdl_pt_update.json index 807b0eb312..b3affeb91d 100644 --- a/src/components/policy/policy_external/test/json/sdl_pt_update.json +++ b/src/components/policy/policy_external/test/json/sdl_pt_update.json @@ -1606,6 +1606,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1624,6 +1625,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1642,6 +1644,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1659,6 +1662,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_have_params.json b/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_have_params.json index 3d0a004dbe..639d0143c8 100644 --- a/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_have_params.json +++ b/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_have_params.json @@ -496,6 +496,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -520,6 +521,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -544,6 +546,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -567,6 +570,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_no_params_in1.json b/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_no_params_in1.json index 6a36f1f9c5..53216cab3d 100644 --- a/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_no_params_in1.json +++ b/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_no_params_in1.json @@ -496,6 +496,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -520,6 +521,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -544,6 +546,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -567,6 +570,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_no_params_in1_omitted_in2.json b/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_no_params_in1_omitted_in2.json index 3303d56844..a529dc9a3b 100644 --- a/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_no_params_in1_omitted_in2.json +++ b/src/components/policy/policy_external/test/json/sdl_update_pt_2_groups_no_params_in1_omitted_in2.json @@ -496,6 +496,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -520,6 +521,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -544,6 +546,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -567,6 +570,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_update_pt_send_location.json b/src/components/policy/policy_external/test/json/sdl_update_pt_send_location.json index e7a33ba2c0..a57791e248 100644 --- a/src/components/policy/policy_external/test/json/sdl_update_pt_send_location.json +++ b/src/components/policy/policy_external/test/json/sdl_update_pt_send_location.json @@ -496,6 +496,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -520,6 +521,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -544,6 +546,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -567,6 +570,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_all_params.json b/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_all_params.json index 08739f9d6a..5a633e7c95 100644 --- a/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_all_params.json +++ b/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_all_params.json @@ -496,6 +496,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -520,6 +521,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -544,6 +546,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -567,6 +570,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_no_params.json b/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_no_params.json index 21396b8cac..86c121491b 100644 --- a/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_no_params.json +++ b/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_no_params.json @@ -496,6 +496,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -520,6 +521,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -544,6 +546,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -567,6 +570,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_some_params.json b/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_some_params.json index 5aa467a23c..2b57912016 100644 --- a/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_some_params.json +++ b/src/components/policy/policy_external/test/json/sdl_update_pt_send_location_some_params.json @@ -496,6 +496,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -520,6 +521,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -544,6 +546,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -567,6 +570,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/json/valid_sdl_pt_update.json b/src/components/policy/policy_external/test/json/valid_sdl_pt_update.json index 5827ab287a..35e6b1d1a6 100644 --- a/src/components/policy/policy_external/test/json/valid_sdl_pt_update.json +++ b/src/components/policy/policy_external/test/json/valid_sdl_pt_update.json @@ -1598,6 +1598,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1616,6 +1617,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1634,6 +1636,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1651,6 +1654,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_external/test/sql_pt_representation_test.cc b/src/components/policy/policy_external/test/sql_pt_representation_test.cc index b0f340b0f2..fddc5e631e 100644 --- a/src/components/policy/policy_external/test/sql_pt_representation_test.cc +++ b/src/components/policy/policy_external/test/sql_pt_representation_test.cc @@ -406,8 +406,8 @@ TEST_F(SQLPTRepresentationTest, query.Prepare(query_select); query.Next(); - // 33 - is current total tables number created by schema - const int policy_tables_number = 33; + // 34 - is current total tables number created by schema + const int policy_tables_number = 34; ASSERT_EQ(policy_tables_number, query.GetInteger(0)); const std::string query_select_count_of_iap_buffer_full = diff --git a/src/components/policy/policy_regular/include/policy/cache_manager.h b/src/components/policy/policy_regular/include/policy/cache_manager.h index 48e00f7049..b789c7252c 100644 --- a/src/components/policy/policy_regular/include/policy/cache_manager.h +++ b/src/components/policy/policy_regular/include/policy/cache_manager.h @@ -147,6 +147,90 @@ class CacheManager : public CacheManagerInterface { virtual const VehicleInfo GetVehicleInfo() const; /** + * @brief Get a list of enabled cloud applications + * @param enabled_apps List filled with the policy app id of each enabled + * cloud application + */ + virtual void GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const; + + /** + * @brief Get cloud app policy information, all fields that aren't set for a + * given app will be filled with empty strings + * @param policy_app_id Unique application id + * @param enabled Whether or not the app is enabled + * @param endpoint Filled with the endpoint used to connect to the cloud + * application + * @param certificate Filled with the certificate used to for creating a + * secure connection to the cloud application + * @param auth_token Filled with the token used for authentication when + * reconnecting to the cloud app + * @param cloud_transport_type Filled with the transport type used by the + * cloud application (ex. "WSS") + * @param hybrid_app_preference Filled with the hybrid app preference for the + * cloud application set by the user + */ + virtual bool GetCloudAppParameters(const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const; + + /** + * Initializes a new cloud application with default policies + * Then adds cloud specific policies + * @param app_id application id + * @return true if success + */ + virtual void InitCloudApp(const std::string& policy_app_id); + + /** + * @brief Enable or disable a cloud application in the HMI + * @param enabled Cloud app enabled state + */ + virtual void SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled); + + /** + * @brief Set an app's auth token + * @param auth_token Cloud app authentication token + */ + virtual void SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token); + + /** + * @brief Set a cloud app's transport type + * @param cloud_transport_type Cloud app transport type + */ + virtual void SetAppCloudTransportType( + const std::string& policy_app_id, + const std::string& cloud_transport_type); + + /** + * @brief Set a cloud app's endpoint url + * @param endpoint URL for websocket connection + */ + virtual void SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint); + + /** + * @brief Set a cloud app's nicknames + * @param nicknames Nicknames for cloud app + */ + virtual void SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames); + + /** + * @brief Set the user preference for how a hybrid (cloud and mobile) app + * should be used + * @param hybrid_app_preference Hybrid app user preference + */ + virtual void SetHybridAppPreference(const std::string& policy_app_id, + const std::string& hybrid_app_preference); + + /** * @brief Allows to update 'vin' field in module_meta table. * * @param new 'vin' value. @@ -186,6 +270,15 @@ class CacheManager : public CacheManagerInterface { virtual std::string GetLockScreenIconUrl() const; /** + * @brief Get Icon Url used for showing a cloud apps icon before the intial + *registration + * + * @return url which point to the resourse where icon could be + *obtained. + */ + virtual std::string GetIconUrl(const std::string& policy_app_id) const; + + /** * @brief Get allowed number of notifications * depending on application priority. * @param priority Priority of application diff --git a/src/components/policy/policy_regular/include/policy/cache_manager_interface.h b/src/components/policy/policy_regular/include/policy/cache_manager_interface.h index 10a6ea7f89..4a59bfb8a9 100644 --- a/src/components/policy/policy_regular/include/policy/cache_manager_interface.h +++ b/src/components/policy/policy_regular/include/policy/cache_manager_interface.h @@ -152,6 +152,91 @@ class CacheManagerInterface { virtual const VehicleInfo GetVehicleInfo() const = 0; /** + * @brief Get a list of enabled cloud applications + * @param enabled_apps List filled with the policy app id of each enabled + * cloud application + */ + virtual void GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const = 0; + + /** + * @brief Get cloud app policy information, all fields that aren't set for a + * given app will be filled with empty strings + * @param policy_app_id Unique application id + * @param enabled Whether or not the app is enabled + * @param endpoint Filled with the endpoint used to connect to the cloud + * application + * @param certificate Filled with the certificate used to for creating a + * secure connection to the cloud application + * @param auth_token Filled with the token used for authentication when + * reconnecting to the cloud app + * @param cloud_transport_type Filled with the transport type used by the + * cloud application (ex. "WSS") + * @param hybrid_app_preference Filled with the hybrid app preference for the + * cloud application set by the user + */ + virtual bool GetCloudAppParameters( + const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const = 0; + + /** + * Initializes a new cloud application with default policies + * Then adds cloud specific policies + * @param app_id application id + * @return true if success + */ + virtual void InitCloudApp(const std::string& policy_app_id) = 0; + + /** + * @brief Enable or disable a cloud application in the HMI + * @param enabled Cloud app enabled state + */ + virtual void SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled) = 0; + + /** + * @brief Set an app's auth token + * @param auth_token Cloud app authentication token + */ + virtual void SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token) = 0; + + /** + * @brief Set a cloud app's transport type + * @param cloud_transport_type Cloud app transport type + */ + virtual void SetAppCloudTransportType( + const std::string& policy_app_id, + const std::string& cloud_transport_type) = 0; + + /** + * @brief Set a cloud app's endpoint url + * @param endpoint URL for websocket connection + */ + virtual void SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint) = 0; + + /** + * @brief Set a cloud app's nicknames + * @param nicknames Nicknames for cloud app + */ + virtual void SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames) = 0; + /** + * @brief Set the user preference for how a hybrid (cloud and mobile) app + * should be used + * @param hybrid_app_preference Hybrid app user preference + */ + virtual void SetHybridAppPreference( + const std::string& policy_app_id, + const std::string& hybrid_app_preference) = 0; + + /** * @brief Allows to update 'vin' field in module_meta table. * * @param new 'vin' value. @@ -192,6 +277,15 @@ class CacheManagerInterface { virtual std::string GetLockScreenIconUrl() const = 0; /** + * @brief Get Icon Url used for showing a cloud apps icon before the intial + *registration + * + * @return url which point to the resourse where icon could be + *obtained. + */ + virtual std::string GetIconUrl(const std::string& policy_app_id) const = 0; + + /** * @brief Get allowed number of notifications * depending on application priority. * @param priority Priority of application diff --git a/src/components/policy/policy_regular/include/policy/policy_manager_impl.h b/src/components/policy/policy_regular/include/policy/policy_manager_impl.h index 51d4ee88aa..1b5a78ed00 100644 --- a/src/components/policy/policy_regular/include/policy/policy_manager_impl.h +++ b/src/components/policy/policy_regular/include/policy/policy_manager_impl.h @@ -117,6 +117,15 @@ class PolicyManagerImpl : public PolicyManager { std::string GetLockScreenIconUrl() const OVERRIDE; /** + * @brief Get Icon Url used for showing a cloud apps icon before the intial + *registration + * + * @return url which point to the resourse where icon could be + *obtained. + */ + std::string GetIconUrl(const std::string& policy_app_id) const OVERRIDE; + + /** * @brief PTU is needed, for this PTS has to be formed and sent. */ bool RequestPTUpdate() OVERRIDE; @@ -565,6 +574,90 @@ class PolicyManagerImpl : public PolicyManager { const VehicleInfo GetVehicleInfo() const OVERRIDE; /** + * @brief Get a list of enabled cloud applications + * @param enabled_apps List filled with the policy app id of each enabled + * cloud application + */ + void GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const OVERRIDE; + + /** + * @brief Get cloud app policy information, all fields that aren't set for a + * given app will be filled with empty strings + * @param policy_app_id Unique application id + * @param enabled Whether or not the app is enabled + * @param endpoint Filled with the endpoint used to connect to the cloud + * application + * @param certificate Filled with the certificate used to for creating a + * secure connection to the cloud application + * @param auth_token Filled with the token used for authentication when + * reconnecting to the cloud app + * @param cloud_transport_type Filled with the transport type used by the + * cloud application (ex. "WSS") + * @param hybrid_app_preference Filled with the hybrid app preference for the + * cloud application set by the user + */ + bool GetCloudAppParameters(const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const OVERRIDE; + + /** + * @ brief Initialize new cloud app in the policy table + * @ param policy_app_id Application ID + */ + + void InitCloudApp(const std::string& policy_app_id) OVERRIDE; + + /** + * @brief Enable or disable a cloud application in the HMI + * @param enabled Cloud app enabled state + */ + void SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled) OVERRIDE; + + /** + * @brief Set an app's auth token + * @param auth_token Cloud app authentication token + */ + void SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token) OVERRIDE; + + /** + * @brief Set a cloud app's transport type + * @param cloud_transport_type Cloud app transport type + */ + void SetAppCloudTransportType( + const std::string& policy_app_id, + const std::string& cloud_transport_type) OVERRIDE; + + /** + * @brief Set a cloud app's endpoint url + * @param endpoint URL for websocket connection + */ + void SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint) OVERRIDE; + + /** + * @brief Set a cloud app's nicknames + * @param nicknames Nicknames for cloud app + */ + void SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames) OVERRIDE; + + /** + * @brief Set the user preference for how a hybrid (cloud and mobile) app + * should be used + * @param hybrid_app_preference Hybrid app user preference + */ + void SetHybridAppPreference( + const std::string& policy_app_id, + const std::string& hybrid_app_preference) OVERRIDE; + + /** * @brief OnAppRegisteredOnMobile allows to handle event when application were * succesfully registered on mobile device. * It will send OnAppPermissionSend notification and will try to start PTU. * @@ -840,6 +933,12 @@ class PolicyManagerImpl : public PolicyManager { const std::string& application_id) OVERRIDE; /** + * @brief notify listener of updated auth token for a given policy id + * @param policy_app_id the app id that has an updated auth token + */ + void SendAuthTokenUpdated(const std::string policy_app_id); + + /** * @brief Gets all allowed module types * @param policy_app_id unique identifier of application * @param modules list of allowed module types diff --git a/src/components/policy/policy_regular/include/policy/policy_table/enums.h b/src/components/policy/policy_regular/include/policy/policy_table/enums.h index 1f10db9f6f..a32060d9bc 100644 --- a/src/components/policy/policy_regular/include/policy/policy_table/enums.h +++ b/src/components/policy/policy_regular/include/policy/policy_table/enums.h @@ -86,6 +86,7 @@ enum Parameter { P_STEERINGWHEELANGLE, P_ENGINEOILLIFE, P_MYKEY, + P_CLOUD_APP_VEHICLE_ID, P_AIRBAGSTATUS, P_BODYINFORMATION, P_CLUSTERMODESTATUS, @@ -167,6 +168,12 @@ bool IsValidEnum(ModuleType val); const char* EnumToJsonString(ModuleType val); bool EnumFromJsonString(const std::string& literal, ModuleType* result); +enum HybridAppPreference { HAP_MOBILE, HAP_CLOUD, HAP_BOTH }; +bool IsValidEnum(HybridAppPreference val); +const char* EnumToJsonString(HybridAppPreference val); +bool EnumFromJsonString(const std::string& literal, + HybridAppPreference* result); + /** * @brief Enumeration FunctionID. * @@ -420,6 +427,16 @@ enum FunctionID { SendHapticDataID = 49, /** + * @brief SetCloudAppPropertiesID. + */ + SetCloudAppPropertiesID = 50, + + /** + * @brief GetCloudAppPropertiesID. + */ + GetCloudAppPropertiesID = 51, + + /** * @brief OnHMIStatusID. */ OnHMIStatusID = 32768, diff --git a/src/components/policy/policy_regular/include/policy/policy_table/types.h b/src/components/policy/policy_regular/include/policy/policy_table/types.h index e201251745..63058dee26 100644 --- a/src/components/policy/policy_regular/include/policy/policy_table/types.h +++ b/src/components/policy/policy_regular/include/policy/policy_table/types.h @@ -142,8 +142,15 @@ struct ApplicationParams : PolicyBase { Optional<RequestSubTypes> RequestSubType; Optional<Integer<uint16_t, 0, 65225> > memory_kb; Optional<Integer<uint32_t, 0, UINT_MAX> > heart_beat_timeout_ms; - Optional<String<0, 255> > certificate; + Optional<String<0, 65535> > certificate; mutable Optional<ModuleTypes> moduleType; + // Cloud application params + Optional<Enum<HybridAppPreference> > hybrid_app_preference; + Optional<String<0, 255> > endpoint; + Optional<Boolean> enabled; + Optional<String<0, 65535> > auth_token; + Optional<String<0, 255> > cloud_transport_type; + Optional<String<0, 65535> > icon_url; public: ApplicationParams(); diff --git a/src/components/policy/policy_regular/src/cache_manager.cc b/src/components/policy/policy_regular/src/cache_manager.cc index bd95fc8e7c..a8e033d505 100644 --- a/src/components/policy/policy_regular/src/cache_manager.cc +++ b/src/components/policy/policy_regular/src/cache_manager.cc @@ -682,6 +682,144 @@ const policy::VehicleInfo CacheManager::GetVehicleInfo() const { return vehicle_info; } +void CacheManager::GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const { + const policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + for (policy_table::ApplicationPolicies::const_iterator it = policies.begin(); + it != policies.end(); + ++it) { + auto app_policy = (*it).second; + if (app_policy.enabled.is_initialized() && *app_policy.enabled) { + enabled_apps.push_back((*it).first); + } + } +} + +bool CacheManager::GetCloudAppParameters( + const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const { + const policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::const_iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + auto app_policy = (*policy_iter).second; + endpoint = app_policy.endpoint.is_initialized() ? *app_policy.endpoint + : std::string(); + auth_token = app_policy.auth_token.is_initialized() ? *app_policy.auth_token + : std::string(); + cloud_transport_type = app_policy.cloud_transport_type.is_initialized() + ? *app_policy.cloud_transport_type + : std::string(); + certificate = app_policy.certificate.is_initialized() + ? *app_policy.certificate + : std::string(); + hybrid_app_preference = + app_policy.hybrid_app_preference.is_initialized() + ? EnumToJsonString(*app_policy.hybrid_app_preference) + : std::string(); + enabled = app_policy.enabled.is_initialized() && *app_policy.enabled; + return true; + } + return false; +} + +void CacheManager::InitCloudApp(const std::string& policy_app_id) { + CACHE_MANAGER_CHECK_VOID(); + sync_primitives::AutoLock auto_lock(cache_lock_); + + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::const_iterator default_iter = + policies.find(kDefaultId); + policy_table::ApplicationPolicies::const_iterator app_iter = + policies.find(policy_app_id); + + if (default_iter != policies.end()) { + if (app_iter == policies.end()) { + policies[policy_app_id] = policies[kDefaultId]; + } + } + // Add cloud app specific policies + + Backup(); +} + +void CacheManager::SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled) { + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + *(*policy_iter).second.enabled = enabled; + } +} + +void CacheManager::SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token) { + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + *(*policy_iter).second.auth_token = auth_token; + } +} + +void CacheManager::SetAppCloudTransportType( + const std::string& policy_app_id, const std::string& cloud_transport_type) { + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + *(*policy_iter).second.cloud_transport_type = cloud_transport_type; + } +} + +void CacheManager::SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint) { + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + *(*policy_iter).second.endpoint = endpoint; + } +} + +void CacheManager::SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames) { + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + (*(*policy_iter).second.nicknames) = nicknames; + } +} + +void CacheManager::SetHybridAppPreference( + const std::string& policy_app_id, + const std::string& hybrid_app_preference) { + policy_table::HybridAppPreference value; + bool valid = EnumFromJsonString(hybrid_app_preference, &value); + policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter && valid) { + *(*policy_iter).second.hybrid_app_preference = value; + } +} + std::vector<UserFriendlyMessage> CacheManager::GetUserFriendlyMsg( const std::vector<std::string>& msg_codes, const std::string& language) { LOG4CXX_AUTO_TRACE(logger_); @@ -778,6 +916,21 @@ std::string CacheManager::GetLockScreenIconUrl() const { return std::string(""); } +std::string CacheManager::GetIconUrl(const std::string& policy_app_id) const { + CACHE_MANAGER_CHECK(std::string()); + std::string url; + const policy_table::ApplicationPolicies& policies = + pt_->policy_table.app_policies_section.apps; + policy_table::ApplicationPolicies::const_iterator policy_iter = + policies.find(policy_app_id); + if (policies.end() != policy_iter) { + auto app_policy = (*policy_iter).second; + url = app_policy.icon_url.is_initialized() ? *app_policy.icon_url + : std::string(); + } + return url; +} + rpc::policy_table_interface_base::NumberOfNotificationsType CacheManager::GetNotificationsNumber(const std::string& priority) { CACHE_MANAGER_CHECK(0); diff --git a/src/components/policy/policy_regular/src/policy_manager_impl.cc b/src/components/policy/policy_regular/src/policy_manager_impl.cc index 4985035629..bbd843b7c2 100644 --- a/src/components/policy/policy_regular/src/policy_manager_impl.cc +++ b/src/components/policy/policy_regular/src/policy_manager_impl.cc @@ -217,7 +217,7 @@ void FilterInvalidApplicationParameters( } app_params.AppHMIType->swap(valid_app_hmi_types); - // Filter RquestTypes array + // Filter RequestTypes array policy_table::RequestTypes valid_request_types; const policy_table::RequestTypes& request_types = *(app_params.RequestType); for (const auto& request_type : request_types) { @@ -368,6 +368,12 @@ bool PolicyManagerImpl::LoadPT(const std::string& file, } else { LOG4CXX_INFO(logger_, "app_hmi_types empty" << pt_content.size()); } + + std::vector<std::string> enabled_apps; + cache_->GetEnabledCloudApps(enabled_apps); + for (auto it = enabled_apps.begin(); it != enabled_apps.end(); ++it) { + SendAuthTokenUpdated(*it); + } } // If there was a user request for policy table update, it should be started @@ -443,6 +449,11 @@ std::string PolicyManagerImpl::GetLockScreenIconUrl() const { return cache_->GetLockScreenIconUrl(); } +std::string PolicyManagerImpl::GetIconUrl( + const std::string& policy_app_id) const { + return cache_->GetIconUrl(policy_app_id); +} + void PolicyManagerImpl::StartPTExchange() { LOG4CXX_AUTO_TRACE(logger_); @@ -544,6 +555,63 @@ const VehicleInfo PolicyManagerImpl::GetVehicleInfo() const { return cache_->GetVehicleInfo(); } +void PolicyManagerImpl::GetEnabledCloudApps( + std::vector<std::string>& enabled_apps) const { + cache_->GetEnabledCloudApps(enabled_apps); +} + +bool PolicyManagerImpl::GetCloudAppParameters( + const std::string& policy_app_id, + bool& enabled, + std::string& endpoint, + std::string& certificate, + std::string& auth_token, + std::string& cloud_transport_type, + std::string& hybrid_app_preference) const { + return cache_->GetCloudAppParameters(policy_app_id, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference); +} + +void PolicyManagerImpl::InitCloudApp(const std::string& policy_app_id) { + cache_->InitCloudApp(policy_app_id); +} + +void PolicyManagerImpl::SetCloudAppEnabled(const std::string& policy_app_id, + const bool enabled) { + cache_->SetCloudAppEnabled(policy_app_id, enabled); +} + +void PolicyManagerImpl::SetAppAuthToken(const std::string& policy_app_id, + const std::string& auth_token) { + cache_->SetAppAuthToken(policy_app_id, auth_token); +} + +void PolicyManagerImpl::SetAppCloudTransportType( + const std::string& policy_app_id, const std::string& cloud_transport_type) { + cache_->SetAppCloudTransportType(policy_app_id, cloud_transport_type); +} + +void PolicyManagerImpl::SetAppEndpoint(const std::string& policy_app_id, + const std::string& endpoint) { + cache_->SetAppEndpoint(policy_app_id, endpoint); +} + +void PolicyManagerImpl::SetAppNicknames(const std::string& policy_app_id, + const StringArray& nicknames) { + cache_->SetAppNicknames(policy_app_id, nicknames); +} + +void PolicyManagerImpl::SetHybridAppPreference( + const std::string& policy_app_id, + const std::string& hybrid_app_preference) { + cache_->SetHybridAppPreference(policy_app_id, hybrid_app_preference); +} + void PolicyManagerImpl::CheckPermissions(const PTString& device_id, const PTString& app_id, const PTString& hmi_level, @@ -1294,6 +1362,11 @@ bool PolicyManagerImpl::InitPT(const std::string& file_name, if (!certificate_data.empty()) { listener_->OnCertificateUpdated(certificate_data); } + std::vector<std::string> enabled_apps; + cache_->GetEnabledCloudApps(enabled_apps); + for (auto it = enabled_apps.begin(); it != enabled_apps.end(); ++it) { + SendAuthTokenUpdated(*it); + } } return ret; } @@ -1409,6 +1482,15 @@ void PolicyManagerImpl::SendAppPermissionsChanged( listener()->OnPermissionsUpdated(application_id, notification_data); } +void PolicyManagerImpl::SendAuthTokenUpdated(const std::string policy_app_id) { + bool enabled = false; + std::string end, cert, ctt, hap; + std::string auth_token; + cache_->GetCloudAppParameters( + policy_app_id, enabled, end, cert, auth_token, ctt, hap); + listener_->OnAuthTokenUpdated(policy_app_id, auth_token); +} + void PolicyManagerImpl::OnPrimaryGroupsChanged( const std::string& application_id) { const std::vector<std::string> devices = diff --git a/src/components/policy/policy_regular/src/policy_table/enums.cc b/src/components/policy/policy_regular/src/policy_table/enums.cc index 428e18d0bd..195213f844 100644 --- a/src/components/policy/policy_regular/src/policy_table/enums.cc +++ b/src/components/policy/policy_regular/src/policy_table/enums.cc @@ -1,5 +1,5 @@ -// This file is generated, do not edit #include "policy/policy_table/enums.h" +#include <cstring> namespace rpc { namespace policy_table_interface_base { @@ -138,6 +138,8 @@ bool IsValidEnum(Parameter val) { return true; case P_FUELRANGE: return true; + case P_CLOUD_APP_VEHICLE_ID: + return true; case P_ODOMETER: return true; case P_TIREPRESSURE: @@ -204,6 +206,8 @@ const char* EnumToJsonString(Parameter val) { return "instantFuelConsumption"; case P_FUELRANGE: return "fuelRange"; + case P_CLOUD_APP_VEHICLE_ID: + return "cloudAppVehicleID"; case P_ODOMETER: return "odometer"; case P_TIREPRESSURE: @@ -280,6 +284,9 @@ bool EnumFromJsonString(const std::string& literal, Parameter* result) { } else if ("fuelRange" == literal) { *result = P_FUELRANGE; return true; + } else if ("cloudAppVehicleID" == literal) { + *result = P_CLOUD_APP_VEHICLE_ID; + return true; } else if ("odometer" == literal) { *result = P_ODOMETER; return true; @@ -662,6 +669,7 @@ bool IsValidEnum(ModuleType val) { return false; } } + const char* EnumToJsonString(ModuleType val) { switch (val) { case MT_CLIMATE: @@ -709,6 +717,38 @@ bool EnumFromJsonString(const std::string& literal, ModuleType* result) { return false; } +bool IsValidEnum(HybridAppPreference val) { + return strlen(EnumToJsonString(val)) > 0; +} + +const char* EnumToJsonString(HybridAppPreference val) { + switch (val) { + case HAP_MOBILE: + return "MOBILE"; + case HAP_CLOUD: + return "CLOUD"; + case HAP_BOTH: + return "BOTH"; + default: + return ""; + } +} + +bool EnumFromJsonString(const std::string& literal, + HybridAppPreference* result) { + if ("MOBILE" == literal) { + *result = HAP_MOBILE; + return true; + } else if ("CLOUD" == literal) { + *result = HAP_CLOUD; + return true; + } else if ("BOTH" == literal) { + *result = HAP_BOTH; + return true; + } + return false; +} + bool IsValidEnum(FunctionID val) { switch (val) { case RegisterAppInterfaceID: @@ -807,6 +847,10 @@ bool IsValidEnum(FunctionID val) { return true; case SendHapticDataID: return true; + case SetCloudAppPropertiesID: + return true; + case GetCloudAppPropertiesID: + return true; case OnHMIStatusID: return true; case OnAppInterfaceUnregisteredID: @@ -954,6 +998,10 @@ const char* EnumToJsonString(FunctionID val) { return "GetSystemCapability"; case SendHapticDataID: return "SendHapticData"; + case SetCloudAppPropertiesID: + return "SetCloudAppProperties"; + case GetCloudAppPropertiesID: + return "GetCloudAppProperties"; case OnHMIStatusID: return "OnHMIStatus"; case OnAppInterfaceUnregisteredID: @@ -1244,6 +1292,16 @@ bool EnumFromJsonString(const std::string& literal, FunctionID* result) { return true; } + if ("SetCloudAppProperties" == literal) { + *result = SetCloudAppPropertiesID; + return true; + } + + if ("GetCloudAppProperties" == literal) { + *result = GetCloudAppPropertiesID; + return true; + } + if ("OnHMIStatus" == literal) { *result = OnHMIStatusID; return true; diff --git a/src/components/policy/policy_regular/src/policy_table/types.cc b/src/components/policy/policy_regular/src/policy_table/types.cc index 851ed1bd18..2ee8bf1b21 100644 --- a/src/components/policy/policy_regular/src/policy_table/types.cc +++ b/src/components/policy/policy_regular/src/policy_table/types.cc @@ -167,8 +167,14 @@ ApplicationParams::ApplicationParams(const Json::Value* value__) , RequestSubType(impl::ValueMember(value__, "RequestSubType")) , memory_kb(impl::ValueMember(value__, "memory_kb"), 0) , heart_beat_timeout_ms(impl::ValueMember(value__, "heart_beat_timeout_ms")) - , certificate(impl::ValueMember(value__, "certificate"), "not_specified") - , moduleType(impl::ValueMember(value__, "moduleType")) {} + , certificate(impl::ValueMember(value__, "certificate")) + , moduleType(impl::ValueMember(value__, "moduleType")) + , hybrid_app_preference(impl::ValueMember(value__, "hybrid_app_preference")) + , endpoint(impl::ValueMember(value__, "endpoint")) + , enabled(impl::ValueMember(value__, "enabled")) + , auth_token(impl::ValueMember(value__, "auth_token")) + , cloud_transport_type(impl::ValueMember(value__, "cloud_transport_type")) + , icon_url(impl::ValueMember(value__, "icon_url")) {} Json::Value ApplicationParams::ToJsonValue() const { Json::Value result__(PolicyBase::ToJsonValue()); @@ -180,7 +186,15 @@ Json::Value ApplicationParams::ToJsonValue() const { impl::WriteJsonField("memory_kb", memory_kb, &result__); impl::WriteJsonField( "heart_beat_timeout_ms", heart_beat_timeout_ms, &result__); + impl::WriteJsonField("certificate", certificate, &result__); impl::WriteJsonField("moduleType", moduleType, &result__); + impl::WriteJsonField( + "hybrid_app_preference", hybrid_app_preference, &result__); + impl::WriteJsonField("endpoint", endpoint, &result__); + impl::WriteJsonField("enabled", enabled, &result__); + impl::WriteJsonField("auth_token", auth_token, &result__); + impl::WriteJsonField("cloud_transport_type", cloud_transport_type, &result__); + impl::WriteJsonField("icon_url", auth_token, &result__); return result__; } @@ -212,6 +226,24 @@ bool ApplicationParams::is_valid() const { if (!moduleType.is_valid()) { return false; } + if (!endpoint.is_valid()) { + return false; + } + if (!enabled.is_valid()) { + return false; + } + if (!auth_token.is_valid()) { + return false; + } + if (!cloud_transport_type.is_valid()) { + return false; + } + if (!hybrid_app_preference.is_valid()) { + return false; + } + if (!icon_url.is_valid()) { + return false; + } return Validate(); } @@ -250,6 +282,24 @@ bool ApplicationParams::struct_empty() const { if (moduleType.is_initialized()) { return false; } + if (endpoint.is_initialized()) { + return false; + } + if (enabled.is_initialized()) { + return false; + } + if (auth_token.is_initialized()) { + return false; + } + if (cloud_transport_type.is_initialized()) { + return false; + } + if (hybrid_app_preference.is_initialized()) { + return false; + } + if (icon_url.is_initialized()) { + return false; + } return true; } @@ -288,6 +338,25 @@ void ApplicationParams::ReportErrors(rpc::ValidationReport* report__) const { if (!moduleType.is_valid()) { moduleType.ReportErrors(&report__->ReportSubobject("moduleType")); } + if (!endpoint.is_valid()) { + moduleType.ReportErrors(&report__->ReportSubobject("endpoint")); + } + if (!enabled.is_valid()) { + moduleType.ReportErrors(&report__->ReportSubobject("enabled")); + } + if (!auth_token.is_valid()) { + moduleType.ReportErrors(&report__->ReportSubobject("auth_token")); + } + if (!cloud_transport_type.is_valid()) { + moduleType.ReportErrors(&report__->ReportSubobject("cloud_transport_type")); + } + if (!hybrid_app_preference.is_valid()) { + moduleType.ReportErrors( + &report__->ReportSubobject("hybrid_app_preference")); + } + if (!icon_url.is_valid()) { + moduleType.ReportErrors(&report__->ReportSubobject("icon_url")); + } } void ApplicationParams::SetPolicyTableType(PolicyTableType pt_type) { @@ -300,6 +369,11 @@ void ApplicationParams::SetPolicyTableType(PolicyTableType pt_type) { heart_beat_timeout_ms.SetPolicyTableType(pt_type); certificate.SetPolicyTableType(pt_type); moduleType.SetPolicyTableType(pt_type); + endpoint.SetPolicyTableType(pt_type); + enabled.SetPolicyTableType(pt_type); + cloud_transport_type.SetPolicyTableType(pt_type); + hybrid_app_preference.SetPolicyTableType(pt_type); + icon_url.SetPolicyTableType(pt_type); } // RpcParameters methods diff --git a/src/components/policy/policy_regular/src/sql_pt_queries.cc b/src/components/policy/policy_regular/src/sql_pt_queries.cc index f5ccffce3b..8d2576866b 100644 --- a/src/components/policy/policy_regular/src/sql_pt_queries.cc +++ b/src/components/policy/policy_regular/src/sql_pt_queries.cc @@ -84,6 +84,9 @@ const std::string kCreateSchema = "CREATE TABLE IF NOT EXISTS `hmi_level`( " " `value` VARCHAR(45) PRIMARY KEY NOT NULL " "); " + "CREATE TABLE IF NOT EXISTS `hybrid_app_preference`( " + " `value` VARCHAR(45) PRIMARY KEY NOT NULL " + "); " "CREATE TABLE IF NOT EXISTS `notifications_by_priority`( " " `priority_value` VARCHAR(45) PRIMARY KEY NOT NULL, " " `value` INTEGER NOT NULL, " @@ -133,7 +136,13 @@ const std::string kCreateSchema = " `is_predata` BOOLEAN, " " `memory_kb` INTEGER NOT NULL, " " `heart_beat_timeout_ms` INTEGER NOT NULL, " - " `certificate` VARCHAR(45), " + " `certificate` VARCHAR(65535), " + " `hybrid_app_preference_value` VARCHAR(255), " + " `endpoint` VARCHAR(255), " + " `enabled` BOOLEAN, " + " `auth_token` VARCHAR(65535), " + " `cloud_transport_type` VARCHAR(255), " + " `icon_url` VARCHAR(65535), " " `remote_control_denied` BOOLEAN NOT NULL DEFAULT 0, " " CONSTRAINT `fk_application_hmi_level1` " " FOREIGN KEY(`default_hmi`) " @@ -141,11 +150,17 @@ const std::string kCreateSchema = " CONSTRAINT `fk_application_priorities1` " " FOREIGN KEY(`priority_value`) " " REFERENCES `priority`(`value`) " + " CONSTRAINT `fk_application_hybrid_app_preference1` " + " FOREIGN KEY(`hybrid_app_preference_value`) " + " REFERENCES `hybrid_app_preference`(`value`) " "); " "CREATE INDEX IF NOT EXISTS `application.fk_application_hmi_level1_idx` " " ON `application`(`default_hmi`); " "CREATE INDEX IF NOT EXISTS `application.fk_application_priorities1_idx` " " ON `application`(`priority_value`); " + "CREATE INDEX IF NOT EXISTS " + "`application.fk_application_hybrid_app_preference1` " + " ON `application`(`hybrid_app_preference_value`); " "CREATE TABLE IF NOT EXISTS `app_group`( " " `application_id` VARCHAR(45) NOT NULL COLLATE NOCASE, " " `functional_group_id` INTEGER NOT NULL, " @@ -391,6 +406,9 @@ const std::string kInsertInitData = "INSERT OR IGNORE INTO `hmi_level`(`value`) VALUES ('LIMITED'); " "INSERT OR IGNORE INTO `hmi_level`(`value`) VALUES ('BACKGROUND'); " "INSERT OR IGNORE INTO `hmi_level`(`value`) VALUES ('NONE'); " + "INSERT OR IGNORE INTO `hybrid_app_preference`(`value`) VALUES ('MOBILE'); " + "INSERT OR IGNORE INTO `hybrid_app_preference`(`value`) VALUES ('CLOUD'); " + "INSERT OR IGNORE INTO `hybrid_app_preference`(`value`) VALUES ('BOTH'); " "INSERT OR IGNORE INTO `version` (`number`) VALUES('0'); " "INSERT OR IGNORE INTO `_internal_data` (`db_version_hash`) VALUES(0); " ""; @@ -491,6 +509,7 @@ const std::string kDropSchema = "`notifications_by_priority.fk_notifications_by_priority_priority1_idx`; " "DROP TABLE IF EXISTS `notifications_by_priority`; " "DROP TABLE IF EXISTS `hmi_level`; " + "DROP TABLE IF EXISTS `hybrid_app_preference`; " "DROP TABLE IF EXISTS `priority`; " "DROP TABLE IF EXISTS `functional_group`; " "DROP TABLE IF EXISTS `module_config`; " @@ -578,8 +597,10 @@ const std::string kInsertRpcWithParameter = const std::string kInsertApplication = "INSERT OR IGNORE INTO `application` (`id`, `priority_value`, " - "`is_revoked`, `memory_kb`," - " `heart_beat_timeout_ms`, `certificate`) VALUES (?,?,?,?,?,?)"; + "`is_revoked`, `memory_kb`, `heart_beat_timeout_ms`, `certificate`, " + "`hybrid_app_preference_value`, `endpoint`, `enabled`, `auth_token`, " + "`cloud_transport_type`, `icon_url`) VALUES " + "(?,?,?,?,?,?,?,?,?,?,?,?)"; const std::string kInsertAppGroup = "INSERT INTO `app_group` (`application_id`, `functional_group_id`)" @@ -688,7 +709,10 @@ const std::string kSelectUserMsgsVersion = const std::string kSelectAppPolicies = "SELECT `id`, `priority_value`, `memory_kb`, " - " `heart_beat_timeout_ms`, `certificate` FROM `application`"; + " `heart_beat_timeout_ms`, `certificate`, `hybrid_app_preference_value`, " + " `endpoint`, `enabled`, `auth_token`, `cloud_transport_type`, `icon_url` " + "FROM " + " `application`"; const std::string kCollectFriendlyMsg = "SELECT * FROM `message`"; @@ -785,15 +809,19 @@ const std::string kDeleteAppGroupByApplicationId = const std::string kInsertApplicationFull = "INSERT OR IGNORE INTO `application` (`id`, `keep_context`, `steal_focus`, " - " `default_hmi`, `priority_value`, `is_revoked`, `is_default`, " - "`is_predata`, " - " `memory_kb`, `heart_beat_timeout_ms`, `certificate`) " - " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + " `default_hmi`, `priority_value`, `is_revoked`, `is_default`, " + " `is_predata`, `memory_kb`, `heart_beat_timeout_ms`, " + " `certificate`, `hybrid_app_preference_value`, `endpoint`, `enabled`, " + " `auth_token`, `cloud_transport_type`, `icon_url`) " + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; const std::string kSelectApplicationFull = "SELECT `keep_context`, `steal_focus`, `default_hmi`, `priority_value`, " " `is_revoked`, `is_default`, `is_predata`, `memory_kb`," - " `heart_beat_timeout_ms`, `certificate` FROM `application` WHERE `id` = " + " `heart_beat_timeout_ms`, `certificate`, `hybrid_app_preference_value`, " + " `endpoint`, `enabled`, `auth_token`, `cloud_transport_type`, `icon_url` " + "FROM `application` " + "WHERE `id` = " "?"; const std::string kSelectDBVersion = diff --git a/src/components/policy/policy_regular/src/sql_pt_representation.cc b/src/components/policy/policy_regular/src/sql_pt_representation.cc index 75f8be74eb..49aeec2642 100644 --- a/src/components/policy/policy_regular/src/sql_pt_representation.cc +++ b/src/components/policy/policy_regular/src/sql_pt_representation.cc @@ -716,12 +716,25 @@ bool SQLPTRepresentation::GatherApplicationPoliciesSection( params.priority = priority; *params.memory_kb = query.GetInteger(2); - *params.heart_beat_timeout_ms = query.GetUInteger(3); - if (!query.IsNull(3)) { + if (!query.IsNull(4)) { *params.certificate = query.GetString(4); } + // Read cloud app properties + policy_table::HybridAppPreference hap; + bool valid = policy_table::EnumFromJsonString(query.GetString(5), &hap); + if (valid) { + *params.hybrid_app_preference = hap; + } + *params.endpoint = query.GetString(6); + if (!query.IsNull(7)) { + *params.enabled = query.GetBoolean(7); + } + *params.auth_token = query.GetString(8); + *params.cloud_transport_type = query.GetString(9); + *params.icon_url = query.GetString(10); + const auto& gather_app_id = ((*policies).apps[app_id].is_string()) ? (*policies).apps[app_id].get_string() : app_id; @@ -984,6 +997,25 @@ bool SQLPTRepresentation::SaveSpecificAppPolicy( app.second.certificate.is_initialized() ? app_query.Bind(5, *app.second.certificate) : app_query.Bind(5); + app.second.hybrid_app_preference.is_initialized() + ? app_query.Bind(6, + std::string(policy_table::EnumToJsonString( + *app.second.hybrid_app_preference))) + : app_query.Bind(6); + app.second.endpoint.is_initialized() ? app_query.Bind(7, *app.second.endpoint) + : app_query.Bind(7); + app.second.enabled.is_initialized() ? app_query.Bind(8, *app.second.enabled) + : app_query.Bind(8); + app.second.auth_token.is_initialized() + ? app_query.Bind(9, *app.second.auth_token) + : app_query.Bind(9); + app.second.cloud_transport_type.is_initialized() + ? app_query.Bind(10, *app.second.cloud_transport_type) + : app_query.Bind(10); + app.second.icon_url.is_initialized() + ? app_query.Bind(11, *app.second.icon_url) + : app_query.Bind(11); + if (!app_query.Exec() || !app_query.Reset()) { LOG4CXX_WARN(logger_, "Incorrect insert into application."); return false; @@ -2084,6 +2116,19 @@ bool SQLPTRepresentation::CopyApplication(const std::string& source, query.Bind(9, source_app.GetInteger(8)); source_app.IsNull(9) ? query.Bind(10) : query.Bind(10, source_app.GetString(9)); + source_app.IsNull(10) ? query.Bind(11) + : query.Bind(11, source_app.GetString(10)); + source_app.IsNull(11) ? query.Bind(12) + : query.Bind(12, source_app.GetString(11)); + source_app.IsNull(12) ? query.Bind(13) + : query.Bind(13, source_app.GetBoolean(12)); + source_app.IsNull(13) ? query.Bind(14) + : query.Bind(14, source_app.GetString(13)); + source_app.IsNull(14) ? query.Bind(15) + : query.Bind(15, source_app.GetString(14)); + source_app.IsNull(15) ? query.Bind(16) + : query.Bind(16, source_app.GetString(15)); + if (!query.Exec()) { LOG4CXX_WARN(logger_, "Failed inserting into application."); return false; diff --git a/src/components/policy/policy_regular/test/PTU.json b/src/components/policy/policy_regular/test/PTU.json index 2f4735dd66..dbf16598f0 100644 --- a/src/components/policy/policy_regular/test/PTU.json +++ b/src/components/policy/policy_regular/test/PTU.json @@ -362,6 +362,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -382,6 +383,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -402,6 +404,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] @@ -421,6 +424,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] diff --git a/src/components/policy/policy_regular/test/PTU2.json b/src/components/policy/policy_regular/test/PTU2.json index 806ab8bcc0..2c0063f69a 100644 --- a/src/components/policy/policy_regular/test/PTU2.json +++ b/src/components/policy/policy_regular/test/PTU2.json @@ -362,6 +362,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -382,6 +383,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -402,6 +404,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] @@ -421,6 +424,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] diff --git a/src/components/policy/policy_regular/test/PTU3.json b/src/components/policy/policy_regular/test/PTU3.json index 28396be29a..d579fd3e3f 100644 --- a/src/components/policy/policy_regular/test/PTU3.json +++ b/src/components/policy/policy_regular/test/PTU3.json @@ -362,6 +362,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -382,6 +383,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -402,6 +404,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] @@ -421,6 +424,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] diff --git a/src/components/policy/policy_regular/test/PTU4.json b/src/components/policy/policy_regular/test/PTU4.json index 4592e228df..84b6404010 100644 --- a/src/components/policy/policy_regular/test/PTU4.json +++ b/src/components/policy/policy_regular/test/PTU4.json @@ -362,6 +362,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -382,6 +383,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -402,6 +404,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] @@ -421,6 +424,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] diff --git a/src/components/policy/policy_regular/test/ptu2_requestType.json b/src/components/policy/policy_regular/test/ptu2_requestType.json index 2a05a94f8b..9013971990 100644 --- a/src/components/policy/policy_regular/test/ptu2_requestType.json +++ b/src/components/policy/policy_regular/test/ptu2_requestType.json @@ -498,6 +498,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -522,6 +523,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -546,6 +548,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -569,6 +572,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_regular/test/ptu_requestType.json b/src/components/policy/policy_regular/test/ptu_requestType.json index b0d9117568..892a77f970 100644 --- a/src/components/policy/policy_regular/test/ptu_requestType.json +++ b/src/components/policy/policy_regular/test/ptu_requestType.json @@ -498,6 +498,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -522,6 +523,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -546,6 +548,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -569,6 +572,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_regular/test/sdl_preloaded_pt.json b/src/components/policy/policy_regular/test/sdl_preloaded_pt.json index 59e3f947c3..ad264c8518 100644 --- a/src/components/policy/policy_regular/test/sdl_preloaded_pt.json +++ b/src/components/policy/policy_regular/test/sdl_preloaded_pt.json @@ -363,6 +363,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -383,6 +384,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -403,6 +405,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] @@ -422,6 +425,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus"] diff --git a/src/components/policy/policy_regular/test/sdl_pt_first_update.json b/src/components/policy/policy_regular/test/sdl_pt_first_update.json index 7b882c6ceb..440963ba48 100644 --- a/src/components/policy/policy_regular/test/sdl_pt_first_update.json +++ b/src/components/policy/policy_regular/test/sdl_pt_first_update.json @@ -1622,6 +1622,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1640,6 +1641,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1658,6 +1660,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1675,6 +1678,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_regular/test/sdl_pt_second_update.json b/src/components/policy/policy_regular/test/sdl_pt_second_update.json index 7d90275328..5900acbcfb 100644 --- a/src/components/policy/policy_regular/test/sdl_pt_second_update.json +++ b/src/components/policy/policy_regular/test/sdl_pt_second_update.json @@ -1622,6 +1622,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1640,6 +1641,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1658,6 +1660,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1675,6 +1678,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_regular/test/sdl_pt_update.json b/src/components/policy/policy_regular/test/sdl_pt_update.json index 909e4d5238..6f5e223cae 100644 --- a/src/components/policy/policy_regular/test/sdl_pt_update.json +++ b/src/components/policy/policy_regular/test/sdl_pt_update.json @@ -1600,6 +1600,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1618,6 +1619,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1636,6 +1638,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1653,6 +1656,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/policy/policy_regular/test/sql_pt_representation_test.cc b/src/components/policy/policy_regular/test/sql_pt_representation_test.cc index 7d192515dc..030dc374dd 100644 --- a/src/components/policy/policy_regular/test/sql_pt_representation_test.cc +++ b/src/components/policy/policy_regular/test/sql_pt_representation_test.cc @@ -426,8 +426,8 @@ TEST_F(SQLPTRepresentationTest, ASSERT_TRUE(reps->RefreshDB()); // Check PT structure destroyed and tables number is 0 - // There are 29 tables in the database, now. - const int32_t total_tables_number = 29; + // There are 30 tables in the database, now. + const int32_t total_tables_number = 30; ASSERT_EQ(total_tables_number, dbms->FetchOneInt(query_select)); const char* query_select_count_of_iap_buffer_full = "SELECT `count_of_iap_buffer_full` FROM `usage_and_error_count`"; diff --git a/src/components/policy/policy_regular/test/valid_sdl_pt_update.json b/src/components/policy/policy_regular/test/valid_sdl_pt_update.json index 5827ab287a..35e6b1d1a6 100644 --- a/src/components/policy/policy_regular/test/valid_sdl_pt_update.json +++ b/src/components/policy/policy_regular/test/valid_sdl_pt_update.json @@ -1598,6 +1598,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1616,6 +1617,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "vin", @@ -1634,6 +1636,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" @@ -1651,6 +1654,7 @@ "headLampStatus", "instantFuelConsumption", "fuelRange", + "cloudAppVehicleID", "odometer", "tirePressure", "wiperStatus" diff --git a/src/components/protocol/src/bson_object_keys.cc b/src/components/protocol/src/bson_object_keys.cc index 11160d7082..acafd3dbd2 100644 --- a/src/components/protocol/src/bson_object_keys.cc +++ b/src/components/protocol/src/bson_object_keys.cc @@ -18,6 +18,7 @@ const char* video_service_transports = "videoServiceTransports"; const char* tcp_ip_address = "tcpIpAddress"; const char* tcp_port = "tcpPort"; const char* reason = "reason"; +const char* auth_token = "authToken"; } // namespace strings diff --git a/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h b/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h index 3e7d64e9d2..89800037b5 100644 --- a/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h +++ b/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h @@ -428,6 +428,9 @@ class ProtocolHandlerImpl void NotifySessionStarted(const SessionContext& context, std::vector<std::string>& rejected_params) OVERRIDE; + void OnAuthTokenUpdated(const std::string& policy_app_id, + const std::string& auth_token) OVERRIDE; + #ifdef BUILD_TESTS const impl::FromMobileQueue& get_from_mobile_queue() const { return raw_ford_messages_from_mobile_; @@ -512,6 +515,10 @@ class ProtocolHandlerImpl void OnTMMessageSendFailed(const transport_manager::DataSendError& error, const RawMessagePtr message) OVERRIDE; + void OnConnectionPending( + const transport_manager::DeviceInfo& device_info, + const transport_manager::ConnectionUID connection_id) OVERRIDE; + void OnConnectionEstablished( const transport_manager::DeviceInfo& device_info, const transport_manager::ConnectionUID connection_id) OVERRIDE; @@ -773,6 +780,10 @@ class ProtocolHandlerImpl sync_primitives::Lock start_session_frame_map_lock_; StartSessionFrameMap start_session_frame_map_; + // Map policy app id -> auth token + sync_primitives::Lock auth_token_map_lock_; + std::map<std::string, std::string> auth_token_map_; + bool tcp_enabled_; std::string tcp_port_; std::string tcp_ip_address_; diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc index d03030b747..27b06af424 100644 --- a/src/components/protocol_handler/src/protocol_handler_impl.cc +++ b/src/components/protocol_handler/src/protocol_handler_impl.cc @@ -59,10 +59,11 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "ProtocolHandler") std::string ConvertPacketDataToString(const uint8_t* data, const size_t data_size); -const size_t kStackSize = 65536; +const size_t kStackSize = 131072; -utils::SemanticVersion defaultProtocolVersion(5, 1, 0); -utils::SemanticVersion minMultipleTransportsVersion(5, 1, 0); +utils::SemanticVersion default_protocol_version(5, 2, 0); +utils::SemanticVersion min_multiple_transports_version(5, 1, 0); +utils::SemanticVersion min_cloud_app_version(5, 2, 0); ProtocolHandlerImpl::ProtocolHandlerImpl( const ProtocolHandlerSettings& settings, @@ -309,16 +310,16 @@ void ProtocolHandlerImpl::SendStartSessionAck( ¶ms, strings::hash_id))); // Minimum protocol version supported by both - utils::SemanticVersion* minVersion = + utils::SemanticVersion* min_version = (full_version.major_version_ < PROTOCOL_VERSION_5) - ? &defaultProtocolVersion + ? &default_protocol_version : utils::SemanticVersion::min(full_version, - defaultProtocolVersion); - char protocolVersionString[256]; - strncpy(protocolVersionString, (*minVersion).toString().c_str(), 255); + default_protocol_version); + char protocol_version_string[256]; + strncpy(protocol_version_string, (*min_version).toString().c_str(), 255); const bool protocol_ver_written = bson_object_put_string( - ¶ms, strings::protocol_version, protocolVersionString); + ¶ms, strings::protocol_version, protocol_version_string); UNUSED(protocol_ver_written); LOG4CXX_DEBUG( logger_, @@ -327,12 +328,12 @@ void ProtocolHandlerImpl::SendStartSessionAck( << bson_object_get_string(¶ms, strings::protocol_version)); LOG4CXX_INFO(logger_, - "Protocol Version String " << protocolVersionString); + "Protocol Version String " << protocol_version_string); std::vector<std::string> secondaryTransports; std::vector<int32_t> audioServiceTransports; std::vector<int32_t> videoServiceTransports; - if (*minVersion >= minMultipleTransportsVersion) { + if (*min_version >= min_multiple_transports_version) { if (ParseSecondaryTransportConfiguration(connection_id, secondaryTransports, audioServiceTransports, @@ -410,10 +411,23 @@ void ProtocolHandlerImpl::SendStartSessionAck( connection_handler_.SetSecondaryTransportID(session_id, kDisabledSecondary); } + + std::string policy_app_id = + connection_handler_.GetCloudAppID(connection_id); + if (*min_version >= min_cloud_app_version && !policy_app_id.empty()) { + sync_primitives::AutoLock lock(auth_token_map_lock_); + auto it = auth_token_map_.find(policy_app_id); + if (it != auth_token_map_.end()) { + char auth_token[65536]; + strncpy(auth_token, it->second.c_str(), 65535); + auth_token[sizeof(auth_token) - 1] = '\0'; + bson_object_put_string(¶ms, strings::auth_token, auth_token); + } + } } - uint8_t* payloadBytes = bson_object_to_bytes(¶ms); - ptr->set_data(payloadBytes, bson_object_size(¶ms)); - free(payloadBytes); + uint8_t* payload_bytes = bson_object_to_bytes(¶ms); + ptr->set_data(payload_bytes, bson_object_size(¶ms)); + free(payload_bytes); } else { set_hash_id(hash_id, *ptr); } @@ -1087,6 +1101,10 @@ void ProtocolHandlerImpl::OnTMMessageSendFailed( << "Error_text: " << error.text()); } +void ProtocolHandlerImpl::OnConnectionPending( + const transport_manager::DeviceInfo& device_info, + const transport_manager::ConnectionUID connection_id) {} + void ProtocolHandlerImpl::OnConnectionEstablished( const transport_manager::DeviceInfo& device_info, const transport_manager::ConnectionUID connection_id) { @@ -1181,6 +1199,17 @@ void ProtocolHandlerImpl::OnTransportConfigUpdated( } } +void ProtocolHandlerImpl::OnAuthTokenUpdated(const std::string& policy_app_id, + const std::string& auth_token) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(auth_token_map_lock_); + if (auth_token.empty()) { + auth_token_map_.erase(policy_app_id); + } else { + auth_token_map_[policy_app_id] = auth_token; + } +} + RESULT_CODE ProtocolHandlerImpl::SendFrame(const ProtocolFramePtr packet) { LOG4CXX_AUTO_TRACE(logger_); if (!packet) { diff --git a/src/components/rpc_base/include/rpc_base/rpc_base_json_inl.h b/src/components/rpc_base/include/rpc_base/rpc_base_json_inl.h index 6c8bb359af..960ca10e21 100644 --- a/src/components/rpc_base/include/rpc_base/rpc_base_json_inl.h +++ b/src/components/rpc_base/include/rpc_base/rpc_base_json_inl.h @@ -206,6 +206,7 @@ String<minlen, maxlen>::String(const Json::Value* value, if (!is_initialized()) { value_state_ = kValid; } else if (is_valid()) { + value_ = value->asString(); value_state_ = length_range_.Includes(value_.length()) ? kValid : kInvalid; } } diff --git a/src/components/smart_objects/include/smart_objects/enum_schema_item.h b/src/components/smart_objects/include/smart_objects/enum_schema_item.h index cbba5bd7cd..942b491927 100644 --- a/src/components/smart_objects/include/smart_objects/enum_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/enum_schema_item.h @@ -220,11 +220,10 @@ class EnumConversionHelper { static bool EnumToString(const EnumType value, std::string* str) { const char* cstr; - if (EnumToCString(value, &cstr)) { - return false; - } - if (str) { + bool success = EnumToCString(value, &cstr); + if (success && str) { *str = cstr; + return true; } return false; } diff --git a/src/components/transport_manager/CMakeLists.txt b/src/components/transport_manager/CMakeLists.txt index 2f734b3a05..286e62b795 100644 --- a/src/components/transport_manager/CMakeLists.txt +++ b/src/components/transport_manager/CMakeLists.txt @@ -72,6 +72,11 @@ else() ) endif() +if(BUILD_CLOUD_APP_SUPPORT) + GET_PROPERTY(BOOST_LIBS_DIRECTORY GLOBAL PROPERTY GLOBAL_BOOST_LIBS) + list(APPEND LIBRARIES boost_system boost_regex -L${BOOST_LIBS_DIRECTORY}) +endif() + if(BUILD_USB_SUPPORT) if (CMAKE_SYSTEM_NAME STREQUAL "Linux") set(EXCLUDE_PATHS @@ -129,3 +134,4 @@ endif() if(BUILD_TESTS) add_subdirectory(test) endif() + diff --git a/src/components/transport_manager/include/transport_manager/cloud/cloud_device.h b/src/components/transport_manager/include/transport_manager/cloud/cloud_device.h new file mode 100644 index 0000000000..47a82e7921 --- /dev/null +++ b/src/components/transport_manager/include/transport_manager/cloud/cloud_device.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, Livio + * 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. + */ + +/** + * \file Cloud_device.h + * \brief CloudDevice class header file. + */ + +#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_DEVICE_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_DEVICE_H_ + +#include "transport_manager/transport_adapter/device.h" + +namespace transport_manager { +namespace transport_adapter { + +class CloudDevice : public Device { + public: + CloudDevice(std::string& host, std::string& port, std::string& name); + + virtual const std::string& GetHost() const; + + virtual const std::string& GetPort() const; + + protected: + virtual bool IsSameAs(const Device* other_device) const; + + virtual ApplicationList GetApplicationList() const; + + private: + const std::string host_; + const std::string port_; +}; + +} // namespace transport_adapter +} // namespace transport_manager + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_DEVICE_H_ diff --git a/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_connection_factory.h b/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_connection_factory.h new file mode 100644 index 0000000000..ef1754a6e7 --- /dev/null +++ b/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_connection_factory.h @@ -0,0 +1,98 @@ +/* + * \file cloud_websocket_connection_factory.h + * \brief CloudWebsocketConnectionFactory class header file. + * + * Copyright (c) 2018, Livio + * 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_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_WEBSOCKET_CONNECTION_FACTORY_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_WEBSOCKET_CONNECTION_FACTORY_H_ + +#include "transport_manager/transport_adapter/server_connection_factory.h" + +namespace transport_manager { +namespace transport_adapter { + +class TransportAdapterController; + +/** + * @brief Create connections. + */ +class CloudWebsocketConnectionFactory : public ServerConnectionFactory { + public: + /** + * @brief Constructor. + * + * @param controller Pointer to the device adapter controller. + */ + CloudWebsocketConnectionFactory(TransportAdapterController* controller); + + protected: + /** + * @brief Start cloud websocket connection factory. + */ + virtual TransportAdapter::Error Init(); + + /** + * @brief Create cloud boost websocket connection. + * + * @param device_uid Device unique identifier. + * @param ap_handle Handle of application. + */ + virtual TransportAdapter::Error CreateConnection( + const DeviceUID& device_uid, const ApplicationHandle& app_handle); + + /** + * @brief + */ + virtual void Terminate(); + + /** + * @brief Check for initialization. + * + * @return true - initialized. + * false - not initialized. + */ + virtual bool IsInitialised() const; + + /** + * @brief Destructor. + */ + virtual ~CloudWebsocketConnectionFactory(); + + private: + TransportAdapterController* controller_; +}; + +} // namespace transport_adapter +} // namespace transport_manager + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_WEBSOCKET_CONNECTION_FACTORY_H_ diff --git a/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_transport_adapter.h b/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_transport_adapter.h new file mode 100644 index 0000000000..138f9ca895 --- /dev/null +++ b/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_transport_adapter.h @@ -0,0 +1,107 @@ +/* + * \file cloud_websocket_transport_adapter.h + * \brief Cloud Websocket Transport Adapterclass header file. + * + * Copyright (c) 2018, Livio + * 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_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_WEBSOCKET_TRANSPORT_ADAPTER_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_WEBSOCKET_TRANSPORT_ADAPTER_H_ + +#include "transport_manager/transport_adapter/transport_adapter_impl.h" + +namespace transport_manager { +namespace transport_adapter { + +/** + * @brief Cloud transport adapter that uses websockets. + */ +class CloudWebsocketTransportAdapter : public TransportAdapterImpl { + public: + /** + * @brief Constructor. + */ + explicit CloudWebsocketTransportAdapter( + resumption::LastState& last_state, + const TransportManagerSettings& settings); + + /** + * @brief Destructor. + */ + virtual ~CloudWebsocketTransportAdapter(); + + /** + * @brief Set CloudTransportConfig for specified app_id + * + * @param app_id app ID string + * @param properties New cloud app properties for the app + */ + void SetAppCloudTransportConfig(std::string app_id, + CloudAppProperties properties); + + /** + * @brief Get CloudTransportConfig for specified app_id + * + * @param app_id app ID string + * @return CloudAppProperties for the app + */ + const CloudAppProperties& GetAppCloudTransportConfig(std::string app_id); + + protected: + /** + * @brief Return type of device. + * + * @return String with device type. + */ + virtual DeviceType GetDeviceType() const; + + /** + * @brief Store adapter state in last state singleton + */ + virtual void Store() const; + + /** + * @brief Restore adapter state from last state singleton + * + * @return True on success false otherwise + */ + virtual bool Restore(); + + void CreateDevice(const std::string& uid) OVERRIDE; + + private: + CloudAppTransportConfig transport_config_; +}; + +} // namespace transport_adapter +} // namespace transport_manager + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TCP_TCP_TRANSPORT_ADAPTER_H_ diff --git a/src/components/transport_manager/include/transport_manager/cloud/websocket_client_connection.h b/src/components/transport_manager/include/transport_manager/cloud/websocket_client_connection.h new file mode 100644 index 0000000000..aa608312a0 --- /dev/null +++ b/src/components/transport_manager/include/transport_manager/cloud/websocket_client_connection.h @@ -0,0 +1,194 @@ +/* + * \file websocket_client_connection.h + * \brief WebsocketClientConnection class header file. + * + * Copyright (c) 2018, Livio + * 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_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_WEBSOCKET_CLIENT_CONNECTION_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_WEBSOCKET_CLIENT_CONNECTION_H_ + +#include <boost/beast/core.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/beast/websocket/ssl.hpp> +#include <boost/asio/connect.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ssl/stream.hpp> +#include <boost/asio/thread_pool.hpp> +#include <cstdlib> +#include <functional> +#include <iostream> +#include <memory> +#include <string> +#include <thread> +#include "transport_manager/transport_adapter/connection.h" +#include "transport_manager/cloud/cloud_websocket_transport_adapter.h" +#include "utils/threads/thread.h" +#include "utils/threads/message_loop_thread.h" +#include "utils/message_queue.h" + +using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> +namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> +namespace websocket = + boost::beast::websocket; // from <boost/beast/websocket.hpp> +using ::utils::MessageQueue; + +typedef std::queue<protocol_handler::RawMessagePtr> AsyncQueue; +typedef protocol_handler::RawMessagePtr Message; +typedef websocket::stream<tcp::socket> WS; +typedef websocket::stream<ssl::stream<tcp::socket> > WSS; + +namespace transport_manager { +namespace transport_adapter { + +class TransportAdapterController; + +/** + * @brief Class responsible for communication over bluetooth sockets. + */ +class WebsocketClientConnection + : public std::enable_shared_from_this<WebsocketClientConnection>, + public Connection { + public: + /** + * @brief Constructor. + * + * @param device_uid Device unique identifier. + * @param app_handle Handle of device. + * @param controller Pointer to the device adapter controller. + */ + WebsocketClientConnection(const DeviceUID& device_uid, + const ApplicationHandle& app_handle, + TransportAdapterController* controller); + + /** + * @brief Destructor. + */ + virtual ~WebsocketClientConnection(); + + /** + * @brief Check if we can start the connection attempt and establish + *connection status. + * + * @param error contains information of any error that occurred during + *connection attempt. + * + * @return result that states whether we successfully connected or not. + */ + TransportAdapter::Error Start(); + + /** + * @brief Send data frame. + * + * @param message Smart pointer to the raw message. + * + * @return Error Information about possible reason of sending data failure. + */ + TransportAdapter::Error SendData(::protocol_handler::RawMessagePtr message); + + /** + * @brief Disconnect the current connection. + * + * @return Error Information about possible reason of Disconnect failure. + */ + TransportAdapter::Error Disconnect(); + + /** + * @brief Attempt to add provided certificate to the ssl::context + * + * @param cert Certificate string from policy table + */ + void AddCertificateAuthority(std::string cert, boost::system::error_code& ec); + + void Shutdown(); + + void Recv(boost::system::error_code ec); + + void OnRead(boost::system::error_code ec, std::size_t bytes_transferred); + + private: + TransportAdapterController* controller_; + boost::asio::io_context ioc_; + ssl::context ctx_; + tcp::resolver resolver_; + boost::beast::flat_buffer buffer_; + std::string host_; + std::string text_; + WS ws_; + WSS wss_; + + std::atomic_bool shutdown_; + + CloudAppProperties cloud_properties; + typedef std::queue<protocol_handler::RawMessagePtr> FrameQueue; + FrameQueue frames_to_send_; + mutable sync_primitives::Lock frames_to_send_mutex_; + + MessageQueue<Message, AsyncQueue> message_queue_; + + class LoopThreadDelegate : public threads::ThreadDelegate { + public: + LoopThreadDelegate(MessageQueue<Message, AsyncQueue>* message_queue, + WebsocketClientConnection* handler); + + virtual void threadMain() OVERRIDE; + virtual void exitThreadMain() OVERRIDE; + + void OnWrite(); + + void SetShutdown(); + + private: + void DrainQueue(); + MessageQueue<Message, AsyncQueue>& message_queue_; + WebsocketClientConnection& handler_; + sync_primitives::Lock queue_lock_; + sync_primitives::ConditionalVariable queue_new_items_; + std::atomic_bool write_pending_; + std::atomic_bool shutdown_; + + sync_primitives::Lock write_lock_; + }; + + LoopThreadDelegate* thread_delegate_; + threads::Thread* write_thread_; + std::thread io_service_thread_; + + const DeviceUID device_uid_; + const ApplicationHandle app_handle_; + + boost::asio::thread_pool io_pool_; +}; + +} // namespace transport_adapter +} // namespace transport_manager + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_BLUETOOTH_BLUETOOTH_SOCKET_CONNECTION_H_ diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h index 69d76b4b2b..7a0a37758c 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h @@ -88,6 +88,10 @@ class TransportAdapterController { */ virtual DeviceSptr FindDevice(const DeviceUID& device_handle) const = 0; + virtual ConnectionSPtr FindPendingConnection( + const DeviceUID& device_handle, + const ApplicationHandle& app_handle) const = 0; + /** * @brief Create connection and fill its parameters. * @@ -100,6 +104,16 @@ class TransportAdapterController { const ApplicationHandle& app_handle) = 0; /** + * @brief Set state of specified connection - PENDING and launch + *OnConnectPending event in device adapter listener. + * + * @param devcie_handle Device unique identifier. + * @param app_handle Handle of application. + */ + virtual void ConnectPending(const DeviceUID& device_handle, + const ApplicationHandle& app_handle) = 0; + + /** * @brief Make state of specified connection - ESTABLISHED and launch *OnConnectDone event in device adapter listener. * diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h index 078f93b32f..b30f1e35b2 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h @@ -41,6 +41,7 @@ #include "utils/lock.h" #include "utils/rwlock.h" +#include "utils/timer.h" #include "transport_manager/transport_adapter/transport_adapter.h" #include "transport_manager/transport_adapter/transport_adapter_controller.h" @@ -61,6 +62,8 @@ class DeviceScanner; class ServerConnectionFactory; class ClientConnectionListener; +typedef std::shared_ptr<timer::Timer> TimerSPtr; + /* * @brief Implementation of device adapter class. **/ @@ -147,6 +150,22 @@ class TransportAdapterImpl : public TransportAdapter, const DeviceUID& device_handle) OVERRIDE; /** + * @brief Retrieves the connection status of a given device + * + * @param device_handle Handle of device to query + * + * @return The connection status of the given device + */ + ConnectionStatus GetConnectionStatus( + const DeviceUID& device_handle) const OVERRIDE; + + /** + * @brief Notifies the application manager that a cloud connection status has + * updated and should trigger an UpdateAppList RPC to the HMI + */ + void ConnectionStatusUpdated(DeviceSptr device, ConnectionStatus status); + + /** * @brief Disconnect from specified session. * * @param devcie_handle Device unique identifier. @@ -245,6 +264,10 @@ class TransportAdapterImpl : public TransportAdapter, */ DeviceSptr FindDevice(const DeviceUID& device_handle) const OVERRIDE; + ConnectionSPtr FindPendingConnection( + const DeviceUID& device_handle, + const ApplicationHandle& app_handle) const OVERRIDE; + /** * @brief Search for device in container of devices, if it is not there - adds *it. @@ -306,6 +329,16 @@ class TransportAdapterImpl : public TransportAdapter, const CommunicationError& error) OVERRIDE; /** + * @brief Set state of specified connection - PENDING and launch + *OnConnectPending event in device adapter listener. + * + * @param devcie_handle Device unique identifier. + * @param app_handle Handle of application. + */ + void ConnectPending(const DeviceUID& device_handle, + const ApplicationHandle& app_handle) OVERRIDE; + + /** * @brief Set state of specified connection - ESTABLISHED and launch *OnConnectDone event in device adapter listener. * @@ -434,6 +467,10 @@ class TransportAdapterImpl : public TransportAdapter, return TransportConfig(); } + void CreateDevice(const std::string& uid) OVERRIDE { + return; + } + /** * @brief Return name of device. * @@ -533,6 +570,23 @@ class TransportAdapterImpl : public TransportAdapter, TransportAdapter::Error ConnectDevice(DeviceSptr device); /** + * @brief Reattempt the last failed connection to a device + */ + void RetryConnection(); + + /** + * @brief Clear any retry timers which have been completed + */ + void ClearCompletedTimers(); + + /** + * @brief Retrieve the next device available for a reattempted connection + * @return The handle first device with an expired retry timer if present, + * otherwise an empty string + */ + DeviceUID GetNextRetryDevice(); + + /** * @brief Remove specified device * @param device_handle Device unique identifier. */ @@ -564,7 +618,7 @@ class TransportAdapterImpl : public TransportAdapter, ConnectionSPtr connection; DeviceUID device_id; ApplicationHandle app_handle; - enum { NEW, ESTABLISHED, FINALISING } state; + enum { NEW, ESTABLISHED, FINALISING, PENDING } state; }; /** @@ -594,6 +648,18 @@ class TransportAdapterImpl : public TransportAdapter, ConnectionMap connections_; /** + * @brief Queue of retry timers. + */ + std::queue<std::pair<TimerSPtr, DeviceUID> > retry_timer_pool_; + sync_primitives::Lock retry_timer_pool_lock_; + + /** + * @brief Queue of completed retry timers. + */ + std::queue<std::pair<TimerSPtr, DeviceUID> > completed_timer_pool_; + sync_primitives::Lock completed_timer_pool_lock_; + + /** * @brief Mutex restricting access to connections map. **/ mutable sync_primitives::RWLock connections_lock_; diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener.h index 4606bac2d4..a0e0a51c1e 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener.h @@ -92,6 +92,25 @@ class TransportAdapterListener { const TransportAdapter* adapter) = 0; /** + * @brief Reaction to connection status update + * @param adapter Current transport adapter + */ + virtual void OnConnectionStatusUpdated(const TransportAdapter* adapter) = 0; + + /** + * @brief Search specified device adapter in the container of shared pointers + * to device adapters to be sure it is available, + * launch event ON_CONNECT_PENDING in transport manager. + * + * @param device_adater Pointer to the device adapter. + * @param device_handle Device unique identifier. + * @param app_id Handle of application. + */ + virtual void OnConnectPending(const TransportAdapter* adapter, + const DeviceUID& device_handle, + const ApplicationHandle& app_id) = 0; + + /** * @brief Search specified device adapter in the container of shared pointers *to device adapters to be sure it is available, * launch event ON_CONNECT_DONE in transport manager. diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener_impl.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener_impl.h index a744400279..0c9c6ef6a2 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener_impl.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener_impl.h @@ -88,6 +88,24 @@ class TransportAdapterListenerImpl virtual void OnFindNewApplicationsRequest(const TransportAdapter* adapter); /** + * @brief Passes notification to that the cloud conection status has updated + */ + virtual void OnConnectionStatusUpdated(const TransportAdapter* adapter); + + /** + * @brief Search specified device adapter in the container of shared pointers + * to device adapters to be sure it is available, + * launch event ON_CONNECT_PENDING in transport manager. + * + * @param device_adater Pointer to the device adapter. + * @param device_handle Device unique identifier. + * @param app_id Handle of application. + */ + virtual void OnConnectPending(const TransportAdapter* adapter, + const DeviceUID& device_handle, + const ApplicationHandle& app_id); + + /** * @brief Search specified device adapter in the container of shared pointers *to device adapters to be sure it is available, * launch event ON_CONNECT_DONE in transport manager. diff --git a/src/components/transport_manager/include/transport_manager/transport_manager_impl.h b/src/components/transport_manager/include/transport_manager/transport_manager_impl.h index c1df49f91b..118439bd4a 100644 --- a/src/components/transport_manager/include/transport_manager/transport_manager_impl.h +++ b/src/components/transport_manager/include/transport_manager/transport_manager_impl.h @@ -43,7 +43,6 @@ #include <functional> #include "utils/timer.h" -#include "utils/timer_task_impl.h" #include "utils/rwlock.h" #include "transport_manager/transport_manager.h" @@ -140,6 +139,12 @@ class TransportManagerImpl **/ int SearchDevices() OVERRIDE; + void AddCloudDevice( + const transport_manager::transport_adapter::CloudAppProperties + cloud_properties) OVERRIDE; + + void RemoveCloudDevice(const DeviceHandle device_id) OVERRIDE; + /** * @brief Connect to all applications discovered on device. * @@ -150,6 +155,16 @@ class TransportManagerImpl int ConnectDevice(const DeviceHandle device_id) OVERRIDE; /** + * @brief Retrieves the connection status of a given device + * + * @param device_handle Handle of device to query + * + * @return The connection status of the given device + */ + ConnectionStatus GetConnectionStatus( + const DeviceHandle& device_handle) const OVERRIDE; + + /** * @brief Disconnect from all applications connected on device. * * @param device_id Handle of device to Disconnect from. @@ -365,7 +380,7 @@ class TransportManagerImpl * @brief Converter variable (Device ID -> Device Handle; Device Handle -> * Device ID) */ - Handle2GUIDConverter converter_; + mutable Handle2GUIDConverter converter_; #ifdef BUILD_TESTS public: @@ -380,7 +395,7 @@ class TransportManagerImpl int connection_id_counter_; sync_primitives::RWLock connections_lock_; std::vector<ConnectionInternal> connections_; - sync_primitives::RWLock device_to_adapter_map_lock_; + mutable sync_primitives::RWLock device_to_adapter_map_lock_; typedef std::map<DeviceUID, TransportAdapter*> DeviceToAdapterMap; DeviceToAdapterMap device_to_adapter_map_; std::vector<TransportAdapter*> transport_adapters_; diff --git a/src/components/transport_manager/src/cloud/cloud_device.cc b/src/components/transport_manager/src/cloud/cloud_device.cc new file mode 100644 index 0000000000..184fcc10cc --- /dev/null +++ b/src/components/transport_manager/src/cloud/cloud_device.cc @@ -0,0 +1,75 @@ +/* + * + * Copyright (c) 2018, Livio + * 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 "transport_manager/cloud/cloud_device.h" + +#include "utils/logger.h" + +namespace transport_manager { +namespace transport_adapter { +CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager") + +CloudDevice::CloudDevice(std::string& host, + std::string& port, + std::string& name) + : Device(name, std::string(name)), host_(host), port_(port) {} + +bool CloudDevice::IsSameAs(const Device* other) const { + LOG4CXX_TRACE(logger_, "enter. device: " << other); + + const CloudDevice* other_cloud_device = + dynamic_cast<const CloudDevice*>(other); + + if (host_ != other_cloud_device->GetHost()) { + return false; + } + if (port_ != other_cloud_device->GetPort()) { + return false; + } + return true; +} + +ApplicationList CloudDevice::GetApplicationList() const { + return ApplicationList{0}; +} + +const std::string& CloudDevice::GetHost() const { + return host_; +} + +const std::string& CloudDevice::GetPort() const { + return port_; +} + +} // namespace transport_adapter +} // namespace transport_manager diff --git a/src/components/transport_manager/src/cloud/cloud_websocket_connection_factory.cc b/src/components/transport_manager/src/cloud/cloud_websocket_connection_factory.cc new file mode 100644 index 0000000000..0d9fda6fe5 --- /dev/null +++ b/src/components/transport_manager/src/cloud/cloud_websocket_connection_factory.cc @@ -0,0 +1,85 @@ +/* + * \file cloud_websocket_connection_factory.cc + * \brief CloudWebsocketConnectionFactory class source file. + * + * Copyright (c) 2018, Livio + * 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 "transport_manager/transport_adapter/transport_adapter_controller.h" +#include "transport_manager/cloud/cloud_websocket_connection_factory.h" +#include "transport_manager/cloud/websocket_client_connection.h" +#include "utils/logger.h" + +#include "transport_manager/cloud/cloud_device.h" + +namespace transport_manager { +namespace transport_adapter { + +CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager") + +CloudWebsocketConnectionFactory::CloudWebsocketConnectionFactory( + TransportAdapterController* controller) + : controller_(controller) {} + +TransportAdapter::Error CloudWebsocketConnectionFactory::Init() { + return TransportAdapter::OK; +} + +TransportAdapter::Error CloudWebsocketConnectionFactory::CreateConnection( + const DeviceUID& device_uid, const ApplicationHandle& app_handle) { + LOG4CXX_AUTO_TRACE(logger_); + auto connection = controller_->FindPendingConnection(device_uid, app_handle); + + std::shared_ptr<WebsocketClientConnection> ws_connection = + std::dynamic_pointer_cast<WebsocketClientConnection>(connection); + if (ws_connection.use_count() == 0) { + return TransportAdapter::Error::BAD_PARAM; + } + + TransportAdapter::Error error = ws_connection->Start(); + if (TransportAdapter::OK != error) { + LOG4CXX_ERROR( + logger_, + "Cloud Websocket connection::Start() failed with error: " << error); + } + return error; +} + +void CloudWebsocketConnectionFactory::Terminate() {} + +bool CloudWebsocketConnectionFactory::IsInitialised() const { + return true; +} + +CloudWebsocketConnectionFactory::~CloudWebsocketConnectionFactory() {} + +} // namespace transport_adapter +} // namespace transport_manager diff --git a/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc b/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc new file mode 100644 index 0000000000..dd575979b2 --- /dev/null +++ b/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2018, Livio + * 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 "transport_manager/cloud/cloud_websocket_transport_adapter.h" +#include "transport_manager/cloud/cloud_websocket_connection_factory.h" + +#include "transport_manager/cloud/cloud_device.h" +#include "transport_manager/cloud/websocket_client_connection.h" + +#include <boost/regex.hpp> + +namespace transport_manager { +namespace transport_adapter { + +CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager") + +CloudWebsocketTransportAdapter::CloudWebsocketTransportAdapter( + resumption::LastState& last_state, const TransportManagerSettings& settings) + : TransportAdapterImpl(NULL, + new CloudWebsocketConnectionFactory(this), + NULL, + last_state, + settings) {} + +CloudWebsocketTransportAdapter::~CloudWebsocketTransportAdapter() {} + +void CloudWebsocketTransportAdapter::SetAppCloudTransportConfig( + std::string app_id, CloudAppProperties properties) { + transport_config_[app_id] = properties; +} + +const CloudAppProperties& +CloudWebsocketTransportAdapter::GetAppCloudTransportConfig(std::string app_id) { + return transport_config_[app_id]; +} + +DeviceType CloudWebsocketTransportAdapter::GetDeviceType() const { + return CLOUD_WEBSOCKET; +} + +void CloudWebsocketTransportAdapter::Store() const {} + +bool CloudWebsocketTransportAdapter::Restore() { + return true; +} + +void CloudWebsocketTransportAdapter::CreateDevice(const std::string& uid) { + // If the device has already been created, just ignore the request + DeviceSptr device = FindDevice(uid); + if (device.use_count() != 0) { + return; + } + + boost::regex pattern( + "(wss?):\\/\\/([A-Z\\d\\.-]{2,})\\.?([A-Z]{2,})?(:\\d{2,4})\\/", + boost::regex::icase); + std::string str = uid; + if (!boost::regex_match(str, pattern)) { + LOG4CXX_DEBUG(logger_, "Invalid Endpoint: " << uid); + return; + } + + LOG4CXX_DEBUG(logger_, "Valid Endpoint: " << uid); + + // Port after second colon in valid endpoint string + std::size_t pos_port = uid.find(":"); + pos_port = uid.find(":", pos_port + 1); + + // Extract host and port from endpoint string + boost::regex group_pattern( + "(wss?:\\/\\/)([A-Z\\d\\.-]{2,}\\.?([A-Z]{2,})?)(:)(\\d{2,5})(\\/" + "[A-Z\\d\\.-]+)*\\/?"); + boost::smatch results; + + std::string host = ""; + std::string port = ""; + if (boost::regex_search(str, results, group_pattern)) { + host = results[2]; + port = results[5]; + + LOG4CXX_DEBUG(logger_, + "Results: " << results[0] << " " << results[1] << " " + << results[2] << " " << results[3] << " " + << results[4] << " " << results[5] << " "); + } else { + LOG4CXX_DEBUG(logger_, "Invalid Pattern: " << uid); + return; + } + + std::string device_id = uid; + + LOG4CXX_DEBUG(logger_, + "Creating Cloud Device For Host: " << host + << " and Port: " << port); + + auto cloud_device = std::make_shared<CloudDevice>(host, port, device_id); + + DeviceVector devices{cloud_device}; + + SearchDeviceDone(devices); + + // Create connection object, do not start until app is activated + std::shared_ptr<WebsocketClientConnection> connection = + std::make_shared<WebsocketClientConnection>(uid, 0, this); + + ConnectionCreated(connection, uid, 0); + ConnectPending(uid, 0); + + return; +} +} +} diff --git a/src/components/transport_manager/src/cloud/websocket_client_connection.cc b/src/components/transport_manager/src/cloud/websocket_client_connection.cc new file mode 100644 index 0000000000..5c9553a970 --- /dev/null +++ b/src/components/transport_manager/src/cloud/websocket_client_connection.cc @@ -0,0 +1,329 @@ +/* + * + * Copyright (c) 2018, Livio + * 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 "transport_manager/cloud/websocket_client_connection.h" +#include "transport_manager/cloud/cloud_device.h" + +#include "transport_manager/transport_adapter/transport_adapter_controller.h" + +#include "utils/logger.h" + +namespace transport_manager { +namespace transport_adapter { +CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager") + +WebsocketClientConnection::WebsocketClientConnection( + const DeviceUID& device_uid, + const ApplicationHandle& app_handle, + TransportAdapterController* controller) + : controller_(controller) + , ctx_(ssl::context::sslv23_client) + , resolver_(ioc_) + , ws_(ioc_) + , wss_(ioc_, ctx_) + , shutdown_(false) + , thread_delegate_(new LoopThreadDelegate(&message_queue_, this)) + , write_thread_(threads::CreateThread("WS Async Send", thread_delegate_)) + , device_uid_(device_uid) + , app_handle_(app_handle) + , io_pool_(1) {} + +WebsocketClientConnection::~WebsocketClientConnection() { + ioc_.stop(); + io_pool_.join(); +} + +void WebsocketClientConnection::AddCertificateAuthority( + const std::string cert, boost::system::error_code& ec) { + ctx_.add_certificate_authority(boost::asio::buffer(cert.data(), cert.size()), + ec); + if (ec) { + return; + } + + wss_.next_layer().set_verify_mode(ssl::verify_peer); +} + +TransportAdapter::Error WebsocketClientConnection::Start() { + LOG4CXX_AUTO_TRACE(logger_); + DeviceSptr device = controller_->FindDevice(device_uid_); + CloudDevice* cloud_device = static_cast<CloudDevice*>(device.get()); + CloudWebsocketTransportAdapter* cloud_ta = + static_cast<CloudWebsocketTransportAdapter*>(controller_); + cloud_properties = cloud_ta->GetAppCloudTransportConfig(device_uid_); + auto const host = cloud_device->GetHost(); + auto const port = cloud_device->GetPort(); + boost::system::error_code ec; + + LOG4CXX_DEBUG(logger_, "Cloud app endpoint: " << cloud_properties.endpoint); + LOG4CXX_DEBUG(logger_, + "Cloud app certificate: " << cloud_properties.certificate); + LOG4CXX_DEBUG( + logger_, + "Cloud app authentication token: " << cloud_properties.auth_token); + LOG4CXX_DEBUG( + logger_, + "Cloud app transport type: " << cloud_properties.cloud_transport_type); + LOG4CXX_DEBUG(logger_, + "Cloud app hybrid app preference: " + << cloud_properties.hybrid_app_preference); + + auto const results = resolver_.resolve(host, port, ec); + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, "Could not resolve host/port: " << str_err); + return TransportAdapter::FAIL; + } + + // Make Connection to host IP Address over TCP + if (cloud_properties.cloud_transport_type == "WSS") { + boost::asio::connect( + wss_.next_layer().next_layer(), results.begin(), results.end(), ec); + } else { + boost::asio::connect(ws_.next_layer(), results.begin(), results.end(), ec); + } + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, + "Could not connect to websocket: " << host << ":" << port); + LOG4CXX_ERROR(logger_, str_err); + return TransportAdapter::FAIL; + } + + if (cloud_properties.cloud_transport_type == "WSS") { + AddCertificateAuthority(cloud_properties.certificate, ec); + + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, + "Failed to add certificate authority: " + << cloud_properties.certificate); + LOG4CXX_ERROR(logger_, str_err); + Shutdown(); + return TransportAdapter::FAIL; + } + + // Perform SSL Handshake + wss_.next_layer().handshake(ssl::stream_base::client, ec); + + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, + "Could not complete SSL Handshake failed with host/port: " + << host << ":" << port); + LOG4CXX_ERROR(logger_, str_err); + Shutdown(); + return TransportAdapter::FAIL; + } + } + + // Perform websocket handshake + if (cloud_properties.cloud_transport_type == "WSS") { + wss_.handshake(host, "/", ec); + } else { + ws_.handshake(host, "/", ec); + } + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, + "Could not complete handshake with host/port: " << host << ":" + << port); + LOG4CXX_ERROR(logger_, str_err); + return TransportAdapter::FAIL; + } + + // Set the binary message write option + if (cloud_properties.cloud_transport_type == "WSS") { + wss_.binary(true); + } else { + ws_.binary(true); + } + write_thread_->start(threads::ThreadOptions()); + controller_->ConnectDone(device_uid_, app_handle_); + + // Start async read + if (cloud_properties.cloud_transport_type == "WSS") { + wss_.async_read(buffer_, + std::bind(&WebsocketClientConnection::OnRead, + this, + std::placeholders::_1, + std::placeholders::_2)); + } else { + ws_.async_read(buffer_, + std::bind(&WebsocketClientConnection::OnRead, + this, + std::placeholders::_1, + std::placeholders::_2)); + } + + boost::asio::post(io_pool_, [&]() { ioc_.run(); }); + + LOG4CXX_DEBUG(logger_, + "Successfully started websocket connection @: " << host << ":" + << port); + return TransportAdapter::OK; +} + +void WebsocketClientConnection::Recv(boost::system::error_code ec) { + if (shutdown_) { + return; + } + + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, str_err); + Shutdown(); + return; + } + if (cloud_properties.cloud_transport_type == "WSS") { + wss_.async_read(buffer_, + std::bind(&WebsocketClientConnection::OnRead, + this, + std::placeholders::_1, + std::placeholders::_2)); + } else { + ws_.async_read(buffer_, + std::bind(&WebsocketClientConnection::OnRead, + this, + std::placeholders::_1, + std::placeholders::_2)); + } +} + +void WebsocketClientConnection::OnRead(boost::system::error_code ec, + std::size_t bytes_transferred) { + boost::ignore_unused(bytes_transferred); + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, str_err); + ws_.lowest_layer().close(); + ioc_.stop(); + Shutdown(); + return; + } + std::string data_str = boost::beast::buffers_to_string(buffer_.data()); + + ssize_t size = (ssize_t)buffer_.size(); + const uint8_t* data = boost::asio::buffer_cast<const uint8_t*>( + boost::beast::buffers_front(buffer_.data())); + + ::protocol_handler::RawMessagePtr frame( + new protocol_handler::RawMessage(0, 0, data, size)); + + controller_->DataReceiveDone(device_uid_, app_handle_, frame); + + buffer_.consume(buffer_.size()); + Recv(ec); +} + +TransportAdapter::Error WebsocketClientConnection::SendData( + ::protocol_handler::RawMessagePtr message) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(frames_to_send_mutex_); + message_queue_.push(message); + return TransportAdapter::OK; +} + +TransportAdapter::Error WebsocketClientConnection::Disconnect() { + LOG4CXX_AUTO_TRACE(logger_); + Shutdown(); + return TransportAdapter::OK; +} + +void WebsocketClientConnection::Shutdown() { + shutdown_ = true; + + if (thread_delegate_) { + thread_delegate_->SetShutdown(); + write_thread_->join(); + delete thread_delegate_; + } + if (buffer_.size()) { + buffer_.consume(buffer_.size()); + } + controller_->DisconnectDone(device_uid_, app_handle_); +} + +WebsocketClientConnection::LoopThreadDelegate::LoopThreadDelegate( + MessageQueue<Message, AsyncQueue>* message_queue, + WebsocketClientConnection* handler) + : message_queue_(*message_queue), handler_(*handler), shutdown_(false) {} + +void WebsocketClientConnection::LoopThreadDelegate::threadMain() { + while (!message_queue_.IsShuttingDown() && !shutdown_) { + DrainQueue(); + message_queue_.wait(); + } + DrainQueue(); +} + +void WebsocketClientConnection::LoopThreadDelegate::exitThreadMain() { + shutdown_ = true; + if (!message_queue_.IsShuttingDown()) { + message_queue_.Shutdown(); + } +} + +void WebsocketClientConnection::LoopThreadDelegate::DrainQueue() { + while (!message_queue_.empty()) { + Message message_ptr; + message_queue_.pop(message_ptr); + if (!shutdown_) { + boost::system::error_code ec; + if (handler_.cloud_properties.cloud_transport_type == "WSS") { + handler_.wss_.write( + boost::asio::buffer(message_ptr->data(), message_ptr->data_size())); + } else { + handler_.ws_.write( + boost::asio::buffer(message_ptr->data(), message_ptr->data_size())); + } + if (ec) { + LOG4CXX_ERROR(logger_, "Error writing to websocket"); + handler_.controller_->DataSendFailed(handler_.device_uid_, + handler_.app_handle_, + message_ptr, + DataSendError()); + } + } + } +} + +void WebsocketClientConnection::LoopThreadDelegate::SetShutdown() { + shutdown_ = true; + if (!message_queue_.IsShuttingDown()) { + message_queue_.Shutdown(); + } +} + +} // namespace transport_adapter +} // namespace transport_manager diff --git a/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc b/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc index 346139cbd2..865e8d6aa8 100644 --- a/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc +++ b/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc @@ -31,8 +31,9 @@ */ #include "config_profile/profile.h" -#include "utils/logger.h" #include "utils/helpers.h" +#include "utils/logger.h" +#include "utils/timer_task_impl.h" #include "transport_manager/transport_adapter/transport_adapter_impl.h" #include "transport_manager/transport_adapter/transport_adapter_listener.h" @@ -60,7 +61,9 @@ DeviceTypes devicesType = { std::make_pair(DeviceType::IOS_USB_DEVICE_MODE, std::string("USB_IOS_DEVICE_MODE")), std::make_pair(DeviceType::IOS_CARPLAY_WIRELESS, - std::string("CARPLAY_WIRELESS_IOS"))}; + std::string("CARPLAY_WIRELESS_IOS")), + std::make_pair(DeviceType::CLOUD_WEBSOCKET, + std::string("CLOUD_WEBSOCKET"))}; } TransportAdapterImpl::TransportAdapterImpl( @@ -207,17 +210,21 @@ TransportAdapter::Error TransportAdapterImpl::Connect( } connections_lock_.AcquireForWriting(); + + std::pair<DeviceUID, ApplicationHandle> connection_key = + std::make_pair(device_id, app_handle); const bool already_exists = - connections_.end() != - connections_.find(std::make_pair(device_id, app_handle)); + connections_.end() != connections_.find(connection_key); + ConnectionInfo& info = connections_[connection_key]; if (!already_exists) { - ConnectionInfo& info = connections_[std::make_pair(device_id, app_handle)]; info.app_handle = app_handle; info.device_id = device_id; info.state = ConnectionInfo::NEW; } + const bool pending_app = ConnectionInfo::PENDING == info.state; connections_lock_.Release(); - if (already_exists) { + + if (already_exists && !pending_app) { LOG4CXX_TRACE(logger_, "exit with ALREADY_EXISTS"); return ALREADY_EXISTS; } @@ -226,7 +233,9 @@ TransportAdapter::Error TransportAdapterImpl::Connect( server_connection_factory_->CreateConnection(device_id, app_handle); if (TransportAdapter::OK != err) { connections_lock_.AcquireForWriting(); - connections_.erase(std::make_pair(device_id, app_handle)); + if (!pending_app) { + connections_.erase(std::make_pair(device_id, app_handle)); + } connections_lock_.Release(); } LOG4CXX_TRACE(logger_, "exit with error: " << err); @@ -239,6 +248,33 @@ TransportAdapter::Error TransportAdapterImpl::ConnectDevice( DeviceSptr device = FindDevice(device_handle); if (device) { TransportAdapter::Error err = ConnectDevice(device); + if (FAIL == err && GetDeviceType() == DeviceType::CLOUD_WEBSOCKET) { + LOG4CXX_TRACE(logger_, + "Error occurred while connecting cloud app: " << err); + // Update retry count + if (device->retry_count() >= + get_settings().cloud_app_max_retry_attempts()) { + device->reset_retry_count(); + ConnectionStatusUpdated(device, ConnectionStatus::PENDING); + return err; + } else if (device->connection_status() == ConnectionStatus::PENDING) { + ConnectionStatusUpdated(device, ConnectionStatus::RETRY); + } + + device->next_retry(); + + // Start timer for next retry + TimerSPtr retry_timer(std::make_shared<timer::Timer>( + "RetryConnectionTimer", + new timer::TimerTaskImpl<TransportAdapterImpl>( + this, &TransportAdapterImpl::RetryConnection))); + sync_primitives::AutoLock locker(retry_timer_pool_lock_); + retry_timer_pool_.push(std::make_pair(retry_timer, device_handle)); + retry_timer->Start(get_settings().cloud_app_retry_timeout(), + timer::kSingleShot); + } else if (OK == err) { + ConnectionStatusUpdated(device, ConnectionStatus::CONNECTED); + } LOG4CXX_TRACE(logger_, "exit with error: " << err); return err; } else { @@ -247,6 +283,60 @@ TransportAdapter::Error TransportAdapterImpl::ConnectDevice( } } +void TransportAdapterImpl::RetryConnection() { + ClearCompletedTimers(); + const DeviceUID device_id = GetNextRetryDevice(); + if (device_id.empty()) { + LOG4CXX_ERROR(logger_, + "Unable to find timer, ignoring RetryConnection request"); + return; + } + ConnectDevice(device_id); +} + +void TransportAdapterImpl::ClearCompletedTimers() { + // Cleanup any retry timers which have completed execution + sync_primitives::AutoLock locker(completed_timer_pool_lock_); + while (!completed_timer_pool_.empty()) { + auto timer_entry = completed_timer_pool_.front(); + if (timer_entry.first->is_completed()) { + completed_timer_pool_.pop(); + } + } +} + +DeviceUID TransportAdapterImpl::GetNextRetryDevice() { + sync_primitives::AutoLock retry_locker(retry_timer_pool_lock_); + if (retry_timer_pool_.empty()) { + return std::string(); + } + auto timer_entry = retry_timer_pool_.front(); + retry_timer_pool_.pop(); + + // Store reference for cleanup later + sync_primitives::AutoLock completed_locker(completed_timer_pool_lock_); + completed_timer_pool_.push(timer_entry); + + return timer_entry.second; +} + +ConnectionStatus TransportAdapterImpl::GetConnectionStatus( + const DeviceUID& device_handle) const { + DeviceSptr device = FindDevice(device_handle); + return device.use_count() == 0 ? ConnectionStatus::INVALID + : device->connection_status(); +} + +void TransportAdapterImpl::ConnectionStatusUpdated(DeviceSptr device, + ConnectionStatus status) { + device->set_connection_status(status); + for (TransportAdapterListenerList::iterator it = listeners_.begin(); + it != listeners_.end(); + ++it) { + (*it)->OnConnectionStatusUpdated(this); + } +} + TransportAdapter::Error TransportAdapterImpl::Disconnect( const DeviceUID& device_id, const ApplicationHandle& app_handle) { LOG4CXX_TRACE(logger_, @@ -276,6 +366,8 @@ TransportAdapter::Error TransportAdapterImpl::DisconnectDevice( } Error error = OK; + DeviceSptr device = FindDevice(device_id); + ConnectionStatusUpdated(device, ConnectionStatus::CLOSING); std::vector<ConnectionInfo> to_disconnect; connections_lock_.AcquireForReading(); @@ -395,6 +487,7 @@ DeviceSptr TransportAdapterImpl::AddDevice(DeviceSptr device) { LOG4CXX_TRACE(logger_, "exit with TRUE. Condition: same_device_found"); return existing_device; } else { + device->set_connection_status(ConnectionStatus::PENDING); for (TransportAdapterListenerList::iterator it = listeners_.begin(); it != listeners_.end(); ++it) { @@ -728,6 +821,26 @@ void TransportAdapterImpl::DeviceSwitched(const DeviceUID& device_handle) { UNUSED(device_handle); } +ConnectionSPtr TransportAdapterImpl::FindPendingConnection( + const DeviceUID& device_id, const ApplicationHandle& app_handle) const { + LOG4CXX_TRACE(logger_, + "enter. device_id: " << &device_id + << ", app_handle: " << &app_handle); + ConnectionSPtr connection; + connections_lock_.AcquireForReading(); + ConnectionMap::const_iterator it = + connections_.find(std::make_pair(device_id, app_handle)); + if (it != connections_.end()) { + const ConnectionInfo& info = it->second; + if (info.state == ConnectionInfo::PENDING) { + connection = info.connection; + } + } + connections_lock_.Release(); + LOG4CXX_TRACE(logger_, "exit with Connection: " << connection); + return connection; +} + DeviceSptr TransportAdapterImpl::FindDevice(const DeviceUID& device_id) const { LOG4CXX_TRACE(logger_, "enter. device_id: " << &device_id); DeviceSptr ret; @@ -743,6 +856,34 @@ DeviceSptr TransportAdapterImpl::FindDevice(const DeviceUID& device_id) const { return ret; } +void TransportAdapterImpl::ConnectPending(const DeviceUID& device_id, + const ApplicationHandle& app_handle) { + LOG4CXX_AUTO_TRACE(logger_); + connections_lock_.AcquireForWriting(); + ConnectionMap::iterator it_conn = + connections_.find(std::make_pair(device_id, app_handle)); + if (it_conn != connections_.end()) { + ConnectionInfo& info = it_conn->second; + info.state = ConnectionInfo::PENDING; + } + connections_lock_.Release(); + + DeviceSptr device = FindDevice(device_id); + if (device.use_count() == 0) { + LOG4CXX_ERROR( + logger_, "Unable to find device, cannot set connection pending status"); + return; + } else { + device->set_connection_status(ConnectionStatus::PENDING); + } + + for (TransportAdapterListenerList::iterator it = listeners_.begin(); + it != listeners_.end(); + ++it) { + (*it)->OnConnectPending(this, device_id, app_handle); + } +} + void TransportAdapterImpl::ConnectDone(const DeviceUID& device_id, const ApplicationHandle& app_handle) { LOG4CXX_TRACE(logger_, @@ -1036,12 +1177,13 @@ void TransportAdapterImpl::RunAppOnDevice(const DeviceUID& device_uid, void TransportAdapterImpl::RemoveDevice(const DeviceUID& device_handle) { LOG4CXX_AUTO_TRACE(logger_); - LOG4CXX_DEBUG(logger_, "Device_handle: " << &device_handle); + LOG4CXX_DEBUG(logger_, "Remove Device_handle: " << &device_handle); sync_primitives::AutoLock locker(devices_mutex_); DeviceMap::iterator i = devices_.find(device_handle); if (i != devices_.end()) { DeviceSptr device = i->second; - if (!device->keep_on_disconnect()) { + bool is_cloud_device = (GetDeviceType() == DeviceType::CLOUD_WEBSOCKET); + if (!device->keep_on_disconnect() || is_cloud_device) { devices_.erase(i); for (TransportAdapterListenerList::iterator it = listeners_.begin(); it != listeners_.end(); diff --git a/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc b/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc index 544cdde999..4ef685adbc 100644 --- a/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc +++ b/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc @@ -116,6 +116,44 @@ void TransportAdapterListenerImpl::OnFindNewApplicationsRequest( LOG4CXX_TRACE(logger_, "exit"); } +void TransportAdapterListenerImpl::OnConnectionStatusUpdated( + const TransportAdapter* adapter) { + LOG4CXX_TRACE(logger_, "enter. adapter* " << adapter); + const TransportAdapterEvent event(EventTypeEnum::ON_CONNECTION_STATUS_UPDATED, + transport_adapter_, + "", + 0, + ::protocol_handler::RawMessagePtr(), + BaseErrorPtr(new BaseError())); + if (transport_manager_ != NULL && + transport_manager::E_SUCCESS != + transport_manager_->ReceiveEventFromDevice(event)) { + LOG4CXX_WARN(logger_, "Failed to receive event from device"); + } + LOG4CXX_TRACE(logger_, "exit"); +} + +void TransportAdapterListenerImpl::OnConnectPending( + const TransportAdapter* adapter, + const DeviceUID& device, + const ApplicationHandle& application_id) { + LOG4CXX_TRACE(logger_, + "enter adapter*: " << adapter << ", device: " << &device + << ", application_id: " << &application_id); + const TransportAdapterEvent event(EventTypeEnum::ON_CONNECT_PENDING, + transport_adapter_, + device, + application_id, + ::protocol_handler::RawMessagePtr(), + BaseErrorPtr(new BaseError())); + if (transport_manager_ != NULL && + transport_manager::E_SUCCESS != + transport_manager_->ReceiveEventFromDevice(event)) { + LOG4CXX_WARN(logger_, "Failed to receive event from device"); + } + LOG4CXX_TRACE(logger_, "exit"); +} + void TransportAdapterListenerImpl::OnConnectDone( const TransportAdapter* adapter, const DeviceUID& device, diff --git a/src/components/transport_manager/src/transport_manager_default.cc b/src/components/transport_manager/src/transport_manager_default.cc index 196ad09af4..41487b054b 100644 --- a/src/components/transport_manager/src/transport_manager_default.cc +++ b/src/components/transport_manager/src/transport_manager_default.cc @@ -44,6 +44,10 @@ #include "transport_manager/usb/usb_aoa_adapter.h" #endif // USB_SUPPORT +#if defined(CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT) +#include "transport_manager/cloud/cloud_websocket_transport_adapter.h" +#endif + #if defined(BUILD_TESTS) #include "transport_manager/iap2_emulation/iap2_transport_adapter.h" #endif // BUILD_TEST @@ -101,6 +105,19 @@ int TransportManagerDefault::Init(resumption::LastState& last_state) { ta_usb = NULL; #endif // USB_SUPPORT +#if defined CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT + transport_adapter::TransportAdapterImpl* ta_cloud = + new transport_adapter::CloudWebsocketTransportAdapter(last_state, + get_settings()); +#ifdef TELEMETRY_MONITOR + if (metric_observer_) { + ta_cloud->SetTelemetryObserver(metric_observer_); + } +#endif // TELEMETRY_MONITOR + AddTransportAdapter(ta_cloud); + ta_cloud = NULL; +#endif + #if defined BUILD_TESTS const uint16_t iap2_bt_emu_port = 23456; transport_adapter::IAP2BluetoothEmulationTransportAdapter* diff --git a/src/components/transport_manager/src/transport_manager_impl.cc b/src/components/transport_manager/src/transport_manager_impl.cc index 2b0296debb..d197882120 100644 --- a/src/components/transport_manager/src/transport_manager_impl.cc +++ b/src/components/transport_manager/src/transport_manager_impl.cc @@ -50,6 +50,7 @@ #include "transport_manager/transport_manager_listener.h" #include "transport_manager/transport_manager_listener_empty.h" #include "transport_manager/transport_adapter/transport_adapter.h" +#include "transport_manager/cloud/cloud_websocket_transport_adapter.h" #include "transport_manager/transport_adapter/transport_adapter_event.h" #include "config_profile/profile.h" @@ -129,6 +130,35 @@ void TransportManagerImpl::ReconnectionTimeout() { device_to_reconnect_); } +void TransportManagerImpl::AddCloudDevice( + const transport_manager::transport_adapter::CloudAppProperties + cloud_properties) { + transport_adapter::DeviceType type = transport_adapter::DeviceType::UNKNOWN; + if ((cloud_properties.cloud_transport_type == "WS") || + (cloud_properties.cloud_transport_type == "WSS")) { + type = transport_adapter::DeviceType::CLOUD_WEBSOCKET; + } else { + return; + } + + std::vector<TransportAdapter*>::iterator ta = transport_adapters_.begin(); + for (; ta != transport_adapters_.end(); ++ta) { + if ((*ta)->GetDeviceType() == type) { + (*ta)->CreateDevice(cloud_properties.endpoint); + transport_adapter::CloudWebsocketTransportAdapter* cta = + static_cast<transport_adapter::CloudWebsocketTransportAdapter*>(*ta); + cta->SetAppCloudTransportConfig(cloud_properties.endpoint, + cloud_properties); + } + } + + return; +} + +void TransportManagerImpl::RemoveCloudDevice(const DeviceHandle device_handle) { + DisconnectDevice(device_handle); +} + int TransportManagerImpl::ConnectDevice(const DeviceHandle device_handle) { LOG4CXX_TRACE(logger_, "enter. DeviceHandle: " << &device_handle); if (!this->is_initialized_) { @@ -157,6 +187,22 @@ int TransportManagerImpl::ConnectDevice(const DeviceHandle device_handle) { return err; } +ConnectionStatus TransportManagerImpl::GetConnectionStatus( + const DeviceHandle& device_handle) const { + DeviceUID device_id = converter_.HandleToUid(device_handle); + + sync_primitives::AutoReadLock lock(device_to_adapter_map_lock_); + DeviceToAdapterMap::const_iterator it = + device_to_adapter_map_.find(device_id); + if (it == device_to_adapter_map_.end()) { + LOG4CXX_ERROR(logger_, "No device adapter found by id " << device_handle); + LOG4CXX_TRACE(logger_, "exit with E_INVALID_HANDLE. Condition: NULL == ta"); + return ConnectionStatus::INVALID; + } + transport_adapter::TransportAdapter* ta = it->second; + return ta->GetConnectionStatus(device_id); +} + int TransportManagerImpl::DisconnectDevice(const DeviceHandle device_handle) { LOG4CXX_TRACE(logger_, "enter. DeviceHandle: " << &device_handle); if (!this->is_initialized_) { @@ -954,22 +1000,93 @@ void TransportManagerImpl::Handle(TransportAdapterEvent event) { LOG4CXX_DEBUG(logger_, "event_type = ON_FIND_NEW_APPLICATIONS_REQUEST"); break; } + case EventTypeEnum::ON_CONNECTION_STATUS_UPDATED: { + RaiseEvent(&TransportManagerListener::OnConnectionStatusUpdated); + LOG4CXX_DEBUG(logger_, "event_type = ON_CONNECTION_STATUS_UPDATED"); + break; + } + case EventTypeEnum::ON_CONNECT_PENDING: { + const DeviceHandle device_handle = converter_.UidToHandle( + event.device_uid, event.transport_adapter->GetConnectionType()); + int connection_id = 0; + std::vector<ConnectionInternal>::iterator it = connections_.begin(); + std::vector<ConnectionInternal>::iterator end = connections_.end(); + for (; it != end; ++it) { + if (it->transport_adapter != event.transport_adapter) { + continue; + } else if (it->Connection::device != event.device_uid) { + continue; + } else if (it->Connection::application != event.application_id) { + continue; + } else if (it->device_handle_ != device_handle) { + continue; + } else { + LOG4CXX_DEBUG(logger_, "Connection Object Already Exists"); + connection_id = it->Connection::id; + break; + } + } + + if (it == end) { + AddConnection(ConnectionInternal(this, + event.transport_adapter, + ++connection_id_counter_, + event.device_uid, + event.application_id, + device_handle)); + connection_id = connection_id_counter_; + } + + RaiseEvent( + &TransportManagerListener::OnConnectionPending, + DeviceInfo(device_handle, + event.device_uid, + event.transport_adapter->DeviceName(event.device_uid), + event.transport_adapter->GetConnectionType()), + connection_id); + LOG4CXX_DEBUG(logger_, "event_type = ON_CONNECT_PENDING"); + break; + } case EventTypeEnum::ON_CONNECT_DONE: { const DeviceHandle device_handle = converter_.UidToHandle( event.device_uid, event.transport_adapter->GetConnectionType()); - AddConnection(ConnectionInternal(this, - event.transport_adapter, - ++connection_id_counter_, - event.device_uid, - event.application_id, - device_handle)); + + int connection_id = 0; + std::vector<ConnectionInternal>::iterator it = connections_.begin(); + std::vector<ConnectionInternal>::iterator end = connections_.end(); + for (; it != end; ++it) { + if (it->transport_adapter != event.transport_adapter) { + continue; + } else if (it->Connection::device != event.device_uid) { + continue; + } else if (it->Connection::application != event.application_id) { + continue; + } else if (it->device_handle_ != device_handle) { + continue; + } else { + LOG4CXX_DEBUG(logger_, "Connection Object Already Exists"); + connection_id = it->Connection::id; + break; + } + } + + if (it == end) { + AddConnection(ConnectionInternal(this, + event.transport_adapter, + ++connection_id_counter_, + event.device_uid, + event.application_id, + device_handle)); + connection_id = connection_id_counter_; + } + RaiseEvent( &TransportManagerListener::OnConnectionEstablished, DeviceInfo(device_handle, event.device_uid, event.transport_adapter->DeviceName(event.device_uid), event.transport_adapter->GetConnectionType()), - connection_id_counter_); + connection_id); LOG4CXX_DEBUG(logger_, "event_type = ON_CONNECT_DONE"); break; } diff --git a/src/components/transport_manager/test/CMakeLists.txt b/src/components/transport_manager/test/CMakeLists.txt index 240784436b..5288d8c697 100644 --- a/src/components/transport_manager/test/CMakeLists.txt +++ b/src/components/transport_manager/test/CMakeLists.txt @@ -75,6 +75,11 @@ if (BUILD_BT_SUPPORT) endif() endif() +if(BUILD_CLOUD_APP_SUPPORT) + GET_PROPERTY(BOOST_LIBS_DIRECTORY GLOBAL PROPERTY GLOBAL_BOOST_LIBS) + list(APPEND LIBRARIES boost_system boost_regex crypto ssl -L${BOOST_LIBS_DIRECTORY}) +endif() + create_test("transport_manager_test" "${SOURCES}" "${LIBRARIES}") file(COPY smartDeviceLink_test.ini DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/components/transport_manager/test/include/transport_manager/mock_transport_manager_listener.h b/src/components/transport_manager/test/include/transport_manager/mock_transport_manager_listener.h index 58e143342a..4eaf34d041 100644 --- a/src/components/transport_manager/test/include/transport_manager/mock_transport_manager_listener.h +++ b/src/components/transport_manager/test/include/transport_manager/mock_transport_manager_listener.h @@ -56,6 +56,9 @@ class MockTransportManagerListener : public TransportManagerListener { MOCK_METHOD1(OnDeviceRemoved, void(const DeviceInfo& device_info)); MOCK_METHOD0(OnScanDevicesFinished, void()); MOCK_METHOD1(OnScanDevicesFailed, void(const SearchDeviceError& error)); + MOCK_METHOD2(OnConnectionPending, + void(const DeviceInfo& device_info, + const ConnectionUID connection_id)); MOCK_METHOD2(OnConnectionEstablished, void(const DeviceInfo& device_info, const ConnectionUID connection_id)); diff --git a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h index 642c193d63..1de5eac702 100644 --- a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h +++ b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h @@ -55,6 +55,9 @@ class MockTransportAdapterController : public TransportAdapterController { void(ConnectionSPtr connection, const DeviceUID& device_handle, const ApplicationHandle& app_handle)); + MOCK_CONST_METHOD2(FindPendingConnection, + ConnectionSPtr(const DeviceUID& device_handle, + const ApplicationHandle& app_handle)); MOCK_METHOD2(ConnectDone, void(const DeviceUID& device_handle, const ApplicationHandle& app_handle)); diff --git a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_impl.h b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_impl.h index 384f55605a..3a1422cee1 100644 --- a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_impl.h +++ b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_impl.h @@ -36,6 +36,8 @@ #include "gmock/gmock.h" #include "transport_manager/transport_manager_settings.h" #include "transport_manager/transport_adapter/transport_adapter_impl.h" +#include "transport_manager/transport_adapter/device.h" +#include "transport_manager/common.h" using ::transport_manager::transport_adapter::TransportAdapterImpl; using ::transport_manager::transport_adapter::DeviceScanner; @@ -70,15 +72,17 @@ class MockTransportAdapterImpl : public TransportAdapterImpl { } virtual ~MockTransportAdapterImpl() {} - virtual DeviceType GetDeviceType() const { - return DeviceType::UNKNOWN; - } - MOCK_CONST_METHOD0(Store, void()); MOCK_METHOD0(Restore, bool()); MOCK_CONST_METHOD1(FindDevice, transport_manager::transport_adapter::DeviceSptr( const DeviceUID& device_id)); + MOCK_METHOD2(ConnectionStatusUpdated, + void(transport_manager::transport_adapter::DeviceSptr device, + ::transport_manager::ConnectionStatus status)); + MOCK_CONST_METHOD0(GetDeviceType, + ::transport_manager::transport_adapter::DeviceType()); + MOCK_METHOD0(RetryConnection, void()); }; } // namespace transport_manager_test diff --git a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_listener.h b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_listener.h index dce23189c8..f7bebf69c3 100644 --- a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_listener.h +++ b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_listener.h @@ -59,6 +59,12 @@ class MockTransportAdapterListener : public TransportAdapterListener { const SearchDeviceError& error)); MOCK_METHOD1(OnFindNewApplicationsRequest, void(const TransportAdapter* adapter)); + MOCK_METHOD1(OnConnectionStatusUpdated, + void(const TransportAdapter* adapter)); + MOCK_METHOD3(OnConnectPending, + void(const TransportAdapter* adapter, + const DeviceUID& device_handle, + const ApplicationHandle& app_id)); MOCK_METHOD1(OnDeviceListUpdated, void(const TransportAdapter* transport_adapter)); MOCK_METHOD3(OnConnectDone, diff --git a/src/components/transport_manager/test/tcp_client_listener_test.cc b/src/components/transport_manager/test/tcp_client_listener_test.cc index 5205d6ae3c..1f4a17cf6c 100644 --- a/src/components/transport_manager/test/tcp_client_listener_test.cc +++ b/src/components/transport_manager/test/tcp_client_listener_test.cc @@ -69,10 +69,16 @@ class MockTransportAdapterController : public TransportAdapterController { MOCK_METHOD1(SearchDeviceDone, void(const DeviceVector& devices)); MOCK_METHOD1(SearchDeviceFailed, void(const SearchDeviceError& error)); MOCK_CONST_METHOD1(FindDevice, DeviceSptr(const DeviceUID& device_handle)); + MOCK_CONST_METHOD2(FindPendingConnection, + ConnectionSPtr(const DeviceUID& device_handle, + const ApplicationHandle& app_handle)); MOCK_METHOD3(ConnectionCreated, void(ConnectionSPtr connection, const DeviceUID& device_handle, const ApplicationHandle& app_handle)); + MOCK_METHOD2(ConnectPending, + void(const DeviceUID& device_handle, + const ApplicationHandle& app_handle)); MOCK_METHOD2(ConnectDone, void(const DeviceUID& device_handle, const ApplicationHandle& app_handle)); diff --git a/src/components/transport_manager/test/transport_adapter_test.cc b/src/components/transport_manager/test/transport_adapter_test.cc index 9e602332c6..dafabf4504 100644 --- a/src/components/transport_manager/test/transport_adapter_test.cc +++ b/src/components/transport_manager/test/transport_adapter_test.cc @@ -31,14 +31,15 @@ */ #include "gtest/gtest.h" -#include "transport_manager/transport_adapter/mock_device_scanner.h" +#include "transport_manager/mock_transport_manager_settings.h" #include "transport_manager/transport_adapter/mock_client_connection_listener.h" -#include "transport_manager/transport_adapter/mock_server_connection_factory.h" -#include "transport_manager/transport_adapter/mock_device.h" #include "transport_manager/transport_adapter/mock_connection.h" -#include "transport_manager/transport_adapter/mock_transport_adapter_listener.h" +#include "transport_manager/transport_adapter/mock_device.h" +#include "transport_manager/transport_adapter/mock_device_scanner.h" +#include "transport_manager/transport_adapter/mock_server_connection_factory.h" #include "transport_manager/transport_adapter/mock_transport_adapter_impl.h" -#include "transport_manager/mock_transport_manager_settings.h" +#include "transport_manager/transport_adapter/mock_transport_adapter_listener.h" +#include "utils/test_async_waiter.h" #include "transport_manager/transport_adapter/transport_adapter_impl.h" #include "transport_manager/transport_adapter/transport_adapter_listener.h" @@ -73,6 +74,11 @@ class TransportAdapterTest : public ::testing::Test { .WillByDefault(Return(true)); } + void SetDefaultExpectations(MockTransportAdapterImpl& adapter) { + ON_CALL(adapter, GetDeviceType()) + .WillByDefault(Return(DeviceType::UNKNOWN)); + } + NiceMock<MockTransportManagerSettings> transport_manager_settings; resumption::LastStateImpl last_state_; std::string dev_id; @@ -89,6 +95,7 @@ TEST_F(TransportAdapterTest, Init) { clientMock, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*dev_mock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(*clientMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); @@ -123,6 +130,7 @@ TEST_F(TransportAdapterTest, SearchDevices_DeviceNotInitialized) { MockDeviceScanner* dev_mock = new MockDeviceScanner(); MockTransportAdapterImpl transport_adapter( dev_mock, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*dev_mock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -138,6 +146,7 @@ TEST_F(TransportAdapterTest, SearchDevices_DeviceInitialized) { MockDeviceScanner* dev_mock = new MockDeviceScanner(); MockTransportAdapterImpl transport_adapter( dev_mock, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*dev_mock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -153,6 +162,7 @@ TEST_F(TransportAdapterTest, SearchDevices_DeviceInitialized) { TEST_F(TransportAdapterTest, SearchDeviceDone_DeviceExisting) { MockTransportAdapterImpl transport_adapter( NULL, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); transport_adapter.Init(); @@ -169,6 +179,7 @@ TEST_F(TransportAdapterTest, SearchDeviceDone_DeviceExisting) { TEST_F(TransportAdapterTest, SearchDeviceFailed) { MockTransportAdapterImpl transport_adapter( NULL, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); transport_adapter.Init(); @@ -183,6 +194,7 @@ TEST_F(TransportAdapterTest, SearchDeviceFailed) { TEST_F(TransportAdapterTest, AddDevice) { MockTransportAdapterImpl transport_adapter( NULL, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); transport_adapter.Init(); @@ -200,6 +212,7 @@ TEST_F(TransportAdapterTest, Connect_ServerNotSupported) { MockClientConnectionListener* clientMock = new MockClientConnectionListener(); MockTransportAdapterImpl transport_adapter( NULL, NULL, clientMock, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*clientMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -217,6 +230,7 @@ TEST_F(TransportAdapterTest, Connect_ServerNotInitialized) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -234,6 +248,7 @@ TEST_F(TransportAdapterTest, Connect_Success) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -252,6 +267,7 @@ TEST_F(TransportAdapterTest, Connect_DeviceAddedTwice) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -274,6 +290,7 @@ TEST_F(TransportAdapterTest, Connect_DeviceAddedTwice) { TEST_F(TransportAdapterTest, ConnectDevice_ServerNotAdded_DeviceAdded) { MockTransportAdapterImpl transport_adapter( NULL, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); transport_adapter.Init(); @@ -292,12 +309,14 @@ TEST_F(TransportAdapterTest, ConnectDevice_ServerNotAdded_DeviceAdded) { TransportAdapter::Error res = transport_adapter.ConnectDevice(uniq_id); EXPECT_EQ(TransportAdapter::FAIL, res); + EXPECT_NE(ConnectionStatus::CONNECTED, mockdev->connection_status()); } TEST_F(TransportAdapterTest, ConnectDevice_DeviceNotAdded) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); transport_adapter.Init(); @@ -318,6 +337,7 @@ TEST_F(TransportAdapterTest, ConnectDevice_DeviceAdded) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -341,14 +361,53 @@ TEST_F(TransportAdapterTest, ConnectDevice_DeviceAdded) { EXPECT_CALL(transport_adapter, FindDevice(uniq_id)).WillOnce(Return(mockdev)); TransportAdapter::Error res = transport_adapter.ConnectDevice(uniq_id); EXPECT_EQ(TransportAdapter::OK, res); + EXPECT_EQ(ConnectionStatus::CONNECTED, mockdev->connection_status()); EXPECT_CALL(*serverMock, Terminate()); } +TEST_F(TransportAdapterTest, ConnectDevice_DeviceAdded_ConnectFailedRetry) { + MockServerConnectionFactory* server_mock = new MockServerConnectionFactory(); + MockTransportAdapterImpl transport_adapter( + NULL, server_mock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); + + EXPECT_CALL(*server_mock, Init()).WillOnce(Return(TransportAdapter::OK)); + EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); + transport_adapter.Init(); + + std::shared_ptr<MockDevice> mockdev = + std::make_shared<MockDevice>(dev_id, uniq_id); + transport_adapter.AddDevice(mockdev); + + std::vector<std::string> dev_list = transport_adapter.GetDeviceList(); + ASSERT_EQ(1u, dev_list.size()); + EXPECT_EQ(uniq_id, dev_list[0]); + + int app_handle = 1; + std::vector<int> int_list = {app_handle}; + EXPECT_CALL(*mockdev, GetApplicationList()).WillOnce(Return(int_list)); + + EXPECT_CALL(*server_mock, IsInitialised()).WillOnce(Return(true)); + EXPECT_CALL(*server_mock, CreateConnection(uniq_id, app_handle)) + .WillOnce(Return(TransportAdapter::FAIL)); + EXPECT_CALL(transport_adapter, FindDevice(uniq_id)).WillOnce(Return(mockdev)); + EXPECT_CALL(transport_adapter, GetDeviceType()) + .WillOnce(Return(DeviceType::CLOUD_WEBSOCKET)); + EXPECT_CALL(transport_manager_settings, cloud_app_max_retry_attempts()) + .WillOnce(Return(0)); + TransportAdapter::Error res = transport_adapter.ConnectDevice(uniq_id); + EXPECT_EQ(TransportAdapter::FAIL, res); + EXPECT_EQ(ConnectionStatus::PENDING, mockdev->connection_status()); + + EXPECT_CALL(*server_mock, Terminate()); +} + TEST_F(TransportAdapterTest, ConnectDevice_DeviceAddedTwice) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -372,6 +431,7 @@ TEST_F(TransportAdapterTest, ConnectDevice_DeviceAddedTwice) { EXPECT_CALL(transport_adapter, FindDevice(uniq_id)).WillOnce(Return(mockdev)); TransportAdapter::Error res = transport_adapter.ConnectDevice(uniq_id); EXPECT_EQ(TransportAdapter::OK, res); + EXPECT_EQ(ConnectionStatus::CONNECTED, mockdev->connection_status()); // Try to connect device second time @@ -382,6 +442,7 @@ TEST_F(TransportAdapterTest, ConnectDevice_DeviceAddedTwice) { EXPECT_CALL(transport_adapter, FindDevice(uniq_id)).WillOnce(Return(mockdev)); TransportAdapter::Error newres = transport_adapter.ConnectDevice(uniq_id); EXPECT_EQ(TransportAdapter::OK, newres); + EXPECT_EQ(ConnectionStatus::CONNECTED, mockdev->connection_status()); EXPECT_CALL(*serverMock, Terminate()); } @@ -390,6 +451,7 @@ TEST_F(TransportAdapterTest, Disconnect_ConnectDoneSuccess) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -420,6 +482,7 @@ TEST_F(TransportAdapterTest, DisconnectDevice_DeviceAddedConnectionCreated) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -439,9 +502,11 @@ TEST_F(TransportAdapterTest, DisconnectDevice_DeviceAddedConnectionCreated) { EXPECT_CALL(*serverMock, IsInitialised()).WillOnce(Return(true)); EXPECT_CALL(*serverMock, CreateConnection(uniq_id, app_handle)) .WillOnce(Return(TransportAdapter::OK)); - EXPECT_CALL(transport_adapter, FindDevice(uniq_id)).WillOnce(Return(mockdev)); + EXPECT_CALL(transport_adapter, FindDevice(uniq_id)) + .WillRepeatedly(Return(mockdev)); TransportAdapter::Error res = transport_adapter.ConnectDevice(uniq_id); EXPECT_EQ(TransportAdapter::OK, res); + EXPECT_EQ(ConnectionStatus::CONNECTED, mockdev->connection_status()); auto mock_connection = std::make_shared<MockConnection>(); transport_adapter.ConnectionCreated(mock_connection, uniq_id, app_handle); @@ -451,6 +516,7 @@ TEST_F(TransportAdapterTest, DisconnectDevice_DeviceAddedConnectionCreated) { TransportAdapter::Error new_res = transport_adapter.DisconnectDevice(uniq_id); EXPECT_EQ(TransportAdapter::OK, new_res); + EXPECT_EQ(ConnectionStatus::CLOSING, mockdev->connection_status()); EXPECT_CALL(*serverMock, Terminate()); } @@ -459,6 +525,7 @@ TEST_F(TransportAdapterTest, DeviceDisconnected) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -484,6 +551,7 @@ TEST_F(TransportAdapterTest, DeviceDisconnected) { .WillOnce(Return(TransportAdapter::OK)); TransportAdapter::Error res = transport_adapter.ConnectDevice(uniq_id); EXPECT_EQ(TransportAdapter::OK, res); + EXPECT_EQ(ConnectionStatus::CONNECTED, mockdev->connection_status()); std::shared_ptr<MockConnection> mock_connection = std::make_shared<MockConnection>(); @@ -507,6 +575,7 @@ TEST_F(TransportAdapterTest, AbortedConnectSuccess) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -533,6 +602,7 @@ TEST_F(TransportAdapterTest, SendData) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( dev_mock, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*dev_mock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); @@ -574,6 +644,7 @@ TEST_F(TransportAdapterTest, SendData_ConnectionNotEstablished) { clientMock, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*dev_mock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(*clientMock, Init()).WillOnce(Return(TransportAdapter::OK)); @@ -609,6 +680,7 @@ TEST_F(TransportAdapterTest, StartClientListening_ClientNotInitialized) { MockClientConnectionListener* clientMock = new MockClientConnectionListener(); MockTransportAdapterImpl transport_adapter( dev_mock, NULL, clientMock, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*dev_mock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(*clientMock, Init()).WillOnce(Return(TransportAdapter::OK)); @@ -630,6 +702,7 @@ TEST_F(TransportAdapterTest, StartClientListening) { MockClientConnectionListener* clientMock = new MockClientConnectionListener(); MockTransportAdapterImpl transport_adapter( dev_mock, NULL, clientMock, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*dev_mock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(*clientMock, Init()).WillOnce(Return(TransportAdapter::OK)); @@ -656,6 +729,7 @@ TEST_F(TransportAdapterTest, StopClientListening_Success) { clientMock, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*dev_mock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(*clientMock, Init()).WillOnce(Return(TransportAdapter::OK)); @@ -690,6 +764,7 @@ TEST_F(TransportAdapterTest, FindNewApplicationsRequest) { clientMock, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*dev_mock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(*clientMock, Init()).WillOnce(Return(TransportAdapter::OK)); @@ -711,6 +786,7 @@ TEST_F(TransportAdapterTest, FindNewApplicationsRequest) { TEST_F(TransportAdapterTest, GetDeviceAndApplicationLists) { MockTransportAdapterImpl transport_adapter( NULL, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); transport_adapter.Init(); @@ -735,6 +811,7 @@ TEST_F(TransportAdapterTest, FindEstablishedConnection) { MockServerConnectionFactory* serverMock = new MockServerConnectionFactory(); MockTransportAdapterImpl transport_adapter( NULL, serverMock, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(*serverMock, Init()).WillOnce(Return(TransportAdapter::OK)); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); @@ -764,6 +841,7 @@ TEST_F(TransportAdapterTest, RunAppOnDevice_NoDeviseWithAskedId_UNSUCCESS) { MockTransportAdapterImpl transport_adapter( NULL, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); std::shared_ptr<MockDevice> mock_device = std::make_shared<MockDevice>("test_device_name", "test_device_uid0"); @@ -783,6 +861,7 @@ TEST_F(TransportAdapterTest, RunAppOnDevice_DeviseWithAskedIdWasFound_SUCCESS) { MockTransportAdapterImpl transport_adapter( NULL, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); std::shared_ptr<MockDevice> mock_device = std::make_shared<MockDevice>("test_device_name", device_uid); @@ -814,6 +893,7 @@ TEST_F(TransportAdapterTest, StopDevice) { TEST_F(TransportAdapterTest, TransportConfigUpdated) { MockTransportAdapterImpl transport_adapter( NULL, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); transport_adapter.Init(); @@ -832,6 +912,7 @@ TEST_F(TransportAdapterTest, TransportConfigUpdated) { TEST_F(TransportAdapterTest, GetTransportConfigration) { MockTransportAdapterImpl transport_adapter( NULL, NULL, NULL, last_state_, transport_manager_settings); + SetDefaultExpectations(transport_adapter); EXPECT_CALL(transport_adapter, Restore()).WillOnce(Return(true)); transport_adapter.Init(); diff --git a/src/components/utils/include/utils/timer.h b/src/components/utils/include/utils/timer.h index e391db992c..b012b97e6a 100644 --- a/src/components/utils/include/utils/timer.h +++ b/src/components/utils/include/utils/timer.h @@ -102,6 +102,8 @@ class Timer { */ bool is_running() const; + bool is_completed() const; + /** * @brief Gets current timer timeout * @return Current timeout in milliseconds. @@ -119,7 +121,7 @@ class Timer { * @brief Constructor * @param timer Timer instance pointer for callback calling */ - TimerDelegate(const Timer* timer, sync_primitives::Lock& state_lock_ref); + TimerDelegate(Timer* timer, sync_primitives::Lock& state_lock_ref); /** * @brief Sets timer timeout @@ -161,7 +163,7 @@ class Timer { void exitThreadMain() OVERRIDE; private: - const Timer* timer_; + Timer* timer_; Milliseconds timeout_; /** @@ -187,13 +189,13 @@ class Timer { * Not thread-safe * @param timeout Timer timeout */ - void StartDelegate(const Milliseconds timeout) const; + void StartDelegate(const Milliseconds timeout); /** * @brief Sets up timer delegate to stop state. * Not thread-safe */ - void StopDelegate() const; + void StopDelegate(); /** * @brief Starts timer thread. @@ -211,14 +213,14 @@ class Timer { * @brief Callback called on timeout. * Not thread-safe */ - void OnTimeout() const; + void OnTimeout(); const std::string name_; TimerTask* task_; mutable sync_primitives::Lock state_lock_; - mutable std::unique_ptr<TimerDelegate> delegate_; + std::unique_ptr<TimerDelegate> delegate_; threads::Thread* thread_; /** @@ -226,6 +228,8 @@ class Timer { */ bool single_shot_; + bool completed_flag_; + DISALLOW_COPY_AND_ASSIGN(Timer); }; diff --git a/src/components/utils/src/timer.cc b/src/components/utils/src/timer.cc index b819b56f54..68693dfc55 100644 --- a/src/components/utils/src/timer.cc +++ b/src/components/utils/src/timer.cc @@ -49,7 +49,8 @@ timer::Timer::Timer(const std::string& name, TimerTask* task) , state_lock_() , delegate_(new TimerDelegate(this, state_lock_)) , thread_(threads::CreateThread(name_.c_str(), delegate_.get())) - , single_shot_(true) { + , single_shot_(true) + , completed_flag_(false) { LOG4CXX_AUTO_TRACE(logger_); DCHECK(!name_.empty()); DCHECK(task_); @@ -76,6 +77,7 @@ void timer::Timer::Start(const Milliseconds timeout, LOG4CXX_AUTO_TRACE(logger_); sync_primitives::AutoLock auto_lock(state_lock_); StopThread(); + completed_flag_ = false; switch (timer_type) { case kSingleShot: { single_shot_ = true; @@ -106,17 +108,21 @@ bool timer::Timer::is_running() const { return !delegate_->stop_flag(); } +bool timer::Timer::is_completed() const { + return completed_flag_; +} + timer::Milliseconds timer::Timer::timeout() const { sync_primitives::AutoLock auto_lock(state_lock_); return delegate_->timeout(); } -void timer::Timer::StartDelegate(const Milliseconds timeout) const { +void timer::Timer::StartDelegate(const Milliseconds timeout) { delegate_->set_stop_flag(false); delegate_->set_timeout(timeout); } -void timer::Timer::StopDelegate() const { +void timer::Timer::StopDelegate() { delegate_->set_stop_flag(true); delegate_->set_timeout(0); } @@ -148,7 +154,7 @@ void timer::Timer::StopThread() { } } -void timer::Timer::OnTimeout() const { +void timer::Timer::OnTimeout() { { sync_primitives::AutoLock auto_lock(state_lock_); if (single_shot_) { @@ -158,10 +164,11 @@ void timer::Timer::OnTimeout() const { DCHECK_OR_RETURN_VOID(task_); task_->run(); + completed_flag_ = true; } timer::Timer::TimerDelegate::TimerDelegate( - const Timer* timer, sync_primitives::Lock& state_lock_ref) + Timer* timer, sync_primitives::Lock& state_lock_ref) : timer_(timer) , timeout_(0) , stop_flag_(true) |