summaryrefslogtreecommitdiff
path: root/src/launch_with_result.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/launch_with_result.c')
-rw-r--r--src/launch_with_result.c151
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;
+}