ed0a39ac955f448b5f04f763e12c24dc60823df5
[platform/core/appfw/launchpad.git] / src / launchpad-process-pool / launchpad.cc
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <bundle_internal.h>
18 #include <errno.h>
19 #include <glib.h>
20 #include <linux/limits.h>
21 #include <malloc.h>
22 #include <math.h>
23 #include <sched.h>
24 #include <security-manager.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <sys/capability.h>
29 #include <sys/prctl.h>
30 #include <sys/socket.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <sys/un.h>
34 #include <sys/wait.h>
35 #include <systemd/sd-daemon.h>
36 #include <time.h>
37 #include <trust-anchor.h>
38 #include <ttrace.h>
39 #include <vconf.h>
40
41 #include <algorithm>
42
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"
61
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
67 #define HYDRA_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"
76
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
84 #define PI 3.14159265
85 #define WIN_SCORE 100
86 #define LOSE_SCORE_RATE 0.7f
87
88 enum candidate_process_state_e {
89   CANDIDATE_PROCESS_STATE_RUNNING,
90   CANDIDATE_PROCESS_STATE_PAUSED,
91 };
92
93 typedef struct {
94   int type;
95   bool prepared;
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 */
98   int hydra_pid;
99   int loader_id;
100   int caller_pid;
101   int send_fd;
102   int hydra_fd;
103   int last_exec_time;
104   guint timer;
105   char* loader_name;
106   char* loader_path;
107   char* loader_extra;
108   int detection_method;
109   int timeout_val;
110   unsigned long long cpu_total_time;
111   unsigned long long cpu_idle_time;
112   int threshold;
113   int threshold_max;
114   int threshold_min;
115   int cur_event;
116   bool on_boot;
117   bool app_exists;
118   bool touched;
119   int activation_method;
120   int deactivation_method;
121   unsigned int ttl;
122   guint live_timer;
123   int state;
124   bool is_hydra;
125   bool app_check;
126   io_channel_h client_channel;
127   io_channel_h channel;
128   io_channel_h hydra_channel;
129   unsigned int score;
130   unsigned int pss;
131   int cpu_check_count;
132   int on_boot_timeout;
133   guint on_boot_timer;
134   int sched_priority;
135   std::vector<std::string> condition_path_exists;
136 } candidate_process_context_t;
137
138 typedef struct {
139   GPollFD* gpollfd;
140   int type;
141   int loader_id;
142 } loader_context_t;
143
144 typedef struct {
145   GQueue* queue;
146   guint timer;
147   guint idle_checker;
148   candidate_process_context_t* running_cpc;
149 } sequencer;
150
151 struct app_launch_arg {
152   const char* appid;
153   const char* app_path;
154   appinfo_t* menu_info;
155   bundle* kb;
156 };
157
158 struct app_arg {
159   int argc;
160   char** argv;
161 };
162
163 struct app_info {
164   const char* type;
165   bool exists;
166 };
167
168 struct cleanup_info_s {
169   char* appid;
170   int pid;
171 };
172
173 typedef struct candidate_info_s {
174   char** argv;
175   int argc;
176   int loader_id;
177   int type;
178   pid_t pid;
179 } candidate_info_t;
180
181 typedef struct request_s {
182   app_pkt_t* pkt;
183   appinfo_t* menu_info;
184   bundle* kb;
185   candidate_process_context_t* cpc;
186   candidate_process_context_t* org_cpc;
187   const char* app_path;
188   int clifd;
189   int cmd;
190   int loader_id;
191   pid_t caller_pid;
192   uid_t caller_uid;
193   pid_t pid; /* result */
194 } request_t;
195
196 typedef request_t* request_h;
197
198 typedef int (*request_handler)(request_h request);
199
200 namespace {
201
202 int __sys_hwacc;
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;
216
217 io_channel_h __logger_channel;
218 io_channel_h __label_monitor_channel;
219 io_channel_h __launchpad_channel;
220 int __client_fd = -1;
221 worker_h __cleaner;
222
223 }  // namespace
224
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,
234                                 bool force);
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);
238
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;
243
244   if (__sequencer.idle_checker > 0)
245     return G_SOURCE_CONTINUE;
246
247   if (g_queue_is_empty(__sequencer.queue)) {
248     __sequencer.timer = 0;
249     return G_SOURCE_REMOVE;
250   }
251
252   cpc = (candidate_process_context_t*)g_queue_pop_head(__sequencer.queue);
253   if (!cpc) {
254     _E("Critical error!");
255     __sequencer.timer = 0;
256     return G_SOURCE_REMOVE;
257     ;
258   }
259
260   if (cpc->app_check && !cpc->app_exists) {
261     _W("The application is not installed. Type(%d)", cpc->type);
262     return G_SOURCE_CONTINUE;
263   }
264
265   if (cpc->timer) {
266     g_source_remove(cpc->timer);
267     cpc->timer = 0;
268   }
269
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;
273   }
274
275   _get_cpu_idle(&total, &idle);
276   cpc->cpu_idle_time = idle;
277   cpc->cpu_total_time = total;
278   cpc->cpu_check_count = 0;
279
280   __sequencer.idle_checker =
281       g_timeout_add(CPU_CHECKER_TIMEOUT, __handle_idle_checker, cpc);
282   __sequencer.running_cpc = cpc;
283
284   _W("[__SEQUENCER__] Add idle checker. Type(%d)", cpc->type);
285
286   return G_SOURCE_CONTINUE;
287 }
288
289 static bool __sequencer_slot_is_running(candidate_process_context_t* cpc) {
290   if (__sequencer.running_cpc == cpc)
291     return true;
292
293   return false;
294 }
295
296 static bool __sequencer_slot_exist(candidate_process_context_t* cpc) {
297   GList* found;
298
299   found = g_queue_find(__sequencer.queue, cpc);
300   if (found)
301     return true;
302
303   return false;
304 }
305
306 static int __sequencer_add_slot(candidate_process_context_t* cpc) {
307   if (__sequencer_slot_exist(cpc)) {
308     _W("Already exists");
309     return -1;
310   }
311
312   if (__sequencer_slot_is_running(cpc)) {
313     _W("slot(%d) is running", cpc->type);
314     return -1;
315   }
316
317   g_queue_push_tail(__sequencer.queue, cpc);
318
319   return 0;
320 }
321
322 static void __sequencer_remove_slot(candidate_process_context_t* cpc) {
323   g_queue_remove(__sequencer.queue, cpc);
324 }
325
326 static void __sequencer_run(void) {
327   if (__sequencer.timer)
328     return;
329
330   __sequencer.timer = g_timeout_add(500, __handle_queuing_slots, nullptr);
331   if (!__sequencer.timer)
332     _E("Failed to add sequencer timer");
333 }
334
335 static void __sequencer_stop(void) {
336   if (!__sequencer.timer)
337     return;
338
339   g_source_remove(__sequencer.timer);
340   __sequencer.timer = 0;
341 }
342
343 static bool __sequencer_queue_is_empty(void) {
344   if (g_queue_is_empty(__sequencer.queue))
345     return true;
346
347   return false;
348 }
349
350 static int __sequencer_init(void) {
351   _D("[__SEQUENCER__] Init");
352
353   __sequencer.queue = g_queue_new();
354   if (!__sequencer.queue) {
355     _E("Out of memory");
356     return -1;
357   }
358
359   return 0;
360 }
361
362 static void __sequencer_fini(void) {
363   _D("[__SEQUENCER__] Finish");
364
365   if (__sequencer.idle_checker > 0)
366     g_source_remove(__sequencer.idle_checker);
367
368   if (__sequencer.timer > 0)
369     g_source_remove(__sequencer.timer);
370
371   g_queue_free(__sequencer.queue);
372 }
373
374 static int __make_loader_id(void) {
375   static int id = PAD_LOADER_ID_DYNAMIC_BASE;
376
377   return ++id;
378 }
379
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;
383
384   if (type == static_cast<int>(launchpad::LoaderType::Dynamic) ||
385       type == static_cast<int>(launchpad::LoaderType::Unsupported))
386     return nullptr;
387
388   while (iter) {
389     cpc = (candidate_process_context_t*)iter->data;
390     if (type == cpc->type)
391       return cpc;
392
393     iter = g_list_next(iter);
394   }
395
396   return nullptr;
397 }
398
399 static candidate_process_context_t* __find_slot_from_pid(int pid) {
400   candidate_process_context_t* cpc;
401   GList* iter = candidate_slot_list;
402
403   while (iter) {
404     cpc = (candidate_process_context_t*)iter->data;
405     if (pid == cpc->pid)
406       return cpc;
407
408     iter = g_list_next(iter);
409   }
410
411   return nullptr;
412 }
413
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;
417
418   while (iter) {
419     cpc = (candidate_process_context_t*)iter->data;
420     if (cpc->is_hydra && pid == cpc->hydra_pid)
421       return cpc;
422
423     iter = g_list_next(iter);
424   }
425
426   return nullptr;
427 }
428
429 static candidate_process_context_t* __find_slot_from_caller_pid(
430     int caller_pid) {
431   candidate_process_context_t* cpc;
432   GList* iter = candidate_slot_list;
433
434   while (iter) {
435     cpc = (candidate_process_context_t*)iter->data;
436     if (caller_pid == cpc->caller_pid)
437       return cpc;
438
439     iter = g_list_next(iter);
440   }
441
442   return nullptr;
443 }
444
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;
448
449   while (iter) {
450     cpc = (candidate_process_context_t*)iter->data;
451     if (id == cpc->loader_id)
452       return cpc;
453
454     iter = g_list_next(iter);
455   }
456
457   return nullptr;
458 }
459
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;
464
465   while (iter) {
466     cpc = (candidate_process_context_t*)iter->data;
467     if (strcmp(cpc->loader_name, loader_name) == 0)
468       return cpc;
469
470     iter = g_list_next(iter);
471   }
472
473   return nullptr;
474 }
475
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);
479
480   return __find_slot_from_static_type(type);
481 }
482
483 static void __update_slot_score(candidate_process_context_t* slot) {
484   if (!slot)
485     return;
486
487   slot->score *= LOSE_SCORE_RATE;
488   slot->score += WIN_SCORE;
489 }
490
491 static void __update_slots_pss(void) {
492   candidate_process_context_t* cpc;
493   GList* iter;
494
495   iter = candidate_slot_list;
496   while (iter) {
497     cpc = (candidate_process_context_t*)iter->data;
498     iter = g_list_next(iter);
499
500     if (cpc->pid == CANDIDATE_NONE)
501       continue;
502
503     _proc_get_mem_pss(cpc->pid, &cpc->pss);
504   }
505 }
506
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;
510
511   if (slot_a->is_hydra && !slot_b->is_hydra)
512     return -1;
513   if (!slot_a->is_hydra && slot_b->is_hydra)
514     return 1;
515
516   if (slot_a->score < slot_b->score)
517     return 1;
518   if (slot_a->score > slot_b->score)
519     return -1;
520
521   if (slot_a->pss < slot_b->pss)
522     return -1;
523   if (slot_a->pss > slot_b->pss)
524     return 1;
525
526   return 0;
527 }
528
529 static candidate_process_context_t* __get_running_slot(bool is_hydra) {
530   candidate_process_context_t* cpc;
531   GList* iter;
532
533   iter = candidate_slot_list;
534   while (iter) {
535     cpc = (candidate_process_context_t*)iter->data;
536     if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE)
537       return cpc;
538
539     iter = g_list_next(iter);
540   }
541
542   return nullptr;
543 }
544
545 static void __pause_all_running_slots(bool is_hydra) {
546   candidate_process_context_t* cpc = nullptr;
547   GList* iter;
548
549   iter = g_list_last(candidate_slot_list);
550   while (iter) {
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())
555         return;
556     }
557
558     iter = g_list_previous(iter);
559   }
560 }
561
562 static void __resume_all_slots(void) {
563   candidate_process_context_t* cpc;
564   GList* iter;
565
566   iter = candidate_slot_list;
567   while (iter) {
568     cpc = (candidate_process_context_t*)iter->data;
569     __update_slot_state(cpc, launchpad::LoaderMethod::AvailableMemory, true);
570
571     iter = g_list_next(iter);
572   }
573 }
574
575 static void __kill_process(int pid) {
576   char err_str[MAX_LOCAL_BUFSZ] = {
577       0,
578   };
579
580   if (kill(pid, SIGKILL) == -1) {
581     _E("send SIGKILL: %s", strerror_r(errno, err_str, sizeof(err_str)));
582   }
583 }
584
585 static void __refuse_candidate_process(int server_fd) {
586   int client_fd = -1;
587
588   if (server_fd == -1) {
589     _E("arguments error!");
590     goto error;
591   }
592
593   client_fd = accept(server_fd, nullptr, nullptr);
594   if (client_fd == -1) {
595     _E("accept error!");
596     goto error;
597   }
598
599   close(client_fd);
600   _D("refuse connection!");
601
602 error:
603   return;
604 }
605
606 static int __accept_candidate_process(int server_fd,
607                                       int* out_client_fd,
608                                       int* out_client_pid,
609                                       int cpc_pid) {
610   int client_fd = -1;
611   int recv_pid = 0;
612   int ret;
613   socklen_t len;
614   struct ucred cred = {};
615
616   if (server_fd == -1 || out_client_fd == nullptr ||
617       out_client_pid == nullptr) {
618     _E("arguments error!");
619     goto error;
620   }
621
622   client_fd = accept(server_fd, nullptr, nullptr);
623   if (client_fd == -1) {
624     _E("accept error!");
625     goto error;
626   }
627
628   if (_set_sock_option(client_fd, 1) < 0) {
629     _E("Failed to set sock option");
630     goto error;
631   }
632
633   ret = recv(client_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL);
634   if (ret == -1) {
635     _E("recv error!");
636     goto error;
637   }
638
639   len = (socklen_t)sizeof(cred);
640   ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &len);
641   if (ret < 0) {
642     _E("getsockopt error");
643     goto error;
644   }
645
646   if (cpc_pid != -1 && cred.pid != cpc_pid) {
647     _E("Invalid accept. pid(%d)", cred.pid);
648     goto error;
649   }
650
651   if (cred.pid != recv_pid)
652     _W("Not equal recv and real pid");
653
654   *out_client_fd = client_fd;
655   *out_client_pid = cred.pid;
656
657   return *out_client_fd;
658
659 error:
660   if (client_fd != -1)
661     close(client_fd);
662
663   return -1;
664 }
665
666 static int __listen_addr(struct sockaddr_un* addr) {
667   int fd = -1;
668   fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
669   if (fd < 0) {
670     _E("Socket error");
671     goto error;
672   }
673
674   unlink(addr->sun_path);
675
676   _D("bind to %s", addr->sun_path);
677   if (bind(fd, (struct sockaddr*)addr, sizeof(struct sockaddr_un)) < 0) {
678     _E("bind error");
679     goto error;
680   }
681
682   _D("listen to %s", addr->sun_path);
683   if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) {
684     _E("listen error");
685     goto error;
686   }
687
688   SECURE_LOGD("[launchpad] done, listen fd: %d", fd);
689   return fd;
690
691 error:
692   if (fd != -1)
693     close(fd);
694
695   return -1;
696 }
697
698 static int __listen_candidate_process(int type, int loader_id) {
699   struct sockaddr_un addr;
700
701   _D("[launchpad] enter, type: %d", type);
702
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,
707            loader_id);
708
709   return __listen_addr(&addr);
710 }
711
712 static int __listen_hydra_process(int type, int loader_id) {
713   struct sockaddr_un addr;
714
715   _D("[launchpad] enter, type: %d", type);
716
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);
721
722   return __listen_addr(&addr);
723 }
724
725 static int __get_loader_id(bundle* kb) {
726   const char* val;
727
728   val = bundle_get_val(kb, AUL_K_LOADER_ID);
729   if (val == nullptr)
730     return -1;
731   _W("Requested loader id: %s", val);
732
733   return atoi(val);
734 }
735
736 static int __candidate_process_real_launch(int candidate_fd, app_pkt_t* pkt) {
737   return _send_pkt_raw(candidate_fd, pkt);
738 }
739
740 static int __real_send(int clifd, int ret) {
741   if (clifd < 3) {
742     _E("Invalid parameter. clifd(%d)", clifd);
743     return -1;
744   }
745
746   if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
747     if (errno == EPIPE) {
748       _E("send failed due to EPIPE.");
749       close(clifd);
750       return -1;
751     }
752     _E("send fail to client");
753   }
754
755   close(clifd);
756   return 0;
757 }
758
759 static int __fork_app_process(int (*child_fn)(void*), void* arg,
760     int sched_priority) {
761   int pid;
762   int ret;
763
764   pid = fork();
765   if (pid == -1) {
766     _E("failed to fork child process");
767     return -1;
768   }
769
770   if (pid == 0) {
771     if (sched_priority != 0)
772       _set_priority(sched_priority);
773
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);
779       exit(1);
780     }
781
782     ret = child_fn(arg);
783     _E("failed to exec app process (%d)", errno);
784     exit(ret);
785   }
786
787   return pid;
788 }
789
790 static int __exec_loader_process(void* arg) {
791   char** argv = static_cast<char**>(arg);
792   char err_buf[1024];
793
794   _signal_unblock_sigchld();
795   _close_all_fds();
796   _setup_stdio(basename(argv[LOADER_ARG_PATH]));
797
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)));
802   } else {
803     _D("Succeeded to prepare candidate_process");
804   }
805
806   return -1;
807 }
808
809 static gboolean __handle_deactivate_event(gpointer user_data) {
810   candidate_process_context_t* cpc;
811
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);
816
817   return G_SOURCE_REMOVE;
818 }
819
820 static void __set_live_timer(candidate_process_context_t* cpc) {
821   if (!cpc)
822     return;
823
824   if (cpc->deactivation_method & static_cast<int>(launchpad::LoaderMethod::Ttl)) {
825     if (cpc->live_timer == 0) {
826       cpc->live_timer =
827           g_timeout_add_seconds(cpc->ttl, __handle_deactivate_event, cpc);
828     }
829   }
830 }
831
832 static int __hydra_send_request(int fd, enum hydra_cmd cmd) {
833   int sent = 0;
834   int size = (int)sizeof(cmd);
835   int send_ret = 0;
836
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);
841       return -1;
842     }
843
844     sent += send_ret;
845     _D("send(%d: ret: %d) : %d / %d", fd, send_ret, sent, size);
846   }
847
848   return 0;
849 }
850
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);
854 }
855
856 static void __candidate_info_free(candidate_info_t* info) {
857   int i;
858
859   if (info == nullptr)
860     return;
861
862   if (info->argv) {
863     for (i = 0; i < info->argc; i++)
864       free(info->argv[i]);
865
866     free(info->argv);
867   }
868
869   free(info);
870 }
871
872 static int __candidate_info_create(candidate_process_context_t* cpt,
873                                    candidate_info_t** candidate_info) {
874   char type_str[12] = {
875       0,
876   };
877   char loader_id_str[12] = {
878       0,
879   };
880   char argbuf[LOADER_ARG_LEN];
881   candidate_info_t* info;
882
883   if (cpt == nullptr)
884     return -EINVAL;
885
886   info = static_cast<candidate_info_t*>(calloc(1, sizeof(candidate_info_t)));
887   if (info == nullptr) {
888     _E("calloc() is failed");
889     return -ENOMEM;
890   }
891
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);
896     return -ENOMEM;
897   }
898
899   memset(argbuf, ' ', LOADER_ARG_LEN);
900   argbuf[LOADER_ARG_LEN - 1] = '\0';
901   info->argv[LOADER_ARG_DUMMY] = strdup(argbuf);
902
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);
910
911   info->argc = LOADER_ARG_DUMMY + 1;
912   info->type = cpt->type;
913   info->loader_id = cpt->loader_id;
914
915   *candidate_info = info;
916   return 0;
917 }
918
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;
922   int ret;
923
924   if (cpt == nullptr)
925     return -1;
926
927   if (cpt->is_hydra && cpt->hydra_pid != HYDRA_NONE)
928     return __hydra_send_launch_candidate_request(cpt->hydra_fd);
929
930   _D("prepare candidate process / type:%d", type);
931   ret = __candidate_info_create(cpt, &info);
932   if (ret < 0)
933     return ret;
934
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);
940     return -1;
941   }
942
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);
949     return -1;
950   }
951
952   cpt->last_exec_time = time(nullptr);
953   if (cpt->is_hydra) {
954     cpt->hydra_pid = info->pid;
955   } else {
956     cpt->pid = info->pid;
957     __set_live_timer(cpt);
958   }
959
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);
964   return 0;
965 }
966
967 static gboolean __handle_timeout_event(gpointer user_data) {
968   candidate_process_context_t* cpc;
969
970   cpc = (candidate_process_context_t*)user_data;
971   cpc->timer = 0;
972
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;
978   }
979
980   __sequencer_add_slot(cpc);
981   __sequencer_run();
982   return G_SOURCE_REMOVE;
983 }
984
985 static void __set_timer(candidate_process_context_t* cpc) {
986   if (cpc == nullptr || cpc->timer > 0) {
987     _E("Invalid parameter");
988     return;
989   }
990
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);
997     if (cpc->timer == 0)
998       _E("g_timeout_add() is failed. %d:%s", cpc->type, cpc->loader_name);
999   } else {
1000     _E("Skip adding timer. detection_method(%d), state(%d)",
1001         cpc->detection_method, cpc->state);
1002   }
1003 }
1004
1005 static void __reset_slot(candidate_process_context_t* cpc) {
1006   if (cpc == nullptr)
1007     return;
1008
1009   cpc->send_fd = -1;
1010   cpc->prepared = false;
1011   cpc->pid = CANDIDATE_NONE;
1012   cpc->client_channel = nullptr;
1013   cpc->timer = 0;
1014   cpc->live_timer = 0;
1015   cpc->on_boot_timer = 0;
1016 }
1017
1018 static void __dispose_candidate_process(candidate_process_context_t* cpc) {
1019   if (!cpc)
1020     return;
1021
1022   _D("Dispose candidate process %d:%s", cpc->type, cpc->loader_name);
1023   if (cpc->pid > 0) {
1024     _D("kill process %d", cpc->pid);
1025     __kill_process(cpc->pid);
1026   }
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);
1031   if (cpc->timer > 0)
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);
1037   __reset_slot(cpc);
1038 }
1039
1040 static void __dispose_hydra_process(candidate_process_context_t* cpc) {
1041   if (!cpc)
1042     return;
1043
1044   __dispose_candidate_process(cpc);
1045
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;
1051   }
1052
1053   if (cpc->hydra_fd > 0) {
1054     close(cpc->hydra_fd);
1055     cpc->hydra_fd = -1;
1056   }
1057 }
1058
1059 static int __send_launchpad_loader(candidate_process_context_t* cpc,
1060                                    app_pkt_t* pkt,
1061                                    const char* app_path,
1062                                    int clifd) {
1063   int pid = -1;
1064   int ret;
1065
1066   ret = _delete_sock_path(cpc->pid, getuid());
1067   if (ret != 0)
1068     return -1;
1069
1070   __candidate_process_real_launch(cpc->send_fd, pkt);
1071   _W("Request to candidate process, pid: %d, bin path: %s", cpc->pid,
1072               app_path);
1073
1074   pid = cpc->pid;
1075   cpc->pid = CANDIDATE_NONE;
1076   __dispose_candidate_process(cpc);
1077   __set_timer(cpc);
1078   __update_slot_score(cpc);
1079
1080   return pid;
1081 }
1082
1083 static int __normal_fork_exec(int argc, char** argv, const char* app_path) {
1084   char* libdir;
1085   char err_buf[1024];
1086
1087   _D("start real fork and exec");
1088
1089   libdir = _get_libdir(app_path);
1090   if (libdir) {
1091     setenv("LD_LIBRARY_PATH", libdir, 1);
1092     free(libdir);
1093   }
1094
1095   _close_all_fds();
1096
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)));
1101     return -1;
1102   }
1103   /* never reach*/
1104   return 0;
1105 }
1106
1107 static int __create_launcher_argv(int* argc,
1108                                   char*** argv,
1109                                   const char* app_type) {
1110   int launcher_argc;
1111   char** launcher_argv;
1112   launchpad::LauncherInfoPtr launcher_info;
1113   const char* exe;
1114   int i;
1115
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();
1124       });
1125
1126   if (it == launcher_info_list.end())
1127     return 0;
1128
1129   launcher_info = *it;
1130   exe = launcher_info->GetExe().c_str();
1131
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");
1137     return -1;
1138   }
1139
1140   i = LOADER_ARG_PATH;
1141   launcher_argv[i++] = strdup(exe);
1142
1143   for (auto& extra_arg : extra_args) {
1144     launcher_argv[i++] = strdup(extra_arg.c_str());
1145   }
1146
1147   *argc = launcher_argc;
1148   *argv = launcher_argv;
1149
1150   return 0;
1151 }
1152
1153 static void __destroy_launcher_argv(int argc, char** argv) {
1154   int i;
1155
1156   if (argv == nullptr)
1157     return;
1158
1159   for (i = 0; i < argc; i++)
1160     free(argv[i]);
1161   free(argv);
1162 }
1163
1164 static int __create_app_argv(int* argc,
1165                              char*** argv,
1166                              const char* app_path,
1167                              bundle* kb,
1168                              const char* app_type) {
1169   int new_argc;
1170   char** new_argv;
1171   bool attach = false;
1172   struct app_arg debug_arg = {
1173       0,
1174   };
1175   struct app_arg launcher_arg = {
1176       0,
1177   };
1178   struct app_arg arg = {
1179       0,
1180   };
1181   struct app_arg debug_extra_arg = {
1182       0,
1183   };
1184   int ret;
1185   int i;
1186   int c;
1187
1188   ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach);
1189   if (ret < 0) {
1190     _E("Failed to create debugger argv");
1191     return -1;
1192   }
1193
1194   if (attach) {
1195     *argc = debug_arg.argc;
1196     *argv = debug_arg.argv;
1197     return 0;
1198   }
1199
1200   ret = _debug_create_extra_argv(&debug_extra_arg.argc, &debug_extra_arg.argv);
1201   if (ret < 0) {
1202     _E("Failed to create debugger extra argv");
1203     _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1204     return -1;
1205   }
1206
1207   ret =
1208       __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv, app_type);
1209   if (ret < 0) {
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);
1213     return -1;
1214   }
1215
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);
1222     return -1;
1223   }
1224   arg.argv[LOADER_ARG_PATH] = strdup(app_path);
1225
1226   new_argc =
1227       debug_arg.argc + launcher_arg.argc + arg.argc + debug_extra_arg.argc;
1228   if (new_argc == arg.argc) {
1229     *argc = arg.argc;
1230     *argv = arg.argv;
1231     return 0;
1232   }
1233
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);
1242     return -1;
1243   }
1244
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];
1254
1255   *argc = new_argc;
1256   *argv = new_argv;
1257
1258   return 0;
1259 }
1260
1261 static void __real_launch(const char* app_path,
1262                           bundle* kb,
1263                           appinfo_t* menu_info) {
1264   int app_argc = 0;
1265   char** app_argv;
1266   int i;
1267   int ret;
1268
1269   if (bundle_get_val(kb, AUL_K_DEBUG) != nullptr)
1270     setenv("TIZEN_DEBUGGING_PORT", "1", 1);
1271
1272   ret = __create_app_argv(&app_argc, &app_argv, app_path, kb,
1273                           menu_info->app_type);
1274   if (ret < 0) {
1275     _E("Failed to create app argv");
1276     exit(-1);
1277   }
1278
1279   for (i = 0; i < app_argc; i++)
1280     SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
1281
1282   PERF("setup argument done");
1283   __normal_fork_exec(app_argc, app_argv, app_path);
1284 }
1285
1286 static int __prepare_exec(const char* appid,
1287                           const char* app_path,
1288                           appinfo_t* menu_info,
1289                           bundle* kb) {
1290   char* file_name;
1291   const char* enabled_light_user;
1292   char process_name[AUL_PR_NAME];
1293   int ret;
1294
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*/
1298   setsid();
1299
1300   ret = _launchpad_plugin_prepare_app(appid, kb);
1301   if (ret < 0) {
1302     _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret);
1303     return PAD_ERR_FAILED;
1304   }
1305
1306   ret = _enable_external_pkg(kb, menu_info->pkgid,
1307                              menu_info->global ? GLOBAL_USER : getuid());
1308   if (ret < 0)
1309     return PAD_ERR_FAILED;
1310
1311   if (menu_info->global)
1312     ret = trust_anchor_launch(menu_info->pkgid, GLOBAL_USER);
1313   else
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;
1319   }
1320
1321   ret = _mount_res_dir(menu_info->root_path, kb);
1322   if (ret < 0)
1323     return PAD_ERR_FAILED;
1324
1325   if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1326     _debug_change_mount_namespace();
1327
1328   /* SET PRIVILEGES*/
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;
1335
1336   if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE)
1337     _setup_stdio(basename(app_path));
1338
1339   /* SET DUMPABLE - for coredump*/
1340   prctl(PR_SET_DUMPABLE, 1);
1341
1342   /* SET PROCESS NAME*/
1343   if (app_path == nullptr)
1344     return PAD_ERR_INVALID_ARGUMENT;
1345
1346   file_name = const_cast<char*>(strrchr(app_path, '/'));
1347   if (file_name == nullptr)
1348     return PAD_ERR_INVALID_PATH;
1349
1350   file_name++;
1351   if (*file_name == '\0')
1352     return PAD_ERR_INVALID_PATH;
1353
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);
1357
1358   /* SET ENVIROMENT*/
1359   _set_env(menu_info, kb);
1360
1361   ret = _wait_tep_mount(kb);
1362   if (ret < 0)
1363     return PAD_ERR_FAILED;
1364
1365   if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) {
1366     ret = _prepare_app_socket();
1367     if (ret < 0)
1368       return PAD_ERR_FAILED;
1369
1370     ret = _prepare_id_file();
1371     if (ret < 0)
1372       return PAD_ERR_FAILED;
1373   }
1374
1375   _send_cmd_to_amd(APP_STARTUP_SIGNAL);
1376   return 0;
1377 }
1378
1379 static int __exec_app_process(void* arg) {
1380   auto* launch_arg = static_cast<app_launch_arg*>(arg);
1381   int ret;
1382
1383   _print_hwc_log("%d|after calling fork(). %s", getpid(), launch_arg->appid);
1384   PERF("fork done");
1385   _D("lock up test log(no error) : fork done");
1386
1387   if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1388     _debug_prepare_debugger(launch_arg->kb);
1389
1390   _signal_unblock_sigchld();
1391
1392   _delete_sock_path(getpid(), getuid());
1393
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);
1397   if (ret < 0)
1398     return ret;
1399
1400   PERF("prepare exec - second done");
1401   __real_launch(launch_arg->app_path, launch_arg->kb, launch_arg->menu_info);
1402
1403   return PAD_ERR_FAILED;
1404 }
1405
1406 static int __launch_directly(const char* appid,
1407                              const char* app_path,
1408                              int clifd,
1409                              bundle* kb,
1410                              appinfo_t* menu_info,
1411                              candidate_process_context_t* cpc) {
1412   struct app_launch_arg arg;
1413   int pid;
1414
1415   arg.appid = appid;
1416   arg.app_path = app_path;
1417   arg.menu_info = menu_info;
1418   arg.kb = kb;
1419
1420   _print_hwc_log("before calling fork(). %s", appid);
1421   pid = __fork_app_process(__exec_app_process, &arg, 0);
1422   if (pid <= 0)
1423     _E("failed to fork app process");
1424
1425   SECURE_LOGD("==> real launch pid : %d %s", pid, app_path);
1426
1427   return pid;
1428 }
1429
1430 static int __create_sock_activation(void) {
1431   int fds;
1432   char launchpad_process_pool_sock_path[108];
1433   int i;
1434
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);
1439
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,
1442                           0) > 0)
1443       return i;
1444   }
1445
1446   _W("There is no socket stream");
1447   return -1;
1448 }
1449
1450 static int __get_launchpad_listen_fd(void) {
1451   const char* val;
1452
1453   val = getenv("LAUNCHPAD_LISTEN_FD");
1454   if (!val) {
1455     _E("Failed to get LAUNCHPAD_LISTEN_FD");
1456     return -1;
1457   }
1458
1459   _W("Listen Fd: %s", val);
1460   return atoi(val);
1461 }
1462
1463 static int __launchpad_pre_init(int argc, char** argv) {
1464   int fd;
1465
1466   /* create launchpad sock */
1467   fd = __create_sock_activation();
1468   if (fd >= 0)
1469     return fd;
1470
1471   fd = __get_launchpad_listen_fd();
1472   if (fd >= 0)
1473     return fd;
1474
1475   fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK);
1476   if (fd < 0) {
1477     _E("server sock error %d", fd);
1478     return -1;
1479   }
1480
1481   return fd;
1482 }
1483
1484 static bool __handle_loader_client_event(int fd,
1485                                          io_condition_e cond,
1486                                          void* data) {
1487   auto* cpc = static_cast<candidate_process_context_t*>(data);
1488
1489   if (cpc == nullptr)
1490     return false;
1491
1492   if (cond & (IO_HUP | IO_NVAL)) {
1493     SECURE_LOGE(
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);
1500     return false;
1501   }
1502
1503   return true;
1504 }
1505
1506 static bool __handle_hydra_client_event(int fd,
1507                                         io_condition_e cond,
1508                                         void* data) {
1509   auto* cpc = static_cast<candidate_process_context_t*>(data);
1510   int recv_pid = -1;
1511   int ret;
1512
1513   if (cpc == nullptr)
1514     return false;
1515
1516   if (cond & (IO_HUP | IO_NVAL)) {
1517     SECURE_LOGE(
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);
1523     return false;
1524   }
1525
1526   if (cond & IO_IN) {
1527     ret = recv(cpc->hydra_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL);
1528     if (ret == -1) {
1529       _E("recv() is failed. errno(%d)", errno);
1530     } else {
1531       _W("candidate process: %d", recv_pid);
1532       if (recv_pid > 1)
1533         cpc->pid = recv_pid;
1534     }
1535   }
1536
1537   return true;
1538 }
1539
1540 static bool __handle_loader_event(int fd, io_condition_e cond, void* data) {
1541   auto* cpc = static_cast<candidate_process_context_t*>(data);
1542   int client_fd;
1543   int client_pid;
1544   int ret;
1545
1546   if (cpc == nullptr)
1547     return false;
1548
1549   if (!cpc->prepared) {
1550     ret = __accept_candidate_process(fd, &client_fd, &client_pid,
1551                                      cpc->is_hydra ? -1 : cpc->pid);
1552     if (ret >= 0) {
1553       /* for hydra need to set pid to pid of non-hydra candidate, */
1554       /* which is connecting now */
1555       if (cpc->is_hydra)
1556         cpc->pid = client_pid;
1557
1558       cpc->prepared = true;
1559       cpc->send_fd = client_fd;
1560
1561       SECURE_LOGI(
1562           "Type %d candidate process was connected, "
1563           "pid: %d",
1564           cpc->type, cpc->pid);
1565
1566       _print_hwc_log(
1567           "Type %d candidate process was connected, "
1568           "pid: %d",
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)
1574         close(client_fd);
1575     }
1576   } else {
1577     __refuse_candidate_process(fd);
1578     _E("Refused candidate process connection");
1579   }
1580
1581   return true;
1582 }
1583
1584 static bool __handle_hydra_event(int fd, io_condition_e cond, void* data) {
1585   auto* cpc = static_cast<candidate_process_context_t*>(data);
1586   int client_fd;
1587   int client_pid;
1588   int ret;
1589
1590   if (cpc == nullptr)
1591     return false;
1592
1593   if (!cpc->prepared) {
1594     ret =
1595         __accept_candidate_process(fd, &client_fd, &client_pid, cpc->hydra_pid);
1596     if (ret >= 0) {
1597       cpc->hydra_fd = client_fd;
1598
1599       SECURE_LOGD(
1600           "Type %d hydra process was connected,"
1601           " pid: %d",
1602           cpc->type, cpc->hydra_pid);
1603
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)
1608         close(client_fd);
1609     }
1610   } else {
1611     __refuse_candidate_process(fd);
1612     _E("Refused hydra process connection");
1613   }
1614
1615   return true;
1616 }
1617
1618 static void __destroy_cleanup_info(struct cleanup_info_s* info) {
1619   if (!info)
1620     return;
1621
1622   free(info->appid);
1623   free(info);
1624 }
1625
1626 static struct cleanup_info_s* __create_cleanup_info(const char* appid,
1627                                                     int pid) {
1628   struct cleanup_info_s* info;
1629
1630   info = static_cast<cleanup_info_s*>(malloc(sizeof(struct cleanup_info_s)));
1631   if (!info) {
1632     _E("Out of memory");
1633     return nullptr;
1634   }
1635
1636   info->appid = strdup(appid);
1637   if (!info->appid) {
1638     _E("strdup(%s) is failed", appid);
1639     __destroy_cleanup_info(info);
1640     return nullptr;
1641   }
1642
1643   info->pid = pid;
1644
1645   return info;
1646 }
1647
1648 static bool __cleanup_app_cb(void* user_data) {
1649   struct cleanup_info_s* info = (struct cleanup_info_s*)user_data;
1650
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);
1655   return false;
1656 }
1657
1658 static void __handle_sigchild(int pid, void* user_data) {
1659   candidate_process_context_t* cpc;
1660   struct cleanup_info_s* info;
1661   char* appid;
1662   int ret = -1;
1663
1664   appid = static_cast<char*>(
1665       g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid)));
1666   if (appid) {
1667     info = __create_cleanup_info(appid, pid);
1668     if (info)
1669       ret = _worker_add_job(__cleaner, __cleanup_app_cb, info);
1670
1671     if (ret != 0) {
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() --");
1676     }
1677
1678     g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid));
1679   }
1680
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);
1687   } else {
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);
1693     }
1694   }
1695
1696   cpc = __find_slot_from_caller_pid(pid);
1697   while (cpc) {
1698     __remove_slot(static_cast<int>(launchpad::LoaderType::Dynamic), cpc->loader_id);
1699     cpc = __find_slot_from_caller_pid(pid);
1700   }
1701 }
1702
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;
1706
1707   if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
1708     _E("fd(%d), io_condition(%d)", fd, cond);
1709     abort();
1710     return false;
1711   }
1712
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);
1716
1717   while (iter) {
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);
1723       }
1724     } else if (cpc->pid > 0) {
1725       __dispose_candidate_process(cpc);
1726       __prepare_candidate_process(cpc->type, cpc->loader_id);
1727     }
1728
1729     iter = g_list_next(iter);
1730   }
1731
1732   return true;
1733 }
1734
1735 static float __interpolator(float input, int cpu_max, int cpu_min) {
1736   float ret;
1737   float min = cpu_min / 100.0f;
1738   float max = cpu_max / 100.0f;
1739
1740   if (input > 1.0f)
1741     input = 1.0f;
1742   if (input < 0.0f)
1743     input = 0.0f;
1744
1745   ret = cos(input * PI) / 2.0f + 0.5f;
1746   ret *= max - min;
1747   ret += min;
1748
1749   return ret;
1750 }
1751
1752 static void __update_threshold(candidate_process_context_t* cpc, float delta) {
1753   static float pos = 0.0f;
1754
1755   pos += delta;
1756   if (pos < 0.0f)
1757     pos = 0.0f;
1758
1759   if (pos > 1.0f)
1760     pos = 1.0f;
1761
1762   cpc->threshold =
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);
1766 }
1767
1768 static gboolean __handle_idle_checker(gpointer data) {
1769   unsigned long long total = 0;
1770   unsigned long long idle = 0;
1771   int per;
1772   candidate_process_context_t* cpc;
1773
1774   if (!data) {
1775     _E("Critical error!");
1776     __sequencer.idle_checker = 0;
1777     __sequencer.running_cpc = nullptr;
1778     return G_SOURCE_REMOVE;
1779   }
1780
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,
1784        cpc->type);
1785     __sequencer.idle_checker = 0;
1786     __sequencer.running_cpc = nullptr;
1787     return G_SOURCE_REMOVE;
1788   }
1789
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;
1795   }
1796
1797   if (cpc->pid != CANDIDATE_NONE) {
1798     _W("Slot is already running. %d:%s:%d", cpc->type, cpc->loader_name,
1799        cpc->pid);
1800     __sequencer.idle_checker = 0;
1801     __sequencer.running_cpc = nullptr;
1802     return G_SOURCE_REMOVE;
1803   }
1804
1805   _get_cpu_idle(&total, &idle);
1806   if (total == cpc->cpu_total_time)
1807     total++;
1808
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);
1811
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;
1819   }
1820
1821   cpc->cpu_idle_time = idle;
1822   cpc->cpu_total_time = total;
1823   __update_threshold(cpc, 0.05f);
1824
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;
1833   }
1834
1835   return G_SOURCE_CONTINUE;
1836 }
1837
1838 static gboolean __on_boot_timeout_cb(gpointer user_data) {
1839   auto* context = static_cast<candidate_process_context_t*>(user_data);
1840
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);
1846   } else {
1847     auto iter = context->condition_path_exists.begin();
1848     while (iter != context->condition_path_exists.end()) {
1849       auto& path = *iter;
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,
1853             context);
1854         return G_SOURCE_REMOVE;
1855       }
1856
1857       iter = context->condition_path_exists.erase(iter);
1858     }
1859
1860     __prepare_candidate_process(context->type, context->loader_id);
1861     context->touched = true;
1862   }
1863
1864   return G_SOURCE_REMOVE;
1865 }
1866
1867 static void __add_on_boot_timer(candidate_process_context_t* context) {
1868   if (context->on_boot_timer != 0)
1869     return;
1870
1871   context->on_boot_timer =
1872       g_timeout_add(context->on_boot_timeout, __on_boot_timeout_cb, context);
1873 }
1874
1875 static int __add_idle_checker(int detection_method, GList* cur) {
1876   candidate_process_context_t* cpc;
1877   GList* iter = cur;
1878
1879   while (iter) {
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);
1883
1884     if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1885       iter = g_list_next(iter);
1886       continue;
1887     }
1888
1889     if (strcmp("null", cpc->loader_path) == 0) {
1890       iter = g_list_next(iter);
1891       continue;
1892     }
1893
1894     if (!cpc->touched && !cpc->on_boot) {
1895       iter = g_list_next(iter);
1896       continue;
1897     }
1898
1899     if (cpc->app_check && !cpc->app_exists) {
1900       iter = g_list_next(iter);
1901       continue;
1902     }
1903
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);
1908         cpc->timer = 0;
1909       }
1910
1911       cpc->cur_event = detection_method;
1912       __sequencer_add_slot(cpc);
1913       __sequencer_run();
1914     }
1915
1916     iter = g_list_next(iter);
1917   }
1918
1919   return -1;
1920 }
1921
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);
1925
1926   return 0;
1927 }
1928
1929 static int __dispatch_cmd_add_loader(bundle* kb) {
1930   const char* add_slot_str = nullptr;
1931   const char* caller_pid = nullptr;
1932   const char* extra;
1933   int lid, size;
1934   char* loader_name;
1935   candidate_process_context_t* cpc;
1936   slot_info_t slot_info;
1937
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);
1942
1943   if (add_slot_str == nullptr || caller_pid == nullptr)
1944     return -1;
1945
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");
1951     return -1;
1952   }
1953
1954   snprintf(loader_name, size, "%s%s%d", add_slot_str, caller_pid, lid);
1955
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;
1979
1980   cpc = __add_slot(&slot_info);
1981   free(loader_name);
1982   if (cpc == nullptr)
1983     return -1;
1984
1985   __set_timer(cpc);
1986   return lid;
1987 }
1988
1989 static int __dispatch_cmd_add_app_defined_loader(bundle* kb) {
1990   const char* loader_name;
1991   int lid, len;
1992   candidate_process_context_t* cpc;
1993   launchpad::LoaderInfoPtr info;
1994   bundle_raw* extra;
1995   slot_info_t slot_info;
1996
1997   _W("cmd add defined loader");
1998   loader_name = bundle_get_val(kb, AUL_K_LOADER_NAME);
1999
2000   if (loader_name == nullptr) {
2001     _E("loader_name is nullptr");
2002     return -EINVAL;
2003   }
2004
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);
2008     return -EINVAL;
2009   }
2010
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;
2034
2035     cpc = __add_slot(&slot_info);
2036     bundle_free_encoded_rawdata(&extra);
2037     if (cpc == nullptr) {
2038       _E("cpc is nullptr");
2039       return -ENOMEM;
2040     }
2041   } else {
2042     lid = cpc->loader_id;
2043   }
2044
2045   if (cpc->pid == CANDIDATE_NONE)
2046     __prepare_candidate_process(static_cast<int>(launchpad::LoaderType::Dynamic), lid);
2047
2048   return lid;
2049 }
2050
2051 static int __dispatch_cmd_remove_loader(bundle* kb) {
2052   const char* id = bundle_get_val(kb, AUL_K_LOADER_ID);
2053   int lid;
2054
2055   _W("cmd remove loader");
2056   if (id) {
2057     lid = atoi(id);
2058     if (__remove_slot(static_cast<int>(launchpad::LoaderType::Dynamic), lid) == 0)
2059       return 0;
2060   }
2061
2062   return -1;
2063 }
2064
2065 static int __check_caller_by_pid(int pid) {
2066   int ret;
2067   char buf[PATH_MAX] = {
2068       0,
2069   };
2070
2071   ret = _proc_get_attr(pid, buf, sizeof(buf));
2072   if (ret < 0)
2073     return -1;
2074
2075   if (strcmp(buf, "User") == 0 || strcmp(buf, "System") == 0 ||
2076       strcmp(buf, "System::Privileged") == 0)
2077     return 0;
2078
2079   return -1;
2080 }
2081
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))
2085     return true;
2086
2087   return false;
2088 }
2089
2090 static candidate_process_context_t* __find_available_slot(
2091     const char* hwacc,
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;
2097
2098   if (loader_name) {
2099     for (auto& info : loader_info_manager->GetLoaderInfoList()) {
2100       if (info->GetName() == loader_name) {
2101         type = info->GetType();
2102         break;
2103       }
2104     }
2105   } else {
2106     if (__is_hw_acc(hwacc))
2107       type = loader_info_manager->FindHwType(app_type);
2108     else
2109       type = loader_info_manager->FindSwType(app_type);
2110   }
2111
2112   cpc = __find_slot(static_cast<int>(type), PAD_LOADER_ID_STATIC);
2113   if (!cpc)
2114     return nullptr;
2115
2116   *org_cpc = cpc;
2117
2118   if (cpc->prepared)
2119     return cpc;
2120
2121   auto a_types = loader_info_manager->GetAlternativeTypes(type);
2122   if (a_types.empty())
2123     return nullptr;
2124
2125   for (auto& a_type : a_types) {
2126     cpc =  __find_slot(static_cast<int>(a_type), PAD_LOADER_ID_STATIC);
2127     if (!cpc)
2128       continue;
2129     if (cpc->prepared) {
2130       return cpc;
2131     }
2132   }
2133
2134   return nullptr;
2135 }
2136
2137 static void __update_slot(int type, bool app_exists) {
2138   candidate_process_context_t* cpc;
2139
2140   cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
2141   if (!cpc)
2142     return;
2143
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) {
2148     if (cpc->pid > 0)
2149       __dispose_candidate_process(cpc);
2150     __sequencer_remove_slot(cpc);
2151     if (__sequencer_queue_is_empty())
2152       __sequencer_stop();
2153   } else {
2154     if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING)
2155       return;
2156
2157     if (!cpc->touched && !cpc->on_boot)
2158       return;
2159
2160     if (cpc->timer > 0) {
2161       g_source_remove(cpc->timer);
2162       cpc->timer = 0;
2163     }
2164
2165     if (cpc->pid == CANDIDATE_NONE) {
2166       __sequencer_add_slot(cpc);
2167       __sequencer_run();
2168     }
2169   }
2170 }
2171
2172 static void __foreach_loader_info(const launchpad::LoaderInfoPtr& info,
2173     void* data) {
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; });
2178
2179   if (it == info->GetAppTypes().end())
2180     return;
2181
2182   info->SetAppExists(ai->exists);
2183   __update_slot(static_cast<int>(info->GetType()), info->IsAppExists());
2184 }
2185
2186 static int __dispatch_cmd_update_app_type(bundle* b) {
2187   struct app_info info;
2188   const char* is_installed;
2189
2190   info.type = bundle_get_val(b, AUL_K_APP_TYPE);
2191   if (!info.type)
2192     return -1;
2193
2194   is_installed = bundle_get_val(b, AUL_K_IS_INSTALLED);
2195   if (is_installed && !strcmp(is_installed, "true"))
2196     info.exists = true;
2197   else
2198     info.exists = false;
2199
2200   _I("[LAUNCHPAD] type(%s), exists(%d)", info.type, info.exists);
2201
2202   for (auto& linfo : loader_info_manager->GetLoaderInfoList()) {
2203     __foreach_loader_info(linfo, &info);
2204   }
2205
2206   return 0;
2207 }
2208
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)
2213     return;
2214
2215   cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2216   if (cpc->is_hydra)
2217     __dispose_hydra_process(cpc);
2218   else
2219     __dispose_candidate_process(cpc);
2220 }
2221
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)
2226     return;
2227
2228   cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2229   if (!cpc->touched && !cpc->on_boot)
2230     return;
2231
2232   if ((cpc->app_check && !cpc->app_exists) || cpc->pid > CANDIDATE_NONE)
2233     return;
2234
2235   if (cpc->detection_method &
2236       static_cast<int>(launchpad::LoaderMethod::Timeout))
2237     __set_timer(cpc);
2238 }
2239
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);
2244   switch (method) {
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);
2250       } else {
2251         __activate_slot(cpc);
2252       }
2253       break;
2254     case launchpad::LoaderMethod::Ttl:
2255       if (force || cpc->deactivation_method & static_cast<int>(method))
2256         __deactivate_slot(cpc);
2257       break;
2258     case launchpad::LoaderMethod::AvailableMemory:
2259       if (force || cpc->activation_method & static_cast<int>(method))
2260         __activate_slot(cpc);
2261       break;
2262     case launchpad::LoaderMethod::Request:
2263       if (force || cpc->activation_method & static_cast<int>(method))
2264         __update_slot_state(cpc, launchpad::LoaderMethod::OutOfMemory, force);
2265       break;
2266     default:
2267       __activate_slot(cpc);
2268       break;
2269   }
2270 }
2271
2272 static void __request_destroy(request_t* request) {
2273   if (request == nullptr)
2274     return;
2275
2276   if (request->clifd > -1)
2277     close(request->clifd);
2278   if (request->menu_info)
2279     _appinfo_free(request->menu_info);
2280   if (request->kb)
2281     bundle_free(request->kb);
2282   if (request->pkt)
2283     free(request->pkt);
2284   free(request);
2285 }
2286
2287 static int __request_create(int fd, request_t** request) {
2288   struct ucred cr;
2289   request_t* req;
2290
2291   if (request == nullptr) {
2292     _E("Invalid parameter");
2293     return -EINVAL;
2294   }
2295
2296   req = static_cast<request_t*>(calloc(1, sizeof(request_t)));
2297   if (req == nullptr) {
2298     _E("calloc() is failed");
2299     return -ENOMEM;
2300   }
2301
2302   req->clifd = -1;
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);
2307     return -ECOMM;
2308   }
2309
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);
2314     req->clifd = -1;
2315     __request_destroy(req);
2316     return -EINVAL;
2317   }
2318
2319   req->cmd = req->pkt->cmd;
2320   req->caller_pid = cr.pid;
2321   req->caller_uid = cr.uid;
2322   *request = req;
2323   return 0;
2324 }
2325
2326 static void __request_send_result(request_h request, int result) {
2327   if (request->clifd < 0)
2328     return;
2329
2330   __real_send(request->clifd, result);
2331   request->clifd = -1;
2332 }
2333
2334 static int __visibility_request_handler(request_h request) {
2335   int ret = __dispatch_cmd_hint(request->kb,
2336       static_cast<int>(launchpad::LoaderMethod::Visibility));
2337
2338   __request_send_result(request, ret);
2339   _D("[PAD_CMD_VISIBILITY] result: %d", ret);
2340   return ret;
2341 }
2342
2343 static int __add_loader_request_handler(request_h request) {
2344   int ret = __dispatch_cmd_add_loader(request->kb);
2345
2346   __request_send_result(request, ret);
2347   _D("[PAD_CMD_ADD_LOADER] result: %d", ret);
2348   return ret;
2349 }
2350
2351 static int __remove_loader_request_handler(request_h request) {
2352   int ret = __dispatch_cmd_remove_loader(request->kb);
2353
2354   __request_send_result(request, ret);
2355   _D("[PAD_CMD_REMOVE_LOADER] result: %d", ret);
2356   return ret;
2357 }
2358
2359 static int __make_default_slots_request_handler(request_h request) {
2360   int ret = __add_default_slots();
2361
2362   __request_send_result(request, ret);
2363   _D("[PAD_CMD_MAKE_DEFAULT_SLOTS] result: %d", ret);
2364   return ret;
2365 }
2366
2367 static int __prepare_app_defined_loader_request_handler(request_h request) {
2368   int ret = __dispatch_cmd_add_app_defined_loader(request->kb);
2369
2370   __request_send_result(request, ret);
2371   _D("[PAD_CMD_PREPARE_APP_DEFINED_LOADER] result: %d", ret);
2372   return ret;
2373 }
2374
2375 static int __demand_request_handler(request_h request) {
2376   int ret = __dispatch_cmd_hint(request->kb,
2377       static_cast<int>(launchpad::LoaderMethod::Demand));
2378
2379   __request_send_result(request, ret);
2380   _D("[PAD_CMD_DEMAND] result: %d", ret);
2381   return ret;
2382 }
2383
2384 static int __ping_request_handler(request_h request) {
2385   __request_send_result(request, getpid());
2386   _D("[PAD_CMD_PING] result: %d", getpid());
2387   return 0;
2388 }
2389
2390 static int __update_app_type_request_handler(request_h request) {
2391   int ret = __dispatch_cmd_update_app_type(request->kb);
2392
2393   _D("[PAD_CMD_UPDATE_APP_TYPE] result: %d", ret);
2394   return ret;
2395 }
2396
2397 static int __connect_request_handler(request_h request) {
2398   if (__client_fd != -1)
2399     close(__client_fd);
2400
2401   __client_fd = request->clifd;
2402   request->clifd = -1;
2403   _D("[PAD_CMD_CONNECT] client fd: %d", __client_fd);
2404   return 0;
2405 }
2406
2407 static int __launch_request_prepare(request_h request) {
2408   const appinfo_t* menu_info;
2409   int type = -1;
2410
2411   request->menu_info = _appinfo_create(request->kb);
2412   if (request->menu_info == nullptr) {
2413     _E("_appinfo_create() is failed");
2414     return -1;
2415   }
2416
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");
2420     return -1;
2421   }
2422
2423   if (request->app_path[0] != '/') {
2424     _E("app path is not absolute path");
2425     return -1;
2426   }
2427
2428   menu_info = request->menu_info;
2429   if (menu_info->hwacc == nullptr) {
2430     _E("Failed to find HW acceeleration type");
2431     return -1;
2432   }
2433
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);
2441
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;
2449     } else {
2450       request->loader_id = PAD_LOADER_ID_DIRECT;
2451     }
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;
2456   } else {
2457     request->loader_id = __get_loader_id(request->kb);
2458     if (request->loader_id <= PAD_LOADER_ID_STATIC) {
2459       request->cpc =
2460           __find_available_slot(menu_info->hwacc, menu_info->app_type,
2461                                 menu_info->loader_name, &request->org_cpc);
2462     } else {
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;
2467     }
2468   }
2469
2470   _modify_bundle(request->kb, request->caller_pid, request->menu_info,
2471                  request->cmd);
2472   if (menu_info->appid == nullptr) {
2473     _E("Unable to get appid from app info");
2474     return -1;
2475   }
2476
2477   PERF("Getting package information & modifying bundle done");
2478   return 0;
2479 }
2480
2481 static void __launch_request_complete(request_h request) {
2482   _memory_monitor_reset_timer();
2483   __request_send_result(request, request->pid);
2484
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);
2491   }
2492 }
2493
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;
2502     }
2503
2504     __update_slot_state(request->org_cpc, launchpad::LoaderMethod::Request, true);
2505     __set_timer(request->org_cpc);
2506   }
2507 }
2508
2509 static void __fork_processing(request_h request) {
2510   if (bundle_get_type(request->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
2511     _debug_init();
2512
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);
2520   }
2521
2522   __request_send_result(request, request->pid);
2523   _W("appid: %s, pid: %d", request->menu_info->appid, request->pid);
2524   __handle_direct_launch(request);
2525 }
2526
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);
2530     return 0;
2531   }
2532
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);
2537   return 0;
2538 }
2539
2540 static int __launch_request_handler(request_h request) {
2541   int ret;
2542
2543   traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH");
2544   INIT_PERF(kb);
2545   PERF("Packet processing start");
2546
2547   ret = __launch_request_prepare(request);
2548   if (ret < 0) {
2549     traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
2550     __request_send_result(request, ret);
2551     return ret;
2552   }
2553
2554   ret = __launch_request_do(request);
2555   if (ret < 0)
2556     request->pid = ret;
2557
2558   __launch_request_complete(request);
2559   traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
2560   _D("[PAD_CMD_LAUNCH] appid: %s, result: %d", request->menu_info->appid,
2561      request->pid);
2562   return 0;
2563 }
2564
2565 static request_handler __request_handlers[PAD_CMD_CONNECT + 1] = {};
2566
2567 static bool __handle_launch_event(int fd, io_condition_e cond, void* data) {
2568   request_t* request = nullptr;
2569   int ret;
2570
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;
2575     return false;
2576   }
2577
2578   ret = __request_create(fd, &request);
2579   if (ret != 0)
2580     return true;
2581
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);
2588       return true;
2589     }
2590   }
2591
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);
2597     return true;
2598   }
2599
2600   __request_handlers[request->cmd](request);
2601   __request_destroy(request);
2602   return true;
2603 }
2604
2605 static void __destroy_slot(candidate_process_context_t* cpc) {
2606   if (!cpc)
2607     return;
2608
2609   if (cpc->hydra_channel)
2610     _io_channel_destroy(cpc->hydra_channel);
2611
2612   if (cpc->channel)
2613     _io_channel_destroy(cpc->channel);
2614
2615   if (cpc->loader_extra)
2616     free(cpc->loader_extra);
2617
2618   if (cpc->loader_path)
2619     free(cpc->loader_path);
2620
2621   if (cpc->loader_name)
2622     free(cpc->loader_name);
2623
2624   delete cpc;
2625 }
2626
2627 static candidate_process_context_t* __create_slot(slot_info_t* info) {
2628   candidate_process_context_t* cpc;
2629
2630   cpc = new candidate_process_context_t();
2631   if (cpc == nullptr) {
2632     _E("Out of memory");
2633     return nullptr;
2634   }
2635
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);
2640     return nullptr;
2641   }
2642
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);
2647     return nullptr;
2648   }
2649
2650   cpc->loader_extra =
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);
2655     return nullptr;
2656   }
2657
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;
2664   cpc->send_fd = -1;
2665   cpc->hydra_fd = -1;
2666   cpc->last_exec_time = 0;
2667   cpc->timer = 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;
2678   cpc->cur_event = 0;
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;
2689   cpc->pss = 0;
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;
2695
2696   if ((cpc->deactivation_method & static_cast<int>(launchpad::LoaderMethod::OutOfMemory)) && __is_low_memory())
2697     cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2698   else
2699     cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2700
2701   _W("loader(%s), type(%d), state(%d)", cpc->loader_name, cpc->type,
2702      cpc->state);
2703   return cpc;
2704 }
2705
2706 static candidate_process_context_t* __add_slot(slot_info_t* info) {
2707   candidate_process_context_t* cpc;
2708   int fd;
2709   io_channel_h channel;
2710   int hydra_fd;
2711   io_channel_h hydra_channel;
2712
2713   if (info == nullptr)
2714     return nullptr;
2715
2716   if (__find_slot(info->type, info->loader_id) != nullptr)
2717     return nullptr;
2718
2719   cpc = __create_slot(info);
2720   if (cpc == nullptr)
2721     return nullptr;
2722
2723   fd = __listen_candidate_process(cpc->type, cpc->loader_id);
2724   if (fd == -1) {
2725     _E("[launchpad] Listening the socket to "
2726        "the type %d candidate process failed.",
2727        cpc->type);
2728     __destroy_slot(cpc);
2729     return nullptr;
2730   }
2731
2732   channel = _io_channel_create(fd, IO_IN, __handle_loader_event, cpc);
2733   if (!channel) {
2734     close(fd);
2735     __destroy_slot(cpc);
2736     return nullptr;
2737   }
2738
2739   cpc->channel = channel;
2740
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.",
2746          cpc->type);
2747       __destroy_slot(cpc);
2748       return nullptr;
2749     }
2750
2751     hydra_channel =
2752         _io_channel_create(hydra_fd, IO_IN, __handle_hydra_event, cpc);
2753     if (!hydra_channel) {
2754       close(hydra_fd);
2755       __destroy_slot(cpc);
2756       return nullptr;
2757     }
2758
2759     cpc->hydra_channel = hydra_channel;
2760   }
2761
2762   candidate_slot_list = g_list_append(candidate_slot_list, cpc);
2763
2764   return cpc;
2765 }
2766
2767 static int __remove_slot(int type, int loader_id) {
2768   candidate_process_context_t* cpc;
2769   GList* iter;
2770
2771   iter = candidate_slot_list;
2772   while (iter) {
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);
2778       return 0;
2779     }
2780
2781     iter = g_list_next(iter);
2782   }
2783
2784   return -1;
2785 }
2786
2787 static int __init_launchpad_fd(int argc, char** argv) {
2788   int fd;
2789
2790   fd = __launchpad_pre_init(argc, argv);
2791   if (fd < 0) {
2792     _E("launchpad pre init failed");
2793     return -1;
2794   }
2795
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) {
2800     close(fd);
2801     return -1;
2802   }
2803
2804   return 0;
2805 }
2806
2807 static bool __on_directory_create(const char* event_name,
2808                                   uint32_t mask,
2809                                   void* user_data) {
2810   if (!event_name) {
2811     _E("Invalid parameter");
2812     return true;
2813   }
2814
2815   if (!strcmp(event_name, LOADERS_PATH)) {
2816     _W("%s is created", LOADERS_PATH);
2817     __init_app_defined_loader_monitor();
2818     return false;
2819   }
2820
2821   return true;
2822 }
2823
2824 static bool __on_file_change(const char* event_name,
2825                              uint32_t mask,
2826                              void* user_data) {
2827   char buf[PATH_MAX];
2828   char* ext;
2829   launchpad::LoaderInfoPtr info;
2830   candidate_process_context_t* cpc;
2831
2832   if (!event_name) {
2833     _E("Invalid parameter");
2834     return true;
2835   }
2836
2837   ext = const_cast<char*>(strrchr(event_name, '.'));
2838   if (ext == nullptr || strcmp(ext, ".loader") != 0)
2839     return true;
2840
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);
2846
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);
2851   }
2852
2853   return true;
2854 }
2855
2856 static void __init_app_defined_loader_monitor(void) {
2857   int ret;
2858
2859   ret = access(APP_DEFINED_LOADER_INFO_PATH, F_OK);
2860   if (ret < 0) {
2861     _W("Failed to access %s", APP_DEFINED_LOADER_INFO_PATH);
2862     ret = _inotify_add_watch(OPT_SHARE_PATH, IN_CREATE, __on_directory_create,
2863                              nullptr);
2864     if (ret != 0)
2865       _E("Failed to add inotify watch %s", OPT_SHARE_PATH);
2866
2867     return;
2868   }
2869
2870   ret = _inotify_add_watch(APP_DEFINED_LOADER_INFO_PATH, IN_CREATE | IN_DELETE,
2871                            __on_file_change, nullptr);
2872
2873   if (ret < 0) {
2874     _E("Failed to add inotify watch %s", APP_DEFINED_LOADER_INFO_PATH);
2875   }
2876
2877   return;
2878 }
2879
2880 static int __init_label_monitor_fd(void) {
2881   int r;
2882   int fd = -1;
2883
2884   auto err_handler = [&]() -> int {
2885     if (fd > 0)
2886       close(fd);
2887
2888     if (label_monitor) {
2889       security_manager_app_labels_monitor_finish(label_monitor);
2890       label_monitor = nullptr;
2891     }
2892     return -1;
2893   };
2894
2895   r = security_manager_app_labels_monitor_init(&label_monitor);
2896   if (r != SECURITY_MANAGER_SUCCESS)
2897     return -1;
2898
2899   r = security_manager_app_labels_monitor_process(label_monitor);
2900   if (r != SECURITY_MANAGER_SUCCESS)
2901     return err_handler();
2902
2903   security_manager_app_labels_monitor_get_fd(label_monitor, &fd);
2904   if (fd < 0) {
2905     _E("failed to get fd");
2906     return err_handler();
2907   }
2908
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();
2914
2915   return 0;
2916
2917
2918 }
2919
2920 static int __verify_loader_caps(const char* loader) {
2921   cap_t cap_d;
2922   cap_flag_value_t eff_state;
2923   cap_flag_value_t inh_state;
2924   cap_value_t values[] = {CAP_SETGID, CAP_MAC_ADMIN};
2925   int r;
2926   int i;
2927   int size = ARRAY_SIZE(values);
2928
2929   /* If Dytransition feature is enabled, CAP_MAC_ADMIN is unnecessary */
2930   if (label_monitor)
2931     size--;
2932
2933   cap_d = cap_get_file(loader);
2934   if (!cap_d) {
2935     _E("Failed to get cap from file(%s)", loader);
2936     return -1;
2937   }
2938
2939   for (i = 0; i < size; i++) {
2940     r = cap_get_flag(cap_d, values[i], CAP_INHERITABLE, &inh_state);
2941     if (r != 0) {
2942       _E("Failed to get cap inh - errno(%d)", errno);
2943       cap_free(cap_d);
2944       return -1;
2945     }
2946
2947     r = cap_get_flag(cap_d, values[i], CAP_EFFECTIVE, &eff_state);
2948     if (r != 0) {
2949       _E("Failed to get cap eff - errno(%d)", errno);
2950       cap_free(cap_d);
2951       return -1;
2952     }
2953
2954     if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) {
2955       _E("The %s doesn't have %d cap", loader, values[i]);
2956       cap_free(cap_d);
2957       return -1;
2958     }
2959   }
2960   cap_free(cap_d);
2961
2962   return 0;
2963 }
2964
2965 static void __get_app_type_string(const launchpad::LoaderInfoPtr& info,
2966     char buf[], size_t size) {
2967   char* ptr = buf;
2968
2969   for (auto& app_type : info->GetAppTypes()) {
2970     if (size < app_type.size() + 1)
2971       return;
2972
2973     strncpy(ptr, app_type.c_str(), size);
2974     ptr += app_type.size();
2975     size -= app_type.size();
2976     (*ptr++) = ' ';
2977     size--;
2978   }
2979 }
2980
2981 static void __add_slot_from_info(const launchpad::LoaderInfoPtr& info) {
2982   candidate_process_context_t* cpc;
2983   bundle_raw* extra = nullptr;
2984   int len;
2985   char buf[2048] = {
2986       0,
2987   };
2988
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()
3001   };
3002
3003   if (info->GetExe() == "null") {
3004     slot_info.loader_id = PAD_LOADER_ID_DIRECT;
3005
3006     cpc = __add_slot(&slot_info);
3007     if (cpc == nullptr)
3008       return;
3009
3010     info->SetType(static_cast<launchpad::LoaderType>(
3011         static_cast<int>(launchpad::LoaderType::User) + user_slot_offset));
3012     user_slot_offset++;
3013     return;
3014   } else if (access(info->GetExe().c_str(), F_OK | X_OK) == 0) {
3015     if (__verify_loader_caps(info->GetExe().c_str()) < 0)
3016       return;
3017
3018     bundle_encode(info->GetExtra().GetHandle(), &extra, &len);
3019
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();
3028
3029     cpc = __add_slot(&slot_info);
3030     bundle_free_encoded_rawdata(&extra);
3031     if (cpc == nullptr)
3032       return;
3033
3034     info->SetType(static_cast<launchpad::LoaderType>(
3035         static_cast<int>(launchpad::LoaderType::User) + user_slot_offset));
3036     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()));
3042   }
3043 }
3044
3045 static int __add_default_slots(void) {
3046   loader_info_manager =
3047       std::make_unique<launchpad::LoaderInfoManager>(LOADER_INFO_PATH);
3048
3049   loader_info_manager->Load();
3050   user_slot_offset = 0;
3051   for (auto& info : loader_info_manager->GetLoaderInfoList()) {
3052     __add_slot_from_info(info);
3053   }
3054   __add_idle_checker(0, candidate_slot_list);
3055
3056   return 0;
3057 }
3058
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);
3063
3064   app_defined_loader_info_manager->Load();
3065 }
3066
3067 static bool __is_low_memory(void) {
3068   if (_memory_monitor_is_low_memory())
3069     return true;
3070
3071   if (__memory_status_low >= MEMORY_STATUS_LOW)
3072     return true;
3073
3074   return false;
3075 }
3076
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);
3080 }
3081
3082 static void __update_lang(keynode_t* node, void* user_data) {
3083   char* lang;
3084
3085   lang = vconf_keynode_get_str(node);
3086   if (!lang) {
3087     _E("Failed to get language");
3088     return;
3089   }
3090
3091   setenv("LANG", lang, 1);
3092 }
3093
3094 static void __region_format_changed_cb(keynode_t* node, void* data) {
3095   char* region;
3096
3097   region = vconf_keynode_get_str(node);
3098   if (!region) {
3099     _E("Failed to get value");
3100     return;
3101   }
3102
3103   setenv("LC_CTYPE", region, 1);
3104 }
3105
3106 static void __memory_status_low_changed_cb(keynode_t* node, void* data) {
3107   candidate_process_context_t* cpc;
3108   GList* iter;
3109
3110   __memory_status_low = vconf_keynode_get_int(node);
3111   if (__memory_status_low >= MEMORY_STATUS_LOW) {
3112     _W("Low memory");
3113     iter = candidate_slot_list;
3114     while (iter) {
3115       cpc = (candidate_process_context_t*)iter->data;
3116       __update_slot_state(cpc, launchpad::LoaderMethod::OutOfMemory, false);
3117       iter = g_list_next(iter);
3118     }
3119   }
3120 }
3121
3122 static void __memory_status_normal_changed_cb(keynode_t* node, void* data) {
3123   candidate_process_context_t* cpc;
3124   GList* iter;
3125
3126   __memory_status_normal = vconf_keynode_get_int(node);
3127   if (__memory_status_normal == MEMORY_STATUS_NORMAL) {
3128     _W("Normal");
3129     iter = candidate_slot_list;
3130     while (iter) {
3131       cpc = (candidate_process_context_t*)iter->data;
3132       __update_slot_state(cpc, launchpad::LoaderMethod::AvailableMemory, true);
3133       iter = g_list_next(iter);
3134     }
3135   }
3136 }
3137
3138 static void __unregister_vconf_events(void) {
3139   const char* key;
3140   config_type_e type;
3141
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);
3145
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);
3149
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);
3154 }
3155
3156 static int __register_vconf_events(void) {
3157   int r;
3158   char* lang;
3159   char* region;
3160   const char* key;
3161   config_type_e type;
3162
3163   r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc);
3164   if (r != VCONF_OK)
3165     _E("Failed to get vconf hw acceleration. err = %d", r);
3166
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);
3171   }
3172
3173   lang = vconf_get_str(VCONFKEY_LANGSET);
3174   if (lang) {
3175     setenv("LANG", lang, 1);
3176     free(lang);
3177   }
3178
3179   r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, nullptr);
3180   if (r != VCONF_OK)
3181     _E("Failed to register callback for langset. err = %d", r);
3182
3183   region = vconf_get_str(VCONFKEY_REGIONFORMAT);
3184   if (region) {
3185     setenv("LC_CTYPE", region, 1);
3186     free(region);
3187   }
3188
3189   r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT,
3190                                __region_format_changed_cb, nullptr);
3191   if (r != VCONF_OK)
3192     _E("Failed to register callback for regionformat. err = %d", r);
3193
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);
3198
3199   r = vconf_get_int(key, &__memory_status_low);
3200   if (r != VCONF_OK)
3201     _E("Failed to get vconf low memory. err = %d", r);
3202
3203   r = vconf_notify_key_changed(key, __memory_status_low_changed_cb, nullptr);
3204   if (r != 0)
3205     _E("Failed to register callback for low memory. err = %d", r);
3206
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);
3211
3212   r = vconf_get_int(key, &__memory_status_normal);
3213   if (r != VCONF_OK)
3214     _E("Failed to get vconf normal memory. err = %d", r);
3215
3216   r = vconf_notify_key_changed(key, __memory_status_normal_changed_cb, nullptr);
3217   if (r != 0)
3218     _E("Failed to register callback for normal memory. err = %d", r);
3219
3220   return 0;
3221 }
3222
3223 static bool __handle_logger(int fd, io_condition_e cond, void* data) {
3224   app_pkt_t* pkt;
3225   struct ucred cr;
3226   int clifd = -1;
3227
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;
3232     return false;
3233   }
3234
3235   pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
3236   if (!pkt) {
3237     _E("Failed to receive the packet");
3238     return true;
3239   }
3240
3241   if (getuid() != cr.uid) {
3242     _E("Invalid caller");
3243     goto end;
3244   }
3245
3246   if (pkt->len <= 0) {
3247     _E("Invalid message");
3248     goto end;
3249   }
3250
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);
3254 end:
3255   if (clifd != -1)
3256     close(clifd);
3257
3258   free(pkt);
3259
3260   return true;
3261 }
3262
3263 static int __init_logger_fd(void) {
3264   int fd;
3265
3266   fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK);
3267   if (fd < 0) {
3268     _E("Failed to create logger socker");
3269     return -1;
3270   }
3271
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) {
3276     close(fd);
3277     return -1;
3278   }
3279
3280   return 0;
3281 }
3282
3283 static int __memory_monitor_cb(bool low_memory, void* user_data) {
3284   candidate_process_context_t* cpc;
3285
3286   cpc = __get_running_slot(false);
3287   if (!cpc && low_memory)
3288     return -1;
3289
3290   if (low_memory) {
3291     _W("Low memory");
3292     __update_slots_pss();
3293
3294     candidate_slot_list = g_list_sort(candidate_slot_list, __compare_slot);
3295     __pause_all_running_slots(false);
3296   } else {
3297     __resume_all_slots();
3298   }
3299
3300   return 0;
3301 }
3302
3303 static gboolean __logger_recovery_cb(gpointer data) {
3304   auto channel = static_cast<io_channel_h>(data);
3305   int ret;
3306
3307   _io_channel_destroy(channel);
3308
3309   ret = __init_logger_fd();
3310   if (ret < 0) {
3311     _E("Failed to recover logger socket");
3312     return G_SOURCE_REMOVE;
3313   }
3314
3315   _E("[__RECOVERY__] Logger socket");
3316
3317   return G_SOURCE_REMOVE;
3318 }
3319
3320 static gboolean __launchpad_recovery_cb(gpointer data) {
3321   auto channel = static_cast<io_channel_h>(data);
3322   int ret;
3323
3324   _io_channel_destroy(channel);
3325
3326   ret = __init_launchpad_fd(0, nullptr);
3327   if (ret < 0) {
3328     _E("Failed to recover launchpad socket");
3329     abort();
3330     return G_SOURCE_REMOVE;
3331   }
3332
3333   _E("[__RECOVERY__] Launchpad socket");
3334
3335   return G_SOURCE_REMOVE;
3336 }
3337
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;
3352
3353   _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__);
3354   int ret = __sequencer_init();
3355   if (ret < 0) {
3356     _E("Failed to initialize sequencer");
3357     return -1;
3358   }
3359
3360   ret = _signal_init();
3361   if (ret < 0) {
3362     _E("Failed to initialize signal");
3363     return -1;
3364   }
3365
3366   _signal_set_sigchld_cb(__handle_sigchild, nullptr);
3367
3368   ret = __init_launchpad_fd(argc, argv);
3369   if (ret != 0) {
3370     _E("__init_launchpad_fd() failed");
3371     return -1;
3372   }
3373
3374   ret = __init_logger_fd();
3375   if (ret != 0) {
3376     _E("__init_logger_fd() failed");
3377     return -1;
3378   }
3379
3380   ret = __init_label_monitor_fd();
3381   if (ret != 0)
3382     _W("Failed to initialize label monitor");
3383
3384   ret = _config_init();
3385   if (ret != 0)
3386     _W("Failed to initialize config");
3387
3388   ret = _dbus_init();
3389   if (ret != 0)
3390     _W("Failed to initialize dbus");
3391
3392   _inotify_init();
3393   _memory_monitor_init();
3394   _memory_monitor_set_event_cb(__memory_monitor_cb, nullptr);
3395
3396   MAX_CPU_CHECK_COUNT =
3397       _config_get_int_value(CONFIG_TYPE_CPU_CHECKER_MAX_COUNT);
3398   __add_default_slots();
3399
3400   launchpad::LauncherInfoInflator inflator;
3401   launcher_info_list = inflator.Inflate(LAUNCHER_INFO_PATH);
3402
3403   __add_app_defined_loaders();
3404
3405   ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL);
3406   if (ret < 0)
3407     _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL);
3408
3409   __pid_table =
3410       g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr, free);
3411   if (!__pid_table) {
3412     _E("Failed to create pid table");
3413     return -1;
3414   }
3415
3416   ret = _worker_create("cleaner+", &__cleaner);
3417   if (ret < 0)
3418     return ret;
3419
3420   __register_vconf_events();
3421   __init_app_defined_loader_monitor();
3422   _log_init();
3423   _print_hwc_log("%s(%d): END", __FUNCTION__, __LINE__);
3424
3425   return 0;
3426 }
3427
3428 static void __after_loop(void) {
3429   _log_fini();
3430   _memory_monitor_fini();
3431   __unregister_vconf_events();
3432   _worker_destroy(__cleaner);
3433   if (__pid_table)
3434     g_hash_table_destroy(__pid_table);
3435
3436   if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0)
3437     _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL);
3438
3439   _debug_fini();
3440   launcher_info_list.clear();
3441   _dbus_fini();
3442   _config_fini();
3443   _inotify_fini();
3444   app_defined_loader_info_manager->Dispose();
3445
3446   if (__label_monitor_channel)
3447     _io_channel_destroy(__label_monitor_channel);
3448
3449   if (label_monitor)
3450     security_manager_app_labels_monitor_finish(label_monitor);
3451
3452   if (__logger_channel)
3453     _io_channel_destroy(__logger_channel);
3454
3455   if (__launchpad_channel)
3456     _io_channel_destroy(__launchpad_channel);
3457
3458   _signal_fini();
3459
3460   __sequencer_fini();
3461 }
3462
3463 int main(int argc, char** argv) {
3464   GMainLoop* mainloop = nullptr;
3465
3466   _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__);
3467   prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
3468
3469   mainloop = g_main_loop_new(nullptr, FALSE);
3470   if (!mainloop) {
3471     _E("Failed to create glib main loop");
3472     return -1;
3473   }
3474
3475   _print_hwc_log("%s(%d): __before_loop()", __FUNCTION__, __LINE__);
3476   if (__before_loop(argc, argv) != 0) {
3477     _E("process-pool Initialization failed!");
3478     return -1;
3479   }
3480
3481 #ifdef TIZEN_FEATURE_PRIORITY_CHANGE
3482   _set_priority(-12);
3483 #endif
3484   _print_hwc_log("%s(%d): g_main_loop_run()", __FUNCTION__, __LINE__);
3485   g_main_loop_run(mainloop);
3486
3487   __after_loop();
3488
3489   return -1;
3490 }