ENDIF()
MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+IF (with_wayland)
+ ADD_DEFINITIONS("-DWAYLAND")
+ENDIF (with_wayland)
+IF (with_x11)
+ ADD_DEFINITIONS("-DX11")
+ENDIF (with_x11)
# Set required packages
INCLUDE(FindPkgConfig)
SET(AUL-1_PKG_CHECK_MODULES dlog app-checker rua glib-2.0 vconf pkgmgr-info privacy-manager-client pkgmgr)
pkg_check_modules(pkgs REQUIRED ${AUL-1_PKG_CHECK_MODULES} )
-pkg_check_modules(libpkgs REQUIRED dlog bundle dbus-glib-1 ail xdgmime app-checker libtzplatform-config pkgmgr-info libsystemd-daemon security-manager)
+SET(AUL-1_LIB_PKG_CHECK_MODULES dlog bundle dbus-glib-1 ail xdgmime app-checker libtzplatform-config pkgmgr-info libsystemd-daemon security-manager)
+IF (with_wayland)
+ pkg_check_modules(libpkgs REQUIRED ${AUL-1_LIB_PKG_CHECK_MODULES} wayland-client)
+ENDIF (with_wayland)
+IF (with_x11)
+ pkg_check_modules(libpkgs REQUIRED ${AUL-1_LIB_PKG_CHECK_MODULES})
+ENDIF (with_x11)
+
PKG_CHECK_MODULES(PKGS REQUIRED glib-2.0 gio-2.0 dlog bundle rua)
FIND_LIBRARY(LIB_DL dl)
### Build ###
# aul_mods : modules (static library)
+SET(SRCS_aul_mods src/app_sock.c src/simple_util.c)
+IF (with_wayland)
+ SET(SRCS_aul_mods ${SRCS_aul_mods} src/tizen-transient-for-protocol.c)
+ENDIF (with_wayland)
add_library(aul_mods STATIC
- src/app_sock.c
- src/simple_util.c
+ ${SRCS_aul_mods}
)
# aul
src/key.c
src/status.c
src/aul_path.c
+ src/app_group.c
)
target_link_libraries(aul aul_mods ${libpkgs_LDFLAGS})
SET_TARGET_PROPERTIES(aul PROPERTIES SOVERSION ${VERSION_MAJOR})
am_daemon/amd_appinfo.c
am_daemon/amd_launch.c
am_daemon/amd_status.c
+ am_daemon/amd_app_group.c
)
SET(AUL-1_LINK_LIBRARY amd aul_mods app-checker-server glib-2.0 bundle ail aul)
target_link_libraries(${AUL-1_LINK_LIBRARY} ${pkgs_LDFLAGS})
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <aul.h>
+#include <pkgmgr-info.h>
+
+#include "app_sock.h"
+#include "simple_util.h"
+
+#define APP_SVC_K_LAUNCH_MODE "__APP_SVC_LAUNCH_MODE__"
+
+static GHashTable *app_group_hash = NULL;
+static int dead_pid = -1;
+static int focused_leader_pid = -1;
+
+typedef struct _app_group_context_t {
+ int pid;
+ int wid;
+ int status;
+} app_group_context_t;
+
+static gint __comp_pid(gconstpointer a, gconstpointer b)
+{
+ app_group_context_t *ac1 = (app_group_context_t*) a;
+
+ return ac1->pid - (int)b;
+}
+
+static void __list_destroy_cb(gpointer data)
+{
+ free(data);
+}
+
+static gboolean __hash_table_cb(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ int pid = (int) user_data;
+ GList *list = (GList*) value;
+ GList *itr = g_list_first(list);
+
+ while (itr != NULL) {
+ app_group_context_t *ac = (app_group_context_t*) itr->data;
+
+ if (ac->pid == pid) {
+ free(ac);
+ list = g_list_remove_link(list, itr);
+ if (g_list_length(list) == 0) {
+ g_list_free_full(list, __list_destroy_cb);
+ return TRUE;
+ } else
+ return FALSE;
+ }
+ itr = g_list_next(itr);
+ }
+
+ return FALSE;
+}
+
+static void __print_table()
+{
+ 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;
+
+ _D("app_group key= %d pid=%d", (int ) key, ac->pid);
+ i = g_list_next(i);
+ }
+ }
+
+}
+
+static gboolean __is_top(int pid)
+{
+ int cnt;
+ int *pids = NULL;
+ int i;
+ gboolean found = FALSE;
+
+ app_group_get_leader_pids(&cnt, &pids);
+ 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;
+
+ if (gpids != NULL)
+ free(gpids);
+
+ if (found)
+ break;
+ }
+
+ if (pids != NULL)
+ free(pids);
+
+ _D("is top: %d", found);
+ return found;
+}
+
+static GList* __find_removable_apps(int from)
+{
+ int cnt;
+ int *pids = NULL;
+ GList *list = NULL;
+ gboolean found = FALSE;
+
+ app_group_get_leader_pids(&cnt, &pids);
+
+ int i, j;
+ int lpid = -1;
+
+ for (i = 0; i < cnt; i++) {
+ int *gpids = NULL;
+ int gcnt;
+
+ app_group_get_group_pids(pids[i], &gcnt, &gpids);
+ for (j = 0; j < gcnt; j++) {
+ if (gpids[j] == from) {
+ found = TRUE;
+ continue;
+ }
+
+ if (found) {
+ list = g_list_append(list, (gpointer) gpids[j]);
+ }
+ }
+
+ if (gpids != NULL)
+ free(gpids);
+
+ if (found)
+ break;
+ }
+
+ if (pids != NULL)
+ free(pids);
+
+ return list;
+}
+
+void app_group_init()
+{
+ app_group_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
+ NULL);
+}
+
+void app_group_add(int leader_pid, int pid, int wid)
+{
+ app_group_context_t *ac = malloc(sizeof(app_group_context_t));
+ if (ac == NULL) {
+ _E("out of memory");
+ return;
+ }
+
+ ac->pid = pid;
+ ac->wid = wid;
+ 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)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);
+}
+
+void app_group_remove(int pid)
+{
+ g_hash_table_foreach_remove(app_group_hash, __hash_table_cb,
+ GINT_TO_POINTER(pid));
+}
+
+int app_group_get_window(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->wid;
+ }
+ i = g_list_next(i);
+ }
+ }
+
+ return -1;
+}
+
+void app_group_clear_top(int pid)
+{
+ if (!__is_top(pid)) {
+ GList *list = __find_removable_apps(pid);
+
+ if (list != NULL) {
+ GList *itr = g_list_last(list);
+
+ while (itr != NULL) {
+ int p = (int)(itr->data);
+
+ aul_app_group_detach_window(p);
+ _term_sub_app(p);
+ app_group_remove(p);
+ itr = g_list_previous(itr);
+ }
+ g_list_free(list);
+ }
+ }
+}
+
+void app_group_resume(int pid)
+{
+ app_group_clear_top(pid);
+}
+
+gboolean app_group_is_group_app(bundle* kb, uid_t uid)
+{
+ if (kb == NULL)
+ return FALSE;
+
+ char *str = NULL;
+ char *mode = NULL;
+ char *appid = NULL;
+ int ret;
+
+ pkgmgrinfo_appinfo_h handle;
+
+ 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;
+ }
+
+ if (mode != NULL && strncmp(mode, "caller", 6) == 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;
+}
+
+void app_group_get_leader_pids(int *cnt, int **pids)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ int size = g_hash_table_size(app_group_hash);
+ int *leader_pids;
+
+ if (size > 0) {
+ leader_pids = (int*) malloc(sizeof(int) * size);
+ if (leader_pids == NULL) {
+ _E("out of memory");
+ *cnt = NULL;
+ *pids = NULL;
+ return;
+ }
+
+ g_hash_table_iter_init(&iter, app_group_hash);
+ int i = 0;
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ leader_pids[i] = (int) key;
+ i++;
+ }
+
+ *cnt = size;
+ *pids = leader_pids;
+ } else {
+ *cnt = 0;
+ *pids = NULL;
+ }
+}
+
+gboolean app_group_is_leader_pid(int pid)
+{
+ int cnt;
+ int *pids = NULL;
+ int i;
+
+ app_group_get_leader_pids(&cnt, &pids);
+
+ for (i=0; i<cnt; i++) {
+ if (pid == pids[i]) {
+ free(pids);
+ return TRUE;
+ }
+ }
+
+ if (pids != NULL)
+ free(pids);
+
+ return FALSE;
+}
+
+void app_group_get_group_pids(int leader_pid, int *cnt, int **pids)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init(&iter, app_group_hash);
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ if ((int) key == leader_pid) {
+ GList *list = (GList*) value;
+ GList *i = g_list_first(list);
+ int size = g_list_length(list);
+
+ if (size > 0) {
+ int *pid_array = (int*) malloc(sizeof(int) * size);
+ int j = 0;
+
+ if (pid_array == NULL) {
+ _E("out of memory");
+ *cnt = 0;
+ *pids = NULL;
+ return;
+ }
+
+ while (i != NULL) {
+ app_group_context_t *ac = (app_group_context_t*) i->data;
+
+ pid_array[j] = ac->pid;
+ i = g_list_next(i);
+ j++;
+ }
+
+ *cnt = size;
+ *pids = pid_array;
+ } else {
+ *cnt = 0;
+ *pids = NULL;
+ }
+ return;
+ }
+ }
+
+ *cnt = 0;
+ *pids = NULL;
+}
+
+gboolean app_group_is_sub_app(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 *found = NULL;
+
+ if (list != NULL) {
+ if ((found = g_list_find_custom(list, (gconstpointer)pid, __comp_pid)) != NULL) {
+ if (g_list_first(list) == found)
+ return FALSE;
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void app_group_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 *found = NULL;
+ GList *before = NULL;
+ GList *after = NULL;
+
+ if (list != NULL) {
+ if ((found = g_list_find_custom(list, (gconstpointer)pid, __comp_pid)) != NULL) {
+ before = g_list_previous(found);
+ after = g_list_next(found);
+
+ if (before == NULL || after == NULL)
+ return;
+
+ _D("reroute");
+ 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);
+ break;
+ }
+ }
+ }
+}
+
+int app_group_get_leader_pid(int pid)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+ int lpid = -1;
+ int again = 0;
+
+repeat:
+ g_hash_table_iter_init(&iter, app_group_hash);
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ GList *list = (GList*) value;
+
+ if (list != NULL) {
+ if (g_list_find_custom(list, (gconstpointer)pid, __comp_pid) != NULL) {
+ lpid = (int)key;
+ break;
+ }
+ }
+ }
+
+ if (lpid == -1 && dead_pid == pid)
+ lpid = focused_leader_pid;
+
+ if (lpid == -1 && again == 0) {
+ pid = getpgid(pid);
+ again = 1;
+ goto repeat;
+ }
+
+ return lpid;
+}
+
+void app_group_set_dead_pid(int pid)
+{
+ focused_leader_pid = app_group_get_leader_pid(pid);
+ dead_pid = pid;
+
+ if (dead_pid == focused_leader_pid) {
+ focused_leader_pid = -1;
+ dead_pid = -1;
+ }
+}
+
+int app_group_get_status(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->status;
+
+ i = g_list_next(i);
+ }
+ }
+ return -1;
+}
+
+int app_group_set_status(int pid, int status)
+{
+ 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) {
+ ac->status = status;
+ return 0;
+ }
+ i = g_list_next(i);
+ }
+ }
+ return -1;
+
+}
--- /dev/null
+#ifndef __AUL_AMD_APP_GROUP_H_
+#define __AUL_AMD_APP_GROUP_H_
+
+#include <glib.h>
+#include <bundle.h>
+
+void app_group_add(int leader_pid, int pid, int wid);
+void app_group_remove(int pid);
+int app_group_get_window(int pid);
+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);
+gboolean app_group_is_sub_app(int pid);
+void app_group_reroute(int pid);
+int app_group_get_caller_pid();
+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);
+#endif
+
return ret;
}
+void _term_sub_app(int pid)
+{
+ int dummy;
+ int ret;
+
+ if ( (ret = __app_send_raw_with_noreply(pid, APP_TERM_BY_PID_ASYNC,
+ (unsigned char *)&dummy, sizeof(int))) < 0) {
+ _E("terminate packet send error - use SIGKILL");
+ if (_send_to_sigkill(pid) < 0) {
+ _E("fail to killing - %d\n", pid);
+ return;
+ }
+ }
+}
+
int _term_app(int pid, int clifd)
{
int dummy;
int ret;
- if ((ret = __app_send_raw_with_delay_reply(pid, APP_TERM_BY_PID,
- (unsigned char *)&dummy,
- sizeof(int))) < 0) {
+ if (app_group_is_leader_pid(pid)) {
+ int cnt;
+ int *pids = NULL;
+ int i;
+
+ app_group_get_group_pids(pid, &cnt, &pids);
+ if (cnt > 0) {
+ for (i = cnt-1 ; i>=0; i--) {
+ if (i != 0)
+ _term_sub_app(pids[i]);
+ app_group_remove(pids[i]);
+
+ }
+ free(pids);
+ }
+ }
+
+ if ( (ret = __app_send_raw_with_delay_reply
+ (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int))) < 0) {
_D("terminate packet send error - use SIGKILL");
if (_send_to_sigkill(pid) < 0) {
- _E("fail to killing - %d", pid);
+ _E("fail to killing - %d\n", pid);
+ __real_send(clifd, -1);
return -1;
}
+ __real_send(clifd, 0);
}
- _D("term done");
-
+ _D("term done\n");
if (ret > 0)
__set_reply_handler(ret, pid, clifd, APP_TERM_BY_PID);
int delay_reply = 0;
int pad_pid = LAUNCHPAD_PID;
bool consented = true;
+ gboolean is_group_app = FALSE;
snprintf(tmpbuf, MAX_PID_STR_BUFSZ, "%d", caller_pid);
bundle_add(kb, AUL_K_CALLER_PID, tmpbuf);
pid = _status_app_is_running_v2(appid, caller_uid);
}
+ if (app_group_is_group_app(kb, caller_uid)) {
+ pid = -1;
+ is_group_app = TRUE;
+ }
+
if (pid > 0) {
if (_status_get_app_info_status(pid) == STATUS_DYING) {
pid = -ETERMINATING;
__real_send(fd, pid);
if(pid > 0) {
- _status_add_app_info_list(appid, app_path, pid, pad_pid, caller_uid);
+ if (!is_group_app)
+ _status_add_app_info_list(appid, app_path, pid, pad_pid, caller_uid);
ret = ac_server_check_launch_privilege(appid, appinfo_get_value(ai, AIT_TYPE), pid);
return ret != AC_R_ERROR ? pid : -1;
}
#include "amd_status.h"
#include "amd_launch.h"
#include "amd_request.h"
+#include "amd_app_group.h"
#define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
* listen any more on DBUS system to catch those events.
* AMD Agents must connect to AMD Daemon to signal a dead process
*/
+ if(pid <= 0)
+ return 0;
+
+ if (app_group_is_leader_pid(pid)) {
+ app_group_clear_top(pid);
+ app_group_set_dead_pid(pid);
+ app_group_remove(pid);
+ } else if (app_group_is_sub_app(pid)) {
+ app_group_reroute(pid);
+ app_group_set_dead_pid(pid);
+ app_group_remove(pid);
+ }
+
__remove_item_running_list(pid, user);
_status_remove_app_info_list(pid, user);
return 0;
}
_requset_init();
+ app_group_init();
if (vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS,
__vconf_cb, NULL) != 0)
static int __send_result_to_client(int fd, int res);
static gboolean __request_handler(gpointer data);
+static int __send_result_data(int fd, int cmd, unsigned char *kb_data, int datalen)
+{
+ int len;
+ int ret;
+ int res = 0;
+ app_pkt_t *pkt = NULL;
+
+ if (datalen > AUL_SOCK_MAXBUFF - 8) {
+ _E("datalen > AUL_SOCK_MAXBUFF\n");
+ return -EINVAL;
+ }
+
+ pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
+ if (NULL == pkt) {
+ _E("Malloc Failed!");
+ return -ENOMEM;
+ }
+ memset(pkt, 0, AUL_SOCK_MAXBUFF);
+
+ pkt->cmd = cmd;
+ pkt->len = datalen;
+ memcpy(pkt->data, kb_data, datalen);
+
+ if ((len = send(fd, pkt, datalen + 8, MSG_NOSIGNAL)) != datalen + 8) {
+ _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
+ if(len > 0) {
+ while (len != datalen + 8) {
+ ret = send(fd, &pkt->data[len-8], datalen + 8 - len, MSG_NOSIGNAL);
+ if (ret < 0) {
+ _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
+ close(fd);
+ if (pkt) {
+ free(pkt);
+ pkt = NULL;
+ }
+ return -ECOMM;
+ }
+ len += ret;
+ _D("sendto() len - %d %d", len, datalen + 8);
+ }
+ } else {
+ close(fd);
+ if (pkt) {
+ free(pkt);
+ pkt = NULL;
+ }
+ return -ECOMM;
+ }
+ }
+ if (pkt) {
+ free(pkt);
+ pkt = NULL;
+ }
+
+ close(fd);
+ return res;
+}
+
extern int __app_dead_handler(int pid, uid_t user);
extern int __agent_dead_handler(uid_t user);
__agent_dead_handler(pcr->uid);
}
+static void __dispatch_app_group_add(int clifd, const app_pkt_t *pkt)
+{
+ bundle *b;
+ char *buf;
+ int pid, wid, leader_pid;
+
+ 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);
+}
+
+static void __dispatch_app_group_remove(int clifd, const app_pkt_t *pkt)
+{
+ bundle *b;
+ char *buf;
+ int pid;
+
+ b = bundle_decode(pkt->data, pkt->len);
+ bundle_get_str(b, AUL_K_PID, &buf);
+ pid = atoi(buf);
+ bundle_free(b);
+ app_group_remove(pid);
+ __real_send(clifd, 0);
+}
+
+static void __dispatch_app_group_get_window(int clifd, const app_pkt_t *pkt)
+{
+ bundle *b;
+ char *buf;
+ int pid;
+ int wid;
+
+ 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);
+}
+
+static void __dispatch_app_group_resume(int clifd, int pid)
+{
+ app_group_resume(pid);
+ __real_send(clifd, 0);
+}
+
+static void __dispatch_app_group_get_leader_pid(int clifd,
+ const app_pkt_t *pkt)
+{
+ bundle *b;
+ char *buf;
+ int pid;
+ int lpid;
+
+ b = bundle_decode(pkt->data, pkt->len);
+ bundle_get_str(b, AUL_K_PID, &buf);
+ pid = atoi(buf);
+ bundle_free(b);
+ lpid = app_group_get_leader_pid(pid);
+ __real_send(clifd, lpid);
+}
+
+static void __dispatch_app_group_get_leader_pids(int clifd,
+ const app_pkt_t *pkt)
+{
+ char *buf;
+ int cnt;
+ int *pids;
+ int empty[1] = { 0 };
+
+ app_group_get_leader_pids(&cnt, &pids);
+
+ if (pids == NULL || cnt == 0) {
+ __send_result_data(clifd, APP_GROUP_GET_LEADER_PIDS, empty, 0);
+ } else {
+ __send_result_data(clifd, APP_GROUP_GET_LEADER_PIDS, pids,
+ cnt * sizeof(int));
+ }
+ if (pids != NULL)
+ free(pids);
+}
+
+static void __dispatch_app_group_get_group_pids(int clifd, const app_pkt_t *pkt)
+{
+ bundle *b;
+ char *buf;
+ int leader_pid;
+ int cnt;
+ int *pids;
+ int empty[1] = { 0 };
+
+ b = bundle_decode(pkt->data, pkt->len);
+ bundle_get_str(b, AUL_K_LEADER_PID, &buf);
+ leader_pid = atoi(buf);
+ bundle_free(b);
+
+ app_group_get_group_pids(leader_pid, &cnt, &pids);
+ if (pids == NULL || cnt == 0) {
+ __send_result_data(clifd, APP_GROUP_GET_GROUP_PIDS, empty, 0);
+ } else {
+ __send_result_data(clifd, APP_GROUP_GET_GROUP_PIDS, pids,
+ cnt * sizeof(int));
+ }
+ if (pids != NULL)
+ free(pids);
+}
+
static gboolean __request_handler(gpointer data)
{
GPollFD *gpollfd = (GPollFD *) data;
appinfo_reload();
__send_result_to_client(clifd, 0);
break;
+
+ case APP_GROUP_ADD:
+ __dispatch_app_group_add(clifd, pkt);
+ break;
+
+ case APP_GROUP_REMOVE:
+ __dispatch_app_group_remove(clifd, pkt);
+ break;
+
+ case APP_GROUP_GET_WINDOW:
+ __dispatch_app_group_get_window(clifd, pkt);
+ break;
+
+ case APP_GROUP_GET_LEADER_PIDS:
+ __dispatch_app_group_get_leader_pids(clifd, pkt);
+ break;
+
+ case APP_GROUP_GET_GROUP_PIDS:
+ __dispatch_app_group_get_group_pids(clifd, pkt);
+ break;
+
+ case APP_GROUP_RESUME:
+ __dispatch_app_group_resume(clifd, cr.pid);
+ break;
+
+ case APP_GROUP_GET_LEADER_PID:
+ __dispatch_app_group_get_leader_pid(clifd, pkt);
+ break;
default:
_E("no support packet");
close(clifd);
#include "simple_util.h"
#include "app_sock.h"
#include "menu_db_util.h"
+#include "amd_app_group.h"
GSList *app_status_info_list = NULL;
{
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->user == uid) || (info_t->user == 0))) {
info_t->status = status;
+ is_sub_app = false;
break;
}
}
//SECURE_LOGD("%s, %d, %d", info_t->appid, info_t->pid, info_t->status);
}
+ if (is_sub_app) {
+ app_group_set_status(pid, status);
+ }
+
return 0;
}
for (iter = app_status_info_list; iter != NULL; iter = g_slist_next(iter))
{
info_t = (app_status_info_t *)iter->data;
+ if (app_group_is_sub_app(info_t->pid))
+ continue;
+
snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", info_t->pid);
strncat((char *)pkt->data, tmp_pid, MAX_PID_STR_BUFSZ);
strncat((char *)pkt->data, ":", 1);
APP_TERM_BGAPP_BY_PID,
APP_PAUSE,
APP_PAUSE_BY_PID,
+ APP_GROUP_ADD,
+ APP_GROUP_REMOVE,
+ APP_GROUP_GET_WINDOW,
+ APP_GROUP_GET_LEADER_PIDS,
+ APP_GROUP_GET_GROUP_PIDS,
+ APP_GROUP_RESUME,
+ APP_GROUP_GET_LEADER_PID,
/* for special purpose */
AMD_RELOAD_APPINFO,
#define AUL_K_APPID "__AUL_APPID__"
/** AUL internal private key */
#define AUL_K_PID "__AUL_PID__"
+/** AUL internal private key */
+#define AUL_K_WID "__AUL_WID__"
+/** AUL internal private key */
+#define AUL_K_LEADER_PID "__AUL_LEADER_PID__"
/** AUL internal private key - To support data control*/
#define AUL_K_DATA_CONTROL_TYPE "__AUL_DATA_CONTROL_TYPE__"
int aul_status_update(int status);
int aul_running_list_update(char *appid, char *app_path, char *pid);
+void aul_app_group_add(int leader_pid, int pid, int wid);
+void aul_app_group_remove(int pid);
+void aul_app_group_attach_window(int parent_wid, int child_wid);
+void aul_app_group_detach_window(int child_wid);
+int aul_app_group_get_window(int pid);
+void aul_app_group_get_leader_pids(int *cnt, int **pids);
+void aul_app_group_get_group_pids(int leader_pid, int *cnt, int **pids);
+int aul_app_group_get_leader_pid(int pid);
+int aul_app_group_clear_top(void);
+int aul_app_group_is_top(void);
+
+
/** @} */
--- /dev/null
+#ifndef TIZEN_TRANSIENT_FOR_CLIENT_PROTOCOL_H
+#define TIZEN_TRANSIENT_FOR_CLIENT_PROTOCOL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+struct wl_client;
+struct wl_resource;
+
+struct tizen_transient_for;
+
+extern const struct wl_interface tizen_transient_for_interface;
+
+struct tizen_transient_for_listener {
+ /**
+ * done - (none)
+ * @child_id: (none)
+ */
+ void (*done)(void *data,
+ struct tizen_transient_for *tizen_transient_for,
+ uint32_t child_id);
+};
+
+static inline int
+tizen_transient_for_add_listener(struct tizen_transient_for *tizen_transient_for,
+ const struct tizen_transient_for_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) tizen_transient_for,
+ (void (**)(void)) listener, data);
+}
+
+#define TIZEN_TRANSIENT_FOR_SET 0
+#define TIZEN_TRANSIENT_FOR_UNSET 1
+
+static inline void
+tizen_transient_for_set_user_data(struct tizen_transient_for *tizen_transient_for, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) tizen_transient_for, user_data);
+}
+
+static inline void *
+tizen_transient_for_get_user_data(struct tizen_transient_for *tizen_transient_for)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) tizen_transient_for);
+}
+
+static inline void
+tizen_transient_for_destroy(struct tizen_transient_for *tizen_transient_for)
+{
+ wl_proxy_destroy((struct wl_proxy *) tizen_transient_for);
+}
+
+static inline void
+tizen_transient_for_set(struct tizen_transient_for *tizen_transient_for, uint32_t child_id, uint32_t parent_id)
+{
+ wl_proxy_marshal((struct wl_proxy *) tizen_transient_for,
+ TIZEN_TRANSIENT_FOR_SET, child_id, parent_id);
+}
+
+static inline void
+tizen_transient_for_unset(struct tizen_transient_for *tizen_transient_for, uint32_t child_id)
+{
+ wl_proxy_marshal((struct wl_proxy *) tizen_transient_for,
+ TIZEN_TRANSIENT_FOR_UNSET, child_id);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Description=Start the Access Control server
[Service]
-EnvironmentFile=-/etc/sysconfig/prelaunch
+EnvironmentFile=-/run/tizen-system-env
ExecStartPre=/usr/bin/mkdir -p -m 1777 /tmp/alaunch
ExecStartPre=/usr/bin/chsmack -a * /tmp/alaunch
ExecStart=/usr/bin/amd
+%bcond_with x
+%bcond_with wayland
+
Name: aul
Summary: App utility library
Version: 0.0.300
BuildRequires: pkgconfig(privacy-manager-client)
BuildRequires: pkgconfig(libtzplatform-config)
BuildRequires: pkgconfig(libsystemd-daemon)
+%if %{with wayland}
+BuildRequires: pkgconfig(wayland-client)
+%endif
%description
Application utility library
Application utility library (devel)
%package test
-Summary: App utility test tools
+Summary: App utility test tools
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
CFLAGS="%{optflags} -D__emul__"; export CFLAGS
%endif
-%cmake .
+%cmake . \
+%if %{with wayland}
+-Dwith_wayland=TRUE\
+%endif
+%if %{with x}
+-Dwith_x11=TRUE\
+%endif
+
%__make %{?_smp_mflags}
%install
--- /dev/null
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <bundle.h>
+#include "aul.h"
+#include "aul_api.h"
+#include "aul_util.h"
+#include "app_sock.h"
+#include "simple_util.h"
+
+#ifdef WAYLAND
+#include <wayland-client.h>
+#include "tizen-transient-for-client-protocol.h"
+static struct tizen_transient_for *tz_transient_for = 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_transient_for"))
+ {
+ tz_transient_for = wl_registry_bind(reg,
+ id,
+ &tizen_transient_for_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)
+{
+ int ret;
+ 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);
+
+ ret = app_send_cmd(AUL_UTIL_PID, APP_GROUP_ADD, b);
+ bundle_free(b);
+}
+
+SLPAPI void aul_app_group_remove(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_REMOVE, 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_transient_for)
+ {
+ _E("ERR: no tizen_surface_extension global interface");
+ wl_registry_destroy(reg);
+ wl_display_disconnect(dpy);
+ return;
+ }
+
+ tizen_transient_for_set(tz_transient_for, child_wid, parent_wid);
+ wl_display_roundtrip(dpy);
+
+ tizen_transient_for_destroy(tz_transient_for);
+ 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_transient_for)
+ {
+ _E("ERR: no tizen_surface_extension global interface");
+ wl_registry_destroy(reg);
+ wl_display_disconnect(dpy);
+ return;
+ }
+
+ tizen_transient_for_unset(tz_transient_for, child_wid);
+ wl_display_roundtrip(dpy);
+
+ tizen_transient_for_destroy(tz_transient_for);
+ wl_registry_destroy(reg);
+ wl_display_disconnect(dpy);
+#else
+ //ecore_x_icccm_transient_for_unset(child_wid);
+#endif
+}
+
+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);
+ ret = app_send_cmd(AUL_UTIL_PID, APP_GROUP_GET_WINDOW, b);
+ bundle_free(b);
+
+ return ret;
+}
+
+SLPAPI void aul_app_group_get_leader_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_LEADER_PIDS,
+ NULL, 0);
+ if (ret != NULL) {
+ *cnt = ret->len / sizeof(int);
+ if (ret->len > 0 && ret->len <= INT_MAX) {
+ *pids = malloc(ret->len);
+ if (*pids == NULL) {
+ _E("out of memory");
+ free(ret);
+ return;
+ }
+
+ memcpy(*pids, ret->data, ret->len);
+ }
+ free(ret);
+ }
+
+}
+
+SLPAPI void aul_app_group_get_group_pids(int leader_pid, int *cnt, int **pids)
+{
+ app_pkt_t *ret = NULL;
+ bundle *b;
+ bundle_raw *br;
+ int datalen;
+ char buf[128];
+ *cnt = 0;
+ *pids = NULL;
+
+ b = bundle_create();
+ snprintf(buf, 128, "%d", leader_pid);
+ bundle_add_str(b, AUL_K_LEADER_PID, buf);
+
+ bundle_encode(b, &br, &datalen);
+ ret = __app_send_cmd_with_result(AUL_UTIL_PID, APP_GROUP_GET_GROUP_PIDS, br,
+ datalen);
+
+ if (ret != NULL) {
+ *cnt = ret->len / sizeof(int);
+ if (ret->len > 0 && ret->len <= INT_MAX) {
+ *pids = malloc(ret->len);
+ if (*pids == NULL) {
+ _E("out of memory");
+ free(br);
+ bundle_free(b);
+ free(ret);
+ return;
+ }
+
+ memcpy(*pids, ret->data, ret->len);
+ }
+ free(ret);
+ }
+
+ free(br);
+ bundle_free(b);
+}
+
+SLPAPI int aul_app_group_get_leader_pid(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_LEADER_PID, b);
+ bundle_free(b);
+
+ return ret;
+}
+
+SLPAPI int aul_app_group_clear_top(void)
+{
+ int dummy[1] = { 0 };
+ return __app_send_raw(AUL_UTIL_PID, APP_GROUP_RESUME, dummy, 0);
+}
+
+SLPAPI int aul_app_group_is_top(void)
+{
+ int lpid = aul_app_group_get_leader_pid(getpid());
+
+ if (lpid > 0) {
+ int cnt;
+ int *pids = NULL;
+ aul_app_group_get_group_pids(lpid, &cnt, &pids);
+ if (cnt > 0) {
+ if (pids[cnt-1] == getpid()) {
+ free(pids);
+ return 1;
+ }
+
+ free(pids);
+ return 0;
+ }
+ }
+
+ return 1;
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+
+static const struct wl_interface *types[] = {
+ NULL,
+ NULL,
+};
+
+static const struct wl_message tizen_transient_for_requests[] = {
+ { "set", "uu", types + 0 },
+ { "unset", "u", types + 0 },
+};
+
+static const struct wl_message tizen_transient_for_events[] = {
+ { "done", "u", types + 0 },
+};
+
+WL_EXPORT const struct wl_interface tizen_transient_for_interface = {
+ "tizen_transient_for", 1,
+ 2, tizen_transient_for_requests,
+ 1, tizen_transient_for_events,
+};
+