/* * 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. */ #if defined(OS_WINDOWS) #include #endif #include "application_manager/application_manager_impl.h" #include "application_manager/resumption/resumption_data_json.h" #include "smart_objects/smart_object.h" #include "formatters/CFormatterJsonBase.h" #include "application_manager/message_helper.h" #include "application_manager/smart_object_keys.h" #include "application_manager/application_manager_settings.h" namespace resumption { namespace Formatters = NsSmartDeviceLink::NsJSONHandler::Formatters; SDL_CREATE_LOGGER("Resumption") ResumptionDataJson::ResumptionDataJson( LastState& last_state, const application_manager::ApplicationManager& application_manager) : ResumptionData(application_manager), last_state_(last_state) {} void ResumptionDataJson::SaveApplication( app_mngr::ApplicationSharedPtr application) { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); DCHECK_OR_RETURN_VOID(application); const std::string& policy_app_id = application->policy_app_id(); SDL_DEBUG("app_id : " << application->app_id() << " policy_app_id : " << policy_app_id); const std::string hash = application->curHash(); const uint32_t grammar_id = application->get_grammar_id(); const utils::json::JsonValue::UInt time_stamp = static_cast(time(NULL)); const std::string device_mac = application->mac_address(); const mobile_apis::HMILevel::eType hmi_level = application->hmi_level(); const bool is_subscribed_for_way_points = application_manager_.IsAppSubscribedForWayPoints(application->app_id()); sync_primitives::AutoLock autolock(resumption_lock_); JsonValue tmp; JsonValueRef json_app = GetFromSavedOrAppend(policy_app_id, device_mac); json_app[strings::device_id] = device_mac; json_app[strings::app_id] = policy_app_id; json_app[strings::grammar_id] = utils::json::JsonValue::UInt(grammar_id); json_app[strings::connection_key] = utils::json::JsonValue::UInt(application->app_id()); json_app[strings::hmi_app_id] = utils::json::JsonValue::UInt(application->hmi_app_id()); json_app[strings::is_media_application] = application->IsAudioApplication(); json_app[strings::hmi_level] = utils::json::JsonValue::Int(hmi_level); json_app[strings::ign_off_count] = utils::json::JsonValue::UInt(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; json_app[strings::subscribed_for_way_points] = is_subscribed_for_way_points; SDL_DEBUG("SaveApplication : " << json_app.ToJson()); } bool ResumptionDataJson::IsHMIApplicationIdExist(uint32_t hmi_app_id) const { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); const JsonValueRef saved_applications = GetSavedApplications(); for (JsonValue::const_iterator itr = saved_applications.begin(), end = saved_applications.end(); itr != end; ++itr) { if ((*itr).HasMember(strings::hmi_app_id)) { if ((*itr)[strings::hmi_app_id].AsUInt() == hmi_app_id) { return true; } } } return false; } uint32_t ResumptionDataJson::GetHMIApplicationID( const std::string& policy_app_id, const std::string& device_id) const { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); uint32_t hmi_app_id = 0; const int idx = GetObjectIndex(policy_app_id, device_id); if (-1 == idx) { SDL_WARN("Application not saved"); return hmi_app_id; } const JsonValueRef json_app = GetSavedApplications()[idx]; if (json_app.HasMember(strings::app_id) && json_app.HasMember(strings::device_id)) { hmi_app_id = json_app[strings::hmi_app_id].AsUInt(); } SDL_DEBUG("hmi_app_id :" << hmi_app_id); return hmi_app_id; } void ResumptionDataJson::OnSuspend() { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); JsonValue to_save; JsonValueRef saved_applications = GetSavedApplications(); for (JsonValue::iterator itr = saved_applications.begin(), end = saved_applications.end(); itr != end; ++itr) { if ((*itr).HasMember(strings::ign_off_count)) { JsonValueRef ign_off_count = (*itr)[strings::ign_off_count]; const uint32_t counter_value = ign_off_count.AsUInt(); ign_off_count = utils::json::JsonValue::UInt(counter_value + 1); } else { SDL_WARN("Unknown key among saved applications"); (*itr)[strings::ign_off_count] = utils::json::JsonValue::UInt(1); } to_save.Append(*itr); } SetSavedApplication(to_save); SetLastIgnOffTime(time(NULL)); SDL_DEBUG(GetResumptionData().ToJson()); } void ResumptionDataJson::OnAwake() { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); JsonValueRef saved_applications = GetSavedApplications(); for (JsonValue::iterator itr = saved_applications.begin(), end = saved_applications.end(); itr != end; ++itr) { if ((*itr).HasMember(strings::ign_off_count)) { const uint32_t ign_off_count = (*itr)[strings::ign_off_count].AsUInt(); if (0 == ign_off_count) { SDL_WARN("Application has not been suspended"); } else { (*itr)[strings::ign_off_count] = utils::json::JsonValue::UInt(ign_off_count - 1); } } else { SDL_WARN("Unknown key among saved applications"); (*itr)[strings::ign_off_count] = utils::json::JsonValue::UInt(0); } } } bool ResumptionDataJson::GetHashId(const std::string& policy_app_id, const std::string& device_id, std::string& hash_id) const { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); const int idx = GetObjectIndex(policy_app_id, device_id); if (-1 == idx) { SDL_WARN("Application not saved"); return false; } const JsonValueRef json_app = GetSavedApplications()[idx]; SDL_DEBUG("Saved_application_data: " << json_app.ToJson()); if (json_app.HasMember(strings::hash_id) && json_app.HasMember(strings::time_stamp)) { hash_id = json_app[strings::hash_id].AsString(); return true; } SDL_WARN("There are some unknown keys in the dictionary."); return false; } bool ResumptionDataJson::GetSavedApplication( const std::string& policy_app_id, const std::string& device_id, smart_objects::SmartObject& saved_app) const { using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); const int idx = GetObjectIndex(policy_app_id, device_id); if (-1 == idx) { return false; } const JsonValueRef json_saved_app = GetSavedApplications()[idx]; Formatters::CFormatterJsonBase::jsonValueToObj(json_saved_app, saved_app); return true; } bool ResumptionDataJson::RemoveApplicationFromSaved( const std::string& policy_app_id, const std::string& device_id) { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); bool result = false; std::vector temp; JsonValueRef saved_applications = GetSavedApplications(); for (JsonValue::iterator itr = saved_applications.begin(), end = saved_applications.end(); itr != end; ++itr) { if ((*itr).HasMember(strings::app_id) && (*itr).HasMember(strings::device_id)) { const std::string& saved_policy_app_id = (*itr)[strings::app_id].AsString(); const std::string& saved_device_id = (*itr)[strings::device_id].AsString(); if (saved_policy_app_id != policy_app_id && saved_device_id != device_id) { temp.push_back((*itr)); } else { result = true; } } } if (false == result) { SDL_TRACE("EXIT result: " << (result ? "true" : "false")); return result; } saved_applications.Clear(); for (std::vector::iterator it = temp.begin(); it != temp.end(); ++it) { saved_applications.Append((*it)); } SDL_TRACE("EXIT result: " << (result ? "true" : "false")); return result; } uint32_t ResumptionDataJson::GetIgnOffTime() const { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); JsonValueRef resumption = GetResumptionData(); if (!resumption.HasMember(strings::last_ign_off_time)) { resumption[strings::last_ign_off_time] = utils::json::JsonValue::UInt(0); SDL_WARN("last_save_time section is missed"); } return resumption[strings::last_ign_off_time].AsUInt(); } ssize_t ResumptionDataJson::IsApplicationSaved( const std::string& policy_app_id, const std::string& device_id) const { SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); return GetObjectIndex(policy_app_id, device_id); } utils::json::JsonValueRef ResumptionDataJson::GetFromSavedOrAppend( const std::string& policy_app_id, const std::string& device_id) const { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); JsonValueRef saved_applications = GetSavedApplications(); for (JsonValue::iterator itr = saved_applications.begin(), end = saved_applications.end(); itr != end; ++itr) { if (device_id == (*itr)[strings::device_id].AsString() && policy_app_id == (*itr)[strings::app_id].AsString()) { return *itr; } } return GetSavedApplications().Append(JsonValue()); } void ResumptionDataJson::GetDataForLoadResumeData( smart_objects::SmartObject& saved_data) const { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); smart_objects::SmartObject so_array_data(smart_objects::SmartType_Array); int i = 0; JsonValueRef saved_applications = GetSavedApplications(); for (JsonValue::iterator itr = saved_applications.begin(), end = saved_applications.end(); itr != end; ++itr) { if (((*itr).HasMember(strings::hmi_level)) && ((*itr).HasMember(strings::ign_off_count)) && ((*itr).HasMember(strings::time_stamp)) && ((*itr).HasMember(strings::app_id)) && ((*itr).HasMember(strings::device_id))) { smart_objects::SmartObject so(smart_objects::SmartType_Map); so[strings::hmi_level] = static_cast((*itr)[strings::hmi_level].AsInt()); so[strings::ign_off_count] = static_cast((*itr)[strings::ign_off_count].AsInt()); so[strings::time_stamp] = static_cast((*itr)[strings::time_stamp].AsUInt()); so[strings::app_id] = (*itr)[strings::app_id].AsString(); so[strings::device_id] = (*itr)[strings::device_id].AsString(); so_array_data[i++] = so; } } saved_data = so_array_data; } ResumptionDataJson::~ResumptionDataJson() { // TODO Probably Save Data on disk } void ResumptionDataJson::UpdateHmiLevel( const std::string& policy_app_id, const std::string& device_id, mobile_apis::HMILevel::eType hmi_level) { SDL_AUTO_TRACE(); using namespace app_mngr; int idx = GetObjectIndex(policy_app_id, device_id); if (-1 == idx) { SDL_WARN("Application isn't saved with mobile_app_id = " << policy_app_id << " device_id = " << device_id); return; } GetSavedApplications()[idx][strings::hmi_level] = utils::json::JsonValue::Int(hmi_level); } utils::json::JsonValueRef ResumptionDataJson::GetSavedApplications() const { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); JsonValueRef resumption = GetResumptionData(); if (!resumption.HasMember(strings::resume_app_list)) { resumption[strings::resume_app_list] = JsonValue(ValueType::ARRAY_VALUE); SDL_WARN("app_list section is missed"); } JsonValueRef resume_app_list = resumption[strings::resume_app_list]; if (!resume_app_list.IsArray()) { SDL_ERROR("resume_app_list type INVALID rewrite"); resume_app_list = JsonValue(ValueType::ARRAY_VALUE); } return resume_app_list; } utils::json::JsonValueRef ResumptionDataJson::GetResumptionData() const { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); JsonValue& last_state = last_state_.dictionary(); if (!last_state.HasMember(strings::resumption)) { last_state[strings::resumption] = JsonValue(ValueType::OBJECT_VALUE); SDL_WARN("resumption section is missed"); } utils::json::JsonValueRef resumption = last_state[strings::resumption]; if (!resumption.IsObject()) { SDL_ERROR("resumption type INVALID rewrite"); resumption = JsonValue(ValueType::OBJECT_VALUE); } return resumption; } ssize_t ResumptionDataJson::GetObjectIndex(const std::string& policy_app_id, const std::string& device_id) const { using namespace app_mngr; using namespace utils::json; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); const JsonValueRef apps = GetSavedApplications(); const JsonValue::ArrayIndex size = apps.Size(); JsonValue::ArrayIndex idx = 0; for (; idx != size; ++idx) { if (apps[idx].HasMember(strings::app_id) && apps[idx].HasMember(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 && policy_app_id == saved_app_id) { SDL_DEBUG("Found " << idx); return idx; } } } return -1; } void ResumptionDataJson::SetSavedApplication( utils::json::JsonValueRef apps_json) { SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); utils::json::JsonValueRef app_list = GetSavedApplications(); app_list = apps_json; } void ResumptionDataJson::SetLastIgnOffTime(time_t ign_off_time) { using namespace app_mngr; SDL_AUTO_TRACE(); sync_primitives::AutoLock autolock(resumption_lock_); SDL_WARN("ign_off_time = " << ign_off_time); utils::json::JsonValueRef resumption = GetResumptionData(); resumption[strings::last_ign_off_time] = utils::json::JsonValue::UInt(ign_off_time); } bool ResumptionDataJson::Init() { SDL_AUTO_TRACE(); return true; } bool ResumptionDataJson::DropAppDataResumption(const std::string& device_id, const std::string& app_id) { SDL_AUTO_TRACE(); using namespace app_mngr; sync_primitives::AutoLock autolock(resumption_lock_); utils::json::JsonValueRef application = GetFromSavedOrAppend(app_id, device_id); if (application.IsNull()) { SDL_DEBUG("Application " << app_id << " with device_id " << device_id << " hasn't been found in resumption data."); return false; } application[strings::application_commands].Clear(); application[strings::application_submenus].Clear(); application[strings::application_choice_sets].Clear(); application[strings::application_global_properties].Clear(); application[strings::application_subscribtions].Clear(); application[strings::application_files].Clear(); application.RemoveMember(strings::grammar_id); SDL_DEBUG("Resumption data for application " << app_id << " with device_id " << device_id << " has been dropped."); return true; } void ResumptionDataJson::Persist() { last_state().SaveToFileSystem(); } } // resumption