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));
87 memset(info_t, 0, sizeof(app_status_info_t));
89 strncpy(info_t->appid, appid, MAX_PACKAGE_STR_SIZE-1);
90 strncpy(info_t->app_path, app_path, MAX_PACKAGE_APP_PATH_SIZE-1);
92 strncpy(info_t->caller, caller, MAX_PACKAGE_STR_SIZE-1);
93 info_t->status = STATUS_LAUNCHING;
95 info_t->pad_pid = pad_pid;
96 app_status_info_list = g_slist_append(app_status_info_list, info_t);
98 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
100 info_t = (app_status_info_t *)iter->data;
102 //SECURE_LOGD("%s, %d, %d", info_t->appid, info_t->pid, info_t->status);
108 static Eina_Bool __app_terminate_timer_cb(void *data)
115 ret = kill(pid, SIGKILL);
117 _D("send SIGKILL: %s", strerror(errno));
119 return ECORE_CALLBACK_CANCEL;
122 int _status_update_app_info_list(int pid, int status)
125 app_status_info_t *info_t = NULL;
127 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
129 info_t = (app_status_info_t *)iter->data;
130 if(pid == info_t->pid) {
131 info_t->status = status;
132 if(status == STATUS_DYING) {
133 if(info_t->pad_pid != DEBUG_LAUNCHPAD_PID)
134 ecore_timer_add(2, __app_terminate_timer_cb, info_t->pid);
140 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
142 info_t = (app_status_info_t *)iter->data;
144 //SECURE_LOGD("%s, %d, %d", info_t->appid, info_t->pid, info_t->status);
150 int _status_remove_app_info_list(int pid)
153 app_status_info_t *info_t = NULL;
155 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
157 info_t = (app_status_info_t *)iter->data;
158 if(pid == info_t->pid) {
159 app_status_info_list = g_slist_remove(app_status_info_list, info_t);
165 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
167 info_t = (app_status_info_t *)iter->data;
169 //SECURE_LOGD("%s, %d, %d", info_t->appid, info_t->pid, info_t->status);
175 int _status_get_app_info_status(int pid)
178 app_status_info_t *info_t = NULL;
180 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
182 info_t = (app_status_info_t *)iter->data;
183 if(pid == info_t->pid) {
184 return info_t->status;
192 int _status_app_is_running(char *appid)
195 app_status_info_t *info_t = NULL;
197 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
199 info_t = (app_status_info_t *)iter->data;
200 if( strncmp(appid, info_t->appid, MAX_PACKAGE_STR_SIZE) == 0 ) {
207 char* _status_app_get_appid_bypid(int pid)
210 app_status_info_t *info_t = NULL;
212 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
214 info_t = (app_status_info_t *)iter->data;
215 if( pid == info_t->pid ) {
216 return info_t->appid;
222 char* _status_get_caller_by_appid(const char *appid)
225 app_status_info_t *info_t = NULL;
227 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
229 info_t = (app_status_info_t *)iter->data;
230 if( strncmp(appid, info_t->appid, MAX_PACKAGE_STR_SIZE-1) == 0) {
231 return info_t->caller;
238 int _status_send_running_appinfo(int fd)
241 app_status_info_t *info_t = NULL;
242 app_pkt_t *pkt = NULL;
244 char tmp_pid[MAX_PID_STR_BUFSZ];
246 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
253 memset(pkt, 0, AUL_SOCK_MAXBUFF);
255 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
257 info_t = (app_status_info_t *)iter->data;
258 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", info_t->pid);
259 strncat((char *)pkt->data, tmp_pid, MAX_PID_STR_BUFSZ);
260 strncat((char *)pkt->data, ":", 1);
261 strncat((char *)pkt->data, info_t->appid, MAX_PACKAGE_STR_SIZE);
262 strncat((char *)pkt->data, ":", 1);
263 strncat((char *)pkt->data, info_t->app_path, MAX_PACKAGE_APP_PATH_SIZE);
264 strncat((char *)pkt->data, ";", 1);
267 pkt->cmd = APP_RUNNING_INFO_RESULT;
268 pkt->len = strlen((char *)pkt->data) + 1;
270 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
272 _E("send failed due to EPIPE.\n");
273 _E("send fail to client");
284 int _status_app_is_running_v2(char *appid)
286 char *apppath = NULL;
290 const struct appinfo *ai;
295 ai = appinfo_find(_saf, appid);
300 ae = appinfo_get_value(ai, AIT_EXEC);
304 apppath = strdup(ae);
305 if (apppath == NULL) {
310 /*truncate apppath if it includes default bundles */
311 while (apppath[i] != 0) {
312 if (apppath[i] == ' ' || apppath[i] == '\t') {
319 ret = __proc_iter_cmdline(NULL, apppath);
326 static int __get_pkginfo(const char *dname, const char *cmdline, void *priv)
328 app_info_from_db *menu_info;
330 char *pkgname = NULL;
331 char *app_path = NULL;
333 r_info = (char *)priv;
335 if ((menu_info = _get_app_info_from_db_by_apppath(cmdline)) == NULL)
338 pkgname = _get_pkgname(menu_info);
342 app_path = _get_app_path(menu_info);
343 if (app_path == NULL)
346 strncat(r_info, dname, 8);
347 strncat(r_info, ":", 1);
348 strncat(r_info, pkgname, MAX_PACKAGE_STR_SIZE);
349 strncat(r_info, ":", 1);
350 strncat(r_info, app_path, MAX_PACKAGE_APP_PATH_SIZE);
351 strncat(r_info, ";", 1);
355 if (menu_info != NULL)
356 _free_app_info_from_db(menu_info);
360 int _status_send_running_appinfo_v2(int fd)
362 app_pkt_t *pkt = NULL;
365 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
372 memset(pkt, 0, AUL_SOCK_MAXBUFF);
374 __proc_iter_cmdline(__get_pkginfo, pkt->data);
376 pkt->cmd = APP_RUNNING_INFO_RESULT;
377 pkt->len = strlen((char *)pkt->data) + 1;
379 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
381 _E("send failed due to EPIPE.\n");
382 _E("send fail to client");
393 int _status_get_pkgname_bypid(int pid, char *pkgname, int len)
396 app_info_from_db *menu_info;
398 cmdline = __proc_get_cmdline_bypid(pid);
402 if ((menu_info = _get_app_info_from_db_by_apppath(cmdline)) == NULL) {
406 snprintf(pkgname, len, "%s", _get_pkgname(menu_info));
410 _free_app_info_from_db(menu_info);
415 int _status_get_appid_bypid(int fd, int pid)
417 app_pkt_t *pkt = NULL;
421 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
428 memset(pkt, 0, AUL_SOCK_MAXBUFF);
430 pkt->cmd = APP_GET_INFO_ERROR;
432 if (_status_get_pkgname_bypid(pid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0) {
433 SECURE_LOGD("appid for %d is %s", pid, pkt->data);
434 pkt->cmd = APP_GET_INFO_OK;
437 /* support app launched by shell script*/
443 _D("second change pgid = %d, pid = %d", pgid, pid);
444 if (_status_get_pkgname_bypid(pgid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0)
445 pkt->cmd = APP_GET_INFO_OK;
448 pkt->len = strlen((char *)pkt->data) + 1;
450 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
452 _E("send failed due to EPIPE.\n");
453 _E("send fail to client");
464 static int __get_pkgid_bypid(int pid, char *pkgid, int len)
467 app_info_from_db *menu_info;
469 cmdline = __proc_get_cmdline_bypid(pid);
473 if ((menu_info = _get_app_info_from_db_by_apppath(cmdline)) == NULL) {
477 snprintf(pkgid, len, "%s", _get_pkgid(menu_info));
480 _free_app_info_from_db(menu_info);
485 int _status_get_pkgid_bypid(int fd, int pid)
487 app_pkt_t *pkt = NULL;
491 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
498 memset(pkt, 0, AUL_SOCK_MAXBUFF);
500 pkt->cmd = APP_GET_INFO_ERROR;
502 if (__get_pkgid_bypid(pid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0) {
503 SECURE_LOGD("appid for %d is %s", pid, pkt->data);
504 pkt->cmd = APP_GET_INFO_OK;
507 /* support app launched by shell script*/
513 _D("second change pgid = %d, pid = %d", pgid, pid);
514 if (__get_pkgid_bypid(pgid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0)
515 pkt->cmd = APP_GET_INFO_OK;
518 pkt->len = strlen((char *)pkt->data) + 1;
520 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
522 _E("send failed due to EPIPE.\n");
523 _E("send fail to client");
534 int _status_get_cmdline(int fd, int pid)
536 app_pkt_t *pkt = NULL;
541 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
548 memset(pkt, 0, AUL_SOCK_MAXBUFF);
550 pkt->cmd = APP_GET_INFO_ERROR;
552 cmdline = __proc_get_cmdline_bypid(pid);
555 _E("cmdline : %s", cmdline);
557 snprintf((char *)pkt->data, MAX_PACKAGE_STR_SIZE, cmdline);
558 _E("pkt->data : %s", pkt->data);
559 pkt->cmd = APP_GET_INFO_OK;
562 pkt->len = strlen((char *)pkt->data) + 1;
564 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
566 _E("send failed due to EPIPE.\n");
567 _E("send fail to client");
581 static void __app_info_iter_limit_cb(void *user_data, const char *appid, const struct appinfo *ai)
583 if(!g_hash_table_lookup(cooldown_tbl, appid)) {
584 appinfo_set_value(ai, AIT_STATUS, "blocking");
588 static void __app_info_iter_waring_cb(void *user_data, const char *appid, const struct appinfo *ai)
590 if(g_hash_table_lookup(cooldown_black_tbl, appid)) {
591 appinfo_set_value(ai, AIT_STATUS, "blocking");
595 static void __app_info_iter_release_cb(void *user_data, const char *appid, const struct appinfo *ai)
597 const char *component = NULL;
601 if(!g_hash_table_lookup(cooldown_tbl, appid)) {
602 component = appinfo_get_value(ai, AIT_COMPTYPE);
603 onboot = appinfo_get_boolean(ai, AIT_ONBOOT);
604 restart = appinfo_get_boolean(ai, AIT_RESTART);
605 if (onboot == 1 && restart == 1 && component && strncmp(component, "svcapp", 6) == 0)
607 if (_status_app_is_running(appid) < 0)
609 _I("start service (cooldown release) - %s", appid);
610 _start_srv(ai, NULL);
614 _E("service: %s is already running", appid);
617 appinfo_set_value(ai, AIT_STATUS, "installed");
623 static int __cooldown_cb(const char* status, void *data)
626 app_status_info_t *info_t = NULL;
630 _I("__cooldown_cb, status: %s", status);
632 if(strncmp(status, "LimitAction", 11) == 0) {
633 appinfo_foreach(_saf, __app_info_iter_limit_cb, NULL);
634 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
636 info_t = (app_status_info_t *)iter->data;
637 if(!g_hash_table_lookup(cooldown_tbl, info_t->appid)) {
638 proc_group_change_status(PROC_CGROUP_SET_TERMINATE_REQUEST, info_t->pid, NULL);
639 ret = __app_send_raw_with_noreply(info_t->pid, APP_TERM_BY_PID_ASYNC, (unsigned char *)&dummy, sizeof(int) );
642 cooldown_status = COOLDOWN_LIMIT;
643 } else if(strncmp(status, "WarningAction", 13) == 0) {
644 appinfo_foreach(_saf, __app_info_iter_waring_cb, NULL);
645 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
647 info_t = (app_status_info_t *)iter->data;
648 if(g_hash_table_lookup(cooldown_black_tbl, info_t->appid)) {
649 proc_group_change_status(PROC_CGROUP_SET_TERMINATE_REQUEST, info_t->pid, NULL);
650 ret = __app_send_raw_with_noreply(info_t->pid, APP_TERM_BY_PID_ASYNC, (unsigned char *)&dummy, sizeof(int) );
653 cooldown_status = COOLDOWN_WARNING;
654 } else if (strncmp(status, "Release", 7) == 0){
655 appinfo_foreach(_saf, __app_info_iter_release_cb, NULL);
656 cooldown_status = COOLDOWN_RELEASE;
662 int _status_get_cooldown_status(void)
664 return cooldown_status;
667 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
668 static int __lcd_status_cb(const char *lcd_status, void *data)
674 char proc_file[PROC_SIZE] = {0, };
675 static int paused_pid = 0;
677 // Check the wake-up gesture is a clock or not.
678 // 0: Off, 1: Clock, 2: Last viewed screen
679 if (vconf_get_int(VCONFKEY_WMS_WAKEUP_BY_GESTURE_SETTING, &gesture) < 0) {
680 _E("Failed to get VCONFKEY_WMS_WAKEUP_BY_GESTURE_SETTING");
684 if (gesture == WAKE_UP_GESTURE_CLOCK) {
685 SECURE_LOGD("Skip when wake-up gesture is a Clock.");
689 // Get the topmost app
690 win = ecore_x_window_focus_get();
691 if (ecore_x_netwm_pid_get(win, &pid) != 1) {
692 _E("Can't get pid for focus x window (%x)", win);
695 SECURE_LOGD("The topmost app's pid is %d.", pid);
697 // Pause or Resume the app when the lcd becomes On/Off
698 if (lcd_status && (strncmp(lcd_status, LCD_OFF, strlen(LCD_OFF)) == 0)) {
699 SECURE_LOGD("LCD status becomes Off. Pause the topmose app, %d", pid);
701 kb = bundle_create();
702 app_send_cmd_with_noreply(pid, APP_PAUSE_LCD_OFF, kb);
704 else if (lcd_status && (strncmp(lcd_status, LCD_ON, strlen(LCD_ON)) == 0)) {
705 if (paused_pid != pid) {
706 SECURE_LOGE("The topmost app(%d) is different with the paused app(%d).", pid, paused_pid);
709 // Check whether the paused app is running or Not
710 snprintf(proc_file, PROC_SIZE, "/proc/%d/cmdline", paused_pid);
711 if (access(proc_file, F_OK) != 0) {
712 SECURE_LOGE("paused app(%d) seems to be killed.", paused_pid);
713 if (paused_pid != pid) {
720 SECURE_LOGD("LCD status becomes On. Resume the paused app, %d", paused_pid);
721 kb = bundle_create();
722 app_send_cmd_with_noreply(paused_pid, APP_RESUME_LCD_ON, kb);
725 _E("Invalid input param for lcd_status.");
733 static int __app_info_handler (const pkgmgrinfo_appinfo_h handle, void *data)
738 pkgmgrinfo_appinfo_get_appid(handle, &tmp_appid);
740 appid = strdup(tmp_appid);
742 g_hash_table_insert(cooldown_tbl, appid, appid);
744 SECURE_LOGD("white_list : %s", appid);
749 static int __blacklist_app_info_handler (const pkgmgrinfo_appinfo_h handle, void *data)
754 pkgmgrinfo_appinfo_get_appid(handle, &tmp_appid);
756 appid = strdup(tmp_appid);
758 g_hash_table_insert(cooldown_black_tbl, appid, appid);
760 SECURE_LOGD("white_list : %s", appid);
765 int _status_init(struct amdmgr* amd)
768 pkgmgrinfo_appinfo_h handle = NULL;
772 aul_listen_cooldown_signal(__cooldown_cb, NULL);
774 cooldown_tbl = g_hash_table_new(g_str_hash, g_str_equal);
775 for(i = 0; i < WHITE_LIST_COUNT; i++) {
776 SECURE_LOGD("pkgid %s", cooldown_list[i]);
777 if (pkgmgrinfo_pkginfo_get_pkginfo(cooldown_list[i], &handle) == PMINFO_R_OK){
778 pkgmgrinfo_appinfo_get_list(handle, PMINFO_SVC_APP, __app_info_handler, NULL);
779 pkgmgrinfo_appinfo_get_list(handle, PMINFO_UI_APP, __app_info_handler, NULL);
780 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
784 cooldown_black_tbl = g_hash_table_new(g_str_hash, g_str_equal);
785 for(i = 0; i < BLACK_LIST_COUNT; i++) {
786 SECURE_LOGD("pkgid %s", cooldown_black_list[i]);
787 if (pkgmgrinfo_pkginfo_get_pkginfo(cooldown_black_list[i], &handle) == PMINFO_R_OK){
788 pkgmgrinfo_appinfo_get_list(handle, PMINFO_SVC_APP, __blacklist_app_info_handler, NULL);
789 pkgmgrinfo_appinfo_get_list(handle, PMINFO_UI_APP, __blacklist_app_info_handler, NULL);
790 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
794 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
795 // Register callback for LCD On/Off
796 aul_listen_lcd_status_signal(__lcd_status_cb, NULL);