4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
28 #include <proc_stat.h>
29 #include <pkgmgr-info.h>
30 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
32 #include <vconf/vconf.h>
35 #include "amd_config.h"
36 #include "amd_status.h"
37 #include "amd_appinfo.h"
39 #include "simple_util.h"
41 #include "menu_db_util.h"
43 GSList *app_status_info_list = NULL;
44 struct appinfomgr *_saf = NULL;
46 GHashTable *cooldown_tbl;
48 GHashTable *cooldown_black_tbl;
50 char *cooldown_list[] = {
53 char *cooldown_black_list[] = {
56 int cooldown_status = 0;
58 #define WHITE_LIST_COUNT 0
59 #define BLACK_LIST_COUNT 0
61 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
62 #define LCD_ON "LCDOn"
63 #define LCD_OFF "LCDOff"
65 #define WAKE_UP_GESTURE_CLOCK 1
68 int _status_add_app_info_list(char *appid, char *app_path, const char *caller, int pid, int pad_pid)
71 app_status_info_t *info_t = NULL;
73 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
75 info_t = (app_status_info_t *)iter->data;
76 if(pid == info_t->pid) {
81 info_t = malloc(sizeof(app_status_info_t));
82 memset(info_t, 0, sizeof(app_status_info_t));
84 strncpy(info_t->appid, appid, MAX_PACKAGE_STR_SIZE-1);
85 strncpy(info_t->app_path, app_path, MAX_PACKAGE_APP_PATH_SIZE-1);
87 strncpy(info_t->caller, caller, MAX_PACKAGE_STR_SIZE-1);
88 info_t->status = STATUS_LAUNCHING;
90 info_t->pad_pid = pad_pid;
91 app_status_info_list = g_slist_append(app_status_info_list, info_t);
93 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
95 info_t = (app_status_info_t *)iter->data;
97 //SECURE_LOGD("%s, %d, %d", info_t->appid, info_t->pid, info_t->status);
103 static Eina_Bool __app_terminate_timer_cb(void *data)
110 ret = kill(pid, SIGKILL);
112 _D("send SIGKILL: %s", strerror(errno));
114 return ECORE_CALLBACK_CANCEL;
117 int _status_update_app_info_list(int pid, int status)
120 app_status_info_t *info_t = NULL;
122 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
124 info_t = (app_status_info_t *)iter->data;
125 if(pid == info_t->pid) {
126 info_t->status = status;
127 if(status == STATUS_DYING) {
128 if(info_t->pad_pid != DEBUG_LAUNCHPAD_PID)
129 ecore_timer_add(2, __app_terminate_timer_cb, info_t->pid);
135 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
137 info_t = (app_status_info_t *)iter->data;
139 //SECURE_LOGD("%s, %d, %d", info_t->appid, info_t->pid, info_t->status);
145 int _status_remove_app_info_list(int pid)
148 app_status_info_t *info_t = NULL;
150 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
152 info_t = (app_status_info_t *)iter->data;
153 if(pid == info_t->pid) {
154 app_status_info_list = g_slist_remove(app_status_info_list, info_t);
160 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
162 info_t = (app_status_info_t *)iter->data;
164 //SECURE_LOGD("%s, %d, %d", info_t->appid, info_t->pid, info_t->status);
170 int _status_get_app_info_status(int pid)
173 app_status_info_t *info_t = NULL;
175 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
177 info_t = (app_status_info_t *)iter->data;
178 if(pid == info_t->pid) {
179 return info_t->status;
187 int _status_app_is_running(char *appid)
190 app_status_info_t *info_t = NULL;
192 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
194 info_t = (app_status_info_t *)iter->data;
195 if( strncmp(appid, info_t->appid, MAX_PACKAGE_STR_SIZE) == 0 ) {
202 char* _status_app_get_appid_bypid(int pid)
205 app_status_info_t *info_t = NULL;
207 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
209 info_t = (app_status_info_t *)iter->data;
210 if( pid == info_t->pid ) {
211 return info_t->appid;
217 char* _status_get_caller_by_appid(const char *appid)
220 app_status_info_t *info_t = NULL;
222 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
224 info_t = (app_status_info_t *)iter->data;
225 if( strncmp(appid, info_t->appid, MAX_PACKAGE_STR_SIZE-1) == 0) {
226 return info_t->caller;
233 int _status_send_running_appinfo(int fd)
236 app_status_info_t *info_t = NULL;
237 app_pkt_t *pkt = NULL;
239 char tmp_pid[MAX_PID_STR_BUFSZ];
241 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
247 memset(pkt, 0, AUL_SOCK_MAXBUFF);
249 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
251 info_t = (app_status_info_t *)iter->data;
252 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", info_t->pid);
253 strncat((char *)pkt->data, tmp_pid, MAX_PID_STR_BUFSZ);
254 strncat((char *)pkt->data, ":", 1);
255 strncat((char *)pkt->data, info_t->appid, MAX_PACKAGE_STR_SIZE);
256 strncat((char *)pkt->data, ":", 1);
257 strncat((char *)pkt->data, info_t->app_path, MAX_PACKAGE_APP_PATH_SIZE);
258 strncat((char *)pkt->data, ";", 1);
261 pkt->cmd = APP_RUNNING_INFO_RESULT;
262 pkt->len = strlen((char *)pkt->data) + 1;
264 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
266 _E("send failed due to EPIPE.\n");
267 _E("send fail to client");
278 int _status_app_is_running_v2(char *appid)
280 char *apppath = NULL;
283 const struct appinfo *ai;
288 ai = appinfo_find(_saf, appid);
293 apppath = strdup(appinfo_get_value(ai, AIT_EXEC));
295 /*truncate apppath if it includes default bundles */
296 while (apppath[i] != 0) {
297 if (apppath[i] == ' ' || apppath[i] == '\t') {
304 ret = __proc_iter_cmdline(NULL, apppath);
311 static int __get_pkginfo(const char *dname, const char *cmdline, void *priv)
313 app_info_from_db *menu_info;
316 r_info = (char *)priv;
318 if ((menu_info = _get_app_info_from_db_by_apppath(cmdline)) == NULL)
321 strncat(r_info, dname, 8);
322 strncat(r_info, ":", 1);
323 strncat(r_info, _get_pkgname(menu_info), MAX_PACKAGE_STR_SIZE);
324 strncat(r_info, ":", 1);
325 strncat(r_info, _get_app_path(menu_info), MAX_PACKAGE_APP_PATH_SIZE);
326 strncat(r_info, ";", 1);
330 if (menu_info != NULL)
331 _free_app_info_from_db(menu_info);
335 int _status_send_running_appinfo_v2(int fd)
337 app_pkt_t *pkt = NULL;
340 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
347 memset(pkt, 0, AUL_SOCK_MAXBUFF);
349 __proc_iter_cmdline(__get_pkginfo, pkt->data);
351 pkt->cmd = APP_RUNNING_INFO_RESULT;
352 pkt->len = strlen((char *)pkt->data) + 1;
354 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
356 _E("send failed due to EPIPE.\n");
357 _E("send fail to client");
368 static int __get_pkgname_bypid(int pid, char *pkgname, int len)
371 app_info_from_db *menu_info;
373 cmdline = __proc_get_cmdline_bypid(pid);
377 if ((menu_info = _get_app_info_from_db_by_apppath(cmdline)) == NULL) {
381 snprintf(pkgname, len, "%s", _get_pkgname(menu_info));
385 _free_app_info_from_db(menu_info);
390 int _status_get_appid_bypid(int fd, int pid)
392 app_pkt_t *pkt = NULL;
396 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
403 memset(pkt, 0, AUL_SOCK_MAXBUFF);
405 pkt->cmd = APP_GET_INFO_ERROR;
407 if (__get_pkgname_bypid(pid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0) {
408 SECURE_LOGD("appid for %d is %s", pid, pkt->data);
409 pkt->cmd = APP_GET_INFO_OK;
412 /* support app launched by shell script*/
418 _D("second change pgid = %d, pid = %d", pgid, pid);
419 if (__get_pkgname_bypid(pgid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0)
420 pkt->cmd = APP_GET_INFO_OK;
423 pkt->len = strlen((char *)pkt->data) + 1;
425 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
427 _E("send failed due to EPIPE.\n");
428 _E("send fail to client");
439 static int __get_pkgid_bypid(int pid, char *pkgid, int len)
442 app_info_from_db *menu_info;
444 cmdline = __proc_get_cmdline_bypid(pid);
448 if ((menu_info = _get_app_info_from_db_by_apppath(cmdline)) == NULL) {
452 snprintf(pkgid, len, "%s", _get_pkgid(menu_info));
455 _free_app_info_from_db(menu_info);
460 int _status_get_pkgid_bypid(int fd, int pid)
462 app_pkt_t *pkt = NULL;
466 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
473 memset(pkt, 0, AUL_SOCK_MAXBUFF);
475 pkt->cmd = APP_GET_INFO_ERROR;
477 if (__get_pkgid_bypid(pid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0) {
478 SECURE_LOGD("appid for %d is %s", pid, pkt->data);
479 pkt->cmd = APP_GET_INFO_OK;
482 /* support app launched by shell script*/
488 _D("second change pgid = %d, pid = %d", pgid, pid);
489 if (__get_pkgid_bypid(pgid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0)
490 pkt->cmd = APP_GET_INFO_OK;
493 pkt->len = strlen((char *)pkt->data) + 1;
495 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
497 _E("send failed due to EPIPE.\n");
498 _E("send fail to client");
509 static void __app_info_iter_limit_cb(void *user_data, const char *appid, const struct appinfo *ai)
511 if(!g_hash_table_lookup(cooldown_tbl, appid)) {
512 appinfo_set_value(ai, AIT_STATUS, "blocking");
516 static void __app_info_iter_waring_cb(void *user_data, const char *appid, const struct appinfo *ai)
518 if(g_hash_table_lookup(cooldown_black_tbl, appid)) {
519 appinfo_set_value(ai, AIT_STATUS, "blocking");
523 static void __app_info_iter_release_cb(void *user_data, const char *appid, const struct appinfo *ai)
525 const char *component = NULL;
529 if(!g_hash_table_lookup(cooldown_tbl, appid)) {
530 component = appinfo_get_value(ai, AIT_COMPTYPE);
531 onboot = appinfo_get_boolean(ai, AIT_ONBOOT);
532 restart = appinfo_get_boolean(ai, AIT_RESTART);
533 if (onboot == 1 && restart == 1 && strncmp(component, "svcapp", 6) == 0)
535 if (_status_app_is_running(appid) < 0)
537 _I("start service (cooldown release) - %s", appid);
538 _start_srv(ai, NULL);
542 _E("service: %s is already running", appid);
545 appinfo_set_value(ai, AIT_STATUS, "installed");
551 static int __cooldown_cb(const char* status, void *data)
554 app_status_info_t *info_t = NULL;
558 _I("__cooldown_cb, status: %s", status);
560 if(strncmp(status, "LimitAction", 11) == 0) {
561 appinfo_foreach(_saf, __app_info_iter_limit_cb, NULL);
562 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
564 info_t = (app_status_info_t *)iter->data;
565 if(!g_hash_table_lookup(cooldown_tbl, info_t->appid)) {
566 proc_group_change_status(PROC_CGROUP_SET_TERMINATE_REQUEST, info_t->pid, NULL);
567 ret = __app_send_raw_with_noreply(info_t->pid, APP_TERM_BY_PID_ASYNC, (unsigned char *)&dummy, sizeof(int) );
570 cooldown_status = COOLDOWN_LIMIT;
571 } else if(strncmp(status, "WarningAction", 13) == 0) {
572 appinfo_foreach(_saf, __app_info_iter_waring_cb, NULL);
573 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
575 info_t = (app_status_info_t *)iter->data;
576 if(g_hash_table_lookup(cooldown_black_tbl, info_t->appid)) {
577 proc_group_change_status(PROC_CGROUP_SET_TERMINATE_REQUEST, info_t->pid, NULL);
578 ret = __app_send_raw_with_noreply(info_t->pid, APP_TERM_BY_PID_ASYNC, (unsigned char *)&dummy, sizeof(int) );
581 cooldown_status = COOLDOWN_WARNING;
582 } else if (strncmp(status, "Release", 7) == 0){
583 appinfo_foreach(_saf, __app_info_iter_release_cb, NULL);
584 cooldown_status = COOLDOWN_RELEASE;
590 int _status_get_cooldown_status(void)
592 return cooldown_status;
595 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
596 static int __lcd_status_cb(const char *lcd_status, void *data)
602 char proc_file[PROC_SIZE] = {0, };
603 static int paused_pid = 0;
605 // Check the wake-up gesture is a clock or not.
606 // 0: Off, 1: Clock, 2: Last viewed screen
607 if (vconf_get_int(VCONFKEY_WMS_WAKEUP_BY_GESTURE_SETTING, &gesture) < 0) {
608 _E("Failed to get VCONFKEY_WMS_WAKEUP_BY_GESTURE_SETTING");
612 if (gesture == WAKE_UP_GESTURE_CLOCK) {
613 SECURE_LOGD("Skip when wake-up gesture is a Clock.");
617 // Get the topmost app
618 win = ecore_x_window_focus_get();
619 if (ecore_x_netwm_pid_get(win, &pid) != 1) {
620 _E("Can't get pid for focus x window (%x)", win);
623 SECURE_LOGD("The topmost app's pid is %d.", pid);
625 // Pause or Resume the app when the lcd becomes On/Off
626 if (lcd_status && (strncmp(lcd_status, LCD_OFF, strlen(LCD_OFF)) == 0)) {
627 SECURE_LOGD("LCD status becomes Off. Pause the topmose app, %d", pid);
629 kb = bundle_create();
630 app_send_cmd_with_noreply(pid, APP_PAUSE_LCD_OFF, kb);
632 else if (lcd_status && (strncmp(lcd_status, LCD_ON, strlen(LCD_ON)) == 0)) {
633 if (paused_pid != pid) {
634 SECURE_LOGE("The topmost app(%d) is different with the paused app(%d).", pid, paused_pid);
637 // Check whether the paused app is running or Not
638 snprintf(proc_file, PROC_SIZE, "/proc/%d/cmdline", paused_pid);
639 if (access(proc_file, F_OK) != 0) {
640 SECURE_LOGE("paused app(%d) seems to be killed.", paused_pid);
641 if (paused_pid != pid) {
648 SECURE_LOGD("LCD status becomes On. Resume the paused app, %d", paused_pid);
649 kb = bundle_create();
650 app_send_cmd_with_noreply(paused_pid, APP_RESUME_LCD_ON, kb);
653 _E("Invalid input param for lcd_status.");
661 static int __app_info_handler (const pkgmgrinfo_appinfo_h handle, void *data)
666 pkgmgrinfo_appinfo_get_appid(handle, &tmp_appid);
668 appid = strdup(tmp_appid);
670 g_hash_table_insert(cooldown_tbl, appid, appid);
672 SECURE_LOGD("white_list : %s", appid);
677 static int __blacklist_app_info_handler (const pkgmgrinfo_appinfo_h handle, void *data)
682 pkgmgrinfo_appinfo_get_appid(handle, &tmp_appid);
684 appid = strdup(tmp_appid);
686 g_hash_table_insert(cooldown_black_tbl, appid, appid);
688 SECURE_LOGD("white_list : %s", appid);
693 int _status_init(struct amdmgr* amd)
696 pkgmgrinfo_appinfo_h handle = NULL;
700 aul_listen_cooldown_signal(__cooldown_cb, NULL);
702 cooldown_tbl = g_hash_table_new(g_str_hash, g_str_equal);
703 for(i = 0; i < WHITE_LIST_COUNT; i++) {
704 SECURE_LOGD("pkgid %s", cooldown_list[i]);
705 if (pkgmgrinfo_pkginfo_get_pkginfo(cooldown_list[i], &handle) == PMINFO_R_OK){
706 pkgmgrinfo_appinfo_get_list(handle, PMINFO_SVC_APP, __app_info_handler, NULL);
707 pkgmgrinfo_appinfo_get_list(handle, PMINFO_UI_APP, __app_info_handler, NULL);
708 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
712 cooldown_black_tbl = g_hash_table_new(g_str_hash, g_str_equal);
713 for(i = 0; i < BLACK_LIST_COUNT; i++) {
714 SECURE_LOGD("pkgid %s", cooldown_black_list[i]);
715 if (pkgmgrinfo_pkginfo_get_pkginfo(cooldown_black_list[i], &handle) == PMINFO_R_OK){
716 pkgmgrinfo_appinfo_get_list(handle, PMINFO_SVC_APP, __blacklist_app_info_handler, NULL);
717 pkgmgrinfo_appinfo_get_list(handle, PMINFO_UI_APP, __blacklist_app_info_handler, NULL);
718 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
722 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
723 // Register callback for LCD On/Off
724 aul_listen_lcd_status_signal(__lcd_status_cb, NULL);