diff options
author | dtrunov <dtrunov@luxoft.com> | 2015-02-27 17:43:07 +0200 |
---|---|---|
committer | dtrunov <dtrunov@luxoft.com> | 2015-06-23 15:09:11 +0300 |
commit | 81d5b783c174d192ec89aa99fe35a87851b83ff7 (patch) | |
tree | 2d1ec92f3f77b0b2b13ad27e0a297c60c31fc973 /src | |
parent | e533d78381ff2102742710fcfae4b83a55bc77b2 (diff) | |
download | sdl_core-81d5b783c174d192ec89aa99fe35a87851b83ff7.tar.gz |
Resumption with DB
Diffstat (limited to 'src')
24 files changed, 4329 insertions, 357 deletions
diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h index d92c6a35c4..8173552a3b 100644 --- a/src/components/application_manager/include/application_manager/application.h +++ b/src/components/application_manager/include/application_manager/application.h @@ -70,6 +70,11 @@ enum APIVersion { kAPIV4 = 4 }; +enum StateApplicationData { + kNotSavedDataForResumption, + kSavedDataForResumption +}; + enum TLimitSource { POLICY_TABLE = 0, CONFIG_FILE @@ -394,6 +399,20 @@ class Application : public virtual InitialApplicationData, */ virtual void UpdateHash() = 0; + /** + * @brief method is called when SDL is saving application data for resumption + * @return TRUE if data of application need to save for resumption, otherwise + * return FALSE + */ + virtual StateApplicationData is_application_data_changed() const = 0; + + /** + * @brief method is called after SDL saved application data for resumption + * @param state_application_data contains FALSE after saving data + */ + virtual void set_is_application_data_changed( + StateApplicationData state_application_data) = 0; + virtual void CloseActiveMessage() = 0; virtual bool IsFullscreen() const = 0; virtual void ChangeSupportingAppHMIType() = 0; diff --git a/src/components/application_manager/include/application_manager/application_impl.h b/src/components/application_manager/include/application_manager/application_impl.h index 895bb1fa98..a0b187f8d0 100644 --- a/src/components/application_manager/include/application_manager/application_impl.h +++ b/src/components/application_manager/include/application_manager/application_impl.h @@ -195,6 +195,11 @@ class ApplicationImpl : public virtual InitialApplicationDataImpl, virtual void UnsubscribeFromSoftButtons(int32_t cmd_id); + virtual StateApplicationData is_application_data_changed() const; + + virtual void set_is_application_data_changed( + StateApplicationData state_application_data); + /** * @brief Check's if it is media, voice communication or navigation application * @@ -300,6 +305,7 @@ class ApplicationImpl : public virtual InitialApplicationDataImpl, bool tts_properties_in_none_; bool tts_properties_in_full_; bool is_foreground_; + StateApplicationData is_application_data_changed_; uint32_t put_file_in_none_count_; uint32_t delete_file_in_none_count_; uint32_t list_files_in_none_count_; diff --git a/src/components/application_manager/include/application_manager/message_helper.h b/src/components/application_manager/include/application_manager/message_helper.h index 9b8093dc53..bcaa78ed3e 100644 --- a/src/components/application_manager/include/application_manager/message_helper.h +++ b/src/components/application_manager/include/application_manager/message_helper.h @@ -214,6 +214,13 @@ class MessageHelper { static smart_objects::SmartObjectList CreateAddCommandRequestToHMI(ApplicationConstSharedPtr app); /** + * @brief prepares commands in order to send it to HMI + * @param app applicaton instace + */ + static smart_objects::SmartObjectList CreateAddVRCommandRequestFromChoiceToHMI( + ApplicationConstSharedPtr app); + + /** * @brief Sends UI_ChangeRegistration to HMI with list of AppHMIType * @param app applicaton instace */ diff --git a/src/components/application_manager/include/application_manager/resume_ctrl.h b/src/components/application_manager/include/application_manager/resume_ctrl.h index 99d694570c..d42675cdfb 100644 --- a/src/components/application_manager/include/application_manager/resume_ctrl.h +++ b/src/components/application_manager/include/application_manager/resume_ctrl.h @@ -76,13 +76,13 @@ class ResumeCtrl: public event_engine::EventObserver { * @brief Save all applications info to the file system */ void SaveAllApplications(); - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief Save application persistent info for future resuming * @param application is application witch need to be saved */ void SaveApplication(ApplicationConstSharedPtr application); - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief Set application HMI Level as saved * @param application is application witch HMI Level is need to restore @@ -116,21 +116,14 @@ class ResumeCtrl: public event_engine::EventObserver { * @return true if success, otherwise return false */ bool RestoreApplicationData(ApplicationSharedPtr application); - - /** - * @brief Check if Resume controller have saved instance of application - * @param application is application witch need to be checked - * @return true if exist, false otherwise - */ - bool ApplicationIsSaved(ApplicationConstSharedPtr application); - +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief Remove application from list of saved applications * @param mobile_app_id application witch need to be removed * @return return true, if success, otherwise return false */ bool RemoveApplicationFromSaved(const std::string& mobile_app_id); - +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief Increments ignition counter for all registered applications * and remember ign_off time stamp @@ -194,19 +187,22 @@ class ResumeCtrl: public event_engine::EventObserver { /** * @brief Check if Resume controller have saved instance of application * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application * @return true if exist, false otherwise */ - bool IsApplicationSaved(const std::string& mobile_app_id); + bool IsApplicationSaved(const std::string& mobile_app_id, + const std::string& device_id); /** * @brief Function is used for application resume. HMI app ID must be * the same(PASA VCA module use it for stored app info). * Retrieves HMI app ID for the given mobile app ID from stored information. - * * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application * @return HMI app ID */ - uint32_t GetHMIApplicationID(const std::string& mobile_app_id); + uint32_t GetHMIApplicationID(const std::string& mobile_app_id, + const std::string& device_id); /** * @brief SaveDataOnTimer : @@ -215,8 +211,6 @@ class ResumeCtrl: public event_engine::EventObserver { */ void SaveDataOnTimer(); - void ClearResumptionInfo(); - void ApplicationsDataUpdated() { is_data_saved = false; } @@ -261,34 +255,29 @@ class ResumeCtrl: public event_engine::EventObserver { */ time_t launch_time() const; - /** - * @brief Check device MAC address - * - * @param application that is need to be restored - * @param saved_device_mac Saved device MAC address - * - * @return TRUE on success, otherwise FALSE - */ - bool IsDeviceMacAddressEqual(ApplicationSharedPtr application, - const std::string& saved_device_mac); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief Get Resumption section of LastState * @return Resumption section of LastState in Json */ Json::Value& GetResumptionData(); - + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief Get applications for resumption of LastState * @return applications for resumption of LastState */ Json::Value& GetSavedApplications(); - +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief Get the last ignition off time from LastState * @return the last ignition off time from LastState */ time_t GetIgnOffTime(); - + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief Setup IgnOff time to LastState * @param ign_off_time - igition off time @@ -313,8 +302,8 @@ class ResumeCtrl: public event_engine::EventObserver { ApplicationConstSharedPtr application); Json::Value GetApplicationFiles( ApplicationConstSharedPtr application); - Json::Value GetApplicationShow( - ApplicationConstSharedPtr application); + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Json::Value JsonFromSO(const smart_objects::SmartObject *so); @@ -327,7 +316,7 @@ class ResumeCtrl: public event_engine::EventObserver { bool use_events = false); void InsertToTimerQueue(uint32_t app_id, uint32_t time_stamp); - + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief AddFiles allows to add files for the application * which should be resumed @@ -337,7 +326,8 @@ class ResumeCtrl: public event_engine::EventObserver { * @param saved_app application specific section from backup file */ void AddFiles(ApplicationSharedPtr application, const Json::Value& saved_app); - + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief AddSubmenues allows to add sub menues for the application * which should be resumed @@ -347,7 +337,8 @@ class ResumeCtrl: public event_engine::EventObserver { * @param saved_app application specific section from backup file */ void AddSubmenues(ApplicationSharedPtr application, const Json::Value& saved_app); - + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief AddCommands allows to add commands for the application * which should be resumed @@ -357,7 +348,8 @@ class ResumeCtrl: public event_engine::EventObserver { * @param saved_app application specific section from backup file */ void AddCommands(ApplicationSharedPtr application, const Json::Value& saved_app); - + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief AddChoicesets allows to add choice sets for the application * which should be resumed @@ -367,7 +359,8 @@ class ResumeCtrl: public event_engine::EventObserver { * @param saved_app application specific section from backup file */ void AddChoicesets(ApplicationSharedPtr application, const Json::Value& saved_app); - + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief SetGlobalProperties allows to restore global properties. * @@ -376,7 +369,8 @@ class ResumeCtrl: public event_engine::EventObserver { * @param saved_app application specific section from backup file */ void SetGlobalProperties(ApplicationSharedPtr application, const Json::Value& saved_app); - + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief AddSubscriptions allows to restore subscriptions * @@ -385,7 +379,7 @@ class ResumeCtrl: public event_engine::EventObserver { * @param saved_app application specific section from backup file */ void AddSubscriptions(ApplicationSharedPtr application, const Json::Value& saved_app); - + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief ProcessHMIRequests allows to process obtained requests. * @@ -395,15 +389,14 @@ class ResumeCtrl: public event_engine::EventObserver { /** * @brief CheckIcons allows to check application icons - * * @param application application under resumtion application - * - * @param json_object - * + * @param smar_obj contains obj with image * @return true in case icons exists, false otherwise */ - bool CheckIcons(ApplicationSharedPtr application, const Json::Value& json_object); + bool CheckIcons(ApplicationSharedPtr application, + const smart_objects::SmartObject& smart_obj); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief GetFromSavedOrAppend allows to get existed record about application * or adds the new one. @@ -413,14 +406,14 @@ class ResumeCtrl: public event_engine::EventObserver { * @return the reference to the record in applications array. */ Json::Value& GetFromSavedOrAppend(const std::string& mobile_app_id); - +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * @brief CheckIgnCycleRestrictions checks if is needed to resume HMI state * by ign cycle restrictions - * @param json_app - saved application + * @param saved_app - saved application * @return true if resumptions allowed, otherwise return false */ - bool CheckIgnCycleRestrictions(const Json::Value& json_app); + bool CheckIgnCycleRestrictions(const smart_objects::SmartObject& saved_app); /** * @brief DisconnectedInLastIgnCycle should check if was connected in prev ign cycle @@ -433,11 +426,11 @@ class ResumeCtrl: public event_engine::EventObserver { * @brief DisconnectedJustBeforeIgnOff should check if application * was dissconnected in N secconds delay before ign off. * N will be readed from profile - * @param json_app - saved applicationa + * @param saved_app - saved application * @return was dissconnected in N secconds delay before ign off * otherwise return false */ - bool DisconnectedJustBeforeIgnOff(const Json::Value& json_app); + bool DisconnectedJustBeforeIgnOff(const smart_objects::SmartObject& saved_app); /** * @brief CheckDelayAfterIgnOn should check if SDL was started less @@ -449,11 +442,12 @@ class ResumeCtrl: public event_engine::EventObserver { /** * @brief CheckAppRestrictions checks if is needed to resume HMI state * by application type and saved app_level - * @param json_app - saved application + * @param saved_app - saved application * @return true if resumptions allowed, otherwise return false */ bool CheckAppRestrictions(ApplicationSharedPtr application, - const Json::Value& json_app); + const smart_objects::SmartObject& saved_app); + ///////////////////////////////////////////////////////////////////////////////////////////// /** * @brief GetObjectIndex allows to obtain specified obbject index from * applications arrays. @@ -463,6 +457,7 @@ class ResumeCtrl: public event_engine::EventObserver { * @return application's index of or -1 if it doesn't exists */ int GetObjectIndex(const std::string& mobile_app_id); + ///////////////////////////////////////////////////////////////////////////////////////////// /** * @brief Timer callback for restoring HMI Level @@ -474,7 +469,7 @@ class ResumeCtrl: public event_engine::EventObserver { * @brief Loads data on start up */ void LoadResumeData(); - + ///////////////////////////////////////////////////////////////////////////////////////////// /* * @brief Return true if application resumption data is valid, * otherwise false @@ -482,6 +477,22 @@ class ResumeCtrl: public event_engine::EventObserver { * @param index application index in the resumption list */ bool IsResumptionDataValid(uint32_t index); + ///////////////////////////////////////////////////////////////////////////////////////////// + + + /** + * @brief Adds app to resumption list + * + * app_id Application to resume + */ + void AddToResumption(uint32_t app_id); + + /** + * @brief Removes app from resumption list + * + * app_id Application to remove + */ + void RemoveFromResumption(uint32_t app_id); template<typename Iterator> Json::Value Append(Iterator first, diff --git a/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h b/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h new file mode 100644 index 0000000000..7e81b975eb --- /dev/null +++ b/src/components/application_manager/include/application_manager/resumption/resume_ctrl.h @@ -0,0 +1,520 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_RESUME_CTRL_H +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_RESUME_CTRL_H + +#include <stdint.h> +#include <vector> +#include <map> +#include <set> +#include <list> + + +#include "interfaces/HMI_API.h" +#include "interfaces/HMI_API_schema.h" +#include "interfaces/MOBILE_API_schema.h" +#include "connection_handler/connection_handler_observer.h" +#include "connection_handler/device.h" +#include "application_manager/event_engine/event_observer.h" +#include "smart_objects/smart_object.h" +#include "application_manager/application.h" +#include "utils/timer_thread.h" + +namespace application_manager { + +namespace resumption { + +namespace smart_objects = NsSmartDeviceLink::NsSmartObjects; + +class ApplicationManagerImpl; +class Application; +class ResumeCtrl: public event_engine::EventObserver { + + public: + + /** + * @brief Constructor + * @param app_mngr ApplicationManager pointer + */ + explicit ResumeCtrl(ApplicationManagerImpl* app_mngr); + + /** + * @brief Event, that raised if application get resumption response from HMI + * @param event : event object, that contains smart_object with HMI message + */ + virtual void on_event(const event_engine::Event& event); + + /** + * @brief Save all applications info to the file system + */ + void SaveAllApplications(); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief Save application persistent info for future resuming + * @param application is application witch need to be saved + */ + void SaveApplication(ApplicationConstSharedPtr application); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief Set application HMI Level as saved + * @param application is application witch HMI Level is need to restore + * @return true if success, otherwise return false + */ + bool RestoreAppHMIState(ApplicationSharedPtr application); + + /** + * @brief Set application HMI Level as stored in policy + * @param application is application witch HMI Level is need to setup + * @return true if success, otherwise return false + */ + bool SetupDefaultHMILevel(ApplicationSharedPtr application); + + /** + * @brief Setup HmiLevel for application + * Do routine of setting up hmi_level + * @param application is application witch HMI Level is need to setup + * @param hmi_level HMI Level is needed to setup + * @param hmi_level AudioStreamingState is needed to setup + * @param check_policy indicate if policy data consent must be verified + * @return true if success, otherwise return false + */ + bool SetAppHMIState(ApplicationSharedPtr application, + const mobile_apis::HMILevel::eType hmi_level, + bool check_policy = true); + + /** + * @brief Set application HMI Level as saved + * @param application is application witch HMI Level is need to restore + * @return true if success, otherwise return false + */ + bool RestoreApplicationData(ApplicationSharedPtr application); + + /** + * @brief Check if Resume controller have saved instance of application + * @param application is application witch need to be checked + * @return true if exist, false otherwise + */ + bool ApplicationIsSaved(ApplicationConstSharedPtr application); + + /** + * @brief Remove application from list of saved applications + * @param application is application witch need to be removed + * @return return true, if success, otherwise return false + */ + bool RemoveApplicationFromSaved(ApplicationConstSharedPtr application); + + /** + * @brief Increments ignition counter for all registered applications + * and remember ign_off time stamp + */ + void Suspend(); + + /** + * @brief Increments ignition counter for all registered applications + * and remember ign_off time stamp + */ + void OnAwake(); + + /** + * @brief Method starts timer "RsmCtrlPercist" when SDL receives onAwakeSDL notification + */ + void StartSavePersistentDataTimer(); + + /** + * @brief Method stops timer "RsmCtrlPercist" when SDL receives OnExitAllApplication notification + * with reason "SUSPEND" + */ + void StopSavePersistentDataTimer(); + + /** + * @brief Start timer for resumption applications + * Restore D1-D5 data + * @param application that is need to be restored + * @return true if it was saved, otherwise return false + */ + bool StartResumption(ApplicationSharedPtr application, const std::string& hash); + + /** + * @brief Start timer for resumption applications + * Does not restore D1-D5 data + * @param application that is need to be restored + * @return true if it was saved, otherwise return false + */ + bool StartResumptionOnlyHMILevel(ApplicationSharedPtr application); + + /** + * @brief Check if there are all files need for resumption + * @param application that is need to be restored + * @return true if it all files exist, otherwise return false + */ + bool CheckPersistenceFilesForResumption(ApplicationSharedPtr application); + + /** + * @brief Check application hash + * @param application that is need to be restored + * @return true if it was saved, otherwise return false + */ + bool CheckApplicationHash(ApplicationSharedPtr application, const std::string& hash); + + /** + * @brief Check if Resume controller have saved application with hmi app id + * @param hmi_app_id - hmi application id + * @return true if exist, false otherwise + */ + bool IsHMIApplicationIdExist(uint32_t hmi_app_id); + + /** + * @brief Check if Resume controller have saved instance of application + * @param mobile_app_id - mobile application id + * @return true if exist, false otherwise + */ + bool IsApplicationSaved(const std::string& mobile_app_id); + + /** + * @brief Function is used for application resume. HMI app ID must be + * the same(PASA VCA module use it for stored app info). + * Retrieves HMI app ID for the given mobile app ID from stored information. + * + * @param mobile_app_id - mobile application id + * @return HMI app ID + */ + uint32_t GetHMIApplicationID(const std::string& mobile_app_id); + + /** + * @brief SaveDataOnTimer : + * Timer callback for persisting ResumptionData each N seconds + * N gets from property + */ + void SaveDataOnTimer(); + + void ClearResumptionInfo(); + + void ApplicationsDataUpdated() { + is_data_saved = false; + } + + /** + * @brief Resume HMI Level and audio streaming state if needed + * @param application - application to restore hmi level + * and audio streaming state + */ + void StartAppHmiStateResumption(ApplicationSharedPtr application); + /** + * @brief Update launch_time_ to current + */ + void ResetLaunchTime(); + + private: + + + typedef std::pair<uint32_t, uint32_t> application_timestamp; + + std::set<ApplicationSharedPtr> retrieve_application(); + + /** + * @brief This struct need to map + * timestamp and application from correlationID + */ + struct ResumingApp { + uint32_t old_session_key; // session key is the same as app_id + ApplicationSharedPtr app; + }; + + struct TimeStampComparator { + bool operator() (const application_timestamp& lhs, + const application_timestamp& rhs) const{ + return lhs.second < rhs.second; + } + }; + + /** + * @brief geter for launch_time_ + * @return value of launch_time_ + */ + time_t launch_time() const; + + /** + * @brief Check device MAC address + * + * @param application that is need to be restored + * @param saved_device_mac Saved device MAC address + * + * @return TRUE on success, otherwise FALSE + */ + bool IsDeviceMacAddressEqual(ApplicationSharedPtr application, + const std::string& saved_device_mac); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief Get Resumption section of LastState + * @return Resumption section of LastState in Json + */ + Json::Value& GetResumptionData(); + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief Get applications for resumption of LastState + * @return applications for resumption of LastState + */ + Json::Value& GetSavedApplications(); +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief Get the last ignition off time from LastState + * @return the last ignition off time from LastState + */ + time_t GetIgnOffTime(); + + /** + * @brief Setup IgnOff time to LastState + * @param ign_off_time - igition off time + */ + void SetLastIgnOffTime(time_t ign_off_time); + + /** + * @brief Set applications for resumption to LastState + * @parems apps_json applications to write in LastState + */ + void SetSavedApplication(Json::Value& apps_json); + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Json::Value GetApplicationCommands( + ApplicationConstSharedPtr application); + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Json::Value GetApplicationSubMenus( + ApplicationConstSharedPtr application); + Json::Value GetApplicationInteractionChoiseSets( + ApplicationConstSharedPtr application); + Json::Value GetApplicationGlobalProperties( + ApplicationConstSharedPtr application); + Json::Value GetApplicationSubscriptions( + ApplicationConstSharedPtr application); + Json::Value GetApplicationFiles( + ApplicationConstSharedPtr application); + Json::Value GetApplicationShow( + ApplicationConstSharedPtr application); + + Json::Value JsonFromSO(const smart_objects::SmartObject *so); + + void SendHMIRequest(const hmi_apis::FunctionID::eType& function_id, + const smart_objects::SmartObject* msg_params = NULL, + bool use_events = false); + + bool ProcessHMIRequest( + smart_objects::SmartObjectSPtr request = NULL, + bool use_events = false); + + void InsertToTimerQueue(uint32_t app_id, uint32_t time_stamp); + + /** + * @brief AddFiles allows to add files for the application + * which should be resumed + * + * @param application application which will be resumed + * + * @param saved_app application specific section from backup file + */ + void AddFiles(ApplicationSharedPtr application, const Json::Value& saved_app); + + /** + * @brief AddSubmenues allows to add sub menues for the application + * which should be resumed + * + * @param application application which will be resumed + * + * @param saved_app application specific section from backup file + */ + void AddSubmenues(ApplicationSharedPtr application, const Json::Value& saved_app); + + /** + * @brief AddCommands allows to add commands for the application + * which should be resumed + * + * @param application application which will be resumed + * + * @param saved_app application specific section from backup file + */ + void AddCommands(ApplicationSharedPtr application, const Json::Value& saved_app); + + /** + * @brief AddChoicesets allows to add choice sets for the application + * which should be resumed + * + * @param application application which will be resumed + * + * @param saved_app application specific section from backup file + */ + void AddChoicesets(ApplicationSharedPtr application, const Json::Value& saved_app); + + /** + * @brief SetGlobalProperties allows to restore global properties. + * + * @param application application which will be resumed + * + * @param saved_app application specific section from backup file + */ + void SetGlobalProperties(ApplicationSharedPtr application, const Json::Value& saved_app); + + /** + * @brief AddSubscriptions allows to restore subscriptions + * + * @param application application which will be resumed + * + * @param saved_app application specific section from backup file + */ + void AddSubscriptions(ApplicationSharedPtr application, const Json::Value& saved_app); + + /** + * @brief ProcessHMIRequests allows to process obtained requests. + * + * @param requests request that should be processed. + */ + void ProcessHMIRequests(const smart_objects::SmartObjectList& requests); + + /** + * @brief CheckIcons allows to check application icons + * + * @param application application under resumtion application + * + * @param json_object + * + * @return true in case icons exists, false otherwise + */ + bool CheckIcons(ApplicationSharedPtr application, const Json::Value& json_object); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief GetFromSavedOrAppend allows to get existed record about application + * or adds the new one. + * + * @param mobile_app_id application id. + * + * @return the reference to the record in applications array. + */ + Json::Value& GetFromSavedOrAppend(const std::string& mobile_app_id); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief CheckIgnCycleRestrictions checks if is needed to resume HMI state + * by ign cycle restrictions + * @param json_app - saved application + * @return true if resumptions allowed, otherwise return false + */ + bool CheckIgnCycleRestrictions(const Json::Value& json_app); + + /** + * @brief DisconnectedInLastIgnCycle should check if was connected in prev ign cycle + * @param json_app - saved applicationa + * @return true if app connected in frep ign_cycle otherwise return false + */ + bool DisconnectedInLastIgnCycle(const Json::Value& json_app); + + /** + * @brief DisconnectedJustBeforeIgnOff should check if application + * was dissconnected in N secconds delay before ign off. + * N will be readed from profile + * @param json_app - saved applicationa + * @return was dissconnected in N secconds delay before ign off + * otherwise return false + */ + bool DisconnectedJustBeforeIgnOff(const Json::Value& json_app); + + /** + * @brief CheckDelayAfterIgnOn should check if SDL was started less + * then N secconds ago. N will be readed from profile. + * @return true if SDL started N secconds ago, otherwise return false + */ + bool CheckDelayAfterIgnOn(); + + /** + * @brief CheckAppRestrictions checks if is needed to resume HMI state + * by application type and saved app_level + * @param json_app - saved application + * @return true if resumptions allowed, otherwise return false + */ + bool CheckAppRestrictions(ApplicationSharedPtr application, + const Json::Value& json_app); + /** + * @brief GetObjectIndex allows to obtain specified obbject index from + * applications arrays. + * + * @param mobile_app_id application id that should be found. + * + * @return application's index of or -1 if it doesn't exists + */ + int GetObjectIndex(const std::string& mobile_app_id); + + /** + * @brief Timer callback for restoring HMI Level + * + */ + void ApplicationResumptiOnTimer(); + + /* + * @brief Loads data on start up + */ + void LoadResumeData(); + + template<typename Iterator> + Json::Value Append(Iterator first, + Iterator last, + const std::string& key, + Json::Value& result) { + while (first != last) { + result[key].append(*first); + ++first; + } + return result; + } + + /** + * @brief times of IGN_OFF that zombie application have to be saved. + */ + static const uint32_t kApplicationLifes = 3; + + /** + *@brief Mapping applications to time_stamps + * wait for timer to resume HMI Level + * + */ + mutable sync_primitives::Lock queue_lock_; + sync_primitives::Lock resumtion_lock_; + ApplicationManagerImpl* app_mngr_; + timer::TimerThread<ResumeCtrl> save_persistent_data_timer_; + timer::TimerThread<ResumeCtrl> restore_hmi_level_timer_; + std::vector<uint32_t> waiting_for_timer_; + bool is_data_saved; + time_t launch_time_; + ResumptionData* resumption_storage_; +}; + +} // namespace resumption +} // namespace application_manager +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_RESUME_CTRL_H diff --git a/src/components/application_manager/include/application_manager/resumption/resumption_data.h b/src/components/application_manager/include/application_manager/resumption/resumption_data.h new file mode 100644 index 0000000000..bf6494896d --- /dev/null +++ b/src/components/application_manager/include/application_manager/resumption/resumption_data.h @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_DATA_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_DATA_H_ + +namespace application_manager { +namespace resumption { +class ResumptionData { + public: + /** + * @brief Save application persistent info for future resuming + * @param application is application witch need to be saved + */ + virtual void SaveApplication(ApplicationConstSharedPtr application) = 0; + + /** + * @brief Returns HMI level of application from saved data + * @param m_app_id contains mobile application id of application + * @param device_id contains id of device on which is running application + * @return HMI level if saved data does not contain HMI level method + * returns -1 + */ + virtual int GetStoredHMILevel(const std::string& m_app_id, + const std::string& device_id) = 0; + + /** + * @brief restores saved data of application + * @param application contains application for which restores data + * @return true if success, otherwise return false + */ + virtual bool RestoreApplicationData(ApplicationSharedPtr application) = 0; + + /** + * @brief Check if saved data of applications have hmi app id + * @param hmi_app_id - hmi application id + * @return true if exist, false otherwise + */ + virtual bool IsHMIApplicationIdExist(uint32_t hmi_app_id) = 0; + + /** + * @brief Checks if saved data have application + * and removes this data if it is not valid + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return true if data exists and data is valid, false otherwise + */ + virtual bool CheckSavedApplication(const std::string& mobile_app_id, + const std::string& device_id) = 0; + + /** + * @brief Retrieves HMI app ID for the given mobile app ID + * and device ID from stored information. + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return HMI app ID + */ + virtual uint32_t GetHMIApplicationID(const std::string& mobile_app_id, + const std::string& device_id) = 0; + + /** + * @brief Increments ignition counter for all registered applications + * and remember ign_off time stamp + */ + virtual void Suspend() = 0; + + /** + * @brief Retrieves hash ID for the given mobile app ID + * and device ID from stored information. + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param hash_id - parameter which will contain HASH id from saved application + * @return TRUE if application will be found in saved data otherwise + * returns FALSE + */ + virtual bool GetHashId(const std::string& mobile_app_id, + const std::string& device_id, + std::string& hash_id) = 0; + + /** + * @brief Increments ignition counter for all registered applications + * and remember ign_off time stamp + */ + virtual void OnAwake() = 0; + + /** + * @brief Retrieves data of saved appliction for the given mobile app ID + * and device ID + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param saved_app - parameter which will contain data of saved application + * @return TRUE if application will be found in saved data otherwise + * returns FALSE + */ + virtual bool GetSavedApplication(const std::string& mobile_app_id, + const std::string& device_id, + smart_objects::SmartObject& saved_app) = 0; + + /** + * @brief Remove application from list of saved applications + * @param mobile_app_id application witch need to be removed + * @param device_id - contains id of device on which is running application + * @return return true, if success, otherwise return false + */ + virtual bool RemoveApplicationFromSaved(const std::string& mobile_app_id, + const std::string& device_id) = 0; + + /** + * @brief Get the last ignition off time from LastState + * @return the last ignition off time from LastState + */ + virtual uint32_t GetIgnOffTime() = 0; + + /** + * @brief Checks if saved data have application + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return index if data of application exists, otherwise returns -1 + */ + virtual int IsApplicationSaved(const std::string& mobile_app_id, + const std::string& device_id) = 0; + + /** + * @brief Retrieves data from saved application + * @param will be contain data for resume_ctrl + */ + virtual void GetDataForLoadResumeData(smart_objects::SmartObject& saved_data) = 0; + + /** + * @brief Changed HMI level for saved application + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param hmi_level - contains new hmi level for saved application + */ + virtual void SetHMILevelForSavedApplication(const std::string& mobile_app_id, + const std::string& device_id, + int32_t hmi_level) = 0; + + virtual ~ResumptionData() {}; + + + + protected: + + /** + * @brief Do selection of commands from application + * @param application contains application of which selection commands + * @return list of commands + */ + smart_objects::SmartObject GetApplicationCommands( + ApplicationConstSharedPtr application); + + /** + * @brief Do selection of submenues from application + * @param application contains application of which selection submenues + * @return list of submenues + */ + smart_objects::SmartObject GetApplicationSubMenus( + ApplicationConstSharedPtr application); + + /** + * @brief Do selection of interactionChoiceSet from application + * @param application contains application of which selection interactionChoiceSet + * @return list of interaction choice set + */ + smart_objects::SmartObject GetApplicationInteractionChoiseSets( + ApplicationConstSharedPtr application); + + /** + * @brief Do selection of global properties from application + * @param application contains application of which selection global properties + * @return global properties of application + */ + smart_objects::SmartObject GetApplicationGlobalProperties( + ApplicationConstSharedPtr application); + + /** + * @brief Do selection of subscriptions from application + * @param application contains application of which selection subscriptions + * @return subscriptions of application + */ + smart_objects::SmartObject GetApplicationSubscriptions( + ApplicationConstSharedPtr application); + + /** + * @brief Do selection of files from application + * @param application contains application of which selection files + * @return files of application + */ + smart_objects::SmartObject GetApplicationFiles( + ApplicationConstSharedPtr application); + + /** + * @brief AddFiles allows to add files for the application + * which should be resumed + * @param application application which will be resumed + * @param saved_app application specific section from backup file + */ + void AddFiles(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app); + + /** + * @brief AddSubmenues allows to add sub menues for the application + * which should be resumed + * @param application application which will be resumed + * @param saved_app application specific section from backup file + */ + void AddSubmenues(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app); + + /** + * @brief AddCommands allows to add commands for the application + * which should be resumed + * @param application application which will be resumed + * @param saved_app application specific section from backup file + */ + void AddCommands(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app); + + /** + * @brief AddChoicesets allows to add choice sets for the application + * which should be resumed + * @param application application which will be resumed + * @param saved_app application specific section from backup file + */ + void AddChoicesets(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app); + + /** + * @brief SetGlobalProperties allows to restore global properties. + * @param application application which will be resumed + * @param saved_app application specific section from backup file + */ + void SetGlobalProperties(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app); + + /** + * @brief AddSubscriptions allows to restore subscriptions + * @param application application which will be resumed + * @param saved_app application specific section from backup file + */ + void AddSubscriptions(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app); + + /** + * @brief checks pointer that it is not equal NULL + * @param contains pointer which need to check + * @return smartObject from pointer + */ + smart_objects::SmartObject PointerToSmartObj (smart_objects::SmartObject* ptr); + + template<typename Iterator> + void Append(Iterator first, + Iterator last, + const std::string& key, + smart_objects::SmartObject& result) { + int i = 0; + result[key] = smart_objects::SmartObject(smart_objects::SmartType_Array); + while (first != last) { + result[key][i++] = *first; + ++first; + } + } +}; +} // namespace resumption +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_DATA_H_ diff --git a/src/components/application_manager/include/application_manager/resumption/resumption_data_db.h b/src/components/application_manager/include/application_manager/resumption/resumption_data_db.h new file mode 100644 index 0000000000..a18495a4c0 --- /dev/null +++ b/src/components/application_manager/include/application_manager/resumption/resumption_data_db.h @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_DATA_DB_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_DATA_DB_H_ + +namespace application_manager { +namespace resumption { +class ResumptionDataDB : public ResumptionData { + public: + /** + * @brief Save application persistent info for future resuming to db + * @param application is application witch need to be saved + */ + virtual void SaveApplication(ApplicationConstSharedPtr application); + + /** + * @brief Returns HMI level of application from saved data + * @param m_app_id contains mobile application id of application + * @param device_id contains id of device on which is running application + * @return HMI level if saved data does not contain HMI level method + * returns -1 + */ + virtual int GetStoredHMILevel(const std::string& m_app_id, + const std::string& device_id); //////////////////////////////////////// + + /** + * @brief restores saved data of application + * @param application contains application for which restores data + * @return true if success, otherwise return false + */ + virtual bool RestoreApplicationData(ApplicationSharedPtr application); + + /** + * @brief Check if saved data of applications have hmi app id + * @param hmi_app_id - hmi application id + * @return true if exist, false otherwise + */ + virtual bool IsHMIApplicationIdExist(uint32_t hmi_app_id); //////////////////////////////////////////// + + /** + * @brief Checks if saved data have application + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return true if data exists, false otherwise + */ + virtual bool CheckSavedApplication(const std::string& mobile_app_id, //////////////////////////////////////////// + const std::string& device_id); + + /** + * @brief Retrieves HMI app ID for the given mobile app ID + * and device ID from stored information. + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return HMI app ID + */ + virtual uint32_t GetHMIApplicationID(const std::string& mobile_app_id, //////////////////////////////////////////// + const std::string& device_id); + + /** + * @brief Increments ignition counter for all registered applications + * and remember ign_off time stamp + */ + virtual void Suspend(); //////////////////////////////////////////// + + /** + * @brief Retrieves hash ID for the given mobile app ID + * and device ID from stored information. + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param hash_id - parameter which will contain HASH id from saved application + * @return TRUE if application will be found in saved data otherwise + * returns FALSE + */ + virtual bool GetHashId(const std::string& mobile_app_id, //////////////////////////////////////////// + const std::string& device_id, + std::string& hash_id); + + /** + * @brief Increments ignition counter for all registered applications + * and remember ign_off time stamp + */ + virtual void OnAwake(); //////////////////////////////////////////// + + /** + * @brief Retrieves data of saved appliction for the given mobile app ID + * and device ID + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param saved_app - parameter which will contain data of saved application + * @return TRUE if application will be found in saved data otherwise + * returns FALSE + */ + virtual bool GetSavedApplication(const std::string& mobile_app_id, + const std::string& device_id, + smart_objects::SmartObject& saved_app); + + /** + * @brief Remove application from list of saved applications + * @param mobile_app_id application witch need to be removed + * @param device_id - contains id of device on which is running application + * @return return true, if success, otherwise return false + */ + virtual bool RemoveApplicationFromSaved(const std::string& mobile_app_id, //////////////////////////////////////////// + const std::string& device_id); + + /** + * @brief Get the last ignition off time from LastState + * @return the last ignition off time from LastState + */ + virtual uint32_t GetIgnOffTime(); //////////////////////////////////////////// + + /** + * @brief Checks if saved data have application + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return 0 if saved data contains application otherwise returns -1 + */ + virtual int IsApplicationSaved(const std::string& mobile_app_id, //////////////////////////////////////////// + const std::string& device_id); + + /** + * @brief Retrieves data from saved application + * @param will contain data for resume_ctrl + */ + virtual void GetDataForLoadResumeData(smart_objects::SmartObject& saved_data); //////////////////////////////////////////// + + /** + * @brief Changed HMI level for saved application + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param hmi_level - contains new hmi level for saved application + */ + virtual void SetHMILevelForSavedApplication(const std::string& mobile_app_id, //////////////////////////////////////////// + const std::string& device_id, + int32_t hmi_level); + + virtual ~ResumptionDataDB(); + private: + + /** + * @brief Retrieves hmi level from db + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param hmi_level - will contains hmi level for saved application + * @return true if application with mobile id and device id has hmi level + * otherwise returns false + */ + bool SelectHMILevel(const std::string& m_app_id, const std::string& device_id, + int& hmi_level); + /** + * @brief Checks existence HMI id in DB + * @param hmi_app_id - HMI id + * return true if hmiID is same with saved hmiID otherwise returns false + */ + bool CheckExistenceHMIId(const uint32_t hmi_app_id); + + /** + * @brief Select HMI id from saved application + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param hmi_id - will contains hmi id from saved application + */ + void SelectHMIId(const std::string& mobile_app_id, const std::string& device_id, + uint32_t& hmi_id); + + /** + * @brief Select hash id from saved application + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param hash_id - will contains hash id from saved application + */ + bool SelectHashId(const std::string& mobile_app_id, + const std::string& device_id, + std::string& hash_id); + + /** + * @brief Select Ign off time + * @return Ign off time from saved data + */ + uint32_t SelectIgnOffTime(); + + /** + * @brief Checks existence application in DB + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return true if saved data contains application otherwise returns false + */ + bool CheckExistenceApplication(const std::string& mobile_app_id, + const std::string& device_id); + + /** + * @brief Retrieves data from saved application + * @param will contain data for resume_ctrl + */ + void SelectDataForLoadResumeData(smart_objects::SmartObject& saved_data); + + /** + * @brief Updates HMI level of saved application + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param hmi_level - contains hmi level for saved appliction + */ + void UpdateHmiLevel(const std::string& mobile_app_id, + const std::string& device_id, + int32_t hmi_level); + + /** + * @brief Delete saved application from db + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return true if application was found and deleted otherwise returns + * false + */ + bool DeleteSavedApplication(const std::string& mobile_app_id, + const std::string& device_id); + /** + * @brief Updates ignition of count on saved applications after onAwake + * notification + */ + void UpdateDataOnAwake(); + + + +}; +} // namespace resumption +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_DATA_DB_H_ diff --git a/src/components/application_manager/include/application_manager/resumption/resumption_data_json.h b/src/components/application_manager/include/application_manager/resumption/resumption_data_json.h new file mode 100644 index 0000000000..6344b72228 --- /dev/null +++ b/src/components/application_manager/include/application_manager/resumption/resumption_data_json.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_DATA_JSON_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_DATA_JSON_H_ + +namespace application_manager { +namespace resumption { +class ResumptionDataJson : public ResumptionData { + public: + /** + * @brief Save application persistent info for future resuming on json format + * @param application is application witch need to be saved + */ + virtual void SaveApplication(ApplicationConstSharedPtr application); + + /** + * @brief Returns HMI level of application from saved data + * @param m_app_id contains mobile application id of application + * @param device_id contains device id + * @return HMI level if saved data does not contain HMI level method + * returns -1 + */ + virtual int GetStoredHMILevel(const std::string& m_app_id, + const std::string& device_id); + + /** + * @brief restores saved data of application + * @param application contains application for which restores data + * @return true if success, otherwise return false + */ + virtual bool RestoreApplicationData(ApplicationSharedPtr application); + + /** + * @brief Check if saved data of applications have hmi app id + * @param hmi_app_id - hmi application id + * @return true if exist, false otherwise + */ + virtual bool IsHMIApplicationIdExist(uint32_t hmi_app_id); + + /** + * @brief Checks if saved data have application + * and removes this data if it is not valid + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return true if data exists and data is valid, false otherwise + */ + virtual bool CheckSavedApplication(const std::string& mobile_app_id, + const std::string& device_id); + + /** + * @brief Retrieves HMI app ID for the given mobile app ID + * and device ID from stored information. + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return HMI app ID + */ + virtual uint32_t GetHMIApplicationID(const std::string& mobile_app_id, + const std::string& device_id); + + /** + * @brief Increments ignition counter for all registered applications + * and remember ign_off time stamp + */ + virtual void Suspend(); + + /** + * @brief Increments ignition counter for all registered applications + * and remember ign_off time stamp + */ + virtual void OnAwake(); + + /** + * @brief Retrieves hash ID for the given mobile app ID + * and device ID from stored information. + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param hash_id - parameter which will contain HASH id from saved application + * @return TRUE if application will be found in saved data otherwise + * returns FALSE + */ + virtual bool GetHashId(const std::string& mobile_app_id, + const std::string& device_id, + std::string& hash_id); + + /** + * @brief Retrieves data of saved appliction for the given mobile app ID + * and device ID + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param saved_app - parameter which will contain data of saved application + * @return TRUE if application will be found in saved data otherwise + * returns FALSE + */ + virtual bool GetSavedApplication(const std::string& mobile_app_id, + const std::string& device_id, + smart_objects::SmartObject& saved_app); + + /** + * @brief Remove application from list of saved applications + * @param mobile_app_id application witch need to be removed + * @param device_id - contains id of device on which is running application + * @return return true, if success, otherwise return false + */ + virtual bool RemoveApplicationFromSaved(const std::string& mobile_app_id, + const std::string& device_id); + + /** + * @brief Get the last ignition off time from LastState + * @return the last ignition off time from LastState + */ + virtual uint32_t GetIgnOffTime(); + + /** + * @brief Checks if saved data have application + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @return index if data of application exists, otherwise returns -1 + */ + virtual int IsApplicationSaved(const std::string& mobile_app_id, + const std::string& device_id); + + /** + * @brief Retrieves data from saved application + * @param will be contain data for resume_ctrl + */ + virtual void GetDataForLoadResumeData(smart_objects::SmartObject& saved_data); + + /** + * @brief Changed HMI level for saved application + * @param mobile_app_id - mobile application id + * @param device_id - contains id of device on which is running application + * @param hmi_level - contains new hmi level for saved application + */ + virtual void SetHMILevelForSavedApplication(const std::string& mobile_app_id, + const std::string& device_id, + int32_t hmi_level); + + + virtual ~ResumptionDataJson(); + private: + + /** + * @brief GetFromSavedOrAppend allows to get existed record about application + * or adds the new one. + * @param mobile_app_id application id. + * @param device_id unique id of device. + * @return the reference to the record in applications array. + */ + Json::Value& GetFromSavedOrAppend(const std::string& mobile_app_id, + const std::string& device_id); + + /** + * @brief Get applications for resumption of LastState + * @return applications for resumption of LastState + */ + Json::Value& GetSavedApplications(); + + /** + * @brief Get Resumption section of LastState + * @return Resumption section of LastState in Json + */ + Json::Value& GetResumptionData(); + + /** + * @brief GetObjectIndex allows to obtain specified object index from + * applications arrays. + * @param mobile_app_id application id that should be found. + * @param device_id unique id of device. + * @return application's index of or -1 if it doesn't exists + */ + int GetObjectIndex(const std::string& mobile_app_id, + const std::string& device_id); + + /** + * @brief Return true if application resumption data is valid, + * otherwise false + * @param index application index in the resumption list + */ + bool IsResumptionJSONDataValid(uint32_t index); + + /** + * @brief Set applications for resumption to LastState + * @parems apps_json applications to write in LastState + */ + void SetSavedApplication(Json::Value& apps_json); + + /** + * @brief Setup IgnOff time to LastState + * @param ign_off_time - igition off time + */ + void SetLastIgnOffTime(time_t ign_off_time); + + +}; +} // namespace resumption +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_DATA_JSON_H_ diff --git a/src/components/application_manager/include/application_manager/resumption/resumption_sql_queries.h b/src/components/application_manager/include/application_manager/resumption/resumption_sql_queries.h new file mode 100644 index 0000000000..a2be40b8a2 --- /dev/null +++ b/src/components/application_manager/include/application_manager/resumption/resumption_sql_queries.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_SQL_QUERY_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_SQL_QUERY_H_ + +#include <string> + +namespace application_manager { +namespace resumption { + +extern const std::string kCreateSchema; +extern const std::string kSelectHMILevel; +extern const std::string kCheckHMIId; +extern const std::string kSelectHMIId; +extern const std::string kSelectHashId; +extern const std::string kSelectIgnOffTime; +extern const std::string kCheckApplication; +extern const std::string kSelectDataForLoadResumeData; +extern const std::string kUpdateHMILevel; +extern const std::string kDeleteApplication; +extern const std::string kUpdateIgnOffCount; +extern const std::string kDeleteApplicationsAccordingWithIgnOffCount; +extern const std::string kUpdateSuspendData; +extern const std::string KUpdateLastIgnOffTime; + +} // namespace resumption +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_RESUMPTION_RESUMPTION_SQL_QUERY_H_ diff --git a/src/components/application_manager/include/application_manager/smart_object_keys.h b/src/components/application_manager/include/application_manager/smart_object_keys.h index f609f2c2df..84311dde22 100644 --- a/src/components/application_manager/include/application_manager/smart_object_keys.h +++ b/src/components/application_manager/include/application_manager/smart_object_keys.h @@ -52,7 +52,7 @@ const char method_name[] = "methodName"; const char info[] = "info"; const char app_id[] = "appID"; const char hmi_app_id[] = "hmiAppID"; -const char device_mac[] = "deviceMAC"; +const char device_id[] = "deviceID"; const char url[] = "url"; const char urlScheme[] = "urlScheme"; const char packageName[] = "packageName"; @@ -250,7 +250,7 @@ const char priority[] = "priority"; //resuming const char application_commands[] = "applicationCommands"; const char application_submenus[] = "applicationSubMenus"; -const char application_choise_sets[] = "applicationChoiceSets"; +const char application_choice_sets[] = "applicationChoiceSets"; const char application_global_properties[] = "globalProperties"; const char application_vehicle_info[] = "vehicleInfo"; const char application_buttons[] = "buttons"; diff --git a/src/components/application_manager/src/application_impl.cc b/src/components/application_manager/src/application_impl.cc index d45cc50bd4..11ad1a54e8 100644 --- a/src/components/application_manager/src/application_impl.cc +++ b/src/components/application_manager/src/application_impl.cc @@ -96,6 +96,8 @@ ApplicationImpl::ApplicationImpl(uint32_t application_id, has_been_activated_(false), tts_properties_in_none_(false), tts_properties_in_full_(false), + is_application_data_changed_( + StateApplicationData::kNotSaveDataForResumption), put_file_in_none_count_(0), delete_file_in_none_count_(0), list_files_in_none_count_(0), @@ -778,9 +780,20 @@ const std::string& ApplicationImpl::curHash() const { return hash_val_; } +StateApplicationData ApplicationImpl::is_application_data_changed() const { + return is_application_data_changed_; +} + +void ApplicationImpl::set_is_application_data_changed( + StateApplicationData state_application_data) { + is_application_data_changed_ = state_application_data; +} + void ApplicationImpl::UpdateHash() { LOG4CXX_AUTO_TRACE(logger_); hash_val_ = utils::gen_hash(profile::Profile::instance()->hash_string_size()); + is_application_data_changed_ = + StateApplicationData::kNotSaveDataForResumption; MessageHelper::SendHashUpdateNotification(app_id()); } diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 2af9b9128f..2a54a26619 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -2189,7 +2189,6 @@ void ApplicationManagerImpl::HeadUnitReset( } } - void ApplicationManagerImpl::SendOnSDLClose() { LOG4CXX_AUTO_TRACE(logger_); diff --git a/src/components/application_manager/src/commands/mobile/register_app_interface_request.cc b/src/components/application_manager/src/commands/mobile/register_app_interface_request.cc index 05c74092ef..77bf827305 100644 --- a/src/components/application_manager/src/commands/mobile/register_app_interface_request.cc +++ b/src/components/application_manager/src/commands/mobile/register_app_interface_request.cc @@ -227,6 +227,21 @@ void RegisterAppInterfaceRequest::Run() { msg_params[strings::app_name].asString() << " hasn't been registered!"); } else { + + // For resuming application need to restore hmi_app_id from resumeCtrl + const std::string mobile_app_id = msg_params[strings::app_id].asString(); + const std::string device_id = + MessageHelper::GetDeviceMacAddressForHandle(application->device()); + ResumeCtrl& resumer = ApplicationManagerImpl::instance()->resume_controller(); + + // there is side affect with 2 mobile app with the same mobile app_id + if (resumer.IsApplicationSaved(mobile_app_id, device_id)) { + app->set_hmi_application_id( + resumer.GetHMIApplicationID(mobile_app_id, device_id)); + } else { + app->set_hmi_application_id( + ApplicationManagerImpl::instance()->GenerateNewHMIAppID()); + } app->set_is_media_application( msg_params[strings::is_media_application].asBool()); @@ -492,7 +507,9 @@ void RegisterAppInterfaceRequest::SendRegisterAppInterfaceResponseToMobile( // in case application exist in resumption we need to send resumeVrgrammars if (false == resumption) { - resumption = resumer.IsApplicationSaved(application->mobile_app_id()); + resumption = resumer.IsApplicationSaved( + application->mobile_app_id(), + MessageHelper::GetDeviceMacAddressForHandle(application->device())); } diff --git a/src/components/application_manager/src/message_helper.cc b/src/components/application_manager/src/message_helper.cc index 19229b9b12..a8f4e7fd37 100644 --- a/src/components/application_manager/src/message_helper.cc +++ b/src/components/application_manager/src/message_helper.cc @@ -1155,6 +1155,54 @@ smart_objects::SmartObjectList MessageHelper::CreateAddCommandRequestToHMI( return requests; } +static smart_objects::SmartObjectList +MessageHelper::CreateAddVRCommandRequestFromChoiceToHMI(ApplicationConstSharedPtr app) { + smart_objects::SmartObjectList requests; + if (!app) { + LOG4CXX_ERROR(logger_, "Invalid application"); + return requests; + } + const DataAccessor<ChoiceSetMap> accessor = app->choice_set_map(); + const ChoiceSetMap& choices = accessor.GetData(); + ChoiceSetMap::const_iterator it = choices.begin(); + for (; choices.end() != it; ++it) { + const uint32_t choice_grammar_id = (*(it->second))[strings::grammar_id].asUint(); + const size_t size = (*(it->second))[strings::choice_set].length(); + for (size_t j = 0; j < size; ++j) { + smart_objects::SmartObjectSPtr vr_command = new smart_objects::SmartObject( + smart_objects::SmartType_Map); + if (!vr_command) { + return requests; + } + (*vr_command)[strings::params][strings::function_id] = + static_cast<int>(hmi_apis::FunctionID::VR_AddCommand); + (*vr_command)[strings::params][strings::message_type] = + static_cast<int>(hmi_apis::messageType::request); + (*vr_command)[strings::params][strings::protocol_version] = + commands::CommandImpl::protocol_version_; + (*vr_command)[strings::params][strings::protocol_type] = + commands::CommandImpl::hmi_protocol_type_; + (*vr_command)[strings::params][strings::correlation_id] = + ApplicationManagerImpl::instance()->GetNextHMICorrelationID(); + smart_objects::SmartObject msg_params = smart_objects::SmartObject( + smart_objects::SmartType_Map); + msg_params[strings::app_id] = application->app_id(); + msg_params[strings::cmd_id] = + (*(it->second))[strings::choice_set][j][strings::choice_id]; + msg_params[strings::vr_commands] = smart_objects::SmartObject( + smart_objects::SmartType_Array); + msg_params[strings::vr_commands] = + (*(it->second))[strings::choice_set][j][strings::vr_commands]; + + msg_params[strings::type] = hmi_apis::Common_VRCommandType::Choice; + msg_params[strings::grammar_id] = choice_grammar_id; + (*vr_command)[strings::msg_params] = msg_params; + requests.push_back(vr_command); + } + } + return requests; +} + smart_objects::SmartObjectSPtr MessageHelper::CreateChangeRegistration( int32_t function_id, int32_t language, uint32_t app_id, const smart_objects::SmartObject* app_types) { diff --git a/src/components/application_manager/src/resume_ctrl.cpp b/src/components/application_manager/src/resume_ctrl.cpp index 6dd46aa3de..6e7f2b473f 100644 --- a/src/components/application_manager/src/resume_ctrl.cpp +++ b/src/components/application_manager/src/resume_ctrl.cpp @@ -71,13 +71,23 @@ ResumeCtrl::ResumeCtrl(ApplicationManagerImpl* app_mngr) void ResumeCtrl::SaveAllApplications() { LOG4CXX_AUTO_TRACE(logger_); - std::set<ApplicationSharedPtr> apps(retrieve_application()); - std::for_each(apps.begin(), - apps.end(), - std::bind1st(std::mem_fun(&ResumeCtrl::SaveApplication), this)); - // remove old + std::set<ApplicationSharedPtr> apps(retrieve_application()); + std::set<ApplicationSharedPtr>::iterator it_begin = apps.begin(); + std::set<ApplicationSharedPtr>::iterator it_end = apps.end(); + + resumtion_lock_.Acquire(); + for (; it_begin != it_end; ++it_begin) { + if (StateApplicationData::kNotSavedDataForResumption == + ((*it_begin)->is_application_data_changed())) { + resumption_storage->SaveApplication(); + (*it_begin)->set_is_application_data_changed( + StateApplicationData::kSavedDataForResumption); + } + } + resumtion_lock_.Release(); } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::SaveApplication(ApplicationConstSharedPtr application) { DCHECK(application.get()); @@ -99,7 +109,7 @@ void ResumeCtrl::SaveApplication(ApplicationConstSharedPtr application) { resumtion_lock_.Acquire(); Json::Value& json_app = GetFromSavedOrAppend(m_app_id); - json_app[strings::device_mac] = + json_app[strings::device_id] = MessageHelper::GetDeviceMacAddressForHandle(application->device()); json_app[strings::app_id] = m_app_id; json_app[strings::grammar_id] = grammar_id; @@ -114,7 +124,7 @@ void ResumeCtrl::SaveApplication(ApplicationConstSharedPtr application) { GetApplicationCommands(application); json_app[strings::application_submenus] = GetApplicationSubMenus(application); - json_app[strings::application_choise_sets] = + json_app[strings::application_choice_sets] = GetApplicationInteractionChoiseSets(application); json_app[strings::application_global_properties] = GetApplicationGlobalProperties(application); @@ -126,13 +136,16 @@ void ResumeCtrl::SaveApplication(ApplicationConstSharedPtr application) { resumtion_lock_.Release(); } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::on_event(const event_engine::Event& event) { LOG4CXX_TRACE(logger_, "Response from HMI command"); } + bool ResumeCtrl::RestoreAppHMIState(ApplicationSharedPtr application) { LOG4CXX_AUTO_TRACE(logger_); + using namespace mobile_apis; if (!application) { LOG4CXX_ERROR(logger_, " RestoreApplicationHMILevel() application pointer in invalid"); @@ -140,20 +153,13 @@ bool ResumeCtrl::RestoreAppHMIState(ApplicationSharedPtr application) { } LOG4CXX_DEBUG(logger_, "ENTER app_id : " << application->app_id()); - sync_primitives::AutoLock lock(resumtion_lock_); - const int idx = GetObjectIndex(application->mobile_app_id()); - if (-1 != idx) { - const Json::Value& json_app = GetSavedApplications()[idx]; - if (json_app.isMember(strings::hmi_level)) { + const HMILevel::eType saved_hmi_level = static_cast<mobile_apis::HMILevel::eType>( + resumption_storage->GetStoredHMILevel(application->mobile_app_id(), + MessageHelper::GetDeviceMacAddressForHandle(application->device()))); - const HMILevel::eType saved_hmi_level = - static_cast<mobile_apis::HMILevel::eType>( - json_app[strings::hmi_level].asInt()); - LOG4CXX_DEBUG(logger_, "Saved HMI Level is : " << saved_hmi_level); - return SetAppHMIState(application, saved_hmi_level); - } else { - LOG4CXX_FATAL(logger_, "There are some unknown keys among the stored apps"); - } + if (mobile_apis::HMILevel::INVALID_ENUM != saved_hmi_level) { + LOG4CXX_DEBUG(logger_, "Saved HMI Level is : " << saved_hmi_level); + return SetAppHMIState(application, saved_hmi_level); } LOG4CXX_INFO(logger_, "Failed to restore application HMILevel"); return false; @@ -247,48 +253,31 @@ bool ResumeCtrl::SetAppHMIState(ApplicationSharedPtr application, return true; } + bool ResumeCtrl::RestoreApplicationData(ApplicationSharedPtr application) { LOG4CXX_AUTO_TRACE(logger_); - if (!application.valid()) { - LOG4CXX_ERROR(logger_, "Application pointer in invalid"); - return false; - } - - LOG4CXX_DEBUG(logger_, "ENTER app_id : " << application->app_id()); sync_primitives::AutoLock lock(resumtion_lock_); - const int idx = GetObjectIndex(application->mobile_app_id()); - if (-1 == idx) { - LOG4CXX_WARN(logger_, "Application not saved"); - return false; - } - - const Json::Value& saved_app = GetSavedApplications()[idx]; - if(saved_app.isMember(strings::grammar_id)) { - const uint32_t app_grammar_id = saved_app[strings::grammar_id].asUInt(); - application->set_grammar_id(app_grammar_id); - - AddFiles(application, saved_app); - AddSubmenues(application, saved_app); - AddCommands(application, saved_app); - AddChoicesets(application, saved_app); - SetGlobalProperties(application, saved_app); - AddSubscriptions(application, saved_app); + const bool result = resumption_storage->RestoreApplicationData(application); + if (result) { + ProcessHMIRequests(MessageHelper::CreateAddSubMenuRequestToHMI(application)); + ProcessHMIRequests(MessageHelper::CreateAddCommandRequestToHMI(application)); + ProcessHMIRequests( + MessageHelper::CreateAddVRCommandRequestFromChoiceToHMI(application)); + MessageHelper::SendGlobalPropertiesToHMI(application); + ProcessHMIRequests(MessageHelper::GetIVISubscriptionRequests(application)); } - return true; + return result; } bool ResumeCtrl::IsHMIApplicationIdExist(uint32_t hmi_app_id) { LOG4CXX_TRACE(logger_, "ENTER hmi_app_id :" << hmi_app_id); + sync_primitives::AutoLock lock(resumtion_lock_); - for (Json::Value::iterator it = GetSavedApplications().begin(); - it != GetSavedApplications().end(); ++it) { - if ((*it).isMember(strings::hmi_app_id)) { - if ((*it)[strings::hmi_app_id].asUInt() == hmi_app_id) { - return true; - } - } + if (resumption_storage->IsHMIApplicationIdExist(hmi_app_id)) { + return true; } + ApplicationManagerImpl::ApplicationListAccessor accessor; ApplicationManagerImpl::ApplictionSet apps(accessor.applications()); ApplicationManagerImpl::ApplictionSetIt it = apps.begin(); @@ -304,44 +293,22 @@ bool ResumeCtrl::IsHMIApplicationIdExist(uint32_t hmi_app_id) { return false; } -bool ResumeCtrl::IsApplicationSaved(const std::string& mobile_app_id) { +bool ResumeCtrl::IsApplicationSaved(const std::string& mobile_app_id, + const std::string& device_id) { LOG4CXX_TRACE(logger_, "ENTER mobile_app_id :" << mobile_app_id); sync_primitives::AutoLock lock(resumtion_lock_); - int index = GetObjectIndex(mobile_app_id); - if (-1 == index) { - return false; - } - - if (!IsResumptionDataValid(index)) { - LOG4CXX_INFO(logger_, "Resumption data for app " << mobile_app_id << - " is corrupted. Remove application from resumption list"); - RemoveApplicationFromSaved(mobile_app_id); - return false; - } - - return true; + return resumption_storage->CheckSavedApplication(mobile_app_id, device_id); } -uint32_t ResumeCtrl::GetHMIApplicationID(const std::string& mobile_app_id) { +uint32_t ResumeCtrl::GetHMIApplicationID(const std::string& mobile_app_id, + const std::string& device_id) { LOG4CXX_AUTO_TRACE(logger_); - uint32_t hmi_app_id = 0; sync_primitives::AutoLock lock(resumtion_lock_); - const int idx = GetObjectIndex(mobile_app_id); - if (-1 == idx) { - LOG4CXX_WARN(logger_, "Application not saved"); - return hmi_app_id; - } - - const Json::Value& json_app = GetSavedApplications()[idx]; - if (json_app.isMember(strings::app_id)) { - hmi_app_id = json_app[strings::hmi_app_id].asUInt(); - } - LOG4CXX_DEBUG(logger_, "hmi_app_id :" << hmi_app_id); - return hmi_app_id; + return resumption_storage->GetHMIApplicationID(mobile_app_id, device_id); } - +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool ResumeCtrl::RemoveApplicationFromSaved(const std::string& mobile_app_id) { LOG4CXX_TRACE(logger_, "Remove mobile_app_id " << mobile_app_id); sync_primitives::AutoLock lock(resumtion_lock_); @@ -373,54 +340,22 @@ bool ResumeCtrl::RemoveApplicationFromSaved(const std::string& mobile_app_id) { LOG4CXX_TRACE(logger_, "EXIT result: " << (result ? "true" : "false")); return result; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::Suspend() { LOG4CXX_AUTO_TRACE(logger_); + StopSavePersistentDataTimer(); SaveAllApplications(); - Json::Value to_save; sync_primitives::AutoLock lock(resumtion_lock_); - for (Json::Value::iterator it = GetSavedApplications().begin(); - it != GetSavedApplications().end(); ++it) { - if ((*it).isMember(strings::suspend_count)) { - const uint32_t suspend_count = (*it)[strings::suspend_count].asUInt(); - (*it)[strings::suspend_count] = suspend_count + 1; - } else { - LOG4CXX_WARN(logger_, "Unknown key among saved applications"); - (*it)[strings::suspend_count] = 1; - } - if ((*it).isMember(strings::ign_off_count)) { - const uint32_t ign_off_count = (*it)[strings::ign_off_count].asUInt(); - if (ign_off_count < kApplicationLifes) { - (*it)[strings::ign_off_count] = ign_off_count + 1; - to_save.append(*it); - } - } else { - LOG4CXX_WARN(logger_, "Unknown key among saved applications"); - (*it)[strings::ign_off_count] = 1; - } - } - SetSavedApplication(to_save); - SetLastIgnOffTime(time(NULL)); - LOG4CXX_DEBUG(logger_, - GetResumptionData().toStyledString()); - resumption::LastState::instance()->SaveToFileSystem(); + resumption_storage->Suspend(); } void ResumeCtrl::OnAwake() { LOG4CXX_AUTO_TRACE(logger_); sync_primitives::AutoLock lock(resumtion_lock_); - for (Json::Value::iterator it = GetSavedApplications().begin(); - it != GetSavedApplications().end(); ++it) { - if ((*it).isMember(strings::ign_off_count)) { - const uint32_t ign_off_count = (*it)[strings::ign_off_count].asUInt(); - (*it)[strings::ign_off_count] = ign_off_count - 1; - } else { - LOG4CXX_WARN(logger_, "Unknown key among saved applications"); - (*it)[strings::ign_off_count] = 0; - } - } + resumption_storage->OnAwake(); ResetLaunchTime(); StartSavePersistentDataTimer(); } @@ -459,35 +394,32 @@ bool ResumeCtrl::StartResumption(ApplicationSharedPtr application, << "received hash = " << hash); sync_primitives::AutoLock lock(resumtion_lock_); - const int idx = GetObjectIndex(application->mobile_app_id()); - if (-1 == idx) { - LOG4CXX_WARN(logger_, "Application not saved"); + std::string saved_hash; + bool result = resumption_storage->GetHashId( + application->mobile_app_id(), + MessageHelper::GetDeviceMacAddressForHandle(application->device()), + saved_hash); + + if (!result) { return false; } - const Json::Value& json_app = GetSavedApplications()[idx]; - LOG4CXX_DEBUG(logger_, "Saved_application_data: " << json_app.toStyledString()); - if (json_app.isMember(strings::hash_id) && json_app.isMember(strings::time_stamp)) { - const std::string& saved_hash = json_app[strings::hash_id].asString(); - - if (saved_hash == hash) { - RestoreApplicationData(application); - } - application->UpdateHash(); - - queue_lock_.Acquire(); - waiting_for_timer_.push_back(application->app_id()); - queue_lock_.Release(); - if (!is_resumption_active_) { - is_resumption_active_ = true; - restore_hmi_level_timer_.start( - profile::Profile::instance()->app_resuming_timeout()); - } - } else { - LOG4CXX_INFO(logger_, "There are some unknown keys in the dictionary."); - return false; + if (saved_hash == hash) { + RestoreApplicationData(application); } + application->UpdateHash(); + sync_primitives::AutoUnlock unlock(lock); + AddToResumption(application->app_id()); + + queue_lock_.Acquire(); + waiting_for_timer_.push_back(application->app_id()); + queue_lock_.Release(); + if (!is_resumption_active_) { + is_resumption_active_ = true; + restore_hmi_level_timer_.start( + profile::Profile::instance()->app_resuming_timeout()); + } return true; } @@ -496,35 +428,42 @@ void ResumeCtrl::StartAppHmiStateResumption(ApplicationSharedPtr application) { using namespace profile; using namespace date_time; DCHECK_OR_RETURN_VOID(application); - const int idx = GetObjectIndex(application->mobile_app_id()); - DCHECK_OR_RETURN_VOID(idx != -1); - const Json::Value& json_app = GetSavedApplications()[idx]; + smart_objects::SmartObject saved_app(smart_objects::SmartType_Map); + sync_primitives::AutoLock lock(resumtion_lock_); + bool result = resumption_storage->GetSavedApplication( + application->mobile_app_id(), + MessageHelper::GetDeviceMacAddressForHandle(application->device()), + saved_app); + DCHECK_OR_RETURN_VOID(result); - if (!json_app.isMember(strings::ign_off_count)) { + if (!saved_app.keyExists(strings::ign_off_count)) { LOG4CXX_INFO(logger_, "Do not need to resume application " << application->app_id()); SetupDefaultHMILevel(application); return; } - // check if if is resumption during one IGN cycle - const uint32_t ign_off_count = json_app[strings::ign_off_count].asUInt(); + // check if is resumption during one IGN cycle + const uint32_t ign_off_count = saved_app[strings::ign_off_count].asUInt(); + const std::string m_app_id = application->mobile_app_id(); + const std::string device_id = + MessageHelper::GetDeviceMacAddressForHandle(application->device()); if (0 == ign_off_count) { - if (CheckAppRestrictions(application, json_app)) { + if (CheckAppRestrictions(application, saved_app)) { LOG4CXX_INFO(logger_, "Resume application after short IGN cycle"); RestoreAppHMIState(application); - RemoveApplicationFromSaved(application->mobile_app_id()); + resumption_storage->RemoveApplicationFromSaved(m_app_id, device_id); } else { LOG4CXX_INFO(logger_, "Do not need to resume application " << application->app_id()); - } + } } else { - if (CheckIgnCycleRestrictions(json_app) && - CheckAppRestrictions(application, json_app)) { + if (CheckIgnCycleRestrictions(saved_app) && + CheckAppRestrictions(application, saved_app)) { LOG4CXX_INFO(logger_, "Resume application after IGN cycle"); RestoreAppHMIState(application); - RemoveApplicationFromSaved(application->mobile_app_id()); + resumption_storage->RemoveApplicationFromSaved(m_app_id, device_id); } else { LOG4CXX_INFO(logger_, "Do not need to resume application " << application->app_id()); @@ -551,8 +490,9 @@ bool ResumeCtrl::StartResumptionOnlyHMILevel(ApplicationSharedPtr application) { << application->mobile_app_id()); sync_primitives::AutoLock lock(resumtion_lock_); - const int idx = GetObjectIndex(application->mobile_app_id()); - if (-1 == idx) { + if (-1 == (resumption_storage->IsApplicationSaved( + application->mobile_app_id, + MessageHelper::GetDeviceMacAddressForHandle(application->device())))) { LOG4CXX_WARN(logger_, "Application not saved"); return false; } @@ -578,28 +518,31 @@ bool ResumeCtrl::CheckPersistenceFilesForResumption(ApplicationSharedPtr applica } LOG4CXX_DEBUG(logger_, "Process app_id = " << application->app_id()); + smart_objects::SmartObject saved_app(smart_objects::SmartType_Map); sync_primitives::AutoLock lock(resumtion_lock_); - const int idx = GetObjectIndex(application->mobile_app_id()); - if (-1 == idx) { + bool result = resumption_storage->GetSavedApplication( + application->mobile_app_id(), + MessageHelper::GetDeviceMacAddressForHandle(application->device()), + saved_app); + + if (!result) { LOG4CXX_WARN(logger_, "Application not saved"); return false; } - const Json::Value& saved_app = GetSavedApplications()[idx]; - - if (!saved_app.isMember(strings::application_commands) || - !saved_app.isMember(strings::application_choise_sets)) { - LOG4CXX_WARN(logger_, "application_commands or " - "application_choise_sets are not exists"); - return false; - } + if (!saved_app.keyExists(strings::application_commands) || + !saved_app.keyExists(strings::application_choice_sets)) { + LOG4CXX_WARN(logger_, "application_commands or " + "application_choice_sets are not exists"); + return false; + } - if (!CheckIcons(application, saved_app[strings::application_commands])) { - return false; - } - if (!CheckIcons(application, saved_app[strings::application_choise_sets])) { - return false; - } + if (!CheckIcons(application, saved_app[strings::application_commands])) { + return false; + } + if (!CheckIcons(application, saved_app[strings::application_choice_sets])) { + return false; + } LOG4CXX_DEBUG(logger_, " result = true"); return true; } @@ -615,25 +558,23 @@ bool ResumeCtrl::CheckApplicationHash(ApplicationSharedPtr application, << " hash : " << hash); sync_primitives::AutoLock lock(resumtion_lock_); + std::string saved_hash; + bool result = resumption_storage->GetHashId( + application->mobile_app_id(), + MessageHelper::GetDeviceMacAddressForHandle(application->device()), + saved_hash); + const int idx = GetObjectIndex(application->mobile_app_id()); - if (-1 == idx) { - LOG4CXX_WARN(logger_, "Application not saved"); + if (!result) { return false; } const Json::Value& json_app = GetSavedApplications()[idx]; - - if (json_app.isMember(strings::hash_id)) { - const std::string& saved_hash = json_app[strings::hash_id].asString(); - - LOG4CXX_TRACE(logger_, "Found saved application : " << json_app.toStyledString()); - LOG4CXX_INFO(logger_, "received hash = " << hash); - LOG4CXX_INFO(logger_, "saved hash = " << saved_hash); - if (hash == saved_hash) { - return true; - } + LOG4CXX_INFO(logger_, "received hash = " << hash); + LOG4CXX_INFO(logger_, "saved hash = " << saved_hash); + if (hash == saved_hash) { + return true; } - return false; } @@ -651,13 +592,8 @@ void ResumeCtrl::SaveDataOnTimer() { } } -bool ResumeCtrl::IsDeviceMacAddressEqual(ApplicationSharedPtr application, - const std::string& saved_device_mac) { - const std::string device_mac = - MessageHelper::GetDeviceMacAddressForHandle(application->device()); - return device_mac == saved_device_mac; -} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Json::Value&ResumeCtrl::GetResumptionData() { LOG4CXX_AUTO_TRACE(logger_); Json::Value& last_state = resumption::LastState::instance()->dictionary; @@ -672,7 +608,8 @@ Json::Value&ResumeCtrl::GetResumptionData() { } return resumption; } - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Json::Value& ResumeCtrl::GetSavedApplications() { LOG4CXX_AUTO_TRACE(logger_); Json::Value& resumption = GetResumptionData(); @@ -687,7 +624,8 @@ Json::Value& ResumeCtrl::GetSavedApplications() { } return resume_app_list; } - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// time_t ResumeCtrl::GetIgnOffTime() { LOG4CXX_AUTO_TRACE(logger_); Json::Value& resumption = GetResumptionData(); @@ -699,28 +637,22 @@ time_t ResumeCtrl::GetIgnOffTime() { resumption[strings::last_ign_off_time].asUInt()); return last_ign_off; } - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::SetLastIgnOffTime(time_t ign_off_time) { LOG4CXX_AUTO_TRACE(logger_); LOG4CXX_WARN(logger_, "ign_off_time = " << ign_off_time); Json::Value& resumption = GetResumptionData(); resumption[strings::last_ign_off_time] = static_cast<uint32_t>(ign_off_time); } - - +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::SetSavedApplication(Json::Value& apps_json) { Json::Value& app_list = GetSavedApplications(); app_list = apps_json; } - -void ResumeCtrl::ClearResumptionInfo() { - LOG4CXX_AUTO_TRACE(logger_); - Json::Value empty_json; - - SetSavedApplication(empty_json); - resumption::LastState::instance()->SaveToFileSystem(); -} - +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Json::Value ResumeCtrl::GetApplicationCommands( ApplicationConstSharedPtr application) { LOG4CXX_AUTO_TRACE(logger_); @@ -741,7 +673,8 @@ Json::Value ResumeCtrl::GetApplicationCommands( } return result; } - +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Json::Value ResumeCtrl::GetApplicationSubMenus( ApplicationConstSharedPtr application) { LOG4CXX_AUTO_TRACE(logger_); @@ -762,7 +695,8 @@ Json::Value ResumeCtrl::GetApplicationSubMenus( } return result; } - +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Json::Value ResumeCtrl::GetApplicationInteractionChoiseSets( ApplicationConstSharedPtr application) { DCHECK(application.get()); @@ -781,7 +715,8 @@ Json::Value ResumeCtrl::GetApplicationInteractionChoiseSets( } return result; } - +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Json::Value ResumeCtrl::GetApplicationGlobalProperties( ApplicationConstSharedPtr application) { LOG4CXX_AUTO_TRACE(logger_); @@ -811,7 +746,8 @@ Json::Value ResumeCtrl::GetApplicationGlobalProperties( sgp[strings::menu_icon] = JsonFromSO(menu_icon); return sgp; } - +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Json::Value ResumeCtrl::GetApplicationSubscriptions( ApplicationConstSharedPtr application) { LOG4CXX_AUTO_TRACE(logger_); @@ -855,29 +791,7 @@ Json::Value ResumeCtrl::GetApplicationFiles( } return result; } - -Json::Value ResumeCtrl::GetApplicationShow( - ApplicationConstSharedPtr application) { - DCHECK(application.get()); - LOG4CXX_TRACE(logger_, "ENTER app_id:" - << application->app_id()); - - Json::Value result; - const smart_objects::SmartObject* show_so = application->show_command(); - if (!show_so) { - return result; - } - result = JsonFromSO(show_so); - return result; -} - -Json::Value ResumeCtrl::JsonFromSO(const smart_objects::SmartObject *so) { - Json::Value temp; - if (so) { - Formatters::CFormatterJsonBase::objToJsonValue(*so, temp); - } - return temp; -} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool ResumeCtrl::ProcessHMIRequest(smart_objects::SmartObjectSPtr request, bool use_events) { @@ -898,6 +812,7 @@ bool ResumeCtrl::ProcessHMIRequest(smart_objects::SmartObjectSPtr request, return false; } +////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::AddFiles(ApplicationSharedPtr application, const Json::Value& saved_app) { LOG4CXX_AUTO_TRACE(logger_); if (saved_app.isMember(strings::application_files)) { @@ -922,7 +837,8 @@ void ResumeCtrl::AddFiles(ApplicationSharedPtr application, const Json::Value& s LOG4CXX_FATAL(logger_, "application_files section is not exists"); } } - +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::AddSubmenues(ApplicationSharedPtr application, const Json::Value& saved_app) { LOG4CXX_AUTO_TRACE(logger_); if (saved_app.isMember(strings::application_submenus)) { @@ -940,7 +856,8 @@ void ResumeCtrl::AddSubmenues(ApplicationSharedPtr application, const Json::Valu LOG4CXX_FATAL(logger_, "application_submenus section is not exists"); } } - +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::AddCommands(ApplicationSharedPtr application, const Json::Value& saved_app) { LOG4CXX_AUTO_TRACE(logger_); if (saved_app.isMember(strings::application_commands)) { @@ -958,11 +875,11 @@ void ResumeCtrl::AddCommands(ApplicationSharedPtr application, const Json::Value LOG4CXX_FATAL(logger_, "application_commands section is not exists"); } } - +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::AddChoicesets(ApplicationSharedPtr application, const Json::Value& saved_app) { - LOG4CXX_AUTO_TRACE(logger_); - if (saved_app.isMember(strings::application_choise_sets)) { - const Json::Value& app_choise_sets = saved_app[strings::application_choise_sets]; + if(saved_app.isMember(strings::application_choice_sets)) { + const Json::Value& app_choise_sets = saved_app[strings::application_choice_sets]; for (Json::Value::iterator json_it = app_choise_sets.begin(); json_it != app_choise_sets.end(); ++json_it) { const Json::Value& json_choiset = *json_it; @@ -993,7 +910,8 @@ void ResumeCtrl::AddChoicesets(ApplicationSharedPtr application, const Json::Val LOG4CXX_FATAL(logger_, "There is no any choicesets"); } } - +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::SetGlobalProperties(ApplicationSharedPtr application, const Json::Value& saved_app) { LOG4CXX_AUTO_TRACE(logger_); const Json::Value& global_properties = saved_app[strings::application_global_properties]; @@ -1004,7 +922,8 @@ void ResumeCtrl::SetGlobalProperties(ApplicationSharedPtr application, const Jso MessageHelper::SendGlobalPropertiesToHMI(application); } } - +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::AddSubscriptions(ApplicationSharedPtr application, const Json::Value& saved_app) { LOG4CXX_AUTO_TRACE(logger_); if (saved_app.isMember(strings::application_subscribtions)) { @@ -1032,6 +951,7 @@ void ResumeCtrl::AddSubscriptions(ApplicationSharedPtr application, const Json:: MessageHelper::SendAllOnButtonSubscriptionNotificationsForApp(application); } } +////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ResumeCtrl::ProcessHMIRequests(const smart_objects::SmartObjectList& requests) { for (smart_objects::SmartObjectList::const_iterator it = requests.begin(), @@ -1042,30 +962,28 @@ void ResumeCtrl::ProcessHMIRequests(const smart_objects::SmartObjectList& reques } bool ResumeCtrl::CheckIcons(ApplicationSharedPtr application, - const Json::Value& json_object) { + const smart_objects::SmartObject& smart_obj) { LOG4CXX_AUTO_TRACE(logger_); bool result = true; - if (!json_object.isNull()) { - Json::Value::const_iterator json_it = json_object.begin(); - for (;json_it != json_object.end() && result; ++json_it) { - const Json::Value& json_command = *json_it; - if (!json_command.isNull()) { - smart_objects::SmartObject message(smart_objects::SmartType::SmartType_Map); - Formatters::CFormatterJsonBase::jsonValueToObj(json_command, message); + if (smart_objects::SmartType_Null != smart_obj.getType()) { + size_t length_obj = smart_obj.length(); + for (size_t i = 0; i < length_obj && result; ++i) { + const smart_objects::SmartObject& so_command = smart_obj[i]; + if (smart_objects::SmartType_Null != so_command.getType()) { const mobile_apis::Result::eType verify_images = MessageHelper::VerifyImageFiles(message, application); result = (mobile_apis::Result::INVALID_DATA != verify_images); } else { - LOG4CXX_WARN(logger_, "Invalid json object"); + LOG4CXX_WARN(logger_, "Invalid smart object"); } } } else { - LOG4CXX_WARN(logger_, "Passed json object is null"); + LOG4CXX_WARN(logger_, "Passed smart object is null"); } LOG4CXX_DEBUG(logger_, "CheckIcons result " << result); return result; } - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Json::Value& ResumeCtrl::GetFromSavedOrAppend(const std::string& mobile_app_id) { LOG4CXX_AUTO_TRACE(logger_); for (Json::Value::iterator it = GetSavedApplications().begin(); @@ -1077,8 +995,9 @@ Json::Value& ResumeCtrl::GetFromSavedOrAppend(const std::string& mobile_app_id) return GetSavedApplications().append(Json::Value()); } - -bool ResumeCtrl::CheckIgnCycleRestrictions(const Json::Value& json_app) { +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool ResumeCtrl::CheckIgnCycleRestrictions( + const smart_objects::SmartObject& saved_app) { LOG4CXX_AUTO_TRACE(logger_); bool result = true; @@ -1087,30 +1006,23 @@ bool ResumeCtrl::CheckIgnCycleRestrictions(const Json::Value& json_app) { result = false; } - if (!DisconnectedJustBeforeIgnOff(json_app)) { + if (!DisconnectedJustBeforeIgnOff(saved_app)) { LOG4CXX_INFO(logger_, "Application was dissconnected long before ign off"); result = false; } return result; } -bool ResumeCtrl::DisconnectedInLastIgnCycle(const Json::Value& json_app) { - LOG4CXX_AUTO_TRACE(logger_); - DCHECK_OR_RETURN(json_app.isMember(strings::suspend_count), false); - const uint32_t suspend_count = json_app[strings::suspend_count].asUInt(); - LOG4CXX_DEBUG(logger_, " suspend_count " << suspend_count); - return (1 == suspend_count); -} - -bool ResumeCtrl::DisconnectedJustBeforeIgnOff(const Json::Value& json_app) { +bool ResumeCtrl::DisconnectedJustBeforeIgnOff(const smart_objects::SmartObject& saved_app) { using namespace date_time; using namespace profile; LOG4CXX_AUTO_TRACE(logger_); - DCHECK_OR_RETURN(json_app.isMember(strings::time_stamp), false); + DCHECK_OR_RETURN(saved_app.keyExists(strings::time_stamp), false); const time_t time_stamp = - static_cast<time_t>(json_app[strings::time_stamp].asUInt()); - time_t ign_off_time = GetIgnOffTime(); + static_cast<time_t>(saved_app[strings::time_stamp].asUInt()); + time_t ign_off_time = + static_cast<time_t>(resumption_storage->GetIgnOffTime()); const uint32_t sec_spent_before_ign = labs(ign_off_time - time_stamp); LOG4CXX_DEBUG(logger_,"ign_off_time " << ign_off_time << "; app_disconnect_time " << time_stamp @@ -1138,14 +1050,14 @@ bool ResumeCtrl::CheckDelayAfterIgnOn() { } bool ResumeCtrl::CheckAppRestrictions(ApplicationSharedPtr application, - const Json::Value& json_app) { + const smart_objects::SmartObject& saved_app) { using namespace mobile_apis; LOG4CXX_AUTO_TRACE(logger_); - DCHECK_OR_RETURN(json_app.isMember(strings::hmi_level), false); + DCHECK_OR_RETURN(saved_app.keyExists(strings::hmi_level), false); const bool is_media_app = application->is_media_application(); const HMILevel::eType hmi_level = - static_cast<HMILevel::eType>(json_app[strings::hmi_level].asInt()); + static_cast<HMILevel::eType>(saved_app[strings::hmi_level].asInt()); LOG4CXX_DEBUG(logger_, "is_media_app " << is_media_app << "; hmi_level " << hmi_level); @@ -1157,7 +1069,7 @@ bool ResumeCtrl::CheckAppRestrictions(ApplicationSharedPtr application, } return false; } - +///////////////////////////////////////////////////////////////////////////////////////////// int ResumeCtrl::GetObjectIndex(const std::string& mobile_app_id) { LOG4CXX_AUTO_TRACE(logger_); @@ -1174,6 +1086,7 @@ int ResumeCtrl::GetObjectIndex(const std::string& mobile_app_id) { } return -1; } +///////////////////////////////////////////////////////////////////////////////////////////// time_t ResumeCtrl::launch_time() const { return launch_time_; } @@ -1207,60 +1120,65 @@ void ResumeCtrl::LoadResumeData() { sync_primitives::AutoLock lock(resumtion_lock_); - Json::Value& resume_app_list = GetSavedApplications(); - Json::Value::iterator full_app = resume_app_list.end(); + smart_objects::SmartObject so_applications_data; + resumption_storage->GetDataForLoadResumeData(so_applications_data); + size_t length = so_applications_data.length(); + smart_objects::SmartObject* full_app = NULL; + smart_objects::SmartObject* limited_app = NULL; + time_t time_stamp_full = 0; - Json::Value::iterator limited_app = resume_app_list.end(); time_t time_stamp_limited = 0; + // only apps with first IGN should be resumed + const int32_t first_ign = 1; - Json::Value::iterator it = resume_app_list.begin(); - for (; it != resume_app_list.end(); ++it) { - if ((*it).isMember(strings::ign_off_count) && - (*it).isMember(strings::hmi_level)) { - - // only apps with first IGN should be resumed - const int32_t first_ign = 1; - if (first_ign == (*it)[strings::ign_off_count].asInt()) { + for (size_t i = 0; i < length; ++i) { - const mobile_apis::HMILevel::eType saved_hmi_level = - static_cast<mobile_apis::HMILevel::eType>((*it)[strings::hmi_level].asInt()); + if (first_ign == so_applications_data[i][strings::ign_off_count].asInt()) { - const time_t saved_time_stamp = - static_cast<time_t>((*it)[strings::time_stamp].asUInt()); + const mobile_apis::HMILevel::eType saved_hmi_level = + static_cast<mobile_apis::HMILevel::eType>( + so_application_data[i][strings::hmi_level].asInt()); + const time_t saved_time_stamp = static_cast<time_t>( + so_application_data[i][strings::time_stamp].asUInt()); - if (mobile_apis::HMILevel::HMI_FULL == saved_hmi_level) { - if (time_stamp_full < saved_time_stamp) { + if (mobile_apis::HMILevel::HMI_FULL == saved_hmi_level) { + if (time_stamp_full < saved_time_stamp) { time_stamp_full = saved_time_stamp; - full_app = it; - } + full_app = &(so_application_data[i]); + } } - if (mobile_apis::HMILevel::HMI_LIMITED == saved_hmi_level) { - if (time_stamp_limited < saved_time_stamp) { + if (mobile_apis::HMILevel::HMI_LIMITED == saved_hmi_level) { + if (time_stamp_limited < saved_time_stamp) { time_stamp_limited = saved_time_stamp; - limited_app = it; - } + limited_app = &(so_application_data[i]); } } - - // set invalid HMI level for all - (*it)[strings::hmi_level] = - static_cast<int32_t>(mobile_apis::HMILevel::INVALID_ENUM); } + // set invalid HMI level for all + resumption_storage->SetHMILevelForSavedApplication( + so_application_data[i][strings::app_id].asString(), + so_application_data[i][strings::device_id].asString(), + static_cast<int32_t>(mobile_apis::HMILevel::INVALID_ENUM)); + } - if (full_app != resume_app_list.end()) { - (*full_app)[strings::hmi_level] = - static_cast<int32_t>(mobile_apis::HMILevel::HMI_FULL); + if (full_app != NULL) { + resumption_storage->SetHMILevelForSavedApplication( + (*full_app)[strings::app_id].asString(), + (*full_app)[strings::device_id].asString(), + static_cast<int32_t>(mobile_apis::HMILevel::HMI_FULL)); } - if (limited_app != resume_app_list.end()) { - (*limited_app)[strings::hmi_level] = - static_cast<int32_t>(mobile_apis::HMILevel::HMI_LIMITED); + if (limited_app != NULL) { + resumption_storage->SetHMILevelForSavedApplication( + (*limited_app)[strings::app_id].asString(), + (*limited_app)[strings::device_id].asString(), + static_cast<int32_t>(mobile_apis::HMILevel::HMI_LIMITED)); } - LOG4CXX_DEBUG(logger_, GetResumptionData().toStyledString()); } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool ResumeCtrl::IsResumptionDataValid(uint32_t index) { const Json::Value& json_app = GetSavedApplications()[index]; if (!json_app.isMember(strings::app_id) || @@ -1280,6 +1198,7 @@ bool ResumeCtrl::IsResumptionDataValid(uint32_t index) { return true; } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// uint32_t ResumeCtrl::SendHMIRequest( const hmi_apis::FunctionID::eType& function_id, diff --git a/src/components/application_manager/src/resumption/resume_ctrl.cc b/src/components/application_manager/src/resumption/resume_ctrl.cc new file mode 100644 index 0000000000..fe6ba78891 --- /dev/null +++ b/src/components/application_manager/src/resumption/resume_ctrl.cc @@ -0,0 +1,1305 @@ +/* + Copyright (c) 2015, Ford Motor Company + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the + distribution. + + Neither the name of the Ford Motor Company nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ +#include "application_manager/resume_ctrl.h" + +#include <fstream> +#include <algorithm> + +#include "config_profile/profile.h" +#include "utils/file_system.h" +#include "connection_handler/connection_handler_impl.h" +#include "application_manager/application_manager_impl.h" +#include "application_manager/application.h" +#include "application_manager/message_helper.h" +#include "smart_objects/smart_object.h" +#include "connection_handler/connection.h" +#include "formatters/CFormatterJsonBase.hpp" +#include "application_manager/commands/command_impl.h" +#include "resumption/last_state.h" +#include "policy/policy_manager_impl.h" +#include "application_manager/policies/policy_handler.h" + +namespace application_manager { + +namespace resumption { + +CREATE_LOGGERPTR_GLOBAL(logger_, "ResumeCtrl") + +namespace Formatters = NsSmartDeviceLink::NsJSONHandler::Formatters; + +ResumeCtrl::ResumeCtrl(ApplicationManagerImpl* app_mngr) + : resumtion_lock_(true), + app_mngr_(app_mngr), + save_persistent_data_timer_("RsmCtrlPercist", + this, &ResumeCtrl::SaveDataOnTimer, true), + restore_hmi_level_timer_("RsmCtrlRstore", + this, &ResumeCtrl::ApplicationResumptiOnTimer), + is_data_saved(true), + launch_time_(time(NULL)) { + LoadResumeData(); + save_persistent_data_timer_.start(profile::Profile::instance()->app_resumption_save_persistent_data_timeout()); +} + +void ResumeCtrl::SaveAllApplications() { + LOG4CXX_AUTO_TRACE(logger_); + std::set<ApplicationSharedPtr> apps(retrieve_application()); + std::set<ApplicationSharedPtr>::iterator it_begin = apps.begin(); + std::set<ApplicationSharedPtr>::iterator it_end = apps.end(); + + resumtion_lock_.Acquire(); + for (; it_begin != it_end; ++it_begin) { + if (StateApplicationData::kNotSavedDataForResumption == + ((*it_begin)->is_application_data_changed())) { + resumption_storage->SaveApplication(); + (*it_begin)->set_is_application_data_changed( + StateApplicationData::kSavedDataForResumption); + } + } + resumtion_lock_.Release(); +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void ResumeCtrl::SaveApplication(ApplicationConstSharedPtr application) { + DCHECK(application.get()); + + if (!application) { + LOG4CXX_FATAL(logger_, "Application object is NULL."); + return; + } + + const std::string& m_app_id = application->mobile_app_id(); + LOG4CXX_TRACE(logger_, "ENTER app_id : " << application->app_id() + << " mobile app_id : " << m_app_id); + + const std::string hash = application->curHash(); // let's make a copy not to depend on application + const uint32_t grammar_id = application->get_grammar_id(); + const uint32_t time_stamp = (uint32_t)time(NULL); + + const mobile_apis::HMILevel::eType hmi_level = application->hmi_level(); + + resumtion_lock_.Acquire(); + Json::Value& json_app = GetFromSavedOrAppend(m_app_id); + + json_app[strings::device_mac] = + MessageHelper::GetDeviceMacAddressForHandle(application->device()); + json_app[strings::app_id] = m_app_id; + json_app[strings::grammar_id] = grammar_id; + json_app[strings::connection_key] = application->app_id(); + json_app[strings::hmi_app_id] = application->hmi_app_id(); + json_app[strings::is_media_application] = application->IsAudioApplication(); + json_app[strings::hmi_level] = static_cast<int32_t> (hmi_level); + json_app[strings::ign_off_count] = 0; + json_app[strings::suspend_count] = 0; + json_app[strings::hash_id] = hash; + json_app[strings::application_commands] = + GetApplicationCommands(application); + json_app[strings::application_submenus] = + GetApplicationSubMenus(application); + json_app[strings::application_choice_sets] = + GetApplicationInteractionChoiseSets(application); + json_app[strings::application_global_properties] = + GetApplicationGlobalProperties(application); + json_app[strings::application_subscribtions] = + GetApplicationSubscriptions(application); + json_app[strings::application_files] = GetApplicationFiles(application); + json_app[strings::time_stamp] = time_stamp; + LOG4CXX_DEBUG(logger_, "SaveApplication : " << json_app.toStyledString()); + + resumtion_lock_.Release(); +} +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void ResumeCtrl::on_event(const event_engine::Event& event) { + LOG4CXX_TRACE(logger_, "Response from HMI command"); +} + +bool ResumeCtrl::RestoreAppHMIState(ApplicationSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + using namespace mobile_apis; + if (!application) { + LOG4CXX_ERROR(logger_, " RestoreApplicationHMILevel() application pointer in invalid"); + return false; + } + LOG4CXX_DEBUG(logger_, "ENTER app_id : " << application->app_id()); + + sync_primitives::AutoLock lock(resumtion_lock_); + const int idx = GetObjectIndex(application->mobile_app_id()); + if (-1 != idx) { + const Json::Value& json_app = GetSavedApplications()[idx]; + if (json_app.isMember(strings::hmi_level)) { + + const HMILevel::eType saved_hmi_level = + static_cast<mobile_apis::HMILevel::eType>( + json_app[strings::hmi_level].asInt()); + LOG4CXX_DEBUG(logger_, "Saved HMI Level is : " << saved_hmi_level); + return SetAppHMIState(application, saved_hmi_level); + } else { + LOG4CXX_FATAL(logger_, "There are some unknown keys among the stored apps"); + } + } + LOG4CXX_INFO(logger_, "Failed to restore application HMILevel"); + return false; +} + +bool ResumeCtrl::SetupDefaultHMILevel(ApplicationSharedPtr application) { + if (false == application.valid()) { + LOG4CXX_ERROR(logger_, "SetupDefaultHMILevel application pointer is invalid"); + return false; + } + LOG4CXX_TRACE(logger_, "ENTER app_id : " << application->app_id()); + mobile_apis::HMILevel::eType default_hmi = ApplicationManagerImpl::instance()-> GetDefaultHmiLevel(application); + bool result = SetAppHMIState(application, default_hmi, false); + return result; +} + +bool ResumeCtrl::SetAppHMIState(ApplicationSharedPtr application, + const mobile_apis::HMILevel::eType hmi_level, + bool check_policy) { + using namespace mobile_apis; + LOG4CXX_AUTO_TRACE(logger_); + if (false == application.valid()) { + LOG4CXX_ERROR(logger_, "Application pointer in invalid"); + return false; + } + LOG4CXX_TRACE(logger_, " ENTER Params : ( " << application->app_id() + << "," << hmi_level + << "," << check_policy << " )"); + const std::string device_id = + MessageHelper::GetDeviceMacAddressForHandle(application->device()); + + if (check_policy && + policy::PolicyHandler::instance()->GetUserConsentForDevice(device_id) + != policy::DeviceConsent::kDeviceAllowed) { + LOG4CXX_ERROR(logger_, "Resumption abort. Data consent wasn't allowed"); + SetupDefaultHMILevel(application); + return false; + } + HMILevel::eType restored_hmi_level = hmi_level; + + if ((hmi_level == application->hmi_level()) && + (hmi_level != mobile_apis::HMILevel::HMI_NONE)) { + LOG4CXX_DEBUG(logger_, "Hmi level " << hmi_level << " should not be set to " + << application->mobile_app_id() + <<" current hmi_level is " << application->hmi_level()); + return false; + } + + if (HMILevel::HMI_FULL == hmi_level) { + restored_hmi_level = app_mngr_->IsHmiLevelFullAllowed(application); + } else if (HMILevel::HMI_LIMITED == hmi_level) { + bool allowed_limited = true; + ApplicationManagerImpl::ApplicationListAccessor accessor; + ApplicationManagerImpl::ApplictionSetConstIt it = accessor.begin(); + for (; accessor.end() != it && allowed_limited; ++it) { + const ApplicationSharedPtr curr_app = *it; + if (curr_app->is_media_application()) { + if (curr_app->hmi_level() == HMILevel::HMI_FULL || + curr_app->hmi_level() == HMILevel::HMI_LIMITED) { + allowed_limited = false; + } + } + } + if (allowed_limited) { + restored_hmi_level = HMILevel::HMI_LIMITED; + } else { + restored_hmi_level = + ApplicationManagerImpl::instance()->GetDefaultHmiLevel(application); + } + } + + const AudioStreamingState::eType restored_audio_state = + HMILevel::HMI_FULL == restored_hmi_level || + HMILevel::HMI_LIMITED == restored_hmi_level ? AudioStreamingState::AUDIBLE: + AudioStreamingState::NOT_AUDIBLE; + + application->set_audio_streaming_state(restored_audio_state); + + if (HMILevel::HMI_FULL == restored_hmi_level) { + MessageHelper::SendActivateAppToHMI(application->app_id()); + } else { + if (HMILevel::HMI_LIMITED == restored_hmi_level) { + MessageHelper::SendOnResumeAudioSourceToHMI(application->app_id()); + } + application->set_hmi_level(restored_hmi_level); + MessageHelper::SendHMIStatusNotification(*(application.get())); + } + LOG4CXX_INFO(logger_, "Set up application " + << application->mobile_app_id() + << " to HMILevel " << hmi_level); + return true; +} + +bool ResumeCtrl::RestoreApplicationData(ApplicationSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + if (!application.valid()) { + LOG4CXX_ERROR(logger_, "Application pointer in invalid"); + return false; + } + + LOG4CXX_DEBUG(logger_, "ENTER app_id : " << application->app_id()); + + sync_primitives::AutoLock lock(resumtion_lock_); + const int idx = GetObjectIndex(application->mobile_app_id()); + if (-1 == idx) { + LOG4CXX_WARN(logger_, "Application not saved"); + return false; + } + + const Json::Value& saved_app = GetSavedApplications()[idx]; + if(saved_app.isMember(strings::grammar_id)) { + const uint32_t app_grammar_id = saved_app[strings::grammar_id].asUInt(); + application->set_grammar_id(app_grammar_id); + + AddFiles(application, saved_app); + AddSubmenues(application, saved_app); + AddCommands(application, saved_app); + AddChoicesets(application, saved_app); + SetGlobalProperties(application, saved_app); + AddSubscriptions(application, saved_app); + } + return true; +} + +bool ResumeCtrl::IsHMIApplicationIdExist(uint32_t hmi_app_id) { + LOG4CXX_TRACE(logger_, "ENTER hmi_app_id :" << hmi_app_id); + sync_primitives::AutoLock lock(resumtion_lock_); + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if ((*it).isMember(strings::hmi_app_id)) { + if ((*it)[strings::hmi_app_id].asUInt() == hmi_app_id) { + return true; + } + } + } + ApplicationManagerImpl::ApplicationListAccessor accessor; + ApplicationManagerImpl::ApplictionSet apps(accessor.applications()); + ApplicationManagerImpl::ApplictionSetIt it = apps.begin(); + ApplicationManagerImpl::ApplictionSetIt it_end = apps.end(); + + for (;it != it_end; ++it) { + if (hmi_app_id == (*it)->hmi_app_id()) { + LOG4CXX_TRACE(logger_, "EXIT result = true"); + return true; + } + } + LOG4CXX_TRACE(logger_, "EXIT result = false"); + return false; +} + +bool ResumeCtrl::IsApplicationSaved(const std::string& mobile_app_id) { + LOG4CXX_TRACE(logger_, "ENTER mobile_app_id :" << mobile_app_id); + bool result = false; + sync_primitives::AutoLock lock(resumtion_lock_); + int index = GetObjectIndex(mobile_app_id); + if (-1 != index) { + result = true; + } + LOG4CXX_TRACE(logger_, "EXIT result: " << + (result ? "true" : "false")); + return result; +} + +uint32_t ResumeCtrl::GetHMIApplicationID(const std::string& mobile_app_id) { + LOG4CXX_AUTO_TRACE(logger_); + uint32_t hmi_app_id = 0; + + sync_primitives::AutoLock lock(resumtion_lock_); + const int idx = GetObjectIndex(mobile_app_id); + if (-1 == idx) { + LOG4CXX_WARN(logger_, "Application not saved"); + return hmi_app_id; + } + + const Json::Value& json_app = GetSavedApplications()[idx]; + if (json_app.isMember(strings::app_id)) { + hmi_app_id = json_app[strings::hmi_app_id].asUInt(); + } + LOG4CXX_DEBUG(logger_, "hmi_app_id :" << hmi_app_id); + return hmi_app_id; +} + +bool ResumeCtrl::RemoveApplicationFromSaved(ApplicationConstSharedPtr application) { + if (false == application.valid()) { + LOG4CXX_ERROR(logger_, "Application pointer in invalid"); + return false; + } + LOG4CXX_TRACE(logger_, "ENTER app_id :" << application->app_id() + << "; mobile_app_id " << application->mobile_app_id()); + + bool result = false; + std::vector<Json::Value> temp; + sync_primitives::AutoLock lock(resumtion_lock_); + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if ((*it).isMember(strings::app_id)) { + const std::string& saved_m_app_id = (*it)[strings::app_id].asString(); + + if (saved_m_app_id != application->mobile_app_id()) { + temp.push_back((*it)); + } else { + result = true; + } + } + } + + if (false == result) { + LOG4CXX_TRACE(logger_, "EXIT result: " << (result ? "true" : "false")); + return result; + } + + GetSavedApplications().clear(); + for (std::vector<Json::Value>::iterator it = temp.begin(); + it != temp.end(); ++it) { + GetSavedApplications().append((*it)); + } + LOG4CXX_TRACE(logger_, "EXIT result: " << (result ? "true" : "false")); + return result; +} + +void ResumeCtrl::Suspend() { + LOG4CXX_AUTO_TRACE(logger_); + StopSavePersistentDataTimer(); + SaveAllApplications(); + Json::Value to_save; + sync_primitives::AutoLock lock(resumtion_lock_); + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if ((*it).isMember(strings::suspend_count)) { + const uint32_t suspend_count = (*it)[strings::suspend_count].asUInt(); + (*it)[strings::suspend_count] = suspend_count + 1; + } else { + LOG4CXX_WARN(logger_, "Unknown key among saved applications"); + (*it)[strings::suspend_count] = 1; + } + if ((*it).isMember(strings::ign_off_count)) { + const uint32_t ign_off_count = (*it)[strings::ign_off_count].asUInt(); + if (ign_off_count < kApplicationLifes) { + (*it)[strings::ign_off_count] = ign_off_count + 1; + to_save.append(*it); + } + } else { + LOG4CXX_WARN(logger_, "Unknown key among saved applications"); + (*it)[strings::ign_off_count] = 1; + } + } + SetSavedApplication(to_save); + SetLastIgnOffTime(time(NULL)); + LOG4CXX_DEBUG(logger_, + GetResumptionData().toStyledString()); + resumption::LastState::instance()->SaveToFileSystem(); +} + +void ResumeCtrl::OnAwake() { + LOG4CXX_AUTO_TRACE(logger_); + + sync_primitives::AutoLock lock(resumtion_lock_); + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if ((*it).isMember(strings::ign_off_count)) { + const uint32_t ign_off_count = (*it)[strings::ign_off_count].asUInt(); + (*it)[strings::ign_off_count] = ign_off_count - 1; + } else { + LOG4CXX_WARN(logger_, "Unknown key among saved applications"); + (*it)[strings::ign_off_count] = 0; + } + } + ResetLaunchTime(); + StartSavePersistentDataTimer(); +} + + + +void ResumeCtrl::StartSavePersistentDataTimer() { + LOG4CXX_AUTO_TRACE(logger_); + if (!save_persistent_data_timer_.isRunning()) { + save_persistent_data_timer_.start( + profile::Profile::instance()->app_resumption_save_persistent_data_timeout()); + } +} + +void ResumeCtrl::StopSavePersistentDataTimer() { + LOG4CXX_AUTO_TRACE(logger_); + if (save_persistent_data_timer_.isRunning()) { + save_persistent_data_timer_.stop(); + } +} + + +bool ResumeCtrl::StartResumption(ApplicationSharedPtr application, + const std::string& hash) { + LOG4CXX_AUTO_TRACE(logger_); + if (!application) { + LOG4CXX_WARN(logger_, "Application not exist"); + return false; + } + + SetupDefaultHMILevel(application); + + LOG4CXX_DEBUG(logger_, " Resume app_id = " << application->app_id() + << " hmi_app_id = " << application->hmi_app_id() + << " mobile_id = " << application->mobile_app_id() + << "received hash = " << hash); + + sync_primitives::AutoLock lock(resumtion_lock_); + const int idx = GetObjectIndex(application->mobile_app_id()); + if (-1 == idx) { + LOG4CXX_WARN(logger_, "Application not saved"); + return false; + } + + const Json::Value& json_app = GetSavedApplications()[idx]; + LOG4CXX_DEBUG(logger_, "Saved_application_data: " << json_app.toStyledString()); + if (json_app.isMember(strings::hash_id) && json_app.isMember(strings::time_stamp)) { + const std::string& saved_hash = json_app[strings::hash_id].asString(); + + if (saved_hash == hash) { + RestoreApplicationData(application); + } + application->UpdateHash(); + ApplicationManagerImpl::ApplicationListAccessor accessor; + if (!restore_hmi_level_timer_.isRunning() && + accessor.applications().size() > 1) { + // if there is already registered app resume without delays + StartAppHmiStateResumption(application); + } else { + queue_lock_.Acquire(); + waiting_for_timer_.push_back(application->app_id()); + queue_lock_.Release(); + restore_hmi_level_timer_.start(profile::Profile::instance()->app_resuming_timeout()); + } + } else { + LOG4CXX_INFO(logger_, "There are some unknown keys in the dictionary."); + return false; + } + + return true; +} + +void ResumeCtrl::StartAppHmiStateResumption(ApplicationSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + using namespace profile; + using namespace date_time; + DCHECK_OR_RETURN_VOID(application); + const int idx = GetObjectIndex(application->mobile_app_id()); + DCHECK_OR_RETURN_VOID(idx != -1); + const Json::Value& json_app = GetSavedApplications()[idx]; + + if (!json_app.isMember(strings::ign_off_count)) { + LOG4CXX_INFO(logger_, "Do not need to resume application " + << application->app_id()); + SetupDefaultHMILevel(application); + return; + } + + // check if if is resumption during one IGN cycle + const uint32_t ign_off_count = json_app[strings::ign_off_count].asUInt(); + + if (0 == ign_off_count) { + if (CheckAppRestrictions(application, json_app)) { + LOG4CXX_INFO(logger_, "Resume application after short IGN cycle"); + RestoreAppHMIState(application); + RemoveApplicationFromSaved(application); + } else { + LOG4CXX_INFO(logger_, "Do not need to resume application " + << application->app_id()); + } + } else { + if (CheckIgnCycleRestrictions(json_app) && + CheckAppRestrictions(application, json_app)) { + LOG4CXX_INFO(logger_, "Resume application after IGN cycle"); + RestoreAppHMIState(application); + RemoveApplicationFromSaved(application); + } else { + LOG4CXX_INFO(logger_, "Do not need to resume application " + << application->app_id()); + } + } +} + +std::set<ApplicationSharedPtr> ResumeCtrl::retrieve_application() { + ApplicationManagerImpl::ApplicationListAccessor accessor; + return std::set<ApplicationSharedPtr>(accessor.begin(), accessor.end()); +} + +bool ResumeCtrl::StartResumptionOnlyHMILevel(ApplicationSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + if (!application.valid()) { + LOG4CXX_WARN(logger_, "Application do not exists"); + return false; + } + + SetupDefaultHMILevel(application); + + LOG4CXX_DEBUG(logger_, "ENTER app_id = " << application->app_id() + << "mobile_id = " + << application->mobile_app_id()); + + sync_primitives::AutoLock lock(resumtion_lock_); + const int idx = GetObjectIndex(application->mobile_app_id()); + if (-1 == idx) { + LOG4CXX_WARN(logger_, "Application not saved"); + return false; + } + + ApplicationManagerImpl::ApplicationListAccessor accessor; + if (!restore_hmi_level_timer_.isRunning() && + accessor.applications().size() > 1) { + StartAppHmiStateResumption(application); + } else { + queue_lock_.Acquire(); + waiting_for_timer_.push_back(application->app_id()); + queue_lock_.Release(); + restore_hmi_level_timer_.start(profile::Profile::instance()->app_resuming_timeout()); + } + + return true; +} + +bool ResumeCtrl::CheckPersistenceFilesForResumption(ApplicationSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + + if (!application.valid()) { + LOG4CXX_WARN(logger_, "Application do not exists"); + return false; + } + LOG4CXX_DEBUG(logger_, "Process app_id = " << application->app_id()); + + sync_primitives::AutoLock lock(resumtion_lock_); + const int idx = GetObjectIndex(application->mobile_app_id()); + if (-1 == idx) { + LOG4CXX_WARN(logger_, "Application not saved"); + return false; + } + + const Json::Value& saved_app = GetSavedApplications()[idx]; + + if (!saved_app.isMember(strings::application_commands) || + !saved_app.isMember(strings::application_choice_sets)) { + LOG4CXX_WARN(logger_, "application_commands or " + "application_choice_sets are not exists"); + return false; + } + + if (!CheckIcons(application, saved_app[strings::application_commands])) { + return false; + } + if (!CheckIcons(application, saved_app[strings::application_choice_sets])) { + return false; + } + LOG4CXX_DEBUG(logger_, " result = true"); + return true; +} + +bool ResumeCtrl::CheckApplicationHash(ApplicationSharedPtr application, + const std::string& hash) { + if (!application) { + LOG4CXX_ERROR(logger_, "Application pointer is invalid"); + return false; + } + + LOG4CXX_DEBUG(logger_, "ENTER app_id : " << application->app_id() + << " hash : " << hash); + + sync_primitives::AutoLock lock(resumtion_lock_); + const int idx = GetObjectIndex(application->mobile_app_id()); + if (-1 == idx) { + LOG4CXX_WARN(logger_, "Application not saved"); + return false; + } + + const Json::Value& json_app = GetSavedApplications()[idx]; + + if (json_app.isMember(strings::hash_id)) { + const std::string& saved_hash = json_app[strings::hash_id].asString(); + + LOG4CXX_TRACE(logger_, "Found saved application : " << json_app.toStyledString()); + LOG4CXX_INFO(logger_, "received hash = " << hash); + LOG4CXX_INFO(logger_, "saved hash = " << saved_hash); + if (hash == saved_hash) { + return true; + } + } + + return false; +} + +void ResumeCtrl::SaveDataOnTimer() { + LOG4CXX_AUTO_TRACE(logger_); + if (restore_hmi_level_timer_.isRunning()) { + LOG4CXX_WARN(logger_, "Resumption timer is active skip saving"); + return; + } + + if (false == is_data_saved) { + SaveAllApplications(); + is_data_saved = true; + resumption::LastState::instance()->SaveToFileSystem(); + } +} + +bool ResumeCtrl::IsDeviceMacAddressEqual(ApplicationSharedPtr application, + const std::string& saved_device_mac) { + const std::string device_mac = + MessageHelper::GetDeviceMacAddressForHandle(application->device()); + return device_mac == saved_device_mac; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +Json::Value&ResumeCtrl::GetResumptionData() { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value& last_state = resumption::LastState::instance()->dictionary; + if (!last_state.isMember(strings::resumption)) { + last_state[strings::resumption] = Json::Value(Json::objectValue); + LOG4CXX_WARN(logger_, "resumption section is missed"); + } + Json::Value& resumption = last_state[strings::resumption]; + if (!resumption.isObject()) { + LOG4CXX_ERROR(logger_, "resumption type INVALID rewrite"); + resumption = Json::Value(Json::objectValue); + } + return resumption; +} +////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +Json::Value& ResumeCtrl::GetSavedApplications() { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value& resumption = GetResumptionData(); + if (!resumption.isMember(strings::resume_app_list)) { + resumption[strings::resume_app_list] = Json::Value(Json::arrayValue); + LOG4CXX_WARN(logger_, "app_list section is missed"); + } + Json::Value& resume_app_list = resumption[strings::resume_app_list]; + if (!resume_app_list.isArray()) { + LOG4CXX_ERROR(logger_, "resume_app_list type INVALID rewrite"); + resume_app_list = Json::Value(Json::arrayValue); + } + return resume_app_list; +} +////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +time_t ResumeCtrl::GetIgnOffTime() { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value& resumption = GetResumptionData(); + if (!resumption.isMember(strings::last_ign_off_time)) { + resumption[strings::last_ign_off_time] = 0; + LOG4CXX_WARN(logger_, "last_save_time section is missed"); + } + time_t last_ign_off = static_cast<time_t>( + resumption[strings::last_ign_off_time].asUInt()); + return last_ign_off; +} + +void ResumeCtrl::SetLastIgnOffTime(time_t ign_off_time) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_WARN(logger_, "ign_off_time = " << ign_off_time); + Json::Value& resumption = GetResumptionData(); + resumption[strings::last_ign_off_time] = static_cast<uint32_t>(ign_off_time); +} + + +void ResumeCtrl::SetSavedApplication(Json::Value& apps_json) { + Json::Value& app_list = GetSavedApplications(); + app_list = apps_json; +} + +void ResumeCtrl::ClearResumptionInfo() { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value empty_json; + + SetSavedApplication(empty_json); + resumption::LastState::instance()->SaveToFileSystem(); +} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Json::Value ResumeCtrl::GetApplicationCommands( + ApplicationConstSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value result; + DCHECK(application.get()); + if (!application) { + LOG4CXX_ERROR(logger_, "NULL Pointer App"); + return result; + } + const DataAccessor<CommandsMap> accessor = application->commands_map(); + const CommandsMap& commands = accessor.GetData(); + CommandsMap::const_iterator it = commands.begin(); + for (;it != commands.end(); ++it) { + smart_objects::SmartObject* so = it->second; + Json::Value curr; + Formatters::CFormatterJsonBase::objToJsonValue(*so, curr); + result.append(curr); + } + return result; +} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +Json::Value ResumeCtrl::GetApplicationSubMenus( + ApplicationConstSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value result; + DCHECK(application.get()); + if (!application) { + LOG4CXX_ERROR(logger_, "NULL Pointer App"); + return result; + } + const DataAccessor<SubMenuMap> accessor = application->sub_menu_map(); + const SubMenuMap& sub_menus = accessor.GetData(); + SubMenuMap::const_iterator it = sub_menus.begin(); + for (;it != sub_menus.end(); ++it) { + smart_objects::SmartObject* so = it->second; + Json::Value curr; + Formatters::CFormatterJsonBase::objToJsonValue(*so, curr); + result.append(curr); + } + return result; +} + +Json::Value ResumeCtrl::GetApplicationInteractionChoiseSets( + ApplicationConstSharedPtr application) { + DCHECK(application.get()); + LOG4CXX_TRACE(logger_, "ENTER app_id:" + << application->app_id()); + + Json::Value result; + const DataAccessor<ChoiceSetMap> accessor = application->choice_set_map(); + const ChoiceSetMap& choices = accessor.GetData(); + ChoiceSetMap::const_iterator it = choices.begin(); + for ( ;it != choices.end(); ++it) { + smart_objects::SmartObject* so = it->second; + Json::Value curr; + Formatters::CFormatterJsonBase::objToJsonValue(*so, curr); + result.append(curr); + } + return result; +} + +Json::Value ResumeCtrl::GetApplicationGlobalProperties( + ApplicationConstSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value sgp; + DCHECK(application.get()); + if (!application) { + LOG4CXX_ERROR(logger_, "NULL Pointer App"); + return sgp; + } + + const smart_objects::SmartObject* help_promt = application->help_prompt(); + const smart_objects::SmartObject* timeout_prompt = application->timeout_prompt(); + const smart_objects::SmartObject* vr_help = application->vr_help(); + const smart_objects::SmartObject* vr_help_title = application->vr_help_title(); + const smart_objects::SmartObject* vr_synonyms = application->vr_synonyms(); + const smart_objects::SmartObject* keyboard_props = application->keyboard_props(); + const smart_objects::SmartObject* menu_title = application->menu_title(); + const smart_objects::SmartObject* menu_icon = application->menu_icon(); + + sgp[strings::help_prompt] = JsonFromSO(help_promt); + sgp[strings::timeout_prompt] = JsonFromSO(timeout_prompt); + sgp[strings::vr_help] = JsonFromSO(vr_help); + sgp[strings::vr_help_title] = JsonFromSO(vr_help_title); + sgp[strings::vr_synonyms] = JsonFromSO(vr_synonyms); + sgp[strings::keyboard_properties] = JsonFromSO(keyboard_props); + sgp[strings::menu_title] = JsonFromSO(menu_title); + sgp[strings::menu_icon] = JsonFromSO(menu_icon); + return sgp; +} + +Json::Value ResumeCtrl::GetApplicationSubscriptions( + ApplicationConstSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value result; + DCHECK(application.get()); + if (!application) { + LOG4CXX_ERROR(logger_, "NULL Pointer App"); + return result; + } + LOG4CXX_DEBUG(logger_, "app_id:" << application->app_id()); + LOG4CXX_DEBUG(logger_, "SubscribedButtons:" << application->SubscribedButtons().size()); + Append(application->SubscribedButtons().begin(), + application->SubscribedButtons().end(), + strings::application_buttons, result); + LOG4CXX_DEBUG(logger_, "SubscribesIVI:" << application->SubscribesIVI().size()); + Append(application->SubscribesIVI().begin(), + application->SubscribesIVI().end(), + strings::application_vehicle_info, result); + return result; +} + +Json::Value ResumeCtrl::GetApplicationFiles( + ApplicationConstSharedPtr application) { + DCHECK(application.get()); + LOG4CXX_TRACE(logger_, "ENTER app_id:" + << application->app_id()); + + Json::Value result; + const AppFilesMap& app_files = application->getAppFiles(); + for(AppFilesMap::const_iterator file_it = app_files.begin(); + file_it != app_files.end(); file_it++) { + const AppFile& file = file_it->second; + if (file.is_persistent) { + Json::Value file_data; + file_data[strings::persistent_file] = file.is_persistent; + file_data[strings::is_download_complete] = file.is_download_complete; + file_data[strings::sync_file_name] = file.file_name; + file_data[strings::file_type] = file.file_type; + result.append(file_data); + } + } + return result; +} + +Json::Value ResumeCtrl::GetApplicationShow( + ApplicationConstSharedPtr application) { + DCHECK(application.get()); + LOG4CXX_TRACE(logger_, "ENTER app_id:" + << application->app_id()); + + Json::Value result; + const smart_objects::SmartObject* show_so = application->show_command(); + if (!show_so) { + return result; + } + result = JsonFromSO(show_so); + return result; +} + +Json::Value ResumeCtrl::JsonFromSO(const smart_objects::SmartObject *so) { + Json::Value temp; + if (so) { + Formatters::CFormatterJsonBase::objToJsonValue(*so, temp); + } + return temp; +} + +bool ResumeCtrl::ProcessHMIRequest(smart_objects::SmartObjectSPtr request, + bool use_events) { + LOG4CXX_AUTO_TRACE(logger_); + if (use_events) { + const hmi_apis::FunctionID::eType function_id = + static_cast<hmi_apis::FunctionID::eType>( + (*request)[strings::function_id].asInt()); + + const int32_t hmi_correlation_id = + (*request)[strings::correlation_id].asInt(); + subscribe_on_event(function_id, hmi_correlation_id); + } + if (!ApplicationManagerImpl::instance()->ManageHMICommand(request)) { + LOG4CXX_ERROR(logger_, "Unable to send request"); + return true; + } + return false; +} + +void ResumeCtrl::AddFiles(ApplicationSharedPtr application, const Json::Value& saved_app) { + LOG4CXX_AUTO_TRACE(logger_); + if (saved_app.isMember(strings::application_files)) { + const Json::Value& application_files = saved_app[strings::application_files]; + for (Json::Value::iterator json_it = application_files.begin(); + json_it != application_files.end(); ++json_it) { + const Json::Value& file_data = *json_it; + + const bool is_persistent = file_data.isMember(strings::persistent_file) && + file_data[strings::persistent_file].asBool(); + if (is_persistent) { + AppFile file; + file.is_persistent = is_persistent; + file.is_download_complete = file_data[strings::is_download_complete].asBool(); + file.file_name = file_data[strings::sync_file_name].asString(); + file.file_type = static_cast<mobile_apis::FileType::eType> ( + file_data[strings::file_type].asInt()); + application->AddFile(file); + } + } + } else { + LOG4CXX_FATAL(logger_, "application_files section is not exists"); + } +} + +void ResumeCtrl::AddSubmenues(ApplicationSharedPtr application, const Json::Value& saved_app) { + LOG4CXX_AUTO_TRACE(logger_); + if (saved_app.isMember(strings::application_submenus)) { + const Json::Value& app_submenus = saved_app[strings::application_submenus]; + for (Json::Value::iterator json_it = app_submenus.begin(); + json_it != app_submenus.end(); ++json_it) { + const Json::Value& json_submenu = *json_it; + smart_objects::SmartObject message(smart_objects::SmartType::SmartType_Map); + Formatters::CFormatterJsonBase::jsonValueToObj(json_submenu, message); + application->AddSubMenu(message[strings::menu_id].asUInt(), message); + } + + ProcessHMIRequests(MessageHelper::CreateAddSubMenuRequestToHMI(application)); + } else { + LOG4CXX_FATAL(logger_, "application_submenus section is not exists"); + } +} + +void ResumeCtrl::AddCommands(ApplicationSharedPtr application, const Json::Value& saved_app) { + LOG4CXX_AUTO_TRACE(logger_); + if (saved_app.isMember(strings::application_commands)) { + const Json::Value& app_commands = saved_app[strings::application_commands]; + for (Json::Value::iterator json_it = app_commands.begin(); + json_it != app_commands.end(); ++json_it) { + const Json::Value& json_command = *json_it; + smart_objects::SmartObject message(smart_objects::SmartType::SmartType_Map); + Formatters::CFormatterJsonBase::jsonValueToObj(json_command, message); + application->AddCommand(message[strings::cmd_id].asUInt(), message); + } + + ProcessHMIRequests(MessageHelper::CreateAddCommandRequestToHMI(application)); + } else { + LOG4CXX_FATAL(logger_, "application_commands section is not exists"); + } +} + +void ResumeCtrl::AddChoicesets(ApplicationSharedPtr application, const Json::Value& saved_app) { + if(saved_app.isMember(strings::application_choice_sets)) { + const Json::Value& app_choise_sets = saved_app[strings::application_choice_sets]; + for (Json::Value::iterator json_it = app_choise_sets.begin(); + json_it != app_choise_sets.end(); ++json_it) { + const Json::Value& json_choiset = *json_it; + smart_objects::SmartObject msg_param(smart_objects::SmartType::SmartType_Map); + Formatters::CFormatterJsonBase::jsonValueToObj(json_choiset , msg_param); + const int32_t choice_set_id = msg_param + [strings::interaction_choice_set_id].asInt(); + uint32_t choice_grammar_id = msg_param[strings::grammar_id].asUInt(); + application->AddChoiceSet(choice_set_id, msg_param); + + const size_t size = msg_param[strings::choice_set].length(); + for (size_t j = 0; j < size; ++j) { + smart_objects::SmartObject choise_params(smart_objects::SmartType_Map); + choise_params[strings::app_id] = application->app_id(); + choise_params[strings::cmd_id] = + msg_param[strings::choice_set][j][strings::choice_id]; + choise_params[strings::vr_commands] = smart_objects::SmartObject( + smart_objects::SmartType_Array); + choise_params[strings::vr_commands] = + msg_param[strings::choice_set][j][strings::vr_commands]; + + choise_params[strings::type] = hmi_apis::Common_VRCommandType::Choice; + choise_params[strings::grammar_id] = choice_grammar_id; + SendHMIRequest(hmi_apis::FunctionID::VR_AddCommand, &choise_params); + } + } + } else { + LOG4CXX_FATAL(logger_, "There is no any choicesets"); + } +} + +void ResumeCtrl::SetGlobalProperties(ApplicationSharedPtr application, const Json::Value& saved_app) { + const Json::Value& global_properties = saved_app[strings::application_global_properties]; + if (!global_properties.isNull()) { + smart_objects::SmartObject properties_so(smart_objects::SmartType::SmartType_Map); + Formatters::CFormatterJsonBase::jsonValueToObj(global_properties , properties_so); + application->load_global_properties(properties_so); + MessageHelper::SendGlobalPropertiesToHMI(application); + } +} + +void ResumeCtrl::AddSubscriptions(ApplicationSharedPtr application, const Json::Value& saved_app) { + if (saved_app.isMember(strings::application_subscribtions)) { + const Json::Value& subscribtions = saved_app[strings::application_subscribtions]; + + if (subscribtions.isMember(strings::application_buttons)) { + const Json::Value& subscribtions_buttons = subscribtions[strings::application_buttons]; + mobile_apis::ButtonName::eType btn; + for (Json::Value::iterator json_it = subscribtions_buttons.begin(); + json_it != subscribtions_buttons.end(); ++json_it) { + btn = static_cast<mobile_apis::ButtonName::eType>((*json_it).asInt()); + application->SubscribeToButton(btn); + } + } + if (subscribtions.isMember(strings::application_vehicle_info)) { + const Json::Value& subscribtions_ivi= subscribtions[strings::application_vehicle_info]; + VehicleDataType ivi; + for (Json::Value::iterator json_it = subscribtions_ivi.begin(); + json_it != subscribtions_ivi.end(); ++json_it) { + ivi = static_cast<VehicleDataType>((*json_it).asInt()); + application->SubscribeToIVI(ivi); + } + } + + ProcessHMIRequests(MessageHelper::GetIVISubscriptionRequests(application)); + } +} + +void ResumeCtrl::ProcessHMIRequests(const smart_objects::SmartObjectList& requests) { + for (smart_objects::SmartObjectList::const_iterator it = requests.begin(), + total = requests.end(); + it != total; ++it) { + ProcessHMIRequest(*it, true); + } +} + +bool ResumeCtrl::CheckIcons(ApplicationSharedPtr application, + const Json::Value& json_object) { + LOG4CXX_AUTO_TRACE(logger_); + bool result = true; + if (!json_object.isNull()) { + Json::Value::const_iterator json_it = json_object.begin(); + for (;json_it != json_object.end() && result; ++json_it) { + const Json::Value& json_command = *json_it; + if (!json_command.isNull()) { + smart_objects::SmartObject message(smart_objects::SmartType::SmartType_Map); + Formatters::CFormatterJsonBase::jsonValueToObj(json_command, message); + const mobile_apis::Result::eType verify_images = + MessageHelper::VerifyImageFiles(message, application); + result = (mobile_apis::Result::INVALID_DATA != verify_images); + } else { + LOG4CXX_WARN(logger_, "Invalid json object"); + } + } + } else { + LOG4CXX_WARN(logger_, "Passed json object is null"); + } + LOG4CXX_DEBUG(logger_, "CheckIcons result " << result); + return result; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Json::Value& ResumeCtrl::GetFromSavedOrAppend(const std::string& mobile_app_id) { + LOG4CXX_AUTO_TRACE(logger_); + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if (mobile_app_id == (*it)[strings::app_id].asString()) { + return *it; + } + } + + return GetSavedApplications().append(Json::Value()); +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +bool ResumeCtrl::CheckIgnCycleRestrictions(const Json::Value& json_app) { + LOG4CXX_AUTO_TRACE(logger_); + bool result = true; + + if (!CheckDelayAfterIgnOn()) { + LOG4CXX_INFO(logger_, "Application was connected long after ign on"); + result = false; + } + + if (!DisconnectedJustBeforeIgnOff(json_app)) { + LOG4CXX_INFO(logger_, "Application was dissconnected long before ign off"); + result = false; + } + return result; +} + +bool ResumeCtrl::DisconnectedInLastIgnCycle(const Json::Value& json_app) { + LOG4CXX_AUTO_TRACE(logger_); + DCHECK_OR_RETURN(json_app.isMember(strings::suspend_count), false); + const uint32_t suspend_count = json_app[strings::suspend_count].asUInt(); + LOG4CXX_DEBUG(logger_, " suspend_count " << suspend_count); + return (1 == suspend_count); +} + +bool ResumeCtrl::DisconnectedJustBeforeIgnOff(const Json::Value& json_app) { + using namespace date_time; + using namespace profile; + LOG4CXX_AUTO_TRACE(logger_); + DCHECK_OR_RETURN(json_app.isMember(strings::time_stamp), false); + + const time_t time_stamp = + static_cast<time_t>(json_app[strings::time_stamp].asUInt()); + time_t ign_off_time = GetIgnOffTime(); + const uint32_t sec_spent_before_ign = labs(ign_off_time - time_stamp); + LOG4CXX_DEBUG(logger_,"ign_off_time " << ign_off_time + << "; app_disconnect_time " << time_stamp + << "; sec_spent_before_ign " << sec_spent_before_ign + << "; resumption_delay_before_ign " << + Profile::instance()->resumption_delay_before_ign()); + return sec_spent_before_ign <= + Profile::instance()->resumption_delay_before_ign(); +} + +bool ResumeCtrl::CheckDelayAfterIgnOn() { + using namespace date_time; + using namespace profile; + LOG4CXX_AUTO_TRACE(logger_); + time_t curr_time = time(NULL); + time_t sdl_launch_time = launch_time(); + const uint32_t seconds_from_sdl_start = labs(curr_time - sdl_launch_time); + const uint32_t wait_time = + Profile::instance()->resumption_delay_after_ign(); + LOG4CXX_DEBUG(logger_, "curr_time " << curr_time + << "; sdl_launch_time " << sdl_launch_time + << "; seconds_from_sdl_start " << seconds_from_sdl_start + << "; wait_time " << wait_time); + return seconds_from_sdl_start <= wait_time; +} + +bool ResumeCtrl::CheckAppRestrictions(ApplicationSharedPtr application, + const Json::Value& json_app) { + using namespace mobile_apis; + LOG4CXX_AUTO_TRACE(logger_); + DCHECK_OR_RETURN(json_app.isMember(strings::hmi_level), false); + + const bool is_media_app = application->is_media_application(); + const HMILevel::eType hmi_level = + static_cast<HMILevel::eType>(json_app[strings::hmi_level].asInt()); + LOG4CXX_DEBUG(logger_, "is_media_app " << is_media_app + << "; hmi_level " << hmi_level); + + if (is_media_app) { + if (hmi_level == HMILevel::HMI_FULL || + hmi_level == HMILevel::HMI_LIMITED) { + return true; + } + } + return false; +} + +int ResumeCtrl::GetObjectIndex(const std::string& mobile_app_id) { + LOG4CXX_AUTO_TRACE(logger_); + + sync_primitives::AutoLock lock(resumtion_lock_); + const Json::Value& apps = GetSavedApplications(); + const Json::ArrayIndex size = apps.size(); + Json::ArrayIndex idx = 0; + for (; idx != size; ++idx) { + const std::string& saved_app_id = apps[idx][strings::app_id].asString(); + if (mobile_app_id == saved_app_id) { + LOG4CXX_DEBUG(logger_, "Found " << idx); + return idx; + } + } + return -1; +} +time_t ResumeCtrl::launch_time() const { + return launch_time_; +} + +void ResumeCtrl::ResetLaunchTime() { + launch_time_ = time(NULL); +} + +void ResumeCtrl::ApplicationResumptiOnTimer() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(queue_lock_); + std::vector<uint32_t>::iterator it = waiting_for_timer_.begin(); + + for (; it != waiting_for_timer_.end(); ++it) { + ApplicationSharedPtr app = + ApplicationManagerImpl::instance()->application(*it); + if (!app.get()) { + LOG4CXX_ERROR(logger_, "Invalid app_id = " << *it); + continue; + } + + StartAppHmiStateResumption(app); + } + + waiting_for_timer_.clear(); +} + +void ResumeCtrl::LoadResumeData() { + LOG4CXX_AUTO_TRACE(logger_); + + sync_primitives::AutoLock lock(resumtion_lock_); + + Json::Value& resume_app_list = GetSavedApplications(); + Json::Value::iterator full_app = resume_app_list.end(); + time_t time_stamp_full = 0; + Json::Value::iterator limited_app = resume_app_list.end(); + time_t time_stamp_limited = 0; + + Json::Value::iterator it = resume_app_list.begin(); + for (; it != resume_app_list.end(); ++it) { + if ((*it).isMember(strings::ign_off_count) && + (*it).isMember(strings::hmi_level)) { + + // only apps with first IGN should be resumed + const int32_t first_ign = 1; + if (first_ign == (*it)[strings::ign_off_count].asInt()) { + + const mobile_apis::HMILevel::eType saved_hmi_level = + static_cast<mobile_apis::HMILevel::eType>((*it)[strings::hmi_level].asInt()); + + const time_t saved_time_stamp = + static_cast<time_t>((*it)[strings::time_stamp].asUInt()); + + if (mobile_apis::HMILevel::HMI_FULL == saved_hmi_level) { + if (time_stamp_full < saved_time_stamp) { + time_stamp_full = saved_time_stamp; + full_app = it; + } + } + + if (mobile_apis::HMILevel::HMI_LIMITED == saved_hmi_level) { + if (time_stamp_limited < saved_time_stamp) { + time_stamp_limited = saved_time_stamp; + limited_app = it; + } + } + } + + // set invalid HMI level for all + (*it)[strings::hmi_level] = + static_cast<int32_t>(mobile_apis::HMILevel::INVALID_ENUM); + } + } + + if (full_app != resume_app_list.end()) { + (*full_app)[strings::hmi_level] = + static_cast<int32_t>(mobile_apis::HMILevel::HMI_FULL); + } + + if (limited_app != resume_app_list.end()) { + (*limited_app)[strings::hmi_level] = + static_cast<int32_t>(mobile_apis::HMILevel::HMI_LIMITED); + } + LOG4CXX_DEBUG(logger_, GetResumptionData().toStyledString()); +} + +void ResumeCtrl::SendHMIRequest( + const hmi_apis::FunctionID::eType& function_id, + const smart_objects::SmartObject* msg_params, bool use_events) { + LOG4CXX_AUTO_TRACE(logger_); + smart_objects::SmartObjectSPtr result = + MessageHelper::CreateModuleInfoSO(function_id); + int32_t hmi_correlation_id = + (*result)[strings::params][strings::correlation_id].asInt(); + if (use_events) { + subscribe_on_event(function_id, hmi_correlation_id); + } + + if (msg_params) { + (*result)[strings::msg_params] = *msg_params; + } + + if (!ApplicationManagerImpl::instance()->ManageHMICommand(result)) { + LOG4CXX_ERROR(logger_, "Unable to send request"); + } +} + +} // namespce resumption + +} // namespace application_manager diff --git a/src/components/application_manager/src/resumption/resumption_data.cc b/src/components/application_manager/src/resumption/resumption_data.cc new file mode 100644 index 0000000000..d4b0d92803 --- /dev/null +++ b/src/components/application_manager/src/resumption/resumption_data.cc @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "application_manager/resumption/resumption_data.h" +#include "utils/logger.h" + +namespace application_manager { +namespace resumption { + +CREATE_LOGGERPTR_GLOBAL(logger_, "ResumptionData") + +smart_objects::SmartObject ResumptionData::GetApplicationCommands( + ApplicationConstSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + + DCHECK(application.get()); + smart_objects::SmartObject commands_array = smart_objects::SmartObject( + smart_objects::SmartType_Array); + if (!application) { + LOG4CXX_ERROR(logger_, "NULL Pointer App"); + return commands_array; + } + const DataAccessor<CommandsMap> accessor = application->commands_map(); + const CommandsMap& commands = accessor.GetData(); + CommandsMap::const_iterator it = commands.begin(); + for (int i = 0; it != commands.end(); ++it, ++i) { + commands_array[i] = *(it->second); + } + return commands_array; +} + +smart_objects::SmartObject ResumptionData::GetApplicationSubMenus( + ApplicationConstSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + + DCHECK(application.get()); + smart_objects::SmartObject submenues_array = smart_objects::SmartObject( + smart_objects::SmartType_Array); + + if (!application) { + LOG4CXX_ERROR(logger_, "NULL Pointer App"); + return submenues_array; + } + const DataAccessor<SubMenuMap> accessor = application->sub_menu_map(); + const SubMenuMap& sub_menus = accessor.GetData(); + SubMenuMap::const_iterator it = sub_menus.begin(); + for (int i = 0;it != sub_menus.end(); ++it, ++i) { + submenues_array[i] = *(it->second); + } + return submenues_array; +} + +smart_objects::SmartObject ResumptionData::GetApplicationInteractionChoiseSets( + ApplicationConstSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + + DCHECK(application.get()); + smart_objects::SmartObject interaction_choice_set_array = + smart_objects::SmartObject(smart_objects::SmartType_Array); + if (!application) { + LOG4CXX_ERROR(logger_, "NULL Pointer App"); + return interaction_choice_set_array; + } + const DataAccessor<ChoiceSetMap> accessor = application->choice_set_map(); + const ChoiceSetMap& choices = accessor.GetData(); + ChoiceSetMap::const_iterator it = choices.begin(); + for (int i = 0; it != choices.end(); ++it, ++i) { + interaction_choice_set_array[i] = *(it->second); + } + return interaction_choice_set_array; +} + +smart_objects::SmartObject ResumptionData::GetApplicationGlobalProperties( + ApplicationConstSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + + DCHECK(application.get()); + smart_objects::SmartObject global_properties = + smart_objects::SmartObject(smart_objects::SmartType_Map); + if (!application) { + LOG4CXX_ERROR(logger_, "NULL Pointer App"); + return global_properties; + } + + global_properties[strings::help_prompt] = + PointerToSmartObj(application->help_prompt()); + global_properties[strings::timeout_prompt] = + PointerToSmartObj(application->timeout_prompt()); + global_properties[strings::vr_help] = + PointerToSmartObj(application->vr_help()); + global_properties[strings::vr_help_title] = + PointerToSmartObj(application->vr_help_title()); + global_properties[strings::vr_synonyms] = + PointerToSmartObj(application->vr_synonyms()); + global_properties[strings::keyboard_properties] = + PointerToSmartObj(application->keyboard_props()); + global_properties[strings::menu_title] = + PointerToSmartObj(application->menu_title()); + global_properties[strings::menu_icon] = + PointerToSmartObj(application->menu_icon()); + return global_properties; +} + +smart_objects::SmartObject ResumptionData::GetApplicationSubscriptions( + ApplicationConstSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + DCHECK(application.get()); + smart_objects::SmartObject subscriptions = + smart_objects::SmartObject(smart_objects::SmartType_Map); + if (!application) { + LOG4CXX_ERROR(logger_, "NULL Pointer App"); + return subscriptions; + } + LOG4CXX_DEBUG(logger_, "app_id:" << application->app_id()); + LOG4CXX_DEBUG(logger_, "SubscribedButtons:" + << application->SubscribedButtons().size()); + Append(application->SubscribedButtons().begin(), + application->SubscribedButtons().end(), + strings::application_buttons, subscriptions); + LOG4CXX_DEBUG(logger_, "SubscribesIVI:" + << application->SubscribesIVI().size()); + Append(application->SubscribesIVI().begin(), + application->SubscribesIVI().end(), + strings::application_vehicle_info, subscriptions); + return subscriptions; +} + +smart_objects::SmartObject ResumptionData::GetApplicationFiles( + ApplicationConstSharedPtr application) { + DCHECK(application.get()); + LOG4CXX_TRACE(logger_, "ENTER app_id:" + << application->app_id()); + + smart_objects::SmartObject files = + smart_objects::SmartObject(smart_objects::SmartType_Array); + if (!application) { + LOG4CXX_ERROR(logger_, "NULL Pointer App"); + return files; + } + + const AppFilesMap& app_files = application->getAppFiles(); + int i = 0; + for(AppFilesMap::const_iterator file_it = app_files.begin(); + file_it != app_files.end(); file_it++, ++i) { + const AppFile& file = file_it->second; + if (file.is_persistent) { + smart_objects::SmartObject file_data = + smart_objects::SmartObject(smart_objects::SmartType_Map); + file_data[strings::persistent_file] = file.is_persistent; + file_data[strings::is_download_complete] = file.is_download_complete; + file_data[strings::sync_file_name] = file.file_name; + file_data[strings::file_type] = file.file_type; + files[i] = file_data; + } + } + return files; +} + +void ResumptionData::AddFiles(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app) { + LOG4CXX_AUTO_TRACE(logger_); + + if (saved_app.keyExists(strings::application_files)) { + const smart_objects::SmartObject& application_files = + saved_app[strings::application_files]; + for (int i = 0; i < application_files.length(); ++i) { + const smart_objects::SmartObject& file_data = + appliction_files[i]; + const bool is_persistent = file_data.keyExists(strings::persistent_file) && + file_data[strings::persistent_file].asBool(); + if (is_persistent) { + AppFile file; + file.is_persistent = is_persistent; + file.is_download_complete = + file_data[strings::is_download_complete].asBool(); + file.file_name = file_data[strings::sync_file_name].asString(); + file.file_type = static_cast<mobile_apis::FileType::eType> ( + file_data[strings::file_type].asInt()); + application->AddFile(file); + } + } + } else { + LOG4CXX_FATAL(logger_, "application_files section is not exists"); + } +} + +void ResumptionData::AddSubmenues(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app) { + LOG4CXX_AUTO_TRACE(logger_); + + if (saved_app.keyExists(strings::application_submenus)) { + const smart_objects::SmartObject& app_submenus = + saved_app[strings::application_submenus]; + for (int i = 0; i < app_submenus.length(); ++i) { + const smart_objects::SmartObject& submenu = app_submenues[i]; + application->AddSubMenu(submenu[strings::menu_id].asUInt(), submenu); + } + } else { + LOG4CXX_FATAL(logger_, "application_submenus section is not exists"); + } +} + +void ResumptionData::AddCommands(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app) { + LOG4CXX_AUTO_TRACE(logger_); + + if (saved_app.keyExists(strings::application_commands)) { + const smart_objects::SmartObject& app_commands = + saved_app[strings::application_commands]; + for (int i = 0; i < app_commands.length(); ++i) { + const smart_objects::SmartObject& command = + app_commands[i]; + application->AddCommand(command[strings::cmd_id].asUInt(), command); + } + } else { + LOG4CXX_FATAL(logger_, "application_commands section is not exists"); + } +} + +void ResumptionData::AddChoicesets(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app) { + LOG4CXX_AUTO_TRACE(logger_); + + if (saved_app.keyExists(strings::application_choice_sets)) { + const smart_objects::SmartObject& app_choice_sets = + saved_app[strings::application_choice_sets]; + for (int i = 0; i < app_choice_sets.length(); ++i) { + const smart_objects::SmartObject& choice_set = + app_choice_sets[i]; + const int32_t choice_set_id = + choice_set[strings::interaction_choice_set_id].asInt(); + application->AddChoiceSet(choice_set_id, choice_set); + } + } else { + LOG4CXX_FATAL(logger_, "There is no any choicesets"); + } +} + +void ResumptionData::SetGlobalProperties(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app) { + LOG4CXX_AUTO_TRACE(logger_); + + if (saved_app.keyExists(strings::application_global_properties)) { + const smart_objects::SmartObject& properties_so = + saved_app[strings::application_global_properties]; + application->load_global_properties(properties_so); + } +} + +void ResumptionData::AddSubscriptions(ApplicationSharedPtr application, + const smart_objects::SmartObject& saved_app) { + LOG4CXX_AUTO_TRACE(logger_); + if (saved_app.keyExists(strings::application_subscribtions)) { + const smart_objects::SmartObject& subscribtions = + saved_app[strings::application_subscribtions]; + + if (subscribtions.keyExists(strings::application_buttons)) { + const smart_objects::SmartObject& subscribtions_buttons = + subscribtions[strings::application_buttons]; + mobile_apis::ButtonName::eType btn; + for (int i = 0; i < subscribtions_buttons.length(); ++i) { + btn = static_cast<mobile_apis::ButtonName::eType>( + (subscribtions_buttons[i]).asInt()); + application->SubscribeToButton(btn); + } + } + + if (subscribtions.keyExists(strings::application_vehicle_info)) { + const smart_objects::SmartObject& subscribtions_ivi = + subscribtions[strings::application_vehicle_info]; + VehicleDataType ivi; + for (int i = 0; i < subscribtions_ivi.length(); ++i) { + ivi = static_cast<VehicleDataType>((subscribtions_ivi[i]).asInt()); + application->SubscribeToIVI(ivi); + } + } + } +} + +smart_objects::SmartObject ResumptionData::PointerToSmartObj( + smart_objects::SmartObject* ptr) { + LOG4CXX_AUTO_TRACE(logger_); + smart_objects::SmartObject temp; + if (ptr) { + temp = *ptr; + } + return temp; +} + +} // namespace resumption +} // namespace application_manager diff --git a/src/components/application_manager/src/resumption/resumption_data_db.cc b/src/components/application_manager/src/resumption/resumption_data_db.cc new file mode 100644 index 0000000000..891d51a3e7 --- /dev/null +++ b/src/components/application_manager/src/resumption/resumption_data_db.cc @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "application_manager/resumption/resumption_data_db.h" +#include "application_manager/resumption/resumption_sql_queries.h" +#if __QNX__ +# include "qdb_wrapper/sql_database.h" +# include "qdb_wrapper/sql_query.h" +#else // __QNX__ +# include "sqlite_wrapper/sql_database.h" +# include "sqlite_wrapper/sql_query.h" +#endif // __QNX__ + +namespace application_manager { +namespace resumption { +CREATE_LOGGERPTR_GLOBAL(logger_, "ResumptionDataDB") + +int ResumptionDataDB::GetStoredHMILevel(const std::string& m_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + int hmi_level; + if (SelectHMILevel(m_app_id, device_id, hmi_level)) { + LOG4CXX_INFO(logger_, "Application with mobile application id = "<<m_app_id + <<" and device id = "<<device_id<<"has hmi level = "<<hmi_level); + return hmi_level; + } + LOG4CXX_FATAL(logger_, "HMI level doesn't exists in saved data"); + return -1; +} + +bool ResumptionDataDB::IsHMIApplicationIdExist(uint32_t hmi_app_id) { + LOG4CXX_AUTO_TRACE(logger_); + + return CheckExistenceHMIId(hmi_app_id); +} + +bool ResumptionDataDB::CheckSavedApplication(const std::string& mobile_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + if (!CheckExistenceApplication(mobile_app_id, device_id)) { + LOG4CXX_INFO(logger_, "Application with mobile_app_id = "<<mobile_app_id + <<" and device_id = "<<device_id<<" does not exist"); + return false; + } + return true; +} + +uint32_t ResumptionDataDB::GetHMIApplicationID(const std::string& mobile_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + uint32_t hmi_app_id = 0; + SelectHMIId(mobile_app_id, device_id, hmi_app_id); + return hmi_app_id; +} + +void ResumptionDataDB::Suspend() { + LOG4CXX_AUTO_TRACE(logger_); + + utils::dbms::SQLQuery query_delete_applications(db()); + utils::dbms::SQLQuery query_update_suspend_data(db()); + utils::dbms::SQLQuery query_update_last_ign_off_time(db()); + + if (query_delete_applications.Prepare(kDeleteApplicationsAccordingWithIgnOffCount)) { + query_delete_applications.Bind(0, static_cast<int>(kApplicationLifes)); + if (query_delete_applications.Exec()) { + LOG4CXX_INFO(logger_, "Saved application with ign_off_count = "<<kApplicationLifes + <<" was deleted"); + } + } + + if (query_update_suspend_data.Prepare(kUpdateSuspendData)) { + if (query_update_suspend_data.Exec()) { + LOG4CXX_INFO(logger_, "Data ign_off_count and suspend_count was updated"); + } + } + + if (query_update_last_ign_off_time.Prepare(KUpdateLastIgnOffTime)) { + query_update_lals_ign_off_time.Bind(0, static_cast<uint32_t>(time(NULL))); + if (query_update_last_ign_off_time.Exec()) { + LOG4CXX_INFO(logger_, "Data last_ign_off_time was updated"); + } + } +} + + +bool ResumptionDataDB::GetHashId(const std::string& mobile_app_id, + const std::string& device_id, + std::string& hash_id) { + LOG4CXX_AUTO_TRACE(logger_); + + return SelectHashId(mobile_app_id, device_id, hash_id); +} + +void ResumptionDataDB::OnAwake() { + LOG4CXX_AUTO_TRACE(logger_); + + UpdateDataOnAwake(); +} + +bool ResumptionDataDB::RemoveApplicationFromSaved( + const std::string& mobile_app_id, const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + return DeleteSavedApplication(mobile_app_id, device_id); +} + +uint32_t ResumptionDataDB::GetIgnOffTime() { + LOG4CXX_AUTO_TRACE(logger_); + + return SelectIgnOffTime(); +} + +int ResumptionDataDB::IsApplicationSaved(const std::string& mobile_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + if (CheckExistenceApplication(mobile_app_id, device_id)) { + return 0; + } + return -1; +} + +void ResumptionDataDB::GetDataForLoadResumeData(smart_objects::SmartObject& saved_data) { + LOG4CXX_AUTO_TRACE(logger_); + SelectDataForLoadResumeData(saved_data); +} + +void ResumptionDataDB::SetHMILevelForSavedApplication(const std::string& mobile_app_id, + const std::string& device_id, int32_t hmi_level) { + LOG4CXX_AUTO_TRACE(logger_); + UpdateHmiLevel(mobile_app_id, device_id, hmi_level); +} + +bool ResumptionDataDB::SelectHMILevel(const std::string& m_app_id, + const std::string& device_id, + int& hmi_level) { + LOG4CXX_AUTO_TRACE(logger_); + + utils::dbms::SQLQuery query(db()); + if (query.Prepare(kSelectHMILevel)) { + query.Bind(0, device_id); + query.Bind(1, m_app_id); + if (query.Exec() && !(query.IsNull(0))) { + hmi_level = query.GetInteger(0); + return true; + } + } + return false; +} + +bool ResumptionDataDB::CheckExistenceHMIId(const uint32_t hmi_app_id) { + LOG4CXX_AUTO_TRACE(logger_); + + utils::dbms::SQLQuery query(db()); + if (query.Prepare(kCheckHMIId)) { + query.Bind(0, hmi_app_id); + if (query.Exec() && !(query.IsNull(0))) { + LOG4CXX_INFO(logger_, "Saved data has HMI appID"); + return true; + } + } + LOG4CXX_FATAL(logger_, "HMI appID = " <<hmi_app_id + <<" doesn't exist in saved data"); + return false; +} + +void ResumptionDataDB::SelectHMIId(const std::string& mobile_app_id, + const std::string& device_id, + uint32_t& hmi_id) { + LOG4CXX_AUTO_TRACE(logger_); + + utils::dbms::SQLQuery query(db()); + if (query.Prepare(kSelectHMIId)) { + query.Bind(0, device_id); + query.Bind(1, mobile_app_id); + if (query.Exec() && !(query.IsNull(0))) { + hmi_id = query.GetInteger(0); + LOG4CXX_INFO(logger_, "Saved HMI appID = "<<hmi_id); + } + } + LOG4CXX_FATAL(logger_, "Saved data doesn't have application with " + "device id = "<<device_id<<" and mobile appID = "<<mobi_app_id + "or hmi id"<<); +} + +bool ResumptionDataDB::SelectHashId(const std::string& mobile_app_id, + const std::string& device_id, + std::string& hash_id) { + LOG4CXX_AUTO_TRACE(logger_); + + utils::dbms::SQLQuery query(db()); + if (query.Prepare(kSelectHashId)) { + query.Bind(0, device_id); + query.Bind(1, mobile_app_id); + if (query.Exec() && !(query.IsNull(0))) { + hash_id = query.GetString(0); + LOG4CXX_INFO(logger_, "Saved hash ID = "<<hash_id); + return true; + } + } + LOG4CXX_FATAL(logger_, "Saved data doesn't have application with " + "device id = "<<device_id<<" and mobile appID = "<<mobi_app_id + "or hashID"); + return false; +} + +uint32_t ResumptionDataDB::SelectIgnOffTime() { + LOG4CXX_AUTO_TRACE(logger_); + + uint32_t ignOffTime = 0; + utils::dbms::SQLQuery query(db()); + if (query.Prepare(kSelectIgnOffTime)) { + if (query.Exec()) { + ignOffTime = query.GetUInteger(0); + LOG4CXX_INFO(logger_, "Last ign off time = "<<ignOffTime); + } + } + LOG4CXX_FATAL(logger_, "Problem with prepare query"); +} + +bool ResumptionDataDB::CheckExistenceApplication(const std::string& mobile_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + utils::dbms::SQLQuery query(db()); + if (query.Prepare(kCheckApplication)) { + query.Bind(0, device_id); + query.Bind(1, mobile_app_id); + if (query.Exec() && !(query.IsNull(0)) && query.GetInteger(0)) { + LOG4CXX_INFO(logger_, "Saved data has application with mobile appID = " + <<mobile_app_id<<" and deviceID = "<<device_id); + return true; + } + } + LOG4CXX_FATAL(logger_, "Saved data does not contain application"); + return false; +} + +void ResumptionDataDB::SelectDataForLoadResumeData( + smart_objects::SmartObject& saved_data) { + LOG4CXX_AUTO_TRACE(logger_); + + utils::dbms::SQLQuery query(db()); + if (query.Prepare(kSelectDataForLoadResumeData)) { + smart_objects::SmartObject so_array_data(smart_objects::SmartType_Array); + int i = 0; + while(query.Next()) { + smart_objects::SmartObject so_obj(smart_objects::SmartType_Map); + so_obj[strings::hmi_level] = query.GetInteger(0); + so_obj[strings::ign_off_count] = query.GetInteger(1); + so_obj[strings::time_stamp] = query.GetUInteger(2); + so_obj[strings::app_id] = query.GetString(3); + so_obj[strings::device_id] = query.GetString(4); + so_array_data[i++] = so_obj; + } + saved_data = so_array_data; + } +} + +void ResumptionDataDB::UpdateHmiLevel(const std::string& mobile_app_id, + const std::string& device_id, + int32_t hmi_level) { + LOG4CXX_AUTO_TRACE(logger_); + + utils::dbms::SQLQuery query(db()); + if (query.Prepare(kUpdateHMILevel)) { + query.Bind(0, hmi_level); + query.Bind(1, device_id); + query.Bind(2, mobile_app_id); + if (query.Exec()) { + LOG4CXX_INFO(logger_, "Saved data has application with mobile appID = " + <<mobile_app_id<<" and deviceID = "<<device_id + <<" has new HMI level = "<<hmi_level); + + } + } +} + +bool ResumptionDataDB::DeleteSavedApplication(const std::string& mobile_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + utils::dbms::SQLQuery query(db()); + if (query.Prepare(kDeleteApplication)) { + query.Bind(0, device_id); + query.Bind(1, mobile_app_id); + if (query.Exec()) { + LOG4CXX_INFO(logger_, "Data of application with mobile appID = " + <<mobile_app_id<<" and deviceID = "<<device_id + <<" was removed successfully"); + return true; + } + } + LOG4CXX_INFO(logger_, "Data of application with mobile appID = " + <<mobile_app_id<<" and deviceID = "<<device_id + <<" was not removed"); + return false; +} + +void ResumptionDataDB::UpdateDataOnAwake() { + LOG4CXX_AUTO_TRACE(logger_); + + utils::dbms::SQLQuery query(db()); + if (query.Prepare(kUpdateIgnOffCount)) { + if (query.Exec()) { + LOG4CXX_INFO(logger_, "Values of ignition off counts were updated successfully"); + } + } +} + + + +} // namespace resumption +} // namespace application_manager diff --git a/src/components/application_manager/src/resumption/resumption_data_json.cc b/src/components/application_manager/src/resumption/resumption_data_json.cc new file mode 100644 index 0000000000..8cf8e7d0d9 --- /dev/null +++ b/src/components/application_manager/src/resumption/resumption_data_json.cc @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "application_manager/resumption/resumption_data_json.h" +#include "smart_objects/smart_object.h" +#include "json/json.h" +namespace application_manager { +namespace resumption { + +CREATE_LOGGERPTR_GLOBAL(logger_, "ResumptionDataJson") + +void ResumptionDataJson::SaveApplication(ApplicationConstSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + + DCHECK(application.get()); + + if (!application) { + LOG4CXX_FATAL(logger_, "Application object is NULL."); + return; + } + + const std::string& m_app_id = application->mobile_app_id(); + LOG4CXX_TRACE(logger_, "ENTER app_id : " << application->app_id() + << " mobile app_id : " << m_app_id); + + // let's make a copy not to depend on application + const std::string hash = application->curHash(); + const uint32_t grammar_id = application->get_grammar_id(); + const uint32_t time_stamp = (uint32_t)time(NULL); + const std::string device_id = + MessageHelper::GetDeviceMacAddressForHandle(application->device()); + + const mobile_apis::HMILevel::eType hmi_level = application->hmi_level(); + + Json::Value tmp; + + Json::Value& json_app = GetFromSavedOrAppend(m_app_id, device_id); + + json_app[strings::device_id] = device_id; + + json_app[strings::app_id] = m_app_id; + json_app[strings::grammar_id] = grammar_id; + json_app[strings::connection_key] = application->app_id(); + json_app[strings::hmi_app_id] = application->hmi_app_id(); + json_app[strings::is_media_application] = application->IsAudioApplication(); + json_app[strings::hmi_level] = static_cast<int32_t> (hmi_level); + json_app[strings::ign_off_count] = 0; + json_app[strings::suspend_count] = 0; + json_app[strings::hash_id] = hash; + Formatters::CFormatterJsonBase::objToJsonValue( + GetApplicationCommands(application), tmp); + json_app[strings::application_commands] = tmp; + Formatters::CFormatterJsonBase::objToJsonValue( + GetApplicationSubMenus(application), tmp); + json_app[strings::application_submenus] = tmp; + Formatters::CFormatterJsonBase::objToJsonValue( + GetApplicationInteractionChoiseSets(application), tmp); + json_app[strings::application_choice_sets] = tmp; + Formatters::CFormatterJsonBase::objToJsonValue( + GetApplicationGlobalProperties(application), tmp); + json_app[strings::application_global_properties] = tmp; + Formatters::CFormatterJsonBase::objToJsonValue( + GetApplicationSubscriptions(application), tmp); + json_app[strings::application_subscribtions] = tmp; + Formatters::CFormatterJsonBase::objToJsonValue( + GetApplicationFiles(application), tmp); + json_app[strings::application_files] = tmp; + json_app[strings::time_stamp] = time_stamp; + LOG4CXX_DEBUG(logger_, "SaveApplication : " << json_app.toStyledString()); +} + +int ResumptionDataJson::GetStoredHMILevel(const std::string& m_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + int idx = GetObjectIndex(m_app_id, device_id); + if (idx != -1) { + const Json::Value& json_app = GetSavedApplications()[idx]; + if (json_app.isMember(strings::hmi_level)) { + return json_app[strings::hmi_level].asInt(); + } + } + LOG4CXX_FATAL(logger_, "There are some unknown keys among the stored apps"); + return -1; +} + +bool ResumptionDataJson::RestoreApplicationData( + ApplicationSharedPtr application) { + LOG4CXX_AUTO_TRACE(logger_); + + if (!application.valid()) { + LOG4CXX_ERROR(logger_, "Application pointer in invalid"); + return false; + } + + LOG4CXX_DEBUG(logger_, "ENTER app_id : " << application->app_id()); + smart_objects::SmartObject saved_app(smart_objects::SmartType_Map); + bool result = GetSavedApplication(application->mobile_app_id(), + MessageHelper::GetDeviceMacAddressForHandle(application->device()), + saved_app); + if (result) { + if(saved_app.keyExists(strings::grammar_id)) { + const uint32_t app_grammar_id = saved_app[strings::grammar_id].asUInt(); + application->set_grammar_id(app_grammar_id); + + AddFiles(application, so_saved_app); + AddSubmenues(application, so_saved_app); + AddCommands(application, so_saved_app); + AddChoicesets(application, so_saved_app); + SetGlobalProperties(application, so_saved_app); + AddSubscriptions(application, so_saved_app); + return true; + } else { + LOG4CXX_WARN(logger_, "Saved data of application does not contain grammar_id"); + return false; + } + } + LOG4CXX_WARN(logger_, "Application not saved"); + return false; +} + +bool ResumptionDataJson::IsHMIApplicationIdExist(uint32_t hmi_app_id) { + LOG4CXX_AUTO_TRACE(logger_); + + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if ((*it).isMember(strings::hmi_app_id)) { + if ((*it)[strings::hmi_app_id].asUInt() == hmi_app_id) { + return true; + } + } + } + return false; +} + +bool ResumptionDataJson::CheckSavedApplication(const std::string& mobile_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + int index = IsApplicationSaved(mobile_app_id, device_id); + if (-1 == index) { + return false; + } + + if (!IsResumptionDataValid(index)) { + LOG4CXX_INFO(logger_, "Resumption data for app_id " << mobile_app_id << + " device id " << device_id << + " is corrupted. Remove application from resumption list"); + RemoveApplicationFromSaved(mobile_app_id, device_id); + return false; + } + return true; +} + +uint32_t ResumptionDataJson::GetHMIApplicationID( + const std::string& mobile_app_id, const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + uint32_t hmi_app_id = 0; + + const int idx = GetObjectIndex(mobile_app_id, device_id); + if (-1 == idx) { + LOG4CXX_WARN(logger_, "Application not saved"); + return hmi_app_id; + } + + const Json::Value& json_app = GetSavedApplications()[idx]; + if (json_app.isMember(strings::app_id) && + json_app.isMember(strings::device_id)) { + hmi_app_id = json_app[strings::hmi_app_id].asUInt(); + } + LOG4CXX_DEBUG(logger_, "hmi_app_id :" << hmi_app_id); + return hmi_app_id; +} + +void ResumptionDataJson::Suspend() { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value to_save; + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if ((*it).isMember(strings::suspend_count)) { + const uint32_t suspend_count = (*it)[strings::suspend_count].asUInt(); + (*it)[strings::suspend_count] = suspend_count + 1; + } else { + LOG4CXX_WARN(logger_, "Unknown key among saved applications"); + (*it)[strings::suspend_count] = 1; + } + if ((*it).isMember(strings::ign_off_count)) { + const uint32_t ign_off_count = (*it)[strings::ign_off_count].asUInt(); + if (ign_off_count < kApplicationLifes) { + (*it)[strings::ign_off_count] = ign_off_count + 1; + to_save.append(*it); + } + } else { + LOG4CXX_WARN(logger_, "Unknown key among saved applications"); + (*it)[strings::ign_off_count] = 1; + } + } + SetSavedApplication(to_save); + SetLastIgnOffTime(time(NULL)); + LOG4CXX_DEBUG(logger_, + GetResumptionData().toStyledString()); + resumption::LastState::instance()->SaveToFileSystem(); +} + +void ResumptionDataJson::OnAwake() { + LOG4CXX_AUTO_TRACE(logger_); + + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if ((*it).isMember(strings::ign_off_count)) { + const uint32_t ign_off_count = (*it)[strings::ign_off_count].asUInt(); + (*it)[strings::ign_off_count] = ign_off_count - 1; + } else { + LOG4CXX_WARN(logger_, "Unknown key among saved applications"); + (*it)[strings::ign_off_count] = 0; + } + } +} + +bool ResumptionDataJson::GetHashId(const std::string& mobile_app_id, + const std::string& device_id, + std::string& hash_id) { + LOG4CXX_AUTO_TRACE(logger_); + + const int idx = GetObjectIndex(mobile_app_id, device_id); + if (-1 == idx) { + LOG4CXX_WARN(logger_, "Application not saved"); + return false; + } + + const Json::Value& json_app = GetSavedApplications()[idx]; + LOG4CXX_DEBUG(logger_, "Saved_application_data: " << json_app.toStyledString()); + if (json_app.isMember(strings::hash_id) && json_app.isMember(strings::time_stamp)) { + hash_id = json_app[strings::hash_id].asString(); + return true; + } + LOG4CXX_WARN(logger_, "There are some unknown keys in the dictionary."); + return false; +} + +bool ResumptionDataJson::GetSavedApplication(const std::string& mobile_app_id, + const std::string& device_id, + smart_objects::SmartObject& saved_app) { + const int idx = GetObjectIndex(mobile_app_id, device_id); + if (-1 == idx) { + return false; + } + const Json::Value& json_saved_app = GetSavedApplications()[idx]; + Formatters::CFormatterJsonBase::jsonValueToObj(json_saved_app, saved_app); + return true; +} + +bool ResumptionDataJson::RemoveApplicationFromSaved(const std::string& mobile_app_id, + const std::string& device_id) { + LOG4CXX_TRACE(logger_, "Remove mobile_app_id " << mobile_app_id); + + bool result = false; + std::vector<Json::Value> temp; + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if ((*it).isMember(strings::app_id) && + (*it).isMember(strings::device_id)) { + const std::string& saved_m_app_id = (*it)[strings::app_id].asString(); + const std::string& saved_device_id = (*it)[strings::device_id].asString(); + if (saved_m_app_id != mobile_app_id && saved_device_id != device_id) { + temp.push_back((*it)); + } else { + result = true; + } + } + } + + if (false == result) { + LOG4CXX_TRACE(logger_, "EXIT result: " << (result ? "true" : "false")); + return result; + } + + GetSavedApplications().clear(); + for (std::vector<Json::Value>::iterator it = temp.begin(); + it != temp.end(); ++it) { + GetSavedApplications().append((*it)); + } + LOG4CXX_TRACE(logger_, "EXIT result: " << (result ? "true" : "false")); + return result; +} + +uint32_t ResumptionDataJson::GetIgnOffTime() { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value& resumption = GetResumptionData(); + if (!resumption.isMember(strings::last_ign_off_time)) { + resumption[strings::last_ign_off_time] = 0; + LOG4CXX_WARN(logger_, "last_save_time section is missed"); + } + return resumption[strings::last_ign_off_time].asUInt(); +} + +int ResumptionDataJson::IsApplicationSaved(const std::string& mobile_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + return GetObjectIndex(mobile_app_id, device_id); +} + +Json::Value& ResumptionDataJson::GetFromSavedOrAppend(const std::string& mobile_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if (device_id == (*it)[strings::device_id].asString() && + mobile_app_id == (*it)[strings::app_id].asString()) { + return *it; + } + } + + return GetSavedApplications().append(Json::Value()); +} + +void ResumptionDataJson::GetDataForLoadResumeData( + smart_objects::SmartObject& saved_data) { + LOG4CXX_AUTO_TRACE(logger_); + smart_objects::SmartObject so_array_data(smart_objects::SmartType_Array); + int i = 0; + for (Json::Value::iterator it = GetSavedApplications().begin(); + it != GetSavedApplications().end(); ++it) { + if (((*it).isMember(strings::hmi_level)) && + ((*it).isMember(strings::ign_off_count)) && + ((*it).isMember(strings::time_stamp)) && + ((*it).isMember(strings::app_id)) && + ((*it).isMember(strings::device_id))) { + smart_objects::SmartObject so(smart_objects::SmartType_Map); + so[strings::hmi_level] = (*it)[strings::hmi_level].asInt(); + so[strings::ign_off_count] = (*it)[strings::ign_off_count].asInt(); + so[strings::time_stamp] = (*it)[strings::time_stamp].asUInt(); + so[strings::app_id] = (*it)[strings::app_id].asString(); + so[strings::device_id] = (*it)[strings::device_id].asString(); + so_array_data[i++] = so; + } + } + saved_data = so_array_data; +} + +void ResumptionDataJson::SetHMILevelForSavedApplication(const std::string& mobile_app_id, + const std::string& device_id, + int32_t hmi_level) { + LOG4CXX_AUTO_TRACE(logger_); + + int idx = GetObjIndex(mobile_app_id, device_id); + if (-1 == idx) { + LOG4CXX_WARN(logger_, "Application isn't saved with mobile_app_id = " + <<mobile_app_id<<" device_id = "<<device_id); + return; + } + GetSavedApplications()[idx][strings::hmi_level] = hmi_level; +} + +Json::Value& ResumptionDataJson::GetSavedApplications() { + LOG4CXX_AUTO_TRACE(logger_); + + Json::Value& resumption = GetResumptionData(); + if (!resumption.isMember(strings::resume_app_list)) { + resumption[strings::resume_app_list] = Json::Value(Json::arrayValue); + LOG4CXX_WARN(logger_, "app_list section is missed"); + } + Json::Value& resume_app_list = resumption[strings::resume_app_list]; + if (!resume_app_list.isArray()) { + LOG4CXX_ERROR(logger_, "resume_app_list type INVALID rewrite"); + resume_app_list = Json::Value(Json::arrayValue); + } + return resume_app_list; +} + +Json::Value& ResumptionDataJson::GetResumptionData() { + LOG4CXX_AUTO_TRACE(logger_); + + Json::Value& last_state = resumption::LastState::instance()->dictionary; + if (!last_state.isMember(strings::resumption)) { + last_state[strings::resumption] = Json::Value(Json::objectValue); + LOG4CXX_WARN(logger_, "resumption section is missed"); + } + Json::Value& resumption = last_state[strings::resumption]; + if (!resumption.isObject()) { + LOG4CXX_ERROR(logger_, "resumption type INVALID rewrite"); + resumption = Json::Value(Json::objectValue); + } + return resumption; +} + +int ResumptionDataJson::GetObjectIndex(const std::string& mobile_app_id, + const std::string& device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + const Json::Value& apps = GetSavedApplications(); + const Json::ArrayIndex size = apps.size(); + Json::ArrayIndex idx = 0; + for (; idx != size; ++idx) { + if (apps[idx].isMember(strings::app_id) && + apps[idx].isMember(strings::device_id)) { + const std::string& saved_app_id = apps[idx][strings::app_id].asString(); + const std::string& saved_device_id = apps[idx][strings::device_id].asString(); + if (device_id == saved_device_id && + mobile_app_id == saved_app_id) { + LOG4CXX_DEBUG(logger_, "Found " << idx); + return idx; + } + } + } + return -1; +} + +bool ResumptionDataJson::IsResumptionDataValid(uint32_t index) { + LOG4CXX_AUTO_TRACE(logger_); + + const Json::Value& json_app = GetSavedApplications()[index]; + if (!json_app.isMember(strings::app_id) || + !json_app.isMember(strings::ign_off_count) || + !json_app.isMember(strings::hmi_level) || + !json_app.isMember(strings::hmi_app_id) || + !json_app.isMember(strings::time_stamp) || + !json_app.isMember(strings::device_id)) { + LOG4CXX_ERROR(logger_, "Wrong resumption data"); + return false; + } + + if (json_app.isMember(strings::hmi_app_id) && + 0 >= json_app[strings::hmi_app_id].asUInt()) { + LOG4CXX_ERROR(logger_, "Wrong resumption hmi app ID"); + return false; + } + + return true; +} + +void ResumptionDataJson::SetSavedApplication(Json::Value& apps_json) { + LOG4CXX_AUTO_TRACE(logger_); + Json::Value& app_list = GetSavedApplications(); + app_list = apps_json; +} + +void ResumptionDataJson::SetLastIgnOffTime(time_t ign_off_time) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_WARN(logger_, "ign_off_time = " << ign_off_time); + Json::Value& resumption = GetResumptionData(); + resumption[strings::last_ign_off_time] = static_cast<uint32_t>(ign_off_time); +} + +} // resumption +} // application_manager diff --git a/src/components/application_manager/src/resumption/resumption_sql_queries.cc b/src/components/application_manager/src/resumption/resumption_sql_queries.cc new file mode 100644 index 0000000000..3ba34a090e --- /dev/null +++ b/src/components/application_manager/src/resumption/resumption_sql_queries.cc @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "application_manager/resumption/resumption_sql_queries.h" + +namespace application_manager { +namespace resumption { + +const std::string kCreateSchema; + +const std::string kSelectHMILevel = + "SELECT `hmiLevel` FROM `application` " + "WHERE `deviceID` = ? AND `AppID` = ?"; + +const std::string kCheckHMIId = + "SELECT `hmiAppID` FROM `application` " + "WHERE `hmiAppID` = ?"; + +const std::string kSelectHMIId = + "SELECT `hmiAppID` FROM `application` " + "WHERE `deviceID` = ? AND `AppID` = ?"; + +const std::string kSelectHashId = + "SELECT `hashID` FROM `application` " + "WHERE `deviceID` = ? AND `AppID` = ?"; + +const std::string kSelectIgnOffTime = + "SELECT `last_ign_off_time` FROM `resumption`"; + +const std::string kCheckApplication = + "SELECT COUNT (`deviceID`) FROM `application` " + "WHERE `deviceID` = ? AND `AppID` = ?"; + +const std::string kSelectDataForLoadResumeData = + "SELECT `hmiLevel`, `ign_off_count`, `timeStamp`, `appID`, `deviceID` " + "FROM `application`" + "WHERE `hmiLevel` IS NOT NULL AND `ign_off_count` IS NOT NULL " + "AND `timeStamp` IS NOT NULL AND `appID` IS NOT NULL AND `deviceID` IS NOT NULL"; + +const std::string kUpdateHMILevel = + "UPDATE `application` " + "SET `hmiLevel` = ? " + "WHERE `deviceID` = ? AND `AppID` = ?"; + +const std::string kDeleteApplication = + "DELETE " + "FROM `application` " + "WHERE `deviceID` = ? AND `AppID` = ?"; + +const std::string kUpdateIgnOffCount = + "UPDATE `application` " + "SET `ign_off_count` = `ign_off_count` - 1" + "WHERE `ign_off_count` > 0"; + +const std::string kDeleteApplicationsAccordingWithIgnOffCount = + "DELETE " + "FROM `application` " + "WHERE `ign_off_count` >= ?"; + +const std::string kUpdateSuspendData = + "UPDATE `application` " + "SET `ign_off_count` = `ign_off_count` + 1, " + "`suspend_count` = `suspend_count` + 1"; + +const std::string KUpdateLastIgnOffTime = + "UPDATE `resumption` " + "SET `last_ign_off_time` = ?"; + +} // namespace resumption +} // namespace application_manager diff --git a/src/components/utils/include/utils/qdb_wrapper/sql_query.h b/src/components/utils/include/utils/qdb_wrapper/sql_query.h index ad79a00a55..122133f4ea 100644 --- a/src/components/utils/include/utils/qdb_wrapper/sql_query.h +++ b/src/components/utils/include/utils/qdb_wrapper/sql_query.h @@ -151,6 +151,13 @@ class SQLQuery { /** * Gets value in the result record * @param pos position of value + * @return unsigned integer value + */ + uint32_t SQLQuery::GetUInteger(int pos) const; + + /** + * Gets value in the result record + * @param pos position of value * @return double value */ double GetDouble(int pos) const; diff --git a/src/components/utils/include/utils/sqlite_wrapper/sql_query.h b/src/components/utils/include/utils/sqlite_wrapper/sql_query.h index 0f79370f9c..1240610ca4 100644 --- a/src/components/utils/include/utils/sqlite_wrapper/sql_query.h +++ b/src/components/utils/include/utils/sqlite_wrapper/sql_query.h @@ -150,6 +150,13 @@ class SQLQuery { /** * Gets value in the result record * @param pos position of value + * @return unsigned integer value + */ + uint32_t GetUInteger(int pos) const; + + /** + * Gets value in the result record + * @param pos position of value * @return double value */ double GetDouble(int pos) const; diff --git a/src/components/utils/src/qdb_wrapper/sql_query.cc b/src/components/utils/src/qdb_wrapper/sql_query.cc index e13cab5ee3..59619bbe4d 100644 --- a/src/components/utils/src/qdb_wrapper/sql_query.cc +++ b/src/components/utils/src/qdb_wrapper/sql_query.cc @@ -240,6 +240,15 @@ int SQLQuery::GetInteger(int pos) const { return 0; } +uint32_t SQLQuery::GetUInteger(int pos) const { + void* ret = qdb_cell(result_, current_row_, pos); + if (rows_ !=0 && ret) { + return *static_cast<uint32_t*>(ret); + } + return 0; +} + + double SQLQuery::GetDouble(int pos) const { void* ret = qdb_cell(result_, current_row_, pos); if (rows_ !=0 && ret) { diff --git a/src/components/utils/src/sqlite_wrapper/sql_query.cc b/src/components/utils/src/sqlite_wrapper/sql_query.cc index f548a9f23f..7b8a6ef837 100644 --- a/src/components/utils/src/sqlite_wrapper/sql_query.cc +++ b/src/components/utils/src/sqlite_wrapper/sql_query.cc @@ -121,6 +121,11 @@ int SQLQuery::GetInteger(int pos) const { return sqlite3_column_int(statement_, pos); } +uint32_t SQLQuery::GetUInteger(int pos) const { + return static_cast<uint32_t>( + sqlite3_column_int64(statement_, pos)); +} + double SQLQuery::GetDouble(int pos) const { return sqlite3_column_double(statement_, pos); } |