2 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
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.
20 #include <sys/prctl.h>
21 #include <sys/socket.h>
23 #include <sys/types.h>
26 #include <sys/capability.h>
30 #include <bundle_internal.h>
31 #include <security-manager.h>
33 #include <systemd/sd-daemon.h>
35 #include <linux/limits.h>
39 #include <trust-anchor.h>
42 #include "launchpad_common.h"
43 #include "launchpad_signal.h"
45 #include "launchpad.h"
46 #include "loader_info.h"
47 #include "launcher_info.h"
48 #include "launchpad_debug.h"
50 #define AUL_PR_NAME 16
51 #define EXEC_CANDIDATE_EXPIRED 5
52 #define EXEC_CANDIDATE_WAIT 1
53 #define DIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a))
54 #define CANDIDATE_NONE 0
55 #define PROCESS_POOL_LAUNCHPAD_SOCK ".launchpad-process-pool-sock"
56 #define LAUNCHPAD_LOGGER_SOCK ".launchpad-logger-sock"
57 #define LOADER_PATH_DEFAULT "/usr/bin/launchpad-loader"
58 #define LOADER_INFO_PATH "/usr/share/aul"
59 #define LAUNCHER_INFO_PATH LOADER_INFO_PATH
60 #define REGULAR_UID_MIN 5000
61 #define PAD_ERR_FAILED -1
62 #define PAD_ERR_REJECTED -2
63 #define PAD_ERR_INVALID_ARGUMENT -3
64 #define PAD_ERR_INVALID_PATH -4
65 #define CPU_CHECKER_TIMEOUT 1000
68 enum candidate_process_state_e {
69 CANDIDATE_PROCESS_STATE_RUNNING,
70 CANDIDATE_PROCESS_STATE_PAUSED,
87 unsigned long long cpu_total_time;
88 unsigned long long cpu_idle_time;
96 int activation_method;
97 int deactivation_method;
101 } candidate_process_context_t;
113 candidate_process_context_t *running_cpc;
116 struct app_launch_arg {
118 const char *app_path;
119 appinfo_t *menu_info;
133 static int __sys_hwacc;
134 static GList *loader_info_list;
135 static int user_slot_offset;
136 static GList *candidate_slot_list;
137 static app_labels_monitor *label_monitor;
138 static GList *launcher_info_list;
139 static GHashTable *__pid_table;
140 static int __memory_status;
141 static sequencer __sequencer;
143 static candidate_process_context_t *__add_slot(int type, int loader_id,
144 int caller_pid, const char *loader_path, const char *extra,
145 int detection_method, int activation_method,
146 int deactivation_method, unsigned int ttl, int timeout_val,
147 int threshold_max, int threshold_min, bool on_boot,
149 static int __remove_slot(int type, int loader_id);
150 static int __add_default_slots(void);
151 static gboolean __handle_idle_checker(gpointer data);
152 static int __add_idle_checker(int detection_method, GList *cur);
153 static void __dispose_candidate_process(candidate_process_context_t *cpc);
154 static bool __is_low_memory(void);
155 static void __update_slot_state(candidate_process_context_t *cpc, int method);
157 static gboolean __handle_queuing_slots(gpointer data)
159 candidate_process_context_t *cpc;
160 unsigned long long total = 0;
161 unsigned long long idle = 0;
163 if (__sequencer.idle_checker > 0)
164 return G_SOURCE_CONTINUE;
166 if (g_queue_is_empty(__sequencer.queue)) {
167 __sequencer.timer = 0;
168 return G_SOURCE_REMOVE;
171 cpc = (candidate_process_context_t *)g_queue_pop_head(
174 _E("Critical error!");
175 __sequencer.timer = 0;
176 return G_SOURCE_REMOVE;;
179 if (!cpc->app_exists) {
180 _W("The application is not installed. Type(%d)", cpc->type);
181 return G_SOURCE_CONTINUE;
185 g_source_remove(cpc->timer);
189 if (cpc->pid != CANDIDATE_NONE) {
190 _W("The slot(%d) is already running. pid(%d)",
191 cpc->type, cpc->pid);
192 return G_SOURCE_CONTINUE;
195 _get_cpu_idle(&total, &idle);
196 cpc->cpu_idle_time = idle;
197 cpc->cpu_total_time = total;
199 __sequencer.idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT,
200 __handle_idle_checker, cpc);
201 __sequencer.running_cpc = cpc;
203 _D("[__SEQUENCER__] Add idle checker. Type(%d)", cpc->type);
205 return G_SOURCE_CONTINUE;
208 static bool __sequencer_slot_is_running(candidate_process_context_t *cpc)
210 if (__sequencer.running_cpc == cpc)
216 static bool __sequencer_slot_exist(candidate_process_context_t *cpc)
220 found = g_queue_find(__sequencer.queue, cpc);
227 static int __sequencer_add_slot(candidate_process_context_t *cpc)
229 if (__sequencer_slot_exist(cpc)) {
230 _W("Already exists");
234 if (__sequencer_slot_is_running(cpc)) {
235 _W("slot(%d) is running", cpc->type);
239 g_queue_push_tail(__sequencer.queue, cpc);
244 static void __sequencer_remove_slot(candidate_process_context_t *cpc)
246 g_queue_remove(__sequencer.queue, cpc);
249 static void __sequencer_run(void)
251 if (__sequencer.timer)
254 __sequencer.timer = g_timeout_add(500, __handle_queuing_slots, NULL);
255 if (!__sequencer.timer)
256 _E("Failed to add sequencer timer");
259 static void __sequencer_stop(void)
261 if (!__sequencer.timer)
264 g_source_remove(__sequencer.timer);
265 __sequencer.timer = 0;
268 static bool __sequencer_queue_is_empty(void)
270 if (g_queue_is_empty(__sequencer.queue))
276 static int __sequencer_init(void)
278 _D("[__SEQUENCER__] Init");
280 __sequencer.queue = g_queue_new();
281 if (!__sequencer.queue) {
289 static void __sequencer_fini(void)
291 _D("[__SEQUENCER__] Finish");
293 if (__sequencer.idle_checker > 0)
294 g_source_remove(__sequencer.idle_checker);
296 if (__sequencer.timer > 0)
297 g_source_remove(__sequencer.timer);
299 g_queue_free(__sequencer.queue);
302 static int __make_loader_id(void)
304 static int id = PAD_LOADER_ID_DYNAMIC_BASE;
309 static candidate_process_context_t *__find_slot_from_static_type(int type)
311 candidate_process_context_t *cpc;
312 GList *iter = candidate_slot_list;
314 if (type == LAUNCHPAD_TYPE_DYNAMIC ||
315 type == LAUNCHPAD_TYPE_UNSUPPORTED)
319 cpc = (candidate_process_context_t *)iter->data;
320 if (type == cpc->type)
323 iter = g_list_next(iter);
329 static candidate_process_context_t *__find_slot_from_pid(int pid)
331 candidate_process_context_t *cpc;
332 GList *iter = candidate_slot_list;
335 cpc = (candidate_process_context_t *)iter->data;
339 iter = g_list_next(iter);
345 static candidate_process_context_t *__find_slot_from_caller_pid(int caller_pid)
347 candidate_process_context_t *cpc;
348 GList *iter = candidate_slot_list;
351 cpc = (candidate_process_context_t *)iter->data;
352 if (caller_pid == cpc->caller_pid)
355 iter = g_list_next(iter);
361 static candidate_process_context_t *__find_slot_from_loader_id(int id)
363 candidate_process_context_t *cpc;
364 GList *iter = candidate_slot_list;
367 cpc = (candidate_process_context_t *)iter->data;
368 if (id == cpc->loader_id)
371 iter = g_list_next(iter);
377 static candidate_process_context_t *__find_slot(int type, int loader_id)
379 if (type == LAUNCHPAD_TYPE_DYNAMIC)
380 return __find_slot_from_loader_id(loader_id);
382 return __find_slot_from_static_type(type);
385 static void __kill_process(int pid)
387 char err_str[MAX_LOCAL_BUFSZ] = { 0, };
389 if (kill(pid, SIGKILL) == -1) {
390 _E("send SIGKILL: %s",
391 strerror_r(errno, err_str, sizeof(err_str)));
395 static void __refuse_candidate_process(int server_fd)
399 if (server_fd == -1) {
400 _E("arguments error!");
404 client_fd = accept(server_fd, NULL, NULL);
405 if (client_fd == -1) {
411 _D("refuse connection!");
417 static int __accept_candidate_process(int server_fd, int *out_client_fd,
424 if (server_fd == -1 || out_client_fd == NULL ||
425 out_client_pid == NULL) {
426 _E("arguments error!");
430 client_fd = accept(server_fd, NULL, NULL);
431 if (client_fd == -1) {
436 if (_set_sock_option(client_fd, 1) < 0) {
437 _E("Failed to set sock option");
441 recv_ret = recv(client_fd, &client_pid, sizeof(client_pid),
443 if (recv_ret == -1) {
448 *out_client_fd = client_fd;
449 *out_client_pid = client_pid;
451 return *out_client_fd;
460 static int __listen_candidate_process(int type, int loader_id)
462 struct sockaddr_un addr;
465 _D("[launchpad] enter, type: %d", type);
467 memset(&addr, 0x00, sizeof(struct sockaddr_un));
468 addr.sun_family = AF_UNIX;
469 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%d/%s%d-%d",
470 SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME,
473 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
479 unlink(addr.sun_path);
481 _D("bind to %s", addr.sun_path);
482 if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
487 _D("listen to %s", addr.sun_path);
488 if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) {
493 SECURE_LOGD("[launchpad] done, listen fd: %d", fd);
503 static int __get_loader_id(bundle *kb)
507 val = bundle_get_val(kb, AUL_K_LOADER_ID);
510 _W("Requested loader id: %s", val);
515 static int __candidate_process_real_launch(int candidate_fd, app_pkt_t *pkt)
517 return _send_pkt_raw(candidate_fd, pkt);
520 static int __real_send(int clifd, int ret)
523 _E("Invalid parameter. clifd(%d)", clifd);
527 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
528 if (errno == EPIPE) {
529 _E("send failed due to EPIPE.");
533 _E("send fail to client");
540 static void __send_result_to_caller(int clifd, int ret, const char *app_path)
542 _W("send result: %d", ret);
548 _E("launching failed");
549 __real_send(clifd, ret);
553 if (__real_send(clifd, ret) < 0)
557 static int __fork_app_process(int (*child_fn)(void *), void *arg)
565 _E("failed to fork child process");
571 _E("failed to exec app process (%d)", errno);
578 static int __exec_loader_process(void *arg)
583 _signal_unblock_sigchld();
585 _setup_stdio(basename(argv[LOADER_ARG_PATH]));
587 if (execv(argv[LOADER_ARG_PATH], argv) < 0) {
588 _send_message_to_logger(argv[LOADER_ARG_PATH],
589 "Failed to prepare candidate process. error(%d:%s)",
590 errno, strerror_r(errno, err_buf, sizeof(err_buf)));
592 _D("Succeeded to prepare candidate_process");
598 static gboolean __handle_deactivate_event(gpointer user_data)
600 candidate_process_context_t *cpc;
602 cpc = (candidate_process_context_t *)user_data;
603 __update_slot_state(cpc, METHOD_TTL);
604 _D("Deactivate event: type(%d)", cpc->type);
606 return G_SOURCE_REMOVE;
609 static void __set_live_timer(candidate_process_context_t *cpc)
614 if (cpc->deactivation_method & METHOD_TTL) {
615 if (cpc->live_timer == 0) {
616 cpc->live_timer = g_timeout_add_seconds(cpc->ttl,
617 __handle_deactivate_event, cpc);
622 static int __prepare_candidate_process(int type, int loader_id)
625 char type_str[2] = {0, };
626 char loader_id_str[10] = {0, };
627 char argbuf[LOADER_ARG_LEN];
628 char *argv[] = {NULL, NULL, NULL, NULL, NULL, NULL};
629 candidate_process_context_t *cpt = __find_slot(type, loader_id);
634 _D("prepare candidate process / type:%d", type);
635 memset(argbuf, ' ', LOADER_ARG_LEN);
636 argbuf[LOADER_ARG_LEN - 1] = '\0';
637 argv[LOADER_ARG_DUMMY] = argbuf;
639 cpt->last_exec_time = time(NULL);
641 type_str[0] = '0' + type;
642 snprintf(loader_id_str, sizeof(loader_id_str), "%d", loader_id);
643 argv[LOADER_ARG_PATH] = cpt->loader_path;
644 argv[LOADER_ARG_TYPE] = type_str;
645 argv[LOADER_ARG_ID] = loader_id_str;
646 argv[LOADER_ARG_EXTRA] = cpt->loader_extra;
648 pid = __fork_app_process(__exec_loader_process, argv);
650 _E("Failed to fork candidate_process");
655 __set_live_timer(cpt);
660 static gboolean __handle_timeout_event(gpointer user_data)
662 candidate_process_context_t *cpc;
664 cpc = (candidate_process_context_t *)user_data;
667 if (cpc->pid != CANDIDATE_NONE) {
668 _W("Candidate(%d) process(%d) is running", cpc->type, cpc->pid);
669 return G_SOURCE_REMOVE;
672 __sequencer_add_slot(cpc);
674 return G_SOURCE_REMOVE;
677 static void __set_timer(candidate_process_context_t *cpc)
679 if (cpc == NULL || cpc->timer > 0)
682 if ((cpc->detection_method & METHOD_TIMEOUT) &&
683 cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) {
684 cpc->timer = g_timeout_add(cpc->timeout_val,
685 __handle_timeout_event, cpc);
689 static void __reset_slot(candidate_process_context_t *cpc)
695 cpc->prepared = false;
696 cpc->pid = CANDIDATE_NONE;
702 static void __dispose_candidate_process(candidate_process_context_t *cpc)
707 _D("Dispose candidate process %d", cpc->type);
709 _D("kill process %d", cpc->pid);
710 __kill_process(cpc->pid);
712 if (cpc->live_timer > 0)
713 g_source_remove(cpc->live_timer);
715 g_source_remove(cpc->source);
717 g_source_remove(cpc->timer);
718 if (cpc->send_fd > 0)
723 static int __send_launchpad_loader(candidate_process_context_t *cpc,
724 app_pkt_t *pkt, const char *app_path, int clifd)
729 ret = _delete_sock_path(cpc->pid, getuid());
733 __candidate_process_real_launch(cpc->send_fd, pkt);
734 SECURE_LOGD("Request to candidate process, pid: %d, bin path: %s",
738 cpc->pid = CANDIDATE_NONE;
739 __dispose_candidate_process(cpc);
744 static int __normal_fork_exec(int argc, char **argv, const char *app_path)
749 _D("start real fork and exec");
751 libdir = _get_libdir(app_path);
753 setenv("LD_LIBRARY_PATH", libdir, 1);
759 if (execv(argv[LOADER_ARG_PATH], argv) < 0) { /* Flawfinder: ignore */
760 _send_message_to_logger(argv[LOADER_ARG_PATH],
761 "Failed to execute a file. error(%d:%s)",
762 errno, strerror_r(errno, err_buf, sizeof(err_buf)));
769 static int __create_launcher_argv(int *argc, char ***argv, const char *app_type)
772 char **launcher_argv;
773 launcher_info_h launcher_info;
775 const char *extra_arg;
780 launcher_info = _launcher_info_find(launcher_info_list, app_type);
781 if (launcher_info == NULL)
784 exe = _launcher_info_get_exe(launcher_info);
786 _E("Failed to get launcher exe");
790 extra_args = _launcher_info_get_extra_args(launcher_info);
791 launcher_argc = g_list_length(extra_args) + 1;
792 launcher_argv = (char **)calloc(launcher_argc, sizeof(char *));
793 if (launcher_argv == NULL) {
799 launcher_argv[i++] = strdup(exe);
801 iter = g_list_first(extra_args);
803 extra_arg = (const char *)iter->data;
805 launcher_argv[i++] = strdup(extra_arg);
807 iter = g_list_next(iter);
810 *argc = launcher_argc;
811 *argv = launcher_argv;
817 static void __destroy_launcher_argv(int argc, char **argv)
824 for (i = 0; i < argc; i++)
829 static int __create_app_argv(int *argc, char ***argv, const char *app_path,
830 bundle *kb, const char *app_type)
835 struct app_arg debug_arg = {0,};
836 struct app_arg launcher_arg = {0,};
837 struct app_arg arg = {0,};
838 struct app_arg debug_extra_arg = {0,};
843 ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach);
845 _E("Failed to create debugger argv");
850 *argc = debug_arg.argc;
851 *argv = debug_arg.argv;
855 ret = _debug_create_extra_argv(&debug_extra_arg.argc,
856 &debug_extra_arg.argv);
858 _E("Failed to create debugger extra argv");
859 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
863 ret = __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv,
866 _E("Failed to create launcher argv");
867 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
868 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
872 arg.argc = bundle_export_to_argv(kb, &arg.argv);
874 _E("Failed to export bundle");
875 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
876 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
877 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
880 arg.argv[LOADER_ARG_PATH] = strdup(app_path);
882 new_argc = debug_arg.argc + launcher_arg.argc + arg.argc +
883 debug_extra_arg.argc;
884 if (new_argc == arg.argc) {
890 new_argv = (char **)calloc(new_argc + 1, sizeof(char *));
891 if (new_argv == NULL) {
893 free(arg.argv[LOADER_ARG_PATH]);
894 bundle_free_exported_argv(arg.argc, &arg.argv);
895 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
896 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
897 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
902 for (i = 0; i < debug_arg.argc; i++)
903 new_argv[c++] = debug_arg.argv[i];
904 for (i = 0; i < launcher_arg.argc; i++)
905 new_argv[c++] = launcher_arg.argv[i];
906 for (i = 0; i < arg.argc; i++)
907 new_argv[c++] = arg.argv[i];
908 for (i = 0; i < debug_extra_arg.argc; i++)
909 new_argv[c++] = debug_extra_arg.argv[i];
917 static void __real_launch(const char *app_path, bundle *kb,
918 appinfo_t *menu_info)
925 if (bundle_get_val(kb, AUL_K_DEBUG) != NULL)
926 putenv("TIZEN_DEBUGGING_PORT=1");
928 ret = __create_app_argv(&app_argc, &app_argv, app_path,
929 kb, menu_info->app_type);
931 _E("Failed to create app argv");
935 for (i = 0; i < app_argc; i++)
936 SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
938 PERF("setup argument done");
939 __normal_fork_exec(app_argc, app_argv, app_path);
942 static int __prepare_exec(const char *appid, const char *app_path,
943 appinfo_t *menu_info, bundle *kb)
946 char process_name[AUL_PR_NAME];
949 /* Set new session ID & new process group ID*/
950 /* In linux, child can set new session ID without check permission */
951 /* TODO : should be add to check permission in the kernel*/
954 ret = _enable_external_pkg(kb, menu_info->pkgid,
955 menu_info->global ? GLOBAL_USER : getuid());
957 return PAD_ERR_FAILED;
959 if (menu_info->global)
960 ret = trust_anchor_launch(menu_info->pkgid, GLOBAL_USER);
962 ret = trust_anchor_launch(menu_info->pkgid, getuid());
963 if (ret != TRUST_ANCHOR_ERROR_NONE &&
964 ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) {
965 _E("trust_anchor_launch() returns %d", ret);
966 return PAD_ERR_REJECTED;
970 _W("security_manager_prepare_app ++");
971 ret = security_manager_prepare_app(appid);
972 _W("security_manager_prepare_app --");
973 if (ret != SECURITY_MANAGER_SUCCESS)
974 return PAD_ERR_REJECTED;
976 _send_cmd_to_amd(APP_STARTUP_SIGNAL);
977 if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE)
978 _setup_stdio(basename(app_path));
980 /* SET DUMPABLE - for coredump*/
981 prctl(PR_SET_DUMPABLE, 1);
983 /* SET PROCESS NAME*/
984 if (app_path == NULL)
985 return PAD_ERR_INVALID_ARGUMENT;
987 file_name = strrchr(app_path, '/');
988 if (file_name == NULL)
989 return PAD_ERR_INVALID_PATH;
992 if (*file_name == '\0')
993 return PAD_ERR_INVALID_PATH;
995 memset(process_name, '\0', AUL_PR_NAME);
996 snprintf(process_name, AUL_PR_NAME, "%s", file_name);
997 prctl(PR_SET_NAME, process_name);
1000 _set_env(menu_info, kb);
1002 ret = _wait_tep_mount(kb);
1004 return PAD_ERR_FAILED;
1006 if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) {
1007 ret = _prepare_app_socket();
1009 return PAD_ERR_FAILED;
1011 ret = _prepare_id_file();
1013 return PAD_ERR_FAILED;
1019 static int __exec_app_process(void *arg)
1021 struct app_launch_arg *launch_arg = arg;
1025 _D("lock up test log(no error) : fork done");
1027 if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1028 _debug_prepare_debugger(launch_arg->kb);
1030 _signal_unblock_sigchld();
1032 _delete_sock_path(getpid(), getuid());
1034 PERF("prepare exec - first done");
1035 ret = __prepare_exec(launch_arg->appid, launch_arg->app_path,
1036 launch_arg->menu_info, launch_arg->kb);
1040 PERF("prepare exec - second done");
1041 __real_launch(launch_arg->app_path, launch_arg->kb,
1042 launch_arg->menu_info);
1044 return PAD_ERR_FAILED;
1047 static int __launch_directly(const char *appid, const char *app_path, int clifd,
1048 bundle *kb, appinfo_t *menu_info,
1049 candidate_process_context_t *cpc)
1051 struct app_launch_arg arg;
1055 arg.app_path = app_path;
1056 arg.menu_info = menu_info;
1059 pid = __fork_app_process(__exec_app_process, &arg);
1061 _E("failed to fork app process");
1063 SECURE_LOGD("==> real launch pid : %d %s", pid, app_path);
1068 static int __create_sock_activation(void)
1072 fds = sd_listen_fds(0);
1074 return SD_LISTEN_FDS_START;
1076 _E("Too many file descriptors received.");
1078 _D("There is no socket stream");
1083 static int __launchpad_pre_init(int argc, char **argv)
1090 /* create launchpad sock */
1091 fd = __create_sock_activation();
1093 fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK);
1095 _E("server sock error %d", fd);
1103 static void __destroy_poll_data(gpointer data)
1108 static gboolean __glib_check(GSource *src)
1113 fd_list = src->poll_fds;
1115 tmp = (GPollFD *) fd_list->data;
1116 if ((tmp->revents & (G_IO_IN | G_IO_PRI | G_IO_HUP |
1119 fd_list = fd_list->next;
1125 static gboolean __glib_dispatch(GSource *src, GSourceFunc callback,
1128 return callback(data);
1131 static gboolean __glib_prepare(GSource *src, gint *timeout)
1136 static void __glib_finalize(GSource *src)
1141 fd_list = src->poll_fds;
1143 gpollfd = (GPollFD *)fd_list->data;
1147 fd_list = fd_list->next;
1151 static GSourceFuncs funcs = {
1152 .prepare = __glib_prepare,
1153 .check = __glib_check,
1154 .dispatch = __glib_dispatch,
1155 .finalize = __glib_finalize
1158 static guint __poll_fd(int fd, gushort events, GSourceFunc func, int type,
1164 loader_context_t *lc;
1166 src = g_source_new(&funcs, sizeof(GSource));
1168 _E("out of memory");
1172 gpollfd = (GPollFD *)g_malloc(sizeof(GPollFD));
1174 _E("out of memory");
1175 g_source_destroy(src);
1179 gpollfd->events = events;
1182 lc = malloc(sizeof(loader_context_t));
1185 g_source_destroy(src);
1189 lc->gpollfd = gpollfd;
1191 lc->loader_id = loader_id;
1193 g_source_add_poll(src, gpollfd);
1194 g_source_set_callback(src, func,
1195 (gpointer) lc, __destroy_poll_data);
1196 g_source_set_priority(src, G_PRIORITY_DEFAULT);
1198 r = g_source_attach(src, NULL);
1201 g_source_destroy(src);
1208 static gboolean __handle_loader_client_event(gpointer data)
1210 loader_context_t *lc = (loader_context_t *) data;
1211 int type = lc->type;
1212 int loader_id = lc->loader_id;
1213 gushort revents = lc->gpollfd->revents;
1214 candidate_process_context_t *cpc = __find_slot(type, loader_id);
1217 return G_SOURCE_REMOVE;
1219 if (revents & (G_IO_HUP | G_IO_NVAL)) {
1220 SECURE_LOGE("Type %d candidate process was " \
1221 "(POLLHUP|POLLNVAL), pid: %d",
1222 cpc->type, cpc->pid);
1223 cpc->pid = CANDIDATE_NONE;
1224 __dispose_candidate_process(cpc);
1225 __prepare_candidate_process(cpc->type, cpc->loader_id);
1226 return G_SOURCE_REMOVE;
1229 return G_SOURCE_CONTINUE;
1232 static gboolean __handle_loader_event(gpointer data)
1234 loader_context_t *lc = (loader_context_t *) data;
1235 int fd = lc->gpollfd->fd;
1236 int type = lc->type;
1237 int loader_id = lc->loader_id;
1242 candidate_process_context_t *cpc = __find_slot(type, loader_id);
1245 return G_SOURCE_REMOVE;
1247 if (!cpc->prepared) {
1248 ret = __accept_candidate_process(fd, &client_fd, &client_pid);
1250 cpc->prepared = true;
1251 cpc->send_fd = client_fd;
1253 SECURE_LOGD("Type %d candidate process was connected," \
1254 " pid: %d", type, cpc->pid);
1255 cpc->source = __poll_fd(client_fd, G_IO_IN | G_IO_HUP,
1256 __handle_loader_client_event, type,
1258 if (cpc->source == 0)
1262 __refuse_candidate_process(fd);
1263 _E("Refused candidate process connection");
1266 return G_SOURCE_CONTINUE;
1269 static gboolean __handle_sigchild(gpointer data)
1271 candidate_process_context_t *cpc;
1272 loader_context_t *lc = (loader_context_t *) data;
1273 int fd = lc->gpollfd->fd;
1274 struct signalfd_siginfo siginfo;
1279 s = read(fd, &siginfo, sizeof(struct signalfd_siginfo));
1283 if (s != sizeof(struct signalfd_siginfo))
1286 _signal_process_sigchld(&siginfo);
1288 appid = g_hash_table_lookup(__pid_table,
1289 GINT_TO_POINTER(siginfo.ssi_pid));
1291 security_manager_cleanup_app(appid, siginfo.ssi_uid, siginfo.ssi_pid);
1292 g_hash_table_remove(__pid_table,
1293 GINT_TO_POINTER(siginfo.ssi_pid));
1296 cpc = __find_slot_from_pid(siginfo.ssi_pid);
1298 cpc->pid = CANDIDATE_NONE;
1299 __dispose_candidate_process(cpc);
1300 __prepare_candidate_process(cpc->type, cpc->loader_id);
1303 cpc = __find_slot_from_caller_pid(siginfo.ssi_pid);
1305 __remove_slot(LAUNCHPAD_TYPE_DYNAMIC, cpc->loader_id);
1306 cpc = __find_slot_from_caller_pid(siginfo.ssi_pid);
1310 return G_SOURCE_CONTINUE;
1313 static gboolean __handle_label_monitor(gpointer data)
1315 candidate_process_context_t *cpc;
1316 GList *iter = candidate_slot_list;
1318 _D("__handle_label_monitor()");
1319 security_manager_app_labels_monitor_process(label_monitor);
1322 cpc = (candidate_process_context_t *)iter->data;
1324 __dispose_candidate_process(cpc);
1325 __prepare_candidate_process(cpc->type, cpc->loader_id);
1328 iter = g_list_next(iter);
1331 return G_SOURCE_CONTINUE;
1334 static float __interpolator(float input, int cpu_max, int cpu_min)
1337 float min = cpu_min / 100.0f;
1338 float max = cpu_max / 100.0f;
1345 ret = cos(input * PI) / 2.0f + 0.5f;
1352 static void __update_threshold(candidate_process_context_t *cpc, float delta)
1354 static float pos = 0.0f;
1363 cpc->threshold = (int)(__interpolator(pos,
1364 cpc->threshold_max, cpc->threshold_min) * 100);
1365 _D("[CPU] type:%d / delta:%f / input cursor : %f / threshold : %d",
1366 cpc->type, delta, pos, cpc->threshold);
1369 static gboolean __handle_idle_checker(gpointer data)
1371 unsigned long long total = 0;
1372 unsigned long long idle = 0;
1374 candidate_process_context_t *cpc;
1377 _E("Critical error!");
1378 __sequencer.idle_checker = 0;
1379 __sequencer.running_cpc = NULL;
1380 return G_SOURCE_REMOVE;
1383 cpc = (candidate_process_context_t *)data;
1384 if (!cpc->app_exists) {
1385 _W("The application is not installed. Type(%d)", cpc->type);
1386 __sequencer.idle_checker = 0;
1387 __sequencer.running_cpc = NULL;
1388 return G_SOURCE_REMOVE;
1391 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1392 _W("Slot state is not running. Type(%d)", cpc->type);
1393 __sequencer.idle_checker = 0;
1394 __sequencer.running_cpc = NULL;
1395 return G_SOURCE_REMOVE;
1398 _get_cpu_idle(&total, &idle);
1399 if (total == cpc->cpu_total_time)
1402 per = (idle - cpc->cpu_idle_time) * 100 / (total - cpc->cpu_total_time);
1403 _D("[CPU] Idle : %d / type : %d", per, cpc->type);
1405 if (per >= cpc->threshold) {
1406 __update_threshold(cpc, -0.02f * (per - cpc->threshold));
1407 __prepare_candidate_process(cpc->type, cpc->loader_id);
1408 cpc->touched = true;
1409 __sequencer.idle_checker = 0;
1410 __sequencer.running_cpc = NULL;
1411 return G_SOURCE_REMOVE;
1414 cpc->cpu_idle_time = idle;
1415 cpc->cpu_total_time = total;
1416 __update_threshold(cpc, 0.05f);
1418 return G_SOURCE_CONTINUE;
1421 static int __add_idle_checker(int detection_method, GList *cur)
1423 candidate_process_context_t *cpc;
1427 cpc = (candidate_process_context_t *)iter->data;
1428 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1429 iter = g_list_next(iter);
1433 if (strcmp("null", cpc->loader_path) == 0) {
1434 iter = g_list_next(iter);
1438 if (!cpc->touched && !cpc->on_boot) {
1439 iter = g_list_next(iter);
1443 if (!cpc->app_exists) {
1444 iter = g_list_next(iter);
1448 if (cpc->pid == CANDIDATE_NONE &&
1450 (cpc->detection_method & detection_method))) {
1451 if (cpc->timer > 0) {
1452 g_source_remove(cpc->timer);
1456 cpc->cur_event = detection_method;
1457 __sequencer_add_slot(cpc);
1461 iter = g_list_next(iter);
1467 static int __dispatch_cmd_hint(bundle *kb, int detection_method)
1469 _W("cmd hint %d", detection_method);
1470 __add_idle_checker(detection_method, candidate_slot_list);
1475 static int __dispatch_cmd_add_loader(bundle *kb)
1477 const char *add_slot_str = NULL;
1478 const char *caller_pid = NULL;
1481 candidate_process_context_t *cpc;
1483 _W("cmd add loader");
1484 add_slot_str = bundle_get_val(kb, AUL_K_LOADER_PATH);
1485 caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID);
1486 extra = bundle_get_val(kb, AUL_K_LOADER_EXTRA);
1488 if (add_slot_str && caller_pid) {
1489 lid = __make_loader_id();
1490 cpc = __add_slot(LAUNCHPAD_TYPE_DYNAMIC, lid, atoi(caller_pid),
1491 add_slot_str, extra,
1492 METHOD_TIMEOUT | METHOD_VISIBILITY,
1493 METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
1494 METHOD_TTL | METHOD_OUT_OF_MEMORY,
1497 DEFAULT_CPU_THRESHOLD_MAX,
1498 DEFAULT_CPU_THRESHOLD_MIN,
1508 static int __dispatch_cmd_remove_loader(bundle *kb)
1510 const char *id = bundle_get_val(kb, AUL_K_LOADER_ID);
1513 _W("cmd remove loader");
1516 if (__remove_slot(LAUNCHPAD_TYPE_DYNAMIC, lid) == 0)
1523 static int __check_caller_by_pid(int pid)
1526 char buf[PATH_MAX] = { 0, };
1528 ret = _proc_get_attr_by_pid(pid, buf, sizeof(buf));
1532 if (strcmp(buf, "User") == 0 ||
1533 strcmp(buf, "System") == 0 ||
1534 strcmp(buf, "System::Privileged") == 0)
1540 static bool __is_hw_acc(const char *hwacc)
1542 if (strcmp(hwacc, "USE") == 0 ||
1543 (strcmp(hwacc, "SYS") == 0 &&
1544 __sys_hwacc == SETTING_HW_ACCELERATION_ON))
1550 static candidate_process_context_t *__find_available_slot(const char *hwacc,
1551 const char *app_type, const char *loader_name,
1552 candidate_process_context_t **org_cpc)
1555 candidate_process_context_t *cpc;
1561 type = _loader_info_find_type_by_loader_name(loader_info_list,
1564 type = _loader_info_find_type(loader_info_list,
1565 app_type, __is_hw_acc(hwacc));
1567 cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1576 a_types = _loader_get_alternative_types(loader_info_list, type, &len);
1580 for (i = 0; i < len; i++) {
1581 cpc = __find_slot(a_types[i], PAD_LOADER_ID_STATIC);
1584 if (cpc->prepared) {
1594 static void __update_slot(int type, bool app_exists)
1596 candidate_process_context_t *cpc;
1598 cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1602 cpc->app_exists = app_exists;
1603 if (!cpc->app_exists) {
1605 __dispose_candidate_process(cpc);
1606 __sequencer_remove_slot(cpc);
1607 if (__sequencer_queue_is_empty())
1610 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING)
1613 if (!cpc->touched && !cpc->on_boot)
1616 if (cpc->timer > 0) {
1617 g_source_remove(cpc->timer);
1621 if (cpc->pid == CANDIDATE_NONE) {
1622 __sequencer_add_slot(cpc);
1628 static void __foreach_loader_info(loader_info_t *info, void *data)
1630 struct app_info *ai = (struct app_info *)data;
1633 exist = _loader_info_exist_app_type(info, ai->type);
1637 info->app_exists = ai->exists;
1638 __update_slot(info->type, info->app_exists);
1641 static int __dispatch_cmd_update_app_type(bundle *b)
1644 struct app_info info;
1645 const char *is_installed;
1647 info.type = bundle_get_val(b, AUL_K_APP_TYPE);
1651 is_installed = bundle_get_val(b, AUL_K_IS_INSTALLED);
1652 if (is_installed && !strcmp(is_installed, "true"))
1655 info.exists = false;
1657 _I("[LAUNCHPAD] type(%s), exists(%d)", info.type, info.exists);
1659 r = _loader_info_foreach(loader_info_list, __foreach_loader_info,
1662 _E("Failed to retrieve loader info");
1669 static void __update_slot_state(candidate_process_context_t *cpc, int method)
1671 if (method == METHOD_OUT_OF_MEMORY) {
1672 if ((cpc->deactivation_method & method) && __is_low_memory()) {
1673 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
1674 __dispose_candidate_process(cpc);
1676 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
1677 if (!cpc->touched && !cpc->on_boot)
1679 if (!cpc->app_exists || cpc->pid > CANDIDATE_NONE)
1681 if (cpc->detection_method & METHOD_TIMEOUT)
1684 } else if (cpc->activation_method & method) {
1685 __update_slot_state(cpc, METHOD_OUT_OF_MEMORY);
1686 } else if (cpc->deactivation_method & method) {
1687 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
1688 __dispose_candidate_process(cpc);
1690 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
1691 if (!cpc->touched && !cpc->on_boot)
1693 if (!cpc->app_exists || cpc->pid > CANDIDATE_NONE)
1695 if (cpc->detection_method & METHOD_TIMEOUT)
1700 static gboolean __handle_launch_event(gpointer data)
1702 loader_context_t *lc = (loader_context_t *) data;
1703 int fd = lc->gpollfd->fd;
1705 app_pkt_t *pkt = NULL;
1706 appinfo_t *menu_info = NULL;
1707 candidate_process_context_t *cpc = NULL;
1708 candidate_process_context_t *org_cpc = NULL;
1709 const char *app_path = NULL;
1717 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH");
1718 pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
1720 _E("packet is NULL");
1724 if (cr.uid >= REGULAR_UID_MIN) {
1725 if (__check_caller_by_pid(cr.pid) < 0) {
1726 _E("Invalid caller pid");
1731 kb = bundle_decode(pkt->data, pkt->len);
1733 _E("bundle decode error");
1737 if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1741 case PAD_CMD_VISIBILITY:
1742 ret = __dispatch_cmd_hint(kb, METHOD_VISIBILITY);
1743 __real_send(clifd, ret);
1746 case PAD_CMD_ADD_LOADER:
1747 ret = __dispatch_cmd_add_loader(kb);
1748 __real_send(clifd, ret);
1751 case PAD_CMD_REMOVE_LOADER:
1752 ret = __dispatch_cmd_remove_loader(kb);
1753 __real_send(clifd, ret);
1756 case PAD_CMD_MAKE_DEFAULT_SLOTS:
1757 ret = __add_default_slots();
1759 _E("Failed to make default slots");
1760 __real_send(clifd, ret);
1763 case PAD_CMD_DEMAND:
1764 ret = __dispatch_cmd_hint(kb, METHOD_DEMAND);
1765 __real_send(clifd, ret);
1769 __real_send(clifd, getpid());
1772 case PAD_CMD_UPDATE_APP_TYPE:
1773 __dispatch_cmd_update_app_type(kb);
1780 PERF("packet processing start");
1782 menu_info = _appinfo_create(kb);
1783 if (menu_info == NULL) {
1784 _E("such pkg no found");
1788 app_path = _appinfo_get_app_path(menu_info);
1789 if (app_path == NULL) {
1790 _E("app_path is NULL");
1793 if (app_path[0] != '/') {
1794 _E("app_path is not absolute path");
1798 if (menu_info->hwacc == NULL) {
1799 _E("[launchpad] Failed to find H/W acceleration type");
1803 SECURE_LOGD("exec : %s", menu_info->app_path);
1804 SECURE_LOGD("comp_type : %s", menu_info->comp_type);
1805 SECURE_LOGD("internal pool : %s", menu_info->internal_pool);
1806 SECURE_LOGD("hwacc : %s", menu_info->hwacc);
1807 SECURE_LOGD("app_type : %s", menu_info->app_type);
1808 SECURE_LOGD("pkg_type : %s", menu_info->pkg_type);
1810 if (menu_info->comp_type &&
1811 strcmp(menu_info->comp_type, "svcapp") == 0) {
1812 loader_id = PAD_LOADER_ID_DIRECT;
1813 } else if (menu_info->comp_type && menu_info->app_type &&
1814 strcmp(menu_info->comp_type, "widgetapp") == 0 &&
1815 strcmp(menu_info->app_type, "webapp") == 0) {
1816 loader_id = PAD_LOADER_ID_DIRECT;
1818 loader_id = __get_loader_id(kb);
1819 if (loader_id <= PAD_LOADER_ID_STATIC) {
1820 cpc = __find_available_slot(menu_info->hwacc,
1821 menu_info->app_type,
1822 menu_info->loader_name, &org_cpc);
1824 type = LAUNCHPAD_TYPE_DYNAMIC;
1825 cpc = __find_slot(type, loader_id);
1829 _modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
1830 if (menu_info->appid == NULL) {
1831 _E("unable to get appid from menu_info");
1835 PERF("get package information & modify bundle done");
1837 if (loader_id == PAD_LOADER_ID_DIRECT || cpc == NULL) {
1838 _W("Launch directly %d %p", loader_id, cpc);
1839 pid = __launch_directly(menu_info->appid, app_path, clifd, kb,
1841 if (org_cpc && org_cpc->app_exists &&
1842 org_cpc->pid == CANDIDATE_NONE &&
1843 !__sequencer_slot_exist(org_cpc)) {
1844 if (org_cpc->timer > 0) {
1845 g_source_remove(org_cpc->timer);
1849 __update_slot_state(org_cpc, METHOD_REQUEST);
1850 __set_timer(org_cpc);
1853 _W("Launch %d type process", cpc->type);
1854 pid = __send_launchpad_loader(cpc, pkt, app_path, clifd);
1857 __send_result_to_caller(clifd, pid, app_path);
1864 _signal_send_app_launch_signal(pid, menu_info->appid);
1865 g_hash_table_insert(__pid_table, GINT_TO_POINTER(pid),
1866 strdup(menu_info->appid));
1869 if (menu_info != NULL)
1870 _appinfo_free(menu_info);
1877 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1879 return G_SOURCE_CONTINUE;
1882 static candidate_process_context_t *__add_slot(int type, int loader_id,
1883 int caller_pid, const char *loader_path,
1884 const char *loader_extra, int detection_method,
1885 int activation_method, int deactivation_method,
1886 unsigned int ttl, int timeout_val,
1887 int threshold_max, int threshold_min,
1888 bool on_boot, bool app_exists)
1890 candidate_process_context_t *cpc;
1894 if (__find_slot(type, loader_id) != NULL)
1897 cpc = (candidate_process_context_t *)malloc(
1898 sizeof(candidate_process_context_t));
1903 cpc->prepared = false;
1904 cpc->pid = CANDIDATE_NONE;
1905 cpc->caller_pid = caller_pid;
1906 cpc->loader_id = loader_id;
1908 cpc->last_exec_time = 0;
1911 cpc->loader_path = strdup(loader_path);
1912 cpc->loader_extra = loader_extra ? strdup(loader_extra) : strdup("");
1913 cpc->detection_method = detection_method;
1914 cpc->timeout_val = timeout_val;
1915 cpc->cpu_total_time = 0;
1916 cpc->cpu_idle_time = 0;
1917 cpc->threshold = threshold_max;
1918 cpc->threshold_max = threshold_max;
1919 cpc->threshold_min = threshold_min;
1920 cpc->on_boot = on_boot;
1921 cpc->app_exists = app_exists;
1922 cpc->touched = false;
1924 cpc->activation_method = activation_method;
1925 cpc->deactivation_method = deactivation_method;
1927 cpc->live_timer = 0;
1929 if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) &&
1931 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
1933 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
1935 fd = __listen_candidate_process(cpc->type, cpc->loader_id);
1937 _E("[launchpad] Listening the socket to " \
1938 "the type %d candidate process failed.",
1944 pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_loader_event,
1945 cpc->type, cpc->loader_id);
1952 candidate_slot_list = g_list_append(candidate_slot_list, cpc);
1957 static int __remove_slot(int type, int loader_id)
1959 candidate_process_context_t *cpc;
1962 iter = candidate_slot_list;
1964 cpc = (candidate_process_context_t *)iter->data;
1965 if (type == cpc->type && loader_id == cpc->loader_id) {
1966 __dispose_candidate_process(cpc);
1967 candidate_slot_list = g_list_delete_link(
1968 candidate_slot_list, iter);
1969 free(cpc->loader_path);
1970 if (cpc->loader_extra)
1971 free(cpc->loader_extra);
1977 iter = g_list_next(iter);
1983 static int __init_launchpad_fd(int argc, char **argv)
1988 fd = __launchpad_pre_init(argc, argv);
1990 _E("launchpad pre init failed");
1994 pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_launch_event, 0,
2004 static int __init_sigchild_fd(void)
2009 fd = _signal_get_sigchld_fd();
2011 _E("failed to get sigchld fd");
2015 pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_sigchild, 0, 0);
2024 static int __init_label_monitor_fd(void)
2030 r = security_manager_app_labels_monitor_init(&label_monitor);
2031 if (r != SECURITY_MANAGER_SUCCESS)
2034 r = security_manager_app_labels_monitor_process(label_monitor);
2035 if (r != SECURITY_MANAGER_SUCCESS)
2038 security_manager_app_labels_monitor_get_fd(label_monitor, &fd);
2040 _E("failed to get fd");
2044 pollfd = __poll_fd(fd, G_IO_IN,
2045 (GSourceFunc)__handle_label_monitor, 0, 0);
2055 if (label_monitor) {
2056 security_manager_app_labels_monitor_finish(label_monitor);
2057 label_monitor = NULL;
2063 static int __verify_loader_caps(const char *loader)
2066 cap_flag_value_t eff_state;
2067 cap_flag_value_t inh_state;
2068 cap_value_t values[] = {CAP_SETGID, CAP_MAC_ADMIN};
2071 int size = ARRAY_SIZE(values);
2073 /* If Dytransition feature is enabled, CAP_MAC_ADMIN is unnecessary */
2077 cap_d = cap_get_file(loader);
2079 _E("Failed to get cap from file(%s)", loader);
2083 for (i = 0; i < size; i++) {
2084 r = cap_get_flag(cap_d, values[i], CAP_INHERITABLE, &inh_state);
2086 _E("Failed to get cap inh - errno(%d)", errno);
2091 r = cap_get_flag(cap_d, values[i], CAP_EFFECTIVE, &eff_state);
2093 _E("Failed to get cap eff - errno(%d)", errno);
2098 if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) {
2099 _E("The %s doesn't have %d cap", loader, values[i]);
2109 static void __add_slot_from_info(gpointer data, gpointer user_data)
2111 loader_info_t *info = (loader_info_t *)data;
2112 candidate_process_context_t *cpc;
2113 bundle_raw *extra = NULL;
2116 if (!strcmp(info->exe, "null")) {
2117 cpc = __add_slot(LAUNCHPAD_TYPE_USER + user_slot_offset,
2118 PAD_LOADER_ID_DIRECT,
2121 info->cpu_threshold_max,
2122 info->cpu_threshold_min,
2128 info->type = LAUNCHPAD_TYPE_USER + user_slot_offset;
2133 if (access(info->exe, F_OK | X_OK) == 0) {
2134 if (__verify_loader_caps(info->exe) < 0)
2138 bundle_encode(info->extra, &extra, &len);
2140 cpc = __add_slot(LAUNCHPAD_TYPE_USER + user_slot_offset,
2141 PAD_LOADER_ID_STATIC,
2142 0, info->exe, (char *)extra,
2143 info->detection_method,
2144 info->activation_method,
2145 info->deactivation_method,
2148 info->cpu_threshold_max,
2149 info->cpu_threshold_min,
2155 info->type = LAUNCHPAD_TYPE_USER + user_slot_offset;
2160 static int __add_default_slots(void)
2162 if (loader_info_list)
2163 _loader_info_dispose(loader_info_list);
2165 loader_info_list = _loader_info_load(LOADER_INFO_PATH);
2166 if (loader_info_list == NULL)
2169 user_slot_offset = 0;
2170 g_list_foreach(loader_info_list, __add_slot_from_info, NULL);
2171 __add_idle_checker(0, candidate_slot_list);
2176 static bool __is_low_memory(void)
2178 if (__memory_status >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)
2183 static void __hw_acceleration_changed_cb(keynode_t *key, void *data)
2185 __sys_hwacc = vconf_keynode_get_int(key);
2186 _D("sys hwacc: %d", __sys_hwacc);
2189 static void __update_lang(keynode_t *node, void *user_data)
2191 char *lang = vconf_keynode_get_str(node);
2194 setenv("LANG", lang, 1);
2197 static void __memory_status_changed_cb(keynode_t *node, void *data)
2199 candidate_process_context_t *cpc;
2200 GList *iter = candidate_slot_list;
2202 __memory_status = vconf_keynode_get_int(node);
2203 if (__memory_status >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) {
2206 cpc = (candidate_process_context_t *)iter->data;
2207 __update_slot_state(cpc, METHOD_OUT_OF_MEMORY);
2208 iter = g_list_next(iter);
2213 cpc = (candidate_process_context_t *)iter->data;
2214 __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY);
2215 iter = g_list_next(iter);
2220 static void __unregister_vconf_events(void)
2222 vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY,
2223 __memory_status_changed_cb);
2224 vconf_ignore_key_changed(VCONFKEY_LANGSET,
2226 vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2227 __hw_acceleration_changed_cb);
2230 static int __register_vconf_events(void)
2235 r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc);
2237 _E("Failed to get vconf hw acceleration. err = %d", r);
2239 r = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2240 __hw_acceleration_changed_cb, NULL);
2241 if (r != VCONF_OK) {
2242 _E("Failed to register callback for hw acceleration. err = %d",
2246 lang = vconf_get_str(VCONFKEY_LANGSET);
2248 setenv("LANG", lang, 1);
2252 r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL);
2254 _E("Failed to register callback for langset. err = %d", r);
2256 r = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &__memory_status);
2258 _E("Failed to get vconf low memory. err = %d", r);
2260 r = vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY,
2261 __memory_status_changed_cb, NULL);
2263 _E("Failed to register callback for low memory. err = %d", r);
2268 static gboolean __handle_logger(gpointer data)
2270 loader_context_t *lc = (loader_context_t *)data;
2271 int fd = lc->gpollfd->fd;
2272 app_pkt_t *pkt = NULL;
2276 pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
2278 _E("Failed to receive the packet");
2279 return G_SOURCE_CONTINUE;
2282 if (getuid() != cr.uid) {
2283 _E("Invalid caller");
2287 if (pkt->len <= 0) {
2288 _E("Invalid message");
2292 SECURE_LOGE("[%d] %s", cr.pid, (const char *)pkt->data);
2300 return G_SOURCE_CONTINUE;
2303 static int __init_logger_fd(void)
2308 fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK);
2310 _E("Failed to create logger socker");
2314 pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_logger, 0, 0);
2323 static int __before_loop(int argc, char **argv)
2327 ret = __sequencer_init();
2329 _E("Failed to initialize sequencer");
2333 ret = __init_sigchild_fd();
2335 _E("__init_sigchild_fd() failed");
2339 ret = __init_launchpad_fd(argc, argv);
2341 _E("__init_launchpad_fd() failed");
2345 ret = __init_logger_fd();
2347 _E("__init_logger_fd() failed");
2351 ret = __init_label_monitor_fd();
2353 _W("Failed to initialize label monitor");
2355 __add_default_slots();
2356 launcher_info_list = _launcher_info_load(LAUNCHER_INFO_PATH);
2358 ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL);
2360 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL);
2362 __pid_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2365 _E("Failed to create pid table");
2369 __register_vconf_events();
2374 static void __after_loop(void)
2376 __unregister_vconf_events();
2378 g_hash_table_destroy(__pid_table);
2380 if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0)
2381 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL);
2384 _launcher_info_unload(launcher_info_list);
2387 security_manager_app_labels_monitor_finish(label_monitor);
2392 int main(int argc, char **argv)
2394 GMainLoop *mainloop = NULL;
2396 mainloop = g_main_loop_new(NULL, FALSE);
2398 _E("Failed to create glib main loop");
2402 if (__before_loop(argc, argv) != 0) {
2403 _E("process-pool Initialization failed!");
2407 #ifdef TIZEN_FEATURE_PRIORITY_CHANGE
2410 g_main_loop_run(mainloop);