From: Sangyoon Jang Date: Mon, 12 Apr 2021 08:52:42 +0000 (+0900) Subject: Add esd-cion module X-Git-Tag: submit/gerrit/20210823.012340~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e9568556c624294baf61d01f8f954801cdf4decc;p=platform%2Fcore%2Fappfw%2Fevent-system.git Add esd-cion module Change-Id: I79a1a49a03073a2f9aa3cdc201d54e5fd1adb627 Signed-off-by: Sangyoon Jang --- diff --git a/include/eventsystem_daemon.h b/include/eventsystem_daemon.h index a5aaa8f..775426b 100644 --- a/include/eventsystem_daemon.h +++ b/include/eventsystem_daemon.h @@ -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 index 0000000..48447e0 --- /dev/null +++ b/src/esd_cion.c @@ -0,0 +1,316 @@ +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/src/esd_main.c b/src/esd_main.c index 42409f4..61f64ea 100644 --- a/src/esd_main.c +++ b/src/esd_main.c @@ -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);