2 * Copyright (c) 2023 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.
17 #include <bundle_internal.h>
20 #include <linux/limits.h>
24 #include <security-manager.h>
28 #include <sys/capability.h>
29 #include <sys/prctl.h>
30 #include <sys/socket.h>
32 #include <sys/types.h>
35 #include <systemd/sd-daemon.h>
37 #include <trust-anchor.h>
43 #include "launchpad-process-pool/launcher_info.hh"
44 #include "launchpad-process-pool/launchpad_config.h"
45 #include "launchpad-process-pool/launchpad_dbus.h"
46 #include "launchpad-process-pool/launchpad_debug.h"
47 #include "launchpad-process-pool/launchpad_inotify.h"
48 #include "launchpad-process-pool/launchpad_io_channel.h"
49 #include "launchpad-process-pool/launchpad_log.h"
50 #include "launchpad-process-pool/launchpad_memory_monitor.h"
51 #include "launchpad-process-pool/launchpad_signal.h"
52 #include "launchpad-process-pool/launchpad_worker.h"
53 #include "launchpad-process-pool/loader_info.hh"
54 #include "launchpad-process-pool/slot_info.h"
55 #include "lib/common/inc/key.h"
56 #include "lib/common/inc/launchpad_common.h"
57 #include "lib/common/inc/launchpad_plugin.h"
58 #include "lib/common/inc/launchpad_proc.h"
59 #include "lib/common/inc/launchpad_types.h"
60 #include "lib/common/inc/perf.h"
62 #define AUL_PR_NAME 16
63 #define EXEC_CANDIDATE_EXPIRED 5
64 #define EXEC_CANDIDATE_WAIT 1
65 #define DIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a))
66 #define CANDIDATE_NONE 0
68 #define PROCESS_POOL_LAUNCHPAD_SOCK ".launchpad-process-pool-sock"
69 #define LAUNCHPAD_LOGGER_SOCK ".launchpad-logger-sock"
70 #define LOADER_PATH_DEFAULT "/usr/bin/launchpad-loader"
71 #define LOADER_INFO_PATH "/usr/share/aul"
72 #define OPT_SHARE_PATH "/opt/share"
73 #define LOADERS_PATH "loaders"
74 #define APP_DEFINED_LOADER_INFO_PATH OPT_SHARE_PATH "/" LOADERS_PATH
75 #define COMMON_LOADER_NAME "common-loader1"
77 #define LAUNCHER_INFO_PATH LOADER_INFO_PATH
78 #define REGULAR_UID_MIN 5000
79 #define PAD_ERR_FAILED -1
80 #define PAD_ERR_REJECTED -2
81 #define PAD_ERR_INVALID_ARGUMENT -3
82 #define PAD_ERR_INVALID_PATH -4
83 #define CPU_CHECKER_TIMEOUT 1000
86 #define LOSE_SCORE_RATE 0.7f
88 enum candidate_process_state_e {
89 CANDIDATE_PROCESS_STATE_RUNNING,
90 CANDIDATE_PROCESS_STATE_PAUSED,
96 int pid; /* for hydra this pid is not the pid of hydra itself */
97 /* but pid of non-hydra candidate, which was forked from hydra */
108 int detection_method;
110 unsigned long long cpu_total_time;
111 unsigned long long cpu_idle_time;
119 int activation_method;
120 int deactivation_method;
126 io_channel_h client_channel;
127 io_channel_h channel;
128 io_channel_h hydra_channel;
135 std::vector<std::string> condition_path_exists;
136 } candidate_process_context_t;
148 candidate_process_context_t* running_cpc;
151 struct app_launch_arg {
153 const char* app_path;
154 appinfo_t* menu_info;
168 struct cleanup_info_s {
173 typedef struct candidate_info_s {
181 typedef struct request_s {
183 appinfo_t* menu_info;
185 candidate_process_context_t* cpc;
186 candidate_process_context_t* org_cpc;
187 const char* app_path;
193 pid_t pid; /* result */
196 typedef request_t* request_h;
198 typedef int (*request_handler)(request_h request);
203 std::unique_ptr<launchpad::LoaderInfoManager> loader_info_manager;
204 std::unique_ptr<launchpad::LoaderInfoManager> app_defined_loader_info_manager;
205 int user_slot_offset;
206 GList* candidate_slot_list;
207 app_labels_monitor* label_monitor;
208 std::vector<launchpad::LauncherInfoPtr> launcher_info_list;
209 GHashTable* __pid_table;
210 int __memory_status_low;
211 int __memory_status_normal;
212 sequencer __sequencer;
213 int MEMORY_STATUS_LOW;
214 int MEMORY_STATUS_NORMAL;
215 int MAX_CPU_CHECK_COUNT;
217 io_channel_h __logger_channel;
218 io_channel_h __label_monitor_channel;
219 io_channel_h __launchpad_channel;
220 int __client_fd = -1;
225 static candidate_process_context_t* __add_slot(slot_info_t* info);
226 static int __remove_slot(int type, int loader_id);
227 static int __add_default_slots(void);
228 static gboolean __handle_idle_checker(gpointer data);
229 static int __add_idle_checker(int detection_method, GList* cur);
230 static void __dispose_candidate_process(candidate_process_context_t* cpc);
231 static bool __is_low_memory(void);
232 static void __update_slot_state(candidate_process_context_t* cpc,
233 launchpad::LoaderMethod method,
235 static void __init_app_defined_loader_monitor(void);
236 static gboolean __launchpad_recovery_cb(gpointer data);
237 static gboolean __logger_recovery_cb(gpointer data);
239 static gboolean __handle_queuing_slots(gpointer data) {
240 candidate_process_context_t* cpc;
241 unsigned long long total = 0;
242 unsigned long long idle = 0;
244 if (__sequencer.idle_checker > 0)
245 return G_SOURCE_CONTINUE;
247 if (g_queue_is_empty(__sequencer.queue)) {
248 __sequencer.timer = 0;
249 return G_SOURCE_REMOVE;
252 cpc = (candidate_process_context_t*)g_queue_pop_head(__sequencer.queue);
254 _E("Critical error!");
255 __sequencer.timer = 0;
256 return G_SOURCE_REMOVE;
260 if (cpc->app_check && !cpc->app_exists) {
261 _W("The application is not installed. Type(%d)", cpc->type);
262 return G_SOURCE_CONTINUE;
266 g_source_remove(cpc->timer);
270 if (cpc->pid != CANDIDATE_NONE) {
271 _W("The slot(%d) is already running. pid(%d)", cpc->type, cpc->pid);
272 return G_SOURCE_CONTINUE;
275 _get_cpu_idle(&total, &idle);
276 cpc->cpu_idle_time = idle;
277 cpc->cpu_total_time = total;
278 cpc->cpu_check_count = 0;
280 __sequencer.idle_checker =
281 g_timeout_add(CPU_CHECKER_TIMEOUT, __handle_idle_checker, cpc);
282 __sequencer.running_cpc = cpc;
284 _W("[__SEQUENCER__] Add idle checker. Type(%d)", cpc->type);
286 return G_SOURCE_CONTINUE;
289 static bool __sequencer_slot_is_running(candidate_process_context_t* cpc) {
290 if (__sequencer.running_cpc == cpc)
296 static bool __sequencer_slot_exist(candidate_process_context_t* cpc) {
299 found = g_queue_find(__sequencer.queue, cpc);
306 static int __sequencer_add_slot(candidate_process_context_t* cpc) {
307 if (__sequencer_slot_exist(cpc)) {
308 _W("Already exists");
312 if (__sequencer_slot_is_running(cpc)) {
313 _W("slot(%d) is running", cpc->type);
317 g_queue_push_tail(__sequencer.queue, cpc);
322 static void __sequencer_remove_slot(candidate_process_context_t* cpc) {
323 g_queue_remove(__sequencer.queue, cpc);
326 static void __sequencer_run(void) {
327 if (__sequencer.timer)
330 __sequencer.timer = g_timeout_add(500, __handle_queuing_slots, nullptr);
331 if (!__sequencer.timer)
332 _E("Failed to add sequencer timer");
335 static void __sequencer_stop(void) {
336 if (!__sequencer.timer)
339 g_source_remove(__sequencer.timer);
340 __sequencer.timer = 0;
343 static bool __sequencer_queue_is_empty(void) {
344 if (g_queue_is_empty(__sequencer.queue))
350 static int __sequencer_init(void) {
351 _D("[__SEQUENCER__] Init");
353 __sequencer.queue = g_queue_new();
354 if (!__sequencer.queue) {
362 static void __sequencer_fini(void) {
363 _D("[__SEQUENCER__] Finish");
365 if (__sequencer.idle_checker > 0)
366 g_source_remove(__sequencer.idle_checker);
368 if (__sequencer.timer > 0)
369 g_source_remove(__sequencer.timer);
371 g_queue_free(__sequencer.queue);
374 static int __make_loader_id(void) {
375 static int id = PAD_LOADER_ID_DYNAMIC_BASE;
380 static candidate_process_context_t* __find_slot_from_static_type(int type) {
381 candidate_process_context_t* cpc;
382 GList* iter = candidate_slot_list;
384 if (type == static_cast<int>(launchpad::LoaderType::Dynamic) ||
385 type == static_cast<int>(launchpad::LoaderType::Unsupported))
389 cpc = (candidate_process_context_t*)iter->data;
390 if (type == cpc->type)
393 iter = g_list_next(iter);
399 static candidate_process_context_t* __find_slot_from_pid(int pid) {
400 candidate_process_context_t* cpc;
401 GList* iter = candidate_slot_list;
404 cpc = (candidate_process_context_t*)iter->data;
408 iter = g_list_next(iter);
414 static candidate_process_context_t* __find_hydra_slot_from_pid(int pid) {
415 candidate_process_context_t* cpc;
416 GList* iter = candidate_slot_list;
419 cpc = (candidate_process_context_t*)iter->data;
420 if (cpc->is_hydra && pid == cpc->hydra_pid)
423 iter = g_list_next(iter);
429 static candidate_process_context_t* __find_slot_from_caller_pid(
431 candidate_process_context_t* cpc;
432 GList* iter = candidate_slot_list;
435 cpc = (candidate_process_context_t*)iter->data;
436 if (caller_pid == cpc->caller_pid)
439 iter = g_list_next(iter);
445 static candidate_process_context_t* __find_slot_from_loader_id(int id) {
446 candidate_process_context_t* cpc;
447 GList* iter = candidate_slot_list;
450 cpc = (candidate_process_context_t*)iter->data;
451 if (id == cpc->loader_id)
454 iter = g_list_next(iter);
460 static candidate_process_context_t* __find_slot_from_loader_name(
461 const char* loader_name) {
462 candidate_process_context_t* cpc;
463 GList* iter = candidate_slot_list;
466 cpc = (candidate_process_context_t*)iter->data;
467 if (strcmp(cpc->loader_name, loader_name) == 0)
470 iter = g_list_next(iter);
476 static candidate_process_context_t* __find_slot(int type, int loader_id) {
477 if (type == static_cast<int>(launchpad::LoaderType::Dynamic))
478 return __find_slot_from_loader_id(loader_id);
480 return __find_slot_from_static_type(type);
483 static void __update_slot_score(candidate_process_context_t* slot) {
487 slot->score *= LOSE_SCORE_RATE;
488 slot->score += WIN_SCORE;
491 static void __update_slots_pss(void) {
492 candidate_process_context_t* cpc;
495 iter = candidate_slot_list;
497 cpc = (candidate_process_context_t*)iter->data;
498 iter = g_list_next(iter);
500 if (cpc->pid == CANDIDATE_NONE)
503 _proc_get_mem_pss(cpc->pid, &cpc->pss);
507 static gint __compare_slot(gconstpointer a, gconstpointer b) {
508 candidate_process_context_t* slot_a = (candidate_process_context_t*)a;
509 candidate_process_context_t* slot_b = (candidate_process_context_t*)b;
511 if (slot_a->is_hydra && !slot_b->is_hydra)
513 if (!slot_a->is_hydra && slot_b->is_hydra)
516 if (slot_a->score < slot_b->score)
518 if (slot_a->score > slot_b->score)
521 if (slot_a->pss < slot_b->pss)
523 if (slot_a->pss > slot_b->pss)
529 static candidate_process_context_t* __get_running_slot(bool is_hydra) {
530 candidate_process_context_t* cpc;
533 iter = candidate_slot_list;
535 cpc = (candidate_process_context_t*)iter->data;
536 if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE)
539 iter = g_list_next(iter);
545 static void __pause_all_running_slots(bool is_hydra) {
546 candidate_process_context_t* cpc = nullptr;
549 iter = g_list_last(candidate_slot_list);
551 cpc = (candidate_process_context_t*)iter->data;
552 if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE) {
553 __update_slot_state(cpc, launchpad::LoaderMethod::OutOfMemory, true);
554 if (!_memory_monitor_is_low_memory())
558 iter = g_list_previous(iter);
562 static void __resume_all_slots(void) {
563 candidate_process_context_t* cpc;
566 iter = candidate_slot_list;
568 cpc = (candidate_process_context_t*)iter->data;
569 __update_slot_state(cpc, launchpad::LoaderMethod::AvailableMemory, true);
571 iter = g_list_next(iter);
575 static void __kill_process(int pid) {
576 char err_str[MAX_LOCAL_BUFSZ] = {
580 if (kill(pid, SIGKILL) == -1) {
581 _E("send SIGKILL: %s", strerror_r(errno, err_str, sizeof(err_str)));
585 static void __refuse_candidate_process(int server_fd) {
588 if (server_fd == -1) {
589 _E("arguments error!");
593 client_fd = accept(server_fd, nullptr, nullptr);
594 if (client_fd == -1) {
600 _D("refuse connection!");
606 static int __accept_candidate_process(int server_fd,
614 struct ucred cred = {};
616 if (server_fd == -1 || out_client_fd == nullptr ||
617 out_client_pid == nullptr) {
618 _E("arguments error!");
622 client_fd = accept(server_fd, nullptr, nullptr);
623 if (client_fd == -1) {
628 if (_set_sock_option(client_fd, 1) < 0) {
629 _E("Failed to set sock option");
633 ret = recv(client_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL);
639 len = (socklen_t)sizeof(cred);
640 ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &len);
642 _E("getsockopt error");
646 if (cpc_pid != -1 && cred.pid != cpc_pid) {
647 _E("Invalid accept. pid(%d)", cred.pid);
651 if (cred.pid != recv_pid)
652 _W("Not equal recv and real pid");
654 *out_client_fd = client_fd;
655 *out_client_pid = cred.pid;
657 return *out_client_fd;
666 static int __listen_addr(struct sockaddr_un* addr) {
668 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
674 unlink(addr->sun_path);
676 _D("bind to %s", addr->sun_path);
677 if (bind(fd, (struct sockaddr*)addr, sizeof(struct sockaddr_un)) < 0) {
682 _D("listen to %s", addr->sun_path);
683 if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) {
688 SECURE_LOGD("[launchpad] done, listen fd: %d", fd);
698 static int __listen_candidate_process(int type, int loader_id) {
699 struct sockaddr_un addr;
701 _D("[launchpad] enter, type: %d", type);
703 memset(&addr, 0x00, sizeof(struct sockaddr_un));
704 addr.sun_family = AF_UNIX;
705 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%u/%s%d-%d",
706 SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME, type,
709 return __listen_addr(&addr);
712 static int __listen_hydra_process(int type, int loader_id) {
713 struct sockaddr_un addr;
715 _D("[launchpad] enter, type: %d", type);
717 memset(&addr, 0x00, sizeof(struct sockaddr_un));
718 addr.sun_family = AF_UNIX;
719 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%d/%s%d-%d",
720 SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME, type, loader_id);
722 return __listen_addr(&addr);
725 static int __get_loader_id(bundle* kb) {
728 val = bundle_get_val(kb, AUL_K_LOADER_ID);
731 _W("Requested loader id: %s", val);
736 static int __candidate_process_real_launch(int candidate_fd, app_pkt_t* pkt) {
737 return _send_pkt_raw(candidate_fd, pkt);
740 static int __real_send(int clifd, int ret) {
742 _E("Invalid parameter. clifd(%d)", clifd);
746 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
747 if (errno == EPIPE) {
748 _E("send failed due to EPIPE.");
752 _E("send fail to client");
759 static int __fork_app_process(int (*child_fn)(void*), void* arg,
760 int sched_priority) {
766 _E("failed to fork child process");
771 if (sched_priority != 0)
772 _set_priority(sched_priority);
774 _W("security_manager_prepare_app_candidate ++");
775 ret = security_manager_prepare_app_candidate();
776 _W("security_manager_prepare_app_candidate --");
777 if (ret != SECURITY_MANAGER_SUCCESS) {
778 _E("failed to prepare app candidate process (%d)", ret);
783 _E("failed to exec app process (%d)", errno);
790 static int __exec_loader_process(void* arg) {
791 char** argv = static_cast<char**>(arg);
794 _signal_unblock_sigchld();
796 _setup_stdio(basename(argv[LOADER_ARG_PATH]));
798 if (execv(argv[LOADER_ARG_PATH], argv) < 0) {
799 _send_message_to_logger(argv[LOADER_ARG_PATH],
800 "Failed to prepare candidate process. error(%d:%s)",
801 errno, strerror_r(errno, err_buf, sizeof(err_buf)));
803 _D("Succeeded to prepare candidate_process");
809 static gboolean __handle_deactivate_event(gpointer user_data) {
810 candidate_process_context_t* cpc;
812 cpc = (candidate_process_context_t*)user_data;
813 __update_slot_state(cpc, launchpad::LoaderMethod::Ttl, false);
814 _D("Deactivate event: type(%d), loader_name(%s)",
815 cpc->type, cpc->loader_name);
817 return G_SOURCE_REMOVE;
820 static void __set_live_timer(candidate_process_context_t* cpc) {
824 if (cpc->deactivation_method & static_cast<int>(launchpad::LoaderMethod::Ttl)) {
825 if (cpc->live_timer == 0) {
827 g_timeout_add_seconds(cpc->ttl, __handle_deactivate_event, cpc);
832 static int __hydra_send_request(int fd, enum hydra_cmd cmd) {
834 int size = (int)sizeof(cmd);
837 while (sent != size) {
838 send_ret = send(fd, (char*)&cmd + sent, size - sent, MSG_NOSIGNAL);
839 if (send_ret == -1) {
840 _E("send error! (%d)", errno);
845 _D("send(%d: ret: %d) : %d / %d", fd, send_ret, sent, size);
851 static int __hydra_send_launch_candidate_request(int fd) {
852 SECURE_LOGD("Send launch cmd to hydra, fd: %d", fd);
853 return __hydra_send_request(fd, LAUNCH_CANDIDATE);
856 static void __candidate_info_free(candidate_info_t* info) {
863 for (i = 0; i < info->argc; i++)
872 static int __candidate_info_create(candidate_process_context_t* cpt,
873 candidate_info_t** candidate_info) {
874 char type_str[12] = {
877 char loader_id_str[12] = {
880 char argbuf[LOADER_ARG_LEN];
881 candidate_info_t* info;
886 info = static_cast<candidate_info_t*>(calloc(1, sizeof(candidate_info_t)));
887 if (info == nullptr) {
888 _E("calloc() is failed");
892 info->argv = static_cast<char**>(calloc(LOADER_ARG_DUMMY + 1, sizeof(char*)));
893 if (info->argv == nullptr) {
894 _E("calloc() is failed");
895 __candidate_info_free(info);
899 memset(argbuf, ' ', LOADER_ARG_LEN);
900 argbuf[LOADER_ARG_LEN - 1] = '\0';
901 info->argv[LOADER_ARG_DUMMY] = strdup(argbuf);
903 snprintf(loader_id_str, sizeof(loader_id_str), "%d", cpt->loader_id);
904 snprintf(type_str, sizeof(type_str), "%d", cpt->type);
905 info->argv[LOADER_ARG_PATH] = strdup(cpt->loader_path);
906 info->argv[LOADER_ARG_TYPE] = strdup(type_str);
907 info->argv[LOADER_ARG_ID] = strdup(loader_id_str);
908 info->argv[LOADER_ARG_HYDRA] = strdup(cpt->is_hydra ? "1" : "0");
909 info->argv[LOADER_ARG_EXTRA] = strdup(cpt->loader_extra);
911 info->argc = LOADER_ARG_DUMMY + 1;
912 info->type = cpt->type;
913 info->loader_id = cpt->loader_id;
915 *candidate_info = info;
919 static int __prepare_candidate_process(int type, int loader_id) {
920 candidate_process_context_t* cpt = __find_slot(type, loader_id);
921 candidate_info_t* info;
927 if (cpt->is_hydra && cpt->hydra_pid != HYDRA_NONE)
928 return __hydra_send_launch_candidate_request(cpt->hydra_fd);
930 _D("prepare candidate process / type:%d", type);
931 ret = __candidate_info_create(cpt, &info);
935 info->pid = __fork_app_process(__exec_loader_process, info->argv,
936 cpt->sched_priority);
937 if (info->pid == -1) {
938 _E("Failed to create a child process. type: %d", type);
939 __candidate_info_free(info);
943 _W("Candidate process. type: %d, loader_id: %d, pid: %d", info->type,
944 info->loader_id, info->pid);
945 cpt = __find_slot(info->type, info->loader_id);
946 if (cpt == nullptr) {
947 _E("Not found slot.");
948 __candidate_info_free(info);
952 cpt->last_exec_time = time(nullptr);
954 cpt->hydra_pid = info->pid;
956 cpt->pid = info->pid;
957 __set_live_timer(cpt);
960 _log_print("[CANDIDATE]", "pid(%7d) | type(%d) | loader(%s)", info->pid,
961 cpt->loader_id, cpt->loader_name);
962 _memory_monitor_reset_timer();
963 __candidate_info_free(info);
967 static gboolean __handle_timeout_event(gpointer user_data) {
968 candidate_process_context_t* cpc;
970 cpc = (candidate_process_context_t*)user_data;
973 _W("type(%d), loader_name(%s), state(%d)",
974 cpc->type, cpc->loader_name, cpc->state);
975 if (cpc->pid != CANDIDATE_NONE) {
976 _W("Candidate(%d) process(%d) is running", cpc->type, cpc->pid);
977 return G_SOURCE_REMOVE;
980 __sequencer_add_slot(cpc);
982 return G_SOURCE_REMOVE;
985 static void __set_timer(candidate_process_context_t* cpc) {
986 if (cpc == nullptr || cpc->timer > 0) {
987 _E("Invalid parameter");
991 _W("type(%d), loader_name(%s), state(%d)",
992 cpc->type, cpc->loader_name, cpc->state);
993 if ((cpc->detection_method &
994 static_cast<int>(launchpad::LoaderMethod::Timeout)) &&
995 cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) {
996 cpc->timer = g_timeout_add(cpc->timeout_val, __handle_timeout_event, cpc);
998 _E("g_timeout_add() is failed. %d:%s", cpc->type, cpc->loader_name);
1000 _E("Skip adding timer. detection_method(%d), state(%d)",
1001 cpc->detection_method, cpc->state);
1005 static void __reset_slot(candidate_process_context_t* cpc) {
1010 cpc->prepared = false;
1011 cpc->pid = CANDIDATE_NONE;
1012 cpc->client_channel = nullptr;
1014 cpc->live_timer = 0;
1015 cpc->on_boot_timer = 0;
1018 static void __dispose_candidate_process(candidate_process_context_t* cpc) {
1022 _D("Dispose candidate process %d:%s", cpc->type, cpc->loader_name);
1024 _D("kill process %d", cpc->pid);
1025 __kill_process(cpc->pid);
1027 if (cpc->live_timer > 0)
1028 g_source_remove(cpc->live_timer);
1029 if (cpc->client_channel)
1030 _io_channel_destroy(cpc->client_channel);
1032 g_source_remove(cpc->timer);
1033 if (cpc->send_fd > 0)
1034 close(cpc->send_fd);
1035 if (cpc->on_boot_timer > 0)
1036 g_source_remove(cpc->on_boot_timer);
1040 static void __dispose_hydra_process(candidate_process_context_t* cpc) {
1044 __dispose_candidate_process(cpc);
1046 _D("Dispose hydra process %d:%s", cpc->type, cpc->loader_name);
1047 if (cpc->hydra_pid > 0) {
1048 _D("kill process %d", cpc->hydra_pid);
1049 __kill_process(cpc->hydra_pid);
1050 cpc->hydra_pid = HYDRA_NONE;
1053 if (cpc->hydra_fd > 0) {
1054 close(cpc->hydra_fd);
1059 static int __send_launchpad_loader(candidate_process_context_t* cpc,
1061 const char* app_path,
1066 ret = _delete_sock_path(cpc->pid, getuid());
1070 __candidate_process_real_launch(cpc->send_fd, pkt);
1071 _W("Request to candidate process, pid: %d, bin path: %s", cpc->pid,
1075 cpc->pid = CANDIDATE_NONE;
1076 __dispose_candidate_process(cpc);
1078 __update_slot_score(cpc);
1083 static int __normal_fork_exec(int argc, char** argv, const char* app_path) {
1087 _D("start real fork and exec");
1089 libdir = _get_libdir(app_path);
1091 setenv("LD_LIBRARY_PATH", libdir, 1);
1097 if (execv(argv[LOADER_ARG_PATH], argv) < 0) { /* Flawfinder: ignore */
1098 _send_message_to_logger(argv[LOADER_ARG_PATH],
1099 "Failed to execute a file. error(%d:%s)", errno,
1100 strerror_r(errno, err_buf, sizeof(err_buf)));
1107 static int __create_launcher_argv(int* argc,
1109 const char* app_type) {
1111 char** launcher_argv;
1112 launchpad::LauncherInfoPtr launcher_info;
1116 auto it = std::find_if(
1117 launcher_info_list.begin(), launcher_info_list.end(),
1118 [app_type](const launchpad::LauncherInfoPtr& info) -> bool {
1119 return std::find_if(info->GetAppTypes().begin(),
1120 info->GetAppTypes().end(),
1121 [app_type](const std::string& type) -> bool {
1122 return strcmp(type.c_str(), app_type) == 0;
1123 }) != info->GetAppTypes().end();
1126 if (it == launcher_info_list.end())
1129 launcher_info = *it;
1130 exe = launcher_info->GetExe().c_str();
1132 auto& extra_args = launcher_info->GetExtraArgs();
1133 launcher_argc = extra_args.size() + 1;
1134 launcher_argv = static_cast<char**>(calloc(launcher_argc, sizeof(char*)));
1135 if (launcher_argv == nullptr) {
1136 _E("out of memory");
1140 i = LOADER_ARG_PATH;
1141 launcher_argv[i++] = strdup(exe);
1143 for (auto& extra_arg : extra_args) {
1144 launcher_argv[i++] = strdup(extra_arg.c_str());
1147 *argc = launcher_argc;
1148 *argv = launcher_argv;
1153 static void __destroy_launcher_argv(int argc, char** argv) {
1156 if (argv == nullptr)
1159 for (i = 0; i < argc; i++)
1164 static int __create_app_argv(int* argc,
1166 const char* app_path,
1168 const char* app_type) {
1171 bool attach = false;
1172 struct app_arg debug_arg = {
1175 struct app_arg launcher_arg = {
1178 struct app_arg arg = {
1181 struct app_arg debug_extra_arg = {
1188 ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach);
1190 _E("Failed to create debugger argv");
1195 *argc = debug_arg.argc;
1196 *argv = debug_arg.argv;
1200 ret = _debug_create_extra_argv(&debug_extra_arg.argc, &debug_extra_arg.argv);
1202 _E("Failed to create debugger extra argv");
1203 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1208 __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv, app_type);
1210 _E("Failed to create launcher argv");
1211 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1212 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1216 arg.argc = bundle_export_to_argv(kb, &arg.argv);
1217 if (arg.argc <= 0) {
1218 _E("Failed to export bundle");
1219 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
1220 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1221 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1224 arg.argv[LOADER_ARG_PATH] = strdup(app_path);
1227 debug_arg.argc + launcher_arg.argc + arg.argc + debug_extra_arg.argc;
1228 if (new_argc == arg.argc) {
1234 new_argv = (char**)calloc(new_argc + 1, sizeof(char*));
1235 if (new_argv == nullptr) {
1236 _E("out of memory");
1237 free(arg.argv[LOADER_ARG_PATH]);
1238 bundle_free_exported_argv(arg.argc, &arg.argv);
1239 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
1240 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1241 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1245 c = LOADER_ARG_PATH;
1246 for (i = 0; i < debug_arg.argc; i++)
1247 new_argv[c++] = debug_arg.argv[i];
1248 for (i = 0; i < launcher_arg.argc; i++)
1249 new_argv[c++] = launcher_arg.argv[i];
1250 for (i = 0; i < arg.argc; i++)
1251 new_argv[c++] = arg.argv[i];
1252 for (i = 0; i < debug_extra_arg.argc; i++)
1253 new_argv[c++] = debug_extra_arg.argv[i];
1261 static void __real_launch(const char* app_path,
1263 appinfo_t* menu_info) {
1269 if (bundle_get_val(kb, AUL_K_DEBUG) != nullptr)
1270 setenv("TIZEN_DEBUGGING_PORT", "1", 1);
1272 ret = __create_app_argv(&app_argc, &app_argv, app_path, kb,
1273 menu_info->app_type);
1275 _E("Failed to create app argv");
1279 for (i = 0; i < app_argc; i++)
1280 SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
1282 PERF("setup argument done");
1283 __normal_fork_exec(app_argc, app_argv, app_path);
1286 static int __prepare_exec(const char* appid,
1287 const char* app_path,
1288 appinfo_t* menu_info,
1291 const char* enabled_light_user;
1292 char process_name[AUL_PR_NAME];
1295 /* Set new session ID & new process group ID*/
1296 /* In linux, child can set new session ID without check permission */
1297 /* TODO : should be add to check permission in the kernel*/
1300 ret = _launchpad_plugin_prepare_app(appid, kb);
1302 _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret);
1303 return PAD_ERR_FAILED;
1306 ret = _enable_external_pkg(kb, menu_info->pkgid,
1307 menu_info->global ? GLOBAL_USER : getuid());
1309 return PAD_ERR_FAILED;
1311 if (menu_info->global)
1312 ret = trust_anchor_launch(menu_info->pkgid, GLOBAL_USER);
1314 ret = trust_anchor_launch(menu_info->pkgid, getuid());
1315 if (ret != TRUST_ANCHOR_ERROR_NONE &&
1316 ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) {
1317 _E("trust_anchor_launch() returns %d", ret);
1318 return PAD_ERR_REJECTED;
1321 ret = _mount_res_dir(menu_info->root_path, kb);
1323 return PAD_ERR_FAILED;
1325 if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1326 _debug_change_mount_namespace();
1329 enabled_light_user = bundle_get_val(kb, AUL_K_ENABLED_LIGHT_USER);
1330 _W("security_manager_prepare_app2 ++ %s", appid);
1331 ret = security_manager_prepare_app2(appid, enabled_light_user);
1332 _W("security_manager_prepare_app2 -- %s", appid);
1333 if (ret != SECURITY_MANAGER_SUCCESS)
1334 return PAD_ERR_REJECTED;
1336 if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE)
1337 _setup_stdio(basename(app_path));
1339 /* SET DUMPABLE - for coredump*/
1340 prctl(PR_SET_DUMPABLE, 1);
1342 /* SET PROCESS NAME*/
1343 if (app_path == nullptr)
1344 return PAD_ERR_INVALID_ARGUMENT;
1346 file_name = const_cast<char*>(strrchr(app_path, '/'));
1347 if (file_name == nullptr)
1348 return PAD_ERR_INVALID_PATH;
1351 if (*file_name == '\0')
1352 return PAD_ERR_INVALID_PATH;
1354 memset(process_name, '\0', AUL_PR_NAME);
1355 snprintf(process_name, AUL_PR_NAME, "%s", file_name);
1356 prctl(PR_SET_NAME, process_name);
1359 _set_env(menu_info, kb);
1361 ret = _wait_tep_mount(kb);
1363 return PAD_ERR_FAILED;
1365 if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) {
1366 ret = _prepare_app_socket();
1368 return PAD_ERR_FAILED;
1370 ret = _prepare_id_file();
1372 return PAD_ERR_FAILED;
1375 _send_cmd_to_amd(APP_STARTUP_SIGNAL);
1379 static int __exec_app_process(void* arg) {
1380 auto* launch_arg = static_cast<app_launch_arg*>(arg);
1383 _print_hwc_log("%d|after calling fork(). %s", getpid(), launch_arg->appid);
1385 _D("lock up test log(no error) : fork done");
1387 if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1388 _debug_prepare_debugger(launch_arg->kb);
1390 _signal_unblock_sigchld();
1392 _delete_sock_path(getpid(), getuid());
1394 PERF("prepare exec - first done");
1395 ret = __prepare_exec(launch_arg->appid, launch_arg->app_path,
1396 launch_arg->menu_info, launch_arg->kb);
1400 PERF("prepare exec - second done");
1401 __real_launch(launch_arg->app_path, launch_arg->kb, launch_arg->menu_info);
1403 return PAD_ERR_FAILED;
1406 static int __launch_directly(const char* appid,
1407 const char* app_path,
1410 appinfo_t* menu_info,
1411 candidate_process_context_t* cpc) {
1412 struct app_launch_arg arg;
1416 arg.app_path = app_path;
1417 arg.menu_info = menu_info;
1420 _print_hwc_log("before calling fork(). %s", appid);
1421 pid = __fork_app_process(__exec_app_process, &arg, 0);
1423 _E("failed to fork app process");
1425 SECURE_LOGD("==> real launch pid : %d %s", pid, app_path);
1430 static int __create_sock_activation(void) {
1432 char launchpad_process_pool_sock_path[108];
1435 fds = sd_listen_fds(0);
1436 snprintf(launchpad_process_pool_sock_path,
1437 sizeof(launchpad_process_pool_sock_path), "%s/daemons/%u/%s",
1438 SOCKET_PATH, getuid(), PROCESS_POOL_LAUNCHPAD_SOCK);
1440 for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + fds; ++i) {
1441 if (sd_is_socket_unix(i, SOCK_STREAM, 1, launchpad_process_pool_sock_path,
1446 _W("There is no socket stream");
1450 static int __get_launchpad_listen_fd(void) {
1453 val = getenv("LAUNCHPAD_LISTEN_FD");
1455 _E("Failed to get LAUNCHPAD_LISTEN_FD");
1459 _W("Listen Fd: %s", val);
1463 static int __launchpad_pre_init(int argc, char** argv) {
1466 /* create launchpad sock */
1467 fd = __create_sock_activation();
1471 fd = __get_launchpad_listen_fd();
1475 fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK);
1477 _E("server sock error %d", fd);
1484 static bool __handle_loader_client_event(int fd,
1485 io_condition_e cond,
1487 auto* cpc = static_cast<candidate_process_context_t*>(data);
1492 if (cond & (IO_HUP | IO_NVAL)) {
1494 "Type %d candidate process was "
1495 "(POLLHUP|POLLNVAL), pid: %d",
1496 cpc->type, cpc->pid);
1497 cpc->pid = CANDIDATE_NONE;
1498 __dispose_candidate_process(cpc);
1499 __prepare_candidate_process(cpc->type, cpc->loader_id);
1506 static bool __handle_hydra_client_event(int fd,
1507 io_condition_e cond,
1509 auto* cpc = static_cast<candidate_process_context_t*>(data);
1516 if (cond & (IO_HUP | IO_NVAL)) {
1518 "Type %d hydra process was "
1519 "(POLLHUP|POLLNVAL), pid: %d",
1520 cpc->type, cpc->hydra_pid);
1521 __dispose_hydra_process(cpc);
1522 __prepare_candidate_process(cpc->type, cpc->loader_id);
1527 ret = recv(cpc->hydra_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL);
1529 _E("recv() is failed. errno(%d)", errno);
1531 _W("candidate process: %d", recv_pid);
1533 cpc->pid = recv_pid;
1540 static bool __handle_loader_event(int fd, io_condition_e cond, void* data) {
1541 auto* cpc = static_cast<candidate_process_context_t*>(data);
1549 if (!cpc->prepared) {
1550 ret = __accept_candidate_process(fd, &client_fd, &client_pid,
1551 cpc->is_hydra ? -1 : cpc->pid);
1553 /* for hydra need to set pid to pid of non-hydra candidate, */
1554 /* which is connecting now */
1556 cpc->pid = client_pid;
1558 cpc->prepared = true;
1559 cpc->send_fd = client_fd;
1562 "Type %d candidate process was connected, "
1564 cpc->type, cpc->pid);
1567 "Type %d candidate process was connected, "
1569 cpc->type, cpc->pid);
1570 cpc->client_channel = _io_channel_create(
1571 client_fd, static_cast<io_condition_e>(IO_IN | IO_HUP),
1572 __handle_loader_client_event, cpc);
1573 if (!cpc->client_channel)
1577 __refuse_candidate_process(fd);
1578 _E("Refused candidate process connection");
1584 static bool __handle_hydra_event(int fd, io_condition_e cond, void* data) {
1585 auto* cpc = static_cast<candidate_process_context_t*>(data);
1593 if (!cpc->prepared) {
1595 __accept_candidate_process(fd, &client_fd, &client_pid, cpc->hydra_pid);
1597 cpc->hydra_fd = client_fd;
1600 "Type %d hydra process was connected,"
1602 cpc->type, cpc->hydra_pid);
1604 cpc->client_channel = _io_channel_create(
1605 client_fd, static_cast<io_condition_e>(IO_IN | IO_HUP),
1606 __handle_hydra_client_event, cpc);
1607 if (!cpc->client_channel)
1611 __refuse_candidate_process(fd);
1612 _E("Refused hydra process connection");
1618 static void __destroy_cleanup_info(struct cleanup_info_s* info) {
1626 static struct cleanup_info_s* __create_cleanup_info(const char* appid,
1628 struct cleanup_info_s* info;
1630 info = static_cast<cleanup_info_s*>(malloc(sizeof(struct cleanup_info_s)));
1632 _E("Out of memory");
1636 info->appid = strdup(appid);
1638 _E("strdup(%s) is failed", appid);
1639 __destroy_cleanup_info(info);
1648 static bool __cleanup_app_cb(void* user_data) {
1649 struct cleanup_info_s* info = (struct cleanup_info_s*)user_data;
1651 _W("security_manager_cleanup_app() ++");
1652 security_manager_cleanup_app(info->appid, getuid(), info->pid);
1653 _W("security_manager_cleanup_app() --");
1654 __destroy_cleanup_info(info);
1658 static void __handle_sigchild(int pid, void* user_data) {
1659 candidate_process_context_t* cpc;
1660 struct cleanup_info_s* info;
1664 appid = static_cast<char*>(
1665 g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid)));
1667 info = __create_cleanup_info(appid, pid);
1669 ret = _worker_add_job(__cleaner, __cleanup_app_cb, info);
1672 __destroy_cleanup_info(info);
1673 _W("security_manager_cleanup_app() ++");
1674 security_manager_cleanup_app(appid, getuid(), pid);
1675 _W("security_manager_cleanup_app() --");
1678 g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid));
1681 _log_print("[SIGCHLD]", "pid(%7d)", pid);
1682 cpc = __find_slot_from_pid(pid);
1683 if (cpc != nullptr) {
1684 cpc->pid = CANDIDATE_NONE;
1685 __dispose_candidate_process(cpc);
1686 __prepare_candidate_process(cpc->type, cpc->loader_id);
1688 cpc = __find_hydra_slot_from_pid(pid);
1689 if (cpc != nullptr) {
1690 cpc->hydra_pid = HYDRA_NONE;
1691 __dispose_hydra_process(cpc);
1692 __prepare_candidate_process(cpc->type, cpc->loader_id);
1696 cpc = __find_slot_from_caller_pid(pid);
1698 __remove_slot(static_cast<int>(launchpad::LoaderType::Dynamic), cpc->loader_id);
1699 cpc = __find_slot_from_caller_pid(pid);
1703 static bool __handle_label_monitor(int fd, io_condition_e cond, void* data) {
1704 candidate_process_context_t* cpc;
1705 GList* iter = candidate_slot_list;
1707 if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
1708 _E("fd(%d), io_condition(%d)", fd, cond);
1713 _D("fd(%d) condition(%d)", fd, cond);
1714 _log_print("[LABEL]", "fd(%d), condition(%d)", fd, cond);
1715 security_manager_app_labels_monitor_process(label_monitor);
1718 cpc = (candidate_process_context_t*)iter->data;
1719 if (cpc->is_hydra) {
1720 if (cpc->hydra_pid > 0) {
1721 __dispose_hydra_process(cpc);
1722 __prepare_candidate_process(cpc->type, cpc->loader_id);
1724 } else if (cpc->pid > 0) {
1725 __dispose_candidate_process(cpc);
1726 __prepare_candidate_process(cpc->type, cpc->loader_id);
1729 iter = g_list_next(iter);
1735 static float __interpolator(float input, int cpu_max, int cpu_min) {
1737 float min = cpu_min / 100.0f;
1738 float max = cpu_max / 100.0f;
1745 ret = cos(input * PI) / 2.0f + 0.5f;
1752 static void __update_threshold(candidate_process_context_t* cpc, float delta) {
1753 static float pos = 0.0f;
1763 (int)(__interpolator(pos, cpc->threshold_max, cpc->threshold_min) * 100);
1764 _D("[CPU] type:%d / delta:%f / input cursor : %f / threshold : %d", cpc->type,
1765 delta, pos, cpc->threshold);
1768 static gboolean __handle_idle_checker(gpointer data) {
1769 unsigned long long total = 0;
1770 unsigned long long idle = 0;
1772 candidate_process_context_t* cpc;
1775 _E("Critical error!");
1776 __sequencer.idle_checker = 0;
1777 __sequencer.running_cpc = nullptr;
1778 return G_SOURCE_REMOVE;
1781 cpc = (candidate_process_context_t*)data;
1782 if (cpc->app_check && !cpc->app_exists) {
1783 _W("The application is not installed. loader(%s:%d)", cpc->loader_name,
1785 __sequencer.idle_checker = 0;
1786 __sequencer.running_cpc = nullptr;
1787 return G_SOURCE_REMOVE;
1790 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1791 _W("Slot state is not running. loader(%s:%d)", cpc->loader_name, cpc->type);
1792 __sequencer.idle_checker = 0;
1793 __sequencer.running_cpc = nullptr;
1794 return G_SOURCE_REMOVE;
1797 if (cpc->pid != CANDIDATE_NONE) {
1798 _W("Slot is already running. %d:%s:%d", cpc->type, cpc->loader_name,
1800 __sequencer.idle_checker = 0;
1801 __sequencer.running_cpc = nullptr;
1802 return G_SOURCE_REMOVE;
1805 _get_cpu_idle(&total, &idle);
1806 if (total == cpc->cpu_total_time)
1809 per = (idle - cpc->cpu_idle_time) * 100 / (total - cpc->cpu_total_time);
1810 _D("[CPU] Idle : %d / loader(%s:%d)", per, cpc->loader_name, cpc->type);
1812 if (per >= cpc->threshold) {
1813 __update_threshold(cpc, -0.02f * (per - cpc->threshold));
1814 __prepare_candidate_process(cpc->type, cpc->loader_id);
1815 cpc->touched = true;
1816 __sequencer.idle_checker = 0;
1817 __sequencer.running_cpc = nullptr;
1818 return G_SOURCE_REMOVE;
1821 cpc->cpu_idle_time = idle;
1822 cpc->cpu_total_time = total;
1823 __update_threshold(cpc, 0.05f);
1825 cpc->cpu_check_count++;
1826 if (cpc->cpu_check_count == MAX_CPU_CHECK_COUNT) {
1827 _W("CPU check count has exceeded %d times. loader(%s:%d)",
1828 cpc->cpu_check_count, cpc->loader_name, cpc->type);
1829 __sequencer.idle_checker = 0;
1830 __sequencer.running_cpc = nullptr;
1831 __sequencer_add_slot(cpc);
1832 return G_SOURCE_REMOVE;
1835 return G_SOURCE_CONTINUE;
1838 static gboolean __on_boot_timeout_cb(gpointer user_data) {
1839 auto* context = static_cast<candidate_process_context_t*>(user_data);
1841 _W("type(%d), loader_name(%s)", context->type, context->loader_name);
1842 context->on_boot_timer = 0;
1843 if (context->pid != CANDIDATE_NONE) {
1844 _E("Candidate process is already running. %d:%s:%d", context->type,
1845 context->loader_name, context->pid);
1847 auto iter = context->condition_path_exists.begin();
1848 while (iter != context->condition_path_exists.end()) {
1850 if (access(path.c_str(), F_OK) != 0) {
1851 _D("%s does not exist", path.c_str());
1852 context->on_boot_timer = g_timeout_add(100, __on_boot_timeout_cb,
1854 return G_SOURCE_REMOVE;
1857 iter = context->condition_path_exists.erase(iter);
1860 __prepare_candidate_process(context->type, context->loader_id);
1861 context->touched = true;
1864 return G_SOURCE_REMOVE;
1867 static void __add_on_boot_timer(candidate_process_context_t* context) {
1868 if (context->on_boot_timer != 0)
1871 context->on_boot_timer =
1872 g_timeout_add(context->on_boot_timeout, __on_boot_timeout_cb, context);
1875 static int __add_idle_checker(int detection_method, GList* cur) {
1876 candidate_process_context_t* cpc;
1880 cpc = (candidate_process_context_t*)iter->data;
1881 if (!cpc->touched && cpc->on_boot && cpc->on_boot_timeout > 0)
1882 __add_on_boot_timer(cpc);
1884 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1885 iter = g_list_next(iter);
1889 if (strcmp("null", cpc->loader_path) == 0) {
1890 iter = g_list_next(iter);
1894 if (!cpc->touched && !cpc->on_boot) {
1895 iter = g_list_next(iter);
1899 if (cpc->app_check && !cpc->app_exists) {
1900 iter = g_list_next(iter);
1904 if (cpc->pid == CANDIDATE_NONE &&
1905 (!cpc->touched || (cpc->detection_method & detection_method))) {
1906 if (cpc->timer > 0) {
1907 g_source_remove(cpc->timer);
1911 cpc->cur_event = detection_method;
1912 __sequencer_add_slot(cpc);
1916 iter = g_list_next(iter);
1922 static int __dispatch_cmd_hint(bundle* kb, int detection_method) {
1923 _W("cmd hint %d", detection_method);
1924 __add_idle_checker(detection_method, candidate_slot_list);
1929 static int __dispatch_cmd_add_loader(bundle* kb) {
1930 const char* add_slot_str = nullptr;
1931 const char* caller_pid = nullptr;
1935 candidate_process_context_t* cpc;
1936 slot_info_t slot_info;
1938 _W("cmd add loader");
1939 add_slot_str = bundle_get_val(kb, AUL_K_LOADER_PATH);
1940 caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID);
1941 extra = bundle_get_val(kb, AUL_K_LOADER_EXTRA);
1943 if (add_slot_str == nullptr || caller_pid == nullptr)
1946 lid = __make_loader_id();
1947 size = snprintf(0, 0, "%s%s%d", add_slot_str, caller_pid, lid);
1948 loader_name = (char*)malloc(size + 1);
1949 if (loader_name == nullptr) {
1950 _E("Out of memory");
1954 snprintf(loader_name, size, "%s%s%d", add_slot_str, caller_pid, lid);
1956 slot_info.type = static_cast<int>(launchpad::LoaderType::Dynamic);
1957 slot_info.loader_id = lid;
1958 slot_info.caller_pid = atoi(caller_pid);
1959 slot_info.loader_name = loader_name;
1960 slot_info.loader_path = add_slot_str;
1961 slot_info.loader_extra = extra;
1962 slot_info.detection_method = static_cast<int>(
1963 launchpad::LoaderMethod::Timeout | launchpad::LoaderMethod::Visibility);
1964 slot_info.activation_method =
1965 static_cast<int>(launchpad::LoaderMethod::Request |
1966 launchpad::LoaderMethod::AvailableMemory);
1967 slot_info.deactivation_method = static_cast<int>(
1968 launchpad::LoaderMethod::Ttl | launchpad::LoaderMethod::OutOfMemory);
1969 slot_info.ttl = 600;
1970 slot_info.timeout_val = 2000;
1971 slot_info.threshold_max = launchpad::DefaultCpuThresholdMax;
1972 slot_info.threshold_min = launchpad::DefaultCpuThresholdMin;
1973 slot_info.on_boot = false;
1974 slot_info.app_exists = true;
1975 slot_info.is_hydra = false;
1976 slot_info.app_check = true;
1977 slot_info.on_boot_timeout = 0;
1978 slot_info.sched_priority = 0;
1980 cpc = __add_slot(&slot_info);
1989 static int __dispatch_cmd_add_app_defined_loader(bundle* kb) {
1990 const char* loader_name;
1992 candidate_process_context_t* cpc;
1993 launchpad::LoaderInfoPtr info;
1995 slot_info_t slot_info;
1997 _W("cmd add defined loader");
1998 loader_name = bundle_get_val(kb, AUL_K_LOADER_NAME);
2000 if (loader_name == nullptr) {
2001 _E("loader_name is nullptr");
2005 info = app_defined_loader_info_manager->FindLoaderInfo(loader_name);
2006 if (info == nullptr) {
2007 _E("loader_name %s, info %d", loader_name, info != nullptr);
2011 cpc = __find_slot_from_loader_name(loader_name);
2012 if (cpc == nullptr) {
2013 lid = __make_loader_id();
2014 bundle_encode(info->GetExtra().GetHandle(), &extra, &len);
2015 slot_info.type = static_cast<int>(launchpad::LoaderType::Dynamic);
2016 slot_info.loader_id = lid;
2017 slot_info.caller_pid = 0;
2018 slot_info.loader_name = loader_name;
2019 slot_info.loader_path = "/usr/bin/app-defined-loader";
2020 slot_info.loader_extra = (const char*)extra;
2021 slot_info.detection_method = static_cast<int>(launchpad::LoaderMethod::Timeout) | static_cast<int>(launchpad::LoaderMethod::Visibility);
2022 slot_info.activation_method = static_cast<int>(launchpad::LoaderMethod::Request) | static_cast<int>(launchpad::LoaderMethod::AvailableMemory);
2023 slot_info.deactivation_method = static_cast<int>(launchpad::LoaderMethod::Ttl) | static_cast<int>(launchpad::LoaderMethod::OutOfMemory);
2024 slot_info.ttl = info->GetTtl();
2025 slot_info.timeout_val = 2000;
2026 slot_info.threshold_max = launchpad::DefaultCpuThresholdMax;
2027 slot_info.threshold_min = launchpad::DefaultCpuThresholdMin;
2028 slot_info.on_boot = false;
2029 slot_info.app_exists = true;
2030 slot_info.is_hydra = false;
2031 slot_info.app_check = true;
2032 slot_info.on_boot_timeout = 0;
2033 slot_info.sched_priority = 0;
2035 cpc = __add_slot(&slot_info);
2036 bundle_free_encoded_rawdata(&extra);
2037 if (cpc == nullptr) {
2038 _E("cpc is nullptr");
2042 lid = cpc->loader_id;
2045 if (cpc->pid == CANDIDATE_NONE)
2046 __prepare_candidate_process(static_cast<int>(launchpad::LoaderType::Dynamic), lid);
2051 static int __dispatch_cmd_remove_loader(bundle* kb) {
2052 const char* id = bundle_get_val(kb, AUL_K_LOADER_ID);
2055 _W("cmd remove loader");
2058 if (__remove_slot(static_cast<int>(launchpad::LoaderType::Dynamic), lid) == 0)
2065 static int __check_caller_by_pid(int pid) {
2067 char buf[PATH_MAX] = {
2071 ret = _proc_get_attr(pid, buf, sizeof(buf));
2075 if (strcmp(buf, "User") == 0 || strcmp(buf, "System") == 0 ||
2076 strcmp(buf, "System::Privileged") == 0)
2082 static bool __is_hw_acc(const char* hwacc) {
2083 if (strcmp(hwacc, "USE") == 0 ||
2084 (strcmp(hwacc, "SYS") == 0 && __sys_hwacc == SETTING_HW_ACCELERATION_ON))
2090 static candidate_process_context_t* __find_available_slot(
2092 const char* app_type,
2093 const char* loader_name,
2094 candidate_process_context_t** org_cpc) {
2095 launchpad::LoaderType type = launchpad::LoaderType::Unsupported;
2096 candidate_process_context_t* cpc;
2099 for (auto& info : loader_info_manager->GetLoaderInfoList()) {
2100 if (info->GetName() == loader_name) {
2101 type = info->GetType();
2106 if (__is_hw_acc(hwacc))
2107 type = loader_info_manager->FindHwType(app_type);
2109 type = loader_info_manager->FindSwType(app_type);
2112 cpc = __find_slot(static_cast<int>(type), PAD_LOADER_ID_STATIC);
2121 auto a_types = loader_info_manager->GetAlternativeTypes(type);
2122 if (a_types.empty())
2125 for (auto& a_type : a_types) {
2126 cpc = __find_slot(static_cast<int>(a_type), PAD_LOADER_ID_STATIC);
2129 if (cpc->prepared) {
2137 static void __update_slot(int type, bool app_exists) {
2138 candidate_process_context_t* cpc;
2140 cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
2144 cpc->app_exists = app_exists;
2145 _W("type(%d), loader_name(%s), app_check(%d), app_exists(%d)",
2146 cpc->type, cpc->loader_name, cpc->app_check, cpc->app_exists);
2147 if (cpc->app_check && !cpc->app_exists) {
2149 __dispose_candidate_process(cpc);
2150 __sequencer_remove_slot(cpc);
2151 if (__sequencer_queue_is_empty())
2154 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING)
2157 if (!cpc->touched && !cpc->on_boot)
2160 if (cpc->timer > 0) {
2161 g_source_remove(cpc->timer);
2165 if (cpc->pid == CANDIDATE_NONE) {
2166 __sequencer_add_slot(cpc);
2172 static void __foreach_loader_info(const launchpad::LoaderInfoPtr& info,
2174 struct app_info* ai = (struct app_info*)data;
2175 auto it = std::find_if(
2176 info->GetAppTypes().begin(), info->GetAppTypes().end(),
2177 [&](const std::string& type) -> bool { return type == ai->type; });
2179 if (it == info->GetAppTypes().end())
2182 info->SetAppExists(ai->exists);
2183 __update_slot(static_cast<int>(info->GetType()), info->IsAppExists());
2186 static int __dispatch_cmd_update_app_type(bundle* b) {
2187 struct app_info info;
2188 const char* is_installed;
2190 info.type = bundle_get_val(b, AUL_K_APP_TYPE);
2194 is_installed = bundle_get_val(b, AUL_K_IS_INSTALLED);
2195 if (is_installed && !strcmp(is_installed, "true"))
2198 info.exists = false;
2200 _I("[LAUNCHPAD] type(%s), exists(%d)", info.type, info.exists);
2202 for (auto& linfo : loader_info_manager->GetLoaderInfoList()) {
2203 __foreach_loader_info(linfo, &info);
2209 static void __deactivate_slot(candidate_process_context_t* cpc) {
2210 _W("type(%d), loader_name(%s), state(%d)",
2211 cpc->type, cpc->loader_name, cpc->state);
2212 if (cpc->state == CANDIDATE_PROCESS_STATE_PAUSED)
2215 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2217 __dispose_hydra_process(cpc);
2219 __dispose_candidate_process(cpc);
2222 static void __activate_slot(candidate_process_context_t* cpc) {
2223 _W("type(%d), loader_name(%s), state(%d)",
2224 cpc->type, cpc->loader_name, cpc->state);
2225 if (cpc->state == CANDIDATE_PROCESS_STATE_RUNNING)
2228 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2229 if (!cpc->touched && !cpc->on_boot)
2232 if ((cpc->app_check && !cpc->app_exists) || cpc->pid > CANDIDATE_NONE)
2235 if (cpc->detection_method &
2236 static_cast<int>(launchpad::LoaderMethod::Timeout))
2240 static void __update_slot_state(candidate_process_context_t* cpc,
2241 launchpad::LoaderMethod method, bool force) {
2242 _W("type(%d), loader_name(%s), state(%d), method(%d), force(%d)",
2243 cpc->type, cpc->loader_name, cpc->state, static_cast<int>(method), force);
2245 case launchpad::LoaderMethod::OutOfMemory:
2246 if ((force || cpc->deactivation_method & static_cast<int>(method)) &&
2247 __is_low_memory()) {
2248 _W("Low memory, deactivate slot %d", cpc->type);
2249 __deactivate_slot(cpc);
2251 __activate_slot(cpc);
2254 case launchpad::LoaderMethod::Ttl:
2255 if (force || cpc->deactivation_method & static_cast<int>(method))
2256 __deactivate_slot(cpc);
2258 case launchpad::LoaderMethod::AvailableMemory:
2259 if (force || cpc->activation_method & static_cast<int>(method))
2260 __activate_slot(cpc);
2262 case launchpad::LoaderMethod::Request:
2263 if (force || cpc->activation_method & static_cast<int>(method))
2264 __update_slot_state(cpc, launchpad::LoaderMethod::OutOfMemory, force);
2267 __activate_slot(cpc);
2272 static void __request_destroy(request_t* request) {
2273 if (request == nullptr)
2276 if (request->clifd > -1)
2277 close(request->clifd);
2278 if (request->menu_info)
2279 _appinfo_free(request->menu_info);
2281 bundle_free(request->kb);
2287 static int __request_create(int fd, request_t** request) {
2291 if (request == nullptr) {
2292 _E("Invalid parameter");
2296 req = static_cast<request_t*>(calloc(1, sizeof(request_t)));
2297 if (req == nullptr) {
2298 _E("calloc() is failed");
2303 req->pkt = _accept_recv_pkt_raw(fd, &req->clifd, &cr);
2304 if (req->pkt == nullptr) {
2305 _E("_accept_recv_pkt_raw() is failed");
2306 __request_destroy(req);
2310 req->kb = bundle_decode(req->pkt->data, req->pkt->len);
2311 if (req->kb == nullptr) {
2312 _E("bundle_decode() is failed");
2313 __real_send(req->clifd, -EINVAL);
2315 __request_destroy(req);
2319 req->cmd = req->pkt->cmd;
2320 req->caller_pid = cr.pid;
2321 req->caller_uid = cr.uid;
2326 static void __request_send_result(request_h request, int result) {
2327 if (request->clifd < 0)
2330 __real_send(request->clifd, result);
2331 request->clifd = -1;
2334 static int __visibility_request_handler(request_h request) {
2335 int ret = __dispatch_cmd_hint(request->kb,
2336 static_cast<int>(launchpad::LoaderMethod::Visibility));
2338 __request_send_result(request, ret);
2339 _D("[PAD_CMD_VISIBILITY] result: %d", ret);
2343 static int __add_loader_request_handler(request_h request) {
2344 int ret = __dispatch_cmd_add_loader(request->kb);
2346 __request_send_result(request, ret);
2347 _D("[PAD_CMD_ADD_LOADER] result: %d", ret);
2351 static int __remove_loader_request_handler(request_h request) {
2352 int ret = __dispatch_cmd_remove_loader(request->kb);
2354 __request_send_result(request, ret);
2355 _D("[PAD_CMD_REMOVE_LOADER] result: %d", ret);
2359 static int __make_default_slots_request_handler(request_h request) {
2360 int ret = __add_default_slots();
2362 __request_send_result(request, ret);
2363 _D("[PAD_CMD_MAKE_DEFAULT_SLOTS] result: %d", ret);
2367 static int __prepare_app_defined_loader_request_handler(request_h request) {
2368 int ret = __dispatch_cmd_add_app_defined_loader(request->kb);
2370 __request_send_result(request, ret);
2371 _D("[PAD_CMD_PREPARE_APP_DEFINED_LOADER] result: %d", ret);
2375 static int __demand_request_handler(request_h request) {
2376 int ret = __dispatch_cmd_hint(request->kb,
2377 static_cast<int>(launchpad::LoaderMethod::Demand));
2379 __request_send_result(request, ret);
2380 _D("[PAD_CMD_DEMAND] result: %d", ret);
2384 static int __ping_request_handler(request_h request) {
2385 __request_send_result(request, getpid());
2386 _D("[PAD_CMD_PING] result: %d", getpid());
2390 static int __update_app_type_request_handler(request_h request) {
2391 int ret = __dispatch_cmd_update_app_type(request->kb);
2393 _D("[PAD_CMD_UPDATE_APP_TYPE] result: %d", ret);
2397 static int __connect_request_handler(request_h request) {
2398 if (__client_fd != -1)
2401 __client_fd = request->clifd;
2402 request->clifd = -1;
2403 _D("[PAD_CMD_CONNECT] client fd: %d", __client_fd);
2407 static int __launch_request_prepare(request_h request) {
2408 const appinfo_t* menu_info;
2411 request->menu_info = _appinfo_create(request->kb);
2412 if (request->menu_info == nullptr) {
2413 _E("_appinfo_create() is failed");
2417 request->app_path = _appinfo_get_app_path(request->menu_info);
2418 if (request->app_path == nullptr) {
2419 _E("_appinfo_get_app_path() is failed");
2423 if (request->app_path[0] != '/') {
2424 _E("app path is not absolute path");
2428 menu_info = request->menu_info;
2429 if (menu_info->hwacc == nullptr) {
2430 _E("Failed to find HW acceeleration type");
2434 SECURE_LOGD("appid: %s", menu_info->appid);
2435 SECURE_LOGD("exec: %s", menu_info->app_path);
2436 SECURE_LOGD("comp_type: %s", menu_info->comp_type);
2437 SECURE_LOGD("internal pool: %s", menu_info->internal_pool);
2438 SECURE_LOGD("hwacc: %s", menu_info->hwacc);
2439 SECURE_LOGD("app_type: %s", menu_info->app_type);
2440 SECURE_LOGD("pkg_type: %s", menu_info->pkg_type);
2442 if (menu_info->comp_type && !strcmp(menu_info->comp_type, "svcapp")) {
2443 request->loader_id = __get_loader_id(request->kb);
2444 if (request->loader_id > PAD_LOADER_ID_DYNAMIC_BASE) {
2445 type = static_cast<int>(launchpad::LoaderType::Dynamic);
2446 request->cpc = __find_slot(type, request->loader_id);
2447 if (request->cpc && !request->cpc->prepared)
2448 request->cpc = nullptr;
2450 request->loader_id = PAD_LOADER_ID_DIRECT;
2452 } else if (menu_info->comp_type && menu_info->app_type &&
2453 !strcmp(menu_info->comp_type, "widgetapp") &&
2454 !strcmp(menu_info->app_type, "webapp")) {
2455 request->loader_id = PAD_LOADER_ID_DIRECT;
2457 request->loader_id = __get_loader_id(request->kb);
2458 if (request->loader_id <= PAD_LOADER_ID_STATIC) {
2460 __find_available_slot(menu_info->hwacc, menu_info->app_type,
2461 menu_info->loader_name, &request->org_cpc);
2463 type = static_cast<int>(launchpad::LoaderType::Dynamic);
2464 request->cpc = __find_slot(type, request->loader_id);
2465 if (request->cpc && !request->cpc->prepared)
2466 request->cpc = nullptr;
2470 _modify_bundle(request->kb, request->caller_pid, request->menu_info,
2472 if (menu_info->appid == nullptr) {
2473 _E("Unable to get appid from app info");
2477 PERF("Getting package information & modifying bundle done");
2481 static void __launch_request_complete(request_h request) {
2482 _memory_monitor_reset_timer();
2483 __request_send_result(request, request->pid);
2485 if (request->pid > 0) {
2486 _dbus_send_app_launch_signal(request->pid, request->menu_info->appid);
2487 g_hash_table_insert(__pid_table, GINT_TO_POINTER(request->pid),
2488 strdup(request->menu_info->appid));
2489 _log_print("[LAUNCH]", "pid(%7d) | appid(%s)", request->pid,
2490 request->menu_info->appid);
2494 static void __handle_direct_launch(request_h request) {
2495 if (request->org_cpc &&
2496 (!request->org_cpc->app_check || request->org_cpc->app_exists) &&
2497 request->org_cpc->pid == CANDIDATE_NONE &&
2498 !__sequencer_slot_exist(request->org_cpc)) {
2499 if (request->org_cpc->timer > 0) {
2500 g_source_remove(request->org_cpc->timer);
2501 request->org_cpc->timer = 0;
2504 __update_slot_state(request->org_cpc, launchpad::LoaderMethod::Request, true);
2505 __set_timer(request->org_cpc);
2509 static void __fork_processing(request_h request) {
2510 if (bundle_get_type(request->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
2513 _W("appid: %s", request->menu_info->appid);
2514 request->pid = __launch_directly(request->menu_info->appid, request->app_path,
2515 request->clifd, request->kb,
2516 request->menu_info, nullptr);
2517 if (request->pid == -1) {
2518 _E("Failed to create a child process. appid(%s)",
2519 request->menu_info->appid);
2522 __request_send_result(request, request->pid);
2523 _W("appid: %s, pid: %d", request->menu_info->appid, request->pid);
2524 __handle_direct_launch(request);
2527 static int __launch_request_do(request_h request) {
2528 if (request->loader_id == PAD_LOADER_ID_DIRECT || request->cpc == nullptr) {
2529 __fork_processing(request);
2533 _W("Launch %d type process. appid(%s)", request->cpc->type,
2534 request->menu_info->appid);
2535 request->pid = __send_launchpad_loader(request->cpc, request->pkt,
2536 request->app_path, request->clifd);
2540 static int __launch_request_handler(request_h request) {
2543 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH");
2545 PERF("Packet processing start");
2547 ret = __launch_request_prepare(request);
2549 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
2550 __request_send_result(request, ret);
2554 ret = __launch_request_do(request);
2558 __launch_request_complete(request);
2559 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
2560 _D("[PAD_CMD_LAUNCH] appid: %s, result: %d", request->menu_info->appid,
2565 static request_handler __request_handlers[PAD_CMD_CONNECT + 1] = {};
2567 static bool __handle_launch_event(int fd, io_condition_e cond, void* data) {
2568 request_t* request = nullptr;
2571 if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
2572 _E("fd(%d), condition(%d)", fd, cond);
2573 g_idle_add(__launchpad_recovery_cb, __launchpad_channel);
2574 __launchpad_channel = nullptr;
2578 ret = __request_create(fd, &request);
2582 _W("cmd(%d), caller(%d)", request->cmd, request->caller_pid);
2583 if (request->caller_uid >= REGULAR_UID_MIN) {
2584 if (__check_caller_by_pid(request->caller_pid) < 0) {
2585 _E("Permission denied. pid(%d)", request->caller_pid);
2586 __request_send_result(request, -EPERM);
2587 __request_destroy(request);
2592 if (request->cmd < 0 || request->cmd >= ARRAY_SIZE(__request_handlers) ||
2593 __request_handlers[request->cmd] == nullptr) {
2594 _E("Unknown command: %d", request->cmd);
2595 __request_send_result(request, -EINVAL);
2596 __request_destroy(request);
2600 __request_handlers[request->cmd](request);
2601 __request_destroy(request);
2605 static void __destroy_slot(candidate_process_context_t* cpc) {
2609 if (cpc->hydra_channel)
2610 _io_channel_destroy(cpc->hydra_channel);
2613 _io_channel_destroy(cpc->channel);
2615 if (cpc->loader_extra)
2616 free(cpc->loader_extra);
2618 if (cpc->loader_path)
2619 free(cpc->loader_path);
2621 if (cpc->loader_name)
2622 free(cpc->loader_name);
2627 static candidate_process_context_t* __create_slot(slot_info_t* info) {
2628 candidate_process_context_t* cpc;
2630 cpc = new candidate_process_context_t();
2631 if (cpc == nullptr) {
2632 _E("Out of memory");
2636 cpc->loader_name = strdup(info->loader_name);
2637 if (cpc->loader_name == nullptr) {
2638 _E("Failed to duplicate loader name(%s)", info->loader_name);
2639 __destroy_slot(cpc);
2643 cpc->loader_path = strdup(info->loader_path);
2644 if (cpc->loader_path == nullptr) {
2645 _E("Failed to duplicate loader path(%s)", info->loader_path);
2646 __destroy_slot(cpc);
2651 info->loader_extra ? strdup(info->loader_extra) : strdup("");
2652 if (cpc->loader_extra == nullptr) {
2653 _E("Failed to duplicate loader extra(%s)", info->loader_extra);
2654 __destroy_slot(cpc);
2658 cpc->type = info->type;
2659 cpc->prepared = false;
2660 cpc->pid = CANDIDATE_NONE;
2661 cpc->hydra_pid = HYDRA_NONE;
2662 cpc->caller_pid = info->caller_pid;
2663 cpc->loader_id = info->loader_id;
2666 cpc->last_exec_time = 0;
2668 cpc->detection_method = info->detection_method;
2669 cpc->timeout_val = info->timeout_val;
2670 cpc->cpu_total_time = 0;
2671 cpc->cpu_idle_time = 0;
2672 cpc->threshold = info->threshold_max;
2673 cpc->threshold_max = info->threshold_max;
2674 cpc->threshold_min = info->threshold_min;
2675 cpc->on_boot = info->on_boot;
2676 cpc->app_exists = info->app_exists;
2677 cpc->touched = false;
2679 cpc->activation_method = info->activation_method;
2680 cpc->deactivation_method = info->deactivation_method;
2681 cpc->ttl = info->ttl;
2682 cpc->live_timer = 0;
2683 cpc->is_hydra = info->is_hydra;
2684 cpc->app_check = info->app_check;
2685 cpc->client_channel = nullptr;
2686 cpc->channel = nullptr;
2687 cpc->hydra_channel = nullptr;
2688 cpc->score = WIN_SCORE;
2690 cpc->cpu_check_count = 0;
2691 cpc->on_boot_timeout = info->on_boot_timeout;
2692 cpc->on_boot_timer = 0;
2693 cpc->sched_priority = info->sched_priority;
2694 cpc->condition_path_exists = info->condition_path_exists;
2696 if ((cpc->deactivation_method & static_cast<int>(launchpad::LoaderMethod::OutOfMemory)) && __is_low_memory())
2697 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2699 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2701 _W("loader(%s), type(%d), state(%d)", cpc->loader_name, cpc->type,
2706 static candidate_process_context_t* __add_slot(slot_info_t* info) {
2707 candidate_process_context_t* cpc;
2709 io_channel_h channel;
2711 io_channel_h hydra_channel;
2713 if (info == nullptr)
2716 if (__find_slot(info->type, info->loader_id) != nullptr)
2719 cpc = __create_slot(info);
2723 fd = __listen_candidate_process(cpc->type, cpc->loader_id);
2725 _E("[launchpad] Listening the socket to "
2726 "the type %d candidate process failed.",
2728 __destroy_slot(cpc);
2732 channel = _io_channel_create(fd, IO_IN, __handle_loader_event, cpc);
2735 __destroy_slot(cpc);
2739 cpc->channel = channel;
2741 if (info->is_hydra) {
2742 hydra_fd = __listen_hydra_process(cpc->type, cpc->loader_id);
2743 if (hydra_fd == -1) {
2744 _E("[launchpad] Listening the socket to "
2745 "the type %d hydra process failed.",
2747 __destroy_slot(cpc);
2752 _io_channel_create(hydra_fd, IO_IN, __handle_hydra_event, cpc);
2753 if (!hydra_channel) {
2755 __destroy_slot(cpc);
2759 cpc->hydra_channel = hydra_channel;
2762 candidate_slot_list = g_list_append(candidate_slot_list, cpc);
2767 static int __remove_slot(int type, int loader_id) {
2768 candidate_process_context_t* cpc;
2771 iter = candidate_slot_list;
2773 cpc = (candidate_process_context_t*)iter->data;
2774 if (type == cpc->type && loader_id == cpc->loader_id) {
2775 __dispose_candidate_process(cpc);
2776 candidate_slot_list = g_list_delete_link(candidate_slot_list, iter);
2777 __destroy_slot(cpc);
2781 iter = g_list_next(iter);
2787 static int __init_launchpad_fd(int argc, char** argv) {
2790 fd = __launchpad_pre_init(argc, argv);
2792 _E("launchpad pre init failed");
2796 auto cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
2797 __launchpad_channel = _io_channel_create(
2798 fd, static_cast<io_condition_e>(cond), __handle_launch_event, nullptr);
2799 if (!__launchpad_channel) {
2807 static bool __on_directory_create(const char* event_name,
2811 _E("Invalid parameter");
2815 if (!strcmp(event_name, LOADERS_PATH)) {
2816 _W("%s is created", LOADERS_PATH);
2817 __init_app_defined_loader_monitor();
2824 static bool __on_file_change(const char* event_name,
2829 launchpad::LoaderInfoPtr info;
2830 candidate_process_context_t* cpc;
2833 _E("Invalid parameter");
2837 ext = const_cast<char*>(strrchr(event_name, '.'));
2838 if (ext == nullptr || strcmp(ext, ".loader") != 0)
2841 _W("event_name(%s), mask(%u)", event_name, mask);
2842 if (mask & IN_CREATE) {
2843 app_defined_loader_info_manager->LoadFile(event_name);
2844 } else if (mask & IN_DELETE) {
2845 snprintf(buf, ext - event_name + 1, "%s", event_name);
2847 info = app_defined_loader_info_manager->FindLoaderInfo(buf);
2848 cpc = __find_slot_from_loader_name(info->GetName().c_str());
2849 __remove_slot(cpc->type, cpc->loader_id);
2850 app_defined_loader_info_manager->Unload(buf);
2856 static void __init_app_defined_loader_monitor(void) {
2859 ret = access(APP_DEFINED_LOADER_INFO_PATH, F_OK);
2861 _W("Failed to access %s", APP_DEFINED_LOADER_INFO_PATH);
2862 ret = _inotify_add_watch(OPT_SHARE_PATH, IN_CREATE, __on_directory_create,
2865 _E("Failed to add inotify watch %s", OPT_SHARE_PATH);
2870 ret = _inotify_add_watch(APP_DEFINED_LOADER_INFO_PATH, IN_CREATE | IN_DELETE,
2871 __on_file_change, nullptr);
2874 _E("Failed to add inotify watch %s", APP_DEFINED_LOADER_INFO_PATH);
2880 static int __init_label_monitor_fd(void) {
2884 auto err_handler = [&]() -> int {
2888 if (label_monitor) {
2889 security_manager_app_labels_monitor_finish(label_monitor);
2890 label_monitor = nullptr;
2895 r = security_manager_app_labels_monitor_init(&label_monitor);
2896 if (r != SECURITY_MANAGER_SUCCESS)
2899 r = security_manager_app_labels_monitor_process(label_monitor);
2900 if (r != SECURITY_MANAGER_SUCCESS)
2901 return err_handler();
2903 security_manager_app_labels_monitor_get_fd(label_monitor, &fd);
2905 _E("failed to get fd");
2906 return err_handler();
2909 auto cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
2910 __label_monitor_channel = _io_channel_create(
2911 fd, static_cast<io_condition_e>(cond), __handle_label_monitor, nullptr);
2912 if (!__label_monitor_channel)
2913 return err_handler();
2920 static int __verify_loader_caps(const char* loader) {
2922 cap_flag_value_t eff_state;
2923 cap_flag_value_t inh_state;
2924 cap_value_t values[] = {CAP_SETGID, CAP_MAC_ADMIN};
2927 int size = ARRAY_SIZE(values);
2929 /* If Dytransition feature is enabled, CAP_MAC_ADMIN is unnecessary */
2933 cap_d = cap_get_file(loader);
2935 _E("Failed to get cap from file(%s)", loader);
2939 for (i = 0; i < size; i++) {
2940 r = cap_get_flag(cap_d, values[i], CAP_INHERITABLE, &inh_state);
2942 _E("Failed to get cap inh - errno(%d)", errno);
2947 r = cap_get_flag(cap_d, values[i], CAP_EFFECTIVE, &eff_state);
2949 _E("Failed to get cap eff - errno(%d)", errno);
2954 if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) {
2955 _E("The %s doesn't have %d cap", loader, values[i]);
2965 static void __get_app_type_string(const launchpad::LoaderInfoPtr& info,
2966 char buf[], size_t size) {
2969 for (auto& app_type : info->GetAppTypes()) {
2970 if (size < app_type.size() + 1)
2973 strncpy(ptr, app_type.c_str(), size);
2974 ptr += app_type.size();
2975 size -= app_type.size();
2981 static void __add_slot_from_info(const launchpad::LoaderInfoPtr& info) {
2982 candidate_process_context_t* cpc;
2983 bundle_raw* extra = nullptr;
2989 slot_info_t slot_info = {
2990 .type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset,
2991 .loader_name = info->GetName().c_str(),
2992 .loader_path = info->GetExe().c_str(),
2993 .threshold_max = info->GetCpuThresholdMax(),
2994 .threshold_min = info->GetCpuThresholdMin(),
2995 .app_exists = info->IsAppExists(),
2996 .is_hydra = info->IsHydraEnabled(),
2997 .app_check = info->IsNeededAppCheck(),
2998 .on_boot_timeout = info->GetOnbootTimeout(),
2999 .sched_priority = info->GetSchedPriority(),
3000 .condition_path_exists = info->GetConditionPathExists()
3003 if (info->GetExe() == "null") {
3004 slot_info.loader_id = PAD_LOADER_ID_DIRECT;
3006 cpc = __add_slot(&slot_info);
3010 info->SetType(static_cast<launchpad::LoaderType>(
3011 static_cast<int>(launchpad::LoaderType::User) + user_slot_offset));
3014 } else if (access(info->GetExe().c_str(), F_OK | X_OK) == 0) {
3015 if (__verify_loader_caps(info->GetExe().c_str()) < 0)
3018 bundle_encode(info->GetExtra().GetHandle(), &extra, &len);
3020 slot_info.loader_id = PAD_LOADER_ID_STATIC;
3021 slot_info.loader_extra = (const char*)extra;
3022 slot_info.detection_method = static_cast<int>(info->GetDetectionMethod());
3023 slot_info.activation_method = static_cast<int>(info->GetActivationMethod());
3024 slot_info.deactivation_method = static_cast<int>(info->GetDeactivationMethod());
3025 slot_info.ttl = info->GetTtl();
3026 slot_info.timeout_val = info->GetTimeoutVal();
3027 slot_info.on_boot = info->IsOnBoot();
3029 cpc = __add_slot(&slot_info);
3030 bundle_free_encoded_rawdata(&extra);
3034 info->SetType(static_cast<launchpad::LoaderType>(
3035 static_cast<int>(launchpad::LoaderType::User) + user_slot_offset));
3037 __get_app_type_string(info, buf, sizeof(buf));
3038 _I("candidate slot. app-type(%s) loader-type(%d)", buf,
3039 static_cast<int>(info->GetType()));
3040 _print_hwc_log("candidate slot. app-type(%s) loader-type(%d)", buf,
3041 static_cast<int>(info->GetType()));
3045 static int __add_default_slots(void) {
3046 loader_info_manager =
3047 std::make_unique<launchpad::LoaderInfoManager>(LOADER_INFO_PATH);
3049 loader_info_manager->Load();
3050 user_slot_offset = 0;
3051 for (auto& info : loader_info_manager->GetLoaderInfoList()) {
3052 __add_slot_from_info(info);
3054 __add_idle_checker(0, candidate_slot_list);
3059 static void __add_app_defined_loaders(void) {
3060 app_defined_loader_info_manager =
3061 std::make_unique<launchpad::LoaderInfoManager>(
3062 APP_DEFINED_LOADER_INFO_PATH);
3064 app_defined_loader_info_manager->Load();
3067 static bool __is_low_memory(void) {
3068 if (_memory_monitor_is_low_memory())
3071 if (__memory_status_low >= MEMORY_STATUS_LOW)
3077 static void __hw_acceleration_changed_cb(keynode_t* key, void* data) {
3078 __sys_hwacc = vconf_keynode_get_int(key);
3079 _D("sys hwacc: %d", __sys_hwacc);
3082 static void __update_lang(keynode_t* node, void* user_data) {
3085 lang = vconf_keynode_get_str(node);
3087 _E("Failed to get language");
3091 setenv("LANG", lang, 1);
3094 static void __region_format_changed_cb(keynode_t* node, void* data) {
3097 region = vconf_keynode_get_str(node);
3099 _E("Failed to get value");
3103 setenv("LC_CTYPE", region, 1);
3106 static void __memory_status_low_changed_cb(keynode_t* node, void* data) {
3107 candidate_process_context_t* cpc;
3110 __memory_status_low = vconf_keynode_get_int(node);
3111 if (__memory_status_low >= MEMORY_STATUS_LOW) {
3113 iter = candidate_slot_list;
3115 cpc = (candidate_process_context_t*)iter->data;
3116 __update_slot_state(cpc, launchpad::LoaderMethod::OutOfMemory, false);
3117 iter = g_list_next(iter);
3122 static void __memory_status_normal_changed_cb(keynode_t* node, void* data) {
3123 candidate_process_context_t* cpc;
3126 __memory_status_normal = vconf_keynode_get_int(node);
3127 if (__memory_status_normal == MEMORY_STATUS_NORMAL) {
3129 iter = candidate_slot_list;
3131 cpc = (candidate_process_context_t*)iter->data;
3132 __update_slot_state(cpc, launchpad::LoaderMethod::AvailableMemory, true);
3133 iter = g_list_next(iter);
3138 static void __unregister_vconf_events(void) {
3142 type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY;
3143 key = _config_get_string_value(type);
3144 vconf_ignore_key_changed(key, __memory_status_normal_changed_cb);
3146 type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY;
3147 key = _config_get_string_value(type);
3148 vconf_ignore_key_changed(key, __memory_status_low_changed_cb);
3150 vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, __region_format_changed_cb);
3151 vconf_ignore_key_changed(VCONFKEY_LANGSET, __update_lang);
3152 vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
3153 __hw_acceleration_changed_cb);
3156 static int __register_vconf_events(void) {
3163 r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc);
3165 _E("Failed to get vconf hw acceleration. err = %d", r);
3167 r = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
3168 __hw_acceleration_changed_cb, nullptr);
3169 if (r != VCONF_OK) {
3170 _E("Failed to register callback for hw acceleration. err = %d", r);
3173 lang = vconf_get_str(VCONFKEY_LANGSET);
3175 setenv("LANG", lang, 1);
3179 r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, nullptr);
3181 _E("Failed to register callback for langset. err = %d", r);
3183 region = vconf_get_str(VCONFKEY_REGIONFORMAT);
3185 setenv("LC_CTYPE", region, 1);
3189 r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT,
3190 __region_format_changed_cb, nullptr);
3192 _E("Failed to register callback for regionformat. err = %d", r);
3194 type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY;
3195 key = _config_get_string_value(type);
3196 type = CONFIG_TYPE_MEMORY_STATUS_LOW_VALUE;
3197 MEMORY_STATUS_LOW = _config_get_int_value(type);
3199 r = vconf_get_int(key, &__memory_status_low);
3201 _E("Failed to get vconf low memory. err = %d", r);
3203 r = vconf_notify_key_changed(key, __memory_status_low_changed_cb, nullptr);
3205 _E("Failed to register callback for low memory. err = %d", r);
3207 type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY;
3208 key = _config_get_string_value(type);
3209 type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_VALUE;
3210 MEMORY_STATUS_NORMAL = _config_get_int_value(type);
3212 r = vconf_get_int(key, &__memory_status_normal);
3214 _E("Failed to get vconf normal memory. err = %d", r);
3216 r = vconf_notify_key_changed(key, __memory_status_normal_changed_cb, nullptr);
3218 _E("Failed to register callback for normal memory. err = %d", r);
3223 static bool __handle_logger(int fd, io_condition_e cond, void* data) {
3228 if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
3229 _E("fd(%d), io_condition(%d)", fd, cond);
3230 g_idle_add(__logger_recovery_cb, __logger_channel);
3231 __logger_channel = nullptr;
3235 pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
3237 _E("Failed to receive the packet");
3241 if (getuid() != cr.uid) {
3242 _E("Invalid caller");
3246 if (pkt->len <= 0) {
3247 _E("Invalid message");
3251 _E("[%d] %s", cr.pid, (const char*)pkt->data);
3252 _log_print("[ERROR]", "pid(%7d) | message(%s)", cr.pid,
3253 (const char*)pkt->data);
3263 static int __init_logger_fd(void) {
3266 fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK);
3268 _E("Failed to create logger socker");
3272 auto cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL;
3273 __logger_channel = _io_channel_create(fd, static_cast<io_condition_e>(cond),
3274 __handle_logger, nullptr);
3275 if (!__logger_channel) {
3283 static int __memory_monitor_cb(bool low_memory, void* user_data) {
3284 candidate_process_context_t* cpc;
3286 cpc = __get_running_slot(false);
3287 if (!cpc && low_memory)
3292 __update_slots_pss();
3294 candidate_slot_list = g_list_sort(candidate_slot_list, __compare_slot);
3295 __pause_all_running_slots(false);
3297 __resume_all_slots();
3303 static gboolean __logger_recovery_cb(gpointer data) {
3304 auto channel = static_cast<io_channel_h>(data);
3307 _io_channel_destroy(channel);
3309 ret = __init_logger_fd();
3311 _E("Failed to recover logger socket");
3312 return G_SOURCE_REMOVE;
3315 _E("[__RECOVERY__] Logger socket");
3317 return G_SOURCE_REMOVE;
3320 static gboolean __launchpad_recovery_cb(gpointer data) {
3321 auto channel = static_cast<io_channel_h>(data);
3324 _io_channel_destroy(channel);
3326 ret = __init_launchpad_fd(0, nullptr);
3328 _E("Failed to recover launchpad socket");
3330 return G_SOURCE_REMOVE;
3333 _E("[__RECOVERY__] Launchpad socket");
3335 return G_SOURCE_REMOVE;
3338 static int __before_loop(int argc, char** argv) {
3339 __request_handlers[PAD_CMD_VISIBILITY] = __visibility_request_handler;
3340 __request_handlers[PAD_CMD_ADD_LOADER] = __add_loader_request_handler;
3341 __request_handlers[PAD_CMD_REMOVE_LOADER] = __remove_loader_request_handler;
3342 __request_handlers[PAD_CMD_MAKE_DEFAULT_SLOTS] =
3343 __make_default_slots_request_handler;
3344 __request_handlers[PAD_CMD_PREPARE_APP_DEFINED_LOADER] =
3345 __prepare_app_defined_loader_request_handler;
3346 __request_handlers[PAD_CMD_DEMAND] = __demand_request_handler;
3347 __request_handlers[PAD_CMD_PING] = __ping_request_handler;
3348 __request_handlers[PAD_CMD_UPDATE_APP_TYPE] =
3349 __update_app_type_request_handler;
3350 __request_handlers[PAD_CMD_CONNECT] = __connect_request_handler;
3351 __request_handlers[PAD_CMD_LAUNCH] = __launch_request_handler;
3353 _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__);
3354 int ret = __sequencer_init();
3356 _E("Failed to initialize sequencer");
3360 ret = _signal_init();
3362 _E("Failed to initialize signal");
3366 _signal_set_sigchld_cb(__handle_sigchild, nullptr);
3368 ret = __init_launchpad_fd(argc, argv);
3370 _E("__init_launchpad_fd() failed");
3374 ret = __init_logger_fd();
3376 _E("__init_logger_fd() failed");
3380 ret = __init_label_monitor_fd();
3382 _W("Failed to initialize label monitor");
3384 ret = _config_init();
3386 _W("Failed to initialize config");
3390 _W("Failed to initialize dbus");
3393 _memory_monitor_init();
3394 _memory_monitor_set_event_cb(__memory_monitor_cb, nullptr);
3396 MAX_CPU_CHECK_COUNT =
3397 _config_get_int_value(CONFIG_TYPE_CPU_CHECKER_MAX_COUNT);
3398 __add_default_slots();
3400 launchpad::LauncherInfoInflator inflator;
3401 launcher_info_list = inflator.Inflate(LAUNCHER_INFO_PATH);
3403 __add_app_defined_loaders();
3405 ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL);
3407 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL);
3410 g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr, free);
3412 _E("Failed to create pid table");
3416 ret = _worker_create("cleaner+", &__cleaner);
3420 __register_vconf_events();
3421 __init_app_defined_loader_monitor();
3423 _print_hwc_log("%s(%d): END", __FUNCTION__, __LINE__);
3428 static void __after_loop(void) {
3430 _memory_monitor_fini();
3431 __unregister_vconf_events();
3432 _worker_destroy(__cleaner);
3434 g_hash_table_destroy(__pid_table);
3436 if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0)
3437 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL);
3440 launcher_info_list.clear();
3444 app_defined_loader_info_manager->Dispose();
3446 if (__label_monitor_channel)
3447 _io_channel_destroy(__label_monitor_channel);
3450 security_manager_app_labels_monitor_finish(label_monitor);
3452 if (__logger_channel)
3453 _io_channel_destroy(__logger_channel);
3455 if (__launchpad_channel)
3456 _io_channel_destroy(__launchpad_channel);
3463 int main(int argc, char** argv) {
3464 GMainLoop* mainloop = nullptr;
3466 _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__);
3467 prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
3469 mainloop = g_main_loop_new(nullptr, FALSE);
3471 _E("Failed to create glib main loop");
3475 _print_hwc_log("%s(%d): __before_loop()", __FUNCTION__, __LINE__);
3476 if (__before_loop(argc, argv) != 0) {
3477 _E("process-pool Initialization failed!");
3481 #ifdef TIZEN_FEATURE_PRIORITY_CHANGE
3484 _print_hwc_log("%s(%d): g_main_loop_run()", __FUNCTION__, __LINE__);
3485 g_main_loop_run(mainloop);