From f345f214eb2a04895dd91479e89c69a440ca7592 Mon Sep 17 00:00:00 2001 From: Jusung Son Date: Fri, 7 Feb 2020 09:10:57 +0900 Subject: [PATCH] Add app-defined loader Requires: - https://review.tizen.org/gerrit/#/c/platform/core/appfw/aul-1/+/224466/ - https://review.tizen.org/gerrit/#/c/platform/core/appfw/amd/+/224634/ - https://review.tizen.org/gerrit/#/c/platform/core/api/app-control/+/224798/ - https://review.tizen.org/gerrit/#/c/platform/core/appfw/launchpad/+/224161/ Change-Id: I66ea0abec98fd387e91cf67a7f5db94e5d0234d0 Signed-off-by: Jusung Son --- CMakeLists.txt | 1 + inc/launchpad_common.h | 1 + inc/launchpad_inotify.h | 34 +++++++++ inc/loader_info.h | 6 +- inc/preexec.h | 0 src/launchpad.c | 152 +++++++++++++++++++++++++++++++++++++- src/launchpad_inotify.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ src/loader_info.c | 55 +++++++++++++- 8 files changed, 437 insertions(+), 3 deletions(-) mode change 100755 => 100644 CMakeLists.txt create mode 100644 inc/launchpad_inotify.h mode change 100755 => 100644 inc/preexec.h mode change 100755 => 100644 src/launchpad.c create mode 100644 src/launchpad_inotify.c diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100755 new mode 100644 index 20d8f0f..6197582 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,6 +147,7 @@ SET(${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES src/launchpad_signal.c src/launchpad_config.c src/launchpad_io_channel.c + src/launchpad_inotify.c ) ADD_EXECUTABLE(${LAUNCHPAD_PROCESS_POOL} ${${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES}) diff --git a/inc/launchpad_common.h b/inc/launchpad_common.h index c5859e2..dc60559 100644 --- a/inc/launchpad_common.h +++ b/inc/launchpad_common.h @@ -46,6 +46,7 @@ #define PAD_CMD_DEMAND 14 #define PAD_CMD_PING 15 #define PAD_CMD_UPDATE_APP_TYPE 16 +#define PAD_CMD_PREPARE_APP_DEFINED_LOADER 17 #define LAUNCHPAD_LAUNCH_SIGNAL 83 #define LAUNCHPAD_DEAD_SIGNAL 61 diff --git a/inc/launchpad_inotify.h b/inc/launchpad_inotify.h new file mode 100644 index 0000000..4db903e --- /dev/null +++ b/inc/launchpad_inotify.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#pragma once + +#include +#include + +typedef struct inotify_watch_info_s *inotify_watch_info_h; + +typedef bool (*inotify_watch_cb)(const char *event_name, uint32_t mask, + void *data); + +int _inotify_add_watch(const char *path, uint32_t mask, + inotify_watch_cb callback, void *data); + +void _inotify_rm_watch(inotify_watch_info_h handle); + +int _inotify_init(void); + +void _inotify_fini(void); diff --git a/inc/loader_info.h b/inc/loader_info.h index 8714198..2e703b5 100644 --- a/inc/loader_info.h +++ b/inc/loader_info.h @@ -57,10 +57,14 @@ typedef struct _loader_info { typedef void (*loader_info_foreach_cb)(loader_info_t *info, void *data); -GList *_loader_info_load(const char *path); +GList *_loader_info_load_dir(const char *path); +GList *_loader_info_load_file(GList *list, const char *path); +GList *_loader_info_unload(GList *list, const char *loader_name); void _loader_info_dispose(GList *info); int _loader_info_find_type(GList *info, const char *app_type, bool hwacc); int _loader_info_find_type_by_loader_name(GList *info, const char *loader_name); +const char* _loader_info_find_loader_path_by_loader_name(GList *info, const char *loader_name); +const loader_info_t* _loader_info_find_loader_by_loader_name(GList *info, const char *loader_name); int *_loader_get_alternative_types(GList *info, int type, int *len); int _loader_info_foreach(GList *info, loader_info_foreach_cb callback, void *data); diff --git a/inc/preexec.h b/inc/preexec.h old mode 100755 new mode 100644 diff --git a/src/launchpad.c b/src/launchpad.c old mode 100755 new mode 100644 index ecd3f61..af409f5 --- a/src/launchpad.c +++ b/src/launchpad.c @@ -49,6 +49,7 @@ #include "launchpad_types.h" #include "loader_info.h" #include "perf.h" +#include "launchpad_inotify.h" #define AUL_PR_NAME 16 #define EXEC_CANDIDATE_EXPIRED 5 @@ -60,6 +61,11 @@ #define LAUNCHPAD_LOGGER_SOCK ".launchpad-logger-sock" #define LOADER_PATH_DEFAULT "/usr/bin/launchpad-loader" #define LOADER_INFO_PATH "/usr/share/aul" +#define OPT_SHARE_PATH "/opt/share" +#define LOADERS_PATH "loaders" +#define APP_DEFINED_LOADER_INFO_PATH OPT_SHARE_PATH "/" LOADERS_PATH +#define COMMON_LOADER_NAME "common-loader1" + #define LAUNCHER_INFO_PATH LOADER_INFO_PATH #define REGULAR_UID_MIN 5000 #define PAD_ERR_FAILED -1 @@ -142,6 +148,7 @@ struct app_info { static int __sys_hwacc; static GList *loader_info_list; +static GList *app_defined_loader_info_list; static int user_slot_offset; static GList *candidate_slot_list; static app_labels_monitor *label_monitor; @@ -171,6 +178,7 @@ static int __add_idle_checker(int detection_method, GList *cur); static void __dispose_candidate_process(candidate_process_context_t *cpc); static bool __is_low_memory(void); static void __update_slot_state(candidate_process_context_t *cpc, int method); +static void __init_app_defined_loader_monitor(void); static gboolean __handle_queuing_slots(gpointer data) { @@ -1588,6 +1596,60 @@ static int __dispatch_cmd_add_loader(bundle *kb) return -1; } +static int __dispatch_cmd_add_app_defined_loader(bundle *kb) +{ + const char *loader_name; + const char *loader_path; + int lid, len; + candidate_process_context_t *cpc; + const loader_info_t *info; + bundle_raw *extra; + + _W("cmd add defined loader"); + loader_name = bundle_get_val(kb, AUL_K_LOADER_NAME); + + if (loader_name == NULL) { + _E("loader_name is NULL"); + return -1; + } + + loader_path = _loader_info_find_loader_path_by_loader_name( + loader_info_list, COMMON_LOADER_NAME); + info = _loader_info_find_loader_by_loader_name( + app_defined_loader_info_list, loader_name); + + if (loader_path == NULL || info == NULL || info->extra == NULL) { + _E("loader_name %s, loader_path %d, info %d", + loader_name, loader_path != NULL, info != NULL); + return -1; + } + + bundle_encode(info->extra, &extra, &len); + + lid = __make_loader_id(); + cpc = __add_slot(LAUNCHPAD_TYPE_DYNAMIC, lid, 0, + loader_path, (const char *)extra, + METHOD_TIMEOUT | METHOD_VISIBILITY, + METHOD_REQUEST | METHOD_AVAILABLE_MEMORY, + METHOD_TTL | METHOD_OUT_OF_MEMORY, + info->ttl, + 2000, + DEFAULT_CPU_THRESHOLD_MAX, + DEFAULT_CPU_THRESHOLD_MIN, + false, + true, 0); + + if (cpc == NULL) { + _E("cpc is NULL"); + bundle_free_encoded_rawdata(&extra); + return -1; + } + + __prepare_candidate_process(LAUNCHPAD_TYPE_DYNAMIC, lid); + + return lid; +} + static int __dispatch_cmd_remove_loader(bundle *kb) { const char *id = bundle_get_val(kb, AUL_K_LOADER_ID); @@ -1841,6 +1903,11 @@ static bool __handle_launch_event(int fd, io_condition_e cond, void *data) __real_send(clifd, ret); clifd = -1; goto end; + case PAD_CMD_PREPARE_APP_DEFINED_LOADER: + ret = __dispatch_cmd_add_app_defined_loader(kb); + __real_send(clifd, ret); + clifd = -1; + goto end; case PAD_CMD_DEMAND: ret = __dispatch_cmd_hint(kb, METHOD_DEMAND); __real_send(clifd, ret); @@ -2191,6 +2258,77 @@ static int __init_sigchild_fd(void) return 0; } +static bool __on_directory_create(const char *event_name, uint32_t mask, + void *user_data) +{ + if (!event_name) { + _E("Invalid parameter"); + return true; + } + + if (!strcmp(event_name, LOADERS_PATH)) { + __init_app_defined_loader_monitor(); + return false; + } + + return true; +} + +static bool __on_file_change(const char *event_name, uint32_t mask, + void *user_data) +{ + char buf[PATH_MAX]; + char *ext; + if (!event_name) { + _E("Invalid parameter"); + return true; + } + + ext = strrchr(event_name, '.'); + if (ext == NULL || strcmp(ext, ".loader") != 0) + return true; + + if (mask & IN_CREATE) { + snprintf(buf, sizeof(buf), "%s/%s", + APP_DEFINED_LOADER_INFO_PATH, event_name); + app_defined_loader_info_list = _loader_info_load_file( + app_defined_loader_info_list, buf); + } else if (mask & IN_DELETE) { + snprintf(buf, ext - event_name, "%s", event_name); + app_defined_loader_info_list = _loader_info_unload( + app_defined_loader_info_list, buf); + } + + return true; +} + +static void __init_app_defined_loader_monitor(void) +{ + int ret; + + ret = access(APP_DEFINED_LOADER_INFO_PATH, F_OK); + if (ret < 0) { + _W("Failed to access %s", APP_DEFINED_LOADER_INFO_PATH); + ret = _inotify_add_watch(OPT_SHARE_PATH, + IN_CREATE, __on_directory_create, NULL); + if (ret != 0) + _E("Failed to add inotify watch %s", OPT_SHARE_PATH); + + return; + } + + ret = _inotify_add_watch(APP_DEFINED_LOADER_INFO_PATH, + IN_CREATE | IN_DELETE, __on_file_change, NULL); + + if (ret < 0) { + _E("Failed to add inotify watch %s", + APP_DEFINED_LOADER_INFO_PATH); + } + + return; + +} + static int __init_label_monitor_fd(void) { int r; @@ -2331,7 +2469,7 @@ static int __add_default_slots(void) if (loader_info_list) _loader_info_dispose(loader_info_list); - loader_info_list = _loader_info_load(LOADER_INFO_PATH); + loader_info_list = _loader_info_load_dir(LOADER_INFO_PATH); if (loader_info_list == NULL) return -1; @@ -2342,6 +2480,11 @@ static int __add_default_slots(void) return 0; } +static void __add_app_defined_loaders(void) +{ + app_defined_loader_info_list = _loader_info_load_dir(APP_DEFINED_LOADER_INFO_PATH); +} + static bool __is_low_memory(void) { if (__memory_status_low >= MEMORY_STATUS_LOW) @@ -2562,9 +2705,13 @@ static int __before_loop(int argc, char **argv) if (ret != 0) _W("Failed to initialize config"); + _inotify_init(); + __add_default_slots(); launcher_info_list = _launcher_info_load(LAUNCHER_INFO_PATH); + __add_app_defined_loaders(); + ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL); if (ret < 0) _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL); @@ -2577,6 +2724,7 @@ static int __before_loop(int argc, char **argv) } __register_vconf_events(); + __init_app_defined_loader_monitor(); return 0; } @@ -2593,6 +2741,8 @@ static void __after_loop(void) _debug_fini(); _launcher_info_unload(launcher_info_list); _config_fini(); + _inotify_fini(); + _loader_info_dispose(app_defined_loader_info_list); if (__label_monitor_channel) _io_channel_destroy(__label_monitor_channel); diff --git a/src/launchpad_inotify.c b/src/launchpad_inotify.c new file mode 100644 index 0000000..9130fa2 --- /dev/null +++ b/src/launchpad_inotify.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include "launchpad_inotify.h" +#include "log_private.h" + +struct inotify_watch_info_s { + int fd; + int wd; + GIOChannel *io; + guint tag; + uint32_t mask; + inotify_watch_cb cb; + void *data; +}; + +static GList *__watch_list; + +static gboolean __inotify_cb(GIOChannel *source, GIOCondition condition, + gpointer data) +{ +#define ALIGN_INOTIFY_EVENT \ + __attribute__ ((aligned(__alignof__(struct inotify_event)))) +#define SIZE_INOTIFY_EVENT (sizeof(struct inotify_event)) + int fd = g_io_channel_unix_get_fd(source); + char buf[4096] ALIGN_INOTIFY_EVENT; + const struct inotify_event *event; + struct inotify_watch_info_s *info = data; + ssize_t len; + char *ptr; + char *nptr; + + while ((len = read(fd, buf, sizeof(buf))) > 0) { + for (ptr = buf; ptr < buf + len; + ptr += sizeof(struct inotify_event) + event->len) { + if ((ptr + SIZE_INOTIFY_EVENT) > (buf + len)) + break; + + event = (const struct inotify_event *)ptr; + nptr = ptr + sizeof(struct inotify_event) + event->len; + if (nptr > buf + len) + break; + + if (event->mask & info->mask) { + if (!info->cb(event->name, event->mask, + info->data)) { + _inotify_rm_watch(info); + return G_SOURCE_CONTINUE; + } + } + } + } + + return G_SOURCE_CONTINUE; +} + +static void __destroy_inotify_watch_info(gpointer data) +{ + struct inotify_watch_info_s *info = (struct inotify_watch_info_s *)data; + + if (info == NULL) + return; + + if (info->tag > 0) + g_source_remove(info->tag); + + if (info->io) + g_io_channel_unref(info->io); + + if (info->wd > 0) + inotify_rm_watch(info->fd, info->wd); + + if (info->fd > 0) + close(info->fd); + + free(info); +} + +static struct inotify_watch_info_s *__create_inotify_watch_info( + const char *path, uint32_t mask, inotify_watch_cb cb, + void *data) +{ + GIOCondition cond = G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP; + struct inotify_watch_info_s *info; + + info = calloc(1, sizeof(struct inotify_watch_info_s)); + if (info == NULL) { + _E("Out of memory"); + return NULL; + } + + info->fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); + if (info->fd < 0) { + _E("inotify_init1() is failed. errno(%d)", errno); + __destroy_inotify_watch_info(info); + return NULL; + } + + info->wd = inotify_add_watch(info->fd, path, mask); + if (info->wd < 0) { + _E("inotify_add_watch() is failed. path(%s), errno(%d)", + path, errno); + __destroy_inotify_watch_info(info); + return NULL; + } + + info->io = g_io_channel_unix_new(info->fd); + if (!info->io) { + _E("g_io_channel_unix_new() is failed"); + __destroy_inotify_watch_info(info); + return NULL; + } + + info->tag = g_io_add_watch(info->io, cond, + __inotify_cb, info); + if (!info->tag) { + _E("g_io_add_watch() is failed"); + __destroy_inotify_watch_info(info); + return NULL; + } + + info->mask = mask; + info->cb = cb; + info->data = data; + + return info; +} + +int _inotify_add_watch(const char *path, uint32_t mask, + inotify_watch_cb callback, void *data) +{ + struct inotify_watch_info_s *info; + + if (path == NULL || callback == NULL) { + _E("Invalid parameter"); + return -1; + } + + info = __create_inotify_watch_info(path, mask, callback, data); + if (info == NULL) + return -1; + + __watch_list = g_list_append(__watch_list, info); + + return 0; +} + +void _inotify_rm_watch(inotify_watch_info_h handle) +{ + if (handle == NULL) + return; + + __watch_list = g_list_remove(__watch_list, handle); + __destroy_inotify_watch_info(handle); +} + +int _inotify_init(void) +{ + _D("inotify init"); + + return 0; +} + +void _inotify_fini(void) +{ + _D("inotify fini"); + + if (__watch_list) + g_list_free_full(__watch_list, __destroy_inotify_watch_info); +} diff --git a/src/loader_info.c b/src/loader_info.c index 39e9f21..375c1fd 100644 --- a/src/loader_info.c +++ b/src/loader_info.c @@ -53,6 +53,9 @@ #define VAL_METHOD_TTL "TTL" #define VAL_METHOD_OUT_OF_MEMORY "OUT_OF_MEMORY" +static int __comp_name(gconstpointer a, gconstpointer b); +static void __free_info(gpointer data); + static loader_info_t *__create_loader_info() { loader_info_t *info; @@ -320,7 +323,7 @@ static GList *__parse_file(GList *list, const char *path) return list; } -GList *_loader_info_load(const char *path) +GList *_loader_info_load_dir(const char *path) { DIR *dir_info; struct dirent *entry = NULL; @@ -346,6 +349,56 @@ GList *_loader_info_load(const char *path) return list; } +GList *_loader_info_load_file(GList *list, const char *path) +{ + return __parse_file(list, path); +} + +GList *_loader_info_unload(GList *list, const char *loader_name) +{ + GList *cur; + loader_info_t *info; + + cur = g_list_find_custom(list, loader_name, __comp_name); + if (cur == NULL) + return list; + + info = cur->data; + + list = g_list_remove(list, info); + __free_info(info); + + return list; +} + +const char* _loader_info_find_loader_path_by_loader_name(GList *list, const char *loader_name) +{ + GList *cur; + loader_info_t *info; + + cur = g_list_find_custom(list, loader_name, __comp_name); + if (cur == NULL) + return NULL; + + info = cur->data; + + return info->exe; +} + +const loader_info_t* _loader_info_find_loader_by_loader_name(GList *list, const char *loader_name) +{ + GList *cur; + loader_info_t *info; + + cur = g_list_find_custom(list, loader_name, __comp_name); + if (cur == NULL) + return NULL; + + info = cur->data; + + return info; +} + static void __free_info(gpointer data) { loader_info_t *info; -- 2.7.4