aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwang_zhiqiang <wang_zhiqiang@dl.cn.nexty-ele.com>2019-02-20 13:52:59 +0800
committerwang_zhiqiang <wang_zhiqiang@dl.cn.nexty-ele.com>2019-03-25 19:42:35 +0800
commit211769e800f3a57de55b3774de82af55d2a0160a (patch)
tree07325ab1aeacb9a0c349e1927812e8080ff8744c
parent25299ef60fa4df5f590ff364cff004e90376a4bf (diff)
Start app and get runnables list by homescreen
1.start application in showWindow. 2.add "getRunnables" verb. 3.handle "application-list-changed" event from afm-main and add "application-list-changed" event. Bug-AGL: SPEC-2188 Change-Id: I619b97424d20af373a945ff502a8133339916923 Signed-off-by: wang_zhiqiang <wang_zhiqiang@dl.cn.nexty-ele.com>
-rw-r--r--package/root/config.xml7
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/homescreen.cpp115
-rw-r--r--src/hs-appinfo.cpp492
-rw-r--r--src/hs-appinfo.h89
-rw-r--r--src/hs-client.cpp28
-rw-r--r--src/hs-client.h1
-rw-r--r--src/hs-clientmanager.cpp38
-rw-r--r--src/hs-clientmanager.h1
-rw-r--r--src/hs-helper.cpp1
-rw-r--r--src/hs-helper.h3
-rw-r--r--src/hs-proxy.cpp135
-rw-r--r--src/hs-proxy.h34
13 files changed, 931 insertions, 17 deletions
diff --git a/package/root/config.xml b/package/root/config.xml
index 6ada42b..65c5d24 100644
--- a/package/root/config.xml
+++ b/package/root/config.xml
@@ -10,10 +10,17 @@
<param name="urn:AGL:permission::public:hidden" value="required" />
<param name="urn:AGL:permission::system:run-by-default" value="required" />
<param name="http://tizen.org/privilege/internal/dbus" value="required" />
+ <param name="urn:AGL:permission:afm:system:widget" value="required" />
+ <param name="urn:AGL:permission:afm:system:runner" value="required" />
+ <param name="urn:AGL:permission:afm:system:widget:start" value="required" />
</feature>
<feature name="urn:AGL:widget:provided-api">
<param name="homescreen" value="ws" />
</feature>
+ <feature name="urn:AGL:widget:required-api">
+ <param name="afm-main" value="ws" />
+ <param name="windowmanager" value="ws" />
+ </feature>
<feature name="urn:AGL:widget:required-binding">
<param name="lib/homescreen-service.so" value="local" />
</feature>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3687345..98dc27c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -26,7 +26,9 @@ set(binding_hs_sources
homescreen.cpp
hs-helper.cpp
hs-clientmanager.cpp
- hs-client.cpp)
+ hs-client.cpp
+ hs-proxy.cpp
+ hs-appinfo.cpp)
link_libraries(-Wl,--as-needed -Wl,--gc-sections -Wl,--no-undefined)
include_directories(${PROJECT_SOURCE_DIR}/include)
diff --git a/src/homescreen.cpp b/src/homescreen.cpp
index e921feb..10cc9bc 100644
--- a/src/homescreen.cpp
+++ b/src/homescreen.cpp
@@ -22,14 +22,53 @@
#include "hs-helper.h"
#include "hmi-debug.h"
#include "hs-clientmanager.h"
+#include "hs-appinfo.h"
const char _error[] = "error";
const char _application_id[] = "application_id";
const char _display_message[] = "display_message";
const char _reply_message[] = "reply_message";
+const char _keyData[] = "data";
+const char _keyId[] = "id";
-static HS_ClientManager* g_client_manager = HS_ClientManager::instance();
+struct hs_instance {
+ HS_ClientManager *client_manager; // the connection session manager
+ HS_AppInfo *app_info; // application info
+
+ hs_instance() : client_manager(HS_ClientManager::instance()), app_info(HS_AppInfo::instance()) {}
+ int init(afb_api_t api);
+};
+
+/**
+ * init function
+ *
+ * #### Parameters
+ * - api : the api serving the request
+ *
+ * #### Return
+ * 0 : init success
+ * 1 : init fail
+ *
+ */
+int hs_instance::init(afb_api_t api)
+{
+ if(client_manager == nullptr) {
+ HMI_ERROR("homescreen-service","FATAL ERROR: client_manager is nullptr.");
+ return -1;
+ }
+ client_manager->init();
+
+ if(app_info == nullptr) {
+ HMI_ERROR("homescreen-service","FATAL ERROR: app_info is nullptr.");
+ return -1;
+ }
+ app_info->init(api);
+
+ return 0;
+}
+
+static struct hs_instance *g_hs_instance;
/*
********** Method of HomeScreen Service (API) **********
@@ -62,7 +101,13 @@ static void tap_shortcut (afb_req_t request)
const char* value = afb_req_value(request, _application_id);
if (value) {
HMI_NOTICE("homescreen-service","request appid = %s.", value);
- ret = g_client_manager->handleRequest(request, __FUNCTION__, value);
+ ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
+ if(ret == AFB_REQ_NOT_STARTED_APPLICATION) {
+ std::string id = g_hs_instance->app_info->getAppProperty(value, _keyId);
+ HS_AfmMainProxy afm_proxy;
+ afm_proxy.start(request, id);
+ ret = 0;
+ }
}
else {
ret = AFB_EVENT_BAD_REQUEST;
@@ -93,7 +138,7 @@ static void tap_shortcut (afb_req_t request)
static void on_screen_message (afb_req_t request)
{
HMI_NOTICE("homescreen-service","called.");
- int ret = g_client_manager->handleRequest(request, __FUNCTION__);
+ int ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__);
if (ret) {
afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
}
@@ -119,7 +164,7 @@ static void on_screen_message (afb_req_t request)
static void on_screen_reply (afb_req_t request)
{
HMI_NOTICE("homescreen-service","called.");
- int ret = g_client_manager->handleRequest(request, __FUNCTION__);
+ int ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__);
if (ret) {
afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
}
@@ -147,7 +192,7 @@ static void subscribe(afb_req_t request)
int ret = 0;
std::string req_appid = std::move(get_application_id(request));
if(!req_appid.empty()) {
- ret = g_client_manager->handleRequest(request, __FUNCTION__, req_appid.c_str());
+ ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, req_appid.c_str());
}
else {
ret = AFB_EVENT_BAD_REQUEST;
@@ -180,7 +225,7 @@ static void unsubscribe(afb_req_t request)
int ret = 0;
std::string req_appid = std::move(get_application_id(request));
if(!req_appid.empty()) {
- ret = g_client_manager->handleRequest(request, __FUNCTION__, req_appid.c_str());
+ ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, req_appid.c_str());
}
else {
ret = AFB_EVENT_BAD_REQUEST;
@@ -213,7 +258,13 @@ static void showWindow(afb_req_t request)
int ret = 0;
const char* value = afb_req_value(request, _application_id);
if (value) {
- ret = g_client_manager->handleRequest(request, __FUNCTION__, value);
+ ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
+ if(ret == AFB_REQ_NOT_STARTED_APPLICATION) {
+ std::string id = g_hs_instance->app_info->getAppProperty(value, _keyId);
+ HS_AfmMainProxy afm_proxy;
+ afm_proxy.start(request, id);
+ ret = 0;
+ }
}
else {
ret = AFB_EVENT_BAD_REQUEST;
@@ -246,7 +297,7 @@ static void hideWindow(afb_req_t request)
int ret = 0;
const char* value = afb_req_value(request, _application_id);
if (value) {
- ret = g_client_manager->handleRequest(request, __FUNCTION__, value);
+ ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
}
else {
ret = AFB_EVENT_BAD_REQUEST;
@@ -279,7 +330,7 @@ static void replyShowWindow(afb_req_t request)
int ret = 0;
const char* value = afb_req_value(request, _application_id);
if (value) {
- ret = g_client_manager->handleRequest(request, __FUNCTION__, value);
+ ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
}
else {
ret = AFB_EVENT_BAD_REQUEST;
@@ -311,7 +362,7 @@ static void replyShowWindow(afb_req_t request)
static void showNotification(afb_req_t request)
{
HMI_NOTICE("homescreen-service","called.");
- int ret = g_client_manager->handleRequest(request, __FUNCTION__, "homescreen");
+ int ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, "homescreen");
if (ret) {
afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
}
@@ -338,7 +389,7 @@ static void showNotification(afb_req_t request)
static void showInformation(afb_req_t request)
{
HMI_NOTICE("homescreen-service","called.");
- int ret = g_client_manager->handleRequest(request, __FUNCTION__, "homescreen");
+ int ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, "homescreen");
if (ret) {
afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
}
@@ -350,6 +401,29 @@ static void showInformation(afb_req_t request)
}
}
+/**
+ * get runnables list
+ *
+ * #### Parameters
+ * - request : the request
+ *
+ * #### Return
+ * None
+ *
+ */
+static void getRunnables(afb_req_t request)
+{
+ HMI_NOTICE("homescreen-service","called.");
+ struct json_object* j_runnable = json_object_new_array();
+ g_hs_instance->app_info->getRunnables(&j_runnable);
+
+ /*create response json object*/
+ struct json_object *res = json_object_new_object();
+ hs_add_object_to_json_object_func(res, __FUNCTION__, 2, _error, 0);
+ json_object_object_add(res, _keyData, j_runnable);
+ afb_req_success_f(request, res, "homescreen binder unsubscribe success.");
+}
+
/*
* array of the verbs exported to afb-daemon
*/
@@ -366,6 +440,7 @@ static const afb_verb_t verbs[]= {
{ .verb="unsubscribe", .callback=unsubscribe },
{ .verb="showNotification", .callback=showNotification },
{ .verb="showInformation", .callback=showInformation },
+ { .verb="getRunnables", .callback=getRunnables },
{NULL } /* marker for end of the array */
};
@@ -399,9 +474,20 @@ static int init(afb_api_t api)
{
HMI_NOTICE("homescreen-service","binding init");
- g_client_manager->init();
+ if(g_hs_instance != nullptr) {
+ HMI_WARNING("homescreen-service", "g_hs_instance isn't null.");
+ delete g_hs_instance->client_manager;
+ delete g_hs_instance->app_info;
+ delete g_hs_instance;
+ g_hs_instance = nullptr;
+ }
+ g_hs_instance = new hs_instance();
+ if(g_hs_instance == nullptr) {
+ HMI_ERROR("homescreen-service", "Fatal Error: new g_hs_instance failed.");
+ return -1;
+ }
- return 0;
+ return g_hs_instance->init(api);
}
/**
@@ -418,7 +504,8 @@ static int init(afb_api_t api)
*/
static void onevent(afb_api_t api, const char *event, struct json_object *object)
{
- HMI_NOTICE("homescreen-service","on_event %s", event);
+ HMI_NOTICE("homescreen-service","on_event %s", event);
+ g_hs_instance->app_info->onEvent(api, event, object);
}
const afb_binding_t afbBindingExport = {
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 <unistd.h>
+#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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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
diff --git a/src/hs-appinfo.h b/src/hs-appinfo.h
new file mode 100644
index 0000000..7747f52
--- /dev/null
+++ b/src/hs-appinfo.h
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#ifndef HOMESCREEN_APPINFO_H
+#define HOMESCREEN_APPINFO_H
+
+#include <string>
+#include <mutex>
+#include <memory>
+#include <vector>
+#include <functional>
+#include <unordered_map>
+#include "hs-helper.h"
+#include "hs-proxy.h"
+
+
+struct AppDetail {
+ std::string name;
+ std::string id;
+ std::string detail; // detail json_object string
+ bool periphery;
+
+ std::string getProperty(std::string key) const;
+};
+
+class HS_AppInfo {
+public:
+ HS_AppInfo() = default;
+ ~HS_AppInfo();
+ HS_AppInfo(HS_AppInfo const &) = delete;
+ HS_AppInfo &operator=(HS_AppInfo const &) = delete;
+ HS_AppInfo(HS_AppInfo &&) = delete;
+ HS_AppInfo &operator=(HS_AppInfo &&) = delete;
+
+ static HS_AppInfo* instance(void);
+ int init(afb_api_t api);
+ void onEvent(afb_api_t api, const char *event, struct json_object *object);
+
+ void getRunnables(struct json_object **object);
+ std::string getAppProperty(const std::string appid, std::string key) const;
+ std::string checkAppId(const std::string &appid);
+
+private:
+ void updateAppDetailList(afb_api_t api, struct json_object *object);
+ void createAppDetailList(struct json_object *object);
+ std::string parseAppDetail(struct json_object *object, AppDetail &info) const;
+ void addAppDetail(struct json_object *object);
+ void removeAppDetail(std::string appid);
+ struct json_object* retrieveRunnables(struct json_object *obj_runnables, std::string id);
+ void pushAppListChangedEvent(const char *oper, struct json_object *object);
+ std::string id2appid(const std::string &id) const;
+ bool isPeripheryApp(const char *appid) const;
+
+ // applications can't display on launcher
+ const std::vector<const char*> periphery_app_list {
+ "launcher",
+ "homescreen",
+ "onscreenapp",
+ "restriction"
+ };
+
+ typedef void (HS_AppInfo::*func_handler)(afb_api_t, struct json_object*);
+ const std::unordered_map<std::string, func_handler> concerned_event_list {
+ {"afm-main/application-list-changed", &HS_AppInfo::updateAppDetailList}
+ };
+
+private:
+ static HS_AppInfo* me;
+ HS_AfmMainProxy* afmmain = nullptr;
+ std::unordered_map<std::string, std::string> appid2name;
+ std::unordered_map<std::string, std::string> name2appid;
+ std::unordered_map<std::string, AppDetail> app_detail_list;
+ std::mutex mtx;
+};
+
+#endif // HOMESCREEN_APPINFO_H \ No newline at end of file
diff --git a/src/hs-client.cpp b/src/hs-client.cpp
index e0d4bf0..c927442 100644
--- a/src/hs-client.cpp
+++ b/src/hs-client.cpp
@@ -465,9 +465,35 @@ int HS_Client::handleRequest(afb_req_t request, const char *verb)
int ret = AFB_EVENT_BAD_REQUEST;
auto ip = func_list.find(std::string(verb));
- if(ip != func_list.end()) {
+ if(ip != func_list.end() && ip->second != nullptr) {
HMI_NOTICE("homescreen-service","[%s]verb found", verb);
ret = (this->*(ip->second))(request);
}
return ret;
+}
+
+/**
+ * push event
+ *
+ * #### Parameters
+ * - event : the event want to push
+ * - param : the parameter contents of event
+ *
+ * #### Return
+ * 0 : success
+ * others : fail
+ *
+ */
+int HS_Client::pushEvent(const char *event, struct json_object *param)
+{
+ if(!checkEvent(event))
+ return 0;
+
+ HMI_NOTICE("homescreen-service","called, event=%s.",event);
+ struct json_object* push_obj = json_object_new_object();
+ hs_add_object_to_json_object_str( push_obj, 4, _application_id, my_id.c_str(), _type, event);
+ if(param != nullptr)
+ json_object_object_add(push_obj, _parameter, param);
+ afb_event_push(my_event, push_obj);
+ return 0;
} \ No newline at end of file
diff --git a/src/hs-client.h b/src/hs-client.h
index ac4d004..cbf2f33 100644
--- a/src/hs-client.h
+++ b/src/hs-client.h
@@ -32,6 +32,7 @@ public:
~HS_Client();
int handleRequest(afb_req_t request, const char *verb);
+ int pushEvent(const char *event, struct json_object *param);
private:
int tap_shortcut(afb_req_t request);
diff --git a/src/hs-clientmanager.cpp b/src/hs-clientmanager.cpp
index 7d658e4..8735c2e 100644
--- a/src/hs-clientmanager.cpp
+++ b/src/hs-clientmanager.cpp
@@ -189,9 +189,45 @@ int HS_ClientManager::handleRequest(afb_req_t request, const char *verb, const c
}
else {
HMI_NOTICE("homescreen-service","not exist session");
- ret = AFB_EVENT_BAD_REQUEST;
+ ret = AFB_REQ_NOT_STARTED_APPLICATION;
}
}
}
return ret;
+}
+
+/**
+ * push event
+ *
+ * #### Parameters
+ * - event : the event want to push
+ * - param : the parameter contents of event
+ * - appid : the destination application's id
+ *
+ * #### Return
+ * 0 : success
+ * others : fail
+ *
+ */
+int HS_ClientManager::pushEvent(const char *event, struct json_object *param, std::string appid)
+{
+ if(event == nullptr) {
+ HMI_ERROR("homescreen-service","event name is null.");
+ return -1;
+ }
+
+ std::lock_guard<std::mutex> lock(this->mtx);
+ if(appid.empty()) { // broadcast event to clients who subscribed this event
+ for(auto m : client_list) {
+ m.second->pushEvent(event, param);
+ }
+ }
+ else { // push event to specific client
+ auto ip = client_list.find(appid);
+ if(ip != client_list.end()) {
+ ip->second->pushEvent(event, param);
+ }
+ }
+
+ return 0;
} \ No newline at end of file
diff --git a/src/hs-clientmanager.h b/src/hs-clientmanager.h
index d485ea8..efc36de 100644
--- a/src/hs-clientmanager.h
+++ b/src/hs-clientmanager.h
@@ -46,6 +46,7 @@ public:
static HS_ClientManager* instance(void);
int init(void);
int handleRequest(afb_req_t request, const char *verb, const char *appid = nullptr);
+ int pushEvent(const char *event, struct json_object *param, std::string appid = "");
void removeClientCtxt(void *data); // don't use, internal only
private:
diff --git a/src/hs-helper.cpp b/src/hs-helper.cpp
index d0f5713..50a3ae1 100644
--- a/src/hs-helper.cpp
+++ b/src/hs-helper.cpp
@@ -28,6 +28,7 @@ const char* evlist[] = {
"replyShowWindow",
"showNotification",
"showInformation",
+ "application-list-changed",
"reserved"
};
diff --git a/src/hs-helper.h b/src/hs-helper.h
index 95ecb66..cc6fb89 100644
--- a/src/hs-helper.h
+++ b/src/hs-helper.h
@@ -27,6 +27,7 @@
#define AFB_REQ_SHOWNOTIFICATION_ERROR 103
#define AFB_REQ_SHOWINFORMATION_ERROR 104
#define AFB_REQ_GETAPPLICATIONID_ERROR 105
+#define AFB_REQ_NOT_STARTED_APPLICATION 106
typedef enum REQ_ERROR
{
@@ -41,6 +42,8 @@ extern const char _error[];
extern const char _application_id[];
extern const char _display_message[];
extern const char _reply_message[];
+extern const char _keyData[];
+extern const char _keyId[];
REQ_ERROR get_value_uint16(const afb_req_t request, const char *source, uint16_t *out_id);
REQ_ERROR get_value_int16(const afb_req_t request, const char *source, int16_t *out_id);
diff --git a/src/hs-proxy.cpp b/src/hs-proxy.cpp
new file mode 100644
index 0000000..0f5e78c
--- /dev/null
+++ b/src/hs-proxy.cpp
@@ -0,0 +1,135 @@
+/*
+ * 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-proxy.h"
+#include "hmi-debug.h"
+
+const char _afm_main[] = "afm-main";
+
+
+/**
+ * the callback function
+ *
+ * #### Parameters
+ * - closure : the user defined closure pointer 'closure'
+ * - object : a JSON object returned (can be NULL)
+ * - error : a string not NULL in case of error but NULL on success
+ * - info : a string handling some info (can be NULL)
+ * - api : the api
+ *
+ * #### Return
+ * None
+ *
+ */
+static void api_callback(void *closure, struct json_object *object, const char *error, const char *info, afb_api_t api)
+{
+ HMI_DEBUG("homescreen-service","asynchronous call, error=%s, info=%s, object=%s.", error, info, json_object_get_string(object));
+}
+
+/**
+ * call api asynchronous
+ *
+ * #### Parameters
+ * - api : the api serving the request
+ * - service : the api name of service
+ * - verb : the verb of service
+ * - args : parameter
+ *
+ * #### Return
+ * None
+ *
+ */
+static void api_call(afb_api_t api, const char *service, const char *verb, struct json_object *args)
+{
+ HMI_DEBUG("homescreen-service","service=%s verb=%s, args=%s.", service, verb, json_object_get_string(args));
+ afb_api_call(api, service, verb, args, api_callback, nullptr);
+}
+
+/**
+ * call api synchronous
+ *
+ * #### Parameters
+ * - api : the api serving the request
+ * - service : the api name of service
+ * - verb : the verb of afm-main
+ * - args : parameter
+ * - object : return the details of application
+ *
+ * #### Return
+ * 0 : success
+ * 1 : fail
+ *
+ */
+static int api_call_sync(afb_api_t api, const char *service, const char *verb, struct json_object *args, struct json_object **object)
+{
+ char *error = nullptr, *info = nullptr;
+ int ret = afb_api_call_sync(api, service, verb, args, object, &error, &info);
+ HMI_DEBUG("homescreen-service","synchronous call, error=%s, info=%s.", error, info);
+ return ret;
+}
+
+/**
+ * get runnables application list
+ *
+ * #### Parameters
+ * - api : the api serving the request
+ * - object : return the details of appid
+ *
+ * #### Return
+ * 0 : success
+ * 1 : fail
+ *
+ */
+int HS_AfmMainProxy::runnables(afb_api_t api, struct json_object **object)
+{
+ return api_call_sync(api, _afm_main, __FUNCTION__, nullptr, object);
+}
+
+/**
+ * get details of application
+ *
+ * #### Parameters
+ * - api : the api serving the request
+ * - id : the id to get details,liked "dashboard@0.1"
+ * - object : return the details of application
+ *
+ * #### Return
+ * 0 : success
+ * 1 : fail
+ *
+ */
+int HS_AfmMainProxy::detail(afb_api_t api, const std::string &id, struct json_object **object)
+{
+ struct json_object *args = json_object_new_string(id.c_str());
+ return api_call_sync(api, _afm_main, __FUNCTION__, args, object);
+}
+
+/**
+ * start application
+ *
+ * #### Parameters
+ * - request : the request
+ * - id : the application id liked "dashboard@0.1"
+ *
+ * #### Return
+ * None
+ *
+ */
+void HS_AfmMainProxy::start(afb_req_t request, const std::string &id)
+{
+ struct json_object *args = json_object_new_string(id.c_str());
+ api_call(request->api, _afm_main, __FUNCTION__, args);
+} \ No newline at end of file
diff --git a/src/hs-proxy.h b/src/hs-proxy.h
new file mode 100644
index 0000000..8741e49
--- /dev/null
+++ b/src/hs-proxy.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef HOMESCREEN_PROXY_H
+#define HOMESCREEN_PROXY_H
+
+#include <string>
+#include <json-c/json.h>
+#include <functional>
+#include "hs-helper.h"
+
+struct HS_AfmMainProxy {
+ // synchronous call, call result in object
+ int runnables(afb_api_t api, struct json_object **object);
+ int detail(afb_api_t api, const std::string &id, struct json_object **object);
+
+ // asynchronous call, reply in callback function
+ void start(afb_req_t request, const std::string &id);
+};
+
+#endif // HOMESCREEN_PROXY_H \ No newline at end of file