summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/application_manager/include/application_manager/app_extension.h7
-rw-r--r--src/components/application_manager/include/application_manager/resumption/resumption_data_processor.h3
-rw-r--r--src/components/application_manager/include/application_manager/resumption/resumption_data_processor_impl.h6
-rw-r--r--src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/app_service_app_extension.h2
-rw-r--r--src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/app_service_app_extension.cc4
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/commands/hmi/rc_get_interior_vehicle_data_request.h2
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/interior_data_manager.h7
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/interior_data_manager_impl.h2
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_app_extension.h57
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_helpers.h15
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_pending_resumption_handler.h165
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_rpc_plugin.h31
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/hmi/rc_get_interior_vehicle_data_request.cc19
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/mobile/get_interior_vehicle_data_request.cc32
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_manager_impl.cc19
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_app_extension.cc167
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_helpers.cc34
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_pending_resumption_handler.cc343
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_rpc_plugin.cc54
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/CMakeLists.txt3
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/button_press_request_test.cc9
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/get_interior_vehicle_data_request_test.cc76
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/on_interior_vehicle_data_notification_test.cc10
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/rc_get_interior_vehicle_data_consent_test.cc8
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/set_interior_vehicle_data_request_test.cc8
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/include/rc_rpc_plugin/mock/mock_interior_data_manager.h2
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/include/rc_rpc_plugin/mock/mock_rc_helpers.h11
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/mock_rc_helpers.cc15
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_app_extension_test.cc198
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_pending_resumption_handler_test.cc421
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/CMakeLists.txt1
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/resource_allocation_manager_impl_test.cc34
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/waypoints_app_extension.h2
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/waypoints_app_extension.cc4
-rw-r--r--src/components/application_manager/rpc_plugins/vehicle_info_plugin/include/vehicle_info_plugin/vehicle_info_app_extension.h2
-rw-r--r--src/components/application_manager/rpc_plugins/vehicle_info_plugin/src/vehicle_info_app_extension.cc24
-rw-r--r--src/components/application_manager/src/application_impl.cc3
-rw-r--r--src/components/application_manager/src/resumption/resumption_data_processor_impl.cc119
38 files changed, 1826 insertions, 93 deletions
diff --git a/src/components/application_manager/include/application_manager/app_extension.h b/src/components/application_manager/include/application_manager/app_extension.h
index bf2675e36f..3b1db4de57 100644
--- a/src/components/application_manager/include/application_manager/app_extension.h
+++ b/src/components/application_manager/include/application_manager/app_extension.h
@@ -74,10 +74,11 @@ class AppExtension {
/**
* @brief RevertResumption Method called by SDL during revert resumption.
- * @param subscriptions Subscriptions from which must discard. Expected that
- * SO contains the map of "IVI data" keys and "subscription bool flag" values
+ * @param resumption_data Resumption data in the SmartObject representation
+ * that contains subscription (VehicleInfo, RemoteControl, etc.)
*/
- virtual void RevertResumption(const ns_smart::SmartObject& subscriptions) = 0;
+ virtual void RevertResumption(
+ const ns_smart::SmartObject& resumption_data) = 0;
private:
const AppExtensionUID kUid_;
diff --git a/src/components/application_manager/include/application_manager/resumption/resumption_data_processor.h b/src/components/application_manager/include/application_manager/resumption/resumption_data_processor.h
index 943022295b..60e2e5d1a4 100644
--- a/src/components/application_manager/include/application_manager/resumption/resumption_data_processor.h
+++ b/src/components/application_manager/include/application_manager/resumption/resumption_data_processor.h
@@ -29,6 +29,7 @@
#include "application_manager/application.h"
#include "application_manager/resumption/resume_ctrl.h"
+#include "application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_rpc_types.h"
#include "smart_objects/smart_object.h"
namespace resumption {
@@ -44,6 +45,8 @@ bool IsResponseSuccessful(const smart_objects::SmartObject& response);
* @brief The ResumptionRequestID struct contains fields, needed during
* processing events, related to responses from HMI to each resumption request
*/
+using ModuleUid = rc_rpc_plugin::rc_rpc_types::ModuleUid;
+
struct ResumptionRequestID {
hmi_apis::FunctionID::eType function_id;
int32_t correlation_id;
diff --git a/src/components/application_manager/include/application_manager/resumption/resumption_data_processor_impl.h b/src/components/application_manager/include/application_manager/resumption/resumption_data_processor_impl.h
index 0b3c84432b..12d25e2ac5 100644
--- a/src/components/application_manager/include/application_manager/resumption/resumption_data_processor_impl.h
+++ b/src/components/application_manager/include/application_manager/resumption/resumption_data_processor_impl.h
@@ -52,6 +52,8 @@ struct ApplicationResumptionStatus {
std::vector<ResumptionRequest> successful_requests;
std::vector<std::string> unsuccessful_vehicle_data_subscriptions_;
std::vector<std::string> successful_vehicle_data_subscriptions_;
+ std::vector<ModuleUid> successful_module_subscriptions_;
+ std::vector<ModuleUid> unsuccessful_module_subscriptions_;
};
/**
@@ -339,6 +341,10 @@ class ResumptionDataProcessorImpl
const smart_objects::SmartObject& response,
ApplicationResumptionStatus& status);
+ void CheckModuleDataSubscription(const smart_objects::SmartObject& request,
+ const smart_objects::SmartObject& response,
+ ApplicationResumptionStatus& status);
+
/**
* @brief Checks whether CreateWindow response successful or not and handles
* it
diff --git a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/app_service_app_extension.h b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/app_service_app_extension.h
index eff9567122..8d307325fc 100644
--- a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/app_service_app_extension.h
+++ b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/app_service_app_extension.h
@@ -103,7 +103,7 @@ class AppServiceAppExtension : public app_mngr::AppExtension {
void ProcessResumption(const smart_objects::SmartObject& saved_app) OVERRIDE;
void RevertResumption(
- const smart_objects::SmartObject& subscriptions) OVERRIDE;
+ const smart_objects::SmartObject& resumption_data) OVERRIDE;
/**
* @brief ExtractVIExtension utility function to extract application extension
diff --git a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/app_service_app_extension.cc b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/app_service_app_extension.cc
index b5b27fc157..5a1815d974 100644
--- a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/app_service_app_extension.cc
+++ b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/app_service_app_extension.cc
@@ -113,10 +113,10 @@ void AppServiceAppExtension::ProcessResumption(
}
void AppServiceAppExtension::RevertResumption(
- const smart_objects::SmartObject& subscriptions) {
+ const smart_objects::SmartObject& resumption_data) {
SDL_LOG_AUTO_TRACE();
- UNUSED(subscriptions);
+ UNUSED(resumption_data);
// ToDo: implementation is blocked by
// https://github.com/smartdevicelink/sdl_core/issues/3470
}
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/commands/hmi/rc_get_interior_vehicle_data_request.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/commands/hmi/rc_get_interior_vehicle_data_request.h
index a75020956c..f81919f4fa 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/commands/hmi/rc_get_interior_vehicle_data_request.h
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/commands/hmi/rc_get_interior_vehicle_data_request.h
@@ -51,6 +51,8 @@ class RCGetInteriorVehicleDataRequest
const RCCommandParams& params);
void Run() OVERRIDE;
+ void onTimeOut() OVERRIDE;
+
~RCGetInteriorVehicleDataRequest();
};
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/interior_data_manager.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/interior_data_manager.h
index c1fe30fa4d..e265fb7427 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/interior_data_manager.h
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/interior_data_manager.h
@@ -87,6 +87,13 @@ class InteriorDataManager {
* false.
*/
virtual bool CheckRequestsToHMIFrequency(const ModuleUid& module) = 0;
+
+ /**
+ * @brief Reverts resumption data and sends ubsubscribe vehicle data request
+ * to a HMI
+ * @param subscriptions Module data that SDL should unsubscribe off
+ */
+ virtual void OnResumptionRevert(const std::set<ModuleUid>& subscriptions) = 0;
};
} // namespace rc_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/interior_data_manager_impl.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/interior_data_manager_impl.h
index 791016cdcd..43927b25c8 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/interior_data_manager_impl.h
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/interior_data_manager_impl.h
@@ -65,6 +65,8 @@ class InteriorDataManagerImpl : public InteriorDataManager {
bool CheckRequestsToHMIFrequency(const ModuleUid& module) OVERRIDE;
+ void OnResumptionRevert(const std::set<ModuleUid>& subscriptions) OVERRIDE;
+
private:
/**
* @brief UpdateHMISubscriptionsOnPolicyUpdated process policy update event.
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_app_extension.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_app_extension.h
index ab88ac8975..8b2162c9ab 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_app_extension.h
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_app_extension.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Ford Motor Company
+ * Copyright (c) 2020, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,9 @@
#include <memory>
#include <set>
#include <string>
+
#include "application_manager/app_extension.h"
+#include "application_manager/application.h"
#include "utils/macro.h"
namespace rc_rpc_plugin {
@@ -137,9 +139,13 @@ struct Grid {
}
};
+class RCRPCPlugin;
+
class RCAppExtension : public application_manager::AppExtension {
public:
- explicit RCAppExtension(application_manager::AppExtensionUID uid);
+ explicit RCAppExtension(application_manager::AppExtensionUID uid,
+ RCRPCPlugin& plugin,
+ application_manager::Application& application);
~RCAppExtension();
/**
@@ -177,6 +183,36 @@ class RCAppExtension : public application_manager::AppExtension {
std::set<ModuleUid> InteriorVehicleDataSubscriptions() const;
/**
+ * @brief AddPendingSubscription adds pending subscription
+ * @param module interior data specification(zone, data type)
+ * @return true in case of pending subscription is successful added, otherwise
+ * false
+ */
+ bool AddPendingSubscription(const ModuleUid& module);
+
+ /**
+ * @brief RemovePendingSubscription removes some particular pending
+ * subscription
+ * @param module interior data specification(zone, data type)
+ */
+ void RemovePendingSubscription(const ModuleUid& module);
+
+ /**
+ * @brief RemovePendingSubscriptions removes all pending subscriptions
+ */
+ void RemovePendingSubscriptions();
+
+ /**
+ * @brief PendingSubscriptions list of preliminary subscriptoins
+ * That will be moved to subscriptions as soon as HMI will respond with
+ * success.
+ * Used for resumption to keep list of preliminary subscriptions and wait for
+ * HMI response
+ * @return list of preliminary subscriptions
+ */
+ std::set<ModuleUid> PendingSubscriptions();
+
+ /**
* @brief GetUserLocation
* @return grid of user location
*/
@@ -197,10 +233,25 @@ class RCAppExtension : public application_manager::AppExtension {
void SetUserLocation(const Grid& grid);
private:
+ /**
+ * @brief Checks if the application's pointer is valid and update the
+ * application's hash in this case
+ */
+ void UpdateHash();
+
std::set<ModuleUid> subscribed_interior_vehicle_data_;
+ std::set<ModuleUid> pending_subscriptions_;
+
Grid user_location_;
+ RCRPCPlugin& plugin_;
+
+ /**
+ * ApplicationSharedPtr needed for updating application's hash
+ */
+ application_manager::Application& application_;
+
// AppExtension interface
public:
void SaveResumptionData(smart_objects::SmartObject& resumption_data) OVERRIDE;
@@ -208,7 +259,7 @@ class RCAppExtension : public application_manager::AppExtension {
void ProcessResumption(const smart_objects::SmartObject& saved_app) OVERRIDE;
void RevertResumption(
- const smart_objects::SmartObject& subscriptions) OVERRIDE;
+ const smart_objects::SmartObject& resumption_data) OVERRIDE;
};
typedef std::shared_ptr<RCAppExtension> RCAppExtensionPtr;
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_helpers.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_helpers.h
index eed860fc7f..1bf4a7a259 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_helpers.h
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_helpers.h
@@ -80,8 +80,12 @@ class RCHelpers {
static RCAppExtensionPtr GetRCExtension(
application_manager::Application& app);
- static smart_objects::SmartObjectSPtr CreateUnsubscribeRequestToHMI(
- const ModuleUid& module, const uint32_t correlation_id);
+ enum InteriorDataAction { SUBSCRIBE, UNSUBSCRIBE, NONE };
+
+ static smart_objects::SmartObjectSPtr CreateGetInteriorVDRequestToHMI(
+ const ModuleUid& module,
+ const uint32_t correlation_id,
+ const InteriorDataAction action);
static std::vector<application_manager::ApplicationSharedPtr>
AppsSubscribedToModule(application_manager::ApplicationManager& app_mngr,
@@ -169,6 +173,13 @@ class RCHelpers {
static smart_objects::SmartObject MergeArray(
const smart_objects::SmartObject& data1,
const smart_objects::SmartObject& data2);
+
+ /**
+ * @brief Determines the success of the response
+ * judging from message type received from HMI
+ * @param response from HMI
+ */
+ static bool IsResponseSuccessful(const smart_objects::SmartObject& response);
};
} // namespace rc_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_pending_resumption_handler.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_pending_resumption_handler.h
new file mode 100644
index 0000000000..944d47b052
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_pending_resumption_handler.h
@@ -0,0 +1,165 @@
+#pragma once
+
+#include <map>
+#include <queue>
+#include "application_manager/event_engine/event_observer.h"
+#include "application_manager/resumption/pending_resumption_handler.h"
+#include "application_manager/resumption/resumption_data_processor.h"
+#include "application_manager/rpc_service.h"
+#include "rc_rpc_plugin/interior_data_cache.h"
+#include "rc_rpc_plugin/rc_app_extension.h"
+
+namespace rc_rpc_plugin {
+
+/**
+ * @brief The RCPendingResumptionHandler class
+ * responsibility to avoid duplication of subscription requests to HMI
+ * if multiple applications are registering
+ */
+class RCPendingResumptionHandler : public resumption::PendingResumptionHandler {
+ public:
+ RCPendingResumptionHandler(
+ application_manager::ApplicationManager& application_manager,
+ rc_rpc_plugin::InteriorDataCache& interior_data_cache);
+
+ void on_event(const application_manager::event_engine::Event& event) override;
+
+ void HandleResumptionSubscriptionRequest(
+ application_manager::AppExtension& extension,
+ application_manager::Application& app) override;
+
+ void OnResumptionRevert() override;
+
+ /**
+ * @brief Creates GetInteriorVehicleData subscription request
+ * @param module unique identifier of module (moduleType + moduleID) used to
+ * create the request
+ * @param correlation_id - unique ID
+ * @return subscription request in smart object representation
+ */
+ static smart_objects::SmartObjectSPtr CreateSubscriptionRequest(
+ const ModuleUid& module, const uint32_t correlation_id);
+
+ /**
+ * @brief Retrieves function id from subscription request
+ * @param subscription_request a subscription request that contains the
+ * function id
+ * @return function id
+ */
+ static hmi_apis::FunctionID::eType GetFunctionId(
+ const smart_objects::SmartObject& subscription_request);
+
+ /**
+ * @brief Retrieves module uid from subscription request
+ * @param subscription_request a subscription request that contains a unique
+ * module identifier
+ * @return unique module identifier
+ */
+ static ModuleUid GetModuleUid(
+ const smart_objects::SmartObject& subscription_request);
+
+ private:
+ /**
+ * @brief The PendingRequest struct contains fields, needed during
+ * processing events, related to responses from HMI to each resumption request
+ */
+ struct PendingRequest {
+ uint32_t app_id;
+ smart_objects::SmartObject message;
+ uint32_t correlation_id() const {
+ namespace am_strings = app_mngr::strings;
+ return message[am_strings::params][am_strings::correlation_id].asInt();
+ }
+ };
+
+ /**
+ * @brief Handles a successful response from HMI
+ * @param event contains response from HMI
+ * @param module_uid a unique identifier for module
+ */
+ void HandleSuccessfulResponse(
+ const application_manager::event_engine::Event& event,
+ const ModuleUid& module_uid);
+
+ /**
+ * @brief Creates next GetInteriorVehicleData subscription request if a
+ * previous resumption of subscriptions is not successful
+ * @param module a unique identifier for module
+ */
+ void ProcessNextPausedResumption(const ModuleUid& module);
+
+ /**
+ * @brief Notifies subscriber about resumption status
+ * @param subscription_response response from HMI
+ * @param correlation_id unique message ID
+ */
+ void RaiseEventForResponse(
+ const smart_objects::SmartObject& subscription_response,
+ const uint32_t correlation_id) const;
+
+ /**
+ * @brief Checks if SDL is still waiting on a subscription response for the
+ * specified module
+ * @param module the unique identifier for the module to be checked against
+ */
+ bool IsPendingForResponse(const ModuleUid& module) const;
+
+ /**
+ * @brief Checks if any app except passed is subscribed to a given module
+ * @param module module to check
+ * @param app_id app to ignore subscription
+ * @return true if any app except passed is subscribed to module, otherwise
+ * false
+ */
+ bool IsOtherAppsSubscribed(const uint32_t app_id,
+ const ModuleUid& module) const;
+
+ /**
+ * @brief Returns pending request, which corresponds to correlation ID
+ * @param corr_id unique message ID
+ * @return optional object, which contains subscription request, or empty
+ * optional, if such request wasn't found
+ */
+ utils::Optional<smart_objects::SmartObject> GetPendingRequest(
+ const uint32_t corr_id);
+
+ /**
+ * @brief Returns ID of application, related to pending request, which
+ * corresponds to correlation ID
+ * @param corr_id unique message ID
+ * @return optional object, which contains ID of application, or empty
+ * optional, if such request wasn't found
+ */
+ utils::Optional<uint32_t> GetPendingApp(const uint32_t corr_id);
+
+ /**
+ * @brief Removes pending request, which corresponds to
+ * correlation ID
+ * @param corr_id unique ID
+ */
+ void RemovePendingRequest(const uint32_t corr_id);
+
+ /**
+ * @brief Adds pending request, related to
+ * application ID
+ * @param request_so pending request message
+ */
+ void AddPendingRequest(const uint32_t app_id,
+ const smart_objects::SmartObject request_so);
+
+ /**
+ * @brief PendingRequestQueue contains subscription request,
+ * which will be sent to the HMI in the case that a previous resumption
+ * attempt for the same module was not successful
+ */
+ using PendingRequestQueue = std::queue<PendingRequest>;
+ std::map<ModuleUid, PendingRequestQueue> paused_resumptions_;
+
+ sync_primitives::Lock pending_resumption_lock_;
+ std::vector<PendingRequest> pending_requests_;
+
+ application_manager::rpc_service::RPCService& rpc_service_;
+ rc_rpc_plugin::InteriorDataCache& interior_data_cache_;
+};
+
+} // namespace rc_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_rpc_plugin.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_rpc_plugin.h
index 51e0668930..528e116403 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_rpc_plugin.h
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_rpc_plugin.h
@@ -37,6 +37,7 @@
#include "application_manager/command_factory.h"
#include "application_manager/plugin_manager/rpc_plugin.h"
+#include "application_manager/resumption/pending_resumption_handler.h"
#include "rc_rpc_plugin/interior_data_cache.h"
#include "rc_rpc_plugin/interior_data_manager.h"
#include "rc_rpc_plugin/rc_capabilities_manager.h"
@@ -103,6 +104,33 @@ class RCRPCPlugin : public plugins::RPCPlugin {
void OnApplicationEvent(plugins::ApplicationEvent event,
app_mngr::ApplicationSharedPtr application) OVERRIDE;
+ /**
+ * @brief ProcessResumptionSubscription send Subscribe vehicle data requests
+ * to HMI
+ * @param app application for subscription
+ * @param ext application extension
+ */
+ void ProcessResumptionSubscription(app_mngr::Application& app,
+ RCAppExtension& ext);
+
+ /**
+ * @brief Reverts resumption data, clears all pending resumption and sends
+ * unsubscribe interior vehicle data requests to HMI
+ * @param subscriptions Module data that SDL should unsubscribe off
+ */
+ void RevertResumption(const std::set<ModuleUid>& subscriptions);
+
+ /**
+ * @brief IsOtherAppsSubscribed check if any app except passed is subscribed
+ * to a given module
+ * @param module module to check
+ * @param app_id app to ignore subscription
+ * @return true if any app except passed is subscribed to module, otherwise
+ * false
+ */
+ bool IsOtherAppsSubscribed(const rc_rpc_types::ModuleUid& module,
+ const uint32_t app_id);
+
static const uint32_t kRCPluginID = 153;
typedef std::vector<application_manager::ApplicationSharedPtr> Apps;
@@ -118,6 +146,9 @@ class RCRPCPlugin : public plugins::RPCPlugin {
std::unique_ptr<InteriorDataCache> interior_data_cache_;
std::unique_ptr<InteriorDataManager> interior_data_manager_;
std::unique_ptr<RCCapabilitiesManager> rc_capabilities_manager_;
+ using PendingResumptionHandlerSPtr =
+ std::shared_ptr<resumption::PendingResumptionHandler>;
+ PendingResumptionHandlerSPtr pending_resumption_handler_;
};
} // namespace rc_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/hmi/rc_get_interior_vehicle_data_request.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/hmi/rc_get_interior_vehicle_data_request.cc
index ffe124f3bd..fede1dbd11 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/hmi/rc_get_interior_vehicle_data_request.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/hmi/rc_get_interior_vehicle_data_request.cc
@@ -31,6 +31,9 @@
*/
#include "rc_rpc_plugin/commands/hmi/rc_get_interior_vehicle_data_request.h"
+#include "application_manager/message_helper.h"
+#include "application_manager/resumption/resume_ctrl.h"
+
#include "utils/macro.h"
namespace rc_rpc_plugin {
@@ -54,5 +57,21 @@ void RCGetInteriorVehicleDataRequest::Run() {
SendRequest();
}
+void RCGetInteriorVehicleDataRequest::onTimeOut() {
+ SDL_LOG_TRACE("function_id: " << function_id()
+ << " correlation_id: " << correlation_id());
+ using namespace application_manager;
+ event_engine::Event timeout_event(
+ hmi_apis::FunctionID::RC_GetInteriorVehicleData);
+
+ auto error_response = MessageHelper::CreateNegativeResponseFromHmi(
+ function_id(),
+ correlation_id(),
+ hmi_apis::Common_Result::GENERIC_ERROR,
+ std::string("Timed out"));
+ timeout_event.set_smart_object(*error_response);
+ timeout_event.raise(application_manager_.event_dispatcher());
+}
+
} // namespace commands
} // namespace rc_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/mobile/get_interior_vehicle_data_request.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/mobile/get_interior_vehicle_data_request.cc
index 7d274870bc..2b801f7406 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/mobile/get_interior_vehicle_data_request.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/commands/mobile/get_interior_vehicle_data_request.cc
@@ -119,21 +119,34 @@ void GetInteriorVehicleDataRequest::ProcessResponseToMobileFromCache(
const auto& request_msg_params = (*message_)[app_mngr::strings::msg_params];
SDL_LOG_DEBUG("kSubscribe exist"
<< request_msg_params.keyExists(message_params::kSubscribe));
+
+ mobile_apis::Result::eType result_code = mobile_apis::Result::SUCCESS;
if (request_msg_params.keyExists(message_params::kSubscribe)) {
response_msg_params[message_params::kIsSubscribed] =
request_msg_params[message_params::kSubscribe].asBool();
if (request_msg_params[message_params::kSubscribe].asBool()) {
auto extension = RCHelpers::GetRCExtension(*app);
DCHECK(extension);
- extension->SubscribeToInteriorVehicleData(module);
+ const bool is_app_already_subscribed =
+ extension->IsSubscribedToInteriorVehicleData(module);
+ if (is_app_already_subscribed) {
+ response_msg_params[app_mngr::strings::info] =
+ "App is already subscribed to the provided module";
+ result_code = mobile_apis::Result::WARNINGS;
+ } else {
+ extension->SubscribeToInteriorVehicleData(module);
+ app->UpdateHash();
+ }
}
}
- SendResponse(
- true, mobile_apis::Result::SUCCESS, nullptr, &response_msg_params);
+ SendResponse(true, result_code, nullptr, &response_msg_params);
if (AppShouldBeUnsubscribed()) {
auto extension = RCHelpers::GetRCExtension(*app);
DCHECK(extension);
- extension->UnsubscribeFromInteriorVehicleData(module);
+ if (extension->IsSubscribedToInteriorVehicleData(module)) {
+ extension->UnsubscribeFromInteriorVehicleData(module);
+ app->UpdateHash();
+ }
}
}
@@ -255,6 +268,9 @@ void GetInteriorVehicleDataRequest::on_event(
const ModuleUid module(module_type, module_id);
if (TheLastAppShouldBeUnsubscribed(app)) {
+ SDL_LOG_DEBUG("Removing module: [" << module.first << ":" << module.second
+ << "] "
+ << "from cache");
interior_data_cache_.Remove(module);
}
ProccessSubscription(hmi_response);
@@ -363,15 +379,19 @@ void GetInteriorVehicleDataRequest::ProccessSubscription(
const std::string module_id = ModuleId();
const ModuleUid module(module_type, module_id);
- if (response_subscribe) {
+ if (response_subscribe &&
+ !extension->IsSubscribedToInteriorVehicleData(module)) {
SDL_LOG_DEBUG("SubscribeToInteriorVehicleData "
<< app->app_id() << " " << module_type << " " << module_id);
extension->SubscribeToInteriorVehicleData(module);
- } else {
+ } else if (!response_subscribe &&
+ extension->IsSubscribedToInteriorVehicleData(module)) {
SDL_LOG_DEBUG("UnsubscribeFromInteriorVehicleData "
<< app->app_id() << " " << module_type << " " << module_id);
extension->UnsubscribeFromInteriorVehicleData(module);
}
+
+ app->UpdateHash();
}
}
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_manager_impl.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_manager_impl.cc
index a4d4026da7..1db25265e7 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_manager_impl.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_manager_impl.cc
@@ -49,6 +49,13 @@ void InteriorDataManagerImpl::OnDisablingRC() {
}
}
+void InteriorDataManagerImpl::OnResumptionRevert(
+ const std::set<ModuleUid>& subscriptions) {
+ for (const auto& module : subscriptions) {
+ UnsubscribeFromInteriorVehicleData(module);
+ }
+}
+
void InteriorDataManagerImpl::StoreRequestToHMITime(const ModuleUid& module) {
SDL_LOG_AUTO_TRACE();
sync_primitives::AutoLock autolock(requests_to_hmi_history_lock_);
@@ -125,8 +132,10 @@ void InteriorDataManagerImpl::UpdateHMISubscriptionsOnAppUnregistered(
void InteriorDataManagerImpl::UnsubscribeFromInteriorVehicleData(
const ModuleUid& module) {
cache_.Remove(module);
- auto unsubscribe_request = RCHelpers::CreateUnsubscribeRequestToHMI(
- module, app_mngr_.GetNextHMICorrelationID());
+ auto unsubscribe_request = RCHelpers::CreateGetInteriorVDRequestToHMI(
+ module,
+ app_mngr_.GetNextHMICorrelationID(),
+ RCHelpers::InteriorDataAction::UNSUBSCRIBE);
SDL_LOG_DEBUG("Send Unsubscribe from module type: " << module.first << " id: "
<< module.second);
rpc_service_.ManageHMICommand(unsubscribe_request);
@@ -138,8 +147,10 @@ void InteriorDataManagerImpl::UnsubscribeFromInteriorVehicleDataOfType(
for (const auto& module : modules) {
cache_.Remove(module);
- auto unsubscribe_request = RCHelpers::CreateUnsubscribeRequestToHMI(
- module, app_mngr_.GetNextHMICorrelationID());
+ auto unsubscribe_request = RCHelpers::CreateGetInteriorVDRequestToHMI(
+ module,
+ app_mngr_.GetNextHMICorrelationID(),
+ RCHelpers::InteriorDataAction::UNSUBSCRIBE);
SDL_LOG_DEBUG("Send Unsubscribe from module type: "
<< module.first << " id: " << module.second);
rpc_service_.ManageHMICommand(unsubscribe_request);
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_app_extension.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_app_extension.cc
index 0f0c6c3ab1..3bfad3095b 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_app_extension.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_app_extension.cc
@@ -30,14 +30,51 @@
POSSIBILITY OF SUCH DAMAGE.
*/
-#include "rc_rpc_plugin/rc_app_extension.h"
#include <algorithm>
+
+#include "rc_rpc_plugin/rc_app_extension.h"
+
#include "rc_rpc_plugin/rc_module_constants.h"
+#include "rc_rpc_plugin/rc_rpc_plugin.h"
#include "smart_objects/smart_object.h"
+#include "utils/logger.h"
+
+SDL_CREATE_LOG_VARIABLE("RemoteControlModule")
+
+namespace {
+std::set<rc_rpc_plugin::ModuleUid> ConvertSmartObjectToModuleCollection(
+ const smart_objects::SmartObject& resumption_data) {
+ using namespace rc_rpc_plugin;
+
+ if (!resumption_data.keyExists(application_manager::hmi_interface::rc)) {
+ SDL_LOG_DEBUG("No resumption module data subscription to revert");
+ return {};
+ }
+
+ const auto& module_data =
+ resumption_data[application_manager::hmi_interface::rc]
+ [message_params::kModuleData];
+
+ std::set<rc_rpc_plugin::ModuleUid> module_collection;
+
+ if (!module_data.empty()) {
+ for (const auto& module : *(module_data.asArray())) {
+ const auto module_type = module[message_params::kModuleType].asString();
+ const auto module_id = module[message_params::kModuleId].asString();
+
+ module_collection.insert({module_type, module_id});
+ }
+ }
+
+ return module_collection;
+}
+} // namespace
namespace rc_rpc_plugin {
-RCAppExtension::RCAppExtension(application_manager::AppExtensionUID uid)
- : AppExtension(uid) {}
+RCAppExtension::RCAppExtension(application_manager::AppExtensionUID uid,
+ RCRPCPlugin& plugin,
+ application_manager::Application& application)
+ : AppExtension(uid), plugin_(plugin), application_(application) {}
void RCAppExtension::SubscribeToInteriorVehicleData(const ModuleUid& module) {
subscribed_interior_vehicle_data_.insert(module);
@@ -50,11 +87,19 @@ void RCAppExtension::UnsubscribeFromInteriorVehicleData(
void RCAppExtension::UnsubscribeFromInteriorVehicleDataOfType(
const std::string& module_type) {
+ bool unsubscribed = false;
for (auto& item : subscribed_interior_vehicle_data_) {
if (module_type == item.first) {
subscribed_interior_vehicle_data_.erase(item);
+ unsubscribed = true;
}
}
+
+ if (unsubscribed) {
+ // If didin't unsubscribe from some module type, we don't need to update
+ // application hash
+ UpdateHash();
+ }
}
void RCAppExtension::UnsubscribeFromInteriorVehicleData() {
@@ -81,18 +126,124 @@ bool RCAppExtension::IsSubscribedToInteriorVehicleData(
}
void RCAppExtension::SaveResumptionData(
- smart_objects::SmartObject& resumption_data) {}
+ smart_objects::SmartObject& resumption_data) {
+ SDL_LOG_AUTO_TRACE();
+
+ if (subscribed_interior_vehicle_data_.empty()) {
+ SDL_LOG_DEBUG("Subscribed modules data is absent");
+ return;
+ }
+
+ resumption_data[message_params::kModuleData] =
+ smart_objects::SmartObject(smart_objects::SmartType_Array);
+ auto& module_data = resumption_data[message_params::kModuleData];
+
+ uint32_t index = 0;
+ for (const auto& module_uid : subscribed_interior_vehicle_data_) {
+ SDL_LOG_DEBUG("Save module: [" << module_uid.first << ":"
+ << module_uid.second << "]");
+ auto module_info_so =
+ smart_objects::SmartObject(smart_objects::SmartType_Map);
+ module_info_so[message_params::kModuleType] = module_uid.first;
+ module_info_so[message_params::kModuleId] = module_uid.second;
+ module_data[index++] = module_info_so;
+ }
+}
void RCAppExtension::ProcessResumption(
- const smart_objects::SmartObject& saved_app) {}
+ const smart_objects::SmartObject& saved_app) {
+ SDL_LOG_AUTO_TRACE();
+ SDL_LOG_TRACE("app id : " << application_.app_id());
+
+ if (!saved_app.keyExists(
+ application_manager::strings::application_subscriptions)) {
+ SDL_LOG_DEBUG("application_subscriptions section does not exist");
+ return;
+ }
+
+ const auto& resumption_data =
+ saved_app[application_manager::strings::application_subscriptions];
+
+ if (!resumption_data.keyExists(message_params::kModuleData)) {
+ SDL_LOG_DEBUG("kModuleData section does not exist");
+ return;
+ }
+
+ auto& module_data = resumption_data[message_params::kModuleData];
+
+ if (0 == module_data.length()) {
+ SDL_LOG_WARN("Subscribed modules data is absent");
+ return;
+ }
+
+ for (const auto& module_so : *module_data.asArray()) {
+ const auto module_type = module_so[message_params::kModuleType].asString();
+ const auto module_id = module_so[message_params::kModuleId].asString();
+
+ ModuleUid module{module_type, module_id};
+ SDL_LOG_TRACE("app id " << application_.app_id() << " type : "
+ << module_type << " id <" << module_id);
+ AddPendingSubscription(module);
+ }
+
+ plugin_.ProcessResumptionSubscription(application_, *this);
+}
void RCAppExtension::RevertResumption(
- const smart_objects::SmartObject& subscriptions) {}
+ const smart_objects::SmartObject& resumption_data) {
+ SDL_LOG_AUTO_TRACE();
+
+ UnsubscribeFromInteriorVehicleData();
+
+ const auto module_subscriptions =
+ ConvertSmartObjectToModuleCollection(resumption_data);
+
+ for (auto& module : module_subscriptions) {
+ SDL_LOG_TRACE("Requested to unsubscribe module_type "
+ << module.first << "module_id: " << module.second);
+ }
+ std::set<rc_rpc_plugin::ModuleUid> to_be_unsubscribed;
+
+ const auto app_id = application_.app_id();
+ auto no_apps_subscribed = [app_id,
+ this](const rc_rpc_plugin::ModuleUid& module) {
+ if (plugin_.IsOtherAppsSubscribed(module, app_id)) {
+ SDL_LOG_DEBUG("Some other app except " << app_id
+ << " is already subscribed to "
+ << " module_type " << module.first
+ << "module_id: " << module.second);
+ return false;
+ }
+ return true;
+ };
+ std::copy_if(module_subscriptions.begin(),
+ module_subscriptions.end(),
+ std::inserter(to_be_unsubscribed, to_be_unsubscribed.end()),
+ no_apps_subscribed);
+
+ plugin_.RevertResumption(to_be_unsubscribed);
+}
std::set<ModuleUid> RCAppExtension::InteriorVehicleDataSubscriptions() const {
return subscribed_interior_vehicle_data_;
}
+bool RCAppExtension::AddPendingSubscription(const ModuleUid& module) {
+ return pending_subscriptions_.insert(module).second;
+}
+
+void RCAppExtension::RemovePendingSubscription(const ModuleUid& module) {
+ pending_subscriptions_.erase(module);
+}
+
+void RCAppExtension::RemovePendingSubscriptions() {
+ pending_subscriptions_.clear();
+}
+
+std::set<ModuleUid> RCAppExtension::PendingSubscriptions() {
+ return pending_subscriptions_;
+}
+
Grid RCAppExtension::GetUserLocation() const {
return user_location_;
}
@@ -113,5 +264,9 @@ void RCAppExtension::SetUserLocation(const Grid& grid) {
user_location_ = grid;
}
+void RCAppExtension::UpdateHash() {
+ application_.UpdateHash();
+}
+
RCAppExtension::~RCAppExtension() {}
} // namespace rc_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_helpers.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_helpers.cc
index dea7203717..768502832d 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_helpers.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_helpers.cc
@@ -182,8 +182,10 @@ RCAppExtensionPtr RCHelpers::GetRCExtension(
return extension;
}
-smart_objects::SmartObjectSPtr RCHelpers::CreateUnsubscribeRequestToHMI(
- const ModuleUid& module, const uint32_t correlation_id) {
+smart_objects::SmartObjectSPtr RCHelpers::CreateGetInteriorVDRequestToHMI(
+ const ModuleUid& module,
+ const uint32_t correlation_id,
+ const InteriorDataAction action) {
using namespace smart_objects;
namespace commands = application_manager::commands;
namespace am_strings = application_manager::strings;
@@ -200,7 +202,10 @@ smart_objects::SmartObjectSPtr RCHelpers::CreateUnsubscribeRequestToHMI(
params[am_strings::correlation_id] = correlation_id;
params[am_strings::function_id] =
hmi_apis::FunctionID::RC_GetInteriorVehicleData;
- msg_params[message_params::kSubscribe] = false;
+ if (NONE != action) {
+ msg_params[message_params::kSubscribe] =
+ (SUBSCRIBE == action) ? true : false;
+ }
msg_params[message_params::kModuleType] = module.first;
msg_params[message_params::kModuleId] = module.second;
return message;
@@ -362,4 +367,27 @@ smart_objects::SmartObject RCHelpers::MergeArray(
return result;
}
+bool RCHelpers::IsResponseSuccessful(
+ const smart_objects::SmartObject& response) {
+ hmi_apis::messageType::eType message_type =
+ static_cast<hmi_apis::messageType::eType>(
+ response[application_manager::strings::params]
+ [application_manager::strings::message_type]
+ .asInt());
+ const bool is_correct_message_type =
+ hmi_apis::messageType::response == message_type;
+
+ bool is_subscribe_successful = false;
+
+ if (response[application_manager::strings::msg_params].keyExists(
+ rc_rpc_plugin::message_params::kIsSubscribed)) {
+ is_subscribe_successful =
+ response[application_manager::strings::msg_params]
+ [rc_rpc_plugin::message_params::kIsSubscribed]
+ .asBool();
+ }
+
+ return is_correct_message_type && is_subscribe_successful;
+}
+
} // namespace rc_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_pending_resumption_handler.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_pending_resumption_handler.cc
new file mode 100644
index 0000000000..e66023f27a
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_pending_resumption_handler.cc
@@ -0,0 +1,343 @@
+#include "rc_rpc_plugin/rc_pending_resumption_handler.h"
+#include <sstream>
+#include "rc_rpc_plugin/rc_helpers.h"
+#include "rc_rpc_plugin/rc_module_constants.h"
+
+namespace rc_rpc_plugin {
+
+SDL_CREATE_LOG_VARIABLE("RemoteControlModule")
+
+RCPendingResumptionHandler::RCPendingResumptionHandler(
+ application_manager::ApplicationManager& application_manager,
+ InteriorDataCache& interior_data_cache)
+ : PendingResumptionHandler(application_manager)
+ , rpc_service_(application_manager.GetRPCService())
+ , interior_data_cache_(interior_data_cache) {}
+
+void RCPendingResumptionHandler::on_event(
+ const application_manager::event_engine::Event& event) {
+ SDL_LOG_AUTO_TRACE();
+ namespace am_strings = application_manager::strings;
+ sync_primitives::AutoLock lock(pending_resumption_lock_);
+ const auto cid = event.smart_object_correlation_id();
+ SDL_LOG_TRACE("Received event with function id: "
+ << event.id() << " and correlation id: " << cid);
+
+ const auto request_optional = GetPendingRequest(cid);
+ const auto app_id_optional = GetPendingApp(cid);
+ if (!request_optional) {
+ SDL_LOG_ERROR("Not waiting for message with correlation id: " << cid);
+ return;
+ }
+
+ auto current_request = *request_optional;
+ const auto app_id = *app_id_optional;
+ RemovePendingRequest(cid);
+ auto module_uid = GetModuleUid(current_request);
+
+ auto& response = event.smart_object();
+ if (RCHelpers::IsResponseSuccessful(response)) {
+ SDL_LOG_DEBUG("Resumption of subscriptions is successful"
+ << " module type: " << module_uid.first
+ << " module id: " << module_uid.second);
+
+ auto app = application_manager_.application(app_id);
+ if (app) {
+ auto rc_app_extension = RCHelpers::GetRCExtension(*app);
+ rc_app_extension->SubscribeToInteriorVehicleData(module_uid);
+ }
+
+ if (response[am_strings::msg_params].keyExists(
+ message_params::kModuleData)) {
+ const auto module_data =
+ response[am_strings::msg_params][message_params::kModuleData];
+ const auto& data_mapping = RCHelpers::GetModuleTypeToDataMapping();
+ if (module_data.keyExists(data_mapping(module_uid.first))) {
+ const auto control_data = module_data[data_mapping(module_uid.first)];
+ interior_data_cache_.Add(module_uid, control_data);
+ }
+ }
+
+ HandleSuccessfulResponse(event, module_uid);
+ } else {
+ SDL_LOG_DEBUG("Resumption of subscriptions is NOT successful"
+ << " module type: " << module_uid.first
+ << " module id: " << module_uid.second);
+
+ ProcessNextPausedResumption(module_uid);
+ }
+}
+
+template <typename RCModulesCollection>
+std::string Stringify(RCModulesCollection& collection) {
+ std::stringstream ss;
+ for (const auto& module : collection) {
+ ss << "{type : " << module.first << " id " << module.second << "} ";
+ }
+ return ss.str();
+}
+
+void RCPendingResumptionHandler::HandleResumptionSubscriptionRequest(
+ application_manager::AppExtension& extension,
+ application_manager::Application& app) {
+ UNUSED(extension);
+ SDL_LOG_AUTO_TRACE();
+ sync_primitives::AutoLock lock(pending_resumption_lock_);
+
+ auto rc_extension = RCHelpers::GetRCExtension(app);
+ auto subscriptions = rc_extension->PendingSubscriptions();
+ rc_extension->RemovePendingSubscriptions();
+ SDL_LOG_TRACE("app id " << app.app_id() << " " << Stringify(subscriptions));
+
+ std::vector<ModuleUid> ignored;
+ std::vector<ModuleUid> already_pending;
+ std::vector<ModuleUid> need_to_subscribe;
+ for (const auto& subscription : subscriptions) {
+ bool is_another_app_subscribed =
+ IsOtherAppsSubscribed(app.app_id(), subscription);
+ bool is_pending_response = IsPendingForResponse(subscription);
+ if (is_another_app_subscribed && !is_pending_response) {
+ rc_extension->SubscribeToInteriorVehicleData(subscription);
+ ignored.push_back(subscription);
+ } else if (is_pending_response) {
+ already_pending.push_back(subscription);
+ } else {
+ need_to_subscribe.push_back(subscription);
+ }
+ }
+ SDL_LOG_TRACE("ignored: " << Stringify(ignored));
+ SDL_LOG_TRACE("already_pending: " << Stringify(already_pending));
+ SDL_LOG_TRACE("need_to_subscribe: " << Stringify(need_to_subscribe));
+
+ for (auto subscription : already_pending) {
+ const auto cid = application_manager_.GetNextHMICorrelationID();
+ const auto subscription_request =
+ CreateSubscriptionRequest(subscription, cid);
+ const auto fid = GetFunctionId(*subscription_request);
+ paused_resumptions_[subscription].push(
+ {app.app_id(), *subscription_request});
+ const auto resumption_request =
+ MakeResumptionRequest(cid, fid, *subscription_request);
+ resumption_data_processor().SubscribeToResponse(app.app_id(),
+ resumption_request);
+ SDL_LOG_DEBUG("Paused request with correlation_id: "
+ << cid << " module type: " << subscription.first
+ << " module id: " << subscription.second);
+ }
+
+ for (auto module : need_to_subscribe) {
+ const auto cid = application_manager_.GetNextHMICorrelationID();
+ const auto subscription_request = CreateSubscriptionRequest(module, cid);
+ const auto fid = GetFunctionId(*subscription_request);
+ const auto resumption_request =
+ MakeResumptionRequest(cid, fid, *subscription_request);
+ AddPendingRequest(app.app_id(), *subscription_request);
+ subscribe_on_event(fid, cid);
+ resumption_data_processor().SubscribeToResponse(app.app_id(),
+ resumption_request);
+ SDL_LOG_DEBUG("Sending request with correlation id: "
+ << cid << " module type: " << module.first
+ << " module id: " << module.second);
+ application_manager_.GetRPCService().ManageHMICommand(subscription_request);
+ }
+}
+
+void RCPendingResumptionHandler::OnResumptionRevert() {
+ SDL_LOG_AUTO_TRACE();
+}
+
+void RCPendingResumptionHandler::HandleSuccessfulResponse(
+ const application_manager::event_engine::Event& event,
+ const ModuleUid& module_uid) {
+ SDL_LOG_AUTO_TRACE();
+
+ auto& response = event.smart_object();
+ auto cid = event.smart_object_correlation_id();
+
+ const auto& it = paused_resumptions_.find(module_uid);
+ if (it != paused_resumptions_.end()) {
+ SDL_LOG_DEBUG("Paused resumptions found");
+ auto& queue_paused = it->second;
+ while (!queue_paused.empty()) {
+ const auto& resumption_request = queue_paused.front();
+ cid = resumption_request.correlation_id();
+ RaiseEventForResponse(response, cid);
+ auto app = application_manager_.application(resumption_request.app_id);
+ if (app) {
+ auto rc_app_extension = RCHelpers::GetRCExtension(*app);
+ rc_app_extension->SubscribeToInteriorVehicleData(module_uid);
+ }
+ queue_paused.pop();
+ }
+ paused_resumptions_.erase(it);
+ }
+}
+
+void RCPendingResumptionHandler::ProcessNextPausedResumption(
+ const ModuleUid& module_uid) {
+ SDL_LOG_AUTO_TRACE();
+
+ auto pop_front_paused_resumptions = [this](const ModuleUid& module_uid) {
+ const auto& it = paused_resumptions_.find(module_uid);
+ if (it == paused_resumptions_.end()) {
+ return std::shared_ptr<PendingRequestQueue::value_type>(nullptr);
+ }
+ auto& queue_paused = it->second;
+ if (queue_paused.empty()) {
+ paused_resumptions_.erase(it);
+ return std::shared_ptr<PendingRequestQueue::value_type>(nullptr);
+ }
+ auto paused_resumption =
+ std::make_shared<PendingRequestQueue::value_type>(queue_paused.front());
+ queue_paused.pop();
+ if (queue_paused.empty()) {
+ paused_resumptions_.erase(it);
+ }
+ return paused_resumption;
+ };
+
+ auto paused_resumption = pop_front_paused_resumptions(module_uid);
+ if (!paused_resumption) {
+ SDL_LOG_DEBUG("No paused resumptions found");
+ return;
+ }
+
+ auto& resumption_request = *paused_resumption;
+ auto subscription_request =
+ std::make_shared<smart_objects::SmartObject>(resumption_request.message);
+ const auto fid = GetFunctionId(*subscription_request);
+ const auto cid =
+ resumption_request
+ .message[app_mngr::strings::params][app_mngr::strings::correlation_id]
+ .asInt();
+ subscribe_on_event(fid, cid);
+ AddPendingRequest(resumption_request.app_id, *subscription_request);
+ SDL_LOG_DEBUG("Sending request with correlation id: "
+ << cid << " module type: " << module_uid.first
+ << " module id: " << module_uid.second);
+ application_manager_.GetRPCService().ManageHMICommand(subscription_request);
+}
+
+void RCPendingResumptionHandler::RaiseEventForResponse(
+ const smart_objects::SmartObject& subscription_response,
+ const uint32_t correlation_id) const {
+ smart_objects::SmartObject event_message = subscription_response;
+ event_message[app_mngr::strings::params][app_mngr::strings::correlation_id] =
+ correlation_id;
+
+ app_mngr::event_engine::Event event(
+ hmi_apis::FunctionID::RC_GetInteriorVehicleData);
+ event.set_smart_object(event_message);
+ event.raise(application_manager_.event_dispatcher());
+}
+
+bool RCPendingResumptionHandler::IsPendingForResponse(
+ const ModuleUid& module_uid) const {
+ auto is_module_exists = [&module_uid](const PendingRequest& pending) {
+ return module_uid == GetModuleUid(pending.message);
+ };
+ auto it = std::find_if(
+ pending_requests_.begin(), pending_requests_.end(), is_module_exists);
+ return it != pending_requests_.end();
+}
+
+bool RCPendingResumptionHandler::IsOtherAppsSubscribed(
+ const uint32_t app_id, const ModuleUid& module_uid) const {
+ auto get_subscriptions = [](application_manager::ApplicationSharedPtr app) {
+ std::set<ModuleUid> result;
+ auto rc_app_extension = RCHelpers::GetRCExtension(*app);
+ if (rc_app_extension) {
+ result = rc_app_extension->InteriorVehicleDataSubscriptions();
+ }
+ return result;
+ };
+
+ auto app_subscribed = [module_uid, &get_subscriptions](
+ application_manager::ApplicationSharedPtr app) {
+ auto subscriptions = get_subscriptions(app);
+ auto it = subscriptions.find(module_uid);
+ return subscriptions.end() != it;
+ };
+
+ std::set<uint32_t> subscribed_apps;
+ for (auto& app : application_manager_.applications().GetData()) {
+ if (app_subscribed(app)) {
+ SDL_LOG_DEBUG("APP " << app->app_id() << " subscribed "
+ << module_uid.first << " " << module_uid.second);
+ subscribed_apps.insert(app->app_id());
+ }
+ }
+
+ subscribed_apps.erase(app_id);
+ return !subscribed_apps.empty();
+}
+
+utils::Optional<smart_objects::SmartObject>
+RCPendingResumptionHandler::GetPendingRequest(const uint32_t corr_id) {
+ auto corr_id_match = [corr_id](const PendingRequest& item) {
+ return corr_id == item.correlation_id();
+ };
+ auto it = std::find_if(
+ pending_requests_.begin(), pending_requests_.end(), corr_id_match);
+ if (it == pending_requests_.end()) {
+ return utils::Optional<smart_objects::SmartObject>::EMPTY;
+ }
+ return it->message;
+}
+
+utils::Optional<uint32_t> RCPendingResumptionHandler::GetPendingApp(
+ const uint32_t corr_id) {
+ auto corr_id_match = [corr_id](const PendingRequest& item) {
+ return corr_id == item.correlation_id();
+ };
+ auto it = std::find_if(
+ pending_requests_.begin(), pending_requests_.end(), corr_id_match);
+ if (it == pending_requests_.end()) {
+ return utils::Optional<uint32_t>::EMPTY;
+ }
+ return it->app_id;
+}
+
+void RCPendingResumptionHandler::RemovePendingRequest(const uint32_t corr_id) {
+ auto corr_id_match = [corr_id](const PendingRequest& item) {
+ return corr_id == item.correlation_id();
+ };
+ const auto it = std::find_if(
+ pending_requests_.begin(), pending_requests_.end(), corr_id_match);
+ if (it == pending_requests_.end()) {
+ SDL_LOG_WARN("Pending request with corr_id " << corr_id << " not found");
+ return;
+ }
+ pending_requests_.erase(it);
+}
+
+void RCPendingResumptionHandler::AddPendingRequest(
+ const uint32_t app_id, const smart_objects::SmartObject request_so) {
+ pending_requests_.push_back({app_id, request_so});
+}
+
+smart_objects::SmartObjectSPtr
+RCPendingResumptionHandler::CreateSubscriptionRequest(
+ const ModuleUid& module, const uint32_t correlation_id) {
+ return RCHelpers::CreateGetInteriorVDRequestToHMI(
+ module, correlation_id, RCHelpers::InteriorDataAction::SUBSCRIBE);
+}
+
+hmi_apis::FunctionID::eType RCPendingResumptionHandler::GetFunctionId(
+ const smart_objects::SmartObject& subscription_request) {
+ const auto function_id = static_cast<hmi_apis::FunctionID::eType>(
+ subscription_request[app_mngr::strings::params]
+ [app_mngr::strings::function_id]
+ .asInt());
+ return function_id;
+}
+
+ModuleUid RCPendingResumptionHandler::GetModuleUid(
+ const smart_objects::SmartObject& subscription_request) {
+ const smart_objects::SmartObject& msg_params =
+ subscription_request[app_mngr::strings::msg_params];
+ return ModuleUid(msg_params[message_params::kModuleType].asString(),
+ msg_params[message_params::kModuleId].asString());
+}
+
+} // namespace rc_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_rpc_plugin.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_rpc_plugin.cc
index 6e9a751bb6..4345aa044a 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_rpc_plugin.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_rpc_plugin.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2018, Ford Motor Company
+ Copyright (c) 2020, Ford Motor Company
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@
#include "rc_rpc_plugin/rc_command_factory.h"
#include "rc_rpc_plugin/rc_consent_manager_impl.h"
#include "rc_rpc_plugin/rc_helpers.h"
+#include "rc_rpc_plugin/rc_pending_resumption_handler.h"
#include "rc_rpc_plugin/resource_allocation_manager_impl.h"
#include "utils/helpers.h"
@@ -76,6 +77,8 @@ bool RCRPCPlugin::Init(
command_factory_.reset(new rc_rpc_plugin::RCCommandFactory(params));
rpc_service_ = &rpc_service;
app_mngr_ = &app_manager;
+ pending_resumption_handler_ = std::make_shared<RCPendingResumptionHandler>(
+ app_manager, *(interior_data_cache_.get()));
// Check all saved consents and remove expired
rc_consent_manager_->RemoveExpiredConsents();
@@ -124,9 +127,9 @@ void RCRPCPlugin::OnApplicationEvent(
}
switch (event) {
case plugins::kApplicationRegistered: {
- auto extension =
- std::shared_ptr<RCAppExtension>(new RCAppExtension(kRCPluginID));
- application->AddExtension(extension);
+ auto extension = std::shared_ptr<RCAppExtension>(
+ new RCAppExtension(kRCPluginID, *this, *application));
+ DCHECK_OR_RETURN_VOID(application->AddExtension(extension));
const auto driver_location =
rc_capabilities_manager_
->GetDriverLocationFromSeatLocationCapability();
@@ -159,6 +162,49 @@ void RCRPCPlugin::OnApplicationEvent(
}
}
+void RCRPCPlugin::ProcessResumptionSubscription(
+ application_manager::Application& app, RCAppExtension& ext) {
+ SDL_LOG_AUTO_TRACE();
+
+ pending_resumption_handler_->HandleResumptionSubscriptionRequest(ext, app);
+}
+
+void RCRPCPlugin::RevertResumption(const std::set<ModuleUid>& subscriptions) {
+ SDL_LOG_AUTO_TRACE();
+
+ interior_data_manager_->OnResumptionRevert(subscriptions);
+ pending_resumption_handler_->OnResumptionRevert();
+}
+
+bool RCRPCPlugin::IsOtherAppsSubscribed(const rc_rpc_types::ModuleUid& module,
+ const uint32_t app_id) {
+ auto get_subscriptions = [](application_manager::ApplicationSharedPtr app) {
+ std::set<ModuleUid> result;
+ auto rc_app_extension = RCHelpers::GetRCExtension(*app);
+ if (rc_app_extension) {
+ result = rc_app_extension->InteriorVehicleDataSubscriptions();
+ }
+ return result;
+ };
+
+ auto another_app_subscribed =
+ [app_id, module, &get_subscriptions](
+ application_manager::ApplicationSharedPtr app) {
+ if (app_id == app->app_id()) {
+ return false;
+ }
+ auto subscriptions = get_subscriptions(app);
+ auto it = subscriptions.find(module);
+ return subscriptions.end() != it;
+ };
+
+ auto accessor = app_mngr_->applications();
+ auto it = std::find_if(accessor.GetData().begin(),
+ accessor.GetData().end(),
+ another_app_subscribed);
+ return accessor.GetData().end() != it;
+}
+
RCRPCPlugin::Apps RCRPCPlugin::GetRCApplications(
application_manager::ApplicationManager& app_mngr) {
using application_manager::ApplicationSet;
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/CMakeLists.txt b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/CMakeLists.txt
index bd46bdf11f..16e95bf599 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/CMakeLists.txt
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/CMakeLists.txt
@@ -45,6 +45,9 @@ ${CMAKE_CURRENT_SOURCE_DIR}/interior_data_cache_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/rc_consent_manager_impl_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/grid_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/rc_helpers_test.cc
+${CMAKE_CURRENT_SOURCE_DIR}/rc_app_extension_test.cc
+${CMAKE_CURRENT_SOURCE_DIR}/rc_pending_resumption_handler_test.cc
+${COMPONENTS_DIR}/application_manager/test/mock_message_helper.cc
)
set(RC_COMMANDS_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/commands)
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/button_press_request_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/button_press_request_test.cc
index 625b2d6312..6c0962a557 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/button_press_request_test.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/button_press_request_test.cc
@@ -82,15 +82,15 @@ class ButtonPressRequestTest
: rc_capabilities_(std::make_shared<smart_objects::SmartObject>(
smart_objects::SmartType_Map))
, mock_app_(std::make_shared<NiceMock<MockApplication> >())
- , rc_app_extention_(
- std::make_shared<rc_rpc_plugin::RCAppExtension>(kModuleId)) {}
+ , rc_app_extension_(std::make_shared<rc_rpc_plugin::RCAppExtension>(
+ kModuleId, rc_plugin_, *mock_app_)) {}
void SetUp() OVERRIDE {
smart_objects::SmartObject control_caps((smart_objects::SmartType_Array));
(*rc_capabilities_)[strings::kradioControlCapabilities] = control_caps;
ON_CALL(app_mngr_, application(_)).WillByDefault(Return(mock_app_));
ON_CALL(*mock_app_, QueryInterface(RCRPCPlugin::kRCPluginID))
- .WillByDefault(Return(rc_app_extention_));
+ .WillByDefault(Return(rc_app_extension_));
ON_CALL(app_mngr_, GetPolicyHandler())
.WillByDefault(ReturnRef(mock_policy_handler_));
ON_CALL(app_mngr_, hmi_capabilities())
@@ -143,7 +143,8 @@ class ButtonPressRequestTest
protected:
smart_objects::SmartObjectSPtr rc_capabilities_;
std::shared_ptr<MockApplication> mock_app_;
- std::shared_ptr<rc_rpc_plugin::RCAppExtension> rc_app_extention_;
+ RCRPCPlugin rc_plugin_;
+ std::shared_ptr<rc_rpc_plugin::RCAppExtension> rc_app_extension_;
test::components::policy_test::MockPolicyHandlerInterface
mock_policy_handler_;
testing::NiceMock<rc_rpc_plugin_test::MockResourceAllocationManager>
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/get_interior_vehicle_data_request_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/get_interior_vehicle_data_request_test.cc
index 82b71f1be4..956a53994d 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/get_interior_vehicle_data_request_test.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/get_interior_vehicle_data_request_test.cc
@@ -92,8 +92,10 @@ class GetInteriorVehicleDataRequestTest
GetInteriorVehicleDataRequestTest()
: mock_app_(std::make_shared<NiceMock<MockApplication> >())
, mock_app2_(std::make_shared<NiceMock<MockApplication> >())
- , rc_app_extention_(std::make_shared<RCAppExtension>(kModuleId))
- , rc_app_extention2_(std::make_shared<RCAppExtension>(kModuleId))
+ , rc_app_extension_(
+ std::make_shared<RCAppExtension>(kModuleId, rc_plugin_, *mock_app_))
+ , rc_app_extension2_(std::make_shared<RCAppExtension>(
+ kModuleId, rc_plugin_, *mock_app2_))
, apps_lock_(std::make_shared<sync_primitives::Lock>())
, apps_da_(apps_, apps_lock_)
, rc_capabilities_(std::make_shared<smart_objects::SmartObject>(
@@ -105,9 +107,9 @@ class GetInteriorVehicleDataRequestTest
ON_CALL(*mock_app2_, is_remote_control_supported())
.WillByDefault(Return(true));
ON_CALL(*mock_app_, QueryInterface(_))
- .WillByDefault(Return(rc_app_extention_));
+ .WillByDefault(Return(rc_app_extension_));
ON_CALL(*mock_app2_, QueryInterface(_))
- .WillByDefault(Return(rc_app_extention2_));
+ .WillByDefault(Return(rc_app_extension2_));
}
/**
@@ -183,8 +185,9 @@ class GetInteriorVehicleDataRequestTest
protected:
std::shared_ptr<MockApplication> mock_app_;
std::shared_ptr<MockApplication> mock_app2_;
- std::shared_ptr<RCAppExtension> rc_app_extention_;
- std::shared_ptr<RCAppExtension> rc_app_extention2_;
+ RCRPCPlugin rc_plugin_;
+ std::shared_ptr<RCAppExtension> rc_app_extension_;
+ std::shared_ptr<RCAppExtension> rc_app_extension2_;
testing::NiceMock<rc_rpc_plugin_test::MockResourceAllocationManager>
mock_allocation_manager_;
testing::NiceMock<rc_rpc_plugin_test::MockInteriorDataCache>
@@ -264,7 +267,7 @@ TEST_F(
Execute_ExpectMessageNotSentToHMI_SuccessSentToMobile_AppSubscribed_DataFromCache) {
// Arrange
const ModuleUid module(module_type, module_id);
- rc_app_extention_->SubscribeToInteriorVehicleData(module);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module);
MessageSharedPtr mobile_message = CreateBasicMessage();
(*mobile_message)[application_manager::strings::msg_params]
[message_params::kModuleType] = module_eType;
@@ -313,6 +316,51 @@ TEST_F(
TEST_F(
GetInteriorVehicleDataRequestTest,
+ Execute_ExpectMessageNotSentToHMI_DoubleSubscription_WarningsSentToMobile) {
+ // Arrange
+ const ModuleUid module(module_type, module_id);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module);
+ MessageSharedPtr mobile_message = CreateBasicMessage();
+ (*mobile_message)[application_manager::strings::msg_params]
+ [message_params::kModuleType] = module_eType;
+ (*mobile_message)[application_manager::strings::msg_params]
+ [message_params::kModuleId] = module_id;
+ (*mobile_message)[application_manager::strings::msg_params]
+ [message_params::kSubscribe] = true;
+
+ auto command =
+ CreateRCCommand<rc_rpc_plugin::commands::GetInteriorVehicleDataRequest>(
+ mobile_message);
+
+ // Expectations
+ EXPECT_CALL(mock_interior_data_cache_, Contains(module))
+ .WillOnce(Return(true));
+
+ smart_objects::SmartObject radio_data;
+ radio_data[message_params::kBand] = enums_value::kAM;
+ EXPECT_CALL(mock_interior_data_cache_, Retrieve(module))
+ .WillOnce(Return(radio_data));
+
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(_, _)).Times(0);
+ MessageSharedPtr command_result;
+ EXPECT_CALL(
+ mock_rpc_service_,
+ ManageMobileCommand(MobileResultCodeIs(mobile_apis::Result::WARNINGS), _))
+ .WillOnce(DoAll(SaveArg<0>(&command_result), Return(true)));
+
+ // Act
+ ASSERT_TRUE(command->Init());
+ command->Run();
+
+ // Assert
+ EXPECT_EQ((*command_result)[application_manager::strings::msg_params]
+ [message_params::kModuleData]
+ [message_params::kRadioControlData],
+ radio_data);
+}
+
+TEST_F(
+ GetInteriorVehicleDataRequestTest,
Execute_ExpectCorrectMessageSentToHMI_LastAppSubscribedUnsubscribe_ClearCache) {
// Arrange
MessageSharedPtr mobile_message = CreateBasicMessage();
@@ -335,7 +383,7 @@ TEST_F(
module_id;
apps_.insert(mock_app_);
- rc_app_extention_->SubscribeToInteriorVehicleData(module);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module);
ON_CALL(app_mngr_, applications()).WillByDefault(Return(apps_da_));
ON_CALL(mock_interior_data_manager_, CheckRequestsToHMIFrequency(_))
.WillByDefault(Return(true));
@@ -379,8 +427,8 @@ TEST_F(GetInteriorVehicleDataRequestTest,
apps_.insert(mock_app_);
apps_.insert(mock_app2_);
- rc_app_extention_->SubscribeToInteriorVehicleData(module);
- rc_app_extention2_->SubscribeToInteriorVehicleData(module);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module);
+ rc_app_extension2_->SubscribeToInteriorVehicleData(module);
smart_objects::SmartObject radio_data;
radio_data[message_params::kBand] = enums_value::kAM;
@@ -408,7 +456,7 @@ TEST_F(GetInteriorVehicleDataRequestTest,
command->Run();
// Assert
- EXPECT_FALSE(rc_app_extention_->IsSubscribedToInteriorVehicleDataOfType(
+ EXPECT_FALSE(rc_app_extension_->IsSubscribedToInteriorVehicleDataOfType(
enums_value::kRadio));
EXPECT_EQ((*command_result)[application_manager::strings::msg_params]
[message_params::kModuleData]
@@ -571,7 +619,7 @@ TEST_F(GetInteriorVehicleDataRequestTest,
hmi_msg_params[application_manager::strings::connection_key] = kConnectionKey;
apps_.insert(mock_app_);
- rc_app_extention_->SubscribeToInteriorVehicleData(module);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module);
ON_CALL(app_mngr_, applications()).WillByDefault(Return(apps_da_));
ON_CALL(mock_interior_data_manager_, CheckRequestsToHMIFrequency(_))
.WillByDefault(Return(true));
@@ -601,13 +649,13 @@ TEST_F(GetInteriorVehicleDataRequestTest,
command->on_event(event);
// Assert
- EXPECT_TRUE(rc_app_extention_->IsSubscribedToInteriorVehicleData(module));
+ EXPECT_TRUE(rc_app_extension_->IsSubscribedToInteriorVehicleData(module));
}
TEST_F(GetInteriorVehicleDataRequestTest,
Execute_ExpectRejectDuToRequestLimitation_NoCahce) {
// Arrange
- rc_app_extention_->UnsubscribeFromInteriorVehicleDataOfType(
+ rc_app_extension_->UnsubscribeFromInteriorVehicleDataOfType(
enums_value::kRadio);
MessageSharedPtr mobile_message = CreateBasicMessage();
(*mobile_message)[application_manager::strings::msg_params]
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/on_interior_vehicle_data_notification_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/on_interior_vehicle_data_notification_test.cc
index d6771c534d..6c7a7ba67e 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/on_interior_vehicle_data_notification_test.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/on_interior_vehicle_data_notification_test.cc
@@ -74,14 +74,15 @@ class OnInteriorVehicleDataNotificationTest
public:
OnInteriorVehicleDataNotificationTest()
: mock_app_(std::make_shared<NiceMock<MockApplication> >())
- , rc_app_extention_(std::make_shared<RCAppExtension>(kModuleId))
+ , rc_app_extension_(
+ std::make_shared<RCAppExtension>(kModuleId, rc_plugin_, *mock_app_))
, apps_lock_(std::make_shared<sync_primitives::Lock>())
, apps_da_(apps_, apps_lock_) {
ON_CALL(*mock_app_, app_id()).WillByDefault(Return(kAppId));
ON_CALL(*mock_app_, is_remote_control_supported())
.WillByDefault(Return(true));
ON_CALL(*mock_app_, QueryInterface(_))
- .WillByDefault(Return(rc_app_extention_));
+ .WillByDefault(Return(rc_app_extension_));
}
MessageSharedPtr CreateBasicMessage() {
@@ -120,7 +121,8 @@ class OnInteriorVehicleDataNotificationTest
protected:
std::shared_ptr<MockApplication> mock_app_;
- std::shared_ptr<RCAppExtension> rc_app_extention_;
+ RCRPCPlugin rc_plugin_;
+ std::shared_ptr<RCAppExtension> rc_app_extension_;
testing::NiceMock<rc_rpc_plugin_test::MockResourceAllocationManager>
mock_allocation_manager_;
testing::NiceMock<rc_rpc_plugin_test::MockInteriorDataCache>
@@ -141,7 +143,7 @@ TEST_F(OnInteriorVehicleDataNotificationTest,
MessageSharedPtr mobile_message = CreateBasicMessage();
apps_.insert(mock_app_);
const ModuleUid module(module_type, module_id);
- rc_app_extention_->SubscribeToInteriorVehicleData(module);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module);
ON_CALL(app_mngr_, applications()).WillByDefault(Return(apps_da_));
// Expectations
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/rc_get_interior_vehicle_data_consent_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/rc_get_interior_vehicle_data_consent_test.cc
index e5f96215eb..8fbaeda2f2 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/rc_get_interior_vehicle_data_consent_test.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/rc_get_interior_vehicle_data_consent_test.cc
@@ -119,7 +119,8 @@ class RCGetInteriorVehicleDataConsentTest
rpc_protection_manager_,
hmi_so_factory_,
mobile_so_factoy_)
- , rc_app_extention_(std::make_shared<RCAppExtension>(kPluginID))
+ , rc_app_extension_(
+ std::make_shared<RCAppExtension>(kPluginID, rc_plugin_, *mock_app_))
, mock_rpc_plugin_manager(
std::make_shared<NiceMock<MockRPCPluginManager> >())
, rpc_plugin(mock_rpc_plugin)
@@ -136,7 +137,7 @@ class RCGetInteriorVehicleDataConsentTest
InterfaceState::STATE_AVAILABLE));
ON_CALL(app_mngr_, application(kAppId)).WillByDefault(Return(mock_app_));
ON_CALL(*mock_app_, QueryInterface(RCRPCPlugin::kRCPluginID))
- .WillByDefault(Return(rc_app_extention_));
+ .WillByDefault(Return(rc_app_extension_));
testing::NiceMock<rc_rpc_plugin_test::MockInteriorDataCache>
mock_interior_data_cache_;
ON_CALL(app_mngr_, GetPolicyHandler())
@@ -217,7 +218,8 @@ class RCGetInteriorVehicleDataConsentTest
std::shared_ptr<application_manager::MockRPCProtectionManager>
rpc_protection_manager_;
am::rpc_service::RPCServiceImpl rpc_service_;
- std::shared_ptr<RCAppExtension> rc_app_extention_;
+ RCRPCPlugin rc_plugin_;
+ std::shared_ptr<RCAppExtension> rc_app_extension_;
std::shared_ptr<am::plugin_manager::MockRPCPluginManager>
mock_rpc_plugin_manager;
utils::Optional<RPCPlugin> rpc_plugin;
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/set_interior_vehicle_data_request_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/set_interior_vehicle_data_request_test.cc
index 1e4da625b2..9b06ddb137 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/set_interior_vehicle_data_request_test.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/commands/set_interior_vehicle_data_request_test.cc
@@ -73,7 +73,8 @@ class SetInteriorVehicleDataRequestTest
public:
SetInteriorVehicleDataRequestTest()
: mock_app_(std::make_shared<NiceMock<MockApplication> >())
- , rc_app_extention_(std::make_shared<RCAppExtension>(kModuleId))
+ , rc_app_extension_(
+ std::make_shared<RCAppExtension>(kModuleId, rc_plugin_, *mock_app_))
, rc_capabilities_(std::make_shared<smart_objects::SmartObject>(
smart_objects::SmartType::SmartType_Array)) {}
@@ -89,7 +90,7 @@ class SetInteriorVehicleDataRequestTest
InterfaceState::STATE_AVAILABLE));
ON_CALL(app_mngr_, application(kAppId)).WillByDefault(Return(mock_app_));
ON_CALL(*mock_app_, QueryInterface(RCRPCPlugin::kRCPluginID))
- .WillByDefault(Return(rc_app_extention_));
+ .WillByDefault(Return(rc_app_extension_));
ON_CALL(*mock_app_, policy_app_id()).WillByDefault(Return(kPolicyAppId));
ON_CALL(mock_allocation_manager_, IsResourceFree(_, _))
@@ -148,7 +149,8 @@ class SetInteriorVehicleDataRequestTest
testing::NiceMock<rc_rpc_plugin_test::MockInteriorDataManager>
mock_interior_data_manager_;
std::shared_ptr<MockApplication> mock_app_;
- std::shared_ptr<RCAppExtension> rc_app_extention_;
+ RCRPCPlugin rc_plugin_;
+ std::shared_ptr<RCAppExtension> rc_app_extension_;
testing::NiceMock<rc_rpc_plugin_test::MockRCCapabilitiesManager>
mock_rc_capabilities_manager_;
smart_objects::SmartObjectSPtr rc_capabilities_;
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/include/rc_rpc_plugin/mock/mock_interior_data_manager.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/include/rc_rpc_plugin/mock/mock_interior_data_manager.h
index 231ac2ae36..3e64bb541f 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/include/rc_rpc_plugin/mock/mock_interior_data_manager.h
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/include/rc_rpc_plugin/mock/mock_interior_data_manager.h
@@ -49,6 +49,8 @@ class MockInteriorDataManager : public rc_rpc_plugin::InteriorDataManager {
MOCK_METHOD1(StoreRequestToHMITime, void(const rc_rpc_plugin::ModuleUid&));
MOCK_METHOD1(CheckRequestsToHMIFrequency,
bool(const rc_rpc_plugin::ModuleUid&));
+ MOCK_METHOD1(OnResumptionRevert,
+ void(const std::set<rc_rpc_plugin::ModuleUid>& subscriptions));
};
} // namespace rc_rpc_plugin_test
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/include/rc_rpc_plugin/mock/mock_rc_helpers.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/include/rc_rpc_plugin/mock/mock_rc_helpers.h
index c73472d2a8..751291c8e2 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/include/rc_rpc_plugin/mock/mock_rc_helpers.h
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/include/rc_rpc_plugin/mock/mock_rc_helpers.h
@@ -54,9 +54,11 @@ class MockRCHelpers {
MOCK_METHOD1(
GetRCExtension,
rc_rpc_plugin::RCAppExtensionPtr(application_manager::Application&));
- MOCK_METHOD2(CreateUnsubscribeRequestToHMI,
- smart_objects::SmartObjectSPtr(const rc_rpc_plugin::ModuleUid&,
- const uint32_t));
+ MOCK_METHOD3(CreateGetInteriorVDRequestToHMI,
+ smart_objects::SmartObjectSPtr(
+ const rc_rpc_plugin::ModuleUid&,
+ const uint32_t,
+ const RCHelpers::InteriorDataAction action));
MOCK_METHOD2(AppsSubscribedToModule,
std::vector<application_manager::ApplicationSharedPtr>(
application_manager::ApplicationManager&,
@@ -89,6 +91,9 @@ class MockRCHelpers {
smart_objects::SmartObject(const smart_objects::SmartObject& data1,
const smart_objects::SmartObject& data2));
+ MOCK_METHOD1(IsResponseSuccessful,
+ bool(const smart_objects::SmartObject& response));
+
static MockRCHelpers* rc_helpers_mock();
};
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/mock_rc_helpers.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/mock_rc_helpers.cc
index 3e60591c6b..2f5fed9971 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/mock_rc_helpers.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/mock_rc_helpers.cc
@@ -60,10 +60,12 @@ rc_rpc_plugin::RCAppExtensionPtr rc_rpc_plugin::RCHelpers::GetRCExtension(
}
smart_objects::SmartObjectSPtr
-rc_rpc_plugin::RCHelpers::CreateUnsubscribeRequestToHMI(
- const ModuleUid& module, const uint32_t correlation_id) {
- return MockRCHelpers::rc_helpers_mock()->CreateUnsubscribeRequestToHMI(
- module, correlation_id);
+rc_rpc_plugin::RCHelpers::CreateGetInteriorVDRequestToHMI(
+ const ModuleUid& module,
+ const uint32_t correlation_id,
+ const RCHelpers::InteriorDataAction action) {
+ return MockRCHelpers::rc_helpers_mock()->CreateGetInteriorVDRequestToHMI(
+ module, correlation_id, action);
}
std::vector<application_manager::ApplicationSharedPtr>
@@ -130,6 +132,11 @@ void RCHelpers::RemoveRedundantGPSDataFromIVDataMsg(
msg_params);
}
+bool RCHelpers::IsResponseSuccessful(
+ const smart_objects::SmartObject& response) {
+ return MockRCHelpers::rc_helpers_mock()->IsResponseSuccessful(response);
+}
+
MockRCHelpers* MockRCHelpers::rc_helpers_mock() {
static ::testing::NiceMock<MockRCHelpers> mock_rc_helpers;
return &mock_rc_helpers;
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_app_extension_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_app_extension_test.cc
new file mode 100644
index 0000000000..60c3fb9135
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_app_extension_test.cc
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "rc_rpc_plugin/rc_app_extension.h"
+
+#include <memory>
+#include <string>
+
+#include "application_manager/mock_application.h"
+#include "gtest/gtest.h"
+#include "rc_rpc_plugin/rc_module_constants.h"
+#include "rc_rpc_plugin/rc_rpc_plugin.h"
+
+namespace {
+const uint32_t kRCAppExtensionId = 1ull;
+} // namespace
+
+namespace test {
+namespace components {
+namespace rc_rpc_plugin_test {
+namespace rc_app_extension_test {
+
+using test::components::application_manager_test::MockApplication;
+using ::testing::NiceMock;
+
+class RcAppExtensionTest : public testing::Test {
+ public:
+ RcAppExtensionTest()
+ : mock_app_(new NiceMock<MockApplication>())
+ , rc_app_extension_(std::make_shared<rc_rpc_plugin::RCAppExtension>(
+ kRCAppExtensionId, rc_plugin_, *mock_app_)) {}
+
+ protected:
+ std::unique_ptr<MockApplication> mock_app_;
+ rc_rpc_plugin::RCRPCPlugin rc_plugin_;
+ rc_rpc_plugin::RCAppExtensionPtr rc_app_extension_;
+};
+
+TEST_F(RcAppExtensionTest, SubscribeToInteriorVehicleData_AppDoesntUpdateHash) {
+ const std::string module_type = "CLIMATE";
+ const std::string module_id = "9cb963f3-c5e8-41cb-b001-19421cc16552";
+ rc_rpc_plugin::ModuleUid module{module_type, module_id};
+
+ EXPECT_CALL(*mock_app_, UpdateHash()).Times(0);
+
+ rc_app_extension_->SubscribeToInteriorVehicleData(module);
+ EXPECT_TRUE(rc_app_extension_->IsSubscribedToInteriorVehicleData(module));
+
+ auto subscription = rc_app_extension_->InteriorVehicleDataSubscriptions();
+ EXPECT_EQ(1ull, subscription.size());
+}
+
+TEST_F(RcAppExtensionTest,
+ UnsubscribeFromInteriorVehicleData_AppDoesntUpdateHash) {
+ const std::string module_type = "CLIMATE";
+ const std::string module_id = "9cb963f3-c5e8-41cb-b001-19421cc16552";
+ rc_rpc_plugin::ModuleUid module{module_type, module_id};
+
+ EXPECT_CALL(*mock_app_, UpdateHash()).Times(0);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module);
+
+ EXPECT_CALL(*mock_app_, UpdateHash()).Times(0);
+ rc_app_extension_->UnsubscribeFromInteriorVehicleData(module);
+
+ EXPECT_FALSE(rc_app_extension_->IsSubscribedToInteriorVehicleData(module));
+
+ auto subscription = rc_app_extension_->InteriorVehicleDataSubscriptions();
+ EXPECT_TRUE(subscription.empty());
+}
+
+TEST_F(RcAppExtensionTest,
+ UnsubscribeFromInteriorVehicleDataOfType_AppDoesntUpdateHash) {
+ const std::string module1_type = "CLIMATE";
+ const std::string module1_id = "9cb963f3-c5e8-41cb-b001-19421cc16552";
+ rc_rpc_plugin::ModuleUid module1{module1_type, module1_id};
+
+ const std::string module2_type = "RADIO";
+ const std::string module2_id = "357a3918-9f35-4d86-a8b6-60cd4308d76f";
+ rc_rpc_plugin::ModuleUid module2{module2_type, module2_id};
+
+ EXPECT_CALL(*mock_app_, UpdateHash()).Times(0);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module1);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module2);
+
+ EXPECT_CALL(*mock_app_, UpdateHash());
+ rc_app_extension_->UnsubscribeFromInteriorVehicleDataOfType(module1_type);
+
+ EXPECT_FALSE(
+ rc_app_extension_->IsSubscribedToInteriorVehicleDataOfType(module1_type));
+ EXPECT_TRUE(
+ rc_app_extension_->IsSubscribedToInteriorVehicleDataOfType(module2_type));
+
+ auto subscription = rc_app_extension_->InteriorVehicleDataSubscriptions();
+ EXPECT_EQ(1ull, subscription.size());
+}
+
+TEST_F(RcAppExtensionTest,
+ UnsubscribeFromInteriorVehicleDataOfType_UNSUCCESS_AppDoesntUpdateHash) {
+ const std::string module1_type = "CLIMATE";
+ const std::string module_id = "9cb963f3-c5e8-41cb-b001-19421cc16552";
+ rc_rpc_plugin::ModuleUid module{module1_type, module_id};
+
+ const std::string module2_type = "RADIO";
+
+ EXPECT_CALL(*mock_app_, UpdateHash()).Times(0);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module);
+
+ EXPECT_CALL(*mock_app_, UpdateHash()).Times(0);
+ rc_app_extension_->UnsubscribeFromInteriorVehicleDataOfType(module2_type);
+
+ EXPECT_TRUE(rc_app_extension_->IsSubscribedToInteriorVehicleData(module));
+
+ auto subscription = rc_app_extension_->InteriorVehicleDataSubscriptions();
+ EXPECT_EQ(1ull, subscription.size());
+}
+
+TEST_F(RcAppExtensionTest, SaveResumptionData_SUCCESS) {
+ using namespace rc_rpc_plugin;
+
+ const std::string module1_type = "CLIMATE";
+ const std::string module1_id = "9cb963f3-c5e8-41cb-b001-19421cc16552";
+ ModuleUid module1{module1_type, module1_id};
+
+ const std::string module2_type = "RADIO";
+ const std::string module2_id = "357a3918-9f35-4d86-a8b6-60cd4308d76f";
+ ModuleUid module2{module2_type, module2_id};
+
+ EXPECT_CALL(*mock_app_, UpdateHash()).Times(0);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module1);
+ rc_app_extension_->SubscribeToInteriorVehicleData(module2);
+
+ const auto subscriptions =
+ rc_app_extension_->InteriorVehicleDataSubscriptions();
+
+ auto subscription_so =
+ smart_objects::SmartObject(smart_objects::SmartType_Map);
+
+ rc_app_extension_->SaveResumptionData(subscription_so);
+
+ const auto module_data =
+ subscription_so[message_params::kModuleData].asArray();
+
+ EXPECT_NE(nullptr, module_data);
+
+ EXPECT_EQ(module_data->size(), subscriptions.size());
+
+ auto module_info_so =
+ smart_objects::SmartObject(smart_objects::SmartType_Map);
+ module_info_so[message_params::kModuleType] = module1.first;
+ module_info_so[message_params::kModuleId] = module1.second;
+
+ auto found_module =
+ std::find(module_data->begin(), module_data->end(), module_info_so);
+
+ EXPECT_NE(found_module, module_data->end());
+
+ module_info_so[message_params::kModuleType] = module2.first;
+ module_info_so[message_params::kModuleId] = module2.second;
+
+ found_module =
+ std::find(module_data->begin(), module_data->end(), module_info_so);
+
+ EXPECT_NE(found_module, module_data->end());
+}
+
+} // namespace rc_app_extension_test
+} // namespace rc_rpc_plugin_test
+} // namespace components
+} // namespace test
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_pending_resumption_handler_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_pending_resumption_handler_test.cc
new file mode 100644
index 0000000000..fe8ade1e05
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_pending_resumption_handler_test.cc
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE. */
+
+#include "rc_rpc_plugin/rc_pending_resumption_handler.h"
+#include "application_manager/mock_application.h"
+#include "application_manager/mock_event_dispatcher.h"
+#include "application_manager/mock_message_helper.h"
+#include "application_manager/mock_resume_ctrl.h"
+#include "application_manager/mock_resumption_data_processor.h"
+#include "application_manager/mock_rpc_service.h"
+#include "application_manager/smart_object_keys.h"
+#include "gtest/gtest.h"
+#include "mock_application_manager.h"
+#include "rc_rpc_plugin/interior_data_cache_impl.h"
+#include "rc_rpc_plugin/rc_module_constants.h"
+#include "rc_rpc_plugin/rc_rpc_plugin.h"
+
+namespace rc_rpc_plugin_test {
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::ReturnRef;
+using ::testing::SaveArg;
+
+using rc_rpc_plugin::ModuleUid;
+
+using application_manager::MockMessageHelper;
+using test::components::resumption_test::MockResumeCtrl;
+using test::components::resumption_test::MockResumptionDataProcessor;
+typedef NiceMock< ::test::components::event_engine_test::MockEventDispatcher>
+ MockEventDispatcher;
+
+typedef NiceMock<
+ ::test::components::application_manager_test::MockApplicationManager>
+ MockApplicationManager;
+typedef NiceMock< ::test::components::application_manager_test::MockApplication>
+ MockApplication;
+typedef NiceMock< ::test::components::application_manager_test::MockRPCService>
+ MockRPCService;
+typedef std::shared_ptr<MockApplication> MockAppPtr;
+
+namespace {
+const uint32_t kAppId_1 = 1u;
+const uint32_t kAppId_2 = 2u;
+const uint32_t kCorrelationId = 10u;
+const std::string kModuleType_1 = "CLIMATE";
+const std::string kModuleId_1 = "9cb963f3-c5e8-41cb-b001-19421cc16552";
+const std::string kModuleType_2 = "RADIO";
+const std::string kModuleId_2 = "357a3918-9f35-4d86-a8b6-60cd4308d76f";
+const uint32_t kRCPluginID = rc_rpc_plugin::RCRPCPlugin::kRCPluginID;
+const auto kSourceHMI = application_manager::commands::Command::SOURCE_HMI;
+} // namespace
+
+/**
+ * @brief EventCheck check that event contains apropriate data,
+ * check that is matched correlation id,
+ * check that function id is correct
+ */
+MATCHER_P(EventCheck, expected_corr_id, "") {
+ namespace strings = application_manager::strings;
+ const auto& response_message = arg.smart_object();
+ const auto cid =
+ response_message[strings::params][strings::correlation_id].asInt();
+ const bool cid_ok = (cid == expected_corr_id);
+ const auto fid =
+ response_message[strings::params][strings::function_id].asInt();
+ const bool fid_ok = (fid == hmi_apis::FunctionID::RC_GetInteriorVehicleData);
+ return fid_ok && cid_ok;
+}
+
+/**
+ * @brief MessageCheck check that message contains apropriate data,
+ * check that is matched correlation id
+ */
+MATCHER_P(MessageCheck, correlation_id, "") {
+ const auto& request = *arg;
+ const auto cid =
+ request[app_mngr::strings::params][app_mngr::strings::correlation_id]
+ .asInt();
+ return cid == correlation_id;
+}
+
+class RCPendingResumptionHandlerTest : public ::testing::Test {
+ public:
+ RCPendingResumptionHandlerTest()
+ : applications_lock_(std::make_shared<sync_primitives::Lock>())
+ , applications_(application_set_, applications_lock_)
+ , mock_message_helper_(*MockMessageHelper::message_helper_mock()) {}
+
+ void SetUp() OVERRIDE {
+ ON_CALL(app_manager_mock_, event_dispatcher())
+ .WillByDefault(ReturnRef(event_dispatcher_mock_));
+ ON_CALL(app_manager_mock_, GetRPCService())
+ .WillByDefault(ReturnRef(mock_rpc_service_));
+ ON_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillByDefault(Return(kCorrelationId));
+ ON_CALL(app_manager_mock_, applications())
+ .WillByDefault(Return(applications_));
+ ON_CALL(app_manager_mock_, resume_controller())
+ .WillByDefault(ReturnRef(resume_ctrl_mock_));
+ ON_CALL(resume_ctrl_mock_, resumption_data_processor())
+ .WillByDefault(ReturnRef(resumption_data_processor_mock_));
+ resumption_handler_.reset(new rc_rpc_plugin::RCPendingResumptionHandler(
+ app_manager_mock_, cache_));
+ }
+
+ smart_objects::SmartObjectSPtr CreateHMIResponseMessage(
+ const application_manager::MessageType& message_type,
+ const hmi_apis::Common_Result::eType& response_code,
+ uint32_t correlation_id) {
+ namespace strings = application_manager::strings;
+ namespace hmi_response = application_manager::hmi_response;
+ smart_objects::SmartObject params(smart_objects::SmartType_Map);
+ params[strings::function_id] =
+ hmi_apis::FunctionID::RC_GetInteriorVehicleData;
+ params[strings::message_type] = message_type;
+ params[strings::correlation_id] = correlation_id;
+ const auto hmi_protocol_type = 1;
+ params[strings::protocol_type] = hmi_protocol_type;
+ params[hmi_response::code] = response_code;
+
+ smart_objects::SmartObjectSPtr response =
+ std::make_shared<smart_objects::SmartObject>(
+ smart_objects::SmartType_Map);
+ auto& message = *response;
+ message[strings::params] = params;
+ message[strings::msg_params] =
+ smart_objects::SmartObject(smart_objects::SmartType_Map);
+ message[strings::msg_params][rc_rpc_plugin::message_params::kIsSubscribed] =
+ true;
+ return response;
+ }
+
+ MockAppPtr CreateApp(uint32_t app_id) {
+ auto mock_app = std::make_shared<MockApplication>();
+ ON_CALL(app_manager_mock_, application(app_id))
+ .WillByDefault(Return(mock_app));
+ ON_CALL(*mock_app, app_id()).WillByDefault(Return(app_id));
+ return mock_app;
+ }
+
+ rc_rpc_plugin::RCAppExtensionPtr CreateExtension(MockApplication& app) {
+ auto rc_app_ext = std::make_shared<rc_rpc_plugin::RCAppExtension>(
+ kRCPluginID, rc_plugin_, app);
+ ON_CALL(app, QueryInterface(kRCPluginID)).WillByDefault(Return(rc_app_ext));
+ return rc_app_ext;
+ }
+
+ protected:
+ application_manager::ApplicationSet application_set_;
+ std::shared_ptr<sync_primitives::Lock> applications_lock_;
+ DataAccessor<application_manager::ApplicationSet> applications_;
+ MockMessageHelper& mock_message_helper_;
+ MockResumeCtrl resume_ctrl_mock_;
+ MockResumptionDataProcessor resumption_data_processor_mock_;
+ MockApplicationManager app_manager_mock_;
+ MockEventDispatcher event_dispatcher_mock_;
+ MockRPCService mock_rpc_service_;
+ rc_rpc_plugin::RCRPCPlugin rc_plugin_;
+ rc_rpc_plugin::InteriorDataCacheImpl cache_;
+ std::unique_ptr<rc_rpc_plugin::RCPendingResumptionHandler>
+ resumption_handler_;
+};
+
+TEST_F(RCPendingResumptionHandlerTest, HandleResumptionNoSubscriptionNoAction) {
+ auto mock_app = CreateApp(kAppId_1);
+ auto rc_app_ext = CreateExtension(*mock_app);
+
+ EXPECT_CALL(resumption_data_processor_mock_, SubscribeToResponse(_, _))
+ .Times(0);
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(_, _)).Times(0);
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext,
+ *mock_app);
+}
+
+TEST_F(RCPendingResumptionHandlerTest,
+ HandleResumptionOneSubscriptionOnAction) {
+ auto mock_app = CreateApp(kAppId_1);
+ auto rc_app_ext = CreateExtension(*mock_app);
+
+ ModuleUid module_uid{kModuleType_1, kModuleId_1};
+ rc_app_ext->AddPendingSubscription(module_uid);
+
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_1));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_1, _));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(MessageCheck(kAppId_1), kSourceHMI));
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext,
+ *mock_app);
+}
+
+TEST_F(RCPendingResumptionHandlerTest,
+ HandleResumptionMultipleSubscriptionsMultipleActions) {
+ auto mock_app = CreateApp(kAppId_1);
+ auto rc_app_ext = CreateExtension(*mock_app);
+
+ ModuleUid module_uid_1 = {kModuleType_1, kModuleId_1};
+ rc_app_ext->AddPendingSubscription(module_uid_1);
+
+ ModuleUid module_uid_2 = {kModuleType_2, kModuleId_2};
+ rc_app_ext->AddPendingSubscription(module_uid_2);
+
+ {
+ InSequence in_sequence;
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_1));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_1, _));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(MessageCheck(kAppId_1), kSourceHMI));
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_2));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_1, _));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(MessageCheck(kAppId_2), kSourceHMI));
+ }
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext,
+ *mock_app);
+}
+
+TEST_F(RCPendingResumptionHandlerTest,
+ HandleResumptionWithPendingSubscription) {
+ auto mock_app = CreateApp(kAppId_1);
+ auto rc_app_ext = CreateExtension(*mock_app);
+
+ ModuleUid module_uid = {kModuleType_1, kModuleId_1};
+ rc_app_ext->AddPendingSubscription(module_uid);
+
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_1));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_1, _));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(MessageCheck(kAppId_1), kSourceHMI));
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext,
+ *mock_app);
+
+ auto rc_app_ext_2 = CreateExtension(*mock_app);
+ rc_app_ext_2->AddPendingSubscription(module_uid);
+
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID());
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_1, _));
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(_, _)).Times(0);
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext_2,
+ *mock_app);
+}
+
+TEST_F(RCPendingResumptionHandlerTest,
+ HandleResumptionWithPendingSubscriptionAndNotPendingOne) {
+ auto mock_app = CreateApp(kAppId_1);
+ auto rc_app_ext = CreateExtension(*mock_app);
+
+ ModuleUid module_uid_1 = {kModuleType_1, kModuleId_1};
+ rc_app_ext->AddPendingSubscription(module_uid_1);
+
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_1));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_1, _));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(MessageCheck(kAppId_1), kSourceHMI));
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext,
+ *mock_app);
+
+ auto rc_app_ext_2 = CreateExtension(*mock_app);
+ ModuleUid module_uid_2 = {kModuleType_2, kModuleId_2};
+ rc_app_ext_2->AddPendingSubscription(module_uid_1);
+ rc_app_ext_2->AddPendingSubscription(module_uid_2);
+
+ {
+ InSequence in_sequence;
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_1));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_1, _));
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_2));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_1, _));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(MessageCheck(kAppId_2), kSourceHMI));
+ }
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext_2,
+ *mock_app);
+}
+
+TEST_F(RCPendingResumptionHandlerTest,
+ Resumption2ApplicationsWithCommonDataSuccess) {
+ auto mock_app_1 = CreateApp(kAppId_1);
+ auto rc_app_ext = CreateExtension(*mock_app_1);
+
+ ModuleUid module_uid = {kModuleType_1, kModuleId_1};
+ rc_app_ext->AddPendingSubscription(module_uid);
+
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_1));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_1, _));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(MessageCheck(kAppId_1), kSourceHMI));
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext,
+ *mock_app_1);
+
+ auto mock_app_2 = CreateApp(kAppId_2);
+ auto rc_app_ext_2 = CreateExtension(*mock_app_2);
+
+ rc_app_ext_2->AddPendingSubscription(module_uid);
+
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_2));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_2, _));
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(_, _)).Times(0);
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext_2,
+ *mock_app_2);
+
+ auto response =
+ CreateHMIResponseMessage(application_manager::MessageType::kResponse,
+ hmi_apis::Common_Result::SUCCESS,
+ kAppId_1);
+
+ application_manager::event_engine::Event event(
+ hmi_apis::FunctionID::RC_GetInteriorVehicleData);
+ event.set_smart_object(*response);
+
+ EXPECT_CALL(event_dispatcher_mock_, raise_event(EventCheck(kAppId_2)));
+
+ resumption_handler_->on_event(event);
+}
+
+TEST_F(RCPendingResumptionHandlerTest,
+ Resumption2ApplicationsWithCommonDataFailedRetry) {
+ auto mock_app_1 = CreateApp(kAppId_1);
+ auto rc_app_ext = CreateExtension(*mock_app_1);
+
+ ModuleUid module_uid = {kModuleType_1, kModuleId_1};
+ rc_app_ext->AddPendingSubscription(module_uid);
+
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_1));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_1, _));
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(_, _));
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext,
+ *mock_app_1);
+
+ auto mock_app_2 = CreateApp(kAppId_2);
+ auto rc_app_ext_2 = CreateExtension(*mock_app_2);
+
+ rc_app_ext_2->AddPendingSubscription(module_uid);
+
+ EXPECT_CALL(app_manager_mock_, GetNextHMICorrelationID())
+ .WillOnce(Return(kAppId_2));
+ EXPECT_CALL(resumption_data_processor_mock_,
+ SubscribeToResponse(kAppId_2, _));
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(_, _)).Times(0);
+
+ resumption_handler_->HandleResumptionSubscriptionRequest(*rc_app_ext_2,
+ *mock_app_2);
+
+ auto response =
+ CreateHMIResponseMessage(application_manager::MessageType::kErrorResponse,
+ hmi_apis::Common_Result::SUCCESS,
+ kAppId_1);
+
+ application_manager::event_engine::Event event(
+ hmi_apis::FunctionID::RC_GetInteriorVehicleData);
+ event.set_smart_object(*response);
+
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(MessageCheck(kAppId_2), kSourceHMI));
+
+ resumption_handler_->on_event(event);
+}
+
+} // namespace rc_rpc_plugin_test
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/CMakeLists.txt b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/CMakeLists.txt
index 4b10d34643..a22543ba09 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/CMakeLists.txt
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/CMakeLists.txt
@@ -45,6 +45,7 @@ ${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_dat
${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/resource_allocation_manager_impl.cc
${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_rpc_plugin.cc
${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_app_extension.cc
+${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_pending_resumption_handler.cc
${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_consent_manager_impl.cc
${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_capabilities_manager_impl.cc
${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_command_factory.cc
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/resource_allocation_manager_impl_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/resource_allocation_manager_impl_test.cc
index 70ed832cb1..501fbc323d 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/resource_allocation_manager_impl_test.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/resource_allocation_manager_impl_test.cc
@@ -113,7 +113,8 @@ class RAManagerTest : public ::testing::Test {
ON_CALL(mock_app_mngr_, GetPolicyHandler())
.WillByDefault(ReturnRef(mock_policy_handler_));
auto plugin_id = rc_rpc_plugin::RCRPCPlugin::kRCPluginID;
- app_ext_ptr_ = std::make_shared<rc_rpc_plugin::RCAppExtension>(plugin_id);
+ app_ext_ptr_ = std::make_shared<rc_rpc_plugin::RCAppExtension>(
+ plugin_id, rc_plugin_, *mock_app_1_);
ON_CALL(*mock_app_1_, app_id()).WillByDefault(Return(kAppId1));
PrepareResources();
@@ -144,7 +145,9 @@ class RAManagerTest : public ::testing::Test {
void SetUp() OVERRIDE {
rc_app_extension_ = std::make_shared<rc_rpc_plugin::RCAppExtension>(
static_cast<application_manager::AppExtensionUID>(
- rc_rpc_plugin::RCRPCPlugin::kRCPluginID));
+ rc_rpc_plugin::RCRPCPlugin::kRCPluginID),
+ rc_plugin_,
+ *mock_app_1_);
ON_CALL(mock_rc_capabilities_manager_,
GetDriverLocationFromSeatLocationCapability())
.WillByDefault(Return(kDriverLocation));
@@ -178,6 +181,7 @@ class RAManagerTest : public ::testing::Test {
mock_rc_capabilities_manager_;
std::vector<ModuleUid> resources_;
Grid module_service_area_;
+ RCRPCPlugin rc_plugin_;
RCAppExtensionPtr rc_app_extension_;
MockRCHelpers* mock_rc_helpers_;
};
@@ -403,9 +407,11 @@ TEST_F(RAManagerTest, AppUnregistered_ReleaseResource) {
mock_app_mngr_, mock_rpc_service_, mock_rc_capabilities_manager_);
ra_manager.SetAccessMode(hmi_apis::Common_RCAccessMode::eType::AUTO_DENY);
- RCAppExtensionPtr rc_extention_ptr =
- std::make_shared<RCAppExtension>(application_manager::AppExtensionUID(
- rc_rpc_plugin::RCRPCPlugin::kRCPluginID));
+ RCAppExtensionPtr rc_extension_ptr = std::make_shared<RCAppExtension>(
+ application_manager::AppExtensionUID(
+ rc_rpc_plugin::RCRPCPlugin::kRCPluginID),
+ rc_plugin_,
+ *mock_app_1_);
EXPECT_EQ(rc_rpc_plugin::AcquireResult::ALLOWED,
ra_manager.AcquireResource(kModuleType1, kModuleId, kAppId1));
@@ -477,12 +483,14 @@ TEST_F(RAManagerTest, AppsDisallowed_ReleaseAllResources) {
EXPECT_CALL(mock_app_mngr_, applications()).WillRepeatedly(Return(apps_da));
- RCAppExtensionPtr rc_extention_ptr =
- std::make_shared<RCAppExtension>(application_manager::AppExtensionUID(
- rc_rpc_plugin::RCRPCPlugin::kRCPluginID));
+ RCAppExtensionPtr rc_extension_ptr = std::make_shared<RCAppExtension>(
+ application_manager::AppExtensionUID(
+ rc_rpc_plugin::RCRPCPlugin::kRCPluginID),
+ rc_plugin_,
+ *mock_app_1_);
EXPECT_CALL(*mock_app_1_, QueryInterface(RCRPCPlugin::kRCPluginID))
- .WillRepeatedly(Return(rc_extention_ptr));
+ .WillRepeatedly(Return(rc_extension_ptr));
// Act
ra_manager.OnPolicyEvent(
@@ -508,13 +516,15 @@ TEST_F(RAManagerTest, AppGotRevokedModulesWithPTU_ReleaseRevokedResource) {
EXPECT_CALL(mock_app_mngr_, application(kAppId1))
.WillRepeatedly(Return(mock_app_1_));
- RCAppExtensionPtr rc_extention_ptr =
+ RCAppExtensionPtr rc_extension_ptr =
std::make_shared<rc_rpc_plugin::RCAppExtension>(
application_manager::AppExtensionUID(
- rc_rpc_plugin::RCRPCPlugin::kRCPluginID));
+ rc_rpc_plugin::RCRPCPlugin::kRCPluginID),
+ rc_plugin_,
+ *mock_app_1_);
EXPECT_CALL(*mock_app_1_, QueryInterface(RCRPCPlugin::kRCPluginID))
- .WillRepeatedly(Return(rc_extention_ptr));
+ .WillRepeatedly(Return(rc_extension_ptr));
ON_CALL(*mock_app_1_, is_remote_control_supported())
.WillByDefault(Return(true));
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/waypoints_app_extension.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/waypoints_app_extension.h
index 37ac24bcbb..9243baedee 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/waypoints_app_extension.h
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/waypoints_app_extension.h
@@ -53,7 +53,7 @@ class WayPointsAppExtension : public app_mngr::AppExtension {
void ProcessResumption(const smart_objects::SmartObject& saved_app) OVERRIDE;
void RevertResumption(
- const smart_objects::SmartObject& subscriptions) OVERRIDE;
+ const smart_objects::SmartObject& resumption_data) OVERRIDE;
/**
* @brief WayPointsAppExtensionUID unique identifier of waypoints
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/waypoints_app_extension.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/waypoints_app_extension.cc
index 61b5d1624a..ed8283e1f9 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/waypoints_app_extension.cc
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/waypoints_app_extension.cc
@@ -67,9 +67,9 @@ void WayPointsAppExtension::ProcessResumption(
}
void WayPointsAppExtension::RevertResumption(
- const smart_objects::SmartObject& subscriptions) {
+ const smart_objects::SmartObject& resumption_data) {
SDL_LOG_AUTO_TRACE();
- UNUSED(subscriptions);
+ UNUSED(resumption_data);
plugin_.RevertResumption(app_);
}
diff --git a/src/components/application_manager/rpc_plugins/vehicle_info_plugin/include/vehicle_info_plugin/vehicle_info_app_extension.h b/src/components/application_manager/rpc_plugins/vehicle_info_plugin/include/vehicle_info_plugin/vehicle_info_app_extension.h
index 2f61ef026a..7e3eabb6a1 100644
--- a/src/components/application_manager/rpc_plugins/vehicle_info_plugin/include/vehicle_info_plugin/vehicle_info_app_extension.h
+++ b/src/components/application_manager/rpc_plugins/vehicle_info_plugin/include/vehicle_info_plugin/vehicle_info_app_extension.h
@@ -146,7 +146,7 @@ class VehicleInfoAppExtension : public app_mngr::AppExtension {
void ProcessResumption(const smart_objects::SmartObject& saved_app) OVERRIDE;
void RevertResumption(
- const smart_objects::SmartObject& subscriptions) OVERRIDE;
+ const smart_objects::SmartObject& resumption_data) OVERRIDE;
/**
* @brief VehicleInfoAppExtensionUID unique identifier of VehicleInfo
diff --git a/src/components/application_manager/rpc_plugins/vehicle_info_plugin/src/vehicle_info_app_extension.cc b/src/components/application_manager/rpc_plugins/vehicle_info_plugin/src/vehicle_info_app_extension.cc
index 5cd790a75b..dd6d797e39 100644
--- a/src/components/application_manager/rpc_plugins/vehicle_info_plugin/src/vehicle_info_app_extension.cc
+++ b/src/components/application_manager/rpc_plugins/vehicle_info_plugin/src/vehicle_info_app_extension.cc
@@ -170,11 +170,31 @@ void VehicleInfoAppExtension::ProcessResumption(
}
void VehicleInfoAppExtension::RevertResumption(
- const smart_objects::SmartObject& subscriptions) {
+ const smart_objects::SmartObject& resumption_data) {
SDL_LOG_AUTO_TRACE();
unsubscribeFromVehicleInfo();
- plugin_.RevertResumption(app_, subscriptions.enumerate());
+
+ if (!resumption_data.keyExists(
+ application_manager::hmi_interface::vehicle_info)) {
+ SDL_LOG_DEBUG("No resumption vahicle data subscription to revert");
+ return;
+ }
+ const auto& resumption_vd_data =
+ resumption_data[application_manager::hmi_interface::vehicle_info];
+
+ std::set<std::string> ivi_subscriptions_to_revert;
+ const auto ivi_subscriptions_keys = resumption_vd_data.enumerate();
+ for (const auto& key : ivi_subscriptions_keys) {
+ // Only boolean keys in subscriptions list are true vehicle data
+ // subscriptions
+ if (smart_objects::SmartType::SmartType_Boolean ==
+ resumption_vd_data.getElement(key).getType()) {
+ ivi_subscriptions_to_revert.insert(key);
+ }
+ }
+
+ plugin_.RevertResumption(app_, ivi_subscriptions_to_revert);
}
VehicleInfoAppExtension& VehicleInfoAppExtension::ExtractVIExtension(
diff --git a/src/components/application_manager/src/application_impl.cc b/src/components/application_manager/src/application_impl.cc
index 3708c45cfa..60070524a0 100644
--- a/src/components/application_manager/src/application_impl.cc
+++ b/src/components/application_manager/src/application_impl.cc
@@ -1254,12 +1254,13 @@ AppExtensionPtr ApplicationImpl::QueryInterface(AppExtensionUID uid) {
return (*it);
}
}
-
return AppExtensionPtr();
}
bool ApplicationImpl::AddExtension(AppExtensionPtr extension) {
if (!QueryInterface(extension->uid())) {
+ SDL_LOG_TRACE("Add extenstion to add id" << app_id() << " with uid "
+ << extension->uid());
extensions_.push_back(extension);
return true;
}
diff --git a/src/components/application_manager/src/resumption/resumption_data_processor_impl.cc b/src/components/application_manager/src/resumption/resumption_data_processor_impl.cc
index d1635eb557..c067167041 100644
--- a/src/components/application_manager/src/resumption/resumption_data_processor_impl.cc
+++ b/src/components/application_manager/src/resumption/resumption_data_processor_impl.cc
@@ -33,6 +33,7 @@
#include "application_manager/event_engine/event_observer.h"
#include "application_manager/message_helper.h"
#include "application_manager/resumption/resumption_data_processor_impl.h"
+#include "application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_module_constants.h"
#include "application_manager/smart_object_keys.h"
namespace resumption {
@@ -45,8 +46,17 @@ using app_mngr::MessageHelper;
namespace strings = app_mngr::strings;
namespace event_engine = app_mngr::event_engine;
namespace commands = app_mngr::commands;
+namespace message_params = rc_rpc_plugin::message_params;
SDL_CREATE_LOG_VARIABLE("Resumption")
+std::map<hmi_apis::Common_ModuleType::eType, std::string>
+ module_types_str_mapping{
+ {hmi_apis::Common_ModuleType::eType::CLIMATE, {"CLIMATE"}},
+ {hmi_apis::Common_ModuleType::eType::RADIO, {"RADIO"}},
+ {hmi_apis::Common_ModuleType::eType::SEAT, {"SEAT"}},
+ {hmi_apis::Common_ModuleType::eType::AUDIO, {"AUDIO"}},
+ {hmi_apis::Common_ModuleType::eType::LIGHT, {"LIGHT"}},
+ {hmi_apis::Common_ModuleType::eType::HMI_SETTINGS, {"HMI_SETTINGS"}}};
bool ResumptionRequestID::operator<(const ResumptionRequestID& other) const {
return correlation_id < other.correlation_id ||
@@ -251,6 +261,11 @@ void ResumptionDataProcessorImpl::ProcessResumptionStatus(
found_request.request_id.function_id) {
CheckCreateWindowResponse(found_request.message, response);
}
+
+ if (hmi_apis::FunctionID::RC_GetInteriorVehicleData ==
+ found_request.request_id.function_id) {
+ CheckModuleDataSubscription(found_request.message, response, status);
+ }
}
bool ResumptionDataProcessorImpl::IsResumptionFinished(
@@ -297,7 +312,8 @@ bool ResumptionDataProcessorImpl::IsResumptionSuccessful(
const ApplicationResumptionStatus& status = it->second;
return status.error_requests.empty() &&
- status.unsuccessful_vehicle_data_subscriptions_.empty();
+ status.unsuccessful_vehicle_data_subscriptions_.empty() &&
+ status.unsuccessful_module_subscriptions_.empty();
}
void ResumptionDataProcessorImpl::EraseAppResumptionData(
@@ -988,15 +1004,44 @@ void ResumptionDataProcessorImpl::DeletePluginsSubscriptions(
}
const ApplicationResumptionStatus& status = it->second;
- smart_objects::SmartObject extension_subscriptions;
+ smart_objects::SmartObject extension_vd_subscriptions;
for (auto ivi : status.successful_vehicle_data_subscriptions_) {
SDL_LOG_DEBUG("ivi " << ivi << " should be deleted");
- extension_subscriptions[ivi] = true;
+ extension_vd_subscriptions[ivi] = true;
+ }
+
+ smart_objects::SmartObject extension_modules_subscriptions(
+ smart_objects::SmartType_Map);
+
+ if (!status.successful_module_subscriptions_.empty()) {
+ extension_modules_subscriptions[message_params::kModuleData] =
+ new smart_objects::SmartObject(smart_objects::SmartType_Array);
+
+ auto& module_data_so =
+ extension_modules_subscriptions[message_params::kModuleData];
+
+ uint32_t index = 0;
+ for (const auto& module : status.successful_module_subscriptions_) {
+ module_data_so[index] =
+ new smart_objects::SmartObject(smart_objects::SmartType_Map);
+ module_data_so[index][message_params::kModuleType] = module.first;
+ module_data_so[index][message_params::kModuleId] = module.second;
+ index++;
+ }
}
+
+ smart_objects::SmartObject resumption_data_to_revert(
+ smart_objects::SmartType_Map);
+ resumption_data_to_revert[application_manager::hmi_interface::vehicle_info] =
+ extension_vd_subscriptions;
+ resumption_data_to_revert[application_manager::hmi_interface::rc] =
+ extension_modules_subscriptions;
+
resumption_status_lock_.Release();
- for (auto& extension : application->Extensions()) {
- extension->RevertResumption(extension_subscriptions);
+ auto extensions = application->Extensions();
+ for (auto& extension : extensions) {
+ extension->RevertResumption(resumption_data_to_revert);
}
}
@@ -1039,6 +1084,70 @@ void ResumptionDataProcessorImpl::CheckVehicleDataResponse(
}
}
+void ResumptionDataProcessorImpl::CheckModuleDataSubscription(
+ const ns_smart_device_link::ns_smart_objects::SmartObject& request,
+ const ns_smart_device_link::ns_smart_objects::SmartObject& response,
+ ApplicationResumptionStatus& status) {
+ SDL_LOG_AUTO_TRACE();
+
+ const auto& msg_params_so = request[strings::msg_params];
+ const auto requested_module_type =
+ msg_params_so[message_params::kModuleType].asString();
+ const auto requested_module_id =
+ msg_params_so[message_params::kModuleId].asString();
+ const ModuleUid requested_module{requested_module_type, requested_module_id};
+
+ if (!IsResponseSuccessful(response)) {
+ SDL_LOG_TRACE("Module data subscription request NOT successful");
+ status.unsuccessful_module_subscriptions_.push_back(requested_module);
+ return;
+ }
+
+ const auto& response_module_data_so =
+ response[strings::msg_params][message_params::kModuleData];
+
+ if (0 == response_module_data_so.length()) {
+ SDL_LOG_TRACE("Module data subscription request not successful");
+ status.unsuccessful_module_subscriptions_.push_back(requested_module);
+ return;
+ }
+
+ const auto responsed_module_type_int =
+ static_cast<hmi_apis::Common_ModuleType::eType>(
+ response_module_data_so[message_params::kModuleType].asUInt());
+
+ const auto responsed_module_type_str =
+ module_types_str_mapping[responsed_module_type_int];
+
+ const auto response_module_id =
+ response_module_data_so[message_params::kModuleId].asString();
+ const ModuleUid responsed_module{responsed_module_type_str,
+ response_module_id};
+
+ bool is_subscribe_success = false;
+ if (response[application_manager::strings::msg_params].keyExists(
+ rc_rpc_plugin::message_params::kIsSubscribed)) {
+ is_subscribe_success =
+ response[application_manager::strings::msg_params]
+ [rc_rpc_plugin::message_params::kIsSubscribed]
+ .asBool();
+ }
+
+ const bool is_the_same_module = requested_module == responsed_module;
+
+ if (is_the_same_module && is_subscribe_success) {
+ SDL_LOG_TRACE("Module [" << requested_module.first << ":"
+ << requested_module.second
+ << "] was successfuly subscribed");
+ status.successful_module_subscriptions_.push_back(requested_module);
+ } else {
+ SDL_LOG_TRACE("Module [" << requested_module.first << ":"
+ << requested_module.second
+ << "] was NOT successfuly subscribed");
+ status.unsuccessful_module_subscriptions_.push_back(requested_module);
+ }
+}
+
void ResumptionDataProcessorImpl::CheckCreateWindowResponse(
const smart_objects::SmartObject& request,
const smart_objects::SmartObject& response) const {