X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fhs-appinfo.cpp;fp=src%2Fhs-appinfo.cpp;h=e1c1990a082e16b2f24adc35876fb09d7f87c270;hb=211769e800f3a57de55b3774de82af55d2a0160a;hp=0000000000000000000000000000000000000000;hpb=25299ef60fa4df5f590ff364cff004e90376a4bf;p=apps%2Fagl-service-homescreen.git diff --git a/src/hs-appinfo.cpp b/src/hs-appinfo.cpp new file mode 100644 index 0000000..e1c1990 --- /dev/null +++ b/src/hs-appinfo.cpp @@ -0,0 +1,492 @@ +/* + * 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 +#include "hs-appinfo.h" +#include "hmi-debug.h" +#include "hs-clientmanager.h" + +#define RETRY_CNT 10 + +const char _keyName[] = "name"; +const char _keyVersion[] = "version"; +const char _keyInstall[] = "install"; +const char _keyUninstall[] = "uninstall"; +const char _keyOperation[] = "operation"; +const char _keyRunnables[] = "runnables"; +const char _keyStart[] = "start"; +const char _keyApplistChanged[] = "application-list-changed"; + +HS_AppInfo* HS_AppInfo::me = nullptr; + +/** + * get application property function + * + * #### Parameters + * - key : retrieve keyword + * + * #### Return + * retrieved property + * + */ +std::string AppDetail::getProperty(std::string key) const +{ + struct json_object *j_obj; + struct json_object *j_detail = json_tokener_parse(this->detail.c_str()); + if(json_object_object_get_ex(j_detail, key.c_str(), &j_obj) == 0) { + HMI_ERROR("homescreen-service","can't find key=%s.", key.c_str()); + return std::string(); + } + return std::string(json_object_get_string(j_obj)); +} + +/** + * HS_AppInfo destruction function + * + * #### Parameters + * - Nothing + * + * #### Return + * None + * + */ +HS_AppInfo::~HS_AppInfo() +{ + if(afmmain) + delete afmmain; +} + +/** + * get instance + * + * #### Parameters + * - Nothing + * + * #### Return + * HS_AppInfo instance pointer + * + */ +HS_AppInfo* HS_AppInfo::instance(void) +{ + if(me == nullptr) + me = new HS_AppInfo(); + + return me; +} + +/** + * HS_AppInfo initialize function + * + * #### Parameters + * - api : the api serving the request + * + * #### Return + * 0 : init success + * 1 : init fail + * + */ +int HS_AppInfo::init(afb_api_t api) +{ + afmmain = new HS_AfmMainProxy(); + if(afmmain == nullptr) { + HMI_ERROR("homescreen-service","Fatal Error:new HS_AfmMainProxy failed"); + return -1; + } + + struct json_object* j_runnable = nullptr; + int retry = 0; + do { + if(afmmain->runnables(api, &j_runnable) == 0) { + createAppDetailList(j_runnable); + json_object_put(j_runnable); + break; + } + + ++retry; + if(retry == RETRY_CNT) { + HMI_ERROR("homescreen-service","get runnables list failed"); + json_object_put(j_runnable); + return -1; + } + HMI_NOTICE("homescreen-service","retry to get runnables list %d", retry); + usleep(100000); // 100ms + } while(1); + + return 0; +} + +/** + * onEvent function + * + * #### Parameters + * - api : the api serving the request + * - event : event name + * - object : event json object + * + * #### Return + * None + * + */ +void HS_AppInfo::onEvent(afb_api_t api, const char *event, struct json_object *object) +{ + auto ip = concerned_event_list.find(std::string(event)); + if(ip != concerned_event_list.end()) { + HMI_NOTICE("homescreen-service","[%s] event received.", event); + (this->*(ip->second))(api, object); + } +} + +/** + * create application detail list function + * + * #### Parameters + * - object : the detail of all applications + * + * #### Return + * None + * + */ +void HS_AppInfo::createAppDetailList(struct json_object *object) +{ + HMI_NOTICE("homescreen-service","applist:%s", json_object_to_json_string(object)); + + if(json_object_get_type(object) == json_type_array) { + int array_len = json_object_array_length(object); + for (int i = 0; i < array_len; ++i) { + struct json_object *obj = json_object_array_get_idx(object, i); + addAppDetail(obj); + } + } + else { + HMI_ERROR("homescreen-service","Apps information input error."); + } +} + +/** + * update application detail function + * + * #### Parameters + * - object : the detail of all applications + * + * #### Return + * None + * + */ +void HS_AppInfo::updateAppDetailList(afb_api_t api, struct json_object *object) +{ + HMI_NOTICE("homescreen-service","update:%s", json_object_to_json_string(object)); + if(json_object_get_type(object) != json_type_object) { + HMI_ERROR("homescreen-service","input detail object error."); + return; + } + + struct json_object *obj_oper, *obj_data; + if(json_object_object_get_ex(object, _keyOperation, &obj_oper) == 0 + || json_object_object_get_ex(object, _keyData, &obj_data) == 0) { + HMI_ERROR("homescreen-service","can't find key=%s, %s.", _keyOperation, _keyData); + return; + } + + std::string id = json_object_get_string(obj_data); + std::string appid = id2appid(id); + if(isPeripheryApp(appid.c_str())) { + HMI_NOTICE("homescreen-service", "install/uninstall application is periphery."); + return; + } + + std::string oper = json_object_get_string(obj_oper); + if(oper == _keyInstall) { + struct json_object* j_runnable = nullptr; + int ret = afmmain->runnables(api, &j_runnable); + if(!ret) { + struct json_object *j_found = retrieveRunnables(j_runnable, id); + if(j_found == nullptr) { + HMI_NOTICE("homescreen-service", "installed application isn't runnables."); + json_object_put(j_runnable); + return; + } + addAppDetail(j_found); + pushAppListChangedEvent(_keyInstall, j_found); + } + else { + HMI_ERROR("homescreen-service","get runnalbes failed."); + } + json_object_put(j_runnable); + } + else if(oper == _keyUninstall) { + std::string appid_checked = checkAppId(appid); + if(appid_checked.empty()) { + HMI_NOTICE("homescreen-service","uninstalled application isn't in runnables list, appid=%s.", appid.c_str()); + return; + } + pushAppListChangedEvent(_keyUninstall, obj_data); + removeAppDetail(appid); + } + else { + HMI_ERROR("homescreen-service","operation error."); + } +} + +/** + * parse application detail function + * + * #### Parameters + * - object : [IN] the detail of application + * - info : [OUT] parsed application detail + * + * #### Return + * the appid of application liked "dashboard" + * + */ +std::string HS_AppInfo::parseAppDetail(struct json_object *object, AppDetail &info) const +{ + struct json_object *name, *id; + if(json_object_object_get_ex(object, _keyName, &name) == 0 + || json_object_object_get_ex(object, _keyId, &id) == 0) { + HMI_ERROR("homescreen-service","can't find key=%s, %s.", _keyName, _keyId); + return std::string(); + } + std::string appid = id2appid(json_object_get_string(id)); + bool periphery = isPeripheryApp(appid.c_str()); + + info = { json_object_get_string(name), + json_object_get_string(id), + json_object_to_json_string(object), + periphery + }; + return appid; +} + +/** + * add application detail to list function + * + * #### Parameters + * - object : application detail + * + * #### Return + * None + * + */ +void HS_AppInfo::addAppDetail(struct json_object *object) +{ + AppDetail info; + std::string appid = parseAppDetail(object, info); + if(appid.empty()) { + HMI_ERROR("homescreen-service","application id error"); + return; + } + + std::lock_guard lock(this->mtx); + appid2name[appid] = info.name; + name2appid[info.name] = appid; + app_detail_list[appid] = std::move(info); +} + +/** + * remove application detail from list function + * + * #### Parameters + * - appid : application id + * + * #### Return + * None + * + */ +void HS_AppInfo::removeAppDetail(std::string appid) +{ + std::lock_guard lock(this->mtx); + auto it = app_detail_list.find(appid); + if(it != app_detail_list.end()) { + appid2name.erase(appid); + name2appid.erase(it->second.name); + app_detail_list.erase(it); + } + else { + HMI_WARNING("homescreen-service","erase application(%s) wasn't in applist.", appid.c_str()); + } +} + +/** + * push app_list_changed event function + * + * #### Parameters + * - oper: install/uninstall + * - object: event data + * + * #### Return + * None + * + */ +void HS_AppInfo::pushAppListChangedEvent(const char *oper, struct json_object *object) +{ + HMI_NOTICE("homescreen-service","called."); + struct json_object *push_obj = json_object_new_object(); + json_object_object_add(push_obj, _keyOperation, json_object_new_string(oper)); + json_object_object_add(push_obj, _keyData, object); + + HS_ClientManager::instance()->pushEvent(_keyApplistChanged, push_obj); +} + +/** + * retrieve runnables function + * + * #### Parameters + * - obj_runnables: runnables array + * - id: application id + * + * #### Return + * found application detail + * + */ +struct json_object* HS_AppInfo::retrieveRunnables(struct json_object *obj_runnables, std::string id) +{ + struct json_object *j_found = nullptr; + if(json_object_get_type(obj_runnables) == json_type_array) { + int array_len = json_object_array_length(obj_runnables); + for (int i = 0; i < array_len; ++i) { + struct json_object *obj = json_object_array_get_idx(obj_runnables, i); + struct json_object *j_id; + if(json_object_object_get_ex(obj, _keyId, &j_id) == 0) { + HMI_WARNING("homescreen-service","can't find id."); + continue; + } + if(id == json_object_get_string(j_id)) { + j_found = obj; + break; + } + } + } + else { + HMI_ERROR("homescreen-service","Apps information input error."); + } + return j_found; +} + +/** + * convert id to appid function + * + * #### Parameters + * - id : the id of application liked "dashboard@0.1" + * + * #### Return + * the appid of application liked "dashboard" + * + */ +std::string HS_AppInfo::id2appid(const std::string &id) const +{ + std::string appid; + std::size_t pos = id.find("@"); + if(pos != std::string::npos) { + appid = id.substr(0,pos); + } + else { + HMI_ERROR("homescreen-service","input id error."); + } + return appid; +} + +/** + * get runnables list + * + * #### Parameters + * - object : runnables list,json array + * + * #### Return + * None + * + */ +void HS_AppInfo::getRunnables(struct json_object **object) +{ + if(json_object_get_type(*object) != json_type_array) { + HMI_ERROR("homescreen-service","json type error."); + return; + } + + std::lock_guard lock(this->mtx); + for(auto it : app_detail_list) { + if(!it.second.periphery) + json_object_array_add(*object, json_tokener_parse(it.second.detail.c_str())); + } +} + +/** + * check appid function + * + * #### Parameters + * - appid : appid liked "dashboard" + * + * #### Return + * success : the correct appid + * fail : empty string + * + */ +std::string HS_AppInfo::checkAppId(const std::string &appid) +{ + std::lock_guard lock(this->mtx); + auto it_appid = appid2name.find(appid); + if(it_appid != appid2name.end()) + return it_appid->first; + + auto it_name = name2appid.find(appid); + if(it_name != name2appid.end()) + return it_name->second; + + return std::string(); +} + +/** + * check if application is a runnable periphery application function + * + * #### Parameters + * - appid : appid liked "launcher" + * + * #### Return + * true : periphery + * false : not periphery + * + */ +bool HS_AppInfo::isPeripheryApp(const char *appid) const +{ + bool ret = false; + for(auto m : periphery_app_list) { + if(strcasecmp(appid, m) == 0) { + ret = true; + break; + } + } + return ret; +} + +/** + * get application specific property + * + * #### Parameters + * - appid : appid liked "launcher" + * - key : the keyword + * + * #### Return + * application property + * + */ +std::string HS_AppInfo::getAppProperty(const std::string appid, std::string key) const +{ + std::string value = ""; + auto it = app_detail_list.find(appid); + if(it != app_detail_list.end()) { + value = it->second.getProperty(key); + } + return value; +} \ No newline at end of file