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);
252 memset(pkt, 0, AUL_SOCK_MAXBUFF);
254 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
256 info_t = (app_status_info_t *)iter->data;
257 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", info_t->pid);
258 strncat((char *)pkt->data, tmp_pid, MAX_PID_STR_BUFSZ);
259 strncat((char *)pkt->data, ":", 1);
260 strncat((char *)pkt->data, info_t->appid, MAX_PACKAGE_STR_SIZE);
261 strncat((char *)pkt->data, ":", 1);
262 strncat((char *)pkt->data, info_t->app_path, MAX_PACKAGE_APP_PATH_SIZE);
263 strncat((char *)pkt->data, ";", 1);
266 pkt->cmd = APP_RUNNING_INFO_RESULT;
267 pkt->len = strlen((char *)pkt->data) + 1;
269 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
271 _E("send failed due to EPIPE.\n");
272 _E("send fail to client");
283 int _status_app_is_running_v2(char *appid)
285 char *apppath = NULL;
289 const struct appinfo *ai;
294 ai = appinfo_find(_saf, appid);
299 ae = appinfo_get_value(ai, AIT_EXEC);
303 apppath = strdup(ae);
304 if (apppath == NULL) {
309 /*truncate apppath if it includes default bundles */
310 while (apppath[i] != 0) {
311 if (apppath[i] == ' ' || apppath[i] == '\t') {
318 ret = __proc_iter_cmdline(NULL, apppath);
325 static int __get_pkginfo(const char *dname, const char *cmdline, void *priv)
327 app_info_from_db *menu_info;
329 char *pkgname = NULL;
330 char *app_path = NULL;
332 r_info = (char *)priv;
334 if ((menu_info = _get_app_info_from_db_by_apppath(cmdline)) == NULL)
337 pkgname = _get_pkgname(menu_info);
341 app_path = _get_app_path(menu_info);
342 if (app_path == NULL)
345 strncat(r_info, dname, 8);
346 strncat(r_info, ":", 1);
347 strncat(r_info, pkgname, MAX_PACKAGE_STR_SIZE);
348 strncat(r_info, ":", 1);
349 strncat(r_info, app_path, MAX_PACKAGE_APP_PATH_SIZE);
350 strncat(r_info, ";", 1);
354 if (menu_info != NULL)
355 _free_app_info_from_db(menu_info);
359 int _status_send_running_appinfo_v2(int fd)
361 app_pkt_t *pkt = NULL;
364 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
371 memset(pkt, 0, AUL_SOCK_MAXBUFF);
373 __proc_iter_cmdline(__get_pkginfo, pkt->data);
375 pkt->cmd = APP_RUNNING_INFO_RESULT;
376 pkt->len = strlen((char *)pkt->data) + 1;
378 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
380 _E("send failed due to EPIPE.\n");
381 _E("send fail to client");
392 int _status_get_pkgname_bypid(int pid, char *pkgname, int len)
395 app_info_from_db *menu_info;
397 cmdline = __proc_get_cmdline_bypid(pid);
401 if ((menu_info = _get_app_info_from_db_by_apppath(cmdline)) == NULL) {
405 snprintf(pkgname, len, "%s", _get_pkgname(menu_info));
409 _free_app_info_from_db(menu_info);
414 int _status_get_appid_bypid(int fd, int pid)
416 app_pkt_t *pkt = NULL;
420 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
427 memset(pkt, 0, AUL_SOCK_MAXBUFF);
429 pkt->cmd = APP_GET_INFO_ERROR;
431 if (_status_get_pkgname_bypid(pid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0) {
432 SECURE_LOGD("appid for %d is %s", pid, pkt->data);
433 pkt->cmd = APP_GET_INFO_OK;
436 /* support app launched by shell script*/
442 _D("second change pgid = %d, pid = %d", pgid, pid);
443 if (_status_get_pkgname_bypid(pgid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0)
444 pkt->cmd = APP_GET_INFO_OK;
447 pkt->len = strlen((char *)pkt->data) + 1;
449 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
451 _E("send failed due to EPIPE.\n");
452 _E("send fail to client");
463 static int __get_pkgid_bypid(int pid, char *pkgid, int len)
466 app_info_from_db *menu_info;
468 cmdline = __proc_get_cmdline_bypid(pid);
472 if ((menu_info = _get_app_info_from_db_by_apppath(cmdline)) == NULL) {
476 snprintf(pkgid, len, "%s", _get_pkgid(menu_info));
479 _free_app_info_from_db(menu_info);
484 int _status_get_pkgid_bypid(int fd, int pid)
486 app_pkt_t *pkt = NULL;
490 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
497 memset(pkt, 0, AUL_SOCK_MAXBUFF);
499 pkt->cmd = APP_GET_INFO_ERROR;
501 if (__get_pkgid_bypid(pid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0) {
502 SECURE_LOGD("appid for %d is %s", pid, pkt->data);
503 pkt->cmd = APP_GET_INFO_OK;
506 /* support app launched by shell script*/
512 _D("second change pgid = %d, pid = %d", pgid, pid);
513 if (__get_pkgid_bypid(pgid, (char *)pkt->data, MAX_PACKAGE_STR_SIZE) == 0)
514 pkt->cmd = APP_GET_INFO_OK;
517 pkt->len = strlen((char *)pkt->data) + 1;
519 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
521 _E("send failed due to EPIPE.\n");
522 _E("send fail to client");
533 int _status_get_cmdline(int fd, int pid)
535 app_pkt_t *pkt = NULL;
540 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
547 memset(pkt, 0, AUL_SOCK_MAXBUFF);
549 pkt->cmd = APP_GET_INFO_ERROR;
551 cmdline = __proc_get_cmdline_bypid(pid);
554 _E("cmdline : %s", cmdline);
556 snprintf((char *)pkt->data, MAX_PACKAGE_STR_SIZE, cmdline);
557 _E("pkt->data : %s", pkt->data);
558 pkt->cmd = APP_GET_INFO_OK;
561 pkt->len = strlen((char *)pkt->data) + 1;
563 if ((len = send(fd, pkt, pkt->len + 8, 0)) != pkt->len + 8) {
565 _E("send failed due to EPIPE.\n");
566 _E("send fail to client");
580 static void __app_info_iter_limit_cb(void *user_data, const char *appid, const struct appinfo *ai)
582 if(!g_hash_table_lookup(cooldown_tbl, appid)) {
583 appinfo_set_value(ai, AIT_STATUS, "blocking");
587 static void __app_info_iter_waring_cb(void *user_data, const char *appid, const struct appinfo *ai)
589 if(g_hash_table_lookup(cooldown_black_tbl, appid)) {
590 appinfo_set_value(ai, AIT_STATUS, "blocking");
594 static void __app_info_iter_release_cb(void *user_data, const char *appid, const struct appinfo *ai)
596 const char *component = NULL;
600 if(!g_hash_table_lookup(cooldown_tbl, appid)) {
601 component = appinfo_get_value(ai, AIT_COMPTYPE);
602 onboot = appinfo_get_boolean(ai, AIT_ONBOOT);
603 restart = appinfo_get_boolean(ai, AIT_RESTART);
604 if (onboot == 1 && restart == 1 && component && strncmp(component, "svcapp", 6) == 0)
606 if (_status_app_is_running(appid) < 0)
608 _I("start service (cooldown release) - %s", appid);
609 _start_srv(ai, NULL);
613 _E("service: %s is already running", appid);
616 appinfo_set_value(ai, AIT_STATUS, "installed");
622 static int __cooldown_cb(const char* status, void *data)
625 app_status_info_t *info_t = NULL;
629 _I("__cooldown_cb, status: %s", status);
631 if(strncmp(status, "LimitAction", 11) == 0) {
632 appinfo_foreach(_saf, __app_info_iter_limit_cb, NULL);
633 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
635 info_t = (app_status_info_t *)iter->data;
636 if(!g_hash_table_lookup(cooldown_tbl, info_t->appid)) {
637 proc_group_change_status(PROC_CGROUP_SET_TERMINATE_REQUEST, info_t->pid, NULL);
638 ret = __app_send_raw_with_noreply(info_t->pid, APP_TERM_BY_PID_ASYNC, (unsigned char *)&dummy, sizeof(int) );
641 cooldown_status = COOLDOWN_LIMIT;
642 } else if(strncmp(status, "WarningAction", 13) == 0) {
643 appinfo_foreach(_saf, __app_info_iter_waring_cb, NULL);
644 for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
646 info_t = (app_status_info_t *)iter->data;
647 if(g_hash_table_lookup(cooldown_black_tbl, info_t->appid)) {
648 proc_group_change_status(PROC_CGROUP_SET_TERMINATE_REQUEST, info_t->pid, NULL);
649 ret = __app_send_raw_with_noreply(info_t->pid, APP_TERM_BY_PID_ASYNC, (unsigned char *)&dummy, sizeof(int) );
652 cooldown_status = COOLDOWN_WARNING;
653 } else if (strncmp(status, "Release", 7) == 0){
654 appinfo_foreach(_saf, __app_info_iter_release_cb, NULL);
655 cooldown_status = COOLDOWN_RELEASE;
661 int _status_get_cooldown_status(void)
663 return cooldown_status;
666 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
667 static int __lcd_status_cb(const char *lcd_status, void *data)
673 char proc_file[PROC_SIZE] = {0, };
674 static int paused_pid = 0;
676 // Check the wake-up gesture is a clock or not.
677 // 0: Off, 1: Clock, 2: Last viewed screen
678 if (vconf_get_int(VCONFKEY_WMS_WAKEUP_BY_GESTURE_SETTING, &gesture) < 0) {
679 _E("Failed to get VCONFKEY_WMS_WAKEUP_BY_GESTURE_SETTING");
683 if (gesture == WAKE_UP_GESTURE_CLOCK) {
684 SECURE_LOGD("Skip when wake-up gesture is a Clock.");
688 // Get the topmost app
689 win = ecore_x_window_focus_get();
690 if (ecore_x_netwm_pid_get(win, &pid) != 1) {
691 _E("Can't get pid for focus x window (%x)", win);
694 SECURE_LOGD("The topmost app's pid is %d.", pid);
696 // Pause or Resume the app when the lcd becomes On/Off
697 if (lcd_status && (strncmp(lcd_status, LCD_OFF, strlen(LCD_OFF)) == 0)) {
698 SECURE_LOGD("LCD status becomes Off. Pause the topmose app, %d", pid);
700 kb = bundle_create();
701 app_send_cmd_with_noreply(pid, APP_PAUSE_LCD_OFF, kb);
703 else if (lcd_status && (strncmp(lcd_status, LCD_ON, strlen(LCD_ON)) == 0)) {
704 if (paused_pid != pid) {
705 SECURE_LOGE("The topmost app(%d) is different with the paused app(%d).", pid, paused_pid);
708 // Check whether the paused app is running or Not
709 snprintf(proc_file, PROC_SIZE, "/proc/%d/cmdline", paused_pid);
710 if (access(proc_file, F_OK) != 0) {
711 SECURE_LOGE("paused app(%d) seems to be killed.", paused_pid);
712 if (paused_pid != pid) {
719 SECURE_LOGD("LCD status becomes On. Resume the paused app, %d", paused_pid);
720 kb = bundle_create();
721 app_send_cmd_with_noreply(paused_pid, APP_RESUME_LCD_ON, kb);
724 _E("Invalid input param for lcd_status.");
732 static int __app_info_handler (const pkgmgrinfo_appinfo_h handle, void *data)
737 pkgmgrinfo_appinfo_get_appid(handle, &tmp_appid);
739 appid = strdup(tmp_appid);
741 g_hash_table_insert(cooldown_tbl, appid, appid);
743 SECURE_LOGD("white_list : %s", appid);
748 static int __blacklist_app_info_handler (const pkgmgrinfo_appinfo_h handle, void *data)
753 pkgmgrinfo_appinfo_get_appid(handle, &tmp_appid);
755 appid = strdup(tmp_appid);
757 g_hash_table_insert(cooldown_black_tbl, appid, appid);
759 SECURE_LOGD("white_list : %s", appid);
764 int _status_init(struct amdmgr* amd)
767 pkgmgrinfo_appinfo_h handle = NULL;
771 aul_listen_cooldown_signal(__cooldown_cb, NULL);
773 cooldown_tbl = g_hash_table_new(g_str_hash, g_str_equal);
774 for(i = 0; i < WHITE_LIST_COUNT; i++) {
775 SECURE_LOGD("pkgid %s", cooldown_list[i]);
776 if (pkgmgrinfo_pkginfo_get_pkginfo(cooldown_list[i], &handle) == PMINFO_R_OK){
777 pkgmgrinfo_appinfo_get_list(handle, PMINFO_SVC_APP, __app_info_handler, NULL);
778 pkgmgrinfo_appinfo_get_list(handle, PMINFO_UI_APP, __app_info_handler, NULL);
779 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
783 cooldown_black_tbl = g_hash_table_new(g_str_hash, g_str_equal);
784 for(i = 0; i < BLACK_LIST_COUNT; i++) {
785 SECURE_LOGD("pkgid %s", cooldown_black_list[i]);
786 if (pkgmgrinfo_pkginfo_get_pkginfo(cooldown_black_list[i], &handle) == PMINFO_R_OK){
787 pkgmgrinfo_appinfo_get_list(handle, PMINFO_SVC_APP, __blacklist_app_info_handler, NULL);
788 pkgmgrinfo_appinfo_get_list(handle, PMINFO_UI_APP, __blacklist_app_info_handler, NULL);
789 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
793 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
794 // Register callback for LCD On/Off
795 aul_listen_lcd_status_signal(__lcd_status_cb, NULL);