diff options
Diffstat (limited to 'src/launch_with_result.c')
-rw-r--r-- | src/launch_with_result.c | 151 |
1 files changed, 133 insertions, 18 deletions
diff --git a/src/launch_with_result.c b/src/launch_with_result.c index f4c39e85..567cc222 100644 --- a/src/launch_with_result.c +++ b/src/launch_with_result.c @@ -20,6 +20,7 @@ #include <string.h> #include <pthread.h> #include <glib.h> +#include <gio/gio.h> #include <bundle_internal.h> #include "aul.h" @@ -27,13 +28,16 @@ #include "aul_sock.h" #include "aul_util.h" #include "aul_svc.h" +#include "aul_error.h" #include "launch.h" typedef struct _app_resultcb_info_t { + GIOChannel *io; int launched_pid; int seq_num; - void (*cb_func) (bundle *kb, int is_cancel, void *data); - void *priv_data; + void (*reply_cb)(bundle *b, int is_cancel, void *data); + void (*error_cb)(int result, void *data); + void *user_data; void (*caller_cb) (int launched_pid, void *data); void *caller_data; } app_resultcb_info_t; @@ -95,16 +99,19 @@ static void __destroy_resultcb(app_resultcb_info_t *info) if (!info) return; + if (info->io) + g_io_channel_unref(info->io); + free(info); } -static app_resultcb_info_t *__create_resultcb(int pid, - void (*cbfunc)(bundle *b, int, void *), - void *data, int seq_num) +static app_resultcb_info_t *__create_resultcb(int pid, int seq_num, + void (*reply_cb)(bundle *, int, void *), + void (*error_cb)(int, void *), void *data) { app_resultcb_info_t *info; - info = (app_resultcb_info_t *)malloc(sizeof(app_resultcb_info_t)); + info = calloc(1, sizeof(app_resultcb_info_t)); if (info == NULL) { _E("Out of memory"); return NULL; @@ -112,10 +119,9 @@ static app_resultcb_info_t *__create_resultcb(int pid, 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->reply_cb = reply_cb; + info->error_cb = error_cb; + info->user_data = data; return info; } @@ -166,7 +172,7 @@ static int __call_app_result_callback(bundle *kb, int is_cancel, } } - if (info->cb_func == NULL) { + if (info->reply_cb == NULL) { _E("Callback function is null"); return -1; } @@ -175,8 +181,9 @@ static int __call_app_result_callback(bundle *kb, int is_cancel, /* In case of aul_forward_app, update the callback data */ if (is_cancel == 1 && fwdpid_str) { launched_pid = atoi(fwdpid_str); - new_info = __create_resultcb(launched_pid, info->cb_func, - info->priv_data, num); + new_info = __create_resultcb(launched_pid, num, + info->reply_cb, info->error_cb, + info->user_data); if (new_info) __add_resultcb(new_info); @@ -191,7 +198,7 @@ static int __call_app_result_callback(bundle *kb, int is_cancel, goto end; } - info->cb_func(kb, is_cancel, info->priv_data); + info->reply_cb(kb, is_cancel, info->user_data); __remove_resultcb(info); __destroy_resultcb(info); @@ -257,7 +264,7 @@ static int __launch_app_with_result(int cmd, const char *appid, bundle *kb, ret = app_request_to_launchpad_for_uid(cmd, appid, kb, uid); if (ret > 0) { - info = __create_resultcb(ret, callback, data, num); + info = __create_resultcb(ret, num, callback, NULL, data); if (info) __add_resultcb(info); } @@ -575,9 +582,10 @@ API int aul_invoke_caller_cb(void *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); + info->seq_num, + info->reply_cb, + info->error_cb, + info->user_data); if (!new_info) break; @@ -609,3 +617,110 @@ API int aul_launch_app_with_result_async_for_uid(const char *appid, bundle *b, return __launch_app_with_result(APP_START_RES_ASYNC, appid, b, callback, data, uid); } + +static gboolean __aul_error_handler(GIOChannel *io, + GIOCondition cond, gpointer user_data) +{ + int fd = g_io_channel_unix_get_fd(io); + app_resultcb_info_t *info = (app_resultcb_info_t *)user_data; + int res; + + if (!info) { + _E("Critical error!"); + return G_SOURCE_REMOVE; + } + + res = aul_sock_recv_result_with_fd(fd); + if (res < 1) + res = aul_error_convert(res); + + _W("Sequence(%d), result(%d)", info->seq_num, res); + + if (info->error_cb) { + info->error_cb(res, info->user_data); + info->error_cb = NULL; + } + + if (res > 0 && info->reply_cb) { + info->launched_pid = res; + __add_resultcb(info); + } else { + __destroy_resultcb(info); + } + + return G_SOURCE_REMOVE; +} + +static int __resultcb_add_watch(int fd, app_resultcb_info_t *info) +{ + GIOCondition cond = G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP; + guint source; + + info->io = g_io_channel_unix_new(fd); + if (!info->io) { + _E("Failed to create gio channel"); + return -1; + } + + source = g_io_add_watch(info->io, cond, __aul_error_handler, info); + if (!source) { + _E("Failed to add gio watch"); + return -1; + } + g_io_channel_set_close_on_unref(info->io, TRUE); + + return 0; +} + +API int aul_send_launch_request_for_uid(const char *appid, bundle *b, uid_t uid, + void (*reply_cb)(bundle *b, int, void *), + void (*error_cb)(int, void *), + void *user_data) +{ + app_resultcb_info_t *info; + char buf[12]; + int seq_num; + int fd; + + if (!aul_is_initialized()) { + if (aul_launch_init(NULL, NULL) < 0) { + _E("Failed to initialize aul launch"); + return AUL_R_ENOINIT; + } + } + + if (!appid || !b || !error_cb) { + _E("Invalid parameter"); + return AUL_R_EINVAL; + } + + seq_num = __gen_seq_num(); + snprintf(buf, sizeof(buf), "%d", seq_num); + bundle_del(b, AUL_K_SEQ_NUM); + bundle_add(b, AUL_K_SEQ_NUM, buf); + + _W("Sequence(%d), appid(%s)", seq_num, appid); + fd = app_request_to_launchpad_for_uid(APP_SEND_LAUNCH_REQUEST, + appid, b, uid); + if (fd < 0 || fd > sysconf(_SC_OPEN_MAX)) { + _E("Failed to send launch request. appid(%s), result(%d)", + appid, fd); + return fd; + } + + info = __create_resultcb(-1, seq_num, reply_cb, error_cb, user_data); + if (!info) { + _E("Failed to create resultcb info"); + close(fd); + return AUL_R_ERROR; + } + + if (__resultcb_add_watch(fd, info) < 0) { + _E("Failed to add resultcb watch"); + __destroy_resultcb(info); + close(fd); + return AUL_R_ERROR; + } + + return AUL_R_OK; +} |