Add esd-cion module 52/256752/12
authorSangyoon Jang <jeremy.jang@samsung.com>
Mon, 12 Apr 2021 08:52:42 +0000 (17:52 +0900)
committerSangyoon Jang <jeremy.jang@samsung.com>
Mon, 24 May 2021 08:01:01 +0000 (17:01 +0900)
Change-Id: I79a1a49a03073a2f9aa3cdc201d54e5fd1adb627
Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
include/eventsystem_daemon.h
src/esd_cion.c [new file with mode: 0644]
src/esd_main.c

index a5aaa8f..775426b 100644 (file)
@@ -49,10 +49,11 @@ extern "C" {
 #define SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED "UserSessionStartupFinished"
 
 int __esd_register_vconf_callbacks(void);
+int __esd_cion_init(void);
+void __esd_cion_finalize(void);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* __EVENTSYSTEM_DAEMONE_H__ */
-
diff --git a/src/esd_cion.c b/src/esd_cion.c
new file mode 100644 (file)
index 0000000..48447e0
--- /dev/null
@@ -0,0 +1,316 @@
+#include <dlog.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pkgmgr-info.h>
+#include <package-manager.h>
+
+#include "eventsystem_daemon.h"
+
+#define CION_METADATA_KEY "http://tizen.org/metadata/cion"
+
+static uid_t cur_uid;
+static pkgmgr_client *pkgmgr;
+static GList *service_list;
+
+struct cion_service {
+       char *pkgid;
+       char *appid;
+       char *service_name;
+       char *uuid;
+       int port;
+};
+
+static void __free_cion_service(gpointer data)
+{
+       struct cion_service *service = (struct cion_service *)data;
+
+       free(service->pkgid);
+       free(service->appid);
+       free(service->service_name);
+       free(service->uuid);
+       free(service);
+}
+
+static int __esd_cion_set_cur_uid(void)
+{
+       /* TODO(jeremy.jang): get current user from gumd or systemd */
+       cur_uid = 5001;
+       return 0;
+}
+
+static int __esd_cion_foreach_metadata_callback(const char *key,
+               const char *val, void *user_data)
+{
+       struct cion_service *service;
+       GList **service_list = (GList **)user_data;
+
+       if (strncmp(key, CION_METADATA_KEY, strlen(CION_METADATA_KEY)) != 0)
+               return 0;
+
+       if (val == NULL || strlen(val) == 0) {
+               _E("Service name is mandatory");
+               return 0;
+       }
+
+       service = calloc(1, sizeof(struct cion_service));
+       if (service == NULL) {
+               _E("Out of memory");
+               return -1;
+       }
+
+       service->service_name = strdup(val);
+       if (service->service_name == NULL) {
+               _E("Out of memory");
+               return -1;
+       }
+
+       *service_list = g_list_append(*service_list, (gpointer)service);
+
+       return 0;
+}
+
+static void __esd_cion_remove_cion_service_by_appid(const char *appid)
+{
+       GList *item;
+       GList *next;
+       struct cion_service *service;
+
+       item = service_list;
+       while (item != NULL) {
+               next = item->next;
+               service = (struct cion_service *)item->data;
+               if (strcmp(service->appid, appid) == 0) {
+                       _D("Remove a cion service [%s:%s:%s:%d]",
+                                       service->appid, service->service_name,
+                                       service->uuid, service->port);
+                       __free_cion_service(service);
+                       service_list = g_list_delete_link(service_list, item);
+               }
+               item = next;
+       }
+}
+
+static void __esd_cion_remove_cion_service_by_pkgid(const char *pkgid)
+{
+       GList *item;
+       GList *next;
+       struct cion_service *service;
+
+       item = service_list;
+       while (item != NULL) {
+               next = item->next;
+               service = (struct cion_service *)item->data;
+               if (strcmp(service->pkgid, pkgid) == 0) {
+                       _D("Remove a cion service [%s:%s:%s:%d]",
+                                       service->appid, service->service_name,
+                                       service->uuid, service->port);
+                       __free_cion_service(service);
+                       service_list = g_list_delete_link(service_list, item);
+               }
+               item = next;
+       }
+}
+
+static int __esd_cion_add_cion_service(struct cion_service *service,
+               const char *pkgid, const char *appid)
+{
+       /* service name already set by __esd_cion_foreach_metadata_callback() */
+       service->pkgid = strdup(pkgid);
+       if (service->pkgid == NULL) {
+               _E("Out of memory");
+               return -1;
+       }
+
+       service->appid = strdup(appid);
+       if (service->appid == NULL) {
+               _E("Out of memory");
+               return -1;
+       }
+
+       /* how to get uuid? */
+
+       service_list = g_list_append(service_list, service);
+       _D("Add a cion service [%s:%s:%s:%d]", service->appid,
+                       service->service_name, service->uuid,
+                       service->port);
+
+       return 0;
+}
+
+static int __esd_cion_foreach_app_callback(const pkgmgrinfo_appinfo_h appinfo,
+               void *user_data)
+{
+       int ret;
+       char *pkgid;
+       char *appid;
+       struct cion_service *service;
+       GList *item;
+       GList *list = NULL;
+
+       ret = pkgmgrinfo_appinfo_foreach_metadata(appinfo,
+                       __esd_cion_foreach_metadata_callback, &list);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get metadata: %d", ret);
+               return -1;
+       }
+
+       ret = pkgmgrinfo_appinfo_get_pkgid(appinfo, &pkgid);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get pkgid: %d", ret);
+               return -1;
+       }
+
+       ret = pkgmgrinfo_appinfo_get_appid(appinfo, &appid);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get appid: %d", ret);
+               return -1;
+       }
+
+       /* remove first, the updated app may no longer provide cion service */
+       __esd_cion_remove_cion_service_by_appid(appid);
+       for (item = list; item; item = item->next) {
+               service = (struct cion_service *)item->data;
+               if (__esd_cion_add_cion_service(service, pkgid, appid)) {
+                       _E("Failed to add a cion service");
+                       __free_cion_service(service);
+               }
+               /* remove reference, the global 'service_list' takes reference
+                * of 'service'.
+                */
+               item->data = NULL;
+       }
+
+       g_list_free(list);
+
+       return 0;
+}
+
+static int __esd_cion_pkgmgr_event_callback(uid_t target_uid, int req_id,
+               const char *pkg_type, const char *pkgid, const char *key,
+               const char *val, const void *pmsg, void *data)
+{
+       int ret;
+       pkgmgrinfo_pkginfo_h pkginfo;
+
+       if (strncmp(key, "end", strlen("end")) ||
+                       strncmp(val, "ok", strlen("ok")))
+               return 0;
+
+       ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, target_uid, &pkginfo);
+       if (ret == PMINFO_R_OK) {
+               /* install or update */
+               ret = pkgmgrinfo_appinfo_get_usr_list(pkginfo, PMINFO_ALL_APP,
+                               __esd_cion_foreach_app_callback, NULL,
+                               target_uid);
+               if (ret != PMINFO_R_OK) {
+                       _E("Failed to get appinfo of pkgid %s: %d", pkgid, ret);
+                       pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+                       return 0;
+               }
+               pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+       } else if (ret == PMINFO_R_ENOENT) {
+               /* uninstall */
+               __esd_cion_remove_cion_service_by_pkgid(pkgid);
+       } else {
+               _E("Failed to get pkginfo of %s: %d", pkgid, ret);
+       }
+
+       return 0;
+}
+
+static int __esd_cion_set_pkgmgr_callback(void)
+{
+       int ret;
+
+       pkgmgr = pkgmgr_client_new(PC_LISTENING);
+       if (pkgmgr == NULL) {
+               _E("Failed to create pkgmgr client");
+               return -1;
+       }
+
+       ret = pkgmgr_client_set_status_type(pkgmgr,
+                       PKGMGR_CLIENT_STATUS_INSTALL |
+                       PKGMGR_CLIENT_STATUS_UPGRADE |
+                       PKGMGR_CLIENT_STATUS_UNINSTALL);
+       if (ret != PKGMGR_R_OK) {
+               _E("Failed to set pkgmgr event status type: %d", ret);
+               pkgmgr_client_free(pkgmgr);
+               pkgmgr = NULL;
+               return -1;
+       }
+
+       ret = pkgmgr_client_listen_status(pkgmgr,
+                       __esd_cion_pkgmgr_event_callback, NULL);
+       if (ret < 0) {
+               _E("Failed to set event callback: %d", ret);
+               pkgmgr_client_free(pkgmgr);
+               pkgmgr = NULL;
+               return -1;
+       }
+
+       return 0;
+}
+
+static int __esd_cion_load_services(uid_t uid)
+{
+       int ret;
+       pkgmgrinfo_appinfo_metadata_filter_h filter;
+
+       ret = pkgmgrinfo_appinfo_metadata_filter_create(&filter);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to create metadata filter: %d", ret);
+               return -1;
+       }
+
+       ret = pkgmgrinfo_appinfo_metadata_filter_add(filter,
+                       CION_METADATA_KEY, "");
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to add keyval to metadata filter: %d", ret);
+               pkgmgrinfo_appinfo_metadata_filter_destroy(filter);
+               return -1;
+       }
+
+       ret = pkgmgrinfo_appinfo_usr_metadata_filter_foreach(filter,
+                       __esd_cion_foreach_app_callback, NULL, uid);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to metadata filter foreach: %d", ret);
+               pkgmgrinfo_appinfo_metadata_filter_destroy(filter);
+               return -1;
+       }
+
+       pkgmgrinfo_appinfo_metadata_filter_destroy(filter);
+
+       return 0;
+}
+
+int __esd_cion_init(void)
+{
+       if (__esd_cion_set_cur_uid()) {
+               _E("Failed to set current uid");
+               return -1;
+       }
+
+       /* how to handle when user switched? */
+       if (__esd_cion_load_services(cur_uid)) {
+               _E("Failed to load cion services");
+               return -1;
+       }
+
+       if (__esd_cion_set_pkgmgr_callback()) {
+               _E("Failed to set pkgmgr event callback");
+               return -1;
+       }
+
+       return 0;
+}
+
+void __esd_cion_finalize(void)
+{
+       if (pkgmgr) {
+               pkgmgr_client_remove_listen_status(pkgmgr);
+               pkgmgr_client_free(pkgmgr);
+       }
+
+       g_list_free_full(service_list, __free_cion_service);
+}
index 42409f4..61f64ea 100644 (file)
@@ -2404,6 +2404,12 @@ int main(int argc, char *argv[])
                return ES_R_ERROR;
        }
 
+       if (__esd_cion_init() != 0) {
+               _E("ESD Cion Initialization failed!");
+               g_main_loop_unref(mainloop);
+               return ES_R_ERROR;
+       }
+
        if (__esd_before_loop() < 0) {
                _E("ESD failed!");
                __esd_finalize();
@@ -2415,6 +2421,7 @@ int main(int argc, char *argv[])
 
        _E("shutdown");
 
+       __esd_cion_finalize();
        __esd_finalize();
 
        g_main_loop_unref(mainloop);