4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
31 #include "simple_util.h"
35 /*#define ACTIVATE_PREEMPT_FEATURE*/
37 typedef struct _app_resultcb_info_t {
39 void (*cb_func) (bundle *kb, int is_cancel, void *data);
41 void (*caller_cb) (int launched_pid, void *data);
43 struct _app_resultcb_info_t *next;
44 } app_resultcb_info_t;
46 static int latest_caller_pid = -1;
47 static app_resultcb_info_t *rescb_head = NULL;
48 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
49 static app_resultcb_info_t *rescb_head2 = NULL;
53 static int is_subapp = 0;
54 subapp_fn subapp_cb = NULL;
55 void *subapp_data = NULL;
57 pthread_mutex_t result_lock = PTHREAD_MUTEX_INITIALIZER;
59 static void __add_resultcb(int pid, void (*cbfunc) (bundle *, int, void *),
61 static app_resultcb_info_t *__find_resultcb(int pid);
62 static void __remove_resultcb(app_resultcb_info_t *info);
63 static int __call_app_result_callback(bundle *kb, int is_cancel,
65 static int __get_caller_pid(bundle *kb);
69 static void __add_resultcb(int pid, void (*cbfunc) (bundle *, int, void *),
72 app_resultcb_info_t *info;
74 info = (app_resultcb_info_t *) malloc(sizeof(app_resultcb_info_t));
77 info->launched_pid = pid;
78 info->cb_func = cbfunc;
79 info->priv_data = data;
80 info->caller_cb = NULL;
81 info->caller_data = NULL;
83 info->next = rescb_head;
87 static app_resultcb_info_t *__find_resultcb(int pid)
89 app_resultcb_info_t *tmp;
90 app_resultcb_info_t *ret = NULL;
92 pthread_mutex_lock(&result_lock);
95 if (tmp->launched_pid == pid) {
100 pthread_mutex_unlock(&result_lock);
105 static void __remove_resultcb(app_resultcb_info_t *info)
107 app_resultcb_info_t *tmp;
109 if (rescb_head == NULL || info == NULL)
112 if (rescb_head == info) {
113 rescb_head = info->next;
120 if (tmp->next == info) {
121 tmp->next = info->next;
129 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
130 static void __add_resultcb2(int pid, void (*cbfunc) (bundle *, int, void *),
133 app_resultcb_info_t *info;
137 info = (app_resultcb_info_t *) malloc(sizeof(app_resultcb_info_t));
140 info->launched_pid = pid;
141 info->cb_func = cbfunc;
142 info->priv_data = data;
143 info->caller_cb = NULL;
144 info->caller_data = NULL;
146 info->next = rescb_head2;
150 static app_resultcb_info_t *__find_resultcb2(int pid)
152 app_resultcb_info_t *tmp;
153 app_resultcb_info_t *ret = NULL;
155 pthread_mutex_lock(&result_lock);
158 _D("id_id : %d", tmp->launched_pid);
159 if (tmp->launched_pid == pid) {
164 pthread_mutex_unlock(&result_lock);
169 static void __remove_resultcb2(app_resultcb_info_t *info)
171 app_resultcb_info_t *tmp;
173 if (rescb_head2 == NULL || info == NULL)
176 if (rescb_head2 == info) {
177 rescb_head2 = info->next;
184 if (tmp->next == info) {
185 tmp->next = info->next;
195 * call result callback function
198 static int __call_app_result_callback(bundle *kb, int is_cancel,
201 app_resultcb_info_t *info;
205 if (((info = __find_resultcb(launched_pid)) == NULL)
206 || (launched_pid < 0)) {
207 _E("reject by pid - wait pid = %d, recvd pid = %d\n", getpid(),
210 /* second chance - support app launched by shell script*/
211 pgid = getpgid(launched_pid);
214 if ((info = __find_resultcb(pgid)) == NULL) {
215 _E("second chance : also reject pgid - %d\n", pgid);
220 if (info->cb_func == NULL || kb == NULL)
223 /* In case of aul_forward_app, update the callback data */
224 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
225 if(is_cancel == 1 && (fwdpid_str = (char *)bundle_get_val(kb, "__AUL_FWD_UG_ID__")))
227 app_resultcb_info_t newinfo;
228 newinfo.launched_pid = atoi(fwdpid_str);
229 newinfo.cb_func = info->cb_func;
230 newinfo.priv_data = info->priv_data;
231 newinfo.caller_cb = NULL;
232 newinfo.caller_data = NULL;
234 if(info->caller_cb) {
235 info->caller_cb(newinfo.launched_pid, info->caller_data);
238 __remove_resultcb(info);
239 __add_resultcb2(newinfo.launched_pid, newinfo.cb_func, newinfo.priv_data);
241 _D("change callback __AUL_FWD_UG_ID__ - %d\n", newinfo.launched_pid);
245 else if(is_cancel == 1 && (fwdpid_str = (char *)bundle_get_val(kb, AUL_K_FWD_CALLEE_PID)))
247 if(is_cancel == 1 && (fwdpid_str = (char *)bundle_get_val(kb, AUL_K_FWD_CALLEE_PID)))
250 app_resultcb_info_t newinfo;
251 newinfo.launched_pid = atoi(fwdpid_str);
252 newinfo.cb_func = info->cb_func;
253 newinfo.priv_data = info->priv_data;
254 newinfo.caller_cb = NULL;
255 newinfo.caller_data = NULL;
257 if(info->caller_cb) {
258 info->caller_cb(newinfo.launched_pid, info->caller_data);
261 __remove_resultcb(info);
262 __add_resultcb(newinfo.launched_pid, newinfo.cb_func, newinfo.priv_data);
264 _D("change callback - %s\n",AUL_K_FWD_CALLEE_PID);
269 info->cb_func(kb, is_cancel, info->priv_data);
270 __remove_resultcb(info);
276 static int __get_caller_pid(bundle *kb)
281 pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
285 pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
297 #ifdef ACTIVATE_PREEMPT_FEATURE
298 static int __send_to_cancel(int pid)
300 /* Say "Your result request is cancel!" to caller */
303 char tmp_pid[MAX_PID_STR_BUFSZ];
305 kb = bundle_create();
308 bundle_add(kb, AUL_K_SEND_RESULT, "1");
310 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", pid);
311 bundle_add(kb, AUL_K_CALLER_PID, tmp_pid);
313 ret = app_send_cmd(LAUNCHPAD_PID, APP_CANCEL, kb);
319 static int __send_to_cancel(int pid)
325 int _app_start_res_prepare(bundle *kb)
328 const char* str = NULL;
330 if (bundle_get_val(kb, AUL_K_WAIT_RESULT) == NULL)
333 str = bundle_get_val(kb, AUL_K_NO_CANCEL);
334 if( str && strncmp("1", str, 1) == 0) {
339 if ((pid = __get_caller_pid(kb)) < 0) {
340 _E("caller pid is not valid");
343 /* If previous caller is still waiting result,
344 send cancel packet to the caller. */
345 if (latest_caller_pid != -1)
346 __send_to_cancel(latest_caller_pid);
348 latest_caller_pid = pid;
349 _D("result msg prepare done");
354 int app_result(int cmd, bundle *kb, int launched_pid)
358 __call_app_result_callback(kb, 0, launched_pid);
361 __call_app_result_callback(kb, 1, launched_pid);
368 SLPAPI int aul_launch_app_with_result(const char *pkgname, bundle *kb,
369 void (*cbfunc) (bundle *, int, void *),
373 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
375 char id_str[256] = {0, };
378 if (!aul_is_initialized()) {
379 if (aul_launch_init(NULL, NULL) < 0)
380 return AUL_R_ENOINIT;
383 if (pkgname == NULL || cbfunc == NULL || kb == NULL)
386 pthread_mutex_lock(&result_lock);
387 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
389 sprintf(id_str, "%d", id);
390 bundle_add(kb, "__AUL_UG_ID__", id_str);
392 ret = app_request_to_launchpad(APP_START_RES, pkgname, kb);
394 __add_resultcb(ret, cbfunc, data);
395 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
396 else if (ret == AUL_R_UG_LOCAL) {
397 __add_resultcb2(id, cbfunc, data);
398 pthread_mutex_unlock(&result_lock);
402 pthread_mutex_unlock(&result_lock);
407 void __iterate(const char *key, const char *val, void *data)
410 _D("%d %s %s", i++, key, val);
413 SLPAPI int aul_forward_app(const char* pkgname, bundle *kb)
419 char tmp_pid[MAX_PID_STR_BUFSZ];
420 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
425 if(pkgname == NULL || kb == NULL)
428 caller = (char *)bundle_get_val(kb, AUL_K_CALLER_PID);
430 _E("original msg doest not have caller pid");
434 bundle_del(kb, AUL_K_ORG_CALLER_PID);
435 bundle_add(kb, AUL_K_ORG_CALLER_PID, caller);
437 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
438 caller_pid = atoi(caller);
441 dupb = bundle_dup(kb);
443 _E("bundle duplicate fail");
447 if(bundle_get_val(kb, AUL_K_WAIT_RESULT) != NULL) {
448 ret = app_request_to_launchpad(APP_START_RES, pkgname, kb);
452 ret = app_request_to_launchpad(APP_START, pkgname, kb);
456 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
460 snprintf(tmp_pid, MAX_PID_STR_BUFSZ,"%d",ret);
462 ret = aul_create_result_bundle(dupb, &outb);
466 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
467 _D("callee_pid(%d) caller_pid(%d)", callee_pid, caller_pid);
469 if(callee_pid == caller_pid) {
470 bundle_del(outb, AUL_K_FWD_CALLEE_PID);
471 bundle_add(outb, "__AUL_FWD_UG_ID__", bundle_get_val(kb, "__AUL_UG_ID__"));
473 bundle_del(outb, AUL_K_FWD_CALLEE_PID);
474 bundle_add(outb, AUL_K_FWD_CALLEE_PID, tmp_pid);
477 bundle_del(outb, AUL_K_FWD_CALLEE_PID);
478 bundle_add(outb, AUL_K_FWD_CALLEE_PID, tmp_pid);
481 // bundle_iterate(outb, __iterate, NULL);
483 ret = aul_send_result(outb, 1);
493 SLPAPI int aul_create_result_bundle(bundle *inb, bundle **outb)
500 _E("return msg create fail");
504 *outb = bundle_create();
506 _E("return msg create fail");
510 if(bundle_get_val(inb, AUL_K_WAIT_RESULT) != NULL) {
511 bundle_add(*outb, AUL_K_SEND_RESULT, "1");
512 _D("original msg is msg with result");
514 _D("original msg is not msg with result");
518 pid_str = bundle_get_val(inb, AUL_K_ORG_CALLER_PID);
520 bundle_add(*outb, AUL_K_ORG_CALLER_PID, pid_str);
524 pid_str = bundle_get_val(inb, AUL_K_CALLER_PID);
525 if (pid_str == NULL) {
526 _E("original msg doest not have caller pid");
531 bundle_add(*outb, AUL_K_CALLER_PID, pid_str);
537 int aul_send_result(bundle *kb, int is_cancel)
543 char callee_appid[256];
544 char tmp_pid[MAX_PID_STR_BUFSZ];
546 if ((pid = __get_caller_pid(kb)) < 0)
549 _D("caller pid : %d", pid);
551 if (bundle_get_val(kb, AUL_K_SEND_RESULT) == NULL)
553 _D("original msg is not msg with result");
557 callee_pid = getpid();
558 callee_pgid = getpgid(callee_pid);
559 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", callee_pgid);
560 bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
562 ret = aul_app_get_appid_bypid(callee_pid, callee_appid, sizeof(callee_appid));
564 bundle_add(kb, AUL_K_CALLEE_APPID, callee_appid);
566 _W("fail(%d) to get callee appid by pid", ret);
569 ret = app_send_cmd_with_noreply(AUL_UTIL_PID, (is_cancel==1)? APP_CANCEL : APP_RESULT, kb);
571 _D("app_send_cmd_with_noreply : %d", ret);
573 if(latest_caller_pid == pid)
574 latest_caller_pid = -1;
579 int app_subapp_terminate_request()
582 subapp_cb(subapp_data);
590 SLPAPI int aul_set_subapp(subapp_fn cb, void *data)
599 SLPAPI int aul_subapp_terminate_request_pid(int pid)
601 char pid_str[MAX_PID_STR_BUFSZ];
603 app_resultcb_info_t *info;
608 info = __find_resultcb(pid);
610 __remove_resultcb(info);
612 snprintf(pid_str, MAX_PID_STR_BUFSZ, "%d", pid);
613 ret = app_request_to_launchpad(APP_TERM_REQ_BY_PID, pid_str, NULL);
617 SLPAPI int aul_is_subapp()
622 SLPAPI int aul_add_caller_cb(int pid, void (*caller_cb) (int, void *), void *data)
624 app_resultcb_info_t *info;
629 info = __find_resultcb(pid);
631 info->caller_cb = caller_cb;
632 info->caller_data = data;
638 SLPAPI int aul_remove_caller_cb(int pid)
640 app_resultcb_info_t *info;
645 info = __find_resultcb(pid);
647 info->caller_cb = NULL;
648 info->caller_data = NULL;
654 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
655 SLPAPI int aul_call_ug_result_callback(bundle *kb, int is_cancel, int id)
657 app_resultcb_info_t *info;
660 info = __find_resultcb2(id);
664 info->cb_func(kb, is_cancel, info->priv_data);
665 __remove_resultcb2(info);