Fix directory hierarchy & cmake configuration files
[platform/core/appfw/launchpad.git] / src / launchpad-process-pool / src / launchpad.c
1 /*
2  * Copyright (c) 2015 - 2016 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 #define _GNU_SOURCE
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <systemd/sd-daemon.h>
22 #include <sys/prctl.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <sys/stat.h>
28 #include <sys/capability.h>
29 #include <sched.h>
30 #include <stdbool.h>
31 #include <malloc.h>
32 #include <bundle_internal.h>
33 #include <security-manager.h>
34 #include <time.h>
35 #include <systemd/sd-daemon.h>
36 #include <glib.h>
37 #include <linux/limits.h>
38 #include <ttrace.h>
39 #include <vconf.h>
40 #include <math.h>
41 #include <trust-anchor.h>
42
43 #include "key.h"
44 #include "launcher_info.h"
45 #include "launchpad_common.h"
46 #include "launchpad_config.h"
47 #include "launchpad_dbus.h"
48 #include "launchpad_debug.h"
49 #include "launchpad_inotify.h"
50 #include "launchpad_io_channel.h"
51 #include "launchpad_log.h"
52 #include "launchpad_memory_monitor.h"
53 #include "launchpad_plugin.h"
54 #include "launchpad_proc.h"
55 #include "launchpad_signal.h"
56 #include "launchpad_types.h"
57 #include "launchpad_worker.h"
58 #include "loader_info.h"
59 #include "perf.h"
60
61 #define AUL_PR_NAME         16
62 #define EXEC_CANDIDATE_EXPIRED 5
63 #define EXEC_CANDIDATE_WAIT 1
64 #define DIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a))
65 #define CANDIDATE_NONE 0
66 #define HYDRA_NONE 0
67 #define PROCESS_POOL_LAUNCHPAD_SOCK ".launchpad-process-pool-sock"
68 #define LAUNCHPAD_LOGGER_SOCK ".launchpad-logger-sock"
69 #define LOADER_PATH_DEFAULT "/usr/bin/launchpad-loader"
70 #define LOADER_INFO_PATH        "/usr/share/aul"
71 #define OPT_SHARE_PATH "/opt/share"
72 #define LOADERS_PATH "loaders"
73 #define APP_DEFINED_LOADER_INFO_PATH    OPT_SHARE_PATH "/" LOADERS_PATH
74 #define COMMON_LOADER_NAME "common-loader1"
75
76 #define LAUNCHER_INFO_PATH      LOADER_INFO_PATH
77 #define REGULAR_UID_MIN 5000
78 #define PAD_ERR_FAILED                  -1
79 #define PAD_ERR_REJECTED                -2
80 #define PAD_ERR_INVALID_ARGUMENT        -3
81 #define PAD_ERR_INVALID_PATH            -4
82 #define CPU_CHECKER_TIMEOUT             1000
83 #define PI                              3.14159265
84 #define WIN_SCORE 100
85 #define LOSE_SCORE_RATE 0.7f
86
87 enum candidate_process_state_e {
88         CANDIDATE_PROCESS_STATE_RUNNING,
89         CANDIDATE_PROCESS_STATE_PAUSED,
90 };
91
92 typedef struct {
93         int type;
94         bool prepared;
95         int pid; /* for hydra this pid is not the pid of hydra itself */
96                  /* but pid of non-hydra candidate, which was forked from hydra */
97         int hydra_pid;
98         int loader_id;
99         int caller_pid;
100         int send_fd;
101         int hydra_fd;
102         int last_exec_time;
103         guint timer;
104         char *loader_name;
105         char *loader_path;
106         char *loader_extra;
107         int detection_method;
108         int timeout_val;
109         unsigned long long cpu_total_time;
110         unsigned long long cpu_idle_time;
111         int threshold;
112         int threshold_max;
113         int threshold_min;
114         int cur_event;
115         bool on_boot;
116         bool app_exists;
117         bool touched;
118         int activation_method;
119         int deactivation_method;
120         unsigned int ttl;
121         guint live_timer;
122         int state;
123         bool is_hydra;
124         bool app_check;
125         io_channel_h client_channel;
126         io_channel_h channel;
127         io_channel_h hydra_channel;
128         unsigned int score;
129         unsigned int pss;
130         int cpu_check_count;
131 } candidate_process_context_t;
132
133 typedef struct {
134         GPollFD *gpollfd;
135         int type;
136         int loader_id;
137 } loader_context_t;
138
139 typedef struct {
140         GQueue *queue;
141         guint timer;
142         guint idle_checker;
143         candidate_process_context_t *running_cpc;
144 } sequencer;
145
146 struct app_launch_arg {
147         const char *appid;
148         const char *app_path;
149         appinfo_t *menu_info;
150         bundle *kb;
151 };
152
153 struct app_arg {
154         int argc;
155         char **argv;
156 };
157
158 struct app_info {
159         const char *type;
160         bool exists;
161 };
162
163 struct cleanup_info_s {
164         char *appid;
165         int pid;
166 };
167
168 static int __sys_hwacc;
169 static GList *loader_info_list;
170 static GList *app_defined_loader_info_list;
171 static int user_slot_offset;
172 static GList *candidate_slot_list;
173 static app_labels_monitor *label_monitor;
174 static GList *launcher_info_list;
175 static GHashTable *__pid_table;
176 static int __memory_status_low;
177 static int __memory_status_normal;
178 static sequencer __sequencer;
179 static int MEMORY_STATUS_LOW;
180 static int MEMORY_STATUS_NORMAL;
181 static int MAX_CPU_CHECK_COUNT;
182
183 static io_channel_h __logger_channel;
184 static io_channel_h __label_monitor_channel;
185 static io_channel_h __launchpad_channel;
186
187 static candidate_process_context_t *__add_slot(int type, int loader_id,
188                 int caller_pid, const char *loader_name,
189                 const char *loader_path, const char *extra,
190                 int detection_method, int activation_method,
191                 int deactivation_method, unsigned int ttl, int timeout_val,
192                 int threshold_max, int threshold_min, bool on_boot,
193                 bool app_exists, bool is_hydra, bool app_check);
194 static int __remove_slot(int type, int loader_id);
195 static int __add_default_slots(void);
196 static gboolean __handle_idle_checker(gpointer data);
197 static int __add_idle_checker(int detection_method, GList *cur);
198 static void __dispose_candidate_process(candidate_process_context_t *cpc);
199 static bool __is_low_memory(void);
200 static void __update_slot_state(candidate_process_context_t *cpc, int method,
201                 bool force);
202 static void __init_app_defined_loader_monitor(void);
203 static gboolean __launchpad_recovery_cb(gpointer data);
204 static gboolean __logger_recovery_cb(gpointer data);
205
206 static gboolean __handle_queuing_slots(gpointer data)
207 {
208         candidate_process_context_t *cpc;
209         unsigned long long total = 0;
210         unsigned long long idle = 0;
211
212         if (__sequencer.idle_checker > 0)
213                 return G_SOURCE_CONTINUE;
214
215         if (g_queue_is_empty(__sequencer.queue)) {
216                 __sequencer.timer = 0;
217                 return G_SOURCE_REMOVE;
218         }
219
220         cpc = (candidate_process_context_t *)g_queue_pop_head(
221                         __sequencer.queue);
222         if (!cpc) {
223                 _E("Critical error!");
224                 __sequencer.timer = 0;
225                 return G_SOURCE_REMOVE;;
226         }
227
228         if (cpc->app_check && !cpc->app_exists) {
229                 _W("The application is not installed. Type(%d)", cpc->type);
230                 return G_SOURCE_CONTINUE;
231         }
232
233         if (cpc->timer) {
234                 g_source_remove(cpc->timer);
235                 cpc->timer = 0;
236         }
237
238         if (cpc->pid != CANDIDATE_NONE) {
239                 _W("The slot(%d) is already running. pid(%d)",
240                                 cpc->type, cpc->pid);
241                 return G_SOURCE_CONTINUE;
242         }
243
244         _get_cpu_idle(&total, &idle);
245         cpc->cpu_idle_time = idle;
246         cpc->cpu_total_time = total;
247         cpc->cpu_check_count = 0;
248
249         __sequencer.idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT,
250                         __handle_idle_checker, cpc);
251         __sequencer.running_cpc = cpc;
252
253         _D("[__SEQUENCER__] Add idle checker. Type(%d)", cpc->type);
254
255         return G_SOURCE_CONTINUE;
256 }
257
258 static bool __sequencer_slot_is_running(candidate_process_context_t *cpc)
259 {
260         if (__sequencer.running_cpc == cpc)
261                 return true;
262
263         return false;
264 }
265
266 static bool __sequencer_slot_exist(candidate_process_context_t *cpc)
267 {
268         GList *found;
269
270         found = g_queue_find(__sequencer.queue, cpc);
271         if (found)
272                 return true;
273
274         return false;
275 }
276
277 static int __sequencer_add_slot(candidate_process_context_t *cpc)
278 {
279         if (__sequencer_slot_exist(cpc)) {
280                 _W("Already exists");
281                 return -1;
282         }
283
284         if (__sequencer_slot_is_running(cpc)) {
285                 _W("slot(%d) is running", cpc->type);
286                 return -1;
287         }
288
289         g_queue_push_tail(__sequencer.queue, cpc);
290
291         return 0;
292 }
293
294 static void __sequencer_remove_slot(candidate_process_context_t *cpc)
295 {
296         g_queue_remove(__sequencer.queue, cpc);
297 }
298
299 static void __sequencer_run(void)
300 {
301         if (__sequencer.timer)
302                 return;
303
304         __sequencer.timer = g_timeout_add(500, __handle_queuing_slots, NULL);
305         if (!__sequencer.timer)
306                 _E("Failed to add sequencer timer");
307 }
308
309 static void __sequencer_stop(void)
310 {
311         if (!__sequencer.timer)
312                 return;
313
314         g_source_remove(__sequencer.timer);
315         __sequencer.timer = 0;
316 }
317
318 static bool __sequencer_queue_is_empty(void)
319 {
320         if (g_queue_is_empty(__sequencer.queue))
321                 return true;
322
323         return false;
324 }
325
326 static int __sequencer_init(void)
327 {
328         _D("[__SEQUENCER__] Init");
329
330         __sequencer.queue = g_queue_new();
331         if (!__sequencer.queue) {
332                 _E("Out of memory");
333                 return -1;
334         }
335
336         return 0;
337 }
338
339 static void __sequencer_fini(void)
340 {
341         _D("[__SEQUENCER__] Finish");
342
343         if (__sequencer.idle_checker > 0)
344                 g_source_remove(__sequencer.idle_checker);
345
346         if (__sequencer.timer > 0)
347                 g_source_remove(__sequencer.timer);
348
349         g_queue_free(__sequencer.queue);
350 }
351
352 static int __make_loader_id(void)
353 {
354         static int id = PAD_LOADER_ID_DYNAMIC_BASE;
355
356         return ++id;
357 }
358
359 static candidate_process_context_t *__find_slot_from_static_type(int type)
360 {
361         candidate_process_context_t *cpc;
362         GList *iter = candidate_slot_list;
363
364         if (type == LAUNCHPAD_LOADER_TYPE_DYNAMIC ||
365                         type == LAUNCHPAD_LOADER_TYPE_UNSUPPORTED)
366                 return NULL;
367
368         while (iter) {
369                 cpc = (candidate_process_context_t *)iter->data;
370                 if (type == cpc->type)
371                         return cpc;
372
373                 iter = g_list_next(iter);
374         }
375
376         return NULL;
377 }
378
379 static candidate_process_context_t *__find_slot_from_pid(int pid)
380 {
381         candidate_process_context_t *cpc;
382         GList *iter = candidate_slot_list;
383
384         while (iter) {
385                 cpc = (candidate_process_context_t *)iter->data;
386                 if (pid == cpc->pid)
387                         return cpc;
388
389                 iter = g_list_next(iter);
390         }
391
392         return NULL;
393 }
394
395 static candidate_process_context_t *__find_hydra_slot_from_pid(int pid)
396 {
397         candidate_process_context_t *cpc;
398         GList *iter = candidate_slot_list;
399
400         while (iter) {
401                 cpc = (candidate_process_context_t *)iter->data;
402                 if (cpc->is_hydra && pid == cpc->hydra_pid)
403                         return cpc;
404
405                 iter = g_list_next(iter);
406         }
407
408         return NULL;
409 }
410
411 static candidate_process_context_t *__find_slot_from_caller_pid(int caller_pid)
412 {
413         candidate_process_context_t *cpc;
414         GList *iter = candidate_slot_list;
415
416         while (iter) {
417                 cpc = (candidate_process_context_t *)iter->data;
418                 if (caller_pid == cpc->caller_pid)
419                         return cpc;
420
421                 iter = g_list_next(iter);
422         }
423
424         return NULL;
425 }
426
427 static candidate_process_context_t *__find_slot_from_loader_id(int id)
428 {
429         candidate_process_context_t *cpc;
430         GList *iter = candidate_slot_list;
431
432         while (iter) {
433                 cpc = (candidate_process_context_t *)iter->data;
434                 if (id == cpc->loader_id)
435                         return cpc;
436
437                 iter = g_list_next(iter);
438         }
439
440         return NULL;
441 }
442
443 static candidate_process_context_t *__find_slot_from_loader_name(const char *loader_name)
444 {
445         candidate_process_context_t *cpc;
446         GList *iter = candidate_slot_list;
447
448         while (iter) {
449                 cpc = (candidate_process_context_t *)iter->data;
450                 if (strcmp(cpc->loader_name, loader_name) == 0)
451                         return cpc;
452
453                 iter = g_list_next(iter);
454         }
455
456         return NULL;
457 }
458
459 static candidate_process_context_t *__find_slot(int type, int loader_id)
460 {
461         if (type == LAUNCHPAD_LOADER_TYPE_DYNAMIC)
462                 return __find_slot_from_loader_id(loader_id);
463
464         return __find_slot_from_static_type(type);
465 }
466
467 static void __update_slot_score(candidate_process_context_t *slot)
468 {
469         if (!slot)
470                 return;
471
472         slot->score *= LOSE_SCORE_RATE;
473         slot->score += WIN_SCORE;
474 }
475
476 static void __update_slots_pss(void)
477 {
478         candidate_process_context_t *cpc;
479         GList *iter;
480
481         iter = candidate_slot_list;
482         while (iter) {
483                 cpc = (candidate_process_context_t *)iter->data;
484                 iter = g_list_next(iter);
485
486                 if (cpc->pid == CANDIDATE_NONE)
487                         continue;
488
489                 _proc_get_mem_pss(cpc->pid, &cpc->pss);
490         }
491 }
492
493 static gint __compare_slot(gconstpointer a, gconstpointer b)
494 {
495         candidate_process_context_t *slot_a = (candidate_process_context_t *)a;
496         candidate_process_context_t *slot_b = (candidate_process_context_t *)b;
497
498         if (slot_a->is_hydra && !slot_b->is_hydra)
499                 return -1;
500         if (!slot_a->is_hydra && slot_b->is_hydra)
501                 return 1;
502
503         if (slot_a->score < slot_b->score)
504                 return 1;
505         if (slot_a->score > slot_b->score)
506                 return -1;
507
508         if (slot_a->pss < slot_b->pss)
509                 return -1;
510         if (slot_a->pss > slot_b->pss)
511                 return 1;
512
513         return 0;
514 }
515
516 static candidate_process_context_t *__get_running_slot(bool is_hydra)
517 {
518         candidate_process_context_t *cpc;
519         GList *iter;
520
521         iter = candidate_slot_list;
522         while (iter) {
523                 cpc = (candidate_process_context_t *)iter->data;
524                 if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE)
525                         return cpc;
526
527                 iter = g_list_next(iter);
528         }
529
530         return NULL;
531 }
532
533 static void __pause_last_running_slot(bool is_hydra)
534 {
535         candidate_process_context_t *cpc = NULL;
536         GList *iter;
537
538         iter = g_list_last(candidate_slot_list);
539         while (iter) {
540                 cpc = (candidate_process_context_t *)iter->data;
541                 if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE)
542                         break;
543
544                 iter = g_list_previous(iter);
545         }
546
547         if (!cpc)
548                 return;
549
550         __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, true);
551 }
552
553 static void __resume_all_slots(void)
554 {
555         candidate_process_context_t *cpc;
556         GList *iter;
557
558         iter = candidate_slot_list;
559         while (iter) {
560                 cpc = (candidate_process_context_t *)iter->data;
561                 __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, false);
562
563                 iter = g_list_next(iter);
564         }
565 }
566
567 static void __kill_process(int pid)
568 {
569         char err_str[MAX_LOCAL_BUFSZ] = { 0, };
570
571         if (kill(pid, SIGKILL) == -1) {
572                 _E("send SIGKILL: %s",
573                                 strerror_r(errno, err_str, sizeof(err_str)));
574         }
575 }
576
577 static void __refuse_candidate_process(int server_fd)
578 {
579         int client_fd = -1;
580
581         if (server_fd == -1) {
582                 _E("arguments error!");
583                 goto error;
584         }
585
586         client_fd = accept(server_fd, NULL, NULL);
587         if (client_fd == -1) {
588                 _E("accept error!");
589                 goto error;
590         }
591
592         close(client_fd);
593         _D("refuse connection!");
594
595 error:
596         return;
597 }
598
599 static int __accept_candidate_process(int server_fd, int *out_client_fd,
600                 int *out_client_pid, int cpc_pid)
601 {
602         int client_fd = -1;
603         int recv_pid = 0;
604         int ret;
605         socklen_t len;
606         struct ucred cred = {};
607
608         if (server_fd == -1 || out_client_fd == NULL ||
609                         out_client_pid == NULL) {
610                 _E("arguments error!");
611                 goto error;
612         }
613
614         client_fd = accept(server_fd, NULL, NULL);
615         if (client_fd == -1) {
616                 _E("accept error!");
617                 goto error;
618         }
619
620         if (_set_sock_option(client_fd, 1) < 0) {
621                 _E("Failed to set sock option");
622                 goto error;
623         }
624
625         ret = recv(client_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL);
626         if (ret == -1) {
627                 _E("recv error!");
628                 goto error;
629         }
630
631         len = sizeof(cred);
632         ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &len);
633         if (ret < 0) {
634                 _E("getsockopt error");
635                 goto error;
636         }
637
638         if (cpc_pid != -1 && cred.pid != cpc_pid) {
639                 _E("Invalid accept. pid(%d)", cred.pid);
640                 goto error;
641         }
642
643         if (cred.pid != recv_pid)
644                 _W("Not equal recv and real pid");
645
646         *out_client_fd = client_fd;
647         *out_client_pid = cred.pid;
648
649         return *out_client_fd;
650
651 error:
652         if (client_fd != -1)
653                 close(client_fd);
654
655         return -1;
656 }
657
658 static int __listen_addr(struct sockaddr_un *addr)
659 {
660         int fd = -1;
661         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
662         if (fd < 0) {
663                 _E("Socket error");
664                 goto error;
665         }
666
667         unlink(addr->sun_path);
668
669         _D("bind to %s", addr->sun_path);
670         if (bind(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_un)) < 0) {
671                 _E("bind error");
672                 goto error;
673         }
674
675         _D("listen to %s", addr->sun_path);
676         if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) {
677                 _E("listen error");
678                 goto error;
679         }
680
681         SECURE_LOGD("[launchpad] done, listen fd: %d", fd);
682         return fd;
683
684 error:
685         if (fd != -1)
686                 close(fd);
687
688         return -1;
689 }
690
691 static int __listen_candidate_process(int type, int loader_id)
692 {
693         struct sockaddr_un addr;
694
695         _D("[launchpad] enter, type: %d", type);
696
697         memset(&addr, 0x00, sizeof(struct sockaddr_un));
698         addr.sun_family = AF_UNIX;
699         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%u/%s%d-%d",
700                         SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME,
701                         type, loader_id);
702
703         return __listen_addr(&addr);
704 }
705
706 static int __listen_hydra_process(int type, int loader_id)
707 {
708         struct sockaddr_un addr;
709
710         _D("[launchpad] enter, type: %d", type);
711
712         memset(&addr, 0x00, sizeof(struct sockaddr_un));
713         addr.sun_family = AF_UNIX;
714         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%d/%s%d-%d",
715                         SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME,
716                         type, loader_id);
717
718         return __listen_addr(&addr);
719 }
720
721 static int __get_loader_id(bundle *kb)
722 {
723         const char *val;
724
725         val = bundle_get_val(kb, AUL_K_LOADER_ID);
726         if (val == NULL)
727                 return -1;
728         _W("Requested loader id: %s", val);
729
730         return atoi(val);
731 }
732
733 static int __candidate_process_real_launch(int candidate_fd, app_pkt_t *pkt)
734 {
735         return _send_pkt_raw(candidate_fd, pkt);
736 }
737
738 static int __real_send(int clifd, int ret)
739 {
740         if (clifd < 3) {
741                 _E("Invalid parameter. clifd(%d)", clifd);
742                 return -1;
743         }
744
745         if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
746                 if (errno == EPIPE) {
747                         _E("send failed due to EPIPE.");
748                         close(clifd);
749                         return -1;
750                 }
751                 _E("send fail to client");
752         }
753
754         close(clifd);
755         return 0;
756 }
757
758 static void __send_result_to_caller(int clifd, int ret, const char *app_path)
759 {
760         _W("send result: %d", ret);
761
762         if (clifd == -1)
763                 return;
764
765         if (ret <= 1) {
766                 _E("launching failed");
767                 __real_send(clifd, ret);
768                 return;
769         }
770
771         if (__real_send(clifd, ret) < 0)
772                 __kill_process(ret);
773 }
774
775 static int __fork_app_process(int (*child_fn)(void *), void *arg)
776 {
777         int pid;
778         int ret;
779
780         pid = fork();
781
782         if (pid == -1) {
783                 _E("failed to fork child process");
784                 return -1;
785         }
786
787         if (pid == 0) {
788                 _W("security_manager_prepare_app_candidate ++");
789                 ret = security_manager_prepare_app_candidate();
790                 _W("security_manager_prepare_app_candidate --");
791                 if (ret != SECURITY_MANAGER_SUCCESS) {
792                         _E("failed to prepare app candidate process (%d)", ret);
793                         exit(1);
794                 }
795
796                 ret = child_fn(arg);
797                 _E("failed to exec app process (%d)", errno);
798                 exit(ret);
799         }
800
801         return pid;
802 }
803
804 static int __exec_loader_process(void *arg)
805 {
806         char **argv = arg;
807         char err_buf[1024];
808
809         _signal_unblock_sigchld();
810         _close_all_fds();
811         _setup_stdio(basename(argv[LOADER_ARG_PATH]));
812
813         if (execv(argv[LOADER_ARG_PATH], argv) < 0) {
814                 _send_message_to_logger(argv[LOADER_ARG_PATH],
815                         "Failed to prepare candidate process. error(%d:%s)",
816                         errno, strerror_r(errno, err_buf, sizeof(err_buf)));
817         } else {
818                 _D("Succeeded to prepare candidate_process");
819         }
820
821         return -1;
822 }
823
824 static gboolean __handle_deactivate_event(gpointer user_data)
825 {
826         candidate_process_context_t *cpc;
827
828         cpc = (candidate_process_context_t *)user_data;
829         __update_slot_state(cpc, METHOD_TTL, false);
830         _D("Deactivate event: type(%d)", cpc->type);
831
832         return G_SOURCE_REMOVE;
833 }
834
835 static void __set_live_timer(candidate_process_context_t *cpc)
836 {
837         if (!cpc)
838                 return;
839
840         if (cpc->deactivation_method & METHOD_TTL) {
841                 if (cpc->live_timer == 0) {
842                         cpc->live_timer = g_timeout_add_seconds(cpc->ttl,
843                                         __handle_deactivate_event, cpc);
844                 }
845         }
846 }
847
848 static int __hydra_send_request(int fd, enum hydra_cmd cmd)
849 {
850         int sent = 0;
851         int size = sizeof(cmd);
852         int send_ret = 0;
853
854         while (sent != size) {
855                 send_ret = send(fd, (char *)&cmd + sent,
856                                 size - sent, MSG_NOSIGNAL);
857                 if (send_ret == -1) {
858                         _E("send error! (%d)", errno);
859                         return -1;
860                 }
861
862                 sent += send_ret;
863                 _D("send(%d: ret: %d) : %d / %d",
864                         fd, send_ret, sent, size);
865         }
866
867         return 0;
868 }
869
870 static int __hydra_send_launch_candidate_request(int fd)
871 {
872         SECURE_LOGD("Send launch cmd to hydra, fd: %d", fd);
873         return __hydra_send_request(fd, LAUNCH_CANDIDATE);
874 }
875
876 static int __prepare_candidate_process(int type, int loader_id)
877 {
878         int pid;
879         char type_str[12] = {0, };
880         char loader_id_str[12] = {0, };
881         char argbuf[LOADER_ARG_LEN];
882         char *argv[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
883         candidate_process_context_t *cpt = __find_slot(type, loader_id);
884
885         if (cpt == NULL)
886                 return -1;
887
888         if (cpt->is_hydra && cpt->hydra_pid != HYDRA_NONE)
889                 return __hydra_send_launch_candidate_request(cpt->hydra_fd);
890
891         _D("prepare candidate process / type:%d", type);
892         memset(argbuf, ' ', LOADER_ARG_LEN);
893         argbuf[LOADER_ARG_LEN - 1] = '\0';
894         argv[LOADER_ARG_DUMMY] = argbuf;
895
896         cpt->last_exec_time = time(NULL);
897
898         snprintf(loader_id_str, sizeof(loader_id_str), "%d", loader_id);
899         snprintf(type_str, sizeof(type_str), "%d", type);
900         argv[LOADER_ARG_PATH] = cpt->loader_path;
901         argv[LOADER_ARG_TYPE] = type_str;
902         argv[LOADER_ARG_ID] = loader_id_str;
903         argv[LOADER_ARG_HYDRA] = cpt->is_hydra ? "1" : "0";
904         argv[LOADER_ARG_EXTRA] = cpt->loader_extra;
905
906         pid = __fork_app_process(__exec_loader_process, argv);
907         if (pid == -1) {
908                 _E("Failed to fork candidate_process");
909                 return -1;
910         }
911
912         if (cpt->is_hydra) {
913                 cpt->hydra_pid = pid;
914         } else {
915                 cpt->pid = pid;
916                 __set_live_timer(cpt);
917         }
918
919         _log_print("[CANDIDATE]", "pid(%7d) | type(%d) | loader(%s)",
920                 pid, cpt->loader_id, cpt->loader_name);
921         _memory_monitor_reset_timer();
922
923         return 0;
924 }
925
926 static gboolean __handle_timeout_event(gpointer user_data)
927 {
928         candidate_process_context_t *cpc;
929
930         cpc = (candidate_process_context_t *)user_data;
931         cpc->timer = 0;
932
933         if (cpc->pid != CANDIDATE_NONE) {
934                 _W("Candidate(%d) process(%d) is running", cpc->type, cpc->pid);
935                 return G_SOURCE_REMOVE;
936         }
937
938         __sequencer_add_slot(cpc);
939         __sequencer_run();
940         return G_SOURCE_REMOVE;
941 }
942
943 static void __set_timer(candidate_process_context_t *cpc)
944 {
945         if (cpc == NULL || cpc->timer > 0)
946                 return;
947
948         if ((cpc->detection_method & METHOD_TIMEOUT) &&
949                         cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) {
950                 cpc->timer = g_timeout_add(cpc->timeout_val,
951                                 __handle_timeout_event, cpc);
952         }
953 }
954
955 static void __reset_slot(candidate_process_context_t *cpc)
956 {
957         if (cpc == NULL)
958                 return;
959
960         cpc->send_fd = -1;
961         cpc->prepared = false;
962         cpc->pid = CANDIDATE_NONE;
963         cpc->client_channel = NULL;
964         cpc->timer = 0;
965         cpc->live_timer = 0;
966 }
967
968 static void __dispose_candidate_process(candidate_process_context_t *cpc)
969 {
970         if (!cpc)
971                 return;
972
973         _D("Dispose candidate process %d", cpc->type);
974         if (cpc->pid > 0) {
975                 _D("kill process %d", cpc->pid);
976                 __kill_process(cpc->pid);
977         }
978         if (cpc->live_timer > 0)
979                 g_source_remove(cpc->live_timer);
980         if (cpc->client_channel)
981                 _io_channel_destroy(cpc->client_channel);
982         if (cpc->timer > 0)
983                 g_source_remove(cpc->timer);
984         if (cpc->send_fd > 0)
985                 close(cpc->send_fd);
986         __reset_slot(cpc);
987 }
988
989 static void __dispose_hydra_process(candidate_process_context_t *cpc)
990 {
991         if (!cpc)
992                 return;
993
994         __dispose_candidate_process(cpc);
995
996         _D("Dispose hydra process %d", cpc->type);
997         if (cpc->hydra_pid > 0) {
998                 _D("kill process %d", cpc->hydra_pid);
999                 __kill_process(cpc->hydra_pid);
1000                 cpc->hydra_pid = HYDRA_NONE;
1001         }
1002
1003         if (cpc->hydra_fd > 0) {
1004                 close(cpc->hydra_fd);
1005                 cpc->hydra_fd = -1;
1006         }
1007 }
1008
1009 static int __send_launchpad_loader(candidate_process_context_t *cpc,
1010                 app_pkt_t *pkt, const char *app_path, int clifd)
1011 {
1012         int pid = -1;
1013         int ret;
1014
1015         ret = _delete_sock_path(cpc->pid, getuid());
1016         if (ret != 0)
1017                 return -1;
1018
1019         __candidate_process_real_launch(cpc->send_fd, pkt);
1020         SECURE_LOGD("Request to candidate process, pid: %d, bin path: %s",
1021                 cpc->pid, app_path);
1022
1023         pid = cpc->pid;
1024         cpc->pid = CANDIDATE_NONE;
1025         __dispose_candidate_process(cpc);
1026         __set_timer(cpc);
1027         __update_slot_score(cpc);
1028
1029         return pid;
1030 }
1031
1032 static int __normal_fork_exec(int argc, char **argv, const char *app_path)
1033 {
1034         char *libdir;
1035         char err_buf[1024];
1036
1037         _D("start real fork and exec");
1038
1039         libdir = _get_libdir(app_path);
1040         if (libdir) {
1041                 setenv("LD_LIBRARY_PATH", libdir, 1);
1042                 free(libdir);
1043         }
1044
1045         _close_all_fds();
1046
1047         if (execv(argv[LOADER_ARG_PATH], argv) < 0) { /* Flawfinder: ignore */
1048                 _send_message_to_logger(argv[LOADER_ARG_PATH],
1049                         "Failed to execute a file. error(%d:%s)",
1050                         errno, strerror_r(errno, err_buf, sizeof(err_buf)));
1051                 return -1;
1052         }
1053         /* never reach*/
1054         return 0;
1055 }
1056
1057 static int __create_launcher_argv(int *argc, char ***argv, const char *app_type)
1058 {
1059         int launcher_argc;
1060         char **launcher_argv;
1061         launcher_info_h launcher_info;
1062         const char *exe;
1063         const char *extra_arg;
1064         GList *extra_args;
1065         GList *iter;
1066         int i;
1067
1068         launcher_info = _launcher_info_find(launcher_info_list, app_type);
1069         if (launcher_info == NULL)
1070                 return 0;
1071
1072         exe = _launcher_info_get_exe(launcher_info);
1073         if (exe == NULL) {
1074                 _E("Failed to get launcher exe");
1075                 return -1;
1076         }
1077
1078         extra_args = _launcher_info_get_extra_args(launcher_info);
1079         launcher_argc = g_list_length(extra_args) + 1;
1080         launcher_argv = (char **)calloc(launcher_argc, sizeof(char *));
1081         if (launcher_argv == NULL) {
1082                 _E("out of memory");
1083                 return -1;
1084         }
1085
1086         i = LOADER_ARG_PATH;
1087         launcher_argv[i++] = strdup(exe);
1088
1089         iter = g_list_first(extra_args);
1090         while (iter) {
1091                 extra_arg = (const char *)iter->data;
1092                 if (extra_arg)
1093                         launcher_argv[i++] = strdup(extra_arg);
1094
1095                 iter = g_list_next(iter);
1096         }
1097
1098         *argc = launcher_argc;
1099         *argv = launcher_argv;
1100
1101
1102         return 0;
1103 }
1104
1105 static void __destroy_launcher_argv(int argc, char **argv)
1106 {
1107         int i;
1108
1109         if (argv == NULL)
1110                 return;
1111
1112         for (i = 0; i < argc; i++)
1113                 free(argv[i]);
1114         free(argv);
1115 }
1116
1117 static int __create_app_argv(int *argc, char ***argv, const char *app_path,
1118                 bundle *kb, const char *app_type)
1119 {
1120         int new_argc;
1121         char **new_argv;
1122         bool attach = false;
1123         struct app_arg debug_arg = {0,};
1124         struct app_arg launcher_arg = {0,};
1125         struct app_arg arg = {0,};
1126         struct app_arg debug_extra_arg = {0,};
1127         int ret;
1128         int i;
1129         int c;
1130
1131         ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach);
1132         if (ret < 0) {
1133                 _E("Failed to create debugger argv");
1134                 return -1;
1135         }
1136
1137         if (attach) {
1138                 *argc = debug_arg.argc;
1139                 *argv = debug_arg.argv;
1140                 return 0;
1141         }
1142
1143         ret = _debug_create_extra_argv(&debug_extra_arg.argc,
1144                         &debug_extra_arg.argv);
1145         if (ret < 0) {
1146                 _E("Failed to create debugger extra argv");
1147                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1148                 return -1;
1149         }
1150
1151         ret = __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv,
1152                         app_type);
1153         if (ret < 0) {
1154                 _E("Failed to create launcher argv");
1155                 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1156                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1157                 return -1;
1158         }
1159
1160         arg.argc = bundle_export_to_argv(kb, &arg.argv);
1161         if (arg.argc <= 0) {
1162                 _E("Failed to export bundle");
1163                 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
1164                 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1165                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1166                 return -1;
1167         }
1168         arg.argv[LOADER_ARG_PATH] = strdup(app_path);
1169
1170         new_argc = debug_arg.argc + launcher_arg.argc + arg.argc +
1171                 debug_extra_arg.argc;
1172         if (new_argc == arg.argc) {
1173                 *argc = arg.argc;
1174                 *argv = arg.argv;
1175                 return 0;
1176         }
1177
1178         new_argv = (char **)calloc(new_argc + 1, sizeof(char *));
1179         if (new_argv == NULL) {
1180                 _E("out of memory");
1181                 free(arg.argv[LOADER_ARG_PATH]);
1182                 bundle_free_exported_argv(arg.argc, &arg.argv);
1183                 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
1184                 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
1185                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
1186                 return -1;
1187         }
1188
1189         c = LOADER_ARG_PATH;
1190         for (i = 0; i < debug_arg.argc; i++)
1191                 new_argv[c++] = debug_arg.argv[i];
1192         for (i = 0; i < launcher_arg.argc; i++)
1193                 new_argv[c++] = launcher_arg.argv[i];
1194         for (i = 0; i < arg.argc; i++)
1195                 new_argv[c++] = arg.argv[i];
1196         for (i = 0; i < debug_extra_arg.argc; i++)
1197                 new_argv[c++] = debug_extra_arg.argv[i];
1198
1199         *argc = new_argc;
1200         *argv = new_argv;
1201
1202         return 0;
1203 }
1204
1205 static void __real_launch(const char *app_path, bundle *kb,
1206                 appinfo_t *menu_info)
1207 {
1208         int app_argc = 0;
1209         char **app_argv;
1210         int i;
1211         int ret;
1212
1213         if (bundle_get_val(kb, AUL_K_DEBUG) != NULL)
1214                 putenv("TIZEN_DEBUGGING_PORT=1");
1215
1216         ret = __create_app_argv(&app_argc, &app_argv, app_path,
1217                         kb, menu_info->app_type);
1218         if (ret < 0) {
1219                 _E("Failed to create app argv");
1220                 exit(-1);
1221         }
1222
1223         for (i = 0; i < app_argc; i++)
1224                 SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
1225
1226         PERF("setup argument done");
1227         __normal_fork_exec(app_argc, app_argv, app_path);
1228 }
1229
1230 static int __prepare_exec(const char *appid, const char *app_path,
1231                         appinfo_t *menu_info, bundle *kb)
1232 {
1233         char *file_name;
1234         char process_name[AUL_PR_NAME];
1235         int ret;
1236
1237         /* Set new session ID & new process group ID*/
1238         /* In linux, child can set new session ID without check permission */
1239         /* TODO : should be add to check permission in the kernel*/
1240         setsid();
1241
1242         ret = _launchpad_plugin_prepare_app(appid, kb);
1243         if (ret < 0) {
1244                 _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret);
1245                 return PAD_ERR_FAILED;
1246         }
1247
1248         ret = _enable_external_pkg(kb, menu_info->pkgid,
1249                         menu_info->global ? GLOBAL_USER : getuid());
1250         if (ret < 0)
1251                 return PAD_ERR_FAILED;
1252
1253         if (menu_info->global)
1254                 ret = trust_anchor_launch(menu_info->pkgid, GLOBAL_USER);
1255         else
1256                 ret = trust_anchor_launch(menu_info->pkgid, getuid());
1257         if (ret != TRUST_ANCHOR_ERROR_NONE &&
1258                         ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) {
1259                 _E("trust_anchor_launch() returns %d", ret);
1260                 return PAD_ERR_REJECTED;
1261         }
1262
1263         /* SET PRIVILEGES*/
1264         _W("security_manager_prepare_app ++");
1265         ret = security_manager_prepare_app(appid);
1266         _W("security_manager_prepare_app --");
1267         if (ret != SECURITY_MANAGER_SUCCESS)
1268                 return PAD_ERR_REJECTED;
1269
1270         _send_cmd_to_amd(APP_STARTUP_SIGNAL);
1271         if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE)
1272                 _setup_stdio(basename(app_path));
1273
1274         /* SET DUMPABLE - for coredump*/
1275         prctl(PR_SET_DUMPABLE, 1);
1276
1277         /* SET PROCESS NAME*/
1278         if (app_path == NULL)
1279                 return PAD_ERR_INVALID_ARGUMENT;
1280
1281         file_name = strrchr(app_path, '/');
1282         if (file_name == NULL)
1283                 return PAD_ERR_INVALID_PATH;
1284
1285         file_name++;
1286         if (*file_name == '\0')
1287                 return PAD_ERR_INVALID_PATH;
1288
1289         memset(process_name, '\0', AUL_PR_NAME);
1290         snprintf(process_name, AUL_PR_NAME, "%s", file_name);
1291         prctl(PR_SET_NAME, process_name);
1292
1293         /* SET ENVIROMENT*/
1294         _set_env(menu_info, kb);
1295
1296         ret = _wait_tep_mount(kb);
1297         if (ret < 0)
1298                 return PAD_ERR_FAILED;
1299
1300         if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) {
1301                 ret = _prepare_app_socket();
1302                 if (ret < 0)
1303                         return PAD_ERR_FAILED;
1304
1305                 ret = _prepare_id_file();
1306                 if (ret < 0)
1307                         return PAD_ERR_FAILED;
1308         }
1309
1310         return 0;
1311 }
1312
1313 static int __exec_app_process(void *arg)
1314 {
1315         struct app_launch_arg *launch_arg = arg;
1316         int ret;
1317
1318         _print_hwc_log("%d|after calling fork(). %s",
1319                         getpid(), launch_arg->appid);
1320         PERF("fork done");
1321         _D("lock up test log(no error) : fork done");
1322
1323         if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1324                 _debug_prepare_debugger(launch_arg->kb);
1325
1326         _signal_unblock_sigchld();
1327
1328         _delete_sock_path(getpid(), getuid());
1329
1330         PERF("prepare exec - first done");
1331         ret = __prepare_exec(launch_arg->appid, launch_arg->app_path,
1332                         launch_arg->menu_info, launch_arg->kb);
1333         if (ret < 0)
1334                 return ret;
1335
1336         PERF("prepare exec - second done");
1337         __real_launch(launch_arg->app_path, launch_arg->kb,
1338                         launch_arg->menu_info);
1339
1340         return PAD_ERR_FAILED;
1341 }
1342
1343 static int __launch_directly(const char *appid, const char *app_path, int clifd,
1344                 bundle *kb, appinfo_t *menu_info,
1345                 candidate_process_context_t *cpc)
1346 {
1347         struct app_launch_arg arg;
1348         int pid;
1349
1350         arg.appid = appid;
1351         arg.app_path = app_path;
1352         arg.menu_info = menu_info;
1353         arg.kb = kb;
1354
1355         _print_hwc_log("before calling fork(). %s", appid);
1356         pid = __fork_app_process(__exec_app_process, &arg);
1357         if (pid <= 0)
1358                 _E("failed to fork app process");
1359
1360         SECURE_LOGD("==> real launch pid : %d %s", pid, app_path);
1361
1362         return pid;
1363 }
1364
1365 static int __create_sock_activation(void)
1366 {
1367         int fds;
1368         char launchpad_process_pool_sock_path[108];
1369         int i;
1370
1371         fds = sd_listen_fds(0);
1372         snprintf(launchpad_process_pool_sock_path,
1373                 sizeof(launchpad_process_pool_sock_path), "%s/daemons/%u/%s",
1374                         SOCKET_PATH, getuid(), PROCESS_POOL_LAUNCHPAD_SOCK);
1375
1376         for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + fds; ++i) {
1377                 if (sd_is_socket_unix(i, SOCK_STREAM, 1,
1378                                 launchpad_process_pool_sock_path, 0) > 0)
1379                         return i;
1380         }
1381
1382         _W("There is no socket stream");
1383         return -1;
1384 }
1385
1386 static int __launchpad_pre_init(int argc, char **argv)
1387 {
1388         int fd;
1389
1390         /* create launchpad sock */
1391         fd = __create_sock_activation();
1392         if (fd < 0) {
1393                 fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK);
1394                 if (fd < 0) {
1395                         _E("server sock error %d", fd);
1396                         return -1;
1397                 }
1398         }
1399
1400         return fd;
1401 }
1402
1403 static bool __handle_loader_client_event(int fd, io_condition_e cond,
1404                 void *data)
1405 {
1406         candidate_process_context_t *cpc = data;
1407
1408         if (cpc == NULL)
1409                 return false;
1410
1411         if (cond & (IO_HUP | IO_NVAL)) {
1412                 SECURE_LOGE("Type %d candidate process was "
1413                                 "(POLLHUP|POLLNVAL), pid: %d",
1414                                 cpc->type, cpc->pid);
1415                 cpc->pid = CANDIDATE_NONE;
1416                 __dispose_candidate_process(cpc);
1417                 __prepare_candidate_process(cpc->type, cpc->loader_id);
1418                 return false;
1419         }
1420
1421         return true;
1422
1423 }
1424
1425 static bool __handle_hydra_client_event(int fd, io_condition_e cond,
1426                 void *data)
1427 {
1428         candidate_process_context_t *cpc = data;
1429
1430         if (cpc == NULL)
1431                 return false;
1432
1433         if (cond & (IO_HUP | IO_NVAL)) {
1434                 SECURE_LOGE("Type %d hydra process was "
1435                                 "(POLLHUP|POLLNVAL), pid: %d",
1436                                 cpc->type, cpc->hydra_pid);
1437                 __dispose_hydra_process(cpc);
1438                 __prepare_candidate_process(cpc->type, cpc->loader_id);
1439                 return false;
1440         }
1441
1442         return true;
1443 }
1444
1445 static bool __handle_loader_event(int fd, io_condition_e cond, void *data)
1446 {
1447         candidate_process_context_t *cpc = data;
1448         int client_fd;
1449         int client_pid;
1450         int ret;
1451
1452         if (cpc == NULL)
1453                 return false;
1454
1455         if (!cpc->prepared) {
1456                 ret = __accept_candidate_process(fd, &client_fd, &client_pid,
1457                                         cpc->is_hydra ? -1 : cpc->pid);
1458                 if (ret >= 0) {
1459                         /* for hydra need to set pid to pid of non-hydra candidate, */
1460                         /* which is connecting now */
1461                         if (cpc->is_hydra)
1462                                 cpc->pid = client_pid;
1463
1464                         cpc->prepared = true;
1465                         cpc->send_fd = client_fd;
1466
1467                         SECURE_LOGD("Type %d candidate process was connected, "
1468                                         "pid: %d", cpc->type, cpc->pid);
1469                         cpc->client_channel = _io_channel_create(client_fd,
1470                                         IO_IN | IO_HUP,
1471                                         __handle_loader_client_event,
1472                                         cpc);
1473                         if (!cpc->client_channel)
1474                                 close(client_fd);
1475                 }
1476         } else {
1477                 __refuse_candidate_process(fd);
1478                 _E("Refused candidate process connection");
1479         }
1480
1481         return true;
1482 }
1483
1484 static bool __handle_hydra_event(int fd, io_condition_e cond, void *data)
1485 {
1486         candidate_process_context_t *cpc = data;
1487         int client_fd;
1488         int client_pid;
1489         int ret;
1490
1491         if (cpc == NULL)
1492                 return false;
1493
1494         if (!cpc->prepared) {
1495                 ret = __accept_candidate_process(fd, &client_fd, &client_pid,
1496                                         cpc->hydra_pid);
1497                 if (ret >= 0) {
1498                         cpc->hydra_fd = client_fd;
1499
1500                         SECURE_LOGD("Type %d hydra process was connected,"
1501                                         " pid: %d", cpc->type, cpc->hydra_pid);
1502
1503                         cpc->client_channel = _io_channel_create(client_fd,
1504                                         IO_IN | IO_HUP,
1505                                         __handle_hydra_client_event,
1506                                         cpc);
1507                         if (!cpc->client_channel)
1508                                 close(client_fd);
1509                 }
1510         } else {
1511                 __refuse_candidate_process(fd);
1512                 _E("Refused hydra process connection");
1513         }
1514
1515         return true;
1516 }
1517
1518 static void __destroy_cleanup_info(struct cleanup_info_s *info)
1519 {
1520         if (!info)
1521                 return;
1522
1523         free(info->appid);
1524         free(info);
1525 }
1526
1527 static struct cleanup_info_s *__create_cleanup_info(const char *appid, int pid)
1528 {
1529         struct cleanup_info_s *info;
1530
1531         info = malloc(sizeof(struct cleanup_info_s));
1532         if (!info) {
1533                 _E("Out of memory");
1534                 return NULL;
1535         }
1536
1537         info->appid = strdup(appid);
1538         if (!info->appid) {
1539                 _E("strdup(%s) is failed", appid);
1540                 __destroy_cleanup_info(info);
1541                 return NULL;
1542         }
1543
1544         info->pid = pid;
1545
1546         return info;
1547 }
1548
1549 static bool __cleanup_app_cb(void *user_data)
1550 {
1551         struct cleanup_info_s *info = (struct cleanup_info_s *)user_data;
1552
1553         _W("security_manager_cleanup_app() ++");
1554         security_manager_cleanup_app(info->appid, getuid(), info->pid);
1555         _W("security_manager_cleanup_app() --");
1556         __destroy_cleanup_info(info);
1557         return false;
1558 }
1559
1560 static void __handle_sigchild(int pid, void *user_data)
1561 {
1562         candidate_process_context_t *cpc;
1563         struct cleanup_info_s *info;
1564         char *appid;
1565         int ret = -1;
1566
1567         appid = g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid));
1568         if (appid) {
1569                 info = __create_cleanup_info(appid, pid);
1570                 if (info)
1571                         ret = _worker_add_job(__cleanup_app_cb, info);
1572
1573                 if (ret != 0) {
1574                         __destroy_cleanup_info(info);
1575                         _W("security_manager_cleanup_app() ++");
1576                         security_manager_cleanup_app(appid, getuid(), pid);
1577                         _W("security_manager_cleanup_app() --");
1578                 }
1579
1580                 g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid));
1581         }
1582
1583         _log_print("[SIGCHLD]", "pid(%7d)", pid);
1584         cpc = __find_slot_from_pid(pid);
1585         if (cpc != NULL) {
1586                 cpc->pid = CANDIDATE_NONE;
1587                 __dispose_candidate_process(cpc);
1588                 __prepare_candidate_process(cpc->type, cpc->loader_id);
1589         } else {
1590                 cpc = __find_hydra_slot_from_pid(pid);
1591                 if (cpc != NULL) {
1592                         cpc->hydra_pid = HYDRA_NONE;
1593                         __dispose_hydra_process(cpc);
1594                         __prepare_candidate_process(cpc->type, cpc->loader_id);
1595                 }
1596         }
1597
1598         cpc = __find_slot_from_caller_pid(pid);
1599         while (cpc) {
1600                 __remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, cpc->loader_id);
1601                 cpc = __find_slot_from_caller_pid(pid);
1602         }
1603 }
1604
1605 static bool __handle_label_monitor(int fd, io_condition_e cond, void *data)
1606 {
1607         candidate_process_context_t *cpc;
1608         GList *iter = candidate_slot_list;
1609
1610         if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
1611                 _E("fd(%d), io_condition(%d)", fd, cond);
1612                 abort();
1613                 return false;
1614         }
1615
1616         _D("fd(%d) condition(%d)", fd, cond);
1617         _log_print("[LABEL]", "fd(%d), condition(%d)", fd, cond);
1618         security_manager_app_labels_monitor_process(label_monitor);
1619
1620         while (iter) {
1621                 cpc = (candidate_process_context_t *)iter->data;
1622                 if (cpc->is_hydra) {
1623                         if (cpc->hydra_pid > 0) {
1624                                 __dispose_hydra_process(cpc);
1625                                 __prepare_candidate_process(cpc->type,
1626                                                 cpc->loader_id);
1627                         }
1628                 } else if (cpc->pid > 0) {
1629                         __dispose_candidate_process(cpc);
1630                         __prepare_candidate_process(cpc->type, cpc->loader_id);
1631                 }
1632
1633                 iter = g_list_next(iter);
1634         }
1635
1636         return true;
1637 }
1638
1639 static float __interpolator(float input, int cpu_max, int cpu_min)
1640 {
1641         float ret;
1642         float min = cpu_min / 100.0f;
1643         float max = cpu_max / 100.0f;
1644
1645         if (input > 1.0f)
1646                 input = 1.0f;
1647         if (input < 0.0f)
1648                 input = 0.0f;
1649
1650         ret = cos(input * PI) / 2.0f + 0.5f;
1651         ret *= max - min;
1652         ret += min;
1653
1654         return ret;
1655 }
1656
1657 static void __update_threshold(candidate_process_context_t *cpc, float delta)
1658 {
1659         static float pos = 0.0f;
1660
1661         pos += delta;
1662         if (pos < 0.0f)
1663                 pos = 0.0f;
1664
1665         if (pos > 1.0f)
1666                 pos = 1.0f;
1667
1668         cpc->threshold = (int)(__interpolator(pos,
1669                                 cpc->threshold_max, cpc->threshold_min) * 100);
1670         _D("[CPU] type:%d / delta:%f / input cursor : %f / threshold : %d",
1671                         cpc->type, delta, pos, cpc->threshold);
1672 }
1673
1674 static gboolean __handle_idle_checker(gpointer data)
1675 {
1676         unsigned long long total = 0;
1677         unsigned long long idle = 0;
1678         int per;
1679         candidate_process_context_t *cpc;
1680
1681         if (!data) {
1682                 _E("Critical error!");
1683                 __sequencer.idle_checker = 0;
1684                 __sequencer.running_cpc = NULL;
1685                 return G_SOURCE_REMOVE;
1686         }
1687
1688         cpc = (candidate_process_context_t *)data;
1689         if (cpc->app_check && !cpc->app_exists) {
1690                 _W("The application is not installed. loader(%s:%d)",
1691                                 cpc->loader_name, cpc->type);
1692                 __sequencer.idle_checker = 0;
1693                 __sequencer.running_cpc = NULL;
1694                 return G_SOURCE_REMOVE;
1695         }
1696
1697         if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1698                 _W("Slot state is not running. loader(%s:%d)",
1699                                 cpc->loader_name, cpc->type);
1700                 __sequencer.idle_checker = 0;
1701                 __sequencer.running_cpc = NULL;
1702                 return G_SOURCE_REMOVE;
1703         }
1704
1705         _get_cpu_idle(&total, &idle);
1706         if (total == cpc->cpu_total_time)
1707                 total++;
1708
1709         per = (idle - cpc->cpu_idle_time) * 100 / (total - cpc->cpu_total_time);
1710         _D("[CPU] Idle : %d / loader(%s:%d)", per, cpc->loader_name, cpc->type);
1711
1712         if (per >= cpc->threshold) {
1713                 __update_threshold(cpc, -0.02f * (per - cpc->threshold));
1714                 __prepare_candidate_process(cpc->type, cpc->loader_id);
1715                 cpc->touched = true;
1716                 __sequencer.idle_checker = 0;
1717                 __sequencer.running_cpc = NULL;
1718                 return G_SOURCE_REMOVE;
1719         }
1720
1721         cpc->cpu_idle_time = idle;
1722         cpc->cpu_total_time = total;
1723         __update_threshold(cpc, 0.05f);
1724
1725         cpc->cpu_check_count++;
1726         if (cpc->cpu_check_count == MAX_CPU_CHECK_COUNT) {
1727                 _W("CPU check count has exceeded %d times. loader(%s:%d)",
1728                                 cpc->cpu_check_count,
1729                                 cpc->loader_name,
1730                                 cpc->type);
1731                 __sequencer.idle_checker = 0;
1732                 __sequencer.running_cpc = NULL;
1733                 __sequencer_add_slot(cpc);
1734                 return G_SOURCE_REMOVE;
1735         }
1736
1737         return G_SOURCE_CONTINUE;
1738 }
1739
1740 static int __add_idle_checker(int detection_method, GList *cur)
1741 {
1742         candidate_process_context_t *cpc;
1743         GList *iter = cur;
1744
1745         while (iter) {
1746                 cpc = (candidate_process_context_t *)iter->data;
1747                 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1748                         iter = g_list_next(iter);
1749                         continue;
1750                 }
1751
1752                 if (strcmp("null", cpc->loader_path) == 0) {
1753                         iter = g_list_next(iter);
1754                         continue;
1755                 }
1756
1757                 if (!cpc->touched && !cpc->on_boot) {
1758                         iter = g_list_next(iter);
1759                         continue;
1760                 }
1761
1762                 if (cpc->app_check && !cpc->app_exists) {
1763                         iter = g_list_next(iter);
1764                         continue;
1765                 }
1766
1767                 if (cpc->pid == CANDIDATE_NONE &&
1768                                 (!cpc->touched ||
1769                                  (cpc->detection_method & detection_method))) {
1770                         if (cpc->timer > 0) {
1771                                 g_source_remove(cpc->timer);
1772                                 cpc->timer = 0;
1773                         }
1774
1775                         cpc->cur_event = detection_method;
1776                         __sequencer_add_slot(cpc);
1777                         __sequencer_run();
1778                 }
1779
1780                 iter = g_list_next(iter);
1781         }
1782
1783         return -1;
1784 }
1785
1786 static int __dispatch_cmd_hint(bundle *kb, int detection_method)
1787 {
1788         _W("cmd hint %d", detection_method);
1789         __add_idle_checker(detection_method, candidate_slot_list);
1790
1791         return 0;
1792 }
1793
1794 static int __dispatch_cmd_add_loader(bundle *kb)
1795 {
1796         const char *add_slot_str = NULL;
1797         const char *caller_pid = NULL;
1798         const char *extra;
1799         int lid, size;
1800         char *loader_name;
1801         candidate_process_context_t *cpc;
1802
1803         _W("cmd add loader");
1804         add_slot_str = bundle_get_val(kb, AUL_K_LOADER_PATH);
1805         caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID);
1806         extra = bundle_get_val(kb, AUL_K_LOADER_EXTRA);
1807
1808         if (add_slot_str && caller_pid) {
1809                 lid = __make_loader_id();
1810
1811                 size = snprintf(0, 0, "%s%s%d", add_slot_str, caller_pid, lid);
1812                 loader_name = (char *)malloc(size + 1);
1813                 if (loader_name == NULL) {
1814                         _E("Out of memory");
1815                         return -1;
1816                 }
1817
1818                 snprintf(loader_name, size, "%s%s%d", add_slot_str, caller_pid, lid);
1819
1820                 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid,
1821                                 atoi(caller_pid), loader_name,
1822                                 add_slot_str, extra,
1823                                 METHOD_TIMEOUT | METHOD_VISIBILITY,
1824                                 METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
1825                                 METHOD_TTL | METHOD_OUT_OF_MEMORY,
1826                                 600,
1827                                 2000,
1828                                 DEFAULT_CPU_THRESHOLD_MAX,
1829                                 DEFAULT_CPU_THRESHOLD_MIN,
1830                                 false,
1831                                 true,
1832                                 false,
1833                                 true);
1834                 __set_timer(cpc);
1835                 free(loader_name);
1836                 return lid;
1837         }
1838
1839         return -1;
1840 }
1841
1842 static int __dispatch_cmd_add_app_defined_loader(bundle *kb)
1843 {
1844         const char *loader_name;
1845         int lid, len;
1846         candidate_process_context_t *cpc;
1847         loader_info_t *info;
1848         bundle_raw *extra;
1849
1850         _W("cmd add defined loader");
1851         loader_name = bundle_get_val(kb, AUL_K_LOADER_NAME);
1852
1853         if (loader_name == NULL) {
1854                 _E("loader_name is NULL");
1855                 return -EINVAL;
1856         }
1857
1858         info = _loader_info_find_loader_by_loader_name(
1859                         app_defined_loader_info_list, loader_name);
1860         if (info == NULL || info->extra == NULL) {
1861                 _E("loader_name %s, info  %d", loader_name, info != NULL);
1862                 return -EINVAL;
1863         }
1864
1865
1866         cpc = __find_slot_from_loader_name(loader_name);
1867         if (cpc == NULL) {
1868                 lid = __make_loader_id();
1869                 bundle_encode(info->extra, &extra, &len);
1870                 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid, 0,
1871                                 loader_name, "/usr/bin/app-defined-loader", (const char *)extra,
1872                                 METHOD_TIMEOUT | METHOD_VISIBILITY,
1873                                 METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
1874                                 METHOD_TTL | METHOD_OUT_OF_MEMORY,
1875                                 info->ttl,
1876                                 2000,
1877                                 DEFAULT_CPU_THRESHOLD_MAX,
1878                                 DEFAULT_CPU_THRESHOLD_MIN,
1879                                 false,
1880                                 true,
1881                                 false,
1882                                 true);
1883
1884                 bundle_free_encoded_rawdata(&extra);
1885                 if (cpc == NULL) {
1886                         _E("cpc is NULL");
1887                         return -ENOMEM;
1888                 }
1889         } else {
1890                 lid = cpc->loader_id;
1891         }
1892
1893         if (cpc->pid == CANDIDATE_NONE)
1894                 __prepare_candidate_process(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid);
1895
1896         return lid;
1897 }
1898
1899 static int __dispatch_cmd_remove_loader(bundle *kb)
1900 {
1901         const char *id = bundle_get_val(kb, AUL_K_LOADER_ID);
1902         int lid;
1903
1904         _W("cmd remove loader");
1905         if (id) {
1906                 lid = atoi(id);
1907                 if (__remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid) == 0)
1908                         return 0;
1909         }
1910
1911         return -1;
1912 }
1913
1914 static int __check_caller_by_pid(int pid)
1915 {
1916         int ret;
1917         char buf[PATH_MAX] = { 0, };
1918
1919         ret = _proc_get_attr(pid, buf, sizeof(buf));
1920         if (ret < 0)
1921                 return -1;
1922
1923         if (strcmp(buf, "User") == 0 ||
1924                         strcmp(buf, "System") == 0 ||
1925                         strcmp(buf, "System::Privileged") == 0)
1926                 return 0;
1927
1928         return -1;
1929 }
1930
1931 static bool __is_hw_acc(const char *hwacc)
1932 {
1933         if (strcmp(hwacc, "USE") == 0 ||
1934                 (strcmp(hwacc, "SYS") == 0 &&
1935                         __sys_hwacc == SETTING_HW_ACCELERATION_ON))
1936                 return true;
1937
1938         return false;
1939 }
1940
1941 static candidate_process_context_t *__find_available_slot(const char *hwacc,
1942                 const char *app_type, const char *loader_name,
1943                 candidate_process_context_t **org_cpc)
1944 {
1945         int type;
1946         candidate_process_context_t *cpc;
1947         int *a_types;
1948         int len = 0;
1949         int i;
1950
1951         if (loader_name) {
1952                 type = _loader_info_find_type_by_loader_name(loader_info_list,
1953                                 loader_name);
1954         } else {
1955                 type = _loader_info_find_type(loader_info_list,
1956                                 app_type, __is_hw_acc(hwacc));
1957         }
1958         cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1959         if (!cpc)
1960                 return NULL;
1961
1962         *org_cpc = cpc;
1963
1964         if (cpc->prepared)
1965                 return cpc;
1966
1967         a_types = _loader_get_alternative_types(loader_info_list, type, &len);
1968         if (!a_types)
1969                 return NULL;
1970
1971         for (i = 0; i < len; i++) {
1972                 cpc = __find_slot(a_types[i], PAD_LOADER_ID_STATIC);
1973                 if (!cpc)
1974                         continue;
1975                 if (cpc->prepared) {
1976                         free(a_types);
1977                         return cpc;
1978                 }
1979         }
1980
1981         free(a_types);
1982         return NULL;
1983 }
1984
1985 static void __update_slot(int type, bool app_exists)
1986 {
1987         candidate_process_context_t *cpc;
1988
1989         cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1990         if (!cpc)
1991                 return;
1992
1993         cpc->app_exists = app_exists;
1994         if (cpc->app_check && !cpc->app_exists) {
1995                 if (cpc->pid > 0)
1996                         __dispose_candidate_process(cpc);
1997                 __sequencer_remove_slot(cpc);
1998                 if (__sequencer_queue_is_empty())
1999                         __sequencer_stop();
2000         } else {
2001                 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING)
2002                         return;
2003
2004                 if (!cpc->touched && !cpc->on_boot)
2005                         return;
2006
2007                 if (cpc->timer > 0) {
2008                         g_source_remove(cpc->timer);
2009                         cpc->timer = 0;
2010                 }
2011
2012                 if (cpc->pid == CANDIDATE_NONE) {
2013                         __sequencer_add_slot(cpc);
2014                         __sequencer_run();
2015                 }
2016         }
2017 }
2018
2019 static void __foreach_loader_info(loader_info_t *info, void *data)
2020 {
2021         struct app_info *ai = (struct app_info *)data;
2022         bool exist;
2023
2024         exist = _loader_info_exist_app_type(info, ai->type);
2025         if (!exist)
2026                 return;
2027
2028         info->app_exists = ai->exists;
2029         __update_slot(info->type, info->app_exists);
2030 }
2031
2032 static int __dispatch_cmd_update_app_type(bundle *b)
2033 {
2034         int r;
2035         struct app_info info;
2036         const char *is_installed;
2037
2038         info.type = bundle_get_val(b, AUL_K_APP_TYPE);
2039         if (!info.type)
2040                 return -1;
2041
2042         is_installed = bundle_get_val(b, AUL_K_IS_INSTALLED);
2043         if (is_installed && !strcmp(is_installed, "true"))
2044                 info.exists = true;
2045         else
2046                 info.exists = false;
2047
2048         _I("[LAUNCHPAD] type(%s), exists(%d)", info.type, info.exists);
2049
2050         r = _loader_info_foreach(loader_info_list, __foreach_loader_info,
2051                         &info);
2052         if (r != 0) {
2053                 _E("Failed to retrieve loader info");
2054                 return -1;
2055         }
2056
2057         return 0;
2058 }
2059
2060 static void __deactivate_slot(candidate_process_context_t *cpc)
2061 {
2062         if (cpc->state == CANDIDATE_PROCESS_STATE_PAUSED)
2063                 return;
2064
2065         cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2066         __dispose_candidate_process(cpc);
2067 }
2068
2069 static void __activate_slot(candidate_process_context_t *cpc)
2070 {
2071         if (cpc->state == CANDIDATE_PROCESS_STATE_RUNNING)
2072                 return;
2073
2074         cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2075         if (!cpc->touched && !cpc->on_boot)
2076                 return;
2077
2078         if ((cpc->app_check && !cpc->app_exists) || cpc->pid > CANDIDATE_NONE)
2079                 return;
2080
2081         if (cpc->detection_method & METHOD_TIMEOUT)
2082                 __set_timer(cpc);
2083 }
2084
2085 static void __update_slot_state(candidate_process_context_t *cpc, int method,
2086                 bool force)
2087 {
2088         switch (method) {
2089         case METHOD_OUT_OF_MEMORY:
2090                 if ((force || cpc->deactivation_method & method) &&
2091                                 __is_low_memory())
2092                         __deactivate_slot(cpc);
2093                 else
2094                         __activate_slot(cpc);
2095                 break;
2096         case METHOD_TTL:
2097                 if (force || cpc->deactivation_method & method)
2098                         __deactivate_slot(cpc);
2099                 break;
2100         case METHOD_AVAILABLE_MEMORY:
2101                 if (force || cpc->activation_method & method)
2102                         __activate_slot(cpc);
2103                 break;
2104         case METHOD_REQUEST:
2105                 if (force || cpc->activation_method & method)
2106                         __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, force);
2107                 break;
2108         default:
2109                 __activate_slot(cpc);
2110                 break;
2111         }
2112 }
2113
2114 static bool __handle_launch_event(int fd, io_condition_e cond, void *data)
2115 {
2116         bundle *kb = NULL;
2117         app_pkt_t *pkt = NULL;
2118         appinfo_t *menu_info = NULL;
2119         candidate_process_context_t *cpc = NULL;
2120         candidate_process_context_t *org_cpc = NULL;
2121         const char *app_path = NULL;
2122         int pid = -1;
2123         int clifd = -1;
2124         struct ucred cr;
2125         int type = -1;
2126         int loader_id;
2127         int ret;
2128
2129         if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
2130                 _E("fd(%d), condition(%d)", fd, cond);
2131                 g_idle_add(__launchpad_recovery_cb, __launchpad_channel);
2132                 __launchpad_channel = NULL;
2133                 return false;
2134         }
2135
2136         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH");
2137         pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
2138         if (!pkt) {
2139                 _E("packet is NULL");
2140                 goto end;
2141         }
2142
2143         if (cr.uid >= REGULAR_UID_MIN) {
2144                 if (__check_caller_by_pid(cr.pid) < 0) {
2145                         _E("Invalid caller pid");
2146                         goto end;
2147                 }
2148         }
2149
2150         kb = bundle_decode(pkt->data, pkt->len);
2151         if (!kb) {
2152                 _E("bundle decode error");
2153                 goto end;
2154         }
2155
2156         if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
2157                 _debug_init();
2158
2159         switch (pkt->cmd) {
2160         case PAD_CMD_VISIBILITY:
2161                 ret = __dispatch_cmd_hint(kb, METHOD_VISIBILITY);
2162                 __real_send(clifd, ret);
2163                 clifd = -1;
2164                 goto end;
2165         case PAD_CMD_ADD_LOADER:
2166                 ret = __dispatch_cmd_add_loader(kb);
2167                 __real_send(clifd, ret);
2168                 clifd = -1;
2169                 goto end;
2170         case PAD_CMD_REMOVE_LOADER:
2171                 ret = __dispatch_cmd_remove_loader(kb);
2172                 __real_send(clifd, ret);
2173                 clifd = -1;
2174                 goto end;
2175         case PAD_CMD_MAKE_DEFAULT_SLOTS:
2176                 ret = __add_default_slots();
2177                 if (ret != 0)
2178                         _E("Failed to make default slots");
2179                 __real_send(clifd, ret);
2180                 clifd = -1;
2181                 goto end;
2182         case PAD_CMD_PREPARE_APP_DEFINED_LOADER:
2183                 ret = __dispatch_cmd_add_app_defined_loader(kb);
2184                 __real_send(clifd, ret);
2185                 clifd = -1;
2186                 goto end;
2187         case PAD_CMD_DEMAND:
2188                 ret = __dispatch_cmd_hint(kb, METHOD_DEMAND);
2189                 __real_send(clifd, ret);
2190                 clifd = -1;
2191                 goto end;
2192         case PAD_CMD_PING:
2193                 __real_send(clifd, getpid());
2194                 clifd = -1;
2195                 goto end;
2196         case PAD_CMD_UPDATE_APP_TYPE:
2197                 __dispatch_cmd_update_app_type(kb);
2198                 close(clifd);
2199                 clifd = -1;
2200                 goto end;
2201         }
2202
2203         INIT_PERF(kb);
2204         PERF("packet processing start");
2205
2206         menu_info = _appinfo_create(kb);
2207         if (menu_info == NULL) {
2208                 _E("such pkg no found");
2209                 goto end;
2210         }
2211
2212         app_path = _appinfo_get_app_path(menu_info);
2213         if (app_path == NULL) {
2214                 _E("app_path is NULL");
2215                 goto end;
2216         }
2217         if (app_path[0] != '/') {
2218                 _E("app_path is not absolute path");
2219                 goto end;
2220         }
2221
2222         if (menu_info->hwacc == NULL) {
2223                 _E("[launchpad] Failed to find H/W acceleration type");
2224                 goto end;
2225         }
2226
2227         SECURE_LOGD("exec : %s", menu_info->app_path);
2228         SECURE_LOGD("comp_type : %s", menu_info->comp_type);
2229         SECURE_LOGD("internal pool : %s", menu_info->internal_pool);
2230         SECURE_LOGD("hwacc : %s", menu_info->hwacc);
2231         SECURE_LOGD("app_type : %s", menu_info->app_type);
2232         SECURE_LOGD("pkg_type : %s", menu_info->pkg_type);
2233
2234         if (menu_info->comp_type &&
2235                         strcmp(menu_info->comp_type, "svcapp") == 0) {
2236                 loader_id = __get_loader_id(kb);
2237                 if (loader_id > PAD_LOADER_ID_DYNAMIC_BASE) {
2238                         type = LAUNCHPAD_LOADER_TYPE_DYNAMIC;
2239                         cpc = __find_slot(type, loader_id);
2240                         if (cpc && !cpc->prepared)
2241                                 cpc = NULL;
2242                 } else {
2243                         loader_id = PAD_LOADER_ID_DIRECT;
2244                 }
2245         } else if (menu_info->comp_type && menu_info->app_type &&
2246                         strcmp(menu_info->comp_type, "widgetapp") == 0 &&
2247                         strcmp(menu_info->app_type, "webapp") == 0) {
2248                 loader_id = PAD_LOADER_ID_DIRECT;
2249         } else {
2250                 loader_id = __get_loader_id(kb);
2251                 if (loader_id <= PAD_LOADER_ID_STATIC) {
2252                         cpc = __find_available_slot(menu_info->hwacc,
2253                                         menu_info->app_type,
2254                                         menu_info->loader_name, &org_cpc);
2255                 } else {
2256                         type = LAUNCHPAD_LOADER_TYPE_DYNAMIC;
2257                         cpc = __find_slot(type, loader_id);
2258                         if (cpc && !cpc->prepared)
2259                                 cpc = NULL;
2260                 }
2261         }
2262
2263         _modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
2264         if (menu_info->appid == NULL) {
2265                 _E("unable to get appid from menu_info");
2266                 goto end;
2267         }
2268
2269         PERF("get package information & modify bundle done");
2270
2271         if (loader_id == PAD_LOADER_ID_DIRECT || cpc == NULL) {
2272                 _W("Launch directly %d %p", loader_id, cpc);
2273                 pid = __launch_directly(menu_info->appid, app_path, clifd, kb,
2274                                 menu_info, NULL);
2275                 if (org_cpc && (!org_cpc->app_check || org_cpc->app_exists) &&
2276                                 org_cpc->pid == CANDIDATE_NONE &&
2277                                 !__sequencer_slot_exist(org_cpc)) {
2278                         if (org_cpc->timer > 0) {
2279                                 g_source_remove(org_cpc->timer);
2280                                 org_cpc->timer = 0;
2281                         }
2282
2283                         __update_slot_state(org_cpc, METHOD_REQUEST, true);
2284                         __set_timer(org_cpc);
2285                 }
2286         } else {
2287                 _W("Launch %d type process", cpc->type);
2288                 pid = __send_launchpad_loader(cpc, pkt, app_path, clifd);
2289         }
2290
2291         _memory_monitor_reset_timer();
2292         __send_result_to_caller(clifd, pid, app_path);
2293         clifd = -1;
2294 end:
2295         if (clifd != -1)
2296                 close(clifd);
2297
2298         if (pid > 0) {
2299                 _dbus_send_app_launch_signal(pid, menu_info->appid);
2300                 g_hash_table_insert(__pid_table, GINT_TO_POINTER(pid),
2301                                 strdup(menu_info->appid));
2302                 _log_print("[LAUNCH]", "pid(%7d) | appid(%s)",
2303                                 pid, menu_info->appid);
2304         }
2305
2306         if (menu_info != NULL)
2307                 _appinfo_free(menu_info);
2308
2309         if (kb != NULL)
2310                 bundle_free(kb);
2311         if (pkt != NULL)
2312                 free(pkt);
2313
2314         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
2315
2316         return true;
2317 }
2318
2319 static void __destroy_slot(candidate_process_context_t *cpc)
2320 {
2321         if (!cpc)
2322                 return;
2323
2324         if (cpc->hydra_channel)
2325                 _io_channel_destroy(cpc->hydra_channel);
2326
2327         if (cpc->channel)
2328                 _io_channel_destroy(cpc->channel);
2329
2330         if (cpc->loader_extra)
2331                 free(cpc->loader_extra);
2332
2333         if (cpc->loader_path)
2334                 free(cpc->loader_path);
2335
2336         if (cpc->loader_name)
2337                 free(cpc->loader_name);
2338
2339         free(cpc);
2340 }
2341
2342 static candidate_process_context_t *__create_slot(int type, int loader_id,
2343                 int caller_pid, const char *loader_name, const char *loader_path,
2344                 const char *loader_extra, int detection_method,
2345                 int activation_method, int deactivation_method,
2346                 unsigned int ttl, int timeout_val,
2347                 int threshold_max, int threshold_min,
2348                 bool on_boot, bool app_exists, bool is_hydra, bool app_check)
2349 {
2350         candidate_process_context_t *cpc;
2351
2352         cpc = calloc(1, sizeof(candidate_process_context_t));
2353         if (cpc == NULL) {
2354                 _E("Out of memory");
2355                 return NULL;
2356         }
2357
2358         cpc->loader_name = strdup(loader_name);
2359         if (cpc->loader_name == NULL) {
2360                 _E("Failed to duplicate loader name(%s)", loader_name);
2361                 __destroy_slot(cpc);
2362                 return NULL;
2363         }
2364
2365         cpc->loader_path = strdup(loader_path);
2366         if (cpc->loader_path == NULL) {
2367                 _E("Failed to duplicate loader path(%s)", loader_path);
2368                 __destroy_slot(cpc);
2369                 return NULL;
2370         }
2371
2372         cpc->loader_extra = loader_extra ? strdup(loader_extra) : strdup("");
2373         if (cpc->loader_extra == NULL) {
2374                 _E("Failed to duplicate loader extra(%s)",
2375                                 loader_extra ? loader_extra : "null");
2376                 __destroy_slot(cpc);
2377                 return NULL;
2378         }
2379
2380         cpc->type = type;
2381         cpc->prepared = false;
2382         cpc->pid = CANDIDATE_NONE;
2383         cpc->hydra_pid = HYDRA_NONE;
2384         cpc->caller_pid = caller_pid;
2385         cpc->loader_id = loader_id;
2386         cpc->send_fd = -1;
2387         cpc->hydra_fd = -1;
2388         cpc->last_exec_time = 0;
2389         cpc->timer = 0;
2390         cpc->detection_method = detection_method;
2391         cpc->timeout_val = timeout_val;
2392         cpc->cpu_total_time = 0;
2393         cpc->cpu_idle_time = 0;
2394         cpc->threshold = threshold_max;
2395         cpc->threshold_max = threshold_max;
2396         cpc->threshold_min = threshold_min;
2397         cpc->on_boot = on_boot;
2398         cpc->app_exists = app_exists;
2399         cpc->touched = false;
2400         cpc->cur_event = 0;
2401         cpc->activation_method = activation_method;
2402         cpc->deactivation_method = deactivation_method;
2403         cpc->ttl = ttl;
2404         cpc->live_timer = 0;
2405         cpc->is_hydra = is_hydra;
2406         cpc->app_check = app_check;
2407         cpc->score = WIN_SCORE;
2408         cpc->pss = 0;
2409         cpc->cpu_check_count = 0;
2410
2411         if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) &&
2412                         __is_low_memory())
2413                 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
2414         else
2415                 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
2416
2417         _W("loader(%s), type(%d), state(%d)",
2418                         cpc->loader_name, cpc->type, cpc->state);
2419         return cpc;
2420 }
2421
2422 static candidate_process_context_t *__add_slot(int type, int loader_id,
2423                 int caller_pid, const char *loader_name, const char *loader_path,
2424                 const char *loader_extra, int detection_method,
2425                 int activation_method, int deactivation_method,
2426                 unsigned int ttl, int timeout_val,
2427                 int threshold_max, int threshold_min,
2428                 bool on_boot, bool app_exists, bool is_hydra, bool app_check)
2429 {
2430         candidate_process_context_t *cpc;
2431         int fd;
2432         io_channel_h channel;
2433         int hydra_fd;
2434         io_channel_h hydra_channel;
2435
2436         if (__find_slot(type, loader_id) != NULL)
2437                 return NULL;
2438
2439         cpc = __create_slot(type, loader_id,
2440                         caller_pid, loader_name, loader_path,
2441                         loader_extra, detection_method,
2442                         activation_method, deactivation_method,
2443                         ttl, timeout_val,
2444                         threshold_max, threshold_min,
2445                         on_boot, app_exists, is_hydra, app_check);
2446         if (cpc == NULL)
2447                 return NULL;
2448
2449         fd = __listen_candidate_process(cpc->type, cpc->loader_id);
2450         if (fd == -1) {
2451                 _E("[launchpad] Listening the socket to " \
2452                                 "the type %d candidate process failed.",
2453                                 cpc->type);
2454                 __destroy_slot(cpc);
2455                 return NULL;
2456         }
2457
2458         channel = _io_channel_create(fd, IO_IN, __handle_loader_event, cpc);
2459         if (!channel) {
2460                 close(fd);
2461                 __destroy_slot(cpc);
2462                 return NULL;
2463         }
2464
2465         cpc->channel = channel;
2466
2467         if (is_hydra) {
2468                 hydra_fd = __listen_hydra_process(cpc->type, cpc->loader_id);
2469                 if (hydra_fd == -1) {
2470                         _E("[launchpad] Listening the socket to " \
2471                                         "the type %d hydra process failed.",
2472                                         cpc->type);
2473                         __destroy_slot(cpc);
2474                         return NULL;
2475                 }
2476
2477                 hydra_channel = _io_channel_create(hydra_fd, IO_IN,
2478                                 __handle_hydra_event, cpc);
2479                 if (!hydra_channel) {
2480                         close(hydra_fd);
2481                         __destroy_slot(cpc);
2482                         return NULL;
2483                 }
2484
2485                 cpc->hydra_channel = hydra_channel;
2486         }
2487
2488
2489         candidate_slot_list = g_list_append(candidate_slot_list, cpc);
2490
2491         return cpc;
2492 }
2493
2494 static int __remove_slot(int type, int loader_id)
2495 {
2496         candidate_process_context_t *cpc;
2497         GList *iter;
2498
2499         iter = candidate_slot_list;
2500         while (iter) {
2501                 cpc = (candidate_process_context_t *)iter->data;
2502                 if (type == cpc->type && loader_id == cpc->loader_id) {
2503                         __dispose_candidate_process(cpc);
2504                         candidate_slot_list = g_list_delete_link(
2505                                         candidate_slot_list, iter);
2506                         __destroy_slot(cpc);
2507                         return 0;
2508                 }
2509
2510                 iter = g_list_next(iter);
2511         }
2512
2513         return -1;
2514 }
2515
2516 static int __init_launchpad_fd(int argc, char **argv)
2517 {
2518         io_condition_e cond;
2519         int fd;
2520
2521         fd = __launchpad_pre_init(argc, argv);
2522         if (fd < 0) {
2523                 _E("launchpad pre init failed");
2524                 return -1;
2525         }
2526
2527         cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
2528         __launchpad_channel = _io_channel_create(fd, cond,
2529                         __handle_launch_event, NULL);
2530         if (!__launchpad_channel) {
2531                 close(fd);
2532                 return -1;
2533         }
2534
2535         return 0;
2536 }
2537
2538 static bool __on_directory_create(const char *event_name, uint32_t mask,
2539                 void *user_data)
2540 {
2541         if (!event_name) {
2542                 _E("Invalid parameter");
2543                 return true;
2544         }
2545
2546         if (!strcmp(event_name, LOADERS_PATH)) {
2547                 __init_app_defined_loader_monitor();
2548                 return false;
2549         }
2550
2551         return true;
2552 }
2553
2554 static bool __on_file_change(const char *event_name, uint32_t mask,
2555                 void *user_data)
2556 {
2557         char buf[PATH_MAX];
2558         char *ext;
2559         loader_info_t* info;
2560         candidate_process_context_t *cpc;
2561
2562         if (!event_name) {
2563                 _E("Invalid parameter");
2564                 return true;
2565         }
2566
2567         ext = strrchr(event_name, '.');
2568         if (ext == NULL || strcmp(ext, ".loader") != 0)
2569                 return true;
2570
2571         if (mask & IN_CREATE) {
2572                 snprintf(buf, sizeof(buf), "%s/%s",
2573                                 APP_DEFINED_LOADER_INFO_PATH, event_name);
2574                 app_defined_loader_info_list = _loader_info_load_file(
2575                                 app_defined_loader_info_list, buf);
2576         } else if (mask & IN_DELETE) {
2577                 snprintf(buf, ext - event_name + 1, "%s", event_name);
2578
2579                 info = _loader_info_find_loader_by_loader_name(
2580                                 app_defined_loader_info_list, buf);
2581                 cpc = __find_slot_from_loader_name(info->name);
2582                 __remove_slot(cpc->type, cpc->loader_id);
2583                 app_defined_loader_info_list = _loader_info_unload(
2584                                 app_defined_loader_info_list, buf);
2585         }
2586
2587         return true;
2588 }
2589
2590 static void __init_app_defined_loader_monitor(void)
2591 {
2592         int ret;
2593
2594         ret = access(APP_DEFINED_LOADER_INFO_PATH, F_OK);
2595         if (ret < 0) {
2596                 _W("Failed to access %s", APP_DEFINED_LOADER_INFO_PATH);
2597                 ret = _inotify_add_watch(OPT_SHARE_PATH,
2598                                 IN_CREATE, __on_directory_create, NULL);
2599                 if (ret != 0)
2600                         _E("Failed to add inotify watch %s", OPT_SHARE_PATH);
2601
2602                 return;
2603         }
2604
2605         ret = _inotify_add_watch(APP_DEFINED_LOADER_INFO_PATH,
2606                         IN_CREATE | IN_DELETE, __on_file_change, NULL);
2607
2608         if (ret < 0) {
2609                 _E("Failed to add inotify watch %s",
2610                                 APP_DEFINED_LOADER_INFO_PATH);
2611         }
2612
2613         return;
2614
2615 }
2616
2617 static int __init_label_monitor_fd(void)
2618 {
2619         io_condition_e cond;
2620         int r;
2621         int fd = -1;
2622
2623         r = security_manager_app_labels_monitor_init(&label_monitor);
2624         if (r != SECURITY_MANAGER_SUCCESS)
2625                 return -1;
2626
2627         r = security_manager_app_labels_monitor_process(label_monitor);
2628         if (r != SECURITY_MANAGER_SUCCESS)
2629                 goto err;
2630
2631         security_manager_app_labels_monitor_get_fd(label_monitor, &fd);
2632         if (fd < 0) {
2633                 _E("failed to get fd");
2634                 goto err;
2635         }
2636
2637         cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL;
2638         __label_monitor_channel = _io_channel_create(fd, cond,
2639                         __handle_label_monitor, NULL);
2640         if (!__label_monitor_channel)
2641                 goto err;
2642
2643         return 0;
2644
2645 err:
2646         if (fd > 0)
2647                 close(fd);
2648
2649         if (label_monitor) {
2650                 security_manager_app_labels_monitor_finish(label_monitor);
2651                 label_monitor = NULL;
2652         }
2653
2654         return -1;
2655 }
2656
2657 static int __verify_loader_caps(const char *loader)
2658 {
2659         cap_t cap_d;
2660         cap_flag_value_t eff_state;
2661         cap_flag_value_t inh_state;
2662         cap_value_t values[] = {CAP_SETGID, CAP_MAC_ADMIN};
2663         int r;
2664         int i;
2665         int size = ARRAY_SIZE(values);
2666
2667         /* If Dytransition feature is enabled, CAP_MAC_ADMIN is unnecessary */
2668         if (label_monitor)
2669                 size--;
2670
2671         cap_d = cap_get_file(loader);
2672         if (!cap_d) {
2673                 _E("Failed to get cap from file(%s)", loader);
2674                 return -1;
2675         }
2676
2677         for (i = 0; i < size; i++) {
2678                 r = cap_get_flag(cap_d, values[i], CAP_INHERITABLE, &inh_state);
2679                 if (r != 0) {
2680                         _E("Failed to get cap inh - errno(%d)", errno);
2681                         cap_free(cap_d);
2682                         return -1;
2683                 }
2684
2685                 r = cap_get_flag(cap_d, values[i], CAP_EFFECTIVE, &eff_state);
2686                 if (r != 0) {
2687                         _E("Failed to get cap eff - errno(%d)", errno);
2688                         cap_free(cap_d);
2689                         return -1;
2690                 }
2691
2692                 if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) {
2693                         _E("The %s doesn't have %d cap", loader, values[i]);
2694                         cap_free(cap_d);
2695                         return -1;
2696                 }
2697         }
2698         cap_free(cap_d);
2699
2700         return 0;
2701 }
2702
2703 static void __add_slot_from_info(gpointer data, gpointer user_data)
2704 {
2705         loader_info_t *info = (loader_info_t *)data;
2706         candidate_process_context_t *cpc;
2707         bundle_raw *extra = NULL;
2708         int len;
2709
2710         if (!strcmp(info->exe, "null")) {
2711                 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset,
2712                                 PAD_LOADER_ID_DIRECT,
2713                                 0, info->name, info->exe, NULL,
2714                                 0, 0, 0, 0, 0,
2715                                 info->cpu_threshold_max,
2716                                 info->cpu_threshold_min,
2717                                 false,
2718                                 info->app_exists,
2719                                 info->is_hydra,
2720                                 info->app_check);
2721                 if (cpc == NULL)
2722                         return;
2723
2724                 info->type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset;
2725                 user_slot_offset++;
2726                 return;
2727         }
2728
2729         if (access(info->exe, F_OK | X_OK) == 0) {
2730                 if (__verify_loader_caps(info->exe) < 0)
2731                         return;
2732
2733                 if (info->extra)
2734                         bundle_encode(info->extra, &extra, &len);
2735
2736                 cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset,
2737                                 PAD_LOADER_ID_STATIC,
2738                                 0, info->name, info->exe, (char *)extra,
2739                                 info->detection_method,
2740                                 info->activation_method,
2741                                 info->deactivation_method,
2742                                 info->ttl,
2743                                 info->timeout_val,
2744                                 info->cpu_threshold_max,
2745                                 info->cpu_threshold_min,
2746                                 info->on_boot,
2747                                 info->app_exists,
2748                                 info->is_hydra,
2749                                 info->app_check);
2750
2751                 bundle_free_encoded_rawdata(&extra);
2752                 if (cpc == NULL)
2753                         return;
2754
2755                 info->type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset;
2756                 user_slot_offset++;
2757         }
2758 }
2759
2760 static int __add_default_slots(void)
2761 {
2762         if (loader_info_list)
2763                 _loader_info_dispose(loader_info_list);
2764
2765         loader_info_list = _loader_info_load_dir(LOADER_INFO_PATH);
2766         if (loader_info_list == NULL)
2767                 return -1;
2768
2769         user_slot_offset = 0;
2770         g_list_foreach(loader_info_list, __add_slot_from_info, NULL);
2771         __add_idle_checker(0, candidate_slot_list);
2772
2773         return 0;
2774 }
2775
2776 static void __add_app_defined_loaders(void)
2777 {
2778         app_defined_loader_info_list = _loader_info_load_dir(APP_DEFINED_LOADER_INFO_PATH);
2779 }
2780
2781 static bool __is_low_memory(void)
2782 {
2783         if (_memory_monitor_is_low_memory())
2784                 return true;
2785
2786         if (__memory_status_low >= MEMORY_STATUS_LOW)
2787                 return true;
2788
2789         return false;
2790 }
2791
2792 static void __hw_acceleration_changed_cb(keynode_t *key, void *data)
2793 {
2794         __sys_hwacc = vconf_keynode_get_int(key);
2795         _D("sys hwacc: %d", __sys_hwacc);
2796 }
2797
2798 static void __update_lang(keynode_t *node, void *user_data)
2799 {
2800         char *lang;
2801
2802         lang = vconf_keynode_get_str(node);
2803         if (!lang) {
2804                 _E("Failed to get language");
2805                 return;
2806         }
2807
2808         setenv("LANG", lang, 1);
2809 }
2810
2811 static void __region_format_changed_cb(keynode_t *node, void *data)
2812 {
2813         char *region;
2814
2815         region = vconf_keynode_get_str(node);
2816         if (!region) {
2817                 _E("Failed to get value");
2818                 return;
2819         }
2820
2821         setenv("LC_CTYPE", region, 1);
2822 }
2823
2824 static void __memory_status_low_changed_cb(keynode_t *node, void *data)
2825 {
2826         candidate_process_context_t *cpc;
2827         GList *iter;
2828
2829         __memory_status_low = vconf_keynode_get_int(node);
2830         if (__memory_status_low >= MEMORY_STATUS_LOW) {
2831                 _W("Low memory");
2832                 iter = candidate_slot_list;
2833                 while (iter) {
2834                         cpc = (candidate_process_context_t *)iter->data;
2835                         __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, false);
2836                         iter = g_list_next(iter);
2837                 }
2838         }
2839 }
2840
2841 static void __memory_status_normal_changed_cb(keynode_t *node, void *data)
2842 {
2843         candidate_process_context_t *cpc;
2844         GList *iter;
2845
2846         __memory_status_normal = vconf_keynode_get_int(node);
2847         if (__memory_status_normal == MEMORY_STATUS_NORMAL) {
2848                 _W("Normal");
2849                 iter = candidate_slot_list;
2850                 while (iter) {
2851                         cpc = (candidate_process_context_t *)iter->data;
2852                         __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, true);
2853                         iter = g_list_next(iter);
2854                 }
2855         }
2856 }
2857
2858 static void __unregister_vconf_events(void)
2859 {
2860         const char *key;
2861         config_type_e type;
2862
2863         type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY;
2864         key = _config_get_string_value(type);
2865         vconf_ignore_key_changed(key, __memory_status_normal_changed_cb);
2866
2867         type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY;
2868         key = _config_get_string_value(type);
2869         vconf_ignore_key_changed(key, __memory_status_low_changed_cb);
2870
2871         vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT,
2872                         __region_format_changed_cb);
2873         vconf_ignore_key_changed(VCONFKEY_LANGSET,
2874                         __update_lang);
2875         vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2876                         __hw_acceleration_changed_cb);
2877 }
2878
2879 static int __register_vconf_events(void)
2880 {
2881         int r;
2882         char *lang;
2883         char *region;
2884         const char *key;
2885         config_type_e type;
2886
2887         r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc);
2888         if (r != VCONF_OK)
2889                 _E("Failed to get vconf hw acceleration. err = %d", r);
2890
2891         r = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2892                         __hw_acceleration_changed_cb, NULL);
2893         if (r != VCONF_OK) {
2894                 _E("Failed to register callback for hw acceleration. err = %d",
2895                                 r);
2896         }
2897
2898         lang = vconf_get_str(VCONFKEY_LANGSET);
2899         if (lang) {
2900                 setenv("LANG", lang, 1);
2901                 free(lang);
2902         }
2903
2904         r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL);
2905         if (r != VCONF_OK)
2906                 _E("Failed to register callback for langset. err = %d", r);
2907
2908         region = vconf_get_str(VCONFKEY_REGIONFORMAT);
2909         if (region) {
2910                 setenv("LC_CTYPE", region, 1);
2911                 free(region);
2912         }
2913
2914         r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT,
2915                         __region_format_changed_cb, NULL);
2916         if (r != VCONF_OK)
2917                 _E("Failed to register callback for regionformat. err = %d", r);
2918
2919         type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY;
2920         key = _config_get_string_value(type);
2921         type = CONFIG_TYPE_MEMORY_STATUS_LOW_VALUE;
2922         MEMORY_STATUS_LOW = _config_get_int_value(type);
2923
2924         r = vconf_get_int(key, &__memory_status_low);
2925         if (r != VCONF_OK)
2926                 _E("Failed to get vconf low memory. err = %d", r);
2927
2928         r = vconf_notify_key_changed(key,
2929                         __memory_status_low_changed_cb, NULL);
2930         if (r != 0)
2931                 _E("Failed to register callback for low memory. err = %d", r);
2932
2933         type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY;
2934         key = _config_get_string_value(type);
2935         type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_VALUE;
2936         MEMORY_STATUS_NORMAL = _config_get_int_value(type);
2937
2938         r = vconf_get_int(key, &__memory_status_normal);
2939         if (r != VCONF_OK)
2940                 _E("Failed to get vconf normal memory. err = %d", r);
2941
2942         r = vconf_notify_key_changed(key,
2943                         __memory_status_normal_changed_cb, NULL);
2944         if (r != 0)
2945                 _E("Failed to register callback for normal memory. err = %d", r);
2946
2947         return 0;
2948 }
2949
2950 static bool __handle_logger(int fd, io_condition_e cond, void *data)
2951 {
2952         app_pkt_t *pkt;
2953         struct ucred cr;
2954         int clifd = -1;
2955
2956         if (cond & (IO_ERR | IO_HUP | IO_NVAL)) {
2957                 _E("fd(%d), io_condition(%d)", fd, cond);
2958                 g_idle_add(__logger_recovery_cb, __logger_channel);
2959                 __logger_channel = NULL;
2960                 return false;
2961         }
2962
2963         pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
2964         if (!pkt) {
2965                 _E("Failed to receive the packet");
2966                 return true;
2967         }
2968
2969         if (getuid() != cr.uid) {
2970                 _E("Invalid caller");
2971                 goto end;
2972         }
2973
2974         if (pkt->len <= 0) {
2975                 _E("Invalid message");
2976                 goto end;
2977         }
2978
2979         _E("[%d] %s", cr.pid, (const char *)pkt->data);
2980         _log_print("[ERROR]", "pid(%7d) | message(%s)",
2981                         cr.pid, (const char *)pkt->data);
2982 end:
2983         if (clifd != -1)
2984                 close(clifd);
2985
2986         free(pkt);
2987
2988         return true;
2989 }
2990
2991 static int __init_logger_fd(void)
2992 {
2993         io_condition_e cond;
2994         int fd;
2995
2996         fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK);
2997         if (fd < 0) {
2998                 _E("Failed to create logger socker");
2999                 return -1;
3000         }
3001
3002         cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL;
3003         __logger_channel = _io_channel_create(fd, cond, __handle_logger, NULL);
3004         if (!__logger_channel) {
3005                 close(fd);
3006                 return -1;
3007         }
3008
3009         return 0;
3010 }
3011
3012 static int __memory_monitor_cb(bool low_memory, void *user_data)
3013 {
3014         candidate_process_context_t *cpc;
3015
3016         cpc = __get_running_slot(false);
3017         if (!cpc && low_memory)
3018                 return -1;
3019
3020         if (low_memory) {
3021                 _W("Low memory");
3022                 __update_slots_pss();
3023
3024                 candidate_slot_list = g_list_sort(candidate_slot_list,
3025                                 __compare_slot);
3026
3027                 do {
3028                         __pause_last_running_slot(false);
3029
3030                         cpc = __get_running_slot(false);
3031                         if (!cpc)
3032                                 break;
3033                 } while (__is_low_memory());
3034         } else {
3035                 __resume_all_slots();
3036         }
3037
3038         return 0;
3039 }
3040
3041 static gboolean __logger_recovery_cb(gpointer data)
3042 {
3043         io_channel_h channel = data;
3044         int ret;
3045
3046         _io_channel_destroy(channel);
3047
3048         ret = __init_logger_fd();
3049         if (ret < 0) {
3050                 _E("Failed to recover logger socket");
3051                 return G_SOURCE_REMOVE;
3052         }
3053
3054         _E("[__RECOVERY__] Logger socket");
3055
3056         return G_SOURCE_REMOVE;
3057 }
3058
3059 static gboolean __launchpad_recovery_cb(gpointer data)
3060 {
3061         io_channel_h channel = data;
3062         int ret;
3063
3064         _io_channel_destroy(channel);
3065
3066         ret = __init_launchpad_fd(0, NULL);
3067         if (ret < 0) {
3068                 _E("Failed to recover launchpad socket");
3069                 abort();
3070                 return G_SOURCE_REMOVE;
3071         }
3072
3073         _E("[__RECOVERY__] Launchpad socket");
3074
3075         return G_SOURCE_REMOVE;
3076 }
3077
3078 static int __before_loop(int argc, char **argv)
3079 {
3080         int ret;
3081
3082         _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__);
3083         ret = __sequencer_init();
3084         if (ret < 0) {
3085                 _E("Failed to initialize sequencer");
3086                 return -1;
3087         }
3088
3089         ret = _signal_init();
3090         if (ret < 0) {
3091                 _E("Failed to initialize signal");
3092                 return -1;
3093         }
3094
3095         _signal_set_sigchld_cb(__handle_sigchild, NULL);
3096
3097         ret = __init_launchpad_fd(argc, argv);
3098         if (ret != 0) {
3099                 _E("__init_launchpad_fd() failed");
3100                 return -1;
3101         }
3102
3103         ret = __init_logger_fd();
3104         if (ret != 0) {
3105                 _E("__init_logger_fd() failed");
3106                 return -1;
3107         }
3108
3109         ret = __init_label_monitor_fd();
3110         if (ret != 0)
3111                 _W("Failed to initialize label monitor");
3112
3113         ret = _config_init();
3114         if (ret != 0)
3115                 _W("Failed to initialize config");
3116
3117         ret = _dbus_init();
3118         if (ret != 0)
3119                 _W("Failed to initialize dbus");
3120
3121         _inotify_init();
3122
3123         MAX_CPU_CHECK_COUNT = _config_get_int_value(
3124                         CONFIG_TYPE_CPU_CHECKER_MAX_COUNT);
3125         __add_default_slots();
3126         launcher_info_list = _launcher_info_load(LAUNCHER_INFO_PATH);
3127
3128         __add_app_defined_loaders();
3129
3130         ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL);
3131         if (ret < 0)
3132                 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL);
3133
3134         __pid_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3135                         NULL, free);
3136         if (!__pid_table) {
3137                 _E("Failed to create pid table");
3138                 return -1;
3139         }
3140
3141         ret = _worker_init();
3142         if (ret < 0)
3143                 return ret;
3144
3145         __register_vconf_events();
3146         __init_app_defined_loader_monitor();
3147         _memory_monitor_init();
3148         _memory_monitor_set_event_cb(__memory_monitor_cb, NULL);
3149         _log_init();
3150         _print_hwc_log("%s(%d): END", __FUNCTION__, __LINE__);
3151
3152         return 0;
3153 }
3154
3155 static void __after_loop(void)
3156 {
3157         _log_fini();
3158         _memory_monitor_fini();
3159         __unregister_vconf_events();
3160         _worker_fini();
3161         if (__pid_table)
3162                 g_hash_table_destroy(__pid_table);
3163
3164         if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0)
3165                 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL);
3166
3167         _debug_fini();
3168         _launcher_info_unload(launcher_info_list);
3169         _dbus_fini();
3170         _config_fini();
3171         _inotify_fini();
3172         _loader_info_dispose(app_defined_loader_info_list);
3173
3174         if (__label_monitor_channel)
3175                 _io_channel_destroy(__label_monitor_channel);
3176
3177         if (label_monitor)
3178                 security_manager_app_labels_monitor_finish(label_monitor);
3179
3180         if (__logger_channel)
3181                 _io_channel_destroy(__logger_channel);
3182
3183         if (__launchpad_channel)
3184                 _io_channel_destroy(__launchpad_channel);
3185
3186         _signal_fini();
3187
3188         __sequencer_fini();
3189 }
3190
3191 int main(int argc, char **argv)
3192 {
3193         GMainLoop *mainloop = NULL;
3194
3195         _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__);
3196         mainloop = g_main_loop_new(NULL, FALSE);
3197         if (!mainloop) {
3198                 _E("Failed to create glib main loop");
3199                 return -1;
3200         }
3201
3202         _print_hwc_log("%s(%d): __before_loop()", __FUNCTION__, __LINE__);
3203         if (__before_loop(argc, argv) != 0) {
3204                 _E("process-pool Initialization failed!");
3205                 return -1;
3206         }
3207
3208 #ifdef TIZEN_FEATURE_PRIORITY_CHANGE
3209         _set_priority(-12);
3210 #endif
3211         _print_hwc_log("%s(%d): g_main_loop_run()", __FUNCTION__, __LINE__);
3212         g_main_loop_run(mainloop);
3213
3214         __after_loop();
3215
3216         return -1;
3217 }
3218