diff options
-rw-r--r-- | src/launch_with_result.c | 299 |
1 files changed, 166 insertions, 133 deletions
diff --git a/src/launch_with_result.c b/src/launch_with_result.c index 61bd0fcc..de9055be 100644 --- a/src/launch_with_result.c +++ b/src/launch_with_result.c @@ -18,7 +18,8 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> - +#include <pthread.h> +#include <glib.h> #include <bundle_internal.h> #include "aul.h" @@ -35,115 +36,93 @@ typedef struct _app_resultcb_info_t { void *priv_data; void (*caller_cb) (int launched_pid, void *data); void *caller_data; - struct _app_resultcb_info_t *next; } app_resultcb_info_t; static int latest_caller_pid = -1; -static app_resultcb_info_t *rescb_head = NULL; static int is_subapp = 0; static subapp_fn subapp_cb = NULL; static void *subapp_data = NULL; +static pthread_mutex_t __aul_mutex = PTHREAD_MUTEX_INITIALIZER; +static GList *__resultcb_list; + static int __gen_seq_num(void) { - static int num = 0; + static int num; + + g_atomic_int_inc(&num); - return num++; + return num; } -static void __add_resultcb(int pid, void (*cbfunc) (bundle *, int, void *), - void *data, int seq_num) +static void __add_resultcb(app_resultcb_info_t *info) { - app_resultcb_info_t *info; - - info = (app_resultcb_info_t *) malloc(sizeof(app_resultcb_info_t)); - if (info == NULL) + if (!info) return; - info->launched_pid = pid; - info->seq_num = seq_num; - info->cb_func = cbfunc; - info->priv_data = data; - info->caller_cb = NULL; - info->caller_data = NULL; - info->next = rescb_head; - rescb_head = info; + pthread_mutex_lock(&__aul_mutex); + __resultcb_list = g_list_prepend(__resultcb_list, info); + pthread_mutex_unlock(&__aul_mutex); } -static app_resultcb_info_t *__find_resultcb(int pid, bundle *kb) +static void __remove_resultcb(app_resultcb_info_t *info) { - app_resultcb_info_t *tmp; - const char *num_str; - int num; - - num_str = bundle_get_val(kb, AUL_K_SEQ_NUM); - if (num_str == NULL) { - _E("No AUL_K_SEQ_NUM"); - return NULL; - } - num = atoi(num_str); - tmp = rescb_head; - while (tmp) { - if (tmp->launched_pid == pid && tmp->seq_num == num) - return tmp; - tmp = tmp->next; - } + if (!info) + return; - return NULL; + pthread_mutex_lock(&__aul_mutex); + __resultcb_list = g_list_remove(__resultcb_list, info); + pthread_mutex_unlock(&__aul_mutex); } -static app_resultcb_info_t *__get_first_resultcb(int pid) +static app_resultcb_info_t *__find_resultcb(int pid, int num) { - app_resultcb_info_t *tmp; - - tmp = rescb_head; - while (tmp) { - if (tmp->launched_pid == pid) - return tmp; - tmp = tmp->next; + app_resultcb_info_t *info; + GList *iter; + + pthread_mutex_lock(&__aul_mutex); + iter = __resultcb_list; + while (iter) { + info = (app_resultcb_info_t *)iter->data; + if (info->launched_pid == pid && info->seq_num == num) { + pthread_mutex_unlock(&__aul_mutex); + return info; + } + iter = g_list_next(iter); } + pthread_mutex_unlock(&__aul_mutex); return NULL; } -static app_resultcb_info_t *__get_next_resultcb(app_resultcb_info_t *info, int pid) +static void __destroy_resultcb(app_resultcb_info_t *info) { - app_resultcb_info_t *tmp; - - if (info == NULL) - return NULL; - tmp = info->next; - while (tmp) { - if (tmp->launched_pid == pid) - return tmp; - tmp = tmp->next; - } + if (!info) + return; - return NULL; + free(info); } -static void __remove_resultcb(app_resultcb_info_t *info) +static app_resultcb_info_t *__create_resultcb(int pid, + void (*cbfunc)(bundle *b, int, void *), + void *data, int seq_num) { - app_resultcb_info_t *tmp; - - if (rescb_head == NULL || info == NULL) - return; + app_resultcb_info_t *info; - if (rescb_head == info) { - rescb_head = info->next; - free(info); - return; + info = (app_resultcb_info_t *)malloc(sizeof(app_resultcb_info_t)); + if (info == NULL) { + _E("Out of memory"); + return NULL; } - tmp = rescb_head; - while (tmp) { - if (tmp->next == info) { - tmp->next = info->next; - free(info); - return; - } - tmp = tmp->next; - } + info->launched_pid = pid; + info->seq_num = seq_num; + info->cb_func = cbfunc; + info->priv_data = data; + info->caller_cb = NULL; + info->caller_data = NULL; + + return info; } /** @@ -151,62 +130,75 @@ static void __remove_resultcb(app_resultcb_info_t *info) * run in caller */ static int __call_app_result_callback(bundle *kb, int is_cancel, - int launched_pid) + int launched_pid) { + app_resultcb_info_t *new_info; app_resultcb_info_t *info; int pgid; const char *fwdpid_str; const char *num_str; + int num; + if (kb == NULL) { + _E("Invalid parameter"); + return -1; + } - if (((info = __find_resultcb(launched_pid, kb)) == NULL) - || (launched_pid < 0)) { - _E("reject by pid - wait pid = %d, recvd pid = %d", getpid(), - launched_pid); + num_str = bundle_get_val(kb, AUL_K_SEQ_NUM); + if (num_str == NULL) { + _E("seq num is null"); + return -1; + } + num = atoi(num_str); + + info = __find_resultcb(launched_pid, num); + if (!info || launched_pid < 0) { + _E("reject by pid - wait pid = %d, recvd pid = %d", + getpid(), launched_pid); /* second chance - support app launched by shell script*/ pgid = getpgid(launched_pid); - if (pgid <= 1) + if (pgid <= 1) { + _E("Failed to get process group id. launched_pid(%d)", + launched_pid); return -1; - if ((info = __find_resultcb(pgid, kb)) == NULL) { + } + + info = __find_resultcb(pgid, num); + if (!info) { _E("second chance : also reject pgid - %d", pgid); return -1; } } - if (info->cb_func == NULL || kb == NULL) + if (info->cb_func == NULL) { + _E("Callback function is null"); return -1; + } + fwdpid_str = bundle_get_val(kb, AUL_K_FWD_CALLEE_PID); /* In case of aul_forward_app, update the callback data */ - if (is_cancel == 1 && - (fwdpid_str = bundle_get_val(kb, AUL_K_FWD_CALLEE_PID))) { - num_str = bundle_get_val(kb, AUL_K_SEQ_NUM); - if (num_str == NULL) { - _E("seq num is null"); - return -1; - } - - app_resultcb_info_t newinfo; - newinfo.launched_pid = atoi(fwdpid_str); - newinfo.seq_num = atoi(num_str); - newinfo.cb_func = info->cb_func; - newinfo.priv_data = info->priv_data; - newinfo.caller_cb = NULL; - newinfo.caller_data = NULL; + if (is_cancel == 1 && fwdpid_str) { + launched_pid = atoi(fwdpid_str); + new_info = __create_resultcb(launched_pid, info->cb_func, + info->priv_data, num); + if (new_info) + __add_resultcb(new_info); if (info->caller_cb) - info->caller_cb(newinfo.launched_pid, info->caller_data); + info->caller_cb(launched_pid, info->caller_data); __remove_resultcb(info); - __add_resultcb(newinfo.launched_pid, newinfo.cb_func, newinfo.priv_data, newinfo.seq_num); + __destroy_resultcb(info); - _D("change callback, fwd pid: %d", newinfo.launched_pid); + _D("change callback, fwd pid: %d", launched_pid); goto end; } info->cb_func(kb, is_cancel, info->priv_data); __remove_resultcb(info); + __destroy_resultcb(info); end: return 0; @@ -310,6 +302,7 @@ static int __launch_app_with_result(int cmd, const char *appid, bundle *kb, int ret; char num_str[MAX_LOCAL_BUFSZ]; int num; + app_resultcb_info_t *info; if (!aul_is_initialized()) { if (aul_launch_init(NULL, NULL) < 0) @@ -325,8 +318,11 @@ static int __launch_app_with_result(int cmd, const char *appid, bundle *kb, bundle_add(kb, AUL_K_SEQ_NUM, num_str); ret = app_request_to_launchpad_for_uid(cmd, appid, kb, uid); - if (ret > 0) - __add_resultcb(ret, callback, data, num); + if (ret > 0) { + info = __create_resultcb(ret, callback, data, num); + if (info) + __add_resultcb(info); + } return ret; } @@ -562,15 +558,23 @@ API int aul_subapp_terminate_request_pid(int pid) char pid_str[MAX_PID_STR_BUFSZ]; int ret; app_resultcb_info_t *info; + GList *iter; if (pid <= 0) return AUL_R_EINVAL; - info = __get_first_resultcb(pid); - while (info != NULL) { - __remove_resultcb(info); - info = __get_first_resultcb(pid); + pthread_mutex_lock(&__aul_mutex); + iter = __resultcb_list; + while (iter) { + info = (app_resultcb_info_t *)iter->data; + iter = g_list_next(iter); + if (info->launched_pid == pid) { + __resultcb_list = g_list_remove( + __resultcb_list, info); + __destroy_resultcb(info); + } } + pthread_mutex_unlock(&__aul_mutex); snprintf(pid_str, MAX_PID_STR_BUFSZ, "%d", pid); ret = app_request_to_launchpad(APP_TERM_REQ_BY_PID, pid_str, NULL); @@ -582,25 +586,29 @@ API int aul_is_subapp() return is_subapp; } -API int aul_add_caller_cb(int pid, void (*caller_cb) (int, void *), void *data) +API int aul_add_caller_cb(int pid, void (*caller_cb)(int, void *), + void *data) { app_resultcb_info_t *info; + GList *iter; if (pid <= 0) return AUL_R_EINVAL; - info = __get_first_resultcb(pid); - if (info == NULL) - return AUL_R_ERROR; - - while (info != NULL) { - if (info->caller_cb == NULL) { + pthread_mutex_lock(&__aul_mutex); + iter = __resultcb_list; + while (iter) { + info = (app_resultcb_info_t *)iter->data; + if (info->launched_pid == pid && + info->caller_cb == NULL) { info->caller_cb = caller_cb; info->caller_data = data; + pthread_mutex_unlock(&__aul_mutex); return AUL_R_OK; } - info = __get_next_resultcb(info, pid); + iter = g_list_next(iter); } + pthread_mutex_unlock(&__aul_mutex); return AUL_R_ERROR; } @@ -608,46 +616,71 @@ API int aul_add_caller_cb(int pid, void (*caller_cb) (int, void *), void *data) API int aul_remove_caller_cb(int pid, void *data) { app_resultcb_info_t *info; + GList *iter; if (pid <= 0) return AUL_R_EINVAL; - info = __get_first_resultcb(pid); - if (info == NULL) - return AUL_R_ERROR; - - while (info != NULL) { - if (info->caller_data == data) { + pthread_mutex_lock(&__aul_mutex); + iter = __resultcb_list; + while (iter) { + info = (app_resultcb_info_t *)iter->data; + if (info->launched_pid == pid && + info->caller_data == data) { info->caller_cb = NULL; info->caller_data = NULL; + pthread_mutex_unlock(&__aul_mutex); return AUL_R_OK; } - info = __get_next_resultcb(info, pid); + iter = g_list_next(iter); } + pthread_mutex_unlock(&__aul_mutex); return AUL_R_ERROR; } static gboolean __invoke_caller_cb(gpointer data) { - app_resultcb_info_t *tmp; + app_resultcb_info_t *info = (app_resultcb_info_t *)data; - tmp = rescb_head; - while (tmp) { - if (tmp->caller_data == data && tmp->caller_cb) { - tmp->caller_cb(tmp->launched_pid, tmp->caller_data); - break; - } - tmp = tmp->next; - } + if (info->caller_cb) + info->caller_cb(info->launched_pid, info->caller_data); + + __destroy_resultcb(info); return G_SOURCE_REMOVE; } API int aul_invoke_caller_cb(void *data) { - if (g_idle_add_full(G_PRIORITY_DEFAULT, __invoke_caller_cb, data, NULL) > 0) - return -1; + app_resultcb_info_t *info; + app_resultcb_info_t *new_info; + GList *iter; + + pthread_mutex_lock(&__aul_mutex); + iter = __resultcb_list; + while (iter) { + info = (app_resultcb_info_t *)iter->data; + if (info->caller_data == data) { + /* Duplicate resultcb info */ + new_info = __create_resultcb(info->launched_pid, + info->cb_func, + info->priv_data, + info->seq_num); + if (!new_info) + break; + + new_info->caller_cb = info->caller_cb; + new_info->caller_data = info->caller_data; + g_idle_add_full(G_PRIORITY_DEFAULT, + __invoke_caller_cb, + new_info, NULL); + break; + } + iter = g_list_next(iter); + + } + pthread_mutex_unlock(&__aul_mutex); return 0; } |