#include "amd_api_noti.h"
#include "amd_app_com.h"
+#include "amd_app_request_broker.h"
#include "amd_app_status.h"
#include "amd_appinfo.h"
#include "amd_cynara.h"
bool debug_mode;
guint timer;
int real_pid;
+ guint disconn_timer;
};
struct fault_app_s {
guint timer;
};
+struct restart_info_s {
+ char *appid;
+ int count;
+ guint timer;
+};
+
static GSList *app_status_list;
static GHashTable *pkg_status_table;
static int limit_bg_uiapps;
static GHashTable *__wd_table;
static inotify_watch_info_h __wh;
static struct vconf_context_s __vconf;
+static GHashTable *__restart_table;
static app_status_h __find_app_status(int pid);
+static gboolean __restart_timeout_handler(gpointer user_data)
+{
+ struct restart_info_s *info = user_data;
+
+ _I("info(%p), appid(%s)", info, info->appid);
+ info->timer = 0;
+ g_hash_table_remove(__restart_table, info->appid);
+ return G_SOURCE_REMOVE;
+}
+
+static void __destroy_restart_info(gpointer user_data)
+{
+ struct restart_info_s *info = user_data;
+
+ if (info->timer != 0)
+ g_source_remove(info->timer);
+
+ free(info->appid);
+ free(info);
+}
+
+static struct restart_info_s *__create_restart_info(const char *appid)
+{
+ struct restart_info_s *info;
+
+ info = calloc(1, sizeof(struct restart_info_s));
+ if (!info) {
+ _E("Out of memory");
+ return NULL;
+ }
+
+ info->appid = strdup(appid);
+ if (!info->appid) {
+ _E("Out of memory");
+ __destroy_restart_info(info);
+ return NULL;
+ }
+
+ info->timer = g_timeout_add_seconds(10, __restart_timeout_handler,
+ info);
+ if (info->timer == 0) {
+ _E("g_timeout_add_seconds() is failed");
+ __destroy_restart_info(info);
+ return NULL;
+ }
+
+ info->count = 1;
+
+ return info;
+}
+
+static bool __check_restart(const char *appid)
+{
+ struct restart_info_s *info;
+
+ info = g_hash_table_lookup(__restart_table, appid);
+ if (!info) {
+ info = __create_restart_info(appid);
+ if (!info) {
+ _E("Failed to create restart info. appid(%s)", appid);
+ return false;
+ }
+
+ _D("info(%p), appid(%s), count(%d)", info, appid, info->count);
+ g_hash_table_insert(__restart_table, info->appid, info);
+ } else {
+ info->count++;
+ _W("info(%p), appid(%s), count(%d)", info, appid, info->count);
+ if (info->count > 5) {
+ g_hash_table_remove(__restart_table, info->appid);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool __can_restart_app(const char *appid, uid_t uid)
+{
+ const char *comp_type;
+ const char *status;
+ struct appinfo *ai;
+ int enablement;
+ int restart;
+ int ret;
+
+ _D("appid(%s)", appid);
+ ai = _appinfo_find(uid, appid);
+ if (!ai)
+ return false;
+
+ comp_type = _appinfo_get_value(ai, AIT_COMPTYPE);
+ if (!comp_type || strcmp(comp_type, APP_TYPE_SERVICE) != 0)
+ return false;
+
+ ret = _appinfo_get_int_value(ai, AIT_ENABLEMENT, &enablement);
+ if (ret == 0 && !(enablement & APP_ENABLEMENT_MASK_ACTIVE)) {
+ _W("%s is disabled", appid);
+ return false;
+ }
+
+ status = _appinfo_get_value(ai, AIT_STATUS);
+ if (status && !strcmp(status, "blocking")) {
+ _appinfo_set_value(ai, AIT_STATUS, "restart");
+ } else if (status && !strcmp(status, "norestart")) {
+ _appinfo_set_value(ai, AIT_STATUS, "installed");
+ } else {
+ ret = _appinfo_get_int_value(ai, AIT_RESTART, &restart);
+ if (ret == 0 && restart && __check_restart(appid))
+ return true;
+ }
+
+ return false;
+}
+
+static int __app_dead_handler(int pid, void *user_data)
+{
+ app_status_h app_status;
+ char appid_buf[256];
+ const char *appid;
+ char buf[128];
+ bool restart;
+ uid_t uid;
+
+ if (pid <= 0)
+ return 0;
+
+ app_status = _app_status_find(pid);
+ if (!app_status)
+ return 0;
+
+ appid = _app_status_get_appid(app_status);
+ _W("APP_DEAD_SIGNAL appid(%s), pid(%d)", appid, pid);
+
+ uid = _app_status_get_uid(app_status);
+ _noti_send(AMD_NOTI_MSG_MAIN_APP_DEAD, pid, uid, app_status, NULL);
+ restart = __can_restart_app(appid, uid);
+ if (restart)
+ snprintf(appid_buf, sizeof(appid_buf), "%s", appid);
+
+ _request_flush_pending_request(pid);
+ _app_status_cleanup(app_status);
+
+ if (restart)
+ _launch_start_app_local(uid, appid_buf);
+
+ snprintf(buf, sizeof(buf), "%d", pid);
+ _util_save_log("TERMINATED", buf);
+ return 0;
+}
+
+static gboolean __dead_timeout_handler(gpointer user_data)
+{
+ app_status_h app_status = user_data;
+
+ _E("Timer expired. appid(%s), pid(%d)",
+ app_status->appid, app_status->pid);
+ app_status->disconn_timer = 0;
+ __app_dead_handler(app_status->pid, NULL);
+ return G_SOURCE_REMOVE;
+}
+
+static int __disconnected_event_cb(int pid, void *user_data)
+{
+ app_status_h app_status;
+
+ app_status = _app_status_find(pid);
+ if (!app_status)
+ return -1;
+
+ app_status->disconn_timer = g_timeout_add_seconds(10,
+ __dead_timeout_handler, app_status);
+ return 0;
+}
+
static int __get_managed_uiapp_cnt(void)
{
GSList *iter;
g_hash_table_destroy(app_status->extras);
if (app_status->timer)
g_source_remove(app_status->timer);
+ if (app_status->disconn_timer)
+ g_source_remove(app_status->disconn_timer);
free(app_status);
}
return G_SOURCE_REMOVE;
}
+static int __listen_app_dead_signal(void *user_data)
+{
+ if (aul_listen_app_dead_signal(__app_dead_handler, user_data) < 0)
+ return -1;
+
+ return 0;
+}
+
int _app_status_init(void)
{
int ret;
+ _signal_add_ready_cb(__listen_app_dead_signal, NULL);
+ _app_request_broker_set_disconnected_event_cb(__disconnected_event_cb,
+ NULL);
+
+ __restart_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, __destroy_restart_info);
+ if (!__restart_table) {
+ _E("g_hash_table_new_full() is failed");
+ return -1;
+ }
+
__wd_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, __remove_inotify_watch);
if (__wd_table == NULL) {
if (__wd_table)
g_hash_table_destroy(__wd_table);
+ if (__restart_table)
+ g_hash_table_destroy(__restart_table);
+
+ aul_listen_app_dead_signal(NULL, NULL);
+
return 0;
}
#include "amd_app_control.h"
#include "amd_app_lifecycle.h"
#include "amd_app_property.h"
-#include "amd_app_request_broker.h"
#include "amd_app_status.h"
#include "amd_appinfo.h"
#include "amd_boot_manager.h"
typedef int (*amd_mod_init_cb)(void);
typedef void (*amd_mod_fini_cb)(void);
-struct restart_info {
- char *appid;
- int count;
- guint timer;
-};
-
-static GHashTable *restart_tbl;
static GList *so_handles;
static sigset_t old_mask;
-static gboolean __restart_timeout_handler(void *data)
-{
- struct restart_info *ri = (struct restart_info *)data;
-
- _D("ri (%p)", ri);
- _D("appid (%s)", ri->appid);
-
- g_hash_table_remove(restart_tbl, ri->appid);
- free(ri->appid);
- free(ri);
-
- return FALSE;
-}
-
-static bool __check_restart(const char *appid)
-{
- struct restart_info *ri = NULL;
- char err_buf[1024];
-
- ri = g_hash_table_lookup(restart_tbl, appid);
- if (!ri) {
- ri = calloc(1, sizeof(struct restart_info));
- if (!ri) {
- _E("create restart info: %s",
- strerror_r(errno, err_buf, sizeof(err_buf)));
- return false;
- }
- ri->appid = strdup(appid);
- if (ri->appid == NULL) {
- _E("Out of memory");
- free(ri);
- return false;
- }
- ri->count = 1;
- g_hash_table_insert(restart_tbl, ri->appid, ri);
-
- _D("ri (%p)", ri);
- _D("appid (%s)", appid);
-
- ri->timer = g_timeout_add(10 * 1000, __restart_timeout_handler,
- ri);
- } else {
- ri->count++;
- _D("count (%d)", ri->count);
- if (ri->count > 5) {
- g_source_remove(ri->timer);
- g_hash_table_remove(restart_tbl, ri->appid);
- free(ri->appid);
- free(ri);
- return false;
- }
- }
- return true;
-}
-
-static bool __can_restart_app(const char *appid, uid_t uid)
-{
- const char *pkg_status;
- const char *component_type;
- struct appinfo *ai;
- int r;
- int val = 0;
- int enable = 1;
-
- _D("appid: %s", appid);
- ai = _appinfo_find(uid, appid);
- if (!ai)
- return false;
-
- component_type = _appinfo_get_value(ai, AIT_COMPTYPE);
- if (!component_type)
- return false;
-
- if (strcmp(component_type, APP_TYPE_SERVICE) != 0)
- return false;
-
- r = _appinfo_get_int_value(ai, AIT_ENABLEMENT, &enable);
- if (r == 0 && !(enable & APP_ENABLEMENT_MASK_ACTIVE)) {
- _D("Disabled");
- return false;
- }
-
- pkg_status = _appinfo_get_value(ai, AIT_STATUS);
- if (pkg_status && strcmp(pkg_status, "blocking") == 0) {
- _appinfo_set_value(ai, AIT_STATUS, "restart");
- } else if (pkg_status && strcmp(pkg_status, "norestart") == 0) {
- _appinfo_set_value(ai, AIT_STATUS, "installed");
- } else {
- r = _appinfo_get_int_value(ai, AIT_RESTART, &val);
- if (r == 0 && val && __check_restart(appid))
- return true;
- }
-
- return false;
-}
-
-static int __app_dead_handler(int pid, void *data)
-{
- bool restart = false;
- char *appid = NULL;
- const char *tmp_appid;
- app_status_h app_status;
- uid_t uid;
- char buf[MAX_LOCAL_BUFSZ];
-
- if (pid <= 0)
- return 0;
-
- app_status = _app_status_find(pid);
- if (app_status == NULL)
- return 0;
-
- _W("APP_DEAD_SIGNAL : %d", pid);
-
- uid = _app_status_get_uid(app_status);
- _noti_send(AMD_NOTI_MSG_MAIN_APP_DEAD, pid, uid, app_status, NULL);
- tmp_appid = _app_status_get_appid(app_status);
- if (tmp_appid == NULL)
- return 0;
-
- uid = _app_status_get_uid(app_status);
- restart = __can_restart_app(tmp_appid, uid);
- if (restart) {
- appid = strdup(tmp_appid);
- if (appid == NULL)
- _W("Out of memory");
- }
-
- _request_flush_pending_request(pid);
- _app_status_cleanup(app_status);
-
- if (restart)
- _launch_start_app_local(uid, appid);
- if (appid)
- free(appid);
-
- snprintf(buf, sizeof(buf), "%d", pid);
- _util_save_log("TERMINATED", buf);
- return 0;
-}
-
-static gboolean __dead_timeout_handler(gpointer user_data)
-{
- int pid = GPOINTER_TO_INT(user_data);
-
- __app_dead_handler(pid, NULL);
- return G_SOURCE_REMOVE;
-}
-
-static int __disconnected_event_cb(int pid, void *user_data)
-{
- g_timeout_add_seconds(10, __dead_timeout_handler, GINT_TO_POINTER(pid));
- return 0;
-}
-
-static int __listen_app_dead_signal(void *data)
-{
- int ret;
-
- ret = aul_listen_app_dead_signal(__app_dead_handler, data);
- if (ret < 0)
- return -1;
-
- return 0;
-}
-
-static void __ignore_app_dead_signal(void)
-{
- aul_listen_app_dead_signal(NULL, NULL);
-}
-
static int __load_modules(const char *path)
{
DIR *dp;
return -1;
}
- _signal_add_ready_cb(__listen_app_dead_signal, NULL);
- _app_request_broker_set_disconnected_event_cb(__disconnected_event_cb,
- NULL);
-
- restart_tbl = g_hash_table_new(g_str_hash, g_str_equal);
-
r = _cynara_init();
if (r != 0) {
_E("cynara initialize failed.");
_app_lifecycle_fini();
_request_fini();
_cynara_finish();
-
- if (restart_tbl) {
- g_hash_table_destroy(restart_tbl);
- restart_tbl = NULL;
- }
-
- __ignore_app_dead_signal();
-
_appinfo_fini();
_direct_launch_fini();
_compinfo_fini();