summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/application_manager/include/application_manager/application.h6
-rw-r--r--src/components/application_manager/include/application_manager/application_impl.h6
-rw-r--r--src/components/application_manager/include/application_manager/application_manager_impl.h36
-rw-r--r--src/components/application_manager/include/application_manager/smart_object_keys.h4
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/register_app_interface_request.h9
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/sdl_activate_app_request.cc32
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc130
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/sdl_activate_app_request_test.cc54
-rw-r--r--src/components/application_manager/src/application_impl.cc5
-rw-r--r--src/components/application_manager/src/application_manager_impl.cc88
-rw-r--r--src/components/application_manager/src/message_helper/message_helper.cc54
-rw-r--r--src/components/application_manager/src/resumption/resume_ctrl_impl.cc16
-rw-r--r--src/components/application_manager/src/smart_object_keys.cc4
-rw-r--r--src/components/application_manager/test/application_manager_impl_test.cc131
-rw-r--r--src/components/application_manager/test/include/application_manager/mock_application.h1
-rw-r--r--src/components/application_manager/test/resumption/resume_ctrl_test.cc1
-rw-r--r--src/components/connection_handler/include/connection_handler/connection_handler_impl.h14
-rw-r--r--src/components/connection_handler/src/connection_handler_impl.cc9
-rw-r--r--src/components/include/application_manager/application_manager.h8
-rw-r--r--src/components/include/application_manager/application_manager_settings.h2
-rw-r--r--src/components/include/connection_handler/connection_handler.h10
-rw-r--r--src/components/include/connection_handler/connection_handler_observer.h2
-rw-r--r--src/components/include/test/application_manager/mock_application_manager.h3
-rw-r--r--src/components/include/test/application_manager/mock_application_manager_settings.h2
-rw-r--r--src/components/include/test/connection_handler/mock_connection_handler.h3
-rw-r--r--src/components/include/test/connection_handler/mock_connection_handler_observer.h1
-rw-r--r--src/components/include/test/transport_manager/mock_transport_manager.h3
-rw-r--r--src/components/include/test/transport_manager/mock_transport_manager_listener.h1
-rw-r--r--src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h4
-rw-r--r--src/components/include/transport_manager/common.h2
-rw-r--r--src/components/include/transport_manager/transport_adapter/device.h50
-rw-r--r--src/components/include/transport_manager/transport_adapter/transport_adapter.h12
-rw-r--r--src/components/include/transport_manager/transport_adapter/transport_adapter_event.h3
-rw-r--r--src/components/include/transport_manager/transport_manager.h10
-rw-r--r--src/components/include/transport_manager/transport_manager_listener.h5
-rw-r--r--src/components/include/transport_manager/transport_manager_listener_empty.h2
-rw-r--r--src/components/interfaces/HMI_API.xml28
-rw-r--r--src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h46
-rw-r--r--src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener.h6
-rw-r--r--src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener_impl.h5
-rw-r--r--src/components/transport_manager/include/transport_manager/transport_manager_impl.h15
-rw-r--r--src/components/transport_manager/src/cloud/cloud_device.cc2
-rw-r--r--src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc32
-rw-r--r--src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc101
-rw-r--r--src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc17
-rw-r--r--src/components/transport_manager/src/transport_manager_impl.cc21
-rw-r--r--src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_impl.h8
-rw-r--r--src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_listener.h2
-rw-r--r--src/components/transport_manager/test/transport_adapter_test.cc101
-rw-r--r--src/components/utils/include/utils/timer.h16
-rw-r--r--src/components/utils/src/timer.cc17
51 files changed, 937 insertions, 203 deletions
diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h
index 2abd2eaea0..7a59263299 100644
--- a/src/components/application_manager/include/application_manager/application.h
+++ b/src/components/application_manager/include/application_manager/application.h
@@ -981,6 +981,12 @@ class Application : public virtual InitialApplicationData,
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;
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 0b43b014b6..6d627d0c67 100644
--- a/src/components/application_manager/include/application_manager/application_impl.h
+++ b/src/components/application_manager/include/application_manager/application_impl.h
@@ -444,6 +444,12 @@ class ApplicationImpl : public virtual Application,
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;
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 20b8c561a3..a3e3cece72 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
@@ -367,6 +367,21 @@ class ApplicationManagerImpl
const transport_manager::DeviceInfo& device_info,
connection_handler::DeviceHandle device_id);
+ /**
+ * @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
*
@@ -492,9 +507,6 @@ class ApplicationManagerImpl
// 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
@@ -1487,12 +1499,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/smart_object_keys.h b/src/components/application_manager/include/application_manager/smart_object_keys.h
index 62192da391..5e6a3bb377 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;
@@ -192,6 +192,8 @@ extern const char* enabled;
extern const char* cloud_app_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;
// PutFile
extern const char* sync_file_name;
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..f8be896996 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);
/*
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/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..b346ee5798 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
@@ -346,19 +346,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 +438,8 @@ void RegisterAppInterfaceRequest::Run() {
FillDeviceInfo(&device_info);
}
+ const std::string& device_mac = application->mac_address();
+
GetPolicyHandler().SetDeviceInfo(device_mac, device_info);
SendRegisterAppInterfaceResponseToMobile(ApplicationType::kNewApplication);
@@ -816,8 +805,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 +813,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 +866,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 +890,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,100 +908,13 @@ 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));
}
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..ea345e3b83 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
@@ -61,8 +61,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 +150,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 +191,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 +253,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 +340,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 +432,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 558a4638c1..80b25dc814 100644
--- a/src/components/application_manager/src/application_impl.cc
+++ b/src/components/application_manager/src/application_impl.cc
@@ -1184,6 +1184,11 @@ const std::string& ApplicationImpl::cloud_app_certificate() const {
return certificate_;
}
+bool ApplicationImpl::is_cloud_app() const {
+ return !endpoint_.empty() &&
+ hybrid_app_preference_ != mobile_apis::HybridAppPreference::MOBILE;
+}
+
void ApplicationImpl::set_cloud_app_endpoint(const std::string& endpoint) {
endpoint_ = endpoint;
}
diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc
index ef008b7200..0923c054cc 100644
--- a/src/components/application_manager/src/application_manager_impl.cc
+++ b/src/components/application_manager/src/application_manager_impl.cc
@@ -381,21 +381,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) {
@@ -541,6 +526,7 @@ ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication(
app_name,
GetPolicyHandler().GetStatisticManager(),
*this));
+
if (!application) {
std::shared_ptr<smart_objects::SmartObject> response(
MessageHelper::CreateNegativeResponse(
@@ -610,13 +596,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_cloud_app_auth_token((*it)->cloud_app_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);
@@ -855,7 +876,7 @@ void ApplicationManagerImpl::CreatePendingApplication(
*this));
if (!application) {
- LOG4CXX_INFO(logger_, "Could not streate application");
+ LOG4CXX_INFO(logger_, "Could not create application");
return;
}
@@ -897,6 +918,28 @@ void ApplicationManagerImpl::CreatePendingApplication(
SendUpdateAppList();
}
+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() {
if (corelation_id_ < max_corelation_id_) {
corelation_id_++;
@@ -3758,6 +3801,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 2f86c50013..58d5171f84 100644
--- a/src/components/application_manager/src/message_helper/message_helper.cc
+++ b/src/components/application_manager/src/message_helper/message_helper.cc
@@ -1542,15 +1542,19 @@ 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());
@@ -1566,6 +1570,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;
}
@@ -1592,6 +1636,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/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 3e2951c553..70581466eb 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";
@@ -159,6 +159,8 @@ const char* enabled = "enabled";
const char* cloud_app_auth_token = "cloudAppAuthToken";
const char* cloud_transport_type = "cloudTransportType";
const char* hybrid_app_preference = "hybridAppPreference";
+const char* is_cloud_application = "isCloudApplication";
+const char* cloud_connection_status = "cloudConnectionStatus";
// PutFile
const char* sync_file_name = "syncFileName";
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..4ea44e5aca 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,121 @@ 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, cloud_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->cloud_app_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 9c9041284c..d5b3752936 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
@@ -348,6 +348,7 @@ class MockApplication : public ::application_manager::Application {
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_cloud_app_auth_token, void(const std::string& auth_token));
MOCK_METHOD1(set_cloud_app_transport_type,
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/connection_handler/include/connection_handler/connection_handler_impl.h b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h
index 7be94c5f70..b8153bcf42 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
@@ -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.
*
@@ -166,6 +176,8 @@ class ConnectionHandlerImpl
void OnScanDevicesFailed(
const transport_manager::SearchDeviceError& error) OVERRIDE;
+ void OnConnectionStatusUpdated() OVERRIDE;
+
/**
* \brief Notifies about pending connection.
*
diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc
index ed2522593c..f72cab61f3 100644
--- a/src/components/connection_handler/src/connection_handler_impl.cc
+++ b/src/components/connection_handler/src/connection_handler_impl.cc
@@ -249,6 +249,10 @@ void ConnectionHandlerImpl::OnScanDevicesFailed(
LOG4CXX_WARN(logger_, "Scan devices failed. " << error.text());
}
+void ConnectionHandlerImpl::OnConnectionStatusUpdated() {
+ connection_handler_observer_->OnConnectionStatusUpdated();
+}
+
void ConnectionHandlerImpl::OnConnectionPending(
const transport_manager::DeviceInfo& device_info,
const transport_manager::ConnectionUID connection_id) {
@@ -1292,6 +1296,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();
diff --git a/src/components/include/application_manager/application_manager.h b/src/components/include/application_manager/application_manager.h
index e6e5c89f45..9e979da08e 100644
--- a/src/components/include/application_manager/application_manager.h
+++ b/src/components/include/application_manager/application_manager.h
@@ -427,6 +427,14 @@ class ApplicationManager {
virtual void OnHMIStartedCooperation() = 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/connection_handler/connection_handler.h b/src/components/include/connection_handler/connection_handler.h
index 93939fc782..eb41141842 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.
*
diff --git a/src/components/include/connection_handler/connection_handler_observer.h b/src/components/include/connection_handler/connection_handler_observer.h
index 298f98803a..f683318ada 100644
--- a/src/components/include/connection_handler/connection_handler_observer.h
+++ b/src/components/include/connection_handler/connection_handler_observer.h
@@ -161,6 +161,8 @@ 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,
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..ca8aa2eb96 100644
--- a/src/components/include/test/application_manager/mock_application_manager.h
+++ b/src/components/include/test/application_manager/mock_application_manager.h
@@ -166,6 +166,9 @@ 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_CONST_METHOD1(GetCloudAppConnectionStatus,
+ hmi_apis::Common_CloudConnectionStatus::eType(
+ application_manager::ApplicationConstSharedPtr app));
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/connection_handler/mock_connection_handler.h b/src/components/include/test/connection_handler/mock_connection_handler.h
index bdc0469844..5836626ae3 100644
--- a/src/components/include/test/connection_handler/mock_connection_handler.h
+++ b/src/components/include/test/connection_handler/mock_connection_handler.h
@@ -60,6 +60,9 @@ 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());
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 2984b2e471..0a8e71c085 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,7 @@ 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,
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 e3f01fccb5..555d51bf76 100644
--- a/src/components/include/test/transport_manager/mock_transport_manager.h
+++ b/src/components/include/test/transport_manager/mock_transport_manager.h
@@ -63,6 +63,9 @@ class MockTransportManager : public ::transport_manager::TransportManager,
void(const std::string& endpoint,
const std::string& cloud_transport_type));
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 734651f455..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,7 @@ 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));
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 0be4da1063..c993f245b9 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
@@ -66,6 +66,10 @@ 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_METHOD0(ConnectionStatusUpdated, void());
MOCK_METHOD2(RunAppOnDevice, void(const std::string&, const std::string&));
MOCK_CONST_METHOD0(IsClientOriginatedConnectSupported, bool());
MOCK_METHOD0(
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 aae4a8b569..f4ce19eb5f 100644
--- a/src/components/include/transport_manager/transport_adapter/transport_adapter.h
+++ b/src/components/include/transport_manager/transport_adapter/transport_adapter.h
@@ -197,6 +197,18 @@ 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;
+
+ virtual void ConnectionStatusUpdated() = 0;
+
+ /**
* @brief RunAppOnDevice allows to run specific application on the certain
*device.
*
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 921562333b..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
@@ -59,7 +59,8 @@ enum class EventTypeEnum {
ON_UNEXPECTED_DISCONNECT,
ON_TRANSPORT_SWITCH_REQUESTED,
ON_TRANSPORT_CONFIG_UPDATED,
- ON_CONNECT_PENDING
+ 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 b5dfa3671b..3ecf815097 100644
--- a/src/components/include/transport_manager/transport_manager.h
+++ b/src/components/include/transport_manager/transport_manager.h
@@ -88,6 +88,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 7da4bcc2f5..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,11 @@ 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.
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 c0a713f38e..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.
*
diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml
index a11cfbfd8a..7adb5fb51e 100644
--- a/src/components/interfaces/HMI_API.xml
+++ b/src/components/interfaces/HMI_API.xml
@@ -292,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" />
@@ -2620,16 +2632,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">
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 0af1f2b614..8d03bdb2c7 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,18 @@ 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;
+
+ void ConnectionStatusUpdated() OVERRIDE;
+
+ /**
* @brief Disconnect from specified session.
*
* @param devcie_handle Device unique identifier.
@@ -547,6 +562,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.
*/
@@ -578,7 +610,7 @@ class TransportAdapterImpl : public TransportAdapter,
ConnectionSPtr connection;
DeviceUID device_id;
ApplicationHandle app_handle;
- enum { NEW, ESTABLISHED, FINALISING, PENDING, RETRY } state;
+ enum { NEW, ESTABLISHED, FINALISING, PENDING } state;
};
/**
@@ -608,6 +640,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 b0368869e7..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,12 @@ 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.
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 76271229ad..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,11 @@ 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.
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 dcb3b6922c..c84b1e9a39 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"
@@ -153,6 +152,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.
@@ -368,7 +377,7 @@ class TransportManagerImpl
* @brief Converter variable (Device ID -> Device Handle; Device Handle ->
* Device ID)
*/
- Handle2GUIDConverter converter_;
+ mutable Handle2GUIDConverter converter_;
#ifdef BUILD_TESTS
public:
@@ -383,7 +392,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
index 90a485c069..184fcc10cc 100644
--- a/src/components/transport_manager/src/cloud/cloud_device.cc
+++ b/src/components/transport_manager/src/cloud/cloud_device.cc
@@ -60,7 +60,7 @@ bool CloudDevice::IsSameAs(const Device* other) const {
}
ApplicationList CloudDevice::GetApplicationList() const {
- return ApplicationList{100};
+ return ApplicationList{0};
}
const std::string& CloudDevice::GetHost() const {
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
index 24efdfb2a4..5093e6c2af 100644
--- a/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc
+++ b/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc
@@ -74,11 +74,31 @@ void CloudWebsocketTransportAdapter::CreateDevice(const std::string& uid) {
}
LOG4CXX_DEBUG(logger_, "Valid Endpoint: " << uid);
- std::size_t pos = uid.find(":");
- pos = uid.find(":", pos + 1);
- // std::size_t size = uid.length();
- std::string host = uid.substr(0, pos);
- std::string port = uid.substr(pos + 1);
+
+ // 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,4})(\\/)");
+ 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_,
@@ -101,4 +121,4 @@ void CloudWebsocketTransportAdapter::CreateDevice(const std::string& uid) {
return;
}
}
-} \ No newline at end of file
+}
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 38b9bd3998..8928ecb4d2 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"
@@ -209,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;
}
@@ -241,6 +246,36 @@ 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->set_connection_status(ConnectionStatus::PENDING);
+ device->reset_retry_count();
+ ConnectionStatusUpdated();
+ return err;
+ } else if (device->connection_status() == ConnectionStatus::PENDING) {
+ device->set_connection_status(ConnectionStatus::RETRY);
+ ConnectionStatusUpdated();
+ }
+
+ 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) {
+ device->set_connection_status(ConnectionStatus::CONNECTED);
+ ConnectionStatusUpdated();
+ }
LOG4CXX_TRACE(logger_, "exit with error: " << err);
return err;
} else {
@@ -249,6 +284,58 @@ 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() {
+ 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_,
@@ -278,6 +365,9 @@ TransportAdapter::Error TransportAdapterImpl::DisconnectDevice(
}
Error error = OK;
+ DeviceSptr device = FindDevice(device_id);
+ device->set_connection_status(ConnectionStatus::CLOSING);
+ ConnectionStatusUpdated();
std::vector<ConnectionInfo> to_disconnect;
connections_lock_.AcquireForReading();
@@ -397,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) {
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 73750fe2f3..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,23 @@ 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,
diff --git a/src/components/transport_manager/src/transport_manager_impl.cc b/src/components/transport_manager/src/transport_manager_impl.cc
index 300ed27718..518a5639db 100644
--- a/src/components/transport_manager/src/transport_manager_impl.cc
+++ b/src/components/transport_manager/src/transport_manager_impl.cc
@@ -177,6 +177,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_) {
@@ -974,6 +990,11 @@ 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());
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..e18d1bc53b 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
@@ -70,15 +70,15 @@ 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_METHOD0(ConnectionStatusUpdated, void());
+ 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 81e133ec2b..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,8 @@ 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,
diff --git a/src/components/transport_manager/test/transport_adapter_test.cc b/src/components/transport_manager/test/transport_adapter_test.cc
index 9e602332c6..b917c60187 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));
@@ -339,16 +359,58 @@ TEST_F(TransportAdapterTest, ConnectDevice_DeviceAdded) {
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, ConnectionStatusUpdated());
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);
+ // transport_adapter.SetDeviceType(DeviceType::CLOUD_WEBSOCKET);
+
+ 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_adapter, ConnectionStatusUpdated());
+ 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));
@@ -370,8 +432,10 @@ TEST_F(TransportAdapterTest, ConnectDevice_DeviceAddedTwice) {
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, ConnectionStatusUpdated());
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
@@ -380,8 +444,10 @@ TEST_F(TransportAdapterTest, ConnectDevice_DeviceAddedTwice) {
EXPECT_CALL(*serverMock, IsInitialised()).WillOnce(Return(true));
EXPECT_CALL(*serverMock, CreateConnection(uniq_id, app_handle)).Times(0);
EXPECT_CALL(transport_adapter, FindDevice(uniq_id)).WillOnce(Return(mockdev));
+ EXPECT_CALL(transport_adapter, ConnectionStatusUpdated());
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 +456,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 +487,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 +507,12 @@ 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));
+ EXPECT_CALL(transport_adapter, ConnectionStatusUpdated());
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);
@@ -449,8 +520,10 @@ TEST_F(TransportAdapterTest, DisconnectDevice_DeviceAddedConnectionCreated) {
EXPECT_CALL(*mock_connection, Disconnect())
.WillOnce(Return(TransportAdapter::OK));
+ EXPECT_CALL(transport_adapter, ConnectionStatusUpdated());
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 +532,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));
@@ -482,8 +556,10 @@ TEST_F(TransportAdapterTest, DeviceDisconnected) {
EXPECT_CALL(*serverMock, IsInitialised()).WillOnce(Return(true));
EXPECT_CALL(*serverMock, CreateConnection(uniq_id, app_handle))
.WillOnce(Return(TransportAdapter::OK));
+ EXPECT_CALL(transport_adapter, ConnectionStatusUpdated());
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 +583,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 +610,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 +652,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 +688,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 +710,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 +737,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 +772,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 +794,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 +819,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 +849,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 +869,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 +901,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 +920,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)