Tizen 2.4 SDK Rev6 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         _W("__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                 _W("app_group_leader_app, pid: %d", pid);
335                 if (app_group_find_second_leader(pid) == -1) {
336                         app_group_clear_top(pid);
337                         app_group_set_dead_pid(pid);
338                         app_group_remove(pid);
339                 } else
340                         app_group_remove_leader_pid(pid);
341         } else if (app_group_is_sub_app(pid)) {
342                 _W("app_group_sub_app, pid: %d", pid);
343                 int caller_pid = app_group_get_next_caller_pid(pid);
344
345                 if (app_group_can_reroute(pid) || (caller_pid > 0 && caller_pid != pid)) {
346                         _W("app_group reroute");
347                         app_group_reroute(pid);
348                 } else {
349                         _W("app_group clear top");
350                         app_group_clear_top(pid);
351                 }
352                 app_group_set_dead_pid(pid);
353                 app_group_remove(pid);
354         }
355
356         app_group_remove_from_recycle_bin(pid);
357
358         _unregister_key_event(pid);
359 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
360         __remove_item_running_list(pid);
361 #endif
362         _revoke_temporary_permission(pid);
363         _status_remove_app_info_list(pid);
364         snprintf(trm_buf, MAX_PACKAGE_STR_SIZE, "appinfo_terminated:[PID]%d", pid);
365         __trm_app_info_send_socket(trm_buf);
366         aul_send_app_terminated_signal(pid);
367
368         snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d", AUL_SOCK_PREFIX, pid);
369         unlink(buf);
370
371 #ifdef _APPFW_FEATURE_AMD_MODULE_LOG
372         snprintf(buf, MAX_LOCAL_BUFSZ, "%d", pid);
373         _status_log_save("TERMINATED", buf);
374 #endif
375
376         return 0;
377 }
378
379 static void __start_cb(void *user_data,
380                 const char *filename, const struct appinfo *ai)
381 {
382         /*struct amdmgr *amd = user_data;*/
383         const char *componet = NULL;
384         int r;
385
386         componet = appinfo_get_value(ai, AIT_COMPTYPE);
387
388         r = appinfo_get_boolean(ai, AIT_ONBOOT);
389
390         if (r == 1 && componet && strncmp(componet, "svcapp", 6) == 0)
391         {
392                 const char *appid = appinfo_get_value(ai, AIT_NAME);
393 #ifdef _APPFW_FEATURE_ULTRA_POWER_SAVING_MODE
394                 r = appinfo_get_boolean(ai, AIT_PRELOAD);
395                 if (ups_mode == SETTING_PSMODE_EMERGENCY && r == 0) {
396                         _W("In UPS mode, skip to launch the servce apps");
397                         return;
398                 }
399 #endif
400                 if (appid && _status_app_is_running(appid) < 0)
401                 {
402                         _W("start service (on-boot) - %s", appid);
403                         _start_srv(ai);
404                 }
405                 else
406                 {
407                         _E("service: %s is already running", appid);
408                 }
409         }
410 }
411
412 static void _start_services(struct amdmgr *amd)
413 {
414 #ifdef _APPFW_FEATURE_ULTRA_POWER_SAVING_MODE
415         if(vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &ups_mode) < 0)
416                 _E("vconf_get_int() failed");
417 #endif
418
419         appinfo_foreach(amd->af, __start_cb, amd);
420 }
421
422 gboolean _get_platform_ready()
423 {
424         return platform_ready;
425 }
426
427 static gboolean __platform_ready_handler(gpointer data)
428 {
429         _E("[Info]__platform_ready_handler");
430         platform_ready = true;
431
432         return FALSE;
433 }
434
435 static int __booting_done_handler(int pid, void *data)
436 {
437         _E("[Info]__booting_done_handler, pid: %d", pid);
438
439         _start_services((struct amdmgr*)data);
440
441         guint timer_id = g_timeout_add(60000, __platform_ready_handler, NULL);
442         SECURE_LOGW("[Info] timer_id: %u", timer_id);
443
444         return 0;
445 }
446
447 static void __window_init(void)
448 {
449         _W("_window_init");
450
451         ecore_x_init(NULL);
452         _set_atom_effect();
453         _key_init();
454         window_initialized = 1;
455 }
456
457 int _window_is_initialized()
458 {
459         return window_initialized;
460 }
461
462 static Eina_Bool _window_cb(void *data, Ecore_Fd_Handler * fd_handler)
463 {
464         int fd;
465         char buf[FILENAME_MAX] = {0};
466         ssize_t len = 0;
467         struct inotify_event* event;
468
469         if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) {
470                 _E("An error has occurred. Stop watching this fd and quit");
471                 return ECORE_CALLBACK_CANCEL;
472         }
473
474         fd = ecore_main_fd_handler_fd_get(fd_handler);
475         if(fd < 0) {
476                 _E("ecore_main_fd_handler_fd_get error");
477                 return ECORE_CALLBACK_CANCEL;
478         }
479         len = read(fd, buf, FILENAME_MAX);
480         if (len < 0)
481                 _E("read failed, error [%s]", strerror(errno));;
482
483         event = (struct inotify_event*) &buf[0];
484
485         if(event)
486                 _D("filename : %s", event->name);
487
488         if (_status_check_window_ready()) {
489                 __window_init();
490                 if (win_info_t) {
491                         ecore_main_fd_handler_del(win_info_t->win_watch_ewd);
492                         inotify_rm_watch(win_info_t->watch_fd, win_info_t->win_watch_wd);
493                         free(win_info_t);
494                         win_info_t = NULL;
495                 }
496         }
497
498         return ECORE_CALLBACK_RENEW;
499 }
500
501 static void _register_window_init(void)
502 {
503         _W("_register_window_init");
504
505         win_info_t = malloc(sizeof(_window_watch_t));
506         if (!win_info_t) {
507                 _E("Unable to allocate memory. don't init widow\n");
508                 return;
509         }
510         win_info_t->watch_fd = inotify_init();
511         win_info_t->win_watch_wd = inotify_add_watch(win_info_t->watch_fd, "/tmp", IN_CREATE);
512         win_info_t->win_watch_ewd = ecore_main_fd_handler_add(win_info_t->watch_fd,
513                                                     ECORE_FD_READ, _window_cb, NULL, NULL, NULL);
514 }
515
516 static void _window_init(void)
517 {
518         if (_status_check_window_ready())
519                 __window_init();
520         else
521                 _register_window_init();
522 }
523
524 static int __init()
525 {
526         struct amdmgr amd;
527         int ret = 0;
528
529         /* sigprocmask() is used to fetch and/or change the signal mask of the calling thread.
530          * As a result, please make sure that there are not any other threads except for calling thread.
531          * */
532         int fd = _signal_block_sigchld();
533         assert(fd != -1);
534
535         ecore_init();
536         evas_init();
537         ecore_event_init();
538
539         _W("ecore init done\n");
540
541         ret = appinfo_init(&amd.af);
542         assert(ret == 0);
543
544         ret = _request_init(&amd, fd);
545         assert(ret == 0);
546
547         _launch_init(&amd);
548         _status_init(&amd);
549         _window_init();
550         app_group_init();
551
552         _W("AMD init done\n");
553
554 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
555         if (vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS, __vconf_cb, NULL) != 0) {
556                 _E("Unable to register callback for VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS\n");
557         }
558 #endif
559
560         aul_listen_app_dead_signal(__app_dead_handler, NULL);
561         aul_listen_booting_done_signal(__booting_done_handler, &amd);
562
563 #ifdef _APPFW_FEATURE_PRIORITY_CHANGE
564         int res = setpriority(PRIO_PROCESS, 0, -12);
565         if (res == -1)
566         {
567                 _E("Setting process (%d) priority to -12 failed, errno: %d (%s)",
568                                 getpid(), errno, strerror(errno));
569         }
570 #endif
571         return 0;
572 }
573
574 gboolean  __amd_ready(gpointer user_data)
575 {
576         _W("AMD ready\n");
577
578         int handle = creat("/tmp/amd_ready", S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
579         if (handle != -1)
580                 close(handle);
581
582         return FALSE;
583 }
584
585 int main(int argc, char *argv[])
586 {
587         _W("AMD main()\n");
588
589 #ifdef _APPFW_FEATURE_APP_CHECKER
590         if (ac_server_initialize() != AC_R_OK){
591                 _E("ac_server_initialize failed!\n");
592                 assert(0);
593                 return -1;
594         }
595 #endif
596         if (__init() != 0){
597                 assert(0);
598                 _E("AMD Initialization failed!\n");
599                 return -1;
600         }
601
602         g_idle_add(__amd_ready, NULL);
603
604         ecore_main_loop_begin();
605
606         return 0;
607 }