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.
21 #include <systemd/sd-daemon.h>
22 #include <sys/prctl.h>
23 #include <sys/socket.h>
25 #include <sys/types.h>
28 #include <sys/capability.h>
32 #include <bundle_internal.h>
33 #include <security-manager.h>
35 #include <systemd/sd-daemon.h>
37 #include <linux/limits.h>
41 #include <trust-anchor.h>
44 #include "launcher_info.h"
45 #include "launchpad_common.h"
46 #include "launchpad_config.h"
47 #include "launchpad_dbus.h"
48 #include "launchpad_debug.h"
49 #include "launchpad_inotify.h"
50 #include "launchpad_io_channel.h"
51 #include "launchpad_log.h"
52 #include "launchpad_memory_monitor.h"
53 #include "launchpad_plugin.h"
54 #include "launchpad_proc.h"
55 #include "launchpad_signal.h"
56 #include "launchpad_types.h"
57 #include "loader_info.h"
60 #define AUL_PR_NAME 16
61 #define EXEC_CANDIDATE_EXPIRED 5
62 #define EXEC_CANDIDATE_WAIT 1
63 #define DIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a))
64 #define CANDIDATE_NONE 0
66 #define PROCESS_POOL_LAUNCHPAD_SOCK ".launchpad-process-pool-sock"
67 #define LAUNCHPAD_LOGGER_SOCK ".launchpad-logger-sock"
68 #define LOADER_PATH_DEFAULT "/usr/bin/launchpad-loader"
69 #define LOADER_INFO_PATH "/usr/share/aul"
70 #define OPT_SHARE_PATH "/opt/share"
71 #define LOADERS_PATH "loaders"
72 #define APP_DEFINED_LOADER_INFO_PATH OPT_SHARE_PATH "/" LOADERS_PATH
73 #define COMMON_LOADER_NAME "common-loader1"
75 #define LAUNCHER_INFO_PATH LOADER_INFO_PATH
76 #define REGULAR_UID_MIN 5000
77 #define PAD_ERR_FAILED -1
78 #define PAD_ERR_REJECTED -2
79 #define PAD_ERR_INVALID_ARGUMENT -3
80 #define PAD_ERR_INVALID_PATH -4
81 #define CPU_CHECKER_TIMEOUT 1000
84 #define LOSE_SCORE_RATE 0.7f
86 enum candidate_process_state_e {
87 CANDIDATE_PROCESS_STATE_RUNNING,
88 CANDIDATE_PROCESS_STATE_PAUSED,
94 int pid; /* for hydra this pid is not the pid of hydra itself */
95 /* but pid of non-hydra candidate, which was forked from hydra */
106 int detection_method;
108 unsigned long long cpu_total_time;
109 unsigned long long cpu_idle_time;
117 int activation_method;
118 int deactivation_method;
124 io_channel_h client_channel;
125 io_channel_h channel;
126 io_channel_h hydra_channel;
130 } candidate_process_context_t;
142 candidate_process_context_t *running_cpc;
145 struct app_launch_arg {
147 const char *app_path;
148 appinfo_t *menu_info;
162 static int __sys_hwacc;
163 static GList *loader_info_list;
164 static GList *app_defined_loader_info_list;
165 static int user_slot_offset;
166 static GList *candidate_slot_list;
167 static app_labels_monitor *label_monitor;
168 static GList *launcher_info_list;
169 static GHashTable *__pid_table;
170 static int __memory_status_low;
171 static int __memory_status_normal;
172 static sequencer __sequencer;
173 static int MEMORY_STATUS_LOW;
174 static int MEMORY_STATUS_NORMAL;
175 static int MAX_CPU_CHECK_COUNT;
177 static io_channel_h __logger_channel;
178 static io_channel_h __label_monitor_channel;
179 static io_channel_h __launchpad_channel;
181 static candidate_process_context_t *__add_slot(int type, int loader_id,
182 int caller_pid, const char *loader_name,
183 const char *loader_path, const char *extra,
184 int detection_method, int activation_method,
185 int deactivation_method, unsigned int ttl, int timeout_val,
186 int threshold_max, int threshold_min, bool on_boot,
187 bool app_exists, bool is_hydra, bool app_check);
188 static int __remove_slot(int type, int loader_id);
189 static int __add_default_slots(void);
190 static gboolean __handle_idle_checker(gpointer data);
191 static int __add_idle_checker(int detection_method, GList *cur);
192 static void __dispose_candidate_process(candidate_process_context_t *cpc);
193 static bool __is_low_memory(void);
194 static void __update_slot_state(candidate_process_context_t *cpc, int method,
196 static void __init_app_defined_loader_monitor(void);
197 static gboolean __launchpad_recovery_cb(gpointer data);
198 static gboolean __logger_recovery_cb(gpointer data);
200 static gboolean __handle_queuing_slots(gpointer data)
202 candidate_process_context_t *cpc;
203 unsigned long long total = 0;
204 unsigned long long idle = 0;
206 if (__sequencer.idle_checker > 0)
207 return G_SOURCE_CONTINUE;
209 if (g_queue_is_empty(__sequencer.queue)) {
210 __sequencer.timer = 0;
211 return G_SOURCE_REMOVE;
214 cpc = (candidate_process_context_t *)g_queue_pop_head(
217 _E("Critical error!");
218 __sequencer.timer = 0;
219 return G_SOURCE_REMOVE;;
222 if (cpc->app_check && !cpc->app_exists) {
223 _W("The application is not installed. Type(%d)", cpc->type);
224 return G_SOURCE_CONTINUE;
228 g_source_remove(cpc->timer);
232 if (cpc->pid != CANDIDATE_NONE) {
233 _W("The slot(%d) is already running. pid(%d)",
234 cpc->type, cpc->pid);
235 return G_SOURCE_CONTINUE;
238 _get_cpu_idle(&total, &idle);
239 cpc->cpu_idle_time = idle;
240 cpc->cpu_total_time = total;
241 cpc->cpu_check_count = 0;
243 __sequencer.idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT,
244 __handle_idle_checker, cpc);
245 __sequencer.running_cpc = cpc;
247 _D("[__SEQUENCER__] Add idle checker. Type(%d)", cpc->type);
249 return G_SOURCE_CONTINUE;
252 static bool __sequencer_slot_is_running(candidate_process_context_t *cpc)
254 if (__sequencer.running_cpc == cpc)
260 static bool __sequencer_slot_exist(candidate_process_context_t *cpc)
264 found = g_queue_find(__sequencer.queue, cpc);
271 static int __sequencer_add_slot(candidate_process_context_t *cpc)
273 if (__sequencer_slot_exist(cpc)) {
274 _W("Already exists");
278 if (__sequencer_slot_is_running(cpc)) {
279 _W("slot(%d) is running", cpc->type);
283 g_queue_push_tail(__sequencer.queue, cpc);
288 static void __sequencer_remove_slot(candidate_process_context_t *cpc)
290 g_queue_remove(__sequencer.queue, cpc);
293 static void __sequencer_run(void)
295 if (__sequencer.timer)
298 __sequencer.timer = g_timeout_add(500, __handle_queuing_slots, NULL);
299 if (!__sequencer.timer)
300 _E("Failed to add sequencer timer");
303 static void __sequencer_stop(void)
305 if (!__sequencer.timer)
308 g_source_remove(__sequencer.timer);
309 __sequencer.timer = 0;
312 static bool __sequencer_queue_is_empty(void)
314 if (g_queue_is_empty(__sequencer.queue))
320 static int __sequencer_init(void)
322 _D("[__SEQUENCER__] Init");
324 __sequencer.queue = g_queue_new();
325 if (!__sequencer.queue) {
333 static void __sequencer_fini(void)
335 _D("[__SEQUENCER__] Finish");
337 if (__sequencer.idle_checker > 0)
338 g_source_remove(__sequencer.idle_checker);
340 if (__sequencer.timer > 0)
341 g_source_remove(__sequencer.timer);
343 g_queue_free(__sequencer.queue);
346 static int __make_loader_id(void)
348 static int id = PAD_LOADER_ID_DYNAMIC_BASE;
353 static candidate_process_context_t *__find_slot_from_static_type(int type)
355 candidate_process_context_t *cpc;
356 GList *iter = candidate_slot_list;
358 if (type == LAUNCHPAD_LOADER_TYPE_DYNAMIC ||
359 type == LAUNCHPAD_LOADER_TYPE_UNSUPPORTED)
363 cpc = (candidate_process_context_t *)iter->data;
364 if (type == cpc->type)
367 iter = g_list_next(iter);
373 static candidate_process_context_t *__find_slot_from_pid(int pid)
375 candidate_process_context_t *cpc;
376 GList *iter = candidate_slot_list;
379 cpc = (candidate_process_context_t *)iter->data;
383 iter = g_list_next(iter);
389 static candidate_process_context_t *__find_hydra_slot_from_pid(int pid)
391 candidate_process_context_t *cpc;
392 GList *iter = candidate_slot_list;
395 cpc = (candidate_process_context_t *)iter->data;
396 if (cpc->is_hydra && pid == cpc->hydra_pid)
399 iter = g_list_next(iter);
405 static candidate_process_context_t *__find_slot_from_caller_pid(int caller_pid)
407 candidate_process_context_t *cpc;
408 GList *iter = candidate_slot_list;
411 cpc = (candidate_process_context_t *)iter->data;
412 if (caller_pid == cpc->caller_pid)
415 iter = g_list_next(iter);
421 static candidate_process_context_t *__find_slot_from_loader_id(int id)
423 candidate_process_context_t *cpc;
424 GList *iter = candidate_slot_list;
427 cpc = (candidate_process_context_t *)iter->data;
428 if (id == cpc->loader_id)
431 iter = g_list_next(iter);
437 static candidate_process_context_t *__find_slot_from_loader_name(const char *loader_name)
439 candidate_process_context_t *cpc;
440 GList *iter = candidate_slot_list;
443 cpc = (candidate_process_context_t *)iter->data;
444 if (strcmp(cpc->loader_name, loader_name) == 0)
447 iter = g_list_next(iter);
453 static candidate_process_context_t *__find_slot(int type, int loader_id)
455 if (type == LAUNCHPAD_LOADER_TYPE_DYNAMIC)
456 return __find_slot_from_loader_id(loader_id);
458 return __find_slot_from_static_type(type);
461 static void __update_slot_score(candidate_process_context_t *slot)
466 slot->score *= LOSE_SCORE_RATE;
467 slot->score += WIN_SCORE;
470 static void __update_slots_pss(void)
472 candidate_process_context_t *cpc;
475 iter = candidate_slot_list;
477 cpc = (candidate_process_context_t *)iter->data;
478 iter = g_list_next(iter);
480 if (cpc->pid == CANDIDATE_NONE)
483 _proc_get_mem_pss(cpc->pid, &cpc->pss);
487 static gint __compare_slot(gconstpointer a, gconstpointer b)
489 candidate_process_context_t *slot_a = (candidate_process_context_t *)a;
490 candidate_process_context_t *slot_b = (candidate_process_context_t *)b;
492 if (slot_a->is_hydra && !slot_b->is_hydra)
494 if (!slot_a->is_hydra && slot_b->is_hydra)
497 if (slot_a->score < slot_b->score)
499 if (slot_a->score > slot_b->score)
502 if (slot_a->pss < slot_b->pss)
504 if (slot_a->pss > slot_b->pss)
510 static candidate_process_context_t *__get_running_slot(bool is_hydra)
512 candidate_process_context_t *cpc;
515 iter = candidate_slot_list;
517 cpc = (candidate_process_context_t *)iter->data;
518 if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE)
521 iter = g_list_next(iter);
527 static void __pause_last_running_slot(bool is_hydra)
529 candidate_process_context_t *cpc = NULL;
532 iter = g_list_last(candidate_slot_list);
534 cpc = (candidate_process_context_t *)iter->data;
535 if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE)
538 iter = g_list_previous(iter);
544 __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, true);
547 static void __resume_all_slots(void)
549 candidate_process_context_t *cpc;
552 iter = candidate_slot_list;
554 cpc = (candidate_process_context_t *)iter->data;
555 __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, false);
557 iter = g_list_next(iter);
561 static void __kill_process(int pid)
563 char err_str[MAX_LOCAL_BUFSZ] = { 0, };
565 if (kill(pid, SIGKILL) == -1) {
566 _E("send SIGKILL: %s",
567 strerror_r(errno, err_str, sizeof(err_str)));
571 static void __refuse_candidate_process(int server_fd)
575 if (server_fd == -1) {
576 _E("arguments error!");
580 client_fd = accept(server_fd, NULL, NULL);
581 if (client_fd == -1) {
587 _D("refuse connection!");
593 static int __accept_candidate_process(int server_fd, int *out_client_fd,
594 int *out_client_pid, int cpc_pid)
600 struct ucred cred = {};
602 if (server_fd == -1 || out_client_fd == NULL ||
603 out_client_pid == NULL) {
604 _E("arguments error!");
608 client_fd = accept(server_fd, NULL, NULL);
609 if (client_fd == -1) {
614 if (_set_sock_option(client_fd, 1) < 0) {
615 _E("Failed to set sock option");
619 ret = recv(client_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL);
626 ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &len);
628 _E("getsockopt error");
632 if (cred.pid != cpc_pid) {
633 _E("Invalid accept. pid(%d)", cred.pid);
637 if (cred.pid != recv_pid)
638 _W("Not equal recv and real pid");
640 *out_client_fd = client_fd;
641 *out_client_pid = cred.pid;
643 return *out_client_fd;
652 static int __listen_addr(struct sockaddr_un *addr)
655 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
661 unlink(addr->sun_path);
663 _D("bind to %s", addr->sun_path);
664 if (bind(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_un)) < 0) {
669 _D("listen to %s", addr->sun_path);
670 if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) {
675 SECURE_LOGD("[launchpad] done, listen fd: %d", fd);
685 static int __listen_candidate_process(int type, int loader_id)
687 struct sockaddr_un addr;
689 _D("[launchpad] enter, type: %d", type);
691 memset(&addr, 0x00, sizeof(struct sockaddr_un));
692 addr.sun_family = AF_UNIX;
693 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%u/%s%d-%d",
694 SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME,
697 return __listen_addr(&addr);
700 static int __listen_hydra_process(int type, int loader_id)
702 struct sockaddr_un addr;
704 _D("[launchpad] enter, type: %d", type);
706 memset(&addr, 0x00, sizeof(struct sockaddr_un));
707 addr.sun_family = AF_UNIX;
708 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%d/%s%d-%d",
709 SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME,
712 return __listen_addr(&addr);
715 static int __get_loader_id(bundle *kb)
719 val = bundle_get_val(kb, AUL_K_LOADER_ID);
722 _W("Requested loader id: %s", val);
727 static int __candidate_process_real_launch(int candidate_fd, app_pkt_t *pkt)
729 return _send_pkt_raw(candidate_fd, pkt);
732 static int __real_send(int clifd, int ret)
735 _E("Invalid parameter. clifd(%d)", clifd);
739 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
740 if (errno == EPIPE) {
741 _E("send failed due to EPIPE.");
745 _E("send fail to client");
752 static void __send_result_to_caller(int clifd, int ret, const char *app_path)
754 _W("send result: %d", ret);
760 _E("launching failed");
761 __real_send(clifd, ret);
765 if (__real_send(clifd, ret) < 0)
769 static int __fork_app_process(int (*child_fn)(void *), void *arg)
777 _E("failed to fork child process");
782 _W("security_manager_prepare_app_candidate ++");
783 ret = security_manager_prepare_app_candidate();
784 _W("security_manager_prepare_app_candidate --");
785 if (ret != SECURITY_MANAGER_SUCCESS) {
786 _E("failed to prepare app candidate process (%d)", ret);
791 _E("failed to exec app process (%d)", errno);
798 static int __exec_loader_process(void *arg)
803 _send_cmd_to_amd(LAUNCHPAD_CHILD_PROCESS);
804 _signal_unblock_sigchld();
806 _setup_stdio(basename(argv[LOADER_ARG_PATH]));
808 if (execv(argv[LOADER_ARG_PATH], argv) < 0) {
809 _send_message_to_logger(argv[LOADER_ARG_PATH],
810 "Failed to prepare candidate process. error(%d:%s)",
811 errno, strerror_r(errno, err_buf, sizeof(err_buf)));
813 _D("Succeeded to prepare candidate_process");
819 static gboolean __handle_deactivate_event(gpointer user_data)
821 candidate_process_context_t *cpc;
823 cpc = (candidate_process_context_t *)user_data;
824 __update_slot_state(cpc, METHOD_TTL, false);
825 _D("Deactivate event: type(%d)", cpc->type);
827 return G_SOURCE_REMOVE;
830 static void __set_live_timer(candidate_process_context_t *cpc)
835 if (cpc->deactivation_method & METHOD_TTL) {
836 if (cpc->live_timer == 0) {
837 cpc->live_timer = g_timeout_add_seconds(cpc->ttl,
838 __handle_deactivate_event, cpc);
843 static int __hydra_send_request(int fd, enum hydra_cmd cmd)
846 int size = sizeof(cmd);
849 while (sent != size) {
850 send_ret = send(fd, (char *)&cmd + sent,
851 size - sent, MSG_NOSIGNAL);
852 if (send_ret == -1) {
853 _E("send error! (%d)", errno);
858 _D("send(%d: ret: %d) : %d / %d",
859 fd, send_ret, sent, size);
865 static int __hydra_send_launch_candidate_request(int fd)
867 SECURE_LOGD("Send launch cmd to hydra, fd: %d", fd);
868 return __hydra_send_request(fd, LAUNCH_CANDIDATE);
871 static int __prepare_candidate_process(int type, int loader_id)
874 char type_str[12] = {0, };
875 char loader_id_str[12] = {0, };
876 char argbuf[LOADER_ARG_LEN];
877 char *argv[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
878 candidate_process_context_t *cpt = __find_slot(type, loader_id);
883 if (cpt->is_hydra && cpt->hydra_pid != HYDRA_NONE)
884 return __hydra_send_launch_candidate_request(cpt->hydra_fd);
886 _D("prepare candidate process / type:%d", type);
887 memset(argbuf, ' ', LOADER_ARG_LEN);
888 argbuf[LOADER_ARG_LEN - 1] = '\0';
889 argv[LOADER_ARG_DUMMY] = argbuf;
891 cpt->last_exec_time = time(NULL);
893 snprintf(loader_id_str, sizeof(loader_id_str), "%d", loader_id);
894 snprintf(type_str, sizeof(type_str), "%d", type);
895 argv[LOADER_ARG_PATH] = cpt->loader_path;
896 argv[LOADER_ARG_TYPE] = type_str;
897 argv[LOADER_ARG_ID] = loader_id_str;
898 argv[LOADER_ARG_HYDRA] = cpt->is_hydra ? "1" : "0";
899 argv[LOADER_ARG_EXTRA] = cpt->loader_extra;
901 pid = __fork_app_process(__exec_loader_process, argv);
903 _E("Failed to fork candidate_process");
908 cpt->hydra_pid = pid;
911 __set_live_timer(cpt);
914 _log_print("[CANDIDATE]", "pid(%7d) | type(%d) | loader(%s)",
915 pid, cpt->loader_id, cpt->loader_name);
916 _memory_monitor_reset_timer();
921 static gboolean __handle_timeout_event(gpointer user_data)
923 candidate_process_context_t *cpc;
925 cpc = (candidate_process_context_t *)user_data;
928 if (cpc->pid != CANDIDATE_NONE) {
929 _W("Candidate(%d) process(%d) is running", cpc->type, cpc->pid);
930 return G_SOURCE_REMOVE;
933 __sequencer_add_slot(cpc);
935 return G_SOURCE_REMOVE;
938 static void __set_timer(candidate_process_context_t *cpc)
940 if (cpc == NULL || cpc->timer > 0)
943 if ((cpc->detection_method & METHOD_TIMEOUT) &&
944 cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) {
945 cpc->timer = g_timeout_add(cpc->timeout_val,
946 __handle_timeout_event, cpc);
950 static void __reset_slot(candidate_process_context_t *cpc)
956 cpc->prepared = false;
957 cpc->pid = CANDIDATE_NONE;
958 cpc->client_channel = NULL;
963 static void __dispose_candidate_process(candidate_process_context_t *cpc)
968 _D("Dispose candidate process %d", cpc->type);
970 _D("kill process %d", cpc->pid);
971 __kill_process(cpc->pid);
973 if (cpc->live_timer > 0)
974 g_source_remove(cpc->live_timer);
975 if (cpc->client_channel)
976 _io_channel_destroy(cpc->client_channel);
978 g_source_remove(cpc->timer);
979 if (cpc->send_fd > 0)
984 static void __dispose_hydra_process(candidate_process_context_t *cpc)
989 __dispose_candidate_process(cpc);
991 _D("Dispose hydra process %d", cpc->type);
992 if (cpc->hydra_pid > 0) {
993 _D("kill process %d", cpc->hydra_pid);
994 __kill_process(cpc->hydra_pid);
995 cpc->hydra_pid = HYDRA_NONE;
998 if (cpc->hydra_fd > 0) {
999 close(cpc->hydra_fd);
1004 static int __send_launchpad_loader(candidate_process_context_t *cpc,
1005 app_pkt_t *pkt, const char *app_path, int clifd)
1010 ret = _delete_sock_path(cpc->pid, getuid());
1014 __candidate_process_real_launch(cpc->send_fd, pkt);
1015 SECURE_LOGD("Request to candidate process, pid: %d, bin path: %s",
1016 cpc->pid, app_path);
1019 cpc->pid = CANDIDATE_NONE;
1020 __dispose_candidate_process(cpc);
1022 __update_slot_score(cpc);
1027 static int __normal_fork_exec(int argc, char **argv, const char *app_path)
1032 _D("start real fork and exec");
1034 libdir = _get_libdir(app_path);
1036 setenv("LD_LIBRARY_PATH", libdir, 1);
1042 if (execv(argv[LOADER_ARG_PATH], argv) < 0) { /* Flawfinder: ignore */
1043 _send_message_to_logger(argv[LOADER_ARG_PATH],
1044 "Failed to execute a file. error(%d:%s)",
1045 errno, strerror_r(errno, err_buf, sizeof(err_buf)));
1052 static int __create_launcher_argv(int *argc, char ***argv, const char *app_type)
1055 char **launcher_argv;
1056 launcher_info_h launcher_info;
1058 const char *extra_arg;
1063 launcher_info = _launcher_info_find(launcher_info_list, app_type);
1064 if (launcher_info == NULL)
1067 exe = _launcher_info_get_exe(launcher_info);
1069 _E("Failed to get launcher exe");
1073 extra_args = _launcher_info_get_extra_args(launcher_info);
1074 launcher_argc = g_list_length(extra_args) + 1;
1075 launcher_argv = (char **)calloc(launcher_argc, sizeof(char *));
1076 if (launcher_argv == NULL) {
1077 _E("out of memory");
1081 i = LOADER_ARG_PATH;
1082 launcher_argv[i++] = strdup(exe);
1084 iter = g_list_first(extra_args);
1086 extra_arg = (const char *)iter->data;
1088 launcher_argv[i++] = strdup(extra_arg);
1090 iter = g_list_next(iter);
1093 *argc = launcher_argc;
1094 *argv = launcher_argv;
1100 static void __destroy_launcher_argv(int argc, char **argv)
1107 for (i = 0; i < argc; i++)
1112 static int __create_app_argv(int *argc, char ***argv, const char *app_path,
1113 bundle *kb, const char *app_type)
1117 bool attach = false;
1118 struct app_arg debug_arg = {0,};
1119 struct app_arg launcher_arg = {0,};
1120 struct app_arg arg = {0,};
1121 struct app_arg debug_extra_arg = {0,};
1126 ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach);
1128 _E("Failed to create debugger argv");
1133 *argc = debug_arg.argc;
1134 *argv = debug_arg.argv;
1138 ret = _debug_create_extra_argv(&debug_extra_arg.argc,
1139 &debug_extra_arg.argv);
1141 _E("Failed to create debugger extra argv");
1142 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1146 ret = __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv,
1149 _E("Failed to create launcher argv");
1150 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1151 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1155 arg.argc = bundle_export_to_argv(kb, &arg.argv);
1156 if (arg.argc <= 0) {
1157 _E("Failed to export bundle");
1158 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
1159 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1160 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1163 arg.argv[LOADER_ARG_PATH] = strdup(app_path);
1165 new_argc = debug_arg.argc + launcher_arg.argc + arg.argc +
1166 debug_extra_arg.argc;
1167 if (new_argc == arg.argc) {
1173 new_argv = (char **)calloc(new_argc + 1, sizeof(char *));
1174 if (new_argv == NULL) {
1175 _E("out of memory");
1176 free(arg.argv[LOADER_ARG_PATH]);
1177 bundle_free_exported_argv(arg.argc, &arg.argv);
1178 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
1179 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1180 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1184 c = LOADER_ARG_PATH;
1185 for (i = 0; i < debug_arg.argc; i++)
1186 new_argv[c++] = debug_arg.argv[i];
1187 for (i = 0; i < launcher_arg.argc; i++)
1188 new_argv[c++] = launcher_arg.argv[i];
1189 for (i = 0; i < arg.argc; i++)
1190 new_argv[c++] = arg.argv[i];
1191 for (i = 0; i < debug_extra_arg.argc; i++)
1192 new_argv[c++] = debug_extra_arg.argv[i];
1200 static void __real_launch(const char *app_path, bundle *kb,
1201 appinfo_t *menu_info)
1208 if (bundle_get_val(kb, AUL_K_DEBUG) != NULL)
1209 putenv("TIZEN_DEBUGGING_PORT=1");
1211 ret = __create_app_argv(&app_argc, &app_argv, app_path,
1212 kb, menu_info->app_type);
1214 _E("Failed to create app argv");
1218 for (i = 0; i < app_argc; i++)
1219 SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
1221 PERF("setup argument done");
1222 __normal_fork_exec(app_argc, app_argv, app_path);
1225 static int __prepare_exec(const char *appid, const char *app_path,
1226 appinfo_t *menu_info, bundle *kb)
1229 char process_name[AUL_PR_NAME];
1232 /* Set new session ID & new process group ID*/
1233 /* In linux, child can set new session ID without check permission */
1234 /* TODO : should be add to check permission in the kernel*/
1237 ret = _launchpad_plugin_prepare_app(appid, kb);
1239 _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret);
1240 return PAD_ERR_FAILED;
1243 ret = _enable_external_pkg(kb, menu_info->pkgid,
1244 menu_info->global ? GLOBAL_USER : getuid());
1246 return PAD_ERR_FAILED;
1248 if (menu_info->global)
1249 ret = trust_anchor_launch(menu_info->pkgid, GLOBAL_USER);
1251 ret = trust_anchor_launch(menu_info->pkgid, getuid());
1252 if (ret != TRUST_ANCHOR_ERROR_NONE &&
1253 ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) {
1254 _E("trust_anchor_launch() returns %d", ret);
1255 return PAD_ERR_REJECTED;
1259 _W("security_manager_prepare_app ++");
1260 ret = security_manager_prepare_app(appid);
1261 _W("security_manager_prepare_app --");
1262 if (ret != SECURITY_MANAGER_SUCCESS)
1263 return PAD_ERR_REJECTED;
1265 _send_cmd_to_amd(APP_STARTUP_SIGNAL);
1266 if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE)
1267 _setup_stdio(basename(app_path));
1269 /* SET DUMPABLE - for coredump*/
1270 prctl(PR_SET_DUMPABLE, 1);
1272 /* SET PROCESS NAME*/
1273 if (app_path == NULL)
1274 return PAD_ERR_INVALID_ARGUMENT;
1276 file_name = strrchr(app_path, '/');
1277 if (file_name == NULL)
1278 return PAD_ERR_INVALID_PATH;
1281 if (*file_name == '\0')
1282 return PAD_ERR_INVALID_PATH;
1284 memset(process_name, '\0', AUL_PR_NAME);
1285 snprintf(process_name, AUL_PR_NAME, "%s", file_name);
1286 prctl(PR_SET_NAME, process_name);
1289 _set_env(menu_info, kb);
1291 ret = _wait_tep_mount(kb);
1293 return PAD_ERR_FAILED;
1295 if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) {
1296 ret = _prepare_app_socket();
1298 return PAD_ERR_FAILED;
1300 ret = _prepare_id_file();
1302 return PAD_ERR_FAILED;
1308 static int __exec_app_process(void *arg)
1310 struct app_launch_arg *launch_arg = arg;
1313 _print_hwc_log("%d|after calling fork(). %s",
1314 getpid(), launch_arg->appid);
1316 _D("lock up test log(no error) : fork done");
1318 if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1319 _debug_prepare_debugger(launch_arg->kb);
1321 _signal_unblock_sigchld();
1323 _delete_sock_path(getpid(), getuid());
1325 PERF("prepare exec - first done");
1326 ret = __prepare_exec(launch_arg->appid, launch_arg->app_path,
1327 launch_arg->menu_info, launch_arg->kb);
1331 PERF("prepare exec - second done");
1332 __real_launch(launch_arg->app_path, launch_arg->kb,
1333 launch_arg->menu_info);
1335 return PAD_ERR_FAILED;
1338 static int __launch_directly(const char *appid, const char *app_path, int clifd,
1339 bundle *kb, appinfo_t *menu_info,
1340 candidate_process_context_t *cpc)
1342 struct app_launch_arg arg;
1346 arg.app_path = app_path;
1347 arg.menu_info = menu_info;
1350 _print_hwc_log("before calling fork(). %s", appid);
1351 pid = __fork_app_process(__exec_app_process, &arg);
1353 _E("failed to fork app process");
1355 SECURE_LOGD("==> real launch pid : %d %s", pid, app_path);
1360 static int __create_sock_activation(void)
1363 char launchpad_process_pool_sock_path[108];
1366 fds = sd_listen_fds(0);
1367 snprintf(launchpad_process_pool_sock_path,
1368 sizeof(launchpad_process_pool_sock_path), "%s/daemons/%u/%s",
1369 SOCKET_PATH, getuid(), PROCESS_POOL_LAUNCHPAD_SOCK);
1371 for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + fds; ++i) {
1372 if (sd_is_socket_unix(i, SOCK_STREAM, 1,
1373 launchpad_process_pool_sock_path, 0) > 0)
1377 _W("There is no socket stream");
1381 static int __launchpad_pre_init(int argc, char **argv)
1385 /* create launchpad sock */
1386 fd = __create_sock_activation();
1388 fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK);
1390 _E("server sock error %d", fd);
1398 static bool __handle_loader_client_event(int fd, io_condition_e cond,
1401 candidate_process_context_t *cpc = data;
1406 if (cond & (IO_HUP | IO_NVAL)) {
1407 SECURE_LOGE("Type %d candidate process was "
1408 "(POLLHUP|POLLNVAL), pid: %d",
1409 cpc->type, cpc->pid);
1410 cpc->pid = CANDIDATE_NONE;
1411 __dispose_candidate_process(cpc);
1412 __prepare_candidate_process(cpc->type, cpc->loader_id);
1420 static bool __handle_hydra_client_event(int fd, io_condition_e cond,
1423 candidate_process_context_t *cpc = data;
1428 if (cond & (IO_HUP | IO_NVAL)) {
1429 SECURE_LOGE("Type %d hydra process was "
1430 "(POLLHUP|POLLNVAL), pid: %d",
1431 cpc->type, cpc->hydra_pid);
1432 __dispose_hydra_process(cpc);
1433 __prepare_candidate_process(cpc->type, cpc->loader_id);
1440 static bool __handle_loader_event(int fd, io_condition_e cond, void *data)
1442 candidate_process_context_t *cpc = data;
1450 if (!cpc->prepared) {
1451 ret = __accept_candidate_process(fd, &client_fd, &client_pid,
1454 /* for hydra need to set pid to pid of non-hydra candidate, */
1455 /* which is connecting now */
1457 cpc->pid = client_pid;
1459 cpc->prepared = true;
1460 cpc->send_fd = client_fd;
1462 SECURE_LOGD("Type %d candidate process was connected, "
1463 "pid: %d", cpc->type, cpc->pid);
1464 cpc->client_channel = _io_channel_create(client_fd,
1466 __handle_loader_client_event,
1468 if (!cpc->client_channel)
1472 __refuse_candidate_process(fd);
1473 _E("Refused candidate process connection");
1479 static bool __handle_hydra_event(int fd, io_condition_e cond, void *data)
1481 candidate_process_context_t *cpc = data;
1489 if (!cpc->prepared) {
1490 ret = __accept_candidate_process(fd, &client_fd, &client_pid,
1493 cpc->hydra_fd = client_fd;
1495 SECURE_LOGD("Type %d hydra process was connected,"
1496 " pid: %d", cpc->type, cpc->hydra_pid);
1498 cpc->client_channel = _io_channel_create(client_fd,
1500 __handle_hydra_client_event,
1502 if (!cpc->client_channel)
1506 __refuse_candidate_process(fd);
1507 _E("Refused hydra process connection");
1513 static void __handle_sigchild(int pid, void *user_data)
1515 candidate_process_context_t *cpc;
1518 appid = g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid));
1520 security_manager_cleanup_app(appid, getuid(), pid);
1521 g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid));
1524 _log_print("[SIGCHLD]", "pid(%7d)", pid);
1525 cpc = __find_slot_from_pid(pid);
1527 cpc->pid = CANDIDATE_NONE;
1528 __dispose_candidate_process(cpc);
1529 __prepare_candidate_process(cpc->type, cpc->loader_id);
1531 cpc = __find_hydra_slot_from_pid(pid);
1533 cpc->hydra_pid = HYDRA_NONE;
1534 __dispose_hydra_process(cpc);
1535 __prepare_candidate_process(cpc->type, cpc->loader_id);
1539 cpc = __find_slot_from_caller_pid(pid);
1541 __remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, cpc->loader_id);
1542 cpc = __find_slot_from_caller_pid(pid);
1546 static bool __handle_label_monitor(int fd, io_condition_e cond, void *data)
1548 candidate_process_context_t *cpc;
1549 GList *iter = candidate_slot_list;
1551 if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
1552 _E("fd(%d), io_condition(%d)", fd, cond);
1557 _D("fd(%d) condition(%d)", fd, cond);
1558 _log_print("[LABEL]", "fd(%d), condition(%d)", fd, cond);
1559 security_manager_app_labels_monitor_process(label_monitor);
1562 cpc = (candidate_process_context_t *)iter->data;
1563 if (cpc->is_hydra) {
1564 if (cpc->hydra_pid > 0) {
1565 __dispose_hydra_process(cpc);
1566 __prepare_candidate_process(cpc->type,
1569 } else if (cpc->pid > 0) {
1570 __dispose_candidate_process(cpc);
1571 __prepare_candidate_process(cpc->type, cpc->loader_id);
1574 iter = g_list_next(iter);
1580 static float __interpolator(float input, int cpu_max, int cpu_min)
1583 float min = cpu_min / 100.0f;
1584 float max = cpu_max / 100.0f;
1591 ret = cos(input * PI) / 2.0f + 0.5f;
1598 static void __update_threshold(candidate_process_context_t *cpc, float delta)
1600 static float pos = 0.0f;
1609 cpc->threshold = (int)(__interpolator(pos,
1610 cpc->threshold_max, cpc->threshold_min) * 100);
1611 _D("[CPU] type:%d / delta:%f / input cursor : %f / threshold : %d",
1612 cpc->type, delta, pos, cpc->threshold);
1615 static gboolean __handle_idle_checker(gpointer data)
1617 unsigned long long total = 0;
1618 unsigned long long idle = 0;
1620 candidate_process_context_t *cpc;
1623 _E("Critical error!");
1624 __sequencer.idle_checker = 0;
1625 __sequencer.running_cpc = NULL;
1626 return G_SOURCE_REMOVE;
1629 cpc = (candidate_process_context_t *)data;
1630 if (cpc->app_check && !cpc->app_exists) {
1631 _W("The application is not installed. loader(%s:%d)",
1632 cpc->loader_name, cpc->type);
1633 __sequencer.idle_checker = 0;
1634 __sequencer.running_cpc = NULL;
1635 return G_SOURCE_REMOVE;
1638 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1639 _W("Slot state is not running. loader(%s:%d)",
1640 cpc->loader_name, cpc->type);
1641 __sequencer.idle_checker = 0;
1642 __sequencer.running_cpc = NULL;
1643 return G_SOURCE_REMOVE;
1646 _get_cpu_idle(&total, &idle);
1647 if (total == cpc->cpu_total_time)
1650 per = (idle - cpc->cpu_idle_time) * 100 / (total - cpc->cpu_total_time);
1651 _D("[CPU] Idle : %d / loader(%s:%d)", per, cpc->loader_name, cpc->type);
1653 if (per >= cpc->threshold) {
1654 __update_threshold(cpc, -0.02f * (per - cpc->threshold));
1655 __prepare_candidate_process(cpc->type, cpc->loader_id);
1656 cpc->touched = true;
1657 __sequencer.idle_checker = 0;
1658 __sequencer.running_cpc = NULL;
1659 return G_SOURCE_REMOVE;
1662 cpc->cpu_idle_time = idle;
1663 cpc->cpu_total_time = total;
1664 __update_threshold(cpc, 0.05f);
1666 cpc->cpu_check_count++;
1667 if (cpc->cpu_check_count == MAX_CPU_CHECK_COUNT) {
1668 _W("CPU check count has exceeded %d times. loader(%s:%d)",
1669 cpc->cpu_check_count,
1672 __sequencer.idle_checker = 0;
1673 __sequencer.running_cpc = NULL;
1674 __sequencer_add_slot(cpc);
1675 return G_SOURCE_REMOVE;
1678 return G_SOURCE_CONTINUE;
1681 static int __add_idle_checker(int detection_method, GList *cur)
1683 candidate_process_context_t *cpc;
1687 cpc = (candidate_process_context_t *)iter->data;
1688 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1689 iter = g_list_next(iter);
1693 if (strcmp("null", cpc->loader_path) == 0) {
1694 iter = g_list_next(iter);
1698 if (!cpc->touched && !cpc->on_boot) {
1699 iter = g_list_next(iter);
1703 if (cpc->app_check && !cpc->app_exists) {
1704 iter = g_list_next(iter);
1708 if (cpc->pid == CANDIDATE_NONE &&
1710 (cpc->detection_method & detection_method))) {
1711 if (cpc->timer > 0) {
1712 g_source_remove(cpc->timer);
1716 cpc->cur_event = detection_method;
1717 __sequencer_add_slot(cpc);
1721 iter = g_list_next(iter);
1727 static int __dispatch_cmd_hint(bundle *kb, int detection_method)
1729 _W("cmd hint %d", detection_method);
1730 __add_idle_checker(detection_method, candidate_slot_list);
1735 static int __dispatch_cmd_add_loader(bundle *kb)
1737 const char *add_slot_str = NULL;
1738 const char *caller_pid = NULL;
1742 candidate_process_context_t *cpc;
1744 _W("cmd add loader");
1745 add_slot_str = bundle_get_val(kb, AUL_K_LOADER_PATH);
1746 caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID);
1747 extra = bundle_get_val(kb, AUL_K_LOADER_EXTRA);
1749 if (add_slot_str && caller_pid) {
1750 lid = __make_loader_id();
1752 size = snprintf(0, 0, "%s%s%d", add_slot_str, caller_pid, lid);
1753 loader_name = (char *)malloc(size + 1);
1754 if (loader_name == NULL) {
1755 _E("Out of memory");
1759 snprintf(loader_name, size, "%s%s%d", add_slot_str, caller_pid, lid);
1761 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid,
1762 atoi(caller_pid), loader_name,
1763 add_slot_str, extra,
1764 METHOD_TIMEOUT | METHOD_VISIBILITY,
1765 METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
1766 METHOD_TTL | METHOD_OUT_OF_MEMORY,
1769 DEFAULT_CPU_THRESHOLD_MAX,
1770 DEFAULT_CPU_THRESHOLD_MIN,
1783 static int __dispatch_cmd_add_app_defined_loader(bundle *kb)
1785 const char *loader_name;
1787 candidate_process_context_t *cpc;
1788 loader_info_t *info;
1791 _W("cmd add defined loader");
1792 loader_name = bundle_get_val(kb, AUL_K_LOADER_NAME);
1794 if (loader_name == NULL) {
1795 _E("loader_name is NULL");
1799 info = _loader_info_find_loader_by_loader_name(
1800 app_defined_loader_info_list, loader_name);
1801 if (info == NULL || info->extra == NULL) {
1802 _E("loader_name %s, info %d", loader_name, info != NULL);
1806 bundle_encode(info->extra, &extra, &len);
1808 cpc = __find_slot_from_loader_name(loader_name);
1810 lid = __make_loader_id();
1811 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid, 0,
1812 loader_name, "/usr/bin/app-defined-loader", (const char *)extra,
1813 METHOD_TIMEOUT | METHOD_VISIBILITY,
1814 METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
1815 METHOD_TTL | METHOD_OUT_OF_MEMORY,
1818 DEFAULT_CPU_THRESHOLD_MAX,
1819 DEFAULT_CPU_THRESHOLD_MIN,
1826 bundle_free_encoded_rawdata(&extra);
1830 lid = cpc->loader_id;
1833 if (cpc->pid == CANDIDATE_NONE)
1834 __prepare_candidate_process(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid);
1839 static int __dispatch_cmd_remove_loader(bundle *kb)
1841 const char *id = bundle_get_val(kb, AUL_K_LOADER_ID);
1844 _W("cmd remove loader");
1847 if (__remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid) == 0)
1854 static int __check_caller_by_pid(int pid)
1857 char buf[PATH_MAX] = { 0, };
1859 ret = _proc_get_attr(pid, buf, sizeof(buf));
1863 if (strcmp(buf, "User") == 0 ||
1864 strcmp(buf, "System") == 0 ||
1865 strcmp(buf, "System::Privileged") == 0)
1871 static bool __is_hw_acc(const char *hwacc)
1873 if (strcmp(hwacc, "USE") == 0 ||
1874 (strcmp(hwacc, "SYS") == 0 &&
1875 __sys_hwacc == SETTING_HW_ACCELERATION_ON))
1881 static candidate_process_context_t *__find_available_slot(const char *hwacc,
1882 const char *app_type, const char *loader_name,
1883 candidate_process_context_t **org_cpc)
1886 candidate_process_context_t *cpc;
1892 type = _loader_info_find_type_by_loader_name(loader_info_list,
1895 type = _loader_info_find_type(loader_info_list,
1896 app_type, __is_hw_acc(hwacc));
1898 cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1907 a_types = _loader_get_alternative_types(loader_info_list, type, &len);
1911 for (i = 0; i < len; i++) {
1912 cpc = __find_slot(a_types[i], PAD_LOADER_ID_STATIC);
1915 if (cpc->prepared) {
1925 static void __update_slot(int type, bool app_exists)
1927 candidate_process_context_t *cpc;
1929 cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1933 cpc->app_exists = app_exists;
1934 if (cpc->app_check && !cpc->app_exists) {
1936 __dispose_candidate_process(cpc);
1937 __sequencer_remove_slot(cpc);
1938 if (__sequencer_queue_is_empty())
1941 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING)
1944 if (!cpc->touched && !cpc->on_boot)
1947 if (cpc->timer > 0) {
1948 g_source_remove(cpc->timer);
1952 if (cpc->pid == CANDIDATE_NONE) {
1953 __sequencer_add_slot(cpc);
1959 static void __foreach_loader_info(loader_info_t *info, void *data)
1961 struct app_info *ai = (struct app_info *)data;
1964 exist = _loader_info_exist_app_type(info, ai->type);
1968 info->app_exists = ai->exists;
1969 __update_slot(info->type, info->app_exists);
1972 static int __dispatch_cmd_update_app_type(bundle *b)
1975 struct app_info info;
1976 const char *is_installed;
1978 info.type = bundle_get_val(b, AUL_K_APP_TYPE);
1982 is_installed = bundle_get_val(b, AUL_K_IS_INSTALLED);
1983 if (is_installed && !strcmp(is_installed, "true"))
1986 info.exists = false;
1988 _I("[LAUNCHPAD] type(%s), exists(%d)", info.type, info.exists);
1990 r = _loader_info_foreach(loader_info_list, __foreach_loader_info,
1993 _E("Failed to retrieve loader info");
2000 static void __deactivate_slot(candidate_process_context_t *cpc)
2002 if (cpc->state == CANDIDATE_PROCESS_STATE_PAUSED)
2005 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2006 __dispose_candidate_process(cpc);
2009 static void __activate_slot(candidate_process_context_t *cpc)
2011 if (cpc->state == CANDIDATE_PROCESS_STATE_RUNNING)
2014 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2015 if (!cpc->touched && !cpc->on_boot)
2018 if ((cpc->app_check && !cpc->app_exists) || cpc->pid > CANDIDATE_NONE)
2021 if (cpc->detection_method & METHOD_TIMEOUT)
2025 static void __update_slot_state(candidate_process_context_t *cpc, int method,
2029 case METHOD_OUT_OF_MEMORY:
2030 if ((force || cpc->deactivation_method & method) &&
2032 __deactivate_slot(cpc);
2034 __activate_slot(cpc);
2037 if (force || cpc->deactivation_method & method)
2038 __deactivate_slot(cpc);
2040 case METHOD_AVAILABLE_MEMORY:
2041 if (force || cpc->activation_method & method)
2042 __activate_slot(cpc);
2044 case METHOD_REQUEST:
2045 if (force || cpc->activation_method & method)
2046 __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, force);
2049 __activate_slot(cpc);
2054 static bool __handle_launch_event(int fd, io_condition_e cond, void *data)
2057 app_pkt_t *pkt = NULL;
2058 appinfo_t *menu_info = NULL;
2059 candidate_process_context_t *cpc = NULL;
2060 candidate_process_context_t *org_cpc = NULL;
2061 const char *app_path = NULL;
2069 if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
2070 _E("fd(%d), condition(%d)", fd, cond);
2071 g_idle_add(__launchpad_recovery_cb, __launchpad_channel);
2072 __launchpad_channel = NULL;
2076 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH");
2077 pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
2079 _E("packet is NULL");
2083 if (cr.uid >= REGULAR_UID_MIN) {
2084 if (__check_caller_by_pid(cr.pid) < 0) {
2085 _E("Invalid caller pid");
2090 kb = bundle_decode(pkt->data, pkt->len);
2092 _E("bundle decode error");
2096 if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
2100 case PAD_CMD_VISIBILITY:
2101 ret = __dispatch_cmd_hint(kb, METHOD_VISIBILITY);
2102 __real_send(clifd, ret);
2105 case PAD_CMD_ADD_LOADER:
2106 ret = __dispatch_cmd_add_loader(kb);
2107 __real_send(clifd, ret);
2110 case PAD_CMD_REMOVE_LOADER:
2111 ret = __dispatch_cmd_remove_loader(kb);
2112 __real_send(clifd, ret);
2115 case PAD_CMD_MAKE_DEFAULT_SLOTS:
2116 ret = __add_default_slots();
2118 _E("Failed to make default slots");
2119 __real_send(clifd, ret);
2122 case PAD_CMD_PREPARE_APP_DEFINED_LOADER:
2123 ret = __dispatch_cmd_add_app_defined_loader(kb);
2124 __real_send(clifd, ret);
2127 case PAD_CMD_DEMAND:
2128 ret = __dispatch_cmd_hint(kb, METHOD_DEMAND);
2129 __real_send(clifd, ret);
2133 __real_send(clifd, getpid());
2136 case PAD_CMD_UPDATE_APP_TYPE:
2137 __dispatch_cmd_update_app_type(kb);
2144 PERF("packet processing start");
2146 menu_info = _appinfo_create(kb);
2147 if (menu_info == NULL) {
2148 _E("such pkg no found");
2152 app_path = _appinfo_get_app_path(menu_info);
2153 if (app_path == NULL) {
2154 _E("app_path is NULL");
2157 if (app_path[0] != '/') {
2158 _E("app_path is not absolute path");
2162 if (menu_info->hwacc == NULL) {
2163 _E("[launchpad] Failed to find H/W acceleration type");
2167 SECURE_LOGD("exec : %s", menu_info->app_path);
2168 SECURE_LOGD("comp_type : %s", menu_info->comp_type);
2169 SECURE_LOGD("internal pool : %s", menu_info->internal_pool);
2170 SECURE_LOGD("hwacc : %s", menu_info->hwacc);
2171 SECURE_LOGD("app_type : %s", menu_info->app_type);
2172 SECURE_LOGD("pkg_type : %s", menu_info->pkg_type);
2174 if (menu_info->comp_type &&
2175 strcmp(menu_info->comp_type, "svcapp") == 0) {
2176 loader_id = __get_loader_id(kb);
2177 if (loader_id > PAD_LOADER_ID_DYNAMIC_BASE) {
2178 type = LAUNCHPAD_LOADER_TYPE_DYNAMIC;
2179 cpc = __find_slot(type, loader_id);
2180 if (cpc && !cpc->prepared)
2183 loader_id = PAD_LOADER_ID_DIRECT;
2185 } else if (menu_info->comp_type && menu_info->app_type &&
2186 strcmp(menu_info->comp_type, "widgetapp") == 0 &&
2187 strcmp(menu_info->app_type, "webapp") == 0) {
2188 loader_id = PAD_LOADER_ID_DIRECT;
2190 loader_id = __get_loader_id(kb);
2191 if (loader_id <= PAD_LOADER_ID_STATIC) {
2192 cpc = __find_available_slot(menu_info->hwacc,
2193 menu_info->app_type,
2194 menu_info->loader_name, &org_cpc);
2196 type = LAUNCHPAD_LOADER_TYPE_DYNAMIC;
2197 cpc = __find_slot(type, loader_id);
2198 if (cpc && !cpc->prepared)
2203 _modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
2204 if (menu_info->appid == NULL) {
2205 _E("unable to get appid from menu_info");
2209 PERF("get package information & modify bundle done");
2211 if (loader_id == PAD_LOADER_ID_DIRECT || cpc == NULL) {
2212 _W("Launch directly %d %p", loader_id, cpc);
2213 pid = __launch_directly(menu_info->appid, app_path, clifd, kb,
2215 if (org_cpc && (!org_cpc->app_check || org_cpc->app_exists) &&
2216 org_cpc->pid == CANDIDATE_NONE &&
2217 !__sequencer_slot_exist(org_cpc)) {
2218 if (org_cpc->timer > 0) {
2219 g_source_remove(org_cpc->timer);
2223 __update_slot_state(org_cpc, METHOD_REQUEST, true);
2224 __set_timer(org_cpc);
2227 _W("Launch %d type process", cpc->type);
2228 pid = __send_launchpad_loader(cpc, pkt, app_path, clifd);
2231 _memory_monitor_reset_timer();
2232 __send_result_to_caller(clifd, pid, app_path);
2239 _dbus_send_app_launch_signal(pid, menu_info->appid);
2240 g_hash_table_insert(__pid_table, GINT_TO_POINTER(pid),
2241 strdup(menu_info->appid));
2242 _log_print("[LAUNCH]", "pid(%7d) | appid(%s)",
2243 pid, menu_info->appid);
2246 if (menu_info != NULL)
2247 _appinfo_free(menu_info);
2254 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
2259 static void __destroy_slot(candidate_process_context_t *cpc)
2264 if (cpc->hydra_channel)
2265 _io_channel_destroy(cpc->hydra_channel);
2268 _io_channel_destroy(cpc->channel);
2270 if (cpc->loader_extra)
2271 free(cpc->loader_extra);
2273 if (cpc->loader_path)
2274 free(cpc->loader_path);
2276 if (cpc->loader_name)
2277 free(cpc->loader_name);
2282 static candidate_process_context_t *__create_slot(int type, int loader_id,
2283 int caller_pid, const char *loader_name, const char *loader_path,
2284 const char *loader_extra, int detection_method,
2285 int activation_method, int deactivation_method,
2286 unsigned int ttl, int timeout_val,
2287 int threshold_max, int threshold_min,
2288 bool on_boot, bool app_exists, bool is_hydra, bool app_check)
2290 candidate_process_context_t *cpc;
2292 cpc = calloc(1, sizeof(candidate_process_context_t));
2294 _E("Out of memory");
2298 cpc->loader_name = strdup(loader_name);
2299 if (cpc->loader_name == NULL) {
2300 _E("Failed to duplicate loader name(%s)", loader_name);
2301 __destroy_slot(cpc);
2305 cpc->loader_path = strdup(loader_path);
2306 if (cpc->loader_path == NULL) {
2307 _E("Failed to duplicate loader path(%s)", loader_path);
2308 __destroy_slot(cpc);
2312 cpc->loader_extra = loader_extra ? strdup(loader_extra) : strdup("");
2313 if (cpc->loader_extra == NULL) {
2314 _E("Failed to duplicate loader extra(%s)",
2315 loader_extra ? loader_extra : "null");
2316 __destroy_slot(cpc);
2321 cpc->prepared = false;
2322 cpc->pid = CANDIDATE_NONE;
2323 cpc->hydra_pid = HYDRA_NONE;
2324 cpc->caller_pid = caller_pid;
2325 cpc->loader_id = loader_id;
2328 cpc->last_exec_time = 0;
2330 cpc->detection_method = detection_method;
2331 cpc->timeout_val = timeout_val;
2332 cpc->cpu_total_time = 0;
2333 cpc->cpu_idle_time = 0;
2334 cpc->threshold = threshold_max;
2335 cpc->threshold_max = threshold_max;
2336 cpc->threshold_min = threshold_min;
2337 cpc->on_boot = on_boot;
2338 cpc->app_exists = app_exists;
2339 cpc->touched = false;
2341 cpc->activation_method = activation_method;
2342 cpc->deactivation_method = deactivation_method;
2344 cpc->live_timer = 0;
2345 cpc->is_hydra = is_hydra;
2346 cpc->app_check = app_check;
2347 cpc->score = WIN_SCORE;
2349 cpc->cpu_check_count = 0;
2351 if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) &&
2353 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2355 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2357 _W("loader(%s), type(%d), state(%d)",
2358 cpc->loader_name, cpc->type, cpc->state);
2362 static candidate_process_context_t *__add_slot(int type, int loader_id,
2363 int caller_pid, const char *loader_name, const char *loader_path,
2364 const char *loader_extra, int detection_method,
2365 int activation_method, int deactivation_method,
2366 unsigned int ttl, int timeout_val,
2367 int threshold_max, int threshold_min,
2368 bool on_boot, bool app_exists, bool is_hydra, bool app_check)
2370 candidate_process_context_t *cpc;
2372 io_channel_h channel;
2374 io_channel_h hydra_channel;
2376 if (__find_slot(type, loader_id) != NULL)
2379 cpc = __create_slot(type, loader_id,
2380 caller_pid, loader_name, loader_path,
2381 loader_extra, detection_method,
2382 activation_method, deactivation_method,
2384 threshold_max, threshold_min,
2385 on_boot, app_exists, is_hydra, app_check);
2389 fd = __listen_candidate_process(cpc->type, cpc->loader_id);
2391 _E("[launchpad] Listening the socket to " \
2392 "the type %d candidate process failed.",
2394 __destroy_slot(cpc);
2398 channel = _io_channel_create(fd, IO_IN, __handle_loader_event, cpc);
2401 __destroy_slot(cpc);
2405 cpc->channel = channel;
2408 hydra_fd = __listen_hydra_process(cpc->type, cpc->loader_id);
2409 if (hydra_fd == -1) {
2410 _E("[launchpad] Listening the socket to " \
2411 "the type %d hydra process failed.",
2413 __destroy_slot(cpc);
2417 hydra_channel = _io_channel_create(hydra_fd, IO_IN,
2418 __handle_hydra_event, cpc);
2419 if (!hydra_channel) {
2421 __destroy_slot(cpc);
2425 cpc->hydra_channel = hydra_channel;
2429 candidate_slot_list = g_list_append(candidate_slot_list, cpc);
2434 static int __remove_slot(int type, int loader_id)
2436 candidate_process_context_t *cpc;
2439 iter = candidate_slot_list;
2441 cpc = (candidate_process_context_t *)iter->data;
2442 if (type == cpc->type && loader_id == cpc->loader_id) {
2443 __dispose_candidate_process(cpc);
2444 candidate_slot_list = g_list_delete_link(
2445 candidate_slot_list, iter);
2446 __destroy_slot(cpc);
2450 iter = g_list_next(iter);
2456 static int __init_launchpad_fd(int argc, char **argv)
2458 io_condition_e cond;
2461 fd = __launchpad_pre_init(argc, argv);
2463 _E("launchpad pre init failed");
2467 cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
2468 __launchpad_channel = _io_channel_create(fd, cond,
2469 __handle_launch_event, NULL);
2470 if (!__launchpad_channel) {
2478 static bool __on_directory_create(const char *event_name, uint32_t mask,
2482 _E("Invalid parameter");
2486 if (!strcmp(event_name, LOADERS_PATH)) {
2487 __init_app_defined_loader_monitor();
2494 static bool __on_file_change(const char *event_name, uint32_t mask,
2499 loader_info_t* info;
2500 candidate_process_context_t *cpc;
2503 _E("Invalid parameter");
2507 ext = strrchr(event_name, '.');
2508 if (ext == NULL || strcmp(ext, ".loader") != 0)
2511 if (mask & IN_CREATE) {
2512 snprintf(buf, sizeof(buf), "%s/%s",
2513 APP_DEFINED_LOADER_INFO_PATH, event_name);
2514 app_defined_loader_info_list = _loader_info_load_file(
2515 app_defined_loader_info_list, buf);
2516 } else if (mask & IN_DELETE) {
2517 snprintf(buf, ext - event_name + 1, "%s", event_name);
2519 info = _loader_info_find_loader_by_loader_name(
2520 app_defined_loader_info_list, buf);
2521 cpc = __find_slot_from_loader_name(info->name);
2522 __remove_slot(cpc->type, cpc->loader_id);
2523 app_defined_loader_info_list = _loader_info_unload(
2524 app_defined_loader_info_list, buf);
2530 static void __init_app_defined_loader_monitor(void)
2534 ret = access(APP_DEFINED_LOADER_INFO_PATH, F_OK);
2536 _W("Failed to access %s", APP_DEFINED_LOADER_INFO_PATH);
2537 ret = _inotify_add_watch(OPT_SHARE_PATH,
2538 IN_CREATE, __on_directory_create, NULL);
2540 _E("Failed to add inotify watch %s", OPT_SHARE_PATH);
2545 ret = _inotify_add_watch(APP_DEFINED_LOADER_INFO_PATH,
2546 IN_CREATE | IN_DELETE, __on_file_change, NULL);
2549 _E("Failed to add inotify watch %s",
2550 APP_DEFINED_LOADER_INFO_PATH);
2557 static int __init_label_monitor_fd(void)
2559 io_condition_e cond;
2563 r = security_manager_app_labels_monitor_init(&label_monitor);
2564 if (r != SECURITY_MANAGER_SUCCESS)
2567 r = security_manager_app_labels_monitor_process(label_monitor);
2568 if (r != SECURITY_MANAGER_SUCCESS)
2571 security_manager_app_labels_monitor_get_fd(label_monitor, &fd);
2573 _E("failed to get fd");
2577 cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
2578 __label_monitor_channel = _io_channel_create(fd, cond,
2579 __handle_label_monitor, NULL);
2580 if (!__label_monitor_channel)
2589 if (label_monitor) {
2590 security_manager_app_labels_monitor_finish(label_monitor);
2591 label_monitor = NULL;
2597 static int __verify_loader_caps(const char *loader)
2600 cap_flag_value_t eff_state;
2601 cap_flag_value_t inh_state;
2602 cap_value_t values[] = {CAP_SETGID, CAP_MAC_ADMIN};
2605 int size = ARRAY_SIZE(values);
2607 /* If Dytransition feature is enabled, CAP_MAC_ADMIN is unnecessary */
2611 cap_d = cap_get_file(loader);
2613 _E("Failed to get cap from file(%s)", loader);
2617 for (i = 0; i < size; i++) {
2618 r = cap_get_flag(cap_d, values[i], CAP_INHERITABLE, &inh_state);
2620 _E("Failed to get cap inh - errno(%d)", errno);
2625 r = cap_get_flag(cap_d, values[i], CAP_EFFECTIVE, &eff_state);
2627 _E("Failed to get cap eff - errno(%d)", errno);
2632 if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) {
2633 _E("The %s doesn't have %d cap", loader, values[i]);
2643 static void __add_slot_from_info(gpointer data, gpointer user_data)
2645 loader_info_t *info = (loader_info_t *)data;
2646 candidate_process_context_t *cpc;
2647 bundle_raw *extra = NULL;
2650 if (!strcmp(info->exe, "null")) {
2651 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset,
2652 PAD_LOADER_ID_DIRECT,
2653 0, info->name, info->exe, NULL,
2655 info->cpu_threshold_max,
2656 info->cpu_threshold_min,
2664 info->type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset;
2669 if (access(info->exe, F_OK | X_OK) == 0) {
2670 if (__verify_loader_caps(info->exe) < 0)
2674 bundle_encode(info->extra, &extra, &len);
2676 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset,
2677 PAD_LOADER_ID_STATIC,
2678 0, info->name, info->exe, (char *)extra,
2679 info->detection_method,
2680 info->activation_method,
2681 info->deactivation_method,
2684 info->cpu_threshold_max,
2685 info->cpu_threshold_min,
2693 info->type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset;
2698 static int __add_default_slots(void)
2700 if (loader_info_list)
2701 _loader_info_dispose(loader_info_list);
2703 loader_info_list = _loader_info_load_dir(LOADER_INFO_PATH);
2704 if (loader_info_list == NULL)
2707 user_slot_offset = 0;
2708 g_list_foreach(loader_info_list, __add_slot_from_info, NULL);
2709 __add_idle_checker(0, candidate_slot_list);
2714 static void __add_app_defined_loaders(void)
2716 app_defined_loader_info_list = _loader_info_load_dir(APP_DEFINED_LOADER_INFO_PATH);
2719 static bool __is_low_memory(void)
2721 if (_memory_monitor_is_low_memory())
2724 if (__memory_status_low >= MEMORY_STATUS_LOW)
2730 static void __hw_acceleration_changed_cb(keynode_t *key, void *data)
2732 __sys_hwacc = vconf_keynode_get_int(key);
2733 _D("sys hwacc: %d", __sys_hwacc);
2736 static void __update_lang(keynode_t *node, void *user_data)
2740 lang = vconf_keynode_get_str(node);
2742 _E("Failed to get language");
2746 setenv("LANG", lang, 1);
2749 static void __region_format_changed_cb(keynode_t *node, void *data)
2753 region = vconf_keynode_get_str(node);
2755 _E("Failed to get value");
2759 setenv("LC_CTYPE", region, 1);
2762 static void __memory_status_low_changed_cb(keynode_t *node, void *data)
2764 candidate_process_context_t *cpc;
2767 __memory_status_low = vconf_keynode_get_int(node);
2768 if (__memory_status_low >= MEMORY_STATUS_LOW) {
2770 iter = candidate_slot_list;
2772 cpc = (candidate_process_context_t *)iter->data;
2773 __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, false);
2774 iter = g_list_next(iter);
2779 static void __memory_status_normal_changed_cb(keynode_t *node, void *data)
2781 candidate_process_context_t *cpc;
2784 __memory_status_normal = vconf_keynode_get_int(node);
2785 if (__memory_status_normal == MEMORY_STATUS_NORMAL) {
2787 iter = candidate_slot_list;
2789 cpc = (candidate_process_context_t *)iter->data;
2790 __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, true);
2791 iter = g_list_next(iter);
2796 static void __unregister_vconf_events(void)
2801 type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY;
2802 key = _config_get_string_value(type);
2803 vconf_ignore_key_changed(key, __memory_status_normal_changed_cb);
2805 type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY;
2806 key = _config_get_string_value(type);
2807 vconf_ignore_key_changed(key, __memory_status_low_changed_cb);
2809 vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT,
2810 __region_format_changed_cb);
2811 vconf_ignore_key_changed(VCONFKEY_LANGSET,
2813 vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2814 __hw_acceleration_changed_cb);
2817 static int __register_vconf_events(void)
2825 r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc);
2827 _E("Failed to get vconf hw acceleration. err = %d", r);
2829 r = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2830 __hw_acceleration_changed_cb, NULL);
2831 if (r != VCONF_OK) {
2832 _E("Failed to register callback for hw acceleration. err = %d",
2836 lang = vconf_get_str(VCONFKEY_LANGSET);
2838 setenv("LANG", lang, 1);
2842 r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL);
2844 _E("Failed to register callback for langset. err = %d", r);
2846 region = vconf_get_str(VCONFKEY_REGIONFORMAT);
2848 setenv("LC_CTYPE", region, 1);
2852 r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT,
2853 __region_format_changed_cb, NULL);
2855 _E("Failed to register callback for regionformat. err = %d", r);
2857 type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY;
2858 key = _config_get_string_value(type);
2859 type = CONFIG_TYPE_MEMORY_STATUS_LOW_VALUE;
2860 MEMORY_STATUS_LOW = _config_get_int_value(type);
2862 r = vconf_get_int(key, &__memory_status_low);
2864 _E("Failed to get vconf low memory. err = %d", r);
2866 r = vconf_notify_key_changed(key,
2867 __memory_status_low_changed_cb, NULL);
2869 _E("Failed to register callback for low memory. err = %d", r);
2871 type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY;
2872 key = _config_get_string_value(type);
2873 type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_VALUE;
2874 MEMORY_STATUS_NORMAL = _config_get_int_value(type);
2876 r = vconf_get_int(key, &__memory_status_normal);
2878 _E("Failed to get vconf normal memory. err = %d", r);
2880 r = vconf_notify_key_changed(key,
2881 __memory_status_normal_changed_cb, NULL);
2883 _E("Failed to register callback for normal memory. err = %d", r);
2888 static bool __handle_logger(int fd, io_condition_e cond, void *data)
2894 if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
2895 _E("fd(%d), io_condition(%d)", fd, cond);
2896 g_idle_add(__logger_recovery_cb, __logger_channel);
2897 __logger_channel = NULL;
2901 pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
2903 _E("Failed to receive the packet");
2907 if (getuid() != cr.uid) {
2908 _E("Invalid caller");
2912 if (pkt->len <= 0) {
2913 _E("Invalid message");
2917 _E("[%d] %s", cr.pid, (const char *)pkt->data);
2918 _log_print("[ERROR]", "pid(%7d) | message(%s)",
2919 cr.pid, (const char *)pkt->data);
2929 static int __init_logger_fd(void)
2931 io_condition_e cond;
2934 fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK);
2936 _E("Failed to create logger socker");
2940 cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL;
2941 __logger_channel = _io_channel_create(fd, cond, __handle_logger, NULL);
2942 if (!__logger_channel) {
2950 static int __memory_monitor_cb(bool low_memory, void *user_data)
2952 candidate_process_context_t *cpc;
2954 cpc = __get_running_slot(false);
2955 if (!cpc && low_memory)
2960 __update_slots_pss();
2962 candidate_slot_list = g_list_sort(candidate_slot_list,
2966 __pause_last_running_slot(false);
2968 cpc = __get_running_slot(false);
2971 } while (__is_low_memory());
2973 __resume_all_slots();
2979 static gboolean __logger_recovery_cb(gpointer data)
2981 io_channel_h channel = data;
2984 _io_channel_destroy(channel);
2986 ret = __init_logger_fd();
2988 _E("Failed to recover logger socket");
2989 return G_SOURCE_REMOVE;
2992 _E("[__RECOVERY__] Logger socket");
2994 return G_SOURCE_REMOVE;
2997 static gboolean __launchpad_recovery_cb(gpointer data)
2999 io_channel_h channel = data;
3002 _io_channel_destroy(channel);
3004 ret = __init_launchpad_fd(0, NULL);
3006 _E("Failed to recover launchpad socket");
3008 return G_SOURCE_REMOVE;
3011 _E("[__RECOVERY__] Launchpad socket");
3013 return G_SOURCE_REMOVE;
3016 static int __before_loop(int argc, char **argv)
3020 ret = __sequencer_init();
3022 _E("Failed to initialize sequencer");
3026 ret = _signal_init();
3028 _E("Failed to initialize signal");
3032 _signal_set_sigchld_cb(__handle_sigchild, NULL);
3034 ret = __init_launchpad_fd(argc, argv);
3036 _E("__init_launchpad_fd() failed");
3040 ret = __init_logger_fd();
3042 _E("__init_logger_fd() failed");
3046 ret = __init_label_monitor_fd();
3048 _W("Failed to initialize label monitor");
3050 ret = _config_init();
3052 _W("Failed to initialize config");
3056 _W("Failed to initialize dbus");
3060 MAX_CPU_CHECK_COUNT = _config_get_int_value(
3061 CONFIG_TYPE_CPU_CHECKER_MAX_COUNT);
3062 __add_default_slots();
3063 launcher_info_list = _launcher_info_load(LAUNCHER_INFO_PATH);
3065 __add_app_defined_loaders();
3067 ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL);
3069 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL);
3071 __pid_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3074 _E("Failed to create pid table");
3078 __register_vconf_events();
3079 __init_app_defined_loader_monitor();
3080 _memory_monitor_init();
3081 _memory_monitor_set_event_cb(__memory_monitor_cb, NULL);
3087 static void __after_loop(void)
3090 _memory_monitor_fini();
3091 __unregister_vconf_events();
3093 g_hash_table_destroy(__pid_table);
3095 if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0)
3096 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL);
3099 _launcher_info_unload(launcher_info_list);
3103 _loader_info_dispose(app_defined_loader_info_list);
3105 if (__label_monitor_channel)
3106 _io_channel_destroy(__label_monitor_channel);
3109 security_manager_app_labels_monitor_finish(label_monitor);
3111 if (__logger_channel)
3112 _io_channel_destroy(__logger_channel);
3114 if (__launchpad_channel)
3115 _io_channel_destroy(__launchpad_channel);
3122 int main(int argc, char **argv)
3124 GMainLoop *mainloop = NULL;
3126 mainloop = g_main_loop_new(NULL, FALSE);
3128 _E("Failed to create glib main loop");
3132 if (__before_loop(argc, argv) != 0) {
3133 _E("process-pool Initialization failed!");
3137 #ifdef TIZEN_FEATURE_PRIORITY_CHANGE
3140 g_main_loop_run(mainloop);