tizen 2.3.1 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 #include <stdio.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <sys/inotify.h>
26 #include <fcntl.h>
27 #include <Ecore_X.h>
28 #include <Ecore_Input.h>
29 #include <utilX.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_cgutil.h"
49 #include "amd_key.h"
50 #include "amd_status.h"
51 #include "amd_launch.h"
52 #include "amd_request.h"
53
54 #ifndef MOUNT_PATH
55 #  define MOUNT_PATH "/sys/fs/cgroup"
56 #endif
57
58 #ifndef AGENT_PATH
59 #  define AGENT_PATH "/usr/bin/daemon-manager-release-agent"
60 #endif
61
62 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
63 typedef struct _r_app_info_t{
64         char pkg_name[MAX_PACKAGE_STR_SIZE];
65         int pid;
66 } r_app_info_t;
67
68 GSList *r_app_info_list = NULL;
69 #endif
70
71 gboolean platform_ready = false;
72
73 #define WINDOW_READY    "/tmp/.wm_ready"
74
75 typedef struct _window_watch {
76         int watch_fd;
77         int win_watch_wd;
78         Ecore_Fd_Handler *win_watch_ewd;
79 } _window_watch_t;
80 static _window_watch_t *win_info_t = NULL;
81
82 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
83 static void __vconf_cb(keynode_t *key, void *data);
84 #endif
85 static int __app_dead_handler(int pid, void *data);
86 static int __init();
87
88 extern int _status_init(struct amdmgr* amd);
89
90 static int __send_to_sigkill(int pid)
91 {
92         int pgid;
93
94         _D("__send_to_sigkill, pid: %d", pid);
95
96         pgid = getpgid(pid);
97         if (pgid <= 1)
98                 return -1;
99
100         if (killpg(pgid, SIGKILL) < 0)
101                 return -1;
102
103         return 0;
104 }
105
106 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
107 static int __kill_bg_apps(int limit)
108 {
109         int len;
110         int i;
111         int n;
112         r_app_info_t *info_t = NULL;
113         GSList *iter = NULL;
114
115         len = g_slist_length(r_app_info_list);
116
117         n = len - limit;
118
119         if (n<=0) return 0;
120
121         for ( i=0, iter = r_app_info_list; i<n ; i++) {
122                 info_t = (r_app_info_t *)iter->data;
123                 //__send_to_sigkill(info_t->pid);
124                 proc_group_change_status(PROC_CGROUP_SET_TERMINATE_REQUEST, info_t->pid, NULL);
125                 _term_app(info_t->pid, 0);
126                 iter = g_slist_next(iter);
127                 r_app_info_list = g_slist_remove(r_app_info_list, info_t);
128                 free(info_t);
129         }
130
131         return 0;
132 }
133
134 static int __remove_item_running_list(int pid)
135 {
136         r_app_info_t *info_t = NULL;
137         GSList *iter = NULL;
138
139         for (iter = r_app_info_list; iter != NULL; iter = g_slist_next(iter))
140         {
141                 info_t = (r_app_info_t *)iter->data;
142                 if(pid == info_t->pid) {
143                         r_app_info_list = g_slist_remove(r_app_info_list, info_t);
144                         free(info_t);
145                         break;
146                 }
147         }
148         return 0;
149 }
150
151 gboolean __add_item_running_list(gpointer user_data)
152 {
153
154         bool taskmanage;
155         pkgmgrinfo_appinfo_h handle = NULL;
156         int ret = 0;
157         r_app_info_t *info_t = NULL;
158         GSList *iter = NULL;
159         int found = 0;
160         int limit;
161
162         item_pkt_t *item  = (item_pkt_t *)user_data;
163         if (item == NULL) {
164                 return false;
165         }
166
167         char* appid = item->appid;
168         int pid = item->pid;
169
170         SECURE_LOGD("__add_item_running_list pid: %d", pid);
171
172         if (vconf_get_int(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS, &limit) != 0){
173                 _E("Unable to get VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS\n");
174         }
175
176         if (appid == NULL) {
177                 return false;
178         } else if (strncmp(appid, "org.tizen.cluster-home", 24) == 0) {
179                 if(limit>0) __kill_bg_apps(limit-1);
180                 return false;
181         }
182
183         SECURE_LOGD("__add_item_running_list appid: %s", appid);
184
185         ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle);
186         if (ret != PMINFO_R_OK) {
187                 _E("pkgmgrinfo_pkginfo_get_pkginfo with %s failed", appid);
188                 return false;
189         }
190
191         ret = pkgmgrinfo_appinfo_is_taskmanage(handle, &taskmanage);
192         if (ret != PMINFO_R_OK) {
193                 _E("pkgmgrinfo_appinfo_is_taskmanage failed");
194                 goto END;
195         }
196
197         if (taskmanage == false)
198                 goto END;
199
200         for (iter = r_app_info_list; iter != NULL; iter = g_slist_next(iter))
201         {
202                 info_t = (r_app_info_t *)iter->data;
203                 if(pid == info_t->pid) {
204                         found = 1;
205                         r_app_info_list = g_slist_remove(r_app_info_list, info_t);
206                         r_app_info_list = g_slist_append(r_app_info_list, info_t);
207                         break;
208                 }
209         }
210
211         if(found == 0) {
212                 info_t = malloc(sizeof(r_app_info_t));
213                 if (info_t == NULL) {
214                         _E("out of memory");
215                         goto END;
216                 }
217
218                 strncpy(info_t->pkg_name, appid, MAX_PACKAGE_STR_SIZE-1);
219                 info_t->pid = pid;
220                 r_app_info_list = g_slist_append(r_app_info_list, info_t);
221         }
222
223         for (iter = r_app_info_list; iter != NULL; iter = g_slist_next(iter))
224         {
225                 info_t = (r_app_info_t *)iter->data;
226         }
227
228         if(limit>0) __kill_bg_apps(limit);
229
230         for (iter = r_app_info_list; iter != NULL; iter = g_slist_next(iter))
231         {
232                 info_t = (r_app_info_t *)iter->data;
233         }
234
235 END:
236         pkgmgrinfo_appinfo_destroy_appinfo(handle);
237
238         free(item);
239         return false;
240 }
241
242 static void __vconf_cb(keynode_t *key, void *data)
243 {
244         int limit;
245         const char *name;
246
247         name = vconf_keynode_get_name(key);
248         if( name == NULL ) {
249                 return;
250         }else if ( strcmp(name, VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS) == 0){
251                 limit = vconf_keynode_get_int(key);
252                 if(limit>0) __kill_bg_apps(limit);
253         }
254 }
255 #endif
256
257 static int __app_dead_handler(int pid, void *data)
258 {
259         char trm_buf[MAX_PACKAGE_STR_SIZE];
260         char buf[MAX_LOCAL_BUFSZ];
261
262         _I("__app_dead_handler, pid: %d", pid);
263
264         if(pid <= 0)
265                 return 0;
266
267         _unregister_key_event(pid);
268 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
269         __remove_item_running_list(pid);
270 #endif
271         _status_remove_app_info_list(pid);
272         snprintf(trm_buf, MAX_PACKAGE_STR_SIZE, "appinfo_terminated:[PID]%d", pid);
273         __trm_app_info_send_socket(trm_buf);
274
275         snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d", AUL_SOCK_PREFIX, pid);
276         unlink(buf);
277
278         return 0;
279 }
280
281 static void __start_cb(void *user_data,
282                 const char *filename, const struct appinfo *ai)
283 {
284         /*struct amdmgr *amd = user_data;*/
285         const char *componet = NULL;
286         int r;
287
288         componet = appinfo_get_value(ai, AIT_COMPTYPE);
289
290         r = appinfo_get_boolean(ai, AIT_ONBOOT);
291
292         if (r == 1 && componet && strncmp(componet, "svcapp", 6) == 0)
293         {
294                 const char *appid = appinfo_get_value(ai, AIT_NAME);
295                 if (appid && _status_app_is_running(appid) < 0)
296                 {
297                         _I("start service (on-boot) - %s", appid);
298                         _start_srv(ai, NULL);
299                 }
300                 else
301                 {
302                         _E("service: %s is already running", appid);
303                 }
304         }
305 }
306
307 static void _start_services(struct amdmgr *amd)
308 {
309         appinfo_foreach(amd->af, __start_cb, amd);
310 }
311
312 gboolean _get_platform_ready()
313 {
314         return platform_ready;
315 }
316
317 static gboolean __platform_ready_handler(gpointer data)
318 {
319         _E("[Info]__platform_ready_handler");
320         platform_ready = true;
321
322         return FALSE;
323 }
324
325 static int __booting_done_handler(int pid, void *data)
326 {
327         guint timer_id;
328
329         _E("[Info]__booting_done_handler, pid: %d", pid);
330
331         _start_services((struct amdmgr*)data);
332
333         timer_id = g_timeout_add(60000, __platform_ready_handler, NULL);
334
335         return 0;
336 }
337
338 static gboolean _check_window_ready(void)
339 {
340         if (access(WINDOW_READY, R_OK) == 0)
341                 return true;
342         else
343                 return false;
344 }
345
346 static void __window_init(void)
347 {
348         _D("_window_init");
349
350         ecore_x_init(NULL);
351         _set_atom_effect();
352 #ifndef __i386__
353         _key_init();
354 #endif
355 }
356
357 static Eina_Bool _window_cb(void *data, Ecore_Fd_Handler * fd_handler)
358 {
359         int fd;
360         char buf[FILENAME_MAX];
361         ssize_t len = 0;
362         struct inotify_event* event;
363
364         if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) {
365                 _E("An error has occurred. Stop watching this fd and quit");
366                 return ECORE_CALLBACK_CANCEL;
367         }
368
369         fd = ecore_main_fd_handler_fd_get(fd_handler);
370         if(fd < 0) {
371                 _E("ecore_main_fd_handler_fd_get error");
372                 return ECORE_CALLBACK_CANCEL;
373         }
374         len = read(fd, buf, FILENAME_MAX);
375
376         event = (struct inotify_event*) &buf[0];
377
378         _D("filename : %s", event->name);
379
380         if (access(WINDOW_READY, R_OK) == 0) {
381                 __window_init();
382                 if (win_info_t) {
383                         ecore_main_fd_handler_del(win_info_t->win_watch_ewd);
384                         inotify_rm_watch(win_info_t->watch_fd, win_info_t->win_watch_wd);
385                         free(win_info_t);
386                         win_info_t = NULL;
387                 }
388         }
389
390         return ECORE_CALLBACK_RENEW;
391 }
392
393 static void _register_window_init(void)
394 {
395         _D("_register_window_init");
396
397         win_info_t = malloc(sizeof(_window_watch_t));
398         if (!win_info_t) {
399                 _E("Unable to allocate memory. don't init widow\n");
400                 return;
401         }
402         win_info_t->watch_fd = inotify_init();
403         win_info_t->win_watch_wd = inotify_add_watch(win_info_t->watch_fd, "/tmp", IN_CREATE);
404         win_info_t->win_watch_ewd = ecore_main_fd_handler_add(win_info_t->watch_fd,
405                                                     ECORE_FD_READ, _window_cb, NULL, NULL, NULL);
406 }
407
408 static void _window_init(void)
409 {
410         if (_check_window_ready())
411                 __window_init();
412         else
413                 _register_window_init();
414 }
415
416 static int __init()
417 {
418         struct amdmgr amd;
419         int ret = 0;
420
421         ecore_init();
422         evas_init();
423         ecore_event_init();
424
425         _D("ecore init done\n");
426
427         ret = appinfo_init(&amd.af);
428         assert(ret == 0);
429
430         ret = cgutil_create(MOUNT_PATH, AGENT_PATH, &amd.cg);
431         assert(ret == 0);
432
433         ret = _request_init(&amd);
434         assert(ret == 0);
435
436         _launch_init(&amd);
437         _status_init(&amd);
438         _window_init();
439
440         _D("AMD init done\n");
441
442 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
443         if (vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS, __vconf_cb, NULL) != 0) {
444                 _E("Unable to register callback for VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS\n");
445         }
446 #endif
447
448         aul_listen_app_dead_signal(__app_dead_handler, NULL);
449         aul_listen_booting_done_signal(__booting_done_handler, &amd);
450
451 #ifdef _APPFW_FEATURE_PRIORITY_CHANGE
452         int res = setpriority(PRIO_PROCESS, 0, -12);
453         if (res == -1)
454         {
455                 SECURE_LOGE("Setting process (%d) priority to -12 failed, errno: %d (%s)",
456                                 getpid(), errno, strerror(errno));
457         }
458 #endif
459         return 0;
460 }
461
462 gboolean  __amd_ready(gpointer user_data)
463 {
464         _D("AMD ready\n");
465
466         int handle = creat("/tmp/amd_ready", S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
467         if (handle != -1)
468                 close(handle);
469
470         return FALSE;
471 }
472
473 int main(int argc, char *argv[])
474 {
475         _D("AMD main()\n");
476
477 #ifdef _APPFW_FEATURE_APP_CHECKER
478         if (ac_server_initialize() != AC_R_OK){
479                 _E("ac_server_initialize failed!\n");
480                 assert(0);
481                 return -1;
482         }
483 #endif
484         if (__init() != 0){
485                 assert(0);
486                 _E("AMD Initialization failed!\n");
487                 return -1;
488         }
489
490         g_idle_add(__amd_ready, NULL);
491
492         ecore_main_loop_begin();
493
494         return 0;
495 }