/* * Copyright (c) 2019 TOYOTA MOTOR CORPORATION * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "hs-apprecover.h" #include "hs-appinfo.h" #include "hs-proxy.h" #include "hs-clientmanager.h" HS_AppRecover* HS_AppRecover::me = nullptr; /** * screen_update event handler * * #### Parameters * - api : the api * - event : received event name * - object : received json object * * #### Return * 0 : event can transfer to others * 1 : event not transfer to others */ int on_screen_update_event(afb_api_t api, const char *event, struct json_object *object) { HS_AppRecover::instance()->screenUpdated(object); return 0; } /** * get instance * * #### Parameters * - Nothing * * #### Return * HS_AppRecover instance pointer * */ HS_AppRecover* HS_AppRecover::instance(void) { if(me == nullptr) me = new HS_AppRecover(); return me; } /** * HS_AppRecover initialize function * * #### Parameters * - api : the api serving the request * * #### Return * 0 : init success * 1 : init fail * */ int HS_AppRecover::init(afb_api_t api) { setEventHook("windowmanager/screenUpdated", on_screen_update_event); HS_WmProxy wm_proxy; wm_proxy.subscribe(api, HS_WmProxy::Event_ScreenUpdated); return 0; } /** * starting recover applications * * #### Parameters * - api : the api * - map : recover app map * * #### Return * None * */ void HS_AppRecover::startRecovery(afb_api_t api) { HS_ClientManager::instance()->addListener(this); for(auto &key : HS_Config::keys_recover_type) { for(auto &m : recover_app_map[key]){ struct app_recover_info recover_info = { .recover_type = key, .visibility = m.visibility, .after = m.after }; m_recover_apps_list[m.appid] = std::move(recover_info); // recover application auto it = m_recovering_set.find(m.appid); if(it == m_recovering_set.end()) { m_recovering_set.insert(m.appid); std::string &after = m_recover_apps_list[m.appid].after; if(!after.empty()) { auto w = m_wait_recover_set.find(m_recover_apps_list[m.appid].after); if(w != m_wait_recover_set.end()) { m_wait_recover_set[after].insert(m.appid); } else { std::set new_set; new_set.insert(m.appid); m_wait_recover_set[after] = std::move(new_set); } continue; // don't immediately start application, wait until after applicaiton started. } startApplication(api, m.appid); } } } recover_app_map.clear(); } /** * notify * * #### Parameters * - api : the api * - appid : application id * * #### Return * None * */ void HS_AppRecover::notify(afb_api_t api, std::string appid) { AFB_INFO("recover appid=[%s].", appid.c_str()); auto it = m_recovering_set.find(appid); if(it != m_recovering_set.end()) { this->removeListenAppId(appid); m_recovering_set.erase(appid); auto ip = m_recover_apps_list.find(appid); if(ip != m_recover_apps_list.end() && ip->second.visibility) { HS_ClientManager::instance()->pushEvent("showWindow", nullptr, appid); } } // check wait recover application auto w = m_wait_recover_set.find(appid); if(w != m_wait_recover_set.end()) { for(auto &ref : m_wait_recover_set[appid]) { startApplication(api, ref); } m_wait_recover_set.erase(appid); } if(m_recovering_set.empty()) { HS_ClientManager::instance()->removeListener(this); } } /** * screenUpdated event handler * * #### Parameters * - obj : screenUpdate object * * #### Return * None * */ void HS_AppRecover::screenUpdated(struct json_object *obj) { if(m_lastmode_list.empty()) { AFB_NOTICE("init lastmode is null, so don't record lastmode."); return; } std::set s_mode; struct json_object *ids_obj; if(json_object_object_get_ex(obj, key_ids.c_str(), &ids_obj)) { if(json_object_get_type(ids_obj) == json_type_array) { int array_len = json_object_array_length(ids_obj); for (int i = 0; i < array_len; ++i) { struct json_object *j_id = json_object_array_get_idx(ids_obj, i); std::string appid = json_object_get_string(j_id); if(!isHomescreenApp(appid)) { s_mode.insert(appid); } } if(!s_mode.empty()) { updateLastmode(s_mode); } } else { AFB_WARNING("screenUpdated list isn't array."); } } } /** * start application * * #### Parameters * - api : the api * - appid : application id liked "dashboard" * * #### Return * None * */ void HS_AppRecover::startApplication(afb_api_t api, const std::string &appid) { this->addListenAppId(appid); HS_AfmMainProxy afm_proxy; afm_proxy.start(api, HS_AppInfo::instance()->getAppProperty(appid, _keyId)); } /** * update lastmode file * * #### Parameters * - set : new lastmode set * * #### Return * None * */ void HS_AppRecover::updateLastmode(std::set &set) { if(set.size() == m_lastmode_list.size()) { bool is_same = true; for(auto &m : set) { auto it = m_lastmode_list.find(m); if(it == m_lastmode_list.end()) { is_same = false; break; } } if(is_same) { // lastmode aren't changed return; } } m_lastmode_list.swap(set); struct json_object *arr_obj = json_object_new_array(); for(auto &it : m_lastmode_list) { struct json_object *j_obj = json_object_new_object(); json_object_object_add(j_obj, HS_Config::key_appid.c_str(), json_object_new_string(it.c_str())); json_object_object_add(j_obj, HS_Config::key_visibility.c_str(), json_object_new_string("visible")); json_object_array_add(arr_obj, j_obj); } auto path = HS_Config::root_dir + "/etc/" + HS_Config::lastmode_json; if(writeJsonFile(path.c_str(), arr_obj) < 0) { AFB_ERROR("write lastmode error."); } } /** * judge whether app is Homescreen app * * #### Parameters * - appid : application id * * #### Return * true : homescreen app * false : not homescreen app * */ bool HS_AppRecover::isHomescreenApp(const std::string &appid) const { auto it = m_recover_apps_list.find(appid); if(it != m_recover_apps_list.end() && it->second.recover_type == HS_Config::keys_recover_type[0]) { return true; } return false; }