summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiwoong Im <jiwoong.im@samsung.com>2015-11-03 14:07:37 +0900
committerJiwoong Im <jiwoong.im@samsung.com>2015-11-10 20:24:51 +0900
commitc68bd8e5a1f6fce682e6d957fac016914307aa1f (patch)
tree5272f346e86a91bc05b25d1c368e1ff52d5b81ce
parent87c2c86befa290d31efc038fc1a1d488e2ba08b6 (diff)
downloadaul-1-c68bd8e5a1f6fce682e6d957fac016914307aa1f.tar.gz
aul-1-c68bd8e5a1f6fce682e6d957fac016914307aa1f.tar.bz2
aul-1-c68bd8e5a1f6fce682e6d957fac016914307aa1f.zip
- sync implementation of app group from tizen_2.4 - add appgroup_info tool Change-Id: Ib5bd77ff6c969bab18d6dbb7affa6fd8c677c5fc Signed-off-by: Jiwoong Im <jiwoong.im@samsung.com>
-rw-r--r--CMakeLists.txt8
-rw-r--r--am_daemon/amd_app_group.c1058
-rw-r--r--am_daemon/amd_app_group.h30
-rw-r--r--am_daemon/amd_appinfo.c10
-rw-r--r--am_daemon/amd_appinfo.h5
-rw-r--r--am_daemon/amd_launch.c86
-rw-r--r--am_daemon/amd_main.c21
-rw-r--r--am_daemon/amd_request.c105
-rw-r--r--am_daemon/amd_status.c15
-rw-r--r--include/app_sock.h10
-rw-r--r--include/aul.h25
-rw-r--r--packaging/aul.spec2
-rw-r--r--src/app_group.c179
-rw-r--r--tool/app_group_info.c153
14 files changed, 1411 insertions, 296 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 91813ab5..a5834c59 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 1b66a380..c22c7d54 100644
--- a/am_daemon/amd_app_group.c
+++ b/am_daemon/amd_app_group.c
@@ -1,30 +1,132 @@
+#define _GNU_SOURCE
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include <stdint.h>
-
+#include <stdlib.h>
+#include <stdbool.h>
#include <glib.h>
-
#include <aul.h>
-#include <pkgmgr-info.h>
+#include <aul_svc.h>
+#include <bundle_internal.h>
#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 <Ecore_Wayland.h>
+#include <wayland-client.h>
+#include <tizen-extension-client-protocol.h>
+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, &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, &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 d85fadc5..9d23295d 100644
--- a/am_daemon/amd_app_group.h
+++ b/am_daemon/amd_app_group.h
@@ -4,15 +4,21 @@
#include <glib.h>
#include <bundle.h>
-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 e98254ec..37269994 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 ed94a441..e5440909 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 2112569b..934639a9 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 50026ed8..81f41f69 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 cbe35465..c4c94931 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 76dd2ec1..ef2636bd 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 b9c5411e..d7413634 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 4abb9f05..11836e0c 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 ca150e17..15317917 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 229e43a3..7079adea 100644
--- a/src/app_group.c
+++ b/src/app_group.c
@@ -1,145 +1,42 @@
+#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <limits.h>
-
-#include <bundle.h>
-
+#include <bundle_internal.h>
#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 <wayland-client.h>
-#include <tizen-extension-client-protocol.h>
-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, &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, &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 00000000..833816c1
--- /dev/null
+++ b/tool/app_group_info.c
@@ -0,0 +1,153 @@
+#include <stdio.h>
+#include <stdlib.h>
+#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;
+}