From: Jiwoong Im Date: Tue, 3 Nov 2015 05:07:37 +0000 (+0900) Subject: sync app group with tizen_2.4 X-Git-Tag: accepted/tizen/mobile/20151111.232020^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F23%2F50923%2F8;p=platform%2Fcore%2Fappfw%2Faul-1.git sync app group with tizen_2.4 - sync implementation of app group from tizen_2.4 - add appgroup_info tool Change-Id: Ib5bd77ff6c969bab18d6dbb7affa6fd8c677c5fc Signed-off-by: Jiwoong Im --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 91813ab..a5834c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ ENDIF (with_x11) INCLUDE(FindPkgConfig) SET(AUL-1_LIB_PKG_CHECK_MODULES dlog bundle dbus-glib-1 xdgmime libtzplatform-config pkgmgr-info libsystemd-daemon security-manager cynara-client cynara-creds-socket cynara-session capi-system-info vconf sqlite3 iniparser) IF (with_wayland) - pkg_check_modules(libpkgs REQUIRED ${AUL-1_LIB_PKG_CHECK_MODULES} wayland-client tizen-extension-client) + pkg_check_modules(libpkgs REQUIRED ${AUL-1_LIB_PKG_CHECK_MODULES} wayland-client tizen-extension-client ecore-wayland) ENDIF (with_wayland) IF (with_x11) pkg_check_modules(libpkgs REQUIRED ${AUL-1_LIB_PKG_CHECK_MODULES}) @@ -105,6 +105,12 @@ ADD_EXECUTABLE(${APP_LAUNCHER} app_launcher.c) TARGET_LINK_LIBRARIES(${APP_LAUNCHER} aul aul_mods ${APP_LAUNCHER_DEPS_LDFLAGS}) INSTALL(TARGETS app_launcher DESTINATION bin) +# appgroup info tool +SET(APPGROUP_INFO "appgroup_info") +ADD_EXECUTABLE(${APPGROUP_INFO} tool/app_group_info.c) +TARGET_LINK_LIBRARIES(${APPGROUP_INFO} aul aul_mods ${APPGROUP_INFO_DEPS_LDFLAGS}) +INSTALL(TARGETS appgroup_info DESTINATION bin) + # pkgconfig file CONFIGURE_FILE(aul.pc.in aul.pc @ONLY) CONFIGURE_FILE(legacy/preload_list.txt.in legacy/preload_list.txt @ONLY) diff --git a/am_daemon/amd_app_group.c b/am_daemon/amd_app_group.c index 1b66a38..c22c7d5 100644 --- a/am_daemon/amd_app_group.c +++ b/am_daemon/amd_app_group.c @@ -1,30 +1,132 @@ +#define _GNU_SOURCE #include -#include #include -#include - +#include +#include #include - #include -#include +#include +#include #include "app_sock.h" #include "simple_util.h" -#include "amd_launch.h" #include "amd_app_group.h" +#include "amd_launch.h" +#include "amd_request.h" +#include "amd_status.h" +#include "app_signal.h" +#include "amd_appinfo.h" #define APP_SVC_K_LAUNCH_MODE "__APP_SVC_LAUNCH_MODE__" +#ifdef WAYLAND +#include +#include +#include +static struct tizen_policy *tz_policy; + +static void _reg_handle_global(void *data, struct wl_registry *reg, + uint32_t id, const char *interface, uint32_t ver) +{ + if (!strcmp(interface, "tizen_policy")) { + tz_policy = wl_registry_bind(reg, + id, + &tizen_policy_interface, + 1); + } +} + +static void _reg_handle_global_remove(void *data, struct wl_registry *reg, + uint32_t id) +{ + /* do nothing */ +} + +static const struct wl_registry_listener reg_listener = { + _reg_handle_global, + _reg_handle_global_remove +}; +#endif + static GHashTable *app_group_hash = NULL; static int dead_pid = -1; static int focused_leader_pid = -1; +static GList *recycle_bin = NULL; + +extern char *home_appid; typedef struct _app_group_context_t { int pid; int wid; int status; + int fg; + int group_sig; + int can_be_leader; + int reroute; + int caller_pid; + int can_shift; + int recycle; + app_group_launch_mode launch_mode; } app_group_context_t; +static void __attach_window(int parent_wid, int child_wid) +{ +#ifdef WAYLAND + struct wl_display *dpy; + struct wl_registry *reg; + + dpy = wl_display_connect(NULL); + reg = wl_display_get_registry(dpy); + wl_registry_add_listener(reg, ®_listener, NULL); + wl_display_roundtrip(dpy); + + if (!tz_policy) { + _E("ERR: no tizen_policy global interface"); + wl_registry_destroy(reg); + wl_display_disconnect(dpy); + return; + } + + tizen_policy_set_transient_for(tz_policy, child_wid, parent_wid); + wl_display_roundtrip(dpy); + + tizen_policy_destroy(tz_policy); + wl_registry_destroy(reg); + wl_display_disconnect(dpy); +#else + //ecore_x_icccm_transient_for_set(child_wid, parent_wid); +#endif +} + +static void __detach_window(int child_wid) +{ +#ifdef WAYLAND + struct wl_display *dpy; + struct wl_registry *reg; + + dpy = wl_display_connect(NULL); + reg = wl_display_get_registry(dpy); + wl_registry_add_listener(reg, ®_listener, NULL); + wl_display_roundtrip(dpy); + + if (!tz_policy) { + _E("ERR: no tz_policy global interface"); + wl_registry_destroy(reg); + wl_display_disconnect(dpy); + return; + } + + tizen_policy_unset_transient_for(tz_policy, child_wid); + wl_display_roundtrip(dpy); + + tizen_policy_destroy(tz_policy); + wl_registry_destroy(reg); + wl_display_disconnect(dpy); +#else + //ecore_x_icccm_transient_for_unset(child_wid); +#endif +} + static gint __comp_pid(gconstpointer a, gconstpointer b) { app_group_context_t *ac1 = (app_group_context_t*) a; @@ -62,21 +164,32 @@ static gboolean __hash_table_cb(gpointer key, gpointer value, return FALSE; } -static gboolean __is_top(int pid) +static GList* __find_removable_apps(int from) { int cnt; int *pids = NULL; - int i; + GList *list = NULL; gboolean found = FALSE; app_group_get_leader_pids(&cnt, &pids); + + int i, j; + for (i = 0; i < cnt; i++) { int *gpids = NULL; int gcnt; app_group_get_group_pids(pids[i], &gcnt, &gpids); - if (gcnt > 0 && gpids[gcnt - 1] == pid) - found = TRUE; + for (j = 0; j < gcnt; j++) { + if (gpids[j] == from) { + found = TRUE; + continue; + } + + if (found) { + list = g_list_append(list, GINT_TO_POINTER(gpids[j])); + } + } if (gpids != NULL) free(gpids); @@ -88,87 +201,285 @@ static gboolean __is_top(int pid) if (pids != NULL) free(pids); - _D("is top: %d", found); - return found; + return list; } - -static GList* __find_removable_apps(int from) +/* + * TODO : BG manangement should be merged +static void __prepare_to_suspend_services(int pid) { - int cnt; - int *pids = NULL; - GList *list = NULL; - gboolean found = FALSE; - int i, j; + int dummy; + SECURE_LOGD("[__SUSPEND__] pid: %d", pid); + __app_send_raw_with_noreply(pid, APP_SUSPEND, (unsigned char *)&dummy, sizeof(int)); +} - app_group_get_leader_pids(&cnt, &pids); +static void __prepare_to_wake_services(int pid) +{ + int dummy; + SECURE_LOGD("[__SUSPEND__] pid: %d", pid); + __app_send_raw_with_noreply(pid, APP_WAKE, (unsigned char *)&dummy, sizeof(int)); +} - for (i = 0; i < cnt; i++) { - int *gpids = NULL; - int gcnt; +static void __set_fg_flag(int cpid, int flag, gboolean force) +{ + int lpid = app_group_get_leader_pid(cpid); + GHashTableIter iter; + gpointer key, value; + int bg_category = 0x00; - app_group_get_group_pids(pids[i], &gcnt, &gpids); - for (j = 0; j < gcnt; j++) { - if (gpids[j] == from) { - found = TRUE; - continue; + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); + app_group_context_t *ac = (app_group_context_t*) i->data; + + if (ac->pid == lpid) { + + while (i != NULL) { + ac = (app_group_context_t*) i->data; + + if (ac->fg != flag || force == TRUE) { + const char *appid = NULL; + const char *pkgid = NULL; + const struct appinfo *ai = NULL; + + appid = _status_app_get_appid_bypid(ac->pid); + ai = appinfo_find(getuid(), appid); + pkgid = appinfo_get_value(ai, AIT_PKGID); + bg_category = (bool)appinfo_get_value(ai, AIT_BG_CATEGORY); + + if (flag) { + _D("send_signal FG %s", appid); + + aul_send_app_status_change_signal(ac->pid, appid, + pkgid, + STATUS_FOREGROUND, + APP_TYPE_UI); + if (!bg_category) + _status_find_service_apps(ac->pid, STATUS_VISIBLE, __prepare_to_wake_services, false); + } else { + _D("send_signal BG %s", appid); + aul_send_app_status_change_signal(ac->pid, appid, + pkgid, + STATUS_BACKGROUND, + APP_TYPE_UI); + if (!bg_category) + _status_find_service_apps(ac->pid, STATUS_BG, __prepare_to_suspend_services, true); + } + ac->fg = flag; + } + i = g_list_next(i); } + break; + } + } +} +*/ - if (found) { - list = g_list_append(list, GINT_TO_POINTER(gpids[j])); +static gboolean __is_visible(int cpid) +{ + int lpid = app_group_get_leader_pid(cpid); + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); + app_group_context_t *ac = (app_group_context_t*) i->data; + + if (ac->pid == lpid) { + while (i != NULL) { + ac = (app_group_context_t*) i->data; + + if (ac->status == STATUS_VISIBLE) + return TRUE; + + i = g_list_next(i); } + break; } + } - if (gpids != NULL) - free(gpids); + return FALSE; +} - if (found) +static gboolean __can_attach_window(bundle *b, const char *appid, app_group_launch_mode *launch_mode) +{ + char *str = NULL; + const char *mode = NULL; + const struct appinfo *ai = NULL; + + ai = appinfo_find(getuid(), appid); + mode = appinfo_get_value(ai, AIT_LAUNCH_MODE); + + if (mode == NULL) + *launch_mode = APP_GROUP_LAUNCH_MODE_SINGLE; + else if (strcmp(mode, "caller") == 0) + *launch_mode = APP_GROUP_LAUNCH_MODE_CALLER; + else if (strcmp(mode, "single") == 0) + *launch_mode = APP_GROUP_LAUNCH_MODE_SINGLE; + else if (strcmp(mode, "group") == 0) + *launch_mode = APP_GROUP_LAUNCH_MODE_GROUP; + else if (strcmp(mode, "singleton") == 0) + *launch_mode = APP_GROUP_LAUNCH_MODE_SINGLETON; + + switch (*launch_mode) { + case APP_GROUP_LAUNCH_MODE_CALLER: + case APP_GROUP_LAUNCH_MODE_SINGLETON: + _D("launch mode from db is caller or singleton"); + + bundle_get_str(b, APP_SVC_K_LAUNCH_MODE, &str); + if (str != NULL && strncmp(str, "group", 5) == 0) { + return TRUE; + } break; + + case APP_GROUP_LAUNCH_MODE_GROUP: + return TRUE; + + case APP_GROUP_LAUNCH_MODE_SINGLE: + return FALSE; } - if (pids != NULL) - free(pids); + return FALSE; +} - return list; +static gboolean __can_be_leader(bundle *b) +{ + char *str = NULL; + + bundle_get_str(b, AUL_SVC_K_CAN_BE_LEADER, &str); + + if (str != NULL && strcmp(str, "true") == 0) + return TRUE; + + return FALSE; } -void app_group_init(void) +static int __get_previous_pid(int pid) { - app_group_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, - NULL); + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); + + int previous_pid = -1; + while (i != NULL) { + app_group_context_t *ac = (app_group_context_t*) i->data; + + if (ac->pid == pid) { + return previous_pid; + } + previous_pid = ac->pid; + i = g_list_next(i); + } + } + + return -1; } -void app_group_add(int leader_pid, int pid, int wid) +static int __get_caller_pid(bundle *kb) { - app_group_context_t *ac = malloc(sizeof(app_group_context_t)); - if (ac == NULL) { - _E("out of memory"); - return; + const char *pid_str; + int pid; + + pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID); + if(pid_str) + goto end; + + pid_str = bundle_get_val(kb, AUL_K_CALLER_PID); + if (pid_str == NULL) + return -1; + +end: + pid = atoi(pid_str); + if (pid <= 1) + return -1; + + return pid; +} + +static app_group_context_t* __detach_context_from_recycle_bin(int pid) +{ + GList *iter = recycle_bin; + + while (iter) { + app_group_context_t *ac = (app_group_context_t*) iter->data; + + if (ac->pid == pid) { + recycle_bin = g_list_remove_link(recycle_bin, iter); + return ac; + } + + iter = g_list_next(iter); } - ac->pid = pid; - ac->wid = wid; + return NULL; + +} + +static void __group_add(int leader_pid, int pid, int wid, app_group_launch_mode mode, + int caller_pid, int can_shift, int recycle) +{ + app_group_context_t *ac = NULL; + + if ((ac = __detach_context_from_recycle_bin(pid)) == NULL) { + ac = malloc(sizeof(app_group_context_t)); + + if (ac == NULL) { + _E("out of memory"); + return; + } + ac->pid = pid; + ac->wid = wid; + ac->fg = 0; + ac->can_be_leader = 0; + ac->reroute = 0; + ac->launch_mode = mode; + ac->caller_pid = caller_pid; + ac->can_shift = can_shift; + ac->recycle = recycle; + } + + if (leader_pid == pid || ac->recycle) + ac->group_sig = 1; + else + ac->group_sig = 0; + dead_pid = -1; GList *list = (GList*) g_hash_table_lookup(app_group_hash, GINT_TO_POINTER(leader_pid)); if (list != NULL) { - if (g_list_find_custom(list, (gconstpointer)(intptr_t)pid, __comp_pid) != NULL) { + if (g_list_find_custom(list, GINT_TO_POINTER(pid), __comp_pid) != NULL) { _E("pid exist"); free(ac); return; } } + list = g_list_append(list, ac); g_hash_table_insert(app_group_hash, GINT_TO_POINTER(leader_pid), list); + + if (ac->wid != 0) + app_group_set_window(pid, ac->wid); } -void app_group_remove(int pid) +static void __group_remove(int pid) { + int ppid = __get_previous_pid(pid); g_hash_table_foreach_remove(app_group_hash, __hash_table_cb, GINT_TO_POINTER(pid)); + + if (ppid != -1) { + app_group_set_status(ppid, -1, false); + } } -int app_group_get_window(int pid) +static app_group_context_t* __get_context(int pid) { GHashTableIter iter; gpointer key, value; @@ -182,81 +493,200 @@ int app_group_get_window(int pid) app_group_context_t *ac = (app_group_context_t*) i->data; if (ac->pid == pid) { - return ac->wid; + return ac; } i = g_list_next(i); } } + return NULL; +} + +static int __can_recycle(int pid) +{ + app_group_context_t *context = __get_context(pid); + + if (context) + return context->recycle; + + return 0; +} + +static int __can_reroute(int pid) +{ + app_group_context_t *context = __get_context(pid); + + if (context) + return context->reroute; + + return 0; +} + +static app_group_context_t* __context_dup(const app_group_context_t *context) +{ + app_group_context_t* dup; + + if (!context) { + _E("context is NULL."); + return NULL; + } + + dup = malloc(sizeof(app_group_context_t)); + if (!dup) { + _E("out of memory"); + return NULL; + } + + memcpy(dup, context, sizeof(app_group_context_t)); + return dup; +} + +static void __do_recycle(app_group_context_t *context) +{ + if (context->fg) { + const char *appid = NULL; + const char *pkgid = NULL; + const struct appinfo *ai = NULL; + + appid = _status_app_get_appid_bypid(context->pid); + ai = appinfo_find(getuid(), appid); + pkgid = appinfo_get_value(ai, AIT_PKGID); + + _D("send_signal BG %s", appid); + aul_send_app_status_change_signal(context->pid, appid, pkgid, + STATUS_BACKGROUND, + APP_TYPE_UI); +// _status_find_service_apps(context->pid, STATUS_BG, __prepare_to_suspend_services, true); + context->fg = 0; + } + recycle_bin = g_list_append(recycle_bin, context); +// _revoke_temporary_permission(context->pid); +} + +void app_group_init() +{ + app_group_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, + NULL); +} + +void app_group_remove(int pid) +{ + __group_remove(pid); + app_group_context_t *context = __detach_context_from_recycle_bin(pid); + + if (context) + free(context); +} + +void app_group_remove_from_recycle_bin(int pid) +{ + app_group_context_t *context = __detach_context_from_recycle_bin(pid); + + if (context) + free(context); +} + +int app_group_get_window(int pid) +{ + app_group_context_t *context = __get_context(pid); + + if (context) + return context->wid; + return -1; } -void app_group_clear_top(int pid) +int app_group_set_window(int pid, int wid) { - if (!__is_top(pid)) { - GList *list = __find_removable_apps(pid); + GHashTableIter iter; + gpointer key, value; - if (list != NULL) { - GList *itr = g_list_last(list); + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); + + int previous_wid = 0; + while (i != NULL) { + app_group_context_t *ac = (app_group_context_t*) i->data; + + if (ac->pid == pid) { + ac->wid = wid; + if (previous_wid != 0) + __attach_window(previous_wid, wid); + + if (ac->can_shift && ac->caller_pid > 0) { + int caller_wid = app_group_get_window(ac->caller_pid); + + if (caller_wid != 0) + __attach_window(caller_wid, wid); + } - while (itr != NULL) { - int p = GPOINTER_TO_INT((itr->data)); + i = g_list_next(i); + if (i) { + ac = (app_group_context_t*) i->data; + if (ac->wid != 0) + __attach_window(wid, ac->wid); + } - aul_app_group_detach_window(p); - _term_sub_app(p); - app_group_remove(p); - itr = g_list_previous(itr); + return 0; } - g_list_free(list); + previous_wid = ac->wid; + i = g_list_next(i); } } + + return -1; } -void app_group_resume(int pid) +void app_group_clear_top(int pid) { - app_group_clear_top(pid); + GList *list = __find_removable_apps(pid); + + if (list != NULL) { + GList *itr = g_list_last(list); + + while (itr != NULL) { + int p = GPOINTER_TO_INT(itr->data); + + __detach_window(p); + _term_sub_app(p); + app_group_remove(p); + itr = g_list_previous(itr); + } + g_list_free(list); + } } -gboolean app_group_is_group_app(bundle* kb, uid_t uid) +gboolean app_group_is_group_app(bundle* kb) { if (kb == NULL) return FALSE; char *str = NULL; - char *mode = NULL; + const char *mode = NULL; char *appid = NULL; - int ret; - - pkgmgrinfo_appinfo_h handle; + const struct appinfo *ai = NULL; bundle_get_str(kb, AUL_K_APPID, &appid); if (appid == NULL) return FALSE; - ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &handle); - if (ret != PMINFO_R_OK) - return FALSE; - ret = pkgmgrinfo_appinfo_get_launch_mode(handle, &mode); - if (ret != PMINFO_R_OK) { - pkgmgrinfo_appinfo_destroy_appinfo(handle); - return FALSE; - } + ai = appinfo_find(getuid(), appid); + mode = appinfo_get_value(ai, AIT_LAUNCH_MODE); - if (mode != NULL && strncmp(mode, "caller", 6) == 0) { + if (mode != NULL && (strncmp(mode, "caller", 6) == 0 || + strncmp(mode, "singleton", 9) == 0)) { bundle_get_str(kb, APP_SVC_K_LAUNCH_MODE, &str); if (str != NULL && strncmp(str, "group", 5) == 0) { - pkgmgrinfo_appinfo_destroy_appinfo(handle); return TRUE; } } else if (mode != NULL && strncmp(mode, "group", 5) == 0) { - pkgmgrinfo_appinfo_destroy_appinfo(handle); return TRUE; } - pkgmgrinfo_appinfo_destroy_appinfo(handle); - return FALSE; } @@ -369,7 +799,7 @@ gboolean app_group_is_sub_app(int pid) GList *found = NULL; if (list != NULL) { - if ((found = g_list_find_custom(list, (gconstpointer)(intptr_t)pid, __comp_pid)) != NULL) { + if ((found = g_list_find_custom(list, GINT_TO_POINTER(pid), __comp_pid)) != NULL) { if (g_list_first(list) == found) return FALSE; return TRUE; @@ -393,7 +823,7 @@ void app_group_reroute(int pid) GList *after = NULL; if (list != NULL) { - if ((found = g_list_find_custom(list, (gconstpointer)(intptr_t)pid, __comp_pid)) != NULL) { + if ((found = g_list_find_custom(list, GINT_TO_POINTER(pid), __comp_pid)) != NULL) { before = g_list_previous(found); after = g_list_next(found); @@ -404,8 +834,8 @@ void app_group_reroute(int pid) app_group_context_t *ac1 = (app_group_context_t*) before->data; app_group_context_t *ac2 = (app_group_context_t*) after->data; - aul_app_group_detach_window(ac2->wid); - aul_app_group_attach_window(ac1->wid, ac2->wid); + __detach_window(ac2->wid); + __attach_window(ac1->wid, ac2->wid); break; } } @@ -425,7 +855,7 @@ repeat: GList *list = (GList*) value; if (list != NULL) { - if (g_list_find_custom(list, (gconstpointer)(intptr_t)pid, __comp_pid) != NULL) { + if (g_list_find_custom(list, GINT_TO_POINTER(pid), __comp_pid) != NULL) { lpid = GPOINTER_TO_INT(key); break; } @@ -477,26 +907,452 @@ int app_group_get_status(int pid) return -1; } -int app_group_set_status(int pid, int status) +int app_group_set_status(int pid, int status, gboolean force) { - GHashTableIter iter; - gpointer key, value; + GHashTableIter iter; + gpointer key, value; - g_hash_table_iter_init(&iter, app_group_hash); - while (g_hash_table_iter_next(&iter, &key, &value)) { - GList *list = (GList*) value; - GList *i = g_list_first(list); + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); - while (i != NULL) { - app_group_context_t *ac = (app_group_context_t*) i->data; + while (i != NULL) { + app_group_context_t *ac = (app_group_context_t*) i->data; - if (ac->pid == pid) { - ac->status = status; + if (ac->pid == pid) { + if (status > 0) + ac->status = status; + GList *last = g_list_last(list); + app_group_context_t *last_ac = (app_group_context_t*) last->data; + + if (last_ac->wid != 0 || status == STATUS_VISIBLE || force == TRUE) { + if (__is_visible(pid)) { + //__set_fg_flag(pid, 1, force); + if (!ac->group_sig && GPOINTER_TO_INT(key) != pid) { + char *appid = NULL; + const char *pkgid = NULL; + const struct appinfo *ai = NULL; + + appid = _status_app_get_appid_bypid(pid); + ai = appinfo_find(getuid(), appid); + pkgid = appinfo_get_value(ai, AIT_PKGID); + + _D("send group signal %d", pid); + aul_send_app_group_signal(GPOINTER_TO_INT(key), pid, pkgid); + ac->group_sig = 1; + } + } /*else + __set_fg_flag(pid, 0, force);*/ + } return 0; } - i = g_list_next(i); - } - } + i = g_list_next(i); + } + } + return -1; +} + +int app_group_get_fg_flag(int pid) +{ + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); + + while (i != NULL) { + app_group_context_t *ac = (app_group_context_t*) i->data; + + if (ac->pid == pid) { + return ac->fg; + } + i = g_list_next(i); + } + } + + return 0; +} + +int app_group_set_hint(int pid, bundle *kb) +{ + char *str_leader = NULL; + char *str_reroute = NULL; + + if (kb == NULL) + return -1; + + bundle_get_str(kb, AUL_SVC_K_CAN_BE_LEADER, &str_leader); + bundle_get_str(kb, AUL_SVC_K_REROUTE, &str_reroute); + + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); + + while (i != NULL) { + app_group_context_t *ac = (app_group_context_t*) i->data; + + if (ac->pid == pid) { + if (str_leader != NULL && strcmp(str_leader, "true") == 0) + ac->can_be_leader = 1; + if (str_reroute != NULL && strcmp(str_reroute, "true") == 0) + ac->reroute = 1; + return 0; + } + i = g_list_next(i); + } + } + + return -1; +} + +int app_group_find_second_leader(int lpid) +{ + GList *list = (GList*) g_hash_table_lookup(app_group_hash, + GINT_TO_POINTER(lpid)); + if (list != NULL) { + list = g_list_next(list); + + if (list != NULL) { + app_group_context_t *ac = (app_group_context_t*) list->data; + if (ac->can_be_leader) { + _W("found the second leader, lpid: %d, pid: %d", lpid, ac->pid); + return ac->pid; + } + } + } + return -1; +} + +void app_group_remove_leader_pid(int lpid) +{ + GList *list = (GList*)g_hash_table_lookup(app_group_hash, + GINT_TO_POINTER(lpid)); + if (list != NULL) { + GList *next = g_list_next(list); + + if (next != NULL) { + app_group_context_t *ac = (app_group_context_t*) list->data; + free(ac); + list = g_list_remove_link(list, list); + + ac = (app_group_context_t*) next->data; + g_hash_table_insert(app_group_hash, GINT_TO_POINTER(ac->pid), next); + g_hash_table_remove(app_group_hash, GINT_TO_POINTER(lpid)); + } + } } + +int app_group_can_start_app(const char *appid, bundle *b, gboolean *can_attach, + int *lpid, app_group_launch_mode *mode) +{ + const char *val = NULL; + int caller_pid; + int caller_wid; + + *can_attach = FALSE; + if (__can_attach_window(b, appid, mode)) { + *can_attach = TRUE; + + val = bundle_get_val(b, AUL_K_ORG_CALLER_PID); + if (val == NULL) { + val = bundle_get_val(b, AUL_K_CALLER_PID); + } + + if (val == NULL) { + _E("no caller pid"); + return -1; + } + + caller_pid = atoi(val); + + *lpid = app_group_get_leader_pid(caller_pid); + if (*lpid != -1) { + caller_wid = app_group_get_window(caller_pid); + + if (caller_wid == 0) { + _E("caller window wasn't ready"); + if (__can_be_leader(b)) + *can_attach = FALSE; + else + *can_attach = TRUE; + } + + } else { + _E("no lpid"); + if (__can_be_leader(b)) + *can_attach = FALSE; + else + return -1; + } + } + + return 0; +} + +void app_group_start_app(int pid, bundle *b, int lpid, gboolean can_attach, + app_group_launch_mode mode) +{ + _E("app_group_start_app"); + + int caller_pid = __get_caller_pid(b); + int can_shift = 0; + int recycle = 0; + const char *str; + + str = bundle_get_val(b, AUL_SVC_K_SHIFT_WINDOW); + if (str != NULL && strcmp(str, "true") == 0) + can_shift = 1; + + str = bundle_get_val(b, AUL_SVC_K_RECYCLE); + if (str != NULL && strcmp(str, "true") == 0) + recycle = 1; + + if (can_attach) + __group_add(lpid, pid, 0, mode, caller_pid, 0, recycle); + else + __group_add(pid, pid, 0, mode, caller_pid, can_shift, 0); + app_group_set_hint(pid, b); +} + +int app_group_find_singleton(const char *appid, int *found_pid, int *found_lpid) +{ + GHashTableIter iter; + gpointer key = NULL; + gpointer value = NULL; + char *target = NULL; + + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + + while (list != NULL) { + app_group_context_t *ac = (app_group_context_t*) list->data; + + if (ac->launch_mode == APP_GROUP_LAUNCH_MODE_SINGLETON) { + target = _status_app_get_appid_bypid(ac->pid); + + if (appid != NULL && target != NULL && strcmp(appid, target) == 0) { + *found_pid = ac->pid; + *found_lpid = GPOINTER_TO_INT(key); + return 0; + } + } + list = g_list_next(list); + } + } + + return -1; +} + +int app_group_can_reroute(int pid) +{ + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); + + while (i != NULL) { + app_group_context_t *ac = (app_group_context_t*) i->data; + + if (ac->pid == pid) { + return ac->reroute; + } + i = g_list_next(i); + } + } + + return 0; +} + +void app_group_lower(int pid, int *exit) +{ + if (app_group_is_sub_app(pid)) { + if (__can_recycle(pid) && __can_reroute(pid)) { + app_group_context_t *ac = __get_context(pid); + if (ac) { + if (ac->wid != 0) + __detach_window(ac->wid); + app_group_reroute(pid); + ac = __context_dup(ac); + __group_remove(pid); + /* if (ac) + __do_recycle(ac); */ + } + *exit = 0; + } else + *exit = 1; + return; + } + + GHashTableIter iter; + gpointer key, value; + + *exit = 0; + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); + + while (i != NULL) { + app_group_context_t *ac = (app_group_context_t*) i->data; + + if (ac->pid == pid) { + if (ac->can_shift) { + __detach_window(ac->wid); + ac->can_shift = 0; +#ifdef WAYLAND + ecore_wl_window_lower((Ecore_Wl_Window *)ac->wid); +#else + //ecore_x_window_lower(ac->wid); +#endif + } + return; + } + i = g_list_next(i); + } + } +} + +void app_group_restart_app(int pid, bundle *b) +{ + if (b == NULL) + return; + + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); + + while (i != NULL) { + app_group_context_t *ac = (app_group_context_t*) i->data; + + if (ac->pid == pid) { + const char *pid_str; + ac->caller_pid = __get_caller_pid(b); + + if (ac->can_shift) { + if (ac->wid != 0) + __detach_window(ac->wid); + ac->can_shift = 0; + } + + pid_str = bundle_get_val(b, AUL_SVC_K_SHIFT_WINDOW); + if (pid_str != NULL && strcmp(pid_str, "true") == 0) { + ac->can_shift = 1; + if (ac->wid != 0) { + if (ac->caller_pid > 0) { + int cwid = app_group_get_window(ac->caller_pid); + + if (cwid != 0) + __attach_window(cwid, ac->wid); + else + _E("invalid caller wid"); + + } else + _E("invalid caller pid"); + + + } + } + return; + } + i = g_list_next(i); + } + } +} + +int app_group_find_pid_from_recycle_bin(const char *appid) +{ + GList *iter = recycle_bin; + + while (iter) { + app_group_context_t *ac = (app_group_context_t*) iter->data; + const char *appid_from_bin = _status_app_get_appid_bypid(ac->pid); + + if (appid && appid_from_bin && strcmp(appid, appid_from_bin) == 0) { + return ac->pid; + } + + iter = g_list_next(iter); + } + + return -1; +} + +void app_group_get_idle_pids(int *cnt, int **pids) +{ + GList *iter = recycle_bin; + int idle_cnt = g_list_length(iter); + + if (idle_cnt <= 0) { + *cnt = 0; + *pids = NULL; + return; + } + + int *idle_pids = NULL; + + idle_pids = malloc(sizeof(int) * idle_cnt); + if (idle_pids == NULL) { + _E("Out-of-memory"); + *cnt = 0; + *pids = NULL; + return; + } + + int i = 0; + while (iter) { + app_group_context_t *ac = (app_group_context_t*) iter->data; + idle_pids[i] = ac->pid; + iter = g_list_next(iter); + i++; + } + + *cnt = idle_cnt; + *pids = idle_pids; +} + +int app_group_get_next_caller_pid(int pid) +{ + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, app_group_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list = (GList*) value; + GList *i = g_list_first(list); + + while (i != NULL) { + app_group_context_t *ac = (app_group_context_t*) i->data; + + if (ac->pid == pid) { + i = g_list_next(i); + if (i == NULL) + return -1; + + ac = (app_group_context_t*) i->data; + return ac->caller_pid; + } + i = g_list_next(i); + } + } + + return -1; +} + + diff --git a/am_daemon/amd_app_group.h b/am_daemon/amd_app_group.h index d85fadc..9d23295 100644 --- a/am_daemon/amd_app_group.h +++ b/am_daemon/amd_app_group.h @@ -4,15 +4,21 @@ #include #include -void app_group_init(void); -void app_group_add(int leader_pid, int pid, int wid); +typedef enum { + APP_GROUP_LAUNCH_MODE_SINGLE = 0, + APP_GROUP_LAUNCH_MODE_GROUP, + APP_GROUP_LAUNCH_MODE_CALLER, + APP_GROUP_LAUNCH_MODE_SINGLETON, +} app_group_launch_mode; + +void app_group_init(); void app_group_remove(int pid); int app_group_get_window(int pid); +int app_group_set_window(int pid, int wid); void app_group_get_leader_pids(int *cnt, int **pids); void app_group_get_group_pids(int leader_pid, int *cnt, int **pids); gboolean app_group_is_leader_pid(int pid); -void app_group_resume(int pid); -gboolean app_group_is_group_app(bundle* kb, uid_t uid); +gboolean app_group_is_group_app(bundle* kb); gboolean app_group_is_sub_app(int pid); void app_group_reroute(int pid); int app_group_get_caller_pid(); @@ -20,6 +26,20 @@ void app_group_clear_top(int pid); int app_group_get_leader_pid(int pid); void app_group_set_dead_pid(int pid); int app_group_get_status(int pid); -int app_group_set_status(int pid, int status); +int app_group_set_status(int pid, int status, gboolean force); +int app_group_get_fg_flag(int pid); +int app_group_set_hint(int pid, bundle *kb); +int app_group_find_second_leader(int lpid); +void app_group_remove_leader_pid(int lpid); +int app_group_can_start_app(const char *appid, bundle *b, gboolean *can_attach, int *lpid, app_group_launch_mode *mode); +void app_group_start_app(int pid, bundle *b, int lpid, gboolean can_attach, app_group_launch_mode mode); +int app_group_find_singleton(const char *appid, int *found_pid, int *found_lpid); +int app_group_can_reroute(int pid); +void app_group_lower(int pid, int *exit); +void app_group_restart_app(int pid, bundle *b); +int app_group_find_pid_from_recycle_bin(const char *appid); +void app_group_get_idle_pids(int *cnt, int **pids); +void app_group_remove_from_recycle_bin(int pid); +int app_group_get_next_caller_pid(int pid); #endif diff --git a/am_daemon/amd_appinfo.c b/am_daemon/amd_appinfo.c index e98254e..3726999 100644 --- a/am_daemon/amd_appinfo.c +++ b/am_daemon/amd_appinfo.c @@ -39,6 +39,7 @@ enum _appinfo_idx { _AI_PKGID, _AI_PRELOAD, _AI_STATUS, + _AI_LAUNCH_MODE, _AI_MAX, }; #define _AI_START _AI_NAME /* start index */ @@ -61,6 +62,7 @@ static struct appinfo_t _appinfos[] = { [_AI_PKGID] = { "PackageId", AIT_PKGID, }, [_AI_PRELOAD] = { "Preload", AIT_PRELOAD, }, [_AI_STATUS] = { "Status", AIT_STATUS, }, + [_AI_LAUNCH_MODE] = {"launch_mode", AIT_LAUNCH_MODE }, }; struct appinfo { @@ -113,6 +115,7 @@ static int __app_info_insert_handler (const pkgmgrinfo_appinfo_h handle, void *d char *type; char *appid; char *pkgid; + char *mode; bool multiple; bool onboot; bool restart; @@ -227,6 +230,13 @@ static int __app_info_insert_handler (const pkgmgrinfo_appinfo_h handle, void *d c->val[_AI_PKGID] = strdup(pkgid); c->val[_AI_STATUS] = strdup("installed"); + if (pkgmgrinfo_appinfo_get_launch_mode(handle, &mode)) { + _E("failed to get launch_mode"); + _free_appinfo(c); + return -1; + } + c->val[_AI_LAUNCH_MODE] = strdup(mode ? mode : "single"); + SECURE_LOGD("%s : %s : %s", c->val[_AI_FILE], c->val[_AI_COMP], c->val[_AI_TYPE]); g_hash_table_insert(info->tbl, c->val[_AI_FILE], c); diff --git a/am_daemon/amd_appinfo.h b/am_daemon/amd_appinfo.h index ed94a44..e544090 100644 --- a/am_daemon/amd_appinfo.h +++ b/am_daemon/amd_appinfo.h @@ -19,8 +19,13 @@ enum appinfo_type { AIT_PKGID, AIT_PRELOAD, AIT_STATUS, + AIT_LAUNCH_MODE, + AIT_MAX }; +#define APP_TYPE_UI "ui" +#define APP_TYPE_SERVICE "svc" + int appinfo_init(void); void appinfo_fini(void); diff --git a/am_daemon/amd_launch.c b/am_daemon/amd_launch.c index 2112569..934639a 100644 --- a/am_daemon/amd_launch.c +++ b/am_daemon/amd_launch.c @@ -283,9 +283,6 @@ int _term_req_app(int pid, int clifd) int _term_bgapp(int pid, int clifd) { - return _term_app(pid, clifd); - /* FIXME: app group feature should be merged */ -#if 0 int dummy; int fd; int cnt; @@ -296,7 +293,7 @@ int _term_bgapp(int pid, int clifd) if (app_group_is_leader_pid(pid)) { app_group_get_group_pids(pid, &cnt, &pids); if (cnt > 0) { - status = _status_get_app_info_status(pids[cnt - 1]); + status = _status_get_app_info_status(pids[cnt - 1], getuid()); if (status == STATUS_BG) { for (i = cnt - 1 ; i >= 0; i--) { if (i != 0) @@ -323,7 +320,6 @@ int _term_bgapp(int pid, int clifd) __set_reply_handler(fd, pid, clifd, APP_TERM_BGAPP_BY_PID); return 0; -#endif } int _fake_launch_app(int cmd, int pid, bundle *kb, int clifd) @@ -557,6 +553,51 @@ static int __compare_signature(const struct appinfo *ai, int cmd, return 0; } +static int __get_pid_for_app_group(const char *appid, int pid, int caller_uid, bundle* kb, + int *lpid, gboolean *can_attach, gboolean *new_process, app_group_launch_mode* launch_mode) +{ + int st = -1; + int found_pid = -1; + int found_lpid = -1; + + if (app_group_is_group_app(kb)) { + pid = -1; + } + + if (pid > 0) + st = _status_get_app_info_status(pid, caller_uid); + + if (pid == -1 || st == STATUS_DYING) { + + if (app_group_find_singleton(appid, &found_pid, &found_lpid) == 0) { + pid = found_pid; + *new_process = FALSE; + } else { + *new_process = TRUE; + } + + if (app_group_can_start_app(appid, kb, can_attach, lpid, launch_mode) != 0 ) { + _E("can't make group info"); + return -EILLEGALACCESS; + } + + if (*can_attach && *lpid == found_lpid) { + _E("can't launch singleton app in the same group"); + return -EILLEGALACCESS; + } + + if (found_pid != -1) { + _W("app_group_clear_top, pid: %d", found_pid); + app_group_clear_top(found_pid); + } + } + + if (pid == -1 && *can_attach) + pid = app_group_find_pid_from_recycle_bin(appid); + + return pid; +} + int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, uid_t caller_uid, int fd) { @@ -567,13 +608,17 @@ int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, const char *app_path = NULL; const char *pkg_type = NULL; const char *pkg_id = NULL; + const char *component_type = NULL; int pid = -1; char tmpbuf[MAX_PID_STR_BUFSZ]; const char *hwacc; char *caller_appid; int delay_reply = 0; int pad_pid = LAUNCHPAD_PID; - gboolean is_group_app = FALSE; + int lpid; + gboolean can_attach; + gboolean new_process; + app_group_launch_mode launch_mode; snprintf(tmpbuf, MAX_PID_STR_BUFSZ, "%d", caller_pid); bundle_add(kb, AUL_K_CALLER_PID, tmpbuf); @@ -625,9 +670,14 @@ int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, pid = _status_app_is_running(appid, caller_uid); } - if (app_group_is_group_app(kb, caller_uid)) { - pid = -1; - is_group_app = TRUE; + component_type = appinfo_get_value(ai, AIT_COMP); + if (strncmp(component_type, APP_TYPE_UI, strlen(APP_TYPE_UI)) == 0) { + pid = __get_pid_for_app_group(appid, pid, caller_uid, kb, + &lpid, &can_attach, &new_process, &launch_mode); + if (pid == -EILLEGALACCESS) { + __real_send(fd, pid); + return pid; + } } if (pid > 0) { @@ -652,15 +702,23 @@ int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, bundle_add(kb, AUL_K_PACKAGETYPE, pkg_type); bundle_add(kb, AUL_K_PKGID, pkg_id); pid = app_agent_send_cmd(caller_uid, cmd, kb); - } - if (!delay_reply) - __real_send(fd, pid); + if (strncmp(component_type, APP_TYPE_UI, strlen(APP_TYPE_UI)) == 0) { + if (new_process) { + _D("add app group info"); + app_group_start_app(pid, kb, lpid, can_attach, launch_mode); + } else { + app_group_restart_app(pid, kb); + } + } + } if (pid > 0) { - if (!is_group_app) - _status_add_app_info_list(appid, app_path, pid, pad_pid, caller_uid); + _status_add_app_info_list(appid, app_path, pid, pad_pid, caller_uid); } + if (!delay_reply) + __real_send(fd, pid); + return pid; } diff --git a/am_daemon/amd_main.c b/am_daemon/amd_main.c index 50026ed..81f41f6 100644 --- a/am_daemon/amd_main.c +++ b/am_daemon/amd_main.c @@ -248,11 +248,24 @@ static int __app_dead_handler(int pid, void *data) _D("APP_DEAD_SIGNAL : %d", pid); if (app_group_is_leader_pid(pid)) { - app_group_clear_top(pid); - app_group_set_dead_pid(pid); - app_group_remove(pid); + _W("app_group_leader_app, pid: %d", pid); + if (app_group_find_second_leader(pid) == -1) { + app_group_clear_top(pid); + app_group_set_dead_pid(pid); + app_group_remove(pid); + } else + app_group_remove_leader_pid(pid); } else if (app_group_is_sub_app(pid)) { - app_group_reroute(pid); + _W("app_group_sub_app, pid: %d", pid); + int caller_pid = app_group_get_next_caller_pid(pid); + + if (app_group_can_reroute(pid) || (caller_pid > 0 && caller_pid != pid)) { + _W("app_group reroute"); + app_group_reroute(pid); + } else { + _W("app_group clear top"); + app_group_clear_top(pid); + } app_group_set_dead_pid(pid); app_group_remove(pid); } diff --git a/am_daemon/amd_request.c b/am_daemon/amd_request.c index cbe3546..c4c9493 100644 --- a/am_daemon/amd_request.c +++ b/am_daemon/amd_request.c @@ -419,68 +419,67 @@ err_out: return -1; } -static int __dispatch_app_group_add(int clifd, const app_pkt_t *pkt, struct ucred *cr) +static int __dispatch_app_group_get_window(int clifd, const app_pkt_t *pkt, struct ucred *cr) { bundle *b; char *buf; - int pid, wid, leader_pid; + int pid; + int wid; b = bundle_decode(pkt->data, pkt->len); bundle_get_str(b, AUL_K_PID, &buf); pid = atoi(buf); - bundle_get_str(b, AUL_K_WID, &buf); - wid = atoi(buf); - bundle_get_str(b, AUL_K_LEADER_PID, &buf); - leader_pid = atoi(buf); bundle_free(b); - app_group_add(leader_pid, pid, wid); - __real_send(clifd, 0); + wid = app_group_get_window(pid); + __send_result_to_client(clifd, wid); return 0; } -static int __dispatch_app_group_remove(int clifd, const app_pkt_t *pkt, struct ucred *cr) +static int __dispatch_app_group_set_window(int clifd, const app_pkt_t *pkt, struct ucred *cr) { bundle *b; char *buf; - int pid; + int wid; + int ret; b = bundle_decode(pkt->data, pkt->len); - bundle_get_str(b, AUL_K_PID, &buf); - pid = atoi(buf); + bundle_get_str(b, AUL_K_WID, &buf); + wid = atoi(buf); bundle_free(b); - app_group_remove(pid); - __real_send(clifd, 0); + ret = app_group_set_window(cr->pid, wid); + __send_result_to_client(clifd, ret); - return 0; + return ret; } -static int __dispatch_app_group_get_window(int clifd, const app_pkt_t *pkt, struct ucred *cr) +static int __dispatch_app_group_get_fg_flag(int clifd, const app_pkt_t *pkt, struct ucred *cr) { bundle *b; char *buf; int pid; - int wid; + int fg; b = bundle_decode(pkt->data, pkt->len); bundle_get_str(b, AUL_K_PID, &buf); pid = atoi(buf); bundle_free(b); - wid = app_group_get_window(pid); - __real_send(clifd, wid); + fg = app_group_get_fg_flag(pid); + __send_result_to_client(clifd, fg); return 0; } -static int __dispatch_app_group_resume(int clifd, const app_pkt_t *pkt, struct ucred *cr) +static int __dispatch_app_group_clear_top(int clifd, const app_pkt_t *pkt, struct ucred *cr) { - app_group_resume(cr->pid); - __real_send(clifd, 0); + app_group_clear_top(cr->pid); + __send_result_to_client(clifd, 0); return 0; } -static int __dispatch_app_group_get_leader_pid(int clifd, const app_pkt_t *pkt, struct ucred *cr) +static int __dispatch_app_group_get_leader_pid(int clifd, + const app_pkt_t *pkt, struct ucred *cr) { bundle *b; char *buf; @@ -492,25 +491,46 @@ static int __dispatch_app_group_get_leader_pid(int clifd, const app_pkt_t *pkt, pid = atoi(buf); bundle_free(b); lpid = app_group_get_leader_pid(pid); - __real_send(clifd, lpid); + __send_result_to_client(clifd, lpid); return 0; } -static int __dispatch_app_group_get_leader_pids(int clifd, const app_pkt_t *pkt, struct ucred *cr) +static int __dispatch_app_group_get_leader_pids(int clifd, + const app_pkt_t *pkt, struct ucred *cr) { int cnt; int *pids; - int empty[1] = { 0 }; + unsigned char empty[1] = { 0 }; app_group_get_leader_pids(&cnt, &pids); if (pids == NULL || cnt == 0) { - __send_result_data(clifd, APP_GROUP_GET_LEADER_PIDS, - (unsigned char *)empty, 0); + __send_result_data(clifd, APP_GROUP_GET_LEADER_PIDS, empty, 0); } else { __send_result_data(clifd, APP_GROUP_GET_LEADER_PIDS, - (unsigned char *)pids, cnt * sizeof(int)); + (unsigned char *)pids, cnt * sizeof(int)); + } + if (pids != NULL) + free(pids); + + return 0; +} + +static int __dispatch_app_group_get_idle_pids(int clifd, + const app_pkt_t *pkt, struct ucred *cr) +{ + int cnt; + int *pids; + unsigned char empty[1] = { 0 }; + + app_group_get_idle_pids(&cnt, &pids); + + if (pids == NULL || cnt == 0) { + __send_result_data(clifd, APP_GROUP_GET_IDLE_PIDS, empty, 0); + } else { + __send_result_data(clifd, APP_GROUP_GET_IDLE_PIDS, + (unsigned char *)pids, cnt * sizeof(int)); } if (pids != NULL) free(pids); @@ -525,7 +545,7 @@ static int __dispatch_app_group_get_group_pids(int clifd, const app_pkt_t *pkt, int leader_pid; int cnt; int *pids; - int empty[1] = { 0 }; + unsigned char empty[1] = { 0 }; b = bundle_decode(pkt->data, pkt->len); bundle_get_str(b, AUL_K_LEADER_PID, &buf); @@ -534,11 +554,10 @@ static int __dispatch_app_group_get_group_pids(int clifd, const app_pkt_t *pkt, app_group_get_group_pids(leader_pid, &cnt, &pids); if (pids == NULL || cnt == 0) { - __send_result_data(clifd, APP_GROUP_GET_GROUP_PIDS, - (unsigned char *)empty, 0); + __send_result_data(clifd, APP_GROUP_GET_GROUP_PIDS, empty, 0); } else { __send_result_data(clifd, APP_GROUP_GET_GROUP_PIDS, - (unsigned char *)pids, cnt * sizeof(int)); + (unsigned char *)pids, cnt * sizeof(int)); } if (pids != NULL) free(pids); @@ -546,6 +565,16 @@ static int __dispatch_app_group_get_group_pids(int clifd, const app_pkt_t *pkt, return 0; } +static int __dispatch_app_group_lower(int clifd, const app_pkt_t *pkt, struct ucred *cr) +{ + int ret = 0; + + app_group_lower(cr->pid, &ret); + __send_result_to_client(clifd, ret); + + return ret; +} + static int __dispatch_app_start(int clifd, const app_pkt_t *pkt, struct ucred *cr) { const char *appid; @@ -956,13 +985,15 @@ static app_cmd_dispatch_func dispatch_table[APP_CMD_MAX] = { [APP_TERM_BGAPP_BY_PID] = __dispatch_app_term, [APP_PAUSE] = __dispatch_app_pause, [APP_PAUSE_BY_PID] = __dispatch_app_process_by_pid, - [APP_GROUP_ADD] = __dispatch_app_group_add, - [APP_GROUP_REMOVE] = __dispatch_app_group_remove, [APP_GROUP_GET_WINDOW] = __dispatch_app_group_get_window, + [APP_GROUP_SET_WINDOW] = __dispatch_app_group_set_window, + [APP_GROUP_GET_FG] = __dispatch_app_group_get_fg_flag, + [APP_GROUP_GET_LEADER_PID] = __dispatch_app_group_get_leader_pid, [APP_GROUP_GET_LEADER_PIDS] = __dispatch_app_group_get_leader_pids, [APP_GROUP_GET_GROUP_PIDS] = __dispatch_app_group_get_group_pids, - [APP_GROUP_RESUME] = __dispatch_app_group_resume, - [APP_GROUP_GET_LEADER_PID] = __dispatch_app_group_get_leader_pid, + [APP_GROUP_GET_IDLE_PIDS] = __dispatch_app_group_get_idle_pids, + [APP_GROUP_LOWER] = __dispatch_app_group_lower, + [APP_GROUP_CLEAR_TOP] = __dispatch_app_group_clear_top, [APP_GET_STATUS] = __dispatch_app_get_status, [AMD_RELOAD_APPINFO] = __dispatch_amd_reload_appinfo, [AGENT_DEAD_SIGNAL] = __dispatch_agent_dead_signal, diff --git a/am_daemon/amd_status.c b/am_daemon/amd_status.c index 76dd2ec..ef2636b 100644 --- a/am_daemon/amd_status.c +++ b/am_daemon/amd_status.c @@ -84,28 +84,17 @@ int _status_update_app_info_list(int pid, int status, uid_t uid) { GSList *iter = NULL; app_status_info_t *info_t = NULL; - bool is_sub_app = true; for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter)) { info_t = (app_status_info_t *)iter->data; if((pid == info_t->pid) && ((info_t->uid == uid) || (info_t->uid == 0))) { info_t->status = status; - is_sub_app = false; break; } } - for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter)) - { - info_t = (app_status_info_t *)iter->data; - - //SECURE_LOGD("%s, %d, %d", info_t->appid, info_t->pid, info_t->status); - } - - if (is_sub_app) { - app_group_set_status(pid, status); - } + app_group_set_status(pid, status, false); return 0; } @@ -166,7 +155,7 @@ int _status_get_app_info_status(int pid, uid_t uid) } } - return -1; + return app_group_get_status(pid); } int _status_app_is_running(const char *appid, uid_t uid) diff --git a/include/app_sock.h b/include/app_sock.h index b9c5411..d741363 100644 --- a/include/app_sock.h +++ b/include/app_sock.h @@ -58,13 +58,15 @@ enum app_cmd { APP_TERM_BGAPP_BY_PID, APP_PAUSE, APP_PAUSE_BY_PID, - APP_GROUP_ADD, - APP_GROUP_REMOVE, APP_GROUP_GET_WINDOW, + APP_GROUP_SET_WINDOW, + APP_GROUP_GET_FG, + APP_GROUP_GET_LEADER_PID, APP_GROUP_GET_LEADER_PIDS, APP_GROUP_GET_GROUP_PIDS, - APP_GROUP_RESUME, - APP_GROUP_GET_LEADER_PID, + APP_GROUP_GET_IDLE_PIDS, + APP_GROUP_LOWER, + APP_GROUP_CLEAR_TOP, APP_GET_STATUS, APP_GET_SOCKET_PAIR, diff --git a/include/aul.h b/include/aul.h index 4abb9f0..11836e0 100644 --- a/include/aul.h +++ b/include/aul.h @@ -1788,6 +1788,16 @@ int aul_app_group_get_window(int pid); /* * This API is only for Appfw internally. */ +int aul_app_group_get_window(int pid); + +/* + * This API is only for Appfw internally. + */ +int aul_app_group_set_window(int wid); + +/* + * This API is only for Appfw internally. + */ void aul_app_group_get_leader_pids(int *cnt, int **pids); /* @@ -1813,6 +1823,21 @@ int aul_app_group_is_top(void); /* * This API is only for Appfw internally. */ +int aul_app_group_get_fg_flag(int pid); + +/* + * This API is only for Appfw internally. + */ +void aul_app_group_lower(int *exit); + +/* + * This API is only for Appfw internally. + */ +void aul_app_group_get_idle_pids(int *cnt, int **pids); + +/* + * This API is only for Appfw internally. + */ int aul_request_data_control_socket_pair(bundle *b, int *fd); /* diff --git a/packaging/aul.spec b/packaging/aul.spec index ca150e1..1531791 100644 --- a/packaging/aul.spec +++ b/packaging/aul.spec @@ -41,6 +41,7 @@ BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(iniparser) BuildRequires: pkgconfig(sqlite3) %if %{with wayland} +BuildRequires: pkgconfig(ecore-wayland) BuildRequires: pkgconfig(wayland-client) BuildRequires: pkgconfig(tizen-extension-client) %endif @@ -133,6 +134,7 @@ systemctl daemon-reload %attr(0644,root,root) %{_libdir}/libaul.so.* %{_bindir}/aul_test %{_bindir}/app_launcher +%{_bindir}/appgroup_info %{_datadir}/aul/miregex/* %{_datadir}/aul/preload_list.txt %{_datadir}/aul/preexec_list.txt diff --git a/src/app_group.c b/src/app_group.c index 229e43a..7079ade 100644 --- a/src/app_group.c +++ b/src/app_group.c @@ -1,145 +1,42 @@ +#define _GNU_SOURCE #include #include #include #include #include -#include - -#include - +#include #include "aul.h" #include "aul_api.h" #include "aul_util.h" #include "app_sock.h" -#include "simple_util.h" #include "launch.h" +#include "simple_util.h" -#ifdef WAYLAND -#include -#include -static struct tizen_policy *tz_policy = NULL; - -static void _reg_handle_global(void *data, struct wl_registry *reg, uint32_t id, - const char *interface, uint32_t ver) -{ - if (!strcmp(interface, "tizen_policy")) { - tz_policy = wl_registry_bind(reg, id, - &tizen_policy_interface, 1); - } -} - -static void _reg_handle_global_remove(void *data, struct wl_registry *reg, - uint32_t id) -{ - /* do nothing */ -} - -static const struct wl_registry_listener reg_listener = { - _reg_handle_global, - _reg_handle_global_remove -}; -#endif - -SLPAPI void aul_app_group_add(int leader_pid, int pid, int wid) -{ - bundle *b; - char buf[128]; - - b = bundle_create(); - snprintf(buf, 128, "%d", leader_pid); - bundle_add_str(b, AUL_K_LEADER_PID, buf); - - snprintf(buf, 128, "%d", pid); - bundle_add_str(b, AUL_K_PID, buf); - - snprintf(buf, 128, "%d", wid); - bundle_add_str(b, AUL_K_WID, buf); - - app_send_cmd(AUL_UTIL_PID, APP_GROUP_ADD, b); - bundle_free(b); -} - -SLPAPI void aul_app_group_remove(int pid) +SLPAPI int aul_app_group_get_window(int pid) { + int ret; bundle *b; char buf[128]; b = bundle_create(); snprintf(buf, 128, "%d", pid); bundle_add_str(b, AUL_K_PID, buf); - - app_send_cmd(AUL_UTIL_PID, APP_GROUP_REMOVE, b); + ret = app_send_cmd(AUL_UTIL_PID, APP_GROUP_GET_WINDOW, b); bundle_free(b); -} -SLPAPI void aul_app_group_attach_window(int parent_wid, int child_wid) -{ -#ifdef WAYLAND - struct wl_display *dpy; - struct wl_registry *reg; - - dpy = wl_display_connect(NULL); - reg = wl_display_get_registry(dpy); - wl_registry_add_listener(reg, ®_listener, NULL); - wl_display_roundtrip(dpy); - - if (!tz_policy) { - _E("ERR: no tizen_policy global interface"); - wl_registry_destroy(reg); - wl_display_disconnect(dpy); - return; - } - - tizen_policy_set_transient_for(tz_policy, child_wid, parent_wid); - wl_display_roundtrip(dpy); - - tizen_policy_destroy(tz_policy); - wl_registry_destroy(reg); - wl_display_disconnect(dpy); -#else - /* ecore_x_icccm_transient_for_set(child_wid, parent_wid); */ -#endif -} - -SLPAPI void aul_app_group_detach_window(int child_wid) -{ -#ifdef WAYLAND - struct wl_display *dpy; - struct wl_registry *reg; - - dpy = wl_display_connect(NULL); - reg = wl_display_get_registry(dpy); - wl_registry_add_listener(reg, ®_listener, NULL); - wl_display_roundtrip(dpy); - - if (!tz_policy) { - _E("ERR: no tz_policy global interface"); - wl_registry_destroy(reg); - wl_display_disconnect(dpy); - return; - } - - tizen_policy_unset_transient_for(tz_policy, child_wid); - wl_display_roundtrip(dpy); - - tizen_policy_destroy(tz_policy); - wl_registry_destroy(reg); - wl_display_disconnect(dpy); -#else - /* ecore_x_icccm_transient_for_unset(child_wid); */ -#endif + return ret; } -SLPAPI int aul_app_group_get_window(int pid) +SLPAPI int aul_app_group_set_window(int wid) { int ret; bundle *b; char buf[128]; b = bundle_create(); - snprintf(buf, 128, "%d", pid); - bundle_add_str(b, AUL_K_PID, buf); - ret = app_send_cmd(AUL_UTIL_PID, APP_GROUP_GET_WINDOW, b); + snprintf(buf, 128, "%d", wid); + bundle_add_str(b, AUL_K_WID, buf); + ret = app_send_cmd(AUL_UTIL_PID, APP_GROUP_SET_WINDOW, b); bundle_free(b); return ret; @@ -155,7 +52,7 @@ SLPAPI void aul_app_group_get_leader_pids(int *cnt, int **pids) NULL, 0); if (ret != NULL) { *cnt = ret->len / sizeof(int); - if (ret->len > 0 && ret->len <= INT_MAX) { + if (ret->len > 0 && ret->len <= AUL_SOCK_MAXBUFF - 8) { *pids = malloc(ret->len); if (*pids == NULL) { _E("out of memory"); @@ -226,8 +123,8 @@ SLPAPI int aul_app_group_get_leader_pid(int pid) SLPAPI int aul_app_group_clear_top(void) { - int dummy[1] = { 0 }; - return __app_send_raw(AUL_UTIL_PID, APP_GROUP_RESUME, (unsigned char *)dummy, 0); + unsigned char dummy[1] = { 0 }; + return __app_send_raw(AUL_UTIL_PID, APP_GROUP_CLEAR_TOP, dummy, 0); } SLPAPI int aul_app_group_is_top(void) @@ -251,3 +148,51 @@ SLPAPI int aul_app_group_is_top(void) return 1; } + +SLPAPI int aul_app_group_get_fg_flag(int pid) +{ + int ret; + bundle *b; + char buf[128]; + + b = bundle_create(); + snprintf(buf, 128, "%d", pid); + bundle_add_str(b, AUL_K_PID, buf); + ret = app_send_cmd(AUL_UTIL_PID, APP_GROUP_GET_FG, b); + bundle_free(b); + + return ret; +} + +SLPAPI void aul_app_group_lower(int *exit) +{ + int ret; + unsigned char dummy[1] = { 0 }; + ret = __app_send_raw(AUL_UTIL_PID, APP_GROUP_LOWER, dummy, 0); + *exit = ret; +} + +SLPAPI void aul_app_group_get_idle_pids(int *cnt, int **pids) +{ + app_pkt_t *ret = NULL; + *cnt = 0; + *pids = NULL; + + ret = __app_send_cmd_with_result(AUL_UTIL_PID, APP_GROUP_GET_IDLE_PIDS, + NULL, 0); + if (ret != NULL) { + *cnt = ret->len / sizeof(int); + if (ret->len > 0 && ret->len <= AUL_SOCK_MAXBUFF - 8) { + *pids = malloc(ret->len); + if (*pids == NULL) { + _E("out of memory"); + free(ret); + return; + } + + memcpy(*pids, ret->data, ret->len); + } + free(ret); + } +} + diff --git a/tool/app_group_info.c b/tool/app_group_info.c new file mode 100644 index 0000000..833816c --- /dev/null +++ b/tool/app_group_info.c @@ -0,0 +1,153 @@ +#include +#include +#include "aul.h" + +static void print_app_status(int status); + +static void print_idle_info(void) +{ + int cnt = 0; + int *pids = NULL; + int i; + char appid_buf[1024] = {0,}; + int ret; + + aul_app_group_get_idle_pids(&cnt, &pids); + printf("< Idle : %d >\n", cnt); + if (pids) { + for (i = 0; i < cnt; ++i) { + printf("---------------------------\n"); + printf(" pid : %d\n", pids[i]); + ret = aul_app_get_appid_bypid(pids[i], appid_buf, sizeof(appid_buf) - 1); + + if (ret != AUL_R_OK) { + appid_buf[0] = '\0'; + } + printf(" appid : %s\n", appid_buf); + } + + free(pids); + } +} + +static int print_info(void) +{ + int *leader_pids = NULL; + int *member_pids = NULL; + int group_cnt = 0; + int member_cnt = 0; + int win_id = 0; + int group_num = 0; + int member_num = 0; + int app_status = -1; + int ret = 0; + char appid_buf[1024] = {0,}; + char pkgid_buf[1024] = {0,}; + int fg; + + aul_app_group_get_leader_pids(&group_cnt, &leader_pids); + printf("App group count : %d\n", group_cnt); + printf("\n"); + + if(group_cnt == 0){ + printf("No app groups\n"); + goto FINISH; + } + + for(group_num = 0; group_num < group_cnt; group_num++){ + aul_app_group_get_group_pids(leader_pids[group_num], &member_cnt, &member_pids); + + printf("< Group : %d >\n", group_num + 1); + printf("member cnt : %d\n", member_cnt); + printf("\n"); + + for(member_num = 0; member_num < member_cnt; member_num++){ + ret = aul_app_get_appid_bypid(member_pids[member_num], appid_buf, sizeof(appid_buf) - 1); + + if(ret != AUL_R_OK){ + appid_buf[0] = '\0'; + } + + ret = aul_app_get_pkgid_bypid(member_pids[member_num], pkgid_buf, sizeof(pkgid_buf) - 1); + if(ret != AUL_R_OK){ + pkgid_buf[0] = '\0'; + } + + win_id = aul_app_group_get_window(member_pids[member_num]); + fg = aul_app_group_get_fg_flag(member_pids[member_num]); + + printf("--- member : %d\n", member_num + 1); + printf(" - app id : %s\n", appid_buf); + printf(" - pkg id : %s\n", pkgid_buf); + printf(" - pid : %d\n", member_pids[member_num]); + printf(" - win id : %d\n", win_id); + if (fg) + printf(" - fg group : TRUE\n"); + else + printf(" - fg group : FALSE\n"); + + app_status = aul_app_get_status_bypid(member_pids[member_num]); + print_app_status(app_status); + printf("\n"); + } + printf("==================================\n"); + printf("\n"); + } + +FINISH: + + if(leader_pids != NULL) + free(leader_pids); + + if(leader_pids != NULL) + free(member_pids); + + return 0; +} + +static void print_app_status(int status) +{ + switch (status) { + case STATUS_LAUNCHING: + printf(" - status : STATUS_LAUNCHING \n"); + break; + case STATUS_CREATED: + printf(" - status : STATUS_CREATED \n"); + break; + case STATUS_FOCUS: + printf(" - status : STATUS_FOCUS \n"); + break; + case STATUS_VISIBLE: + printf(" - status : STATUS_VISIBLE \n"); + break; + case STATUS_BG: + printf(" - status : STATUS_BG \n"); + break; + case STATUS_DYING: + printf(" - status : STATUS_DYING \n"); + break; + case STATUS_HOME: + printf(" - status : STATUS_HOME \n"); + break; + case STATUS_NORESTART: + printf(" - status : STATUS_NORESTART \n"); + break; + default: + printf(" - status error or unknown status\n"); + break; + }; +} + +int main(int argc, char** argv) +{ + printf("\n"); + printf("### App Group Informantion ###\n"); + printf("\n"); + + print_info(); + print_idle_info(); + + printf("### end ###\n"); + + return 0; +}