tizen 2.3 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                 strncpy(info_t->pkg_name, appid, MAX_PACKAGE_STR_SIZE-1);
214                 info_t->pid = pid;
215                 r_app_info_list = g_slist_append(r_app_info_list, info_t);
216         }
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         if(limit>0) __kill_bg_apps(limit);
224
225         for (iter = r_app_info_list; iter != NULL; iter = g_slist_next(iter))
226         {
227                 info_t = (r_app_info_t *)iter->data;
228         }
229
230 END:
231         pkgmgrinfo_appinfo_destroy_appinfo(handle);
232
233         free(item);
234         return false;
235 }
236
237 static void __vconf_cb(keynode_t *key, void *data)
238 {
239         int limit;
240         const char *name;
241
242         name = vconf_keynode_get_name(key);
243         if( name == NULL ) {
244                 return;
245         }else if ( strcmp(name, VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS) == 0){
246                 limit = vconf_keynode_get_int(key);
247                 if(limit>0) __kill_bg_apps(limit);
248         }
249 }
250 #endif
251
252 static int __app_dead_handler(int pid, void *data)
253 {
254         char trm_buf[MAX_PACKAGE_STR_SIZE];
255         char buf[MAX_LOCAL_BUFSZ];
256
257         _I("__app_dead_handler, pid: %d", pid);
258
259         if(pid <= 0)
260                 return 0;
261
262         _unregister_key_event(pid);
263 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
264         __remove_item_running_list(pid);
265 #endif
266         _status_remove_app_info_list(pid);
267         snprintf(trm_buf, MAX_PACKAGE_STR_SIZE, "appinfo_terminated:[PID]%d", pid);
268         __trm_app_info_send_socket(trm_buf);
269
270         snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d", AUL_SOCK_PREFIX, pid);
271         unlink(buf);
272
273         return 0;
274 }
275
276 static void __start_cb(void *user_data,
277                 const char *filename, const struct appinfo *ai)
278 {
279         /*struct amdmgr *amd = user_data;*/
280         const char *componet = NULL;
281         int r;
282
283         componet = appinfo_get_value(ai, AIT_COMPTYPE);
284
285         r = appinfo_get_boolean(ai, AIT_ONBOOT);
286
287         if (r == 1 && strncmp(componet, "svcapp", 6) == 0)
288         {
289                 const char *appid = appinfo_get_value(ai, AIT_NAME);
290                 if (_status_app_is_running(appid) < 0)
291                 {
292                         _I("start service (on-boot) - %s", appid);
293                         _start_srv(ai, NULL);
294                 }
295                 else
296                 {
297                         _E("service: %s is already running", appid);
298                 }
299         }
300 }
301
302 static void _start_services(struct amdmgr *amd)
303 {
304         appinfo_foreach(amd->af, __start_cb, amd);
305 }
306
307 gboolean _get_platform_ready()
308 {
309         return platform_ready;
310 }
311
312 static gboolean __platform_ready_handler(gpointer data)
313 {
314         _E("[Info]__platform_ready_handler");
315         platform_ready = true;
316
317         return FALSE;
318 }
319
320 static int __booting_done_handler(int pid, void *data)
321 {
322         guint timer_id;
323
324         _E("[Info]__booting_done_handler, pid: %d", pid);
325
326         _start_services((struct amdmgr*)data);
327
328         timer_id = g_timeout_add(60000, __platform_ready_handler, NULL);
329
330         return 0;
331 }
332
333 static gboolean _check_window_ready(void)
334 {
335         if (access(WINDOW_READY, R_OK) == 0)
336                 return true;
337         else
338                 return false;
339 }
340
341 static void __window_init(void)
342 {
343         _D("_window_init");
344
345         ecore_x_init(NULL);
346         _set_atom_effect();
347 #ifndef __i386__
348         _key_init();
349 #endif
350 }
351
352 static Eina_Bool _window_cb(void *data, Ecore_Fd_Handler * fd_handler)
353 {
354         int fd;
355         char buf[FILENAME_MAX];
356         ssize_t len = 0;
357         struct inotify_event* event;
358
359         if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) {
360                 _E("An error has occurred. Stop watching this fd and quit");
361                 return ECORE_CALLBACK_CANCEL;
362         }
363
364         fd = ecore_main_fd_handler_fd_get(fd_handler);
365         if(fd < 0) {
366                 _E("ecore_main_fd_handler_fd_get error");
367                 return ECORE_CALLBACK_CANCEL;
368         }
369         len = read(fd, buf, FILENAME_MAX);
370
371         event = (struct inotify_event*) &buf[0];
372
373         _D("filename : %s", event->name);
374
375         if (access(WINDOW_READY, R_OK) == 0) {
376                 __window_init();
377                 if (win_info_t) {
378                         ecore_main_fd_handler_del(win_info_t->win_watch_ewd);
379                         inotify_rm_watch(win_info_t->watch_fd, win_info_t->win_watch_wd);
380                         free(win_info_t);
381                         win_info_t = NULL;
382                 }
383         }
384
385         return ECORE_CALLBACK_RENEW;
386 }
387
388 static void _register_window_init(void)
389 {
390         _D("_register_window_init");
391
392         win_info_t = malloc(sizeof(_window_watch_t));
393         if (!win_info_t) {
394                 _E("Unable to allocate memory. don't init widow\n");
395                 return;
396         }
397         win_info_t->watch_fd = inotify_init();
398         win_info_t->win_watch_wd = inotify_add_watch(win_info_t->watch_fd, "/tmp", IN_CREATE);
399         win_info_t->win_watch_ewd = ecore_main_fd_handler_add(win_info_t->watch_fd,
400                                                     ECORE_FD_READ, _window_cb, NULL, NULL, NULL);
401 }
402
403 static void _window_init(void)
404 {
405         if (_check_window_ready())
406                 __window_init();
407         else
408                 _register_window_init();
409 }
410
411 static int __init()
412 {
413         struct amdmgr amd;
414         int ret = 0;
415
416         ecore_init();
417         evas_init();
418         ecore_event_init();
419
420         _D("ecore init done\n");
421
422         ret = appinfo_init(&amd.af);
423         assert(ret == 0);
424
425         ret = cgutil_create(MOUNT_PATH, AGENT_PATH, &amd.cg);
426         assert(ret == 0);
427
428         ret = _request_init(&amd);
429         assert(ret == 0);
430
431         _launch_init(&amd);
432         _status_init(&amd);
433         _window_init();
434
435         _D("AMD init done\n");
436
437 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
438         if (vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS, __vconf_cb, NULL) != 0) {
439                 _E("Unable to register callback for VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS\n");
440         }
441 #endif
442
443         aul_listen_app_dead_signal(__app_dead_handler, NULL);
444         aul_listen_booting_done_signal(__booting_done_handler, &amd);
445
446 #ifdef _APPFW_FEATURE_PRIORITY_CHANGE
447         int res = setpriority(PRIO_PROCESS, 0, -12);
448         if (res == -1)
449         {
450                 SECURE_LOGE("Setting process (%d) priority to -12 failed, errno: %d (%s)",
451                                 getpid(), errno, strerror(errno));
452         }
453 #endif
454         return 0;
455 }
456
457 gboolean  __amd_ready(gpointer user_data)
458 {
459         _D("AMD ready\n");
460
461         int handle = creat("/tmp/amd_ready", S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
462         if (handle != -1)
463                 close(handle);
464
465         return FALSE;
466 }
467
468 int main(int argc, char *argv[])
469 {
470         _D("AMD main()\n");
471
472 #ifdef _APPFW_FEATURE_APP_CHECKER
473         if (ac_server_initialize() != AC_R_OK){
474                 _E("ac_server_initialize failed!\n");
475                 assert(0);
476                 return -1;
477         }
478 #endif
479         if (__init() != 0){
480                 assert(0);
481                 _E("AMD Initialization failed!\n");
482                 return -1;
483         }
484
485         g_idle_add(__amd_ready, NULL);
486
487         ecore_main_loop_begin();
488
489         return 0;
490 }