2 * Copyright (c) 2011 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
28 #include <pkgmgr-info.h>
30 #include "app_context.h"
31 #include "app_manager.h"
32 #include "app_manager_internal.h"
38 #define LOG_TAG "CAPI_APPFW_APP_MANAGER"
42 static int app_context_create(const char *app_id, pid_t pid, const char *pkg_id, app_state_e app_state, bool is_sub_app, const char *instance_id, app_context_h *app_context);
44 struct app_context_s {
48 app_state_e app_state;
53 typedef struct _foreach_context_ {
54 app_manager_app_context_cb callback;
59 typedef struct _retrieval_context_ {
63 app_state_e app_state;
66 const char *instance_id;
67 } retrieval_context_s;
69 static app_manager_app_context_status_cb _status_cb;
71 static app_state_e app_context_get_app_status(int status)
73 app_state_e app_state;
77 app_state = APP_STATE_FOREGROUND;
79 case STATUS_LAUNCHING:
81 app_state = APP_STATE_BACKGROUND;
84 app_state = APP_STATE_SERVICE;
86 case STATUS_TERMINATE:
87 app_state = APP_STATE_TERMINATED;
90 app_state = APP_STATE_UNDEFINED;
97 static int app_context_foreach_app_context_cb(const aul_app_info *aul_app_context, void *cb_data)
99 foreach_context_s *foreach_context = cb_data;
100 app_context_h app_context;
101 app_state_e app_state;
102 bool is_sub_app = false;
104 if (foreach_context == NULL) {
105 app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
109 if (foreach_context->iteration == true) {
110 app_state = app_context_get_app_status(aul_app_context->status);
112 if (aul_app_context->is_sub_app)
115 if (app_context_create(aul_app_context->appid,
116 aul_app_context->pid,
117 aul_app_context->pkgid,
120 aul_app_context->instance_id,
121 &app_context) == APP_MANAGER_ERROR_NONE) {
122 foreach_context->iteration = foreach_context->callback(app_context, foreach_context->user_data);
123 app_context_destroy(app_context);
130 int app_context_foreach_app_context(app_manager_app_context_cb callback, void *user_data)
132 foreach_context_s foreach_context = {
133 .callback = callback,
134 .user_data = user_data,
138 if (callback == NULL)
139 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
141 if (aul_app_get_running_app_info(app_context_foreach_app_context_cb, &foreach_context) != AUL_R_OK)
142 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL);
144 return APP_MANAGER_ERROR_NONE;
147 static int app_context_foreach_running_app_context_cb(const aul_app_info *aul_app_context, void *cb_data)
149 foreach_context_s *foreach_context = cb_data;
150 app_context_h app_context;
151 app_state_e app_state;
152 bool is_sub_app = false;
154 if (foreach_context == NULL) {
155 app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
159 if (foreach_context->iteration == true) {
160 app_state = app_context_get_app_status(aul_app_context->status);
162 if (aul_app_context->is_sub_app)
165 if (app_context_create(aul_app_context->appid,
166 aul_app_context->pid,
167 aul_app_context->pkgid,
170 aul_app_context->instance_id,
171 &app_context) == APP_MANAGER_ERROR_NONE) {
172 foreach_context->iteration = foreach_context->callback(app_context, foreach_context->user_data);
173 app_context_destroy(app_context);
180 int app_context_foreach_running_app_context(app_manager_app_context_cb callback, void *user_data)
183 foreach_context_s foreach_context = {
184 .callback = callback,
185 .user_data = user_data,
189 if (callback == NULL)
190 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
192 ret = aul_app_get_all_running_app_info(app_context_foreach_running_app_context_cb, &foreach_context);
194 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL);
196 return APP_MANAGER_ERROR_NONE;
199 static int app_context_retrieve_app_context(const aul_app_info *aul_app_context, void *cb_data)
201 retrieval_context_s *retrieval_context = cb_data;
202 app_state_e app_state;
204 if (aul_app_context != NULL && retrieval_context != NULL && retrieval_context->matched == false) {
205 if (retrieval_context->instance_id &&
206 !strcmp(aul_app_context->instance_id, retrieval_context->instance_id) &&
207 !strcmp(aul_app_context->appid, retrieval_context->app_id)) {
208 app_state = app_context_get_app_status(aul_app_context->status);
210 retrieval_context->pid = aul_app_context->pid;
211 retrieval_context->pkg_id = strdup(aul_app_context->pkgid);
212 retrieval_context->app_state = app_state;
213 if (aul_app_context->is_sub_app)
214 retrieval_context->is_sub_app = true;
215 retrieval_context->matched = true;
216 } else if (retrieval_context->instance_id == NULL &&
217 !strcmp(aul_app_context->appid, retrieval_context->app_id)) {
218 app_state = app_context_get_app_status(aul_app_context->status);
220 retrieval_context->pid = aul_app_context->pid;
221 retrieval_context->pkg_id = strdup(aul_app_context->pkgid);
222 retrieval_context->app_state = app_state;
223 if (aul_app_context->is_sub_app)
224 retrieval_context->is_sub_app = true;
225 retrieval_context->matched = true;
232 int app_context_get_app_context(const char *app_id, app_context_h *app_context)
235 retrieval_context_s retrieval_context = {
239 .app_state = APP_STATE_UNDEFINED,
245 if (app_id == NULL || app_context == NULL)
246 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
248 if (aul_app_is_running(app_id) == 0)
249 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
251 aul_app_get_running_app_info(app_context_retrieve_app_context, &retrieval_context);
253 if (retrieval_context.matched == false)
254 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
256 ret = app_context_create(retrieval_context.app_id,
257 retrieval_context.pid,
258 retrieval_context.pkg_id,
259 retrieval_context.app_state,
260 retrieval_context.is_sub_app,
261 retrieval_context.instance_id,
263 free(retrieval_context.pkg_id);
268 static int app_context_create(const char *app_id, pid_t pid, const char *pkg_id, app_state_e app_state, bool is_sub_app, const char *instance_id, app_context_h *app_context)
270 app_context_h app_context_created;
272 if (app_id == NULL || pid <= 0 || pkg_id == NULL || app_context == NULL)
273 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
275 app_context_created = calloc(1, sizeof(struct app_context_s));
276 if (app_context_created == NULL)
277 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
279 app_context_created->app_id = strdup(app_id);
280 if (app_context_created->app_id == NULL) {
281 free(app_context_created);
282 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
285 app_context_created->pkg_id = strdup(pkg_id);
286 if (app_context_created->pkg_id == NULL) {
287 free(app_context_created->app_id);
288 free(app_context_created);
289 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
293 app_context_created->instance_id = strdup(instance_id);
294 if (app_context_created->instance_id == NULL) {
295 free(app_context_created->pkg_id);
296 free(app_context_created->app_id);
297 free(app_context_created);
298 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
302 app_context_created->pid = pid;
303 app_context_created->app_state = app_state;
304 app_context_created->is_sub_app = is_sub_app;
306 *app_context = app_context_created;
308 return APP_MANAGER_ERROR_NONE;
311 API int app_context_destroy(app_context_h app_context)
313 if (app_context == NULL)
314 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
316 free(app_context->app_id);
317 free(app_context->pkg_id);
318 free(app_context->instance_id);
321 return APP_MANAGER_ERROR_NONE;
324 API int app_context_get_package(app_context_h app_context, char **package)
326 dlog_print(DLOG_WARN, LOG_TAG, "DEPRECATION WARNING: app_context_get_package() is deprecated and will be removed from next release. Use app_context_get_app_id() instead.");
327 /* TODO: this function must be deprecated */
328 return app_context_get_app_id(app_context, package);
332 API int app_context_get_app_id(app_context_h app_context, char **app_id)
336 if (app_context == NULL || app_id == NULL)
337 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
339 app_id_dup = strdup(app_context->app_id);
340 if (app_id_dup == NULL)
341 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
343 *app_id = app_id_dup;
345 return APP_MANAGER_ERROR_NONE;
348 API int app_context_get_pid(app_context_h app_context, pid_t *pid)
350 if (app_context == NULL || pid == NULL)
351 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
353 *pid = app_context->pid;
355 return APP_MANAGER_ERROR_NONE;
358 API int app_context_get_package_id(app_context_h app_context, char **pkg_id)
362 if (app_context == NULL || pkg_id == NULL)
363 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
365 pkg_id_dup = strdup(app_context->pkg_id);
366 if (pkg_id_dup == NULL)
367 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
369 *pkg_id = pkg_id_dup;
371 return APP_MANAGER_ERROR_NONE;
374 API int app_context_get_app_state(app_context_h app_context, app_state_e *state)
376 if (app_context == NULL || state == NULL)
377 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
379 *state = app_context->app_state;
381 return APP_MANAGER_ERROR_NONE;
384 API int app_context_is_terminated(app_context_h app_context, bool *terminated)
386 char appid[APPID_MAX] = {0, };
388 if (app_context == NULL || terminated == NULL)
389 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
391 if (aul_app_is_running(app_context->app_id) == 1) {
394 if (aul_app_get_appid_bypid(app_context->pid, appid, sizeof(appid)) == AUL_R_OK)
400 return APP_MANAGER_ERROR_NONE;
403 API int app_context_is_equal(app_context_h lhs, app_context_h rhs, bool *equal)
405 if (lhs == NULL || rhs == NULL || equal == NULL)
406 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
408 if (!strcmp(lhs->app_id, rhs->app_id) && lhs->pid == rhs->pid)
413 return APP_MANAGER_ERROR_NONE;
416 API int app_context_is_sub_app(app_context_h app_context, bool *is_sub_app)
418 if (app_context == NULL || is_sub_app == NULL)
419 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
421 *is_sub_app = app_context->is_sub_app;
423 return APP_MANAGER_ERROR_NONE;
426 API int app_context_clone(app_context_h *clone, app_context_h app_context)
430 if (clone == NULL || app_context == NULL)
431 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
433 retval = app_context_create(app_context->app_id,
436 app_context->app_state,
437 app_context->is_sub_app,
438 app_context->instance_id,
440 if (retval != APP_MANAGER_ERROR_NONE)
441 return app_manager_error(retval, __FUNCTION__, NULL);
443 return APP_MANAGER_ERROR_NONE;
446 typedef struct _event_cb_context_ {
447 GHashTable *pid_table;
448 app_manager_app_context_event_cb callback;
450 } event_cb_context_s;
452 static pthread_mutex_t event_cb_context_mutex = PTHREAD_MUTEX_INITIALIZER;
453 static event_cb_context_s *event_cb_context = NULL;
455 static void app_context_lock_event_cb_context()
457 pthread_mutex_lock(&event_cb_context_mutex);
460 static void app_context_unlock_event_cb_context()
462 pthread_mutex_unlock(&event_cb_context_mutex);
465 static bool app_context_load_all_app_context_cb_locked(app_context_h app_context, void *user_data)
467 app_context_h app_context_cloned;
469 if (app_context_clone(&app_context_cloned, app_context) == APP_MANAGER_ERROR_NONE) {
470 SECURE_LOGI("[%s] app_id(%s), pid(%d)", __FUNCTION__, app_context->app_id, app_context->pid);
472 if (event_cb_context != NULL && event_cb_context->pid_table != NULL) {
473 g_hash_table_insert(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context_cloned->pid)), app_context_cloned);
475 app_context_destroy(app_context_cloned);
476 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
483 static void app_context_pid_table_entry_destroyed_cb(void *data)
485 app_context_h app_context = data;
487 if (app_context != NULL)
488 app_context_destroy(app_context);
491 static int app_context_get_pkgid_by_appid(const char *app_id, char **pkg_id)
493 pkgmgrinfo_appinfo_h appinfo;
496 if (app_id == NULL || pkg_id == NULL)
497 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
499 if (pkgmgrinfo_appinfo_get_usr_appinfo(app_id, getuid(), &appinfo) < 0)
500 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "fail to get appinfo");
502 if (pkgmgrinfo_appinfo_get_pkgid(appinfo, &pkg_id_dup) < 0) {
503 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
504 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "fail to get pkgid");
507 *pkg_id = strdup(pkg_id_dup);
509 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
510 return APP_MANAGER_ERROR_NONE;
513 static int app_context_launched_event_cb(pid_t pid, const char *app_id, void *data)
515 app_context_h app_context = NULL;
518 if (pid < 0 || app_id == NULL)
519 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
521 if (app_context_get_pkgid_by_appid(app_id, &pkg_id) < 0)
522 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "no such pkg_id");
524 app_context_lock_event_cb_context();
526 if (app_context_create(app_id, pid, pkg_id, APP_STATE_UNDEFINED, false, NULL, &app_context) == APP_MANAGER_ERROR_NONE) {
527 if (event_cb_context != NULL && event_cb_context->pid_table != NULL) {
528 g_hash_table_insert(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context->pid)), app_context);
529 event_cb_context->callback(app_context, APP_CONTEXT_EVENT_LAUNCHED, event_cb_context->user_data);
531 app_context_destroy(app_context);
532 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
536 app_context_unlock_event_cb_context();
542 static int app_context_terminated_event_cb(pid_t pid, void *data)
544 app_context_h app_context;
545 int lookup_key = pid;
547 app_context_lock_event_cb_context();
549 if (event_cb_context != NULL && event_cb_context->pid_table != NULL) {
550 app_context = g_hash_table_lookup(event_cb_context->pid_table, GINT_TO_POINTER(&lookup_key));
552 if (app_context != NULL) {
553 event_cb_context->callback(app_context, APP_CONTEXT_EVENT_TERMINATED, event_cb_context->user_data);
554 g_hash_table_remove(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context->pid)));
557 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
560 app_context_unlock_event_cb_context();
565 int app_context_set_event_cb(app_manager_app_context_event_cb callback, void *user_data)
567 if (callback == NULL)
568 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
570 app_context_lock_event_cb_context();
572 if (event_cb_context == NULL) {
573 event_cb_context = calloc(1, sizeof(event_cb_context_s));
575 if (event_cb_context == NULL) {
576 app_context_unlock_event_cb_context();
577 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
580 event_cb_context->pid_table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, app_context_pid_table_entry_destroyed_cb);
581 if (event_cb_context->pid_table == NULL) {
582 free(event_cb_context);
583 event_cb_context = NULL;
584 app_context_unlock_event_cb_context();
585 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "failed to initialize pid-table");
588 app_context_foreach_app_context(app_context_load_all_app_context_cb_locked, NULL);
590 aul_listen_app_dead_signal(app_context_terminated_event_cb, NULL);
591 aul_listen_app_launch_signal_v2(app_context_launched_event_cb, NULL);
595 event_cb_context->callback = callback;
596 event_cb_context->user_data = user_data;
598 app_context_unlock_event_cb_context();
600 return APP_MANAGER_ERROR_NONE;
603 void app_context_unset_event_cb(void)
605 app_context_lock_event_cb_context();
607 if (event_cb_context != NULL) {
608 /* aul_listen_app_dead_signal(NULL, NULL); */
609 /* aul_listen_app_launch_signal(NULL, NULL); */
611 g_hash_table_destroy(event_cb_context->pid_table);
612 free(event_cb_context);
613 event_cb_context = NULL;
616 app_context_unlock_event_cb_context();
619 static int app_context_status_cb(const char *appid, const char *pkgid, int pid, int status, int is_subapp, void *data)
621 app_context_h app_context = NULL;
623 app_context_status_e context_status;
626 state = app_context_get_app_status(status);
627 if (state == APP_STATE_TERMINATED)
628 context_status = APP_CONTEXT_STATUS_TERMINATED;
630 context_status = APP_CONTEXT_STATUS_LAUNCHED;
632 ret = app_context_create(appid, pid, pkgid, state, is_subapp, NULL, &app_context);
633 if (ret != APP_MANAGER_ERROR_NONE)
634 return app_manager_error(ret, __FUNCTION__, NULL);
636 _status_cb(app_context, context_status, data);
637 app_context_destroy(app_context);
639 return APP_MANAGER_ERROR_NONE;
642 int app_context_set_status_cb(app_manager_app_context_status_cb callback, const char *appid, void *user_data)
646 if (callback == NULL || appid == NULL)
647 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
649 _status_cb = callback;
651 ret = aul_listen_app_status(appid, app_context_status_cb, user_data);
654 ret = APP_MANAGER_ERROR_NONE;
657 ret = APP_MANAGER_ERROR_INVALID_PARAMETER;
660 ret = APP_MANAGER_ERROR_IO_ERROR;
667 int app_context_get_app_context_by_instance_id(const char *app_id, const char *instance_id, app_context_h *app_context)
670 retrieval_context_s retrieval_context = {
674 .app_state = APP_STATE_UNDEFINED,
677 .instance_id = instance_id
680 if (app_id == NULL || instance_id == NULL || app_context == NULL)
681 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
683 aul_app_get_running_app_instance_info(app_context_retrieve_app_context, &retrieval_context);
684 if (retrieval_context.matched == false)
685 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
687 ret = app_context_create(retrieval_context.app_id,
688 retrieval_context.pid,
689 retrieval_context.pkg_id,
690 retrieval_context.app_state,
691 retrieval_context.is_sub_app,
692 retrieval_context.instance_id,
694 free(retrieval_context.pkg_id);
699 int app_context_get_instance_id(app_context_h app_context, char **instance_id)
701 if (app_context == NULL || app_context->instance_id == NULL || instance_id == NULL)
702 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
704 *instance_id = strdup(app_context->instance_id);
705 if (*instance_id == NULL)
706 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
708 return APP_MANAGER_ERROR_NONE;