2 * Copyright (c) 2019 TOYOTA MOTOR CORPORATION
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "hs-appinfo.h"
20 #include "hs-helper.h"
21 #include "hs-clientmanager.h"
25 const char _keyName[] = "name";
26 const char _keyVersion[] = "version";
27 const char _keyInstall[] = "install";
28 const char _keyUninstall[] = "uninstall";
29 const char _keyOperation[] = "operation";
30 const char _keyRunnables[] = "runnables";
31 const char _keyStart[] = "start";
32 const char _keyApplistChanged[] = "application-list-changed";
34 HS_AppInfo* HS_AppInfo::me = nullptr;
35 const std::unordered_map<std::string, HS_AppInfo::func_handler> HS_AppInfo::concerned_event_list {
36 {"afm-main/application-list-changed", &HS_AppInfo::updateAppDetailList}
44 * - api : the api serving the request
45 * - event : event name
46 * - object : event json object
49 * 0 : continue transfer
53 static int eventHandler(afb_api_t api, const char *event, struct json_object *object)
55 return HS_AppInfo::instance()->onEvent(api, event, object);
59 * get application property function
62 * - key : retrieve keyword
68 std::string AppDetail::getProperty(std::string key) const
70 struct json_object *j_obj;
71 struct json_object *j_detail = json_tokener_parse(this->detail.c_str());
72 if(json_object_object_get_ex(j_detail, key.c_str(), &j_obj) == 0) {
73 AFB_WARNING("can't find key=%s.", key.c_str());
76 return std::string(json_object_get_string(j_obj));
80 * HS_AppInfo destruction function
89 HS_AppInfo::~HS_AppInfo()
102 * HS_AppInfo instance pointer
105 HS_AppInfo* HS_AppInfo::instance(void)
108 me = new HS_AppInfo();
114 * HS_AppInfo initialize function
117 * - api : the api serving the request
124 int HS_AppInfo::init(afb_api_t api)
126 afmmain = new HS_AfmMainProxy();
127 if(afmmain == nullptr) {
128 AFB_ERROR("new HS_AfmMainProxy failed");
132 struct json_object* j_runnable = nullptr;
135 if(afmmain->runnables(api, &j_runnable) == 0) {
136 createAppDetailList(j_runnable);
137 json_object_put(j_runnable);
142 if(retry == RETRY_CNT) {
143 AFB_ERROR("get runnables list failed");
144 json_object_put(j_runnable);
147 AFB_DEBUG("retry to get runnables list %d", retry);
148 usleep(100000); // 100ms
151 for(auto &ref : concerned_event_list) {
152 setEventHook(ref.first.c_str(), eventHandler);
162 * - api : the api serving the request
163 * - event : event name
164 * - object : event json object
167 * 0 : continue transfer
170 int HS_AppInfo::onEvent(afb_api_t api, const char *event, struct json_object *object)
173 auto ip = concerned_event_list.find(std::string(event));
174 if(ip != concerned_event_list.end()) {
175 ret = (this->*(ip->second))(api, object);
181 * create application detail list function
184 * - object : the detail of all applications
190 void HS_AppInfo::createAppDetailList(struct json_object *object)
192 AFB_DEBUG("applist:%s", json_object_to_json_string(object));
194 if(json_object_get_type(object) == json_type_array) {
195 int array_len = json_object_array_length(object);
196 for (int i = 0; i < array_len; ++i) {
197 struct json_object *obj = json_object_array_get_idx(object, i);
202 AFB_ERROR("Apps information input error.");
207 * update application detail function
210 * - object : the detail of all applications
213 * 0 : continue transfer
217 int HS_AppInfo::updateAppDetailList(afb_api_t api, struct json_object *object)
219 AFB_DEBUG("update:%s", json_object_to_json_string(object));
220 if(json_object_get_type(object) != json_type_object) {
221 AFB_ERROR("input detail object error.");
225 struct json_object *obj_oper, *obj_data;
226 if(json_object_object_get_ex(object, _keyOperation, &obj_oper) == 0
227 || json_object_object_get_ex(object, _keyData, &obj_data) == 0) {
228 AFB_ERROR("can't find key=%s, %s.", _keyOperation, _keyData);
232 std::string id = json_object_get_string(obj_data);
233 std::string appid = id2appid(id);
234 if(isPeripheryApp(appid.c_str())) {
235 AFB_INFO( "install/uninstall application is periphery.");
239 std::string oper = json_object_get_string(obj_oper);
240 if(oper == _keyInstall) {
241 struct json_object* j_runnable = nullptr;
242 int ret = afmmain->runnables(api, &j_runnable);
244 struct json_object *j_found = retrieveRunnables(j_runnable, id);
245 if(j_found == nullptr) {
246 AFB_INFO( "installed application isn't runnables.");
247 json_object_put(j_runnable);
250 addAppDetail(json_object_get(j_found));
251 pushAppListChangedEvent(_keyInstall, j_found);
254 AFB_ERROR("get runnalbes failed.");
256 json_object_put(j_runnable);
258 else if(oper == _keyUninstall) {
259 std::string appid_checked = checkAppId(appid);
260 if(appid_checked.empty()) {
261 AFB_INFO("uninstalled application isn't in runnables list, appid=%s.", appid.c_str());
264 pushAppListChangedEvent(_keyUninstall, json_object_get(obj_data));
265 removeAppDetail(appid);
268 AFB_ERROR("operation error.");
274 * parse application detail function
277 * - object : [IN] the detail of application
278 * - info : [OUT] parsed application detail
281 * the appid of application liked "dashboard"
284 std::string HS_AppInfo::parseAppDetail(struct json_object *object, AppDetail &info) const
286 struct json_object *name, *id;
287 if(json_object_object_get_ex(object, _keyName, &name) == 0
288 || json_object_object_get_ex(object, _keyId, &id) == 0) {
289 AFB_ERROR("can't find key=%s, %s.", _keyName, _keyId);
290 return std::string();
292 std::string appid = id2appid(json_object_get_string(id));
293 bool periphery = isPeripheryApp(appid.c_str());
295 info = { json_object_get_string(name),
296 json_object_get_string(id),
297 json_object_to_json_string(object),
304 * add application detail to list function
307 * - object : application detail
313 void HS_AppInfo::addAppDetail(struct json_object *object)
316 std::string appid = parseAppDetail(object, info);
318 AFB_ERROR("application id error");
322 std::lock_guard<std::mutex> lock(this->mtx);
323 appid2name[appid] = info.name;
324 name2appid[info.name] = appid;
325 app_detail_list[appid] = std::move(info);
329 * remove application detail from list function
332 * - appid : application id
338 void HS_AppInfo::removeAppDetail(std::string appid)
340 std::lock_guard<std::mutex> lock(this->mtx);
341 auto it = app_detail_list.find(appid);
342 if(it != app_detail_list.end()) {
343 appid2name.erase(appid);
344 name2appid.erase(it->second.name);
345 app_detail_list.erase(it);
348 AFB_WARNING("erase application(%s) wasn't in applist.", appid.c_str());
353 * push app_list_changed event function
356 * - oper: install/uninstall
357 * - object: event data
363 void HS_AppInfo::pushAppListChangedEvent(const char *oper, struct json_object *object)
365 struct json_object *push_obj = json_object_new_object();
366 json_object_object_add(push_obj, _keyOperation, json_object_new_string(oper));
367 json_object_object_add(push_obj, _keyData, object);
369 HS_ClientManager::instance()->pushEvent(_keyApplistChanged, push_obj);
373 * retrieve runnables function
376 * - obj_runnables: runnables array
377 * - id: application id
380 * found application detail
383 struct json_object* HS_AppInfo::retrieveRunnables(struct json_object *obj_runnables, std::string id)
385 struct json_object *j_found = nullptr;
386 if(json_object_get_type(obj_runnables) == json_type_array) {
387 int array_len = json_object_array_length(obj_runnables);
388 for (int i = 0; i < array_len; ++i) {
389 struct json_object *obj = json_object_array_get_idx(obj_runnables, i);
390 struct json_object *j_id;
391 if(json_object_object_get_ex(obj, _keyId, &j_id) == 0) {
392 AFB_WARNING("can't find id.");
395 if(id == json_object_get_string(j_id)) {
402 AFB_ERROR("Apps information input error.");
408 * convert id to appid function
411 * - id : the id of application liked "dashboard@0.1"
414 * the appid of application liked "dashboard"
417 std::string HS_AppInfo::id2appid(const std::string &id) const
420 std::size_t pos = id.find("@");
421 appid = id.substr(0,pos);
429 * - object : runnables list,json array
435 void HS_AppInfo::getRunnables(struct json_object **object)
437 if(json_object_get_type(*object) != json_type_array) {
438 AFB_ERROR("json type error.");
442 std::lock_guard<std::mutex> lock(this->mtx);
443 for(auto it : app_detail_list) {
444 if(!it.second.periphery)
445 json_object_array_add(*object, json_tokener_parse(it.second.detail.c_str()));
450 * check appid function
453 * - appid : appid liked "dashboard"
456 * success : the correct appid
457 * fail : empty string
460 std::string HS_AppInfo::checkAppId(const std::string &appid)
462 std::lock_guard<std::mutex> lock(this->mtx);
463 auto it_appid = appid2name.find(appid);
464 if(it_appid != appid2name.end())
465 return it_appid->first;
467 auto it_name = name2appid.find(appid);
468 if(it_name != name2appid.end())
469 return it_name->second;
471 return std::string();
475 * check if application is a runnable periphery application function
478 * - appid : appid liked "launcher"
482 * false : not periphery
485 bool HS_AppInfo::isPeripheryApp(const char *appid) const
488 for(auto m : periphery_app_list) {
489 if(strcasecmp(appid, m) == 0) {
498 * get application specific property
501 * - appid : appid liked "launcher"
502 * - key : the keyword
505 * application property
508 std::string HS_AppInfo::getAppProperty(const std::string appid, std::string key) const
510 std::string value = "";
511 auto it = app_detail_list.find(appid);
512 if(it != app_detail_list.end()) {
513 value = it->second.getProperty(key);