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 "launchpad_worker.h"
58 #include "loader_info.h"
61 #define AUL_PR_NAME 16
62 #define EXEC_CANDIDATE_EXPIRED 5
63 #define EXEC_CANDIDATE_WAIT 1
64 #define DIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a))
65 #define CANDIDATE_NONE 0
67 #define PROCESS_POOL_LAUNCHPAD_SOCK ".launchpad-process-pool-sock"
68 #define LAUNCHPAD_LOGGER_SOCK ".launchpad-logger-sock"
69 #define LOADER_PATH_DEFAULT "/usr/bin/launchpad-loader"
70 #define LOADER_INFO_PATH "/usr/share/aul"
71 #define OPT_SHARE_PATH "/opt/share"
72 #define LOADERS_PATH "loaders"
73 #define APP_DEFINED_LOADER_INFO_PATH OPT_SHARE_PATH "/" LOADERS_PATH
74 #define COMMON_LOADER_NAME "common-loader1"
76 #define LAUNCHER_INFO_PATH LOADER_INFO_PATH
77 #define REGULAR_UID_MIN 5000
78 #define PAD_ERR_FAILED -1
79 #define PAD_ERR_REJECTED -2
80 #define PAD_ERR_INVALID_ARGUMENT -3
81 #define PAD_ERR_INVALID_PATH -4
82 #define CPU_CHECKER_TIMEOUT 1000
85 #define LOSE_SCORE_RATE 0.7f
87 enum candidate_process_state_e {
88 CANDIDATE_PROCESS_STATE_RUNNING,
89 CANDIDATE_PROCESS_STATE_PAUSED,
95 int pid; /* for hydra this pid is not the pid of hydra itself */
96 /* but pid of non-hydra candidate, which was forked from hydra */
107 int detection_method;
109 unsigned long long cpu_total_time;
110 unsigned long long cpu_idle_time;
118 int activation_method;
119 int deactivation_method;
125 io_channel_h client_channel;
126 io_channel_h channel;
127 io_channel_h hydra_channel;
131 } candidate_process_context_t;
143 candidate_process_context_t *running_cpc;
146 struct app_launch_arg {
148 const char *app_path;
149 appinfo_t *menu_info;
163 struct cleanup_info_s {
168 static int __sys_hwacc;
169 static GList *loader_info_list;
170 static GList *app_defined_loader_info_list;
171 static int user_slot_offset;
172 static GList *candidate_slot_list;
173 static app_labels_monitor *label_monitor;
174 static GList *launcher_info_list;
175 static GHashTable *__pid_table;
176 static int __memory_status_low;
177 static int __memory_status_normal;
178 static sequencer __sequencer;
179 static int MEMORY_STATUS_LOW;
180 static int MEMORY_STATUS_NORMAL;
181 static int MAX_CPU_CHECK_COUNT;
183 static io_channel_h __logger_channel;
184 static io_channel_h __label_monitor_channel;
185 static io_channel_h __launchpad_channel;
187 static candidate_process_context_t *__add_slot(int type, int loader_id,
188 int caller_pid, const char *loader_name,
189 const char *loader_path, const char *extra,
190 int detection_method, int activation_method,
191 int deactivation_method, unsigned int ttl, int timeout_val,
192 int threshold_max, int threshold_min, bool on_boot,
193 bool app_exists, bool is_hydra, bool app_check);
194 static int __remove_slot(int type, int loader_id);
195 static int __add_default_slots(void);
196 static gboolean __handle_idle_checker(gpointer data);
197 static int __add_idle_checker(int detection_method, GList *cur);
198 static void __dispose_candidate_process(candidate_process_context_t *cpc);
199 static bool __is_low_memory(void);
200 static void __update_slot_state(candidate_process_context_t *cpc, int method,
202 static void __init_app_defined_loader_monitor(void);
203 static gboolean __launchpad_recovery_cb(gpointer data);
204 static gboolean __logger_recovery_cb(gpointer data);
206 static gboolean __handle_queuing_slots(gpointer data)
208 candidate_process_context_t *cpc;
209 unsigned long long total = 0;
210 unsigned long long idle = 0;
212 if (__sequencer.idle_checker > 0)
213 return G_SOURCE_CONTINUE;
215 if (g_queue_is_empty(__sequencer.queue)) {
216 __sequencer.timer = 0;
217 return G_SOURCE_REMOVE;
220 cpc = (candidate_process_context_t *)g_queue_pop_head(
223 _E("Critical error!");
224 __sequencer.timer = 0;
225 return G_SOURCE_REMOVE;;
228 if (cpc->app_check && !cpc->app_exists) {
229 _W("The application is not installed. Type(%d)", cpc->type);
230 return G_SOURCE_CONTINUE;
234 g_source_remove(cpc->timer);
238 if (cpc->pid != CANDIDATE_NONE) {
239 _W("The slot(%d) is already running. pid(%d)",
240 cpc->type, cpc->pid);
241 return G_SOURCE_CONTINUE;
244 _get_cpu_idle(&total, &idle);
245 cpc->cpu_idle_time = idle;
246 cpc->cpu_total_time = total;
247 cpc->cpu_check_count = 0;
249 __sequencer.idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT,
250 __handle_idle_checker, cpc);
251 __sequencer.running_cpc = cpc;
253 _D("[__SEQUENCER__] Add idle checker. Type(%d)", cpc->type);
255 return G_SOURCE_CONTINUE;
258 static bool __sequencer_slot_is_running(candidate_process_context_t *cpc)
260 if (__sequencer.running_cpc == cpc)
266 static bool __sequencer_slot_exist(candidate_process_context_t *cpc)
270 found = g_queue_find(__sequencer.queue, cpc);
277 static int __sequencer_add_slot(candidate_process_context_t *cpc)
279 if (__sequencer_slot_exist(cpc)) {
280 _W("Already exists");
284 if (__sequencer_slot_is_running(cpc)) {
285 _W("slot(%d) is running", cpc->type);
289 g_queue_push_tail(__sequencer.queue, cpc);
294 static void __sequencer_remove_slot(candidate_process_context_t *cpc)
296 g_queue_remove(__sequencer.queue, cpc);
299 static void __sequencer_run(void)
301 if (__sequencer.timer)
304 __sequencer.timer = g_timeout_add(500, __handle_queuing_slots, NULL);
305 if (!__sequencer.timer)
306 _E("Failed to add sequencer timer");
309 static void __sequencer_stop(void)
311 if (!__sequencer.timer)
314 g_source_remove(__sequencer.timer);
315 __sequencer.timer = 0;
318 static bool __sequencer_queue_is_empty(void)
320 if (g_queue_is_empty(__sequencer.queue))
326 static int __sequencer_init(void)
328 _D("[__SEQUENCER__] Init");
330 __sequencer.queue = g_queue_new();
331 if (!__sequencer.queue) {
339 static void __sequencer_fini(void)
341 _D("[__SEQUENCER__] Finish");
343 if (__sequencer.idle_checker > 0)
344 g_source_remove(__sequencer.idle_checker);
346 if (__sequencer.timer > 0)
347 g_source_remove(__sequencer.timer);
349 g_queue_free(__sequencer.queue);
352 static int __make_loader_id(void)
354 static int id = PAD_LOADER_ID_DYNAMIC_BASE;
359 static candidate_process_context_t *__find_slot_from_static_type(int type)
361 candidate_process_context_t *cpc;
362 GList *iter = candidate_slot_list;
364 if (type == LAUNCHPAD_LOADER_TYPE_DYNAMIC ||
365 type == LAUNCHPAD_LOADER_TYPE_UNSUPPORTED)
369 cpc = (candidate_process_context_t *)iter->data;
370 if (type == cpc->type)
373 iter = g_list_next(iter);
379 static candidate_process_context_t *__find_slot_from_pid(int pid)
381 candidate_process_context_t *cpc;
382 GList *iter = candidate_slot_list;
385 cpc = (candidate_process_context_t *)iter->data;
389 iter = g_list_next(iter);
395 static candidate_process_context_t *__find_hydra_slot_from_pid(int pid)
397 candidate_process_context_t *cpc;
398 GList *iter = candidate_slot_list;
401 cpc = (candidate_process_context_t *)iter->data;
402 if (cpc->is_hydra && pid == cpc->hydra_pid)
405 iter = g_list_next(iter);
411 static candidate_process_context_t *__find_slot_from_caller_pid(int caller_pid)
413 candidate_process_context_t *cpc;
414 GList *iter = candidate_slot_list;
417 cpc = (candidate_process_context_t *)iter->data;
418 if (caller_pid == cpc->caller_pid)
421 iter = g_list_next(iter);
427 static candidate_process_context_t *__find_slot_from_loader_id(int id)
429 candidate_process_context_t *cpc;
430 GList *iter = candidate_slot_list;
433 cpc = (candidate_process_context_t *)iter->data;
434 if (id == cpc->loader_id)
437 iter = g_list_next(iter);
443 static candidate_process_context_t *__find_slot_from_loader_name(const char *loader_name)
445 candidate_process_context_t *cpc;
446 GList *iter = candidate_slot_list;
449 cpc = (candidate_process_context_t *)iter->data;
450 if (strcmp(cpc->loader_name, loader_name) == 0)
453 iter = g_list_next(iter);
459 static candidate_process_context_t *__find_slot(int type, int loader_id)
461 if (type == LAUNCHPAD_LOADER_TYPE_DYNAMIC)
462 return __find_slot_from_loader_id(loader_id);
464 return __find_slot_from_static_type(type);
467 static void __update_slot_score(candidate_process_context_t *slot)
472 slot->score *= LOSE_SCORE_RATE;
473 slot->score += WIN_SCORE;
476 static void __update_slots_pss(void)
478 candidate_process_context_t *cpc;
481 iter = candidate_slot_list;
483 cpc = (candidate_process_context_t *)iter->data;
484 iter = g_list_next(iter);
486 if (cpc->pid == CANDIDATE_NONE)
489 _proc_get_mem_pss(cpc->pid, &cpc->pss);
493 static gint __compare_slot(gconstpointer a, gconstpointer b)
495 candidate_process_context_t *slot_a = (candidate_process_context_t *)a;
496 candidate_process_context_t *slot_b = (candidate_process_context_t *)b;
498 if (slot_a->is_hydra && !slot_b->is_hydra)
500 if (!slot_a->is_hydra && slot_b->is_hydra)
503 if (slot_a->score < slot_b->score)
505 if (slot_a->score > slot_b->score)
508 if (slot_a->pss < slot_b->pss)
510 if (slot_a->pss > slot_b->pss)
516 static candidate_process_context_t *__get_running_slot(bool is_hydra)
518 candidate_process_context_t *cpc;
521 iter = candidate_slot_list;
523 cpc = (candidate_process_context_t *)iter->data;
524 if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE)
527 iter = g_list_next(iter);
533 static void __pause_last_running_slot(bool is_hydra)
535 candidate_process_context_t *cpc = NULL;
538 iter = g_list_last(candidate_slot_list);
540 cpc = (candidate_process_context_t *)iter->data;
541 if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE)
544 iter = g_list_previous(iter);
550 __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, true);
553 static void __resume_all_slots(void)
555 candidate_process_context_t *cpc;
558 iter = candidate_slot_list;
560 cpc = (candidate_process_context_t *)iter->data;
561 __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, false);
563 iter = g_list_next(iter);
567 static void __kill_process(int pid)
569 char err_str[MAX_LOCAL_BUFSZ] = { 0, };
571 if (kill(pid, SIGKILL) == -1) {
572 _E("send SIGKILL: %s",
573 strerror_r(errno, err_str, sizeof(err_str)));
577 static void __refuse_candidate_process(int server_fd)
581 if (server_fd == -1) {
582 _E("arguments error!");
586 client_fd = accept(server_fd, NULL, NULL);
587 if (client_fd == -1) {
593 _D("refuse connection!");
599 static int __accept_candidate_process(int server_fd, int *out_client_fd,
600 int *out_client_pid, int cpc_pid)
606 struct ucred cred = {};
608 if (server_fd == -1 || out_client_fd == NULL ||
609 out_client_pid == NULL) {
610 _E("arguments error!");
614 client_fd = accept(server_fd, NULL, NULL);
615 if (client_fd == -1) {
620 if (_set_sock_option(client_fd, 1) < 0) {
621 _E("Failed to set sock option");
625 ret = recv(client_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL);
632 ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &len);
634 _E("getsockopt error");
638 if (cpc_pid != -1 && cred.pid != cpc_pid) {
639 _E("Invalid accept. pid(%d)", cred.pid);
643 if (cred.pid != recv_pid)
644 _W("Not equal recv and real pid");
646 *out_client_fd = client_fd;
647 *out_client_pid = cred.pid;
649 return *out_client_fd;
658 static int __listen_addr(struct sockaddr_un *addr)
661 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
667 unlink(addr->sun_path);
669 _D("bind to %s", addr->sun_path);
670 if (bind(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_un)) < 0) {
675 _D("listen to %s", addr->sun_path);
676 if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) {
681 SECURE_LOGD("[launchpad] done, listen fd: %d", fd);
691 static int __listen_candidate_process(int type, int loader_id)
693 struct sockaddr_un addr;
695 _D("[launchpad] enter, type: %d", type);
697 memset(&addr, 0x00, sizeof(struct sockaddr_un));
698 addr.sun_family = AF_UNIX;
699 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%u/%s%d-%d",
700 SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME,
703 return __listen_addr(&addr);
706 static int __listen_hydra_process(int type, int loader_id)
708 struct sockaddr_un addr;
710 _D("[launchpad] enter, type: %d", type);
712 memset(&addr, 0x00, sizeof(struct sockaddr_un));
713 addr.sun_family = AF_UNIX;
714 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%d/%s%d-%d",
715 SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME,
718 return __listen_addr(&addr);
721 static int __get_loader_id(bundle *kb)
725 val = bundle_get_val(kb, AUL_K_LOADER_ID);
728 _W("Requested loader id: %s", val);
733 static int __candidate_process_real_launch(int candidate_fd, app_pkt_t *pkt)
735 return _send_pkt_raw(candidate_fd, pkt);
738 static int __real_send(int clifd, int ret)
741 _E("Invalid parameter. clifd(%d)", clifd);
745 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
746 if (errno == EPIPE) {
747 _E("send failed due to EPIPE.");
751 _E("send fail to client");
758 static void __send_result_to_caller(int clifd, int ret, const char *app_path)
760 _W("send result: %d", ret);
766 _E("launching failed");
767 __real_send(clifd, ret);
771 if (__real_send(clifd, ret) < 0)
775 static int __fork_app_process(int (*child_fn)(void *), void *arg)
783 _E("failed to fork child process");
788 _W("security_manager_prepare_app_candidate ++");
789 ret = security_manager_prepare_app_candidate();
790 _W("security_manager_prepare_app_candidate --");
791 if (ret != SECURITY_MANAGER_SUCCESS) {
792 _E("failed to prepare app candidate process (%d)", ret);
797 _E("failed to exec app process (%d)", errno);
804 static int __exec_loader_process(void *arg)
809 _signal_unblock_sigchld();
811 _setup_stdio(basename(argv[LOADER_ARG_PATH]));
813 if (execv(argv[LOADER_ARG_PATH], argv) < 0) {
814 _send_message_to_logger(argv[LOADER_ARG_PATH],
815 "Failed to prepare candidate process. error(%d:%s)",
816 errno, strerror_r(errno, err_buf, sizeof(err_buf)));
818 _D("Succeeded to prepare candidate_process");
824 static gboolean __handle_deactivate_event(gpointer user_data)
826 candidate_process_context_t *cpc;
828 cpc = (candidate_process_context_t *)user_data;
829 __update_slot_state(cpc, METHOD_TTL, false);
830 _D("Deactivate event: type(%d)", cpc->type);
832 return G_SOURCE_REMOVE;
835 static void __set_live_timer(candidate_process_context_t *cpc)
840 if (cpc->deactivation_method & METHOD_TTL) {
841 if (cpc->live_timer == 0) {
842 cpc->live_timer = g_timeout_add_seconds(cpc->ttl,
843 __handle_deactivate_event, cpc);
848 static int __hydra_send_request(int fd, enum hydra_cmd cmd)
851 int size = sizeof(cmd);
854 while (sent != size) {
855 send_ret = send(fd, (char *)&cmd + sent,
856 size - sent, MSG_NOSIGNAL);
857 if (send_ret == -1) {
858 _E("send error! (%d)", errno);
863 _D("send(%d: ret: %d) : %d / %d",
864 fd, send_ret, sent, size);
870 static int __hydra_send_launch_candidate_request(int fd)
872 SECURE_LOGD("Send launch cmd to hydra, fd: %d", fd);
873 return __hydra_send_request(fd, LAUNCH_CANDIDATE);
876 static int __prepare_candidate_process(int type, int loader_id)
879 char type_str[12] = {0, };
880 char loader_id_str[12] = {0, };
881 char argbuf[LOADER_ARG_LEN];
882 char *argv[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
883 candidate_process_context_t *cpt = __find_slot(type, loader_id);
888 if (cpt->is_hydra && cpt->hydra_pid != HYDRA_NONE)
889 return __hydra_send_launch_candidate_request(cpt->hydra_fd);
891 _D("prepare candidate process / type:%d", type);
892 memset(argbuf, ' ', LOADER_ARG_LEN);
893 argbuf[LOADER_ARG_LEN - 1] = '\0';
894 argv[LOADER_ARG_DUMMY] = argbuf;
896 cpt->last_exec_time = time(NULL);
898 snprintf(loader_id_str, sizeof(loader_id_str), "%d", loader_id);
899 snprintf(type_str, sizeof(type_str), "%d", type);
900 argv[LOADER_ARG_PATH] = cpt->loader_path;
901 argv[LOADER_ARG_TYPE] = type_str;
902 argv[LOADER_ARG_ID] = loader_id_str;
903 argv[LOADER_ARG_HYDRA] = cpt->is_hydra ? "1" : "0";
904 argv[LOADER_ARG_EXTRA] = cpt->loader_extra;
906 pid = __fork_app_process(__exec_loader_process, argv);
908 _E("Failed to fork candidate_process");
913 cpt->hydra_pid = pid;
916 __set_live_timer(cpt);
919 _log_print("[CANDIDATE]", "pid(%7d) | type(%d) | loader(%s)",
920 pid, cpt->loader_id, cpt->loader_name);
921 _memory_monitor_reset_timer();
926 static gboolean __handle_timeout_event(gpointer user_data)
928 candidate_process_context_t *cpc;
930 cpc = (candidate_process_context_t *)user_data;
933 if (cpc->pid != CANDIDATE_NONE) {
934 _W("Candidate(%d) process(%d) is running", cpc->type, cpc->pid);
935 return G_SOURCE_REMOVE;
938 __sequencer_add_slot(cpc);
940 return G_SOURCE_REMOVE;
943 static void __set_timer(candidate_process_context_t *cpc)
945 if (cpc == NULL || cpc->timer > 0)
948 if ((cpc->detection_method & METHOD_TIMEOUT) &&
949 cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) {
950 cpc->timer = g_timeout_add(cpc->timeout_val,
951 __handle_timeout_event, cpc);
955 static void __reset_slot(candidate_process_context_t *cpc)
961 cpc->prepared = false;
962 cpc->pid = CANDIDATE_NONE;
963 cpc->client_channel = NULL;
968 static void __dispose_candidate_process(candidate_process_context_t *cpc)
973 _D("Dispose candidate process %d", cpc->type);
975 _D("kill process %d", cpc->pid);
976 __kill_process(cpc->pid);
978 if (cpc->live_timer > 0)
979 g_source_remove(cpc->live_timer);
980 if (cpc->client_channel)
981 _io_channel_destroy(cpc->client_channel);
983 g_source_remove(cpc->timer);
984 if (cpc->send_fd > 0)
989 static void __dispose_hydra_process(candidate_process_context_t *cpc)
994 __dispose_candidate_process(cpc);
996 _D("Dispose hydra process %d", cpc->type);
997 if (cpc->hydra_pid > 0) {
998 _D("kill process %d", cpc->hydra_pid);
999 __kill_process(cpc->hydra_pid);
1000 cpc->hydra_pid = HYDRA_NONE;
1003 if (cpc->hydra_fd > 0) {
1004 close(cpc->hydra_fd);
1009 static int __send_launchpad_loader(candidate_process_context_t *cpc,
1010 app_pkt_t *pkt, const char *app_path, int clifd)
1015 ret = _delete_sock_path(cpc->pid, getuid());
1019 __candidate_process_real_launch(cpc->send_fd, pkt);
1020 SECURE_LOGD("Request to candidate process, pid: %d, bin path: %s",
1021 cpc->pid, app_path);
1024 cpc->pid = CANDIDATE_NONE;
1025 __dispose_candidate_process(cpc);
1027 __update_slot_score(cpc);
1032 static int __normal_fork_exec(int argc, char **argv, const char *app_path)
1037 _D("start real fork and exec");
1039 libdir = _get_libdir(app_path);
1041 setenv("LD_LIBRARY_PATH", libdir, 1);
1047 if (execv(argv[LOADER_ARG_PATH], argv) < 0) { /* Flawfinder: ignore */
1048 _send_message_to_logger(argv[LOADER_ARG_PATH],
1049 "Failed to execute a file. error(%d:%s)",
1050 errno, strerror_r(errno, err_buf, sizeof(err_buf)));
1057 static int __create_launcher_argv(int *argc, char ***argv, const char *app_type)
1060 char **launcher_argv;
1061 launcher_info_h launcher_info;
1063 const char *extra_arg;
1068 launcher_info = _launcher_info_find(launcher_info_list, app_type);
1069 if (launcher_info == NULL)
1072 exe = _launcher_info_get_exe(launcher_info);
1074 _E("Failed to get launcher exe");
1078 extra_args = _launcher_info_get_extra_args(launcher_info);
1079 launcher_argc = g_list_length(extra_args) + 1;
1080 launcher_argv = (char **)calloc(launcher_argc, sizeof(char *));
1081 if (launcher_argv == NULL) {
1082 _E("out of memory");
1086 i = LOADER_ARG_PATH;
1087 launcher_argv[i++] = strdup(exe);
1089 iter = g_list_first(extra_args);
1091 extra_arg = (const char *)iter->data;
1093 launcher_argv[i++] = strdup(extra_arg);
1095 iter = g_list_next(iter);
1098 *argc = launcher_argc;
1099 *argv = launcher_argv;
1105 static void __destroy_launcher_argv(int argc, char **argv)
1112 for (i = 0; i < argc; i++)
1117 static int __create_app_argv(int *argc, char ***argv, const char *app_path,
1118 bundle *kb, const char *app_type)
1122 bool attach = false;
1123 struct app_arg debug_arg = {0,};
1124 struct app_arg launcher_arg = {0,};
1125 struct app_arg arg = {0,};
1126 struct app_arg debug_extra_arg = {0,};
1131 ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach);
1133 _E("Failed to create debugger argv");
1138 *argc = debug_arg.argc;
1139 *argv = debug_arg.argv;
1143 ret = _debug_create_extra_argv(&debug_extra_arg.argc,
1144 &debug_extra_arg.argv);
1146 _E("Failed to create debugger extra argv");
1147 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1151 ret = __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv,
1154 _E("Failed to create launcher argv");
1155 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1156 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1160 arg.argc = bundle_export_to_argv(kb, &arg.argv);
1161 if (arg.argc <= 0) {
1162 _E("Failed to export bundle");
1163 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
1164 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1165 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1168 arg.argv[LOADER_ARG_PATH] = strdup(app_path);
1170 new_argc = debug_arg.argc + launcher_arg.argc + arg.argc +
1171 debug_extra_arg.argc;
1172 if (new_argc == arg.argc) {
1178 new_argv = (char **)calloc(new_argc + 1, sizeof(char *));
1179 if (new_argv == NULL) {
1180 _E("out of memory");
1181 free(arg.argv[LOADER_ARG_PATH]);
1182 bundle_free_exported_argv(arg.argc, &arg.argv);
1183 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
1184 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1185 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1189 c = LOADER_ARG_PATH;
1190 for (i = 0; i < debug_arg.argc; i++)
1191 new_argv[c++] = debug_arg.argv[i];
1192 for (i = 0; i < launcher_arg.argc; i++)
1193 new_argv[c++] = launcher_arg.argv[i];
1194 for (i = 0; i < arg.argc; i++)
1195 new_argv[c++] = arg.argv[i];
1196 for (i = 0; i < debug_extra_arg.argc; i++)
1197 new_argv[c++] = debug_extra_arg.argv[i];
1205 static void __real_launch(const char *app_path, bundle *kb,
1206 appinfo_t *menu_info)
1213 if (bundle_get_val(kb, AUL_K_DEBUG) != NULL)
1214 putenv("TIZEN_DEBUGGING_PORT=1");
1216 ret = __create_app_argv(&app_argc, &app_argv, app_path,
1217 kb, menu_info->app_type);
1219 _E("Failed to create app argv");
1223 for (i = 0; i < app_argc; i++)
1224 SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
1226 PERF("setup argument done");
1227 __normal_fork_exec(app_argc, app_argv, app_path);
1230 static int __prepare_exec(const char *appid, const char *app_path,
1231 appinfo_t *menu_info, bundle *kb)
1234 char process_name[AUL_PR_NAME];
1237 /* Set new session ID & new process group ID*/
1238 /* In linux, child can set new session ID without check permission */
1239 /* TODO : should be add to check permission in the kernel*/
1242 ret = _launchpad_plugin_prepare_app(appid, kb);
1244 _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret);
1245 return PAD_ERR_FAILED;
1248 ret = _enable_external_pkg(kb, menu_info->pkgid,
1249 menu_info->global ? GLOBAL_USER : getuid());
1251 return PAD_ERR_FAILED;
1253 if (menu_info->global)
1254 ret = trust_anchor_launch(menu_info->pkgid, GLOBAL_USER);
1256 ret = trust_anchor_launch(menu_info->pkgid, getuid());
1257 if (ret != TRUST_ANCHOR_ERROR_NONE &&
1258 ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) {
1259 _E("trust_anchor_launch() returns %d", ret);
1260 return PAD_ERR_REJECTED;
1264 _W("security_manager_prepare_app ++");
1265 ret = security_manager_prepare_app(appid);
1266 _W("security_manager_prepare_app --");
1267 if (ret != SECURITY_MANAGER_SUCCESS)
1268 return PAD_ERR_REJECTED;
1270 _send_cmd_to_amd(APP_STARTUP_SIGNAL);
1271 if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE)
1272 _setup_stdio(basename(app_path));
1274 /* SET DUMPABLE - for coredump*/
1275 prctl(PR_SET_DUMPABLE, 1);
1277 /* SET PROCESS NAME*/
1278 if (app_path == NULL)
1279 return PAD_ERR_INVALID_ARGUMENT;
1281 file_name = strrchr(app_path, '/');
1282 if (file_name == NULL)
1283 return PAD_ERR_INVALID_PATH;
1286 if (*file_name == '\0')
1287 return PAD_ERR_INVALID_PATH;
1289 memset(process_name, '\0', AUL_PR_NAME);
1290 snprintf(process_name, AUL_PR_NAME, "%s", file_name);
1291 prctl(PR_SET_NAME, process_name);
1294 _set_env(menu_info, kb);
1296 ret = _wait_tep_mount(kb);
1298 return PAD_ERR_FAILED;
1300 if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) {
1301 ret = _prepare_app_socket();
1303 return PAD_ERR_FAILED;
1305 ret = _prepare_id_file();
1307 return PAD_ERR_FAILED;
1313 static int __exec_app_process(void *arg)
1315 struct app_launch_arg *launch_arg = arg;
1318 _print_hwc_log("%d|after calling fork(). %s",
1319 getpid(), launch_arg->appid);
1321 _D("lock up test log(no error) : fork done");
1323 if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1324 _debug_prepare_debugger(launch_arg->kb);
1326 _signal_unblock_sigchld();
1328 _delete_sock_path(getpid(), getuid());
1330 PERF("prepare exec - first done");
1331 ret = __prepare_exec(launch_arg->appid, launch_arg->app_path,
1332 launch_arg->menu_info, launch_arg->kb);
1336 PERF("prepare exec - second done");
1337 __real_launch(launch_arg->app_path, launch_arg->kb,
1338 launch_arg->menu_info);
1340 return PAD_ERR_FAILED;
1343 static int __launch_directly(const char *appid, const char *app_path, int clifd,
1344 bundle *kb, appinfo_t *menu_info,
1345 candidate_process_context_t *cpc)
1347 struct app_launch_arg arg;
1351 arg.app_path = app_path;
1352 arg.menu_info = menu_info;
1355 _print_hwc_log("before calling fork(). %s", appid);
1356 pid = __fork_app_process(__exec_app_process, &arg);
1358 _E("failed to fork app process");
1360 SECURE_LOGD("==> real launch pid : %d %s", pid, app_path);
1365 static int __create_sock_activation(void)
1368 char launchpad_process_pool_sock_path[108];
1371 fds = sd_listen_fds(0);
1372 snprintf(launchpad_process_pool_sock_path,
1373 sizeof(launchpad_process_pool_sock_path), "%s/daemons/%u/%s",
1374 SOCKET_PATH, getuid(), PROCESS_POOL_LAUNCHPAD_SOCK);
1376 for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + fds; ++i) {
1377 if (sd_is_socket_unix(i, SOCK_STREAM, 1,
1378 launchpad_process_pool_sock_path, 0) > 0)
1382 _W("There is no socket stream");
1386 static int __launchpad_pre_init(int argc, char **argv)
1390 /* create launchpad sock */
1391 fd = __create_sock_activation();
1393 fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK);
1395 _E("server sock error %d", fd);
1403 static bool __handle_loader_client_event(int fd, io_condition_e cond,
1406 candidate_process_context_t *cpc = data;
1411 if (cond & (IO_HUP | IO_NVAL)) {
1412 SECURE_LOGE("Type %d candidate process was "
1413 "(POLLHUP|POLLNVAL), pid: %d",
1414 cpc->type, cpc->pid);
1415 cpc->pid = CANDIDATE_NONE;
1416 __dispose_candidate_process(cpc);
1417 __prepare_candidate_process(cpc->type, cpc->loader_id);
1425 static bool __handle_hydra_client_event(int fd, io_condition_e cond,
1428 candidate_process_context_t *cpc = data;
1433 if (cond & (IO_HUP | IO_NVAL)) {
1434 SECURE_LOGE("Type %d hydra process was "
1435 "(POLLHUP|POLLNVAL), pid: %d",
1436 cpc->type, cpc->hydra_pid);
1437 __dispose_hydra_process(cpc);
1438 __prepare_candidate_process(cpc->type, cpc->loader_id);
1445 static bool __handle_loader_event(int fd, io_condition_e cond, void *data)
1447 candidate_process_context_t *cpc = data;
1455 if (!cpc->prepared) {
1456 ret = __accept_candidate_process(fd, &client_fd, &client_pid,
1457 cpc->is_hydra ? -1 : cpc->pid);
1459 /* for hydra need to set pid to pid of non-hydra candidate, */
1460 /* which is connecting now */
1462 cpc->pid = client_pid;
1464 cpc->prepared = true;
1465 cpc->send_fd = client_fd;
1467 SECURE_LOGD("Type %d candidate process was connected, "
1468 "pid: %d", cpc->type, cpc->pid);
1469 cpc->client_channel = _io_channel_create(client_fd,
1471 __handle_loader_client_event,
1473 if (!cpc->client_channel)
1477 __refuse_candidate_process(fd);
1478 _E("Refused candidate process connection");
1484 static bool __handle_hydra_event(int fd, io_condition_e cond, void *data)
1486 candidate_process_context_t *cpc = data;
1494 if (!cpc->prepared) {
1495 ret = __accept_candidate_process(fd, &client_fd, &client_pid,
1498 cpc->hydra_fd = client_fd;
1500 SECURE_LOGD("Type %d hydra process was connected,"
1501 " pid: %d", cpc->type, cpc->hydra_pid);
1503 cpc->client_channel = _io_channel_create(client_fd,
1505 __handle_hydra_client_event,
1507 if (!cpc->client_channel)
1511 __refuse_candidate_process(fd);
1512 _E("Refused hydra process connection");
1518 static void __destroy_cleanup_info(struct cleanup_info_s *info)
1527 static struct cleanup_info_s *__create_cleanup_info(const char *appid, int pid)
1529 struct cleanup_info_s *info;
1531 info = malloc(sizeof(struct cleanup_info_s));
1533 _E("Out of memory");
1537 info->appid = strdup(appid);
1539 _E("strdup(%s) is failed", appid);
1540 __destroy_cleanup_info(info);
1549 static bool __cleanup_app_cb(void *user_data)
1551 struct cleanup_info_s *info = (struct cleanup_info_s *)user_data;
1553 _W("security_manager_cleanup_app() ++");
1554 security_manager_cleanup_app(info->appid, getuid(), info->pid);
1555 _W("security_manager_cleanup_app() --");
1556 __destroy_cleanup_info(info);
1560 static void __handle_sigchild(int pid, void *user_data)
1562 candidate_process_context_t *cpc;
1563 struct cleanup_info_s *info;
1567 appid = g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid));
1569 info = __create_cleanup_info(appid, pid);
1571 ret = _worker_add_job(__cleanup_app_cb, info);
1574 __destroy_cleanup_info(info);
1575 _W("security_manager_cleanup_app() ++");
1576 security_manager_cleanup_app(appid, getuid(), pid);
1577 _W("security_manager_cleanup_app() --");
1580 g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid));
1583 _log_print("[SIGCHLD]", "pid(%7d)", pid);
1584 cpc = __find_slot_from_pid(pid);
1586 cpc->pid = CANDIDATE_NONE;
1587 __dispose_candidate_process(cpc);
1588 __prepare_candidate_process(cpc->type, cpc->loader_id);
1590 cpc = __find_hydra_slot_from_pid(pid);
1592 cpc->hydra_pid = HYDRA_NONE;
1593 __dispose_hydra_process(cpc);
1594 __prepare_candidate_process(cpc->type, cpc->loader_id);
1598 cpc = __find_slot_from_caller_pid(pid);
1600 __remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, cpc->loader_id);
1601 cpc = __find_slot_from_caller_pid(pid);
1605 static bool __handle_label_monitor(int fd, io_condition_e cond, void *data)
1607 candidate_process_context_t *cpc;
1608 GList *iter = candidate_slot_list;
1610 if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
1611 _E("fd(%d), io_condition(%d)", fd, cond);
1616 _D("fd(%d) condition(%d)", fd, cond);
1617 _log_print("[LABEL]", "fd(%d), condition(%d)", fd, cond);
1618 security_manager_app_labels_monitor_process(label_monitor);
1621 cpc = (candidate_process_context_t *)iter->data;
1622 if (cpc->is_hydra) {
1623 if (cpc->hydra_pid > 0) {
1624 __dispose_hydra_process(cpc);
1625 __prepare_candidate_process(cpc->type,
1628 } else if (cpc->pid > 0) {
1629 __dispose_candidate_process(cpc);
1630 __prepare_candidate_process(cpc->type, cpc->loader_id);
1633 iter = g_list_next(iter);
1639 static float __interpolator(float input, int cpu_max, int cpu_min)
1642 float min = cpu_min / 100.0f;
1643 float max = cpu_max / 100.0f;
1650 ret = cos(input * PI) / 2.0f + 0.5f;
1657 static void __update_threshold(candidate_process_context_t *cpc, float delta)
1659 static float pos = 0.0f;
1668 cpc->threshold = (int)(__interpolator(pos,
1669 cpc->threshold_max, cpc->threshold_min) * 100);
1670 _D("[CPU] type:%d / delta:%f / input cursor : %f / threshold : %d",
1671 cpc->type, delta, pos, cpc->threshold);
1674 static gboolean __handle_idle_checker(gpointer data)
1676 unsigned long long total = 0;
1677 unsigned long long idle = 0;
1679 candidate_process_context_t *cpc;
1682 _E("Critical error!");
1683 __sequencer.idle_checker = 0;
1684 __sequencer.running_cpc = NULL;
1685 return G_SOURCE_REMOVE;
1688 cpc = (candidate_process_context_t *)data;
1689 if (cpc->app_check && !cpc->app_exists) {
1690 _W("The application is not installed. loader(%s:%d)",
1691 cpc->loader_name, cpc->type);
1692 __sequencer.idle_checker = 0;
1693 __sequencer.running_cpc = NULL;
1694 return G_SOURCE_REMOVE;
1697 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1698 _W("Slot state is not running. loader(%s:%d)",
1699 cpc->loader_name, cpc->type);
1700 __sequencer.idle_checker = 0;
1701 __sequencer.running_cpc = NULL;
1702 return G_SOURCE_REMOVE;
1705 _get_cpu_idle(&total, &idle);
1706 if (total == cpc->cpu_total_time)
1709 per = (idle - cpc->cpu_idle_time) * 100 / (total - cpc->cpu_total_time);
1710 _D("[CPU] Idle : %d / loader(%s:%d)", per, cpc->loader_name, cpc->type);
1712 if (per >= cpc->threshold) {
1713 __update_threshold(cpc, -0.02f * (per - cpc->threshold));
1714 __prepare_candidate_process(cpc->type, cpc->loader_id);
1715 cpc->touched = true;
1716 __sequencer.idle_checker = 0;
1717 __sequencer.running_cpc = NULL;
1718 return G_SOURCE_REMOVE;
1721 cpc->cpu_idle_time = idle;
1722 cpc->cpu_total_time = total;
1723 __update_threshold(cpc, 0.05f);
1725 cpc->cpu_check_count++;
1726 if (cpc->cpu_check_count == MAX_CPU_CHECK_COUNT) {
1727 _W("CPU check count has exceeded %d times. loader(%s:%d)",
1728 cpc->cpu_check_count,
1731 __sequencer.idle_checker = 0;
1732 __sequencer.running_cpc = NULL;
1733 __sequencer_add_slot(cpc);
1734 return G_SOURCE_REMOVE;
1737 return G_SOURCE_CONTINUE;
1740 static int __add_idle_checker(int detection_method, GList *cur)
1742 candidate_process_context_t *cpc;
1746 cpc = (candidate_process_context_t *)iter->data;
1747 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1748 iter = g_list_next(iter);
1752 if (strcmp("null", cpc->loader_path) == 0) {
1753 iter = g_list_next(iter);
1757 if (!cpc->touched && !cpc->on_boot) {
1758 iter = g_list_next(iter);
1762 if (cpc->app_check && !cpc->app_exists) {
1763 iter = g_list_next(iter);
1767 if (cpc->pid == CANDIDATE_NONE &&
1769 (cpc->detection_method & detection_method))) {
1770 if (cpc->timer > 0) {
1771 g_source_remove(cpc->timer);
1775 cpc->cur_event = detection_method;
1776 __sequencer_add_slot(cpc);
1780 iter = g_list_next(iter);
1786 static int __dispatch_cmd_hint(bundle *kb, int detection_method)
1788 _W("cmd hint %d", detection_method);
1789 __add_idle_checker(detection_method, candidate_slot_list);
1794 static int __dispatch_cmd_add_loader(bundle *kb)
1796 const char *add_slot_str = NULL;
1797 const char *caller_pid = NULL;
1801 candidate_process_context_t *cpc;
1803 _W("cmd add loader");
1804 add_slot_str = bundle_get_val(kb, AUL_K_LOADER_PATH);
1805 caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID);
1806 extra = bundle_get_val(kb, AUL_K_LOADER_EXTRA);
1808 if (add_slot_str && caller_pid) {
1809 lid = __make_loader_id();
1811 size = snprintf(0, 0, "%s%s%d", add_slot_str, caller_pid, lid);
1812 loader_name = (char *)malloc(size + 1);
1813 if (loader_name == NULL) {
1814 _E("Out of memory");
1818 snprintf(loader_name, size, "%s%s%d", add_slot_str, caller_pid, lid);
1820 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid,
1821 atoi(caller_pid), loader_name,
1822 add_slot_str, extra,
1823 METHOD_TIMEOUT | METHOD_VISIBILITY,
1824 METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
1825 METHOD_TTL | METHOD_OUT_OF_MEMORY,
1828 DEFAULT_CPU_THRESHOLD_MAX,
1829 DEFAULT_CPU_THRESHOLD_MIN,
1842 static int __dispatch_cmd_add_app_defined_loader(bundle *kb)
1844 const char *loader_name;
1846 candidate_process_context_t *cpc;
1847 loader_info_t *info;
1850 _W("cmd add defined loader");
1851 loader_name = bundle_get_val(kb, AUL_K_LOADER_NAME);
1853 if (loader_name == NULL) {
1854 _E("loader_name is NULL");
1858 info = _loader_info_find_loader_by_loader_name(
1859 app_defined_loader_info_list, loader_name);
1860 if (info == NULL || info->extra == NULL) {
1861 _E("loader_name %s, info %d", loader_name, info != NULL);
1866 cpc = __find_slot_from_loader_name(loader_name);
1868 lid = __make_loader_id();
1869 bundle_encode(info->extra, &extra, &len);
1870 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid, 0,
1871 loader_name, "/usr/bin/app-defined-loader", (const char *)extra,
1872 METHOD_TIMEOUT | METHOD_VISIBILITY,
1873 METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
1874 METHOD_TTL | METHOD_OUT_OF_MEMORY,
1877 DEFAULT_CPU_THRESHOLD_MAX,
1878 DEFAULT_CPU_THRESHOLD_MIN,
1884 bundle_free_encoded_rawdata(&extra);
1890 lid = cpc->loader_id;
1893 if (cpc->pid == CANDIDATE_NONE)
1894 __prepare_candidate_process(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid);
1899 static int __dispatch_cmd_remove_loader(bundle *kb)
1901 const char *id = bundle_get_val(kb, AUL_K_LOADER_ID);
1904 _W("cmd remove loader");
1907 if (__remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid) == 0)
1914 static int __check_caller_by_pid(int pid)
1917 char buf[PATH_MAX] = { 0, };
1919 ret = _proc_get_attr(pid, buf, sizeof(buf));
1923 if (strcmp(buf, "User") == 0 ||
1924 strcmp(buf, "System") == 0 ||
1925 strcmp(buf, "System::Privileged") == 0)
1931 static bool __is_hw_acc(const char *hwacc)
1933 if (strcmp(hwacc, "USE") == 0 ||
1934 (strcmp(hwacc, "SYS") == 0 &&
1935 __sys_hwacc == SETTING_HW_ACCELERATION_ON))
1941 static candidate_process_context_t *__find_available_slot(const char *hwacc,
1942 const char *app_type, const char *loader_name,
1943 candidate_process_context_t **org_cpc)
1946 candidate_process_context_t *cpc;
1952 type = _loader_info_find_type_by_loader_name(loader_info_list,
1955 type = _loader_info_find_type(loader_info_list,
1956 app_type, __is_hw_acc(hwacc));
1958 cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1967 a_types = _loader_get_alternative_types(loader_info_list, type, &len);
1971 for (i = 0; i < len; i++) {
1972 cpc = __find_slot(a_types[i], PAD_LOADER_ID_STATIC);
1975 if (cpc->prepared) {
1985 static void __update_slot(int type, bool app_exists)
1987 candidate_process_context_t *cpc;
1989 cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1993 cpc->app_exists = app_exists;
1994 if (cpc->app_check && !cpc->app_exists) {
1996 __dispose_candidate_process(cpc);
1997 __sequencer_remove_slot(cpc);
1998 if (__sequencer_queue_is_empty())
2001 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING)
2004 if (!cpc->touched && !cpc->on_boot)
2007 if (cpc->timer > 0) {
2008 g_source_remove(cpc->timer);
2012 if (cpc->pid == CANDIDATE_NONE) {
2013 __sequencer_add_slot(cpc);
2019 static void __foreach_loader_info(loader_info_t *info, void *data)
2021 struct app_info *ai = (struct app_info *)data;
2024 exist = _loader_info_exist_app_type(info, ai->type);
2028 info->app_exists = ai->exists;
2029 __update_slot(info->type, info->app_exists);
2032 static int __dispatch_cmd_update_app_type(bundle *b)
2035 struct app_info info;
2036 const char *is_installed;
2038 info.type = bundle_get_val(b, AUL_K_APP_TYPE);
2042 is_installed = bundle_get_val(b, AUL_K_IS_INSTALLED);
2043 if (is_installed && !strcmp(is_installed, "true"))
2046 info.exists = false;
2048 _I("[LAUNCHPAD] type(%s), exists(%d)", info.type, info.exists);
2050 r = _loader_info_foreach(loader_info_list, __foreach_loader_info,
2053 _E("Failed to retrieve loader info");
2060 static void __deactivate_slot(candidate_process_context_t *cpc)
2062 if (cpc->state == CANDIDATE_PROCESS_STATE_PAUSED)
2065 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2066 __dispose_candidate_process(cpc);
2069 static void __activate_slot(candidate_process_context_t *cpc)
2071 if (cpc->state == CANDIDATE_PROCESS_STATE_RUNNING)
2074 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2075 if (!cpc->touched && !cpc->on_boot)
2078 if ((cpc->app_check && !cpc->app_exists) || cpc->pid > CANDIDATE_NONE)
2081 if (cpc->detection_method & METHOD_TIMEOUT)
2085 static void __update_slot_state(candidate_process_context_t *cpc, int method,
2089 case METHOD_OUT_OF_MEMORY:
2090 if ((force || cpc->deactivation_method & method) &&
2092 __deactivate_slot(cpc);
2094 __activate_slot(cpc);
2097 if (force || cpc->deactivation_method & method)
2098 __deactivate_slot(cpc);
2100 case METHOD_AVAILABLE_MEMORY:
2101 if (force || cpc->activation_method & method)
2102 __activate_slot(cpc);
2104 case METHOD_REQUEST:
2105 if (force || cpc->activation_method & method)
2106 __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, force);
2109 __activate_slot(cpc);
2114 static bool __handle_launch_event(int fd, io_condition_e cond, void *data)
2117 app_pkt_t *pkt = NULL;
2118 appinfo_t *menu_info = NULL;
2119 candidate_process_context_t *cpc = NULL;
2120 candidate_process_context_t *org_cpc = NULL;
2121 const char *app_path = NULL;
2129 if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
2130 _E("fd(%d), condition(%d)", fd, cond);
2131 g_idle_add(__launchpad_recovery_cb, __launchpad_channel);
2132 __launchpad_channel = NULL;
2136 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH");
2137 pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
2139 _E("packet is NULL");
2143 if (cr.uid >= REGULAR_UID_MIN) {
2144 if (__check_caller_by_pid(cr.pid) < 0) {
2145 _E("Invalid caller pid");
2150 kb = bundle_decode(pkt->data, pkt->len);
2152 _E("bundle decode error");
2156 if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
2160 case PAD_CMD_VISIBILITY:
2161 ret = __dispatch_cmd_hint(kb, METHOD_VISIBILITY);
2162 __real_send(clifd, ret);
2165 case PAD_CMD_ADD_LOADER:
2166 ret = __dispatch_cmd_add_loader(kb);
2167 __real_send(clifd, ret);
2170 case PAD_CMD_REMOVE_LOADER:
2171 ret = __dispatch_cmd_remove_loader(kb);
2172 __real_send(clifd, ret);
2175 case PAD_CMD_MAKE_DEFAULT_SLOTS:
2176 ret = __add_default_slots();
2178 _E("Failed to make default slots");
2179 __real_send(clifd, ret);
2182 case PAD_CMD_PREPARE_APP_DEFINED_LOADER:
2183 ret = __dispatch_cmd_add_app_defined_loader(kb);
2184 __real_send(clifd, ret);
2187 case PAD_CMD_DEMAND:
2188 ret = __dispatch_cmd_hint(kb, METHOD_DEMAND);
2189 __real_send(clifd, ret);
2193 __real_send(clifd, getpid());
2196 case PAD_CMD_UPDATE_APP_TYPE:
2197 __dispatch_cmd_update_app_type(kb);
2204 PERF("packet processing start");
2206 menu_info = _appinfo_create(kb);
2207 if (menu_info == NULL) {
2208 _E("such pkg no found");
2212 app_path = _appinfo_get_app_path(menu_info);
2213 if (app_path == NULL) {
2214 _E("app_path is NULL");
2217 if (app_path[0] != '/') {
2218 _E("app_path is not absolute path");
2222 if (menu_info->hwacc == NULL) {
2223 _E("[launchpad] Failed to find H/W acceleration type");
2227 SECURE_LOGD("exec : %s", menu_info->app_path);
2228 SECURE_LOGD("comp_type : %s", menu_info->comp_type);
2229 SECURE_LOGD("internal pool : %s", menu_info->internal_pool);
2230 SECURE_LOGD("hwacc : %s", menu_info->hwacc);
2231 SECURE_LOGD("app_type : %s", menu_info->app_type);
2232 SECURE_LOGD("pkg_type : %s", menu_info->pkg_type);
2234 if (menu_info->comp_type &&
2235 strcmp(menu_info->comp_type, "svcapp") == 0) {
2236 loader_id = __get_loader_id(kb);
2237 if (loader_id > PAD_LOADER_ID_DYNAMIC_BASE) {
2238 type = LAUNCHPAD_LOADER_TYPE_DYNAMIC;
2239 cpc = __find_slot(type, loader_id);
2240 if (cpc && !cpc->prepared)
2243 loader_id = PAD_LOADER_ID_DIRECT;
2245 } else if (menu_info->comp_type && menu_info->app_type &&
2246 strcmp(menu_info->comp_type, "widgetapp") == 0 &&
2247 strcmp(menu_info->app_type, "webapp") == 0) {
2248 loader_id = PAD_LOADER_ID_DIRECT;
2250 loader_id = __get_loader_id(kb);
2251 if (loader_id <= PAD_LOADER_ID_STATIC) {
2252 cpc = __find_available_slot(menu_info->hwacc,
2253 menu_info->app_type,
2254 menu_info->loader_name, &org_cpc);
2256 type = LAUNCHPAD_LOADER_TYPE_DYNAMIC;
2257 cpc = __find_slot(type, loader_id);
2258 if (cpc && !cpc->prepared)
2263 _modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
2264 if (menu_info->appid == NULL) {
2265 _E("unable to get appid from menu_info");
2269 PERF("get package information & modify bundle done");
2271 if (loader_id == PAD_LOADER_ID_DIRECT || cpc == NULL) {
2272 _W("Launch directly %d %p", loader_id, cpc);
2273 pid = __launch_directly(menu_info->appid, app_path, clifd, kb,
2275 if (org_cpc && (!org_cpc->app_check || org_cpc->app_exists) &&
2276 org_cpc->pid == CANDIDATE_NONE &&
2277 !__sequencer_slot_exist(org_cpc)) {
2278 if (org_cpc->timer > 0) {
2279 g_source_remove(org_cpc->timer);
2283 __update_slot_state(org_cpc, METHOD_REQUEST, true);
2284 __set_timer(org_cpc);
2287 _W("Launch %d type process", cpc->type);
2288 pid = __send_launchpad_loader(cpc, pkt, app_path, clifd);
2291 _memory_monitor_reset_timer();
2292 __send_result_to_caller(clifd, pid, app_path);
2299 _dbus_send_app_launch_signal(pid, menu_info->appid);
2300 g_hash_table_insert(__pid_table, GINT_TO_POINTER(pid),
2301 strdup(menu_info->appid));
2302 _log_print("[LAUNCH]", "pid(%7d) | appid(%s)",
2303 pid, menu_info->appid);
2306 if (menu_info != NULL)
2307 _appinfo_free(menu_info);
2314 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
2319 static void __destroy_slot(candidate_process_context_t *cpc)
2324 if (cpc->hydra_channel)
2325 _io_channel_destroy(cpc->hydra_channel);
2328 _io_channel_destroy(cpc->channel);
2330 if (cpc->loader_extra)
2331 free(cpc->loader_extra);
2333 if (cpc->loader_path)
2334 free(cpc->loader_path);
2336 if (cpc->loader_name)
2337 free(cpc->loader_name);
2342 static candidate_process_context_t *__create_slot(int type, int loader_id,
2343 int caller_pid, const char *loader_name, const char *loader_path,
2344 const char *loader_extra, int detection_method,
2345 int activation_method, int deactivation_method,
2346 unsigned int ttl, int timeout_val,
2347 int threshold_max, int threshold_min,
2348 bool on_boot, bool app_exists, bool is_hydra, bool app_check)
2350 candidate_process_context_t *cpc;
2352 cpc = calloc(1, sizeof(candidate_process_context_t));
2354 _E("Out of memory");
2358 cpc->loader_name = strdup(loader_name);
2359 if (cpc->loader_name == NULL) {
2360 _E("Failed to duplicate loader name(%s)", loader_name);
2361 __destroy_slot(cpc);
2365 cpc->loader_path = strdup(loader_path);
2366 if (cpc->loader_path == NULL) {
2367 _E("Failed to duplicate loader path(%s)", loader_path);
2368 __destroy_slot(cpc);
2372 cpc->loader_extra = loader_extra ? strdup(loader_extra) : strdup("");
2373 if (cpc->loader_extra == NULL) {
2374 _E("Failed to duplicate loader extra(%s)",
2375 loader_extra ? loader_extra : "null");
2376 __destroy_slot(cpc);
2381 cpc->prepared = false;
2382 cpc->pid = CANDIDATE_NONE;
2383 cpc->hydra_pid = HYDRA_NONE;
2384 cpc->caller_pid = caller_pid;
2385 cpc->loader_id = loader_id;
2388 cpc->last_exec_time = 0;
2390 cpc->detection_method = detection_method;
2391 cpc->timeout_val = timeout_val;
2392 cpc->cpu_total_time = 0;
2393 cpc->cpu_idle_time = 0;
2394 cpc->threshold = threshold_max;
2395 cpc->threshold_max = threshold_max;
2396 cpc->threshold_min = threshold_min;
2397 cpc->on_boot = on_boot;
2398 cpc->app_exists = app_exists;
2399 cpc->touched = false;
2401 cpc->activation_method = activation_method;
2402 cpc->deactivation_method = deactivation_method;
2404 cpc->live_timer = 0;
2405 cpc->is_hydra = is_hydra;
2406 cpc->app_check = app_check;
2407 cpc->score = WIN_SCORE;
2409 cpc->cpu_check_count = 0;
2411 if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) &&
2413 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2415 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2417 _W("loader(%s), type(%d), state(%d)",
2418 cpc->loader_name, cpc->type, cpc->state);
2422 static candidate_process_context_t *__add_slot(int type, int loader_id,
2423 int caller_pid, const char *loader_name, const char *loader_path,
2424 const char *loader_extra, int detection_method,
2425 int activation_method, int deactivation_method,
2426 unsigned int ttl, int timeout_val,
2427 int threshold_max, int threshold_min,
2428 bool on_boot, bool app_exists, bool is_hydra, bool app_check)
2430 candidate_process_context_t *cpc;
2432 io_channel_h channel;
2434 io_channel_h hydra_channel;
2436 if (__find_slot(type, loader_id) != NULL)
2439 cpc = __create_slot(type, loader_id,
2440 caller_pid, loader_name, loader_path,
2441 loader_extra, detection_method,
2442 activation_method, deactivation_method,
2444 threshold_max, threshold_min,
2445 on_boot, app_exists, is_hydra, app_check);
2449 fd = __listen_candidate_process(cpc->type, cpc->loader_id);
2451 _E("[launchpad] Listening the socket to " \
2452 "the type %d candidate process failed.",
2454 __destroy_slot(cpc);
2458 channel = _io_channel_create(fd, IO_IN, __handle_loader_event, cpc);
2461 __destroy_slot(cpc);
2465 cpc->channel = channel;
2468 hydra_fd = __listen_hydra_process(cpc->type, cpc->loader_id);
2469 if (hydra_fd == -1) {
2470 _E("[launchpad] Listening the socket to " \
2471 "the type %d hydra process failed.",
2473 __destroy_slot(cpc);
2477 hydra_channel = _io_channel_create(hydra_fd, IO_IN,
2478 __handle_hydra_event, cpc);
2479 if (!hydra_channel) {
2481 __destroy_slot(cpc);
2485 cpc->hydra_channel = hydra_channel;
2489 candidate_slot_list = g_list_append(candidate_slot_list, cpc);
2494 static int __remove_slot(int type, int loader_id)
2496 candidate_process_context_t *cpc;
2499 iter = candidate_slot_list;
2501 cpc = (candidate_process_context_t *)iter->data;
2502 if (type == cpc->type && loader_id == cpc->loader_id) {
2503 __dispose_candidate_process(cpc);
2504 candidate_slot_list = g_list_delete_link(
2505 candidate_slot_list, iter);
2506 __destroy_slot(cpc);
2510 iter = g_list_next(iter);
2516 static int __init_launchpad_fd(int argc, char **argv)
2518 io_condition_e cond;
2521 fd = __launchpad_pre_init(argc, argv);
2523 _E("launchpad pre init failed");
2527 cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
2528 __launchpad_channel = _io_channel_create(fd, cond,
2529 __handle_launch_event, NULL);
2530 if (!__launchpad_channel) {
2538 static bool __on_directory_create(const char *event_name, uint32_t mask,
2542 _E("Invalid parameter");
2546 if (!strcmp(event_name, LOADERS_PATH)) {
2547 __init_app_defined_loader_monitor();
2554 static bool __on_file_change(const char *event_name, uint32_t mask,
2559 loader_info_t* info;
2560 candidate_process_context_t *cpc;
2563 _E("Invalid parameter");
2567 ext = strrchr(event_name, '.');
2568 if (ext == NULL || strcmp(ext, ".loader") != 0)
2571 if (mask & IN_CREATE) {
2572 snprintf(buf, sizeof(buf), "%s/%s",
2573 APP_DEFINED_LOADER_INFO_PATH, event_name);
2574 app_defined_loader_info_list = _loader_info_load_file(
2575 app_defined_loader_info_list, buf);
2576 } else if (mask & IN_DELETE) {
2577 snprintf(buf, ext - event_name + 1, "%s", event_name);
2579 info = _loader_info_find_loader_by_loader_name(
2580 app_defined_loader_info_list, buf);
2581 cpc = __find_slot_from_loader_name(info->name);
2582 __remove_slot(cpc->type, cpc->loader_id);
2583 app_defined_loader_info_list = _loader_info_unload(
2584 app_defined_loader_info_list, buf);
2590 static void __init_app_defined_loader_monitor(void)
2594 ret = access(APP_DEFINED_LOADER_INFO_PATH, F_OK);
2596 _W("Failed to access %s", APP_DEFINED_LOADER_INFO_PATH);
2597 ret = _inotify_add_watch(OPT_SHARE_PATH,
2598 IN_CREATE, __on_directory_create, NULL);
2600 _E("Failed to add inotify watch %s", OPT_SHARE_PATH);
2605 ret = _inotify_add_watch(APP_DEFINED_LOADER_INFO_PATH,
2606 IN_CREATE | IN_DELETE, __on_file_change, NULL);
2609 _E("Failed to add inotify watch %s",
2610 APP_DEFINED_LOADER_INFO_PATH);
2617 static int __init_label_monitor_fd(void)
2619 io_condition_e cond;
2623 r = security_manager_app_labels_monitor_init(&label_monitor);
2624 if (r != SECURITY_MANAGER_SUCCESS)
2627 r = security_manager_app_labels_monitor_process(label_monitor);
2628 if (r != SECURITY_MANAGER_SUCCESS)
2631 security_manager_app_labels_monitor_get_fd(label_monitor, &fd);
2633 _E("failed to get fd");
2637 cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
2638 __label_monitor_channel = _io_channel_create(fd, cond,
2639 __handle_label_monitor, NULL);
2640 if (!__label_monitor_channel)
2649 if (label_monitor) {
2650 security_manager_app_labels_monitor_finish(label_monitor);
2651 label_monitor = NULL;
2657 static int __verify_loader_caps(const char *loader)
2660 cap_flag_value_t eff_state;
2661 cap_flag_value_t inh_state;
2662 cap_value_t values[] = {CAP_SETGID, CAP_MAC_ADMIN};
2665 int size = ARRAY_SIZE(values);
2667 /* If Dytransition feature is enabled, CAP_MAC_ADMIN is unnecessary */
2671 cap_d = cap_get_file(loader);
2673 _E("Failed to get cap from file(%s)", loader);
2677 for (i = 0; i < size; i++) {
2678 r = cap_get_flag(cap_d, values[i], CAP_INHERITABLE, &inh_state);
2680 _E("Failed to get cap inh - errno(%d)", errno);
2685 r = cap_get_flag(cap_d, values[i], CAP_EFFECTIVE, &eff_state);
2687 _E("Failed to get cap eff - errno(%d)", errno);
2692 if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) {
2693 _E("The %s doesn't have %d cap", loader, values[i]);
2703 static void __add_slot_from_info(gpointer data, gpointer user_data)
2705 loader_info_t *info = (loader_info_t *)data;
2706 candidate_process_context_t *cpc;
2707 bundle_raw *extra = NULL;
2710 if (!strcmp(info->exe, "null")) {
2711 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset,
2712 PAD_LOADER_ID_DIRECT,
2713 0, info->name, info->exe, NULL,
2715 info->cpu_threshold_max,
2716 info->cpu_threshold_min,
2724 info->type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset;
2729 if (access(info->exe, F_OK | X_OK) == 0) {
2730 if (__verify_loader_caps(info->exe) < 0)
2734 bundle_encode(info->extra, &extra, &len);
2736 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset,
2737 PAD_LOADER_ID_STATIC,
2738 0, info->name, info->exe, (char *)extra,
2739 info->detection_method,
2740 info->activation_method,
2741 info->deactivation_method,
2744 info->cpu_threshold_max,
2745 info->cpu_threshold_min,
2751 bundle_free_encoded_rawdata(&extra);
2755 info->type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset;
2760 static int __add_default_slots(void)
2762 if (loader_info_list)
2763 _loader_info_dispose(loader_info_list);
2765 loader_info_list = _loader_info_load_dir(LOADER_INFO_PATH);
2766 if (loader_info_list == NULL)
2769 user_slot_offset = 0;
2770 g_list_foreach(loader_info_list, __add_slot_from_info, NULL);
2771 __add_idle_checker(0, candidate_slot_list);
2776 static void __add_app_defined_loaders(void)
2778 app_defined_loader_info_list = _loader_info_load_dir(APP_DEFINED_LOADER_INFO_PATH);
2781 static bool __is_low_memory(void)
2783 if (_memory_monitor_is_low_memory())
2786 if (__memory_status_low >= MEMORY_STATUS_LOW)
2792 static void __hw_acceleration_changed_cb(keynode_t *key, void *data)
2794 __sys_hwacc = vconf_keynode_get_int(key);
2795 _D("sys hwacc: %d", __sys_hwacc);
2798 static void __update_lang(keynode_t *node, void *user_data)
2802 lang = vconf_keynode_get_str(node);
2804 _E("Failed to get language");
2808 setenv("LANG", lang, 1);
2811 static void __region_format_changed_cb(keynode_t *node, void *data)
2815 region = vconf_keynode_get_str(node);
2817 _E("Failed to get value");
2821 setenv("LC_CTYPE", region, 1);
2824 static void __memory_status_low_changed_cb(keynode_t *node, void *data)
2826 candidate_process_context_t *cpc;
2829 __memory_status_low = vconf_keynode_get_int(node);
2830 if (__memory_status_low >= MEMORY_STATUS_LOW) {
2832 iter = candidate_slot_list;
2834 cpc = (candidate_process_context_t *)iter->data;
2835 __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, false);
2836 iter = g_list_next(iter);
2841 static void __memory_status_normal_changed_cb(keynode_t *node, void *data)
2843 candidate_process_context_t *cpc;
2846 __memory_status_normal = vconf_keynode_get_int(node);
2847 if (__memory_status_normal == MEMORY_STATUS_NORMAL) {
2849 iter = candidate_slot_list;
2851 cpc = (candidate_process_context_t *)iter->data;
2852 __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, true);
2853 iter = g_list_next(iter);
2858 static void __unregister_vconf_events(void)
2863 type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY;
2864 key = _config_get_string_value(type);
2865 vconf_ignore_key_changed(key, __memory_status_normal_changed_cb);
2867 type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY;
2868 key = _config_get_string_value(type);
2869 vconf_ignore_key_changed(key, __memory_status_low_changed_cb);
2871 vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT,
2872 __region_format_changed_cb);
2873 vconf_ignore_key_changed(VCONFKEY_LANGSET,
2875 vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2876 __hw_acceleration_changed_cb);
2879 static int __register_vconf_events(void)
2887 r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc);
2889 _E("Failed to get vconf hw acceleration. err = %d", r);
2891 r = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2892 __hw_acceleration_changed_cb, NULL);
2893 if (r != VCONF_OK) {
2894 _E("Failed to register callback for hw acceleration. err = %d",
2898 lang = vconf_get_str(VCONFKEY_LANGSET);
2900 setenv("LANG", lang, 1);
2904 r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL);
2906 _E("Failed to register callback for langset. err = %d", r);
2908 region = vconf_get_str(VCONFKEY_REGIONFORMAT);
2910 setenv("LC_CTYPE", region, 1);
2914 r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT,
2915 __region_format_changed_cb, NULL);
2917 _E("Failed to register callback for regionformat. err = %d", r);
2919 type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY;
2920 key = _config_get_string_value(type);
2921 type = CONFIG_TYPE_MEMORY_STATUS_LOW_VALUE;
2922 MEMORY_STATUS_LOW = _config_get_int_value(type);
2924 r = vconf_get_int(key, &__memory_status_low);
2926 _E("Failed to get vconf low memory. err = %d", r);
2928 r = vconf_notify_key_changed(key,
2929 __memory_status_low_changed_cb, NULL);
2931 _E("Failed to register callback for low memory. err = %d", r);
2933 type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY;
2934 key = _config_get_string_value(type);
2935 type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_VALUE;
2936 MEMORY_STATUS_NORMAL = _config_get_int_value(type);
2938 r = vconf_get_int(key, &__memory_status_normal);
2940 _E("Failed to get vconf normal memory. err = %d", r);
2942 r = vconf_notify_key_changed(key,
2943 __memory_status_normal_changed_cb, NULL);
2945 _E("Failed to register callback for normal memory. err = %d", r);
2950 static bool __handle_logger(int fd, io_condition_e cond, void *data)
2956 if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
2957 _E("fd(%d), io_condition(%d)", fd, cond);
2958 g_idle_add(__logger_recovery_cb, __logger_channel);
2959 __logger_channel = NULL;
2963 pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
2965 _E("Failed to receive the packet");
2969 if (getuid() != cr.uid) {
2970 _E("Invalid caller");
2974 if (pkt->len <= 0) {
2975 _E("Invalid message");
2979 _E("[%d] %s", cr.pid, (const char *)pkt->data);
2980 _log_print("[ERROR]", "pid(%7d) | message(%s)",
2981 cr.pid, (const char *)pkt->data);
2991 static int __init_logger_fd(void)
2993 io_condition_e cond;
2996 fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK);
2998 _E("Failed to create logger socker");
3002 cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL;
3003 __logger_channel = _io_channel_create(fd, cond, __handle_logger, NULL);
3004 if (!__logger_channel) {
3012 static int __memory_monitor_cb(bool low_memory, void *user_data)
3014 candidate_process_context_t *cpc;
3016 cpc = __get_running_slot(false);
3017 if (!cpc && low_memory)
3022 __update_slots_pss();
3024 candidate_slot_list = g_list_sort(candidate_slot_list,
3028 __pause_last_running_slot(false);
3030 cpc = __get_running_slot(false);
3033 } while (__is_low_memory());
3035 __resume_all_slots();
3041 static gboolean __logger_recovery_cb(gpointer data)
3043 io_channel_h channel = data;
3046 _io_channel_destroy(channel);
3048 ret = __init_logger_fd();
3050 _E("Failed to recover logger socket");
3051 return G_SOURCE_REMOVE;
3054 _E("[__RECOVERY__] Logger socket");
3056 return G_SOURCE_REMOVE;
3059 static gboolean __launchpad_recovery_cb(gpointer data)
3061 io_channel_h channel = data;
3064 _io_channel_destroy(channel);
3066 ret = __init_launchpad_fd(0, NULL);
3068 _E("Failed to recover launchpad socket");
3070 return G_SOURCE_REMOVE;
3073 _E("[__RECOVERY__] Launchpad socket");
3075 return G_SOURCE_REMOVE;
3078 static int __before_loop(int argc, char **argv)
3082 _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__);
3083 ret = __sequencer_init();
3085 _E("Failed to initialize sequencer");
3089 ret = _signal_init();
3091 _E("Failed to initialize signal");
3095 _signal_set_sigchld_cb(__handle_sigchild, NULL);
3097 ret = __init_launchpad_fd(argc, argv);
3099 _E("__init_launchpad_fd() failed");
3103 ret = __init_logger_fd();
3105 _E("__init_logger_fd() failed");
3109 ret = __init_label_monitor_fd();
3111 _W("Failed to initialize label monitor");
3113 ret = _config_init();
3115 _W("Failed to initialize config");
3119 _W("Failed to initialize dbus");
3123 MAX_CPU_CHECK_COUNT = _config_get_int_value(
3124 CONFIG_TYPE_CPU_CHECKER_MAX_COUNT);
3125 __add_default_slots();
3126 launcher_info_list = _launcher_info_load(LAUNCHER_INFO_PATH);
3128 __add_app_defined_loaders();
3130 ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL);
3132 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL);
3134 __pid_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3137 _E("Failed to create pid table");
3141 ret = _worker_init();
3145 __register_vconf_events();
3146 __init_app_defined_loader_monitor();
3147 _memory_monitor_init();
3148 _memory_monitor_set_event_cb(__memory_monitor_cb, NULL);
3150 _print_hwc_log("%s(%d): END", __FUNCTION__, __LINE__);
3155 static void __after_loop(void)
3158 _memory_monitor_fini();
3159 __unregister_vconf_events();
3162 g_hash_table_destroy(__pid_table);
3164 if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0)
3165 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL);
3168 _launcher_info_unload(launcher_info_list);
3172 _loader_info_dispose(app_defined_loader_info_list);
3174 if (__label_monitor_channel)
3175 _io_channel_destroy(__label_monitor_channel);
3178 security_manager_app_labels_monitor_finish(label_monitor);
3180 if (__logger_channel)
3181 _io_channel_destroy(__logger_channel);
3183 if (__launchpad_channel)
3184 _io_channel_destroy(__launchpad_channel);
3191 int main(int argc, char **argv)
3193 GMainLoop *mainloop = NULL;
3195 _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__);
3196 mainloop = g_main_loop_new(NULL, FALSE);
3198 _E("Failed to create glib main loop");
3202 _print_hwc_log("%s(%d): __before_loop()", __FUNCTION__, __LINE__);
3203 if (__before_loop(argc, argv) != 0) {
3204 _E("process-pool Initialization failed!");
3208 #ifdef TIZEN_FEATURE_PRIORITY_CHANGE
3211 _print_hwc_log("%s(%d): g_main_loop_run()", __FUNCTION__, __LINE__);
3212 g_main_loop_run(mainloop);