summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/launch_with_result.c299
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;
}