Tizen 2.4.0 rev3 SDK Public Release
[framework/appfw/aul-1.git] / am_daemon / amd_main.c
1 /*
2  *  aul
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #define _GNU_SOURCE
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/inotify.h>
27 #include <fcntl.h>
28 #include <Ecore_X.h>
29 #include <Ecore_Input.h>
30 #include <Ecore.h>
31 #include <Evas.h>
32 #include <aul.h>
33 #include <vconf.h>
34 #ifdef _APPFW_FEATURE_APP_CHECKER
35 #include <app-checker-server.h>
36 #endif
37 #include <glib.h>
38 #include <sys/resource.h>
39 #include <assert.h>
40 #include <pkgmgr-info.h>
41 #include <proc_stat.h>
42
43 #include "amd_config.h"
44 #include "simple_util.h"
45 #include "aul_util.h"
46 #include "app_sock.h"
47 #include "amd_appinfo.h"
48 #include "amd_key.h"
49 #include "amd_status.h"
50 #include "amd_launch.h"
51 #include "amd_request.h"
52 #include "amd_app_group.h"
53 #ifdef _APPFW_FEATURE_EXPANSION_PKG_INSTALL
54 #include "appfw_env.h"
55 #include "app_signal.h"
56 #endif
57
58
59 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
60 typedef struct _r_app_info_t{
61         char pkg_name[MAX_PACKAGE_STR_SIZE];
62         int pid;
63 } r_app_info_t;
64
65 GSList *r_app_info_list = NULL;
66 #endif
67
68 gboolean platform_ready = false;
69 #ifdef _APPFW_FEATURE_ULTRA_POWER_SAVING_MODE
70 int ups_mode = 0;
71 #endif
72
73 typedef struct _window_watch {
74         int watch_fd;
75         int win_watch_wd;
76         Ecore_Fd_Handler *win_watch_ewd;
77 } _window_watch_t;
78 static _window_watch_t *win_info_t = NULL;
79
80 #ifdef _APPFW_FEATURE_EXPANSION_PKG_INSTALL
81 extern DBusConnection *conn;
82 extern struct appinfomgr *_laf;
83 #endif
84
85 static int window_initialized = 0;
86
87 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
88 static void __vconf_cb(keynode_t *key, void *data);
89 #endif
90 static int __app_dead_handler(int pid, void *data);
91 static int __init();
92
93 extern int _status_init(struct amdmgr* amd);
94
95 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
96 static int __kill_bg_apps(int limit)
97 {
98         int len;
99         int i;
100         int n;
101         r_app_info_t *info_t = NULL;
102         GSList *iter = NULL;
103
104         len = g_slist_length(r_app_info_list);
105
106         n = len - limit;
107
108         if (n<=0) return 0;
109
110         for ( i=0, iter = r_app_info_list; i<n ; i++) {
111                 info_t = (r_app_info_t *)iter->data;
112                 aul_send_app_terminate_request_signal(info_t->pid, NULL, NULL, NULL);
113                 _term_app(info_t->pid, 0);
114                 iter = g_slist_next(iter);
115                 r_app_info_list = g_slist_remove(r_app_info_list, info_t);
116                 free(info_t);
117         }
118
119         return 0;
120 }
121
122 static int __remove_item_running_list(int pid)
123 {
124         r_app_info_t *info_t = NULL;
125         GSList *iter = NULL;
126
127         for (iter = r_app_info_list; iter != NULL; iter = g_slist_next(iter))
128         {
129                 info_t = (r_app_info_t *)iter->data;
130                 if(pid == info_t->pid) {
131                         r_app_info_list = g_slist_remove(r_app_info_list, info_t);
132                         free(info_t);
133                         break;
134                 }
135         }
136         return 0;
137 }
138
139 gboolean __add_item_running_list(gpointer user_data)
140 {
141
142         bool taskmanage;
143         pkgmgrinfo_appinfo_h handle = NULL;
144         int ret = 0;
145         r_app_info_t *info_t = NULL;
146         GSList *iter = NULL;
147         int found = 0;
148         int limit;
149
150         item_pkt_t *item  = (item_pkt_t *)user_data;
151         if (item == NULL) {
152                 return false;
153         }
154
155         char* appid = item->appid;
156         int pid = item->pid;
157
158         SECURE_LOGD("__add_item_running_list pid: %d", pid);
159
160         if (vconf_get_int(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS, &limit) != 0){
161                 _E("Unable to get VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS\n");
162         }
163
164         if (appid == NULL) {
165                 return false;
166         } else if (strncmp(appid, "org.tizen.cluster-home", 24) == 0) {
167                 if(limit>0) __kill_bg_apps(limit-1);
168                 return false;
169         }
170
171         SECURE_LOGD("__add_item_running_list appid: %s", appid);
172
173         ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle);
174         if (ret != PMINFO_R_OK) {
175                 _E("pkgmgrinfo_pkginfo_get_pkginfo with %s failed", appid);
176                 return false;
177         }
178
179         ret = pkgmgrinfo_appinfo_is_taskmanage(handle, &taskmanage);
180         if (ret != PMINFO_R_OK) {
181                 _E("pkgmgrinfo_appinfo_is_taskmanage failed");
182                 goto END;
183         }
184
185         if (taskmanage == false)
186                 goto END;
187
188         for (iter = r_app_info_list; iter != NULL; iter = g_slist_next(iter))
189         {
190                 info_t = (r_app_info_t *)iter->data;
191                 if(pid == info_t->pid) {
192                         found = 1;
193                         r_app_info_list = g_slist_remove(r_app_info_list, info_t);
194                         r_app_info_list = g_slist_append(r_app_info_list, info_t);
195                         break;
196                 }
197         }
198
199         if(found == 0) {
200                 info_t = malloc(sizeof(r_app_info_t));
201                 if (info_t == NULL) {
202                         _E("out of memory");
203                         goto END;
204                 }
205
206                 strncpy(info_t->pkg_name, appid, MAX_PACKAGE_STR_SIZE-1);
207                 info_t->pid = pid;
208                 r_app_info_list = g_slist_append(r_app_info_list, info_t);
209         }
210
211         for (iter = r_app_info_list; iter != NULL; iter = g_slist_next(iter))
212         {
213                 info_t = (r_app_info_t *)iter->data;
214         }
215
216         if(limit>0) __kill_bg_apps(limit);
217
218         for (iter = r_app_info_list; iter != NULL; iter = g_slist_next(iter))
219         {
220                 info_t = (r_app_info_t *)iter->data;
221         }
222
223 END:
224         pkgmgrinfo_appinfo_destroy_appinfo(handle);
225         return false;
226 }
227
228 static void __vconf_cb(keynode_t *key, void *data)
229 {
230         int limit;
231         const char *name;
232
233         name = vconf_keynode_get_name(key);
234         if( name == NULL ) {
235                 return;
236         }else if ( strcmp(name, VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS) == 0){
237                 limit = vconf_keynode_get_int(key);
238                 if(limit>0) __kill_bg_apps(limit);
239         }
240 }
241 #endif
242
243 #ifdef _APPFW_FEATURE_EXPANSION_PKG_INSTALL
244 static int __tep_unmount_dbus(char *mnt_path)
245 {
246         DBusMessage *msg;
247         msg = dbus_message_new_method_call(TEP_BUS_NAME, TEP_OBJECT_PATH,
248                                            TEP_INTERFACE_NAME, TEP_UNMOUNT_METHOD);
249         if (!msg) {
250                 _E("dbus_message_new_method_call(%s:%s-%s)", TEP_OBJECT_PATH,
251                    TEP_INTERFACE_NAME, TEP_UNMOUNT_METHOD);
252                 return -1;
253         }
254
255         if (!dbus_message_append_args(msg,
256                                       DBUS_TYPE_STRING, &mnt_path,
257                                       DBUS_TYPE_INVALID)) {
258                 _E("Ran out of memory while constructing args\n");
259                 dbus_message_unref(msg);
260                 return -1;
261         }
262
263         if (dbus_connection_send(conn, msg, NULL) == FALSE) {
264                 _E("dbus send error");
265                 dbus_message_unref(msg);
266                 return -1;
267         }
268         dbus_message_unref(msg);
269         return 0;
270 }
271
272 static void __send_unmount_request(int pid)
273 {
274         const char *tep_name = NULL;
275         const struct appinfo *ai = NULL;
276         char *appid = NULL;
277         appid = _status_app_get_appid_bypid(pid);
278         if (!appid) {
279                 _E("_status_app_get_appid_bypid : appid not found");
280                 return;
281         }
282         ai = appinfo_find(_laf, appid);
283         tep_name = appinfo_get_value(ai, AIT_TEP);
284         if (tep_name != NULL) {
285                 char tep_message[PATH_MAX] = {0, };
286                 const char *installed_storage = NULL;
287                 char *mnt_path = NULL;
288                 struct stat link_buf;
289
290                 installed_storage  = appinfo_get_value(ai, AIT_STORAGE_TYPE);
291                 if (installed_storage != NULL) {
292                         if (strncmp(installed_storage, "internal", 8) == 0) {
293                                 snprintf(tep_message, sizeof(tep_message), "%s%s/res/tep", appfw_env_get_apps_path(), appid);
294                                 mnt_path = strdup(tep_message);
295                         } else if (strncmp(installed_storage, "external", 8) == 0) {
296                                 snprintf(tep_message, sizeof(tep_message), "%step/tep-access", appfw_env_get_external_storage_path());
297                                 mnt_path = strdup(tep_message);
298                         }
299                         if (mnt_path) {
300                                 int ret = __tep_unmount_dbus(mnt_path);
301                                 if (ret < 0) {
302                                         _E("dbus call failed for unmount");
303                                 }
304                                 ret = lstat(mnt_path, &link_buf);
305                                 if (ret == 0) {
306                                         ret = unlink(mnt_path);
307                                         if (ret == 0)
308                                                 _D("Symbolic link removed");
309                                         else
310                                                 _E("Failed to remove the link");
311                                 }
312                                 free(mnt_path);
313                         }
314                 }
315         }
316 }
317 #endif
318
319 static int __app_dead_handler(int pid, void *data)
320 {
321         char trm_buf[MAX_PACKAGE_STR_SIZE];
322         char buf[MAX_LOCAL_BUFSZ];
323
324         _I("__app_dead_handler, pid: %d", pid);
325
326         if(pid <= 0)
327                 return 0;
328
329 #ifdef _APPFW_FEATURE_EXPANSION_PKG_INSTALL
330         __send_unmount_request(pid);
331 #endif
332
333         if (app_group_is_leader_pid(pid)) {
334                 if (app_group_find_second_leader(pid) == -1) {
335                         app_group_clear_top(pid);
336                         app_group_set_dead_pid(pid);
337                         app_group_remove(pid);
338                 } else
339                         app_group_remove_leader_pid(pid);
340         } else if (app_group_is_sub_app(pid)) {
341                 if (app_group_can_reroute(pid))
342                         app_group_reroute(pid);
343                 else
344                         app_group_clear_top(pid);
345                 app_group_set_dead_pid(pid);
346                 app_group_remove(pid);
347         }
348
349         app_group_remove_from_recycle_bin(pid);
350
351         _unregister_key_event(pid);
352 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
353         __remove_item_running_list(pid);
354 #endif
355         _revoke_temporary_permission(pid);
356         _status_remove_app_info_list(pid);
357         snprintf(trm_buf, MAX_PACKAGE_STR_SIZE, "appinfo_terminated:[PID]%d", pid);
358         __trm_app_info_send_socket(trm_buf);
359         aul_send_app_terminated_signal(pid);
360
361         snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d", AUL_SOCK_PREFIX, pid);
362         unlink(buf);
363
364 #ifdef _APPFW_FEATURE_AMD_MODULE_LOG
365         snprintf(buf, MAX_LOCAL_BUFSZ, "%d", pid);
366         _status_log_save("TERMINATED", buf);
367 #endif
368
369         return 0;
370 }
371
372 static void __start_cb(void *user_data,
373                 const char *filename, const struct appinfo *ai)
374 {
375         /*struct amdmgr *amd = user_data;*/
376         const char *componet = NULL;
377         int r;
378
379         componet = appinfo_get_value(ai, AIT_COMPTYPE);
380
381         r = appinfo_get_boolean(ai, AIT_ONBOOT);
382
383         if (r == 1 && componet && strncmp(componet, "svcapp", 6) == 0)
384         {
385                 const char *appid = appinfo_get_value(ai, AIT_NAME);
386 #ifdef _APPFW_FEATURE_ULTRA_POWER_SAVING_MODE
387                 r = appinfo_get_boolean(ai, AIT_PRELOAD);
388                 if (ups_mode == SETTING_PSMODE_EMERGENCY && r == 0) {
389                         _W("In UPS mode, skip to launch the servce apps");
390                         return;
391                 }
392 #endif
393                 if (appid && _status_app_is_running(appid) < 0)
394                 {
395                         _W("start service (on-boot) - %s", appid);
396                         _start_srv(ai);
397                 }
398                 else
399                 {
400                         _E("service: %s is already running", appid);
401                 }
402         }
403 }
404
405 static void _start_services(struct amdmgr *amd)
406 {
407 #ifdef _APPFW_FEATURE_ULTRA_POWER_SAVING_MODE
408         if(vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &ups_mode) < 0)
409                 _E("vconf_get_int() failed");
410 #endif
411
412         appinfo_foreach(amd->af, __start_cb, amd);
413 }
414
415 gboolean _get_platform_ready()
416 {
417         return platform_ready;
418 }
419
420 static gboolean __platform_ready_handler(gpointer data)
421 {
422         _E("[Info]__platform_ready_handler");
423         platform_ready = true;
424
425         return FALSE;
426 }
427
428 static int __booting_done_handler(int pid, void *data)
429 {
430         _E("[Info]__booting_done_handler, pid: %d", pid);
431
432         _start_services((struct amdmgr*)data);
433
434         guint timer_id = g_timeout_add(60000, __platform_ready_handler, NULL);
435         SECURE_LOGW("[Info] timer_id: %u", timer_id);
436
437         return 0;
438 }
439
440 static void __window_init(void)
441 {
442         _W("_window_init");
443
444         ecore_x_init(NULL);
445         _set_atom_effect();
446 #ifndef __i386__
447         _key_init();
448 #endif
449         window_initialized = 1;
450 }
451
452 int _window_is_initialized()
453 {
454         return window_initialized;
455 }
456
457 static Eina_Bool _window_cb(void *data, Ecore_Fd_Handler * fd_handler)
458 {
459         int fd;
460         char buf[FILENAME_MAX] = {0};
461         ssize_t len = 0;
462         struct inotify_event* event;
463
464         if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) {
465                 _E("An error has occurred. Stop watching this fd and quit");
466                 return ECORE_CALLBACK_CANCEL;
467         }
468
469         fd = ecore_main_fd_handler_fd_get(fd_handler);
470         if(fd < 0) {
471                 _E("ecore_main_fd_handler_fd_get error");
472                 return ECORE_CALLBACK_CANCEL;
473         }
474         len = read(fd, buf, FILENAME_MAX);
475         if (len < 0)
476                 _E("read failed, error [%s]", strerror(errno));;
477
478         event = (struct inotify_event*) &buf[0];
479
480         if(event)
481                 _D("filename : %s", event->name);
482
483         if (_status_check_window_ready()) {
484                 __window_init();
485                 if (win_info_t) {
486                         ecore_main_fd_handler_del(win_info_t->win_watch_ewd);
487                         inotify_rm_watch(win_info_t->watch_fd, win_info_t->win_watch_wd);
488                         free(win_info_t);
489                         win_info_t = NULL;
490                 }
491         }
492
493         return ECORE_CALLBACK_RENEW;
494 }
495
496 static void _register_window_init(void)
497 {
498         _W("_register_window_init");
499
500         win_info_t = malloc(sizeof(_window_watch_t));
501         if (!win_info_t) {
502                 _E("Unable to allocate memory. don't init widow\n");
503                 return;
504         }
505         win_info_t->watch_fd = inotify_init();
506         win_info_t->win_watch_wd = inotify_add_watch(win_info_t->watch_fd, "/tmp", IN_CREATE);
507         win_info_t->win_watch_ewd = ecore_main_fd_handler_add(win_info_t->watch_fd,
508                                                     ECORE_FD_READ, _window_cb, NULL, NULL, NULL);
509 }
510
511 static void _window_init(void)
512 {
513         if (_status_check_window_ready())
514                 __window_init();
515         else
516                 _register_window_init();
517 }
518
519 static int __init()
520 {
521         struct amdmgr amd;
522         int ret = 0;
523
524         /* sigprocmask() is used to fetch and/or change the signal mask of the calling thread.
525          * As a result, please make sure that there are not any other threads except for calling thread.
526          * */
527         int fd = _signal_block_sigchld();
528         assert(fd != -1);
529
530         ecore_init();
531         evas_init();
532         ecore_event_init();
533
534         _W("ecore init done\n");
535
536         ret = appinfo_init(&amd.af);
537         assert(ret == 0);
538
539         ret = _request_init(&amd, fd);
540         assert(ret == 0);
541
542         _launch_init(&amd);
543         _status_init(&amd);
544         _window_init();
545         app_group_init();
546
547         _W("AMD init done\n");
548
549 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
550         if (vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS, __vconf_cb, NULL) != 0) {
551                 _E("Unable to register callback for VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS\n");
552         }
553 #endif
554
555         aul_listen_app_dead_signal(__app_dead_handler, NULL);
556         aul_listen_booting_done_signal(__booting_done_handler, &amd);
557
558 #ifdef _APPFW_FEATURE_PRIORITY_CHANGE
559         int res = setpriority(PRIO_PROCESS, 0, -12);
560         if (res == -1)
561         {
562                 _E("Setting process (%d) priority to -12 failed, errno: %d (%s)",
563                                 getpid(), errno, strerror(errno));
564         }
565 #endif
566         return 0;
567 }
568
569 gboolean  __amd_ready(gpointer user_data)
570 {
571         _W("AMD ready\n");
572
573         int handle = creat("/tmp/amd_ready", S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
574         if (handle != -1)
575                 close(handle);
576
577         return FALSE;
578 }
579
580 int main(int argc, char *argv[])
581 {
582         _W("AMD main()\n");
583
584 #ifdef _APPFW_FEATURE_APP_CHECKER
585         if (ac_server_initialize() != AC_R_OK){
586                 _E("ac_server_initialize failed!\n");
587                 assert(0);
588                 return -1;
589         }
590 #endif
591         if (__init() != 0){
592                 assert(0);
593                 _E("AMD Initialization failed!\n");
594                 return -1;
595         }
596
597         g_idle_add(__amd_ready, NULL);
598
599         ecore_main_loop_begin();
600
601         return 0;
602 }