summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIra Lytvynenko (GitHub) <ILytvynenko@luxoft.com>2020-09-05 01:34:34 +0300
committerGitHub <noreply@github.com>2020-09-04 18:34:34 -0400
commit10f19d1b142f92d9c617216795c5c0df664607bc (patch)
tree2a8cf54314b7822729d0a5f352d685b6847d0b24
parentb94d63a0f3e73dc03e7e49d74bf39e2423eb844f (diff)
downloadsdl_core-10f19d1b142f92d9c617216795c5c0df664607bc.tar.gz
[SDL-0188] Interior Vehicle Data Resumption (#3480)
* Add changes related to AppExtension and RCAppExtension * Change OnTimeOut() method in affected requests * Add changes related to ApplicationHelper class * Add changes related to EventDispatcher * Fill subscription data for all pending requests Changed SDL logic to update subscription results for each pending subscription request before notifying resumption processor about current subscription is processed. This should be done beforehand because after raising event to processor it can finish resumption process and if it has failed then it can trigger sending of the next subscription request. So at that point, each subscription request should contain updated subscriptions status, otherwise some redundant requests might be sent. * Add RC data to resumption data processor * Add RCPendingResumptionHandler class * Process timeout for get interior vehicle data * Revert Interior vehicle data * Add resumption logic to RC app extension * Resumption logic in RC plugin * Helpers RC functions * Update hash for RC data * Filter RC subscriptions in vehicle data plugin * UTs for the RCPendingResumptionHandler Co-authored-by: Yana Chernysheva <ychernysheva@luxoft.com> Co-authored-by: Andrii Kalinich (GitHub) <AKalinich@luxoft.com> Co-authored-by: Aleksandr Kutsan <AKutsan@luxoft.com> Co-authored-by: Igor Gapchuk <igapchuck@luxoft.com> Co-authored-by: sniukalov <sniukaov@luxoft.com> Co-authored-by: Dmitriy Boltovskiy <dboltovskyi@luxoft.com>
-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 {