2 * Copyright (c) 2011 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, char *pkg_id, app_state_e app_state, bool is_sub_app, app_context_h *app_context);
44 struct app_context_s {
48 app_state_e app_state;
52 typedef struct _foreach_context_ {
53 app_manager_app_context_cb callback;
58 typedef struct _retrieval_context_ {
62 app_state_e app_state;
65 } retrieval_context_s;
67 static app_state_e app_context_get_app_status(int status)
69 app_state_e app_state;
73 app_state = APP_STATE_FOREGROUND;
75 case STATUS_LAUNCHING:
77 app_state = APP_STATE_BACKGROUND;
80 app_state = APP_STATE_SERVICE;
83 app_state = APP_STATE_UNDEFINED;
90 static int app_context_foreach_app_context_cb(const aul_app_info *aul_app_context, void *cb_data)
92 foreach_context_s* foreach_context = cb_data;
93 app_context_h app_context;
94 app_state_e app_state;
95 bool is_sub_app = false;
97 if (foreach_context == NULL) {
98 app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
102 if (foreach_context->iteration == true) {
103 app_state = app_context_get_app_status(aul_app_context->status);
105 if (aul_app_context->is_sub_app)
108 if (app_context_create(aul_app_context->appid,
109 aul_app_context->pid,
110 aul_app_context->pkgid,
113 &app_context) == APP_MANAGER_ERROR_NONE) {
114 foreach_context->iteration = foreach_context->callback(app_context, foreach_context->user_data);
115 app_context_destroy(app_context);
122 int app_context_foreach_app_context(app_manager_app_context_cb callback, void *user_data)
124 foreach_context_s foreach_context = {
125 .callback = callback,
126 .user_data = user_data,
130 if (callback == NULL)
131 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
133 if (aul_app_get_running_app_info(app_context_foreach_app_context_cb, &foreach_context) != AUL_R_OK)
134 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL);
136 return APP_MANAGER_ERROR_NONE;
139 static int app_context_foreach_running_app_context_cb(const aul_app_info *aul_app_context, void *cb_data)
141 foreach_context_s* foreach_context = cb_data;
142 app_context_h app_context;
143 app_state_e app_state;
144 bool is_sub_app = false;
146 if (foreach_context == NULL) {
147 app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
151 if (foreach_context->iteration == true) {
152 app_state = app_context_get_app_status(aul_app_context->status);
154 if (aul_app_context->is_sub_app)
157 if (app_context_create(aul_app_context->appid,
158 aul_app_context->pid,
159 aul_app_context->pkgid,
162 &app_context) == APP_MANAGER_ERROR_NONE) {
163 foreach_context->iteration = foreach_context->callback(app_context, foreach_context->user_data);
164 app_context_destroy(app_context);
171 int app_context_foreach_running_app_context(app_manager_app_context_cb callback, void *user_data)
174 foreach_context_s foreach_context = {
175 .callback = callback,
176 .user_data = user_data,
180 if (callback == NULL)
181 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
183 ret = aul_app_get_all_running_app_info(app_context_foreach_running_app_context_cb, &foreach_context);
184 if (ret != AUL_R_OK) {
185 if (ret == AUL_R_EILLACC)
186 return app_manager_error(APP_MANAGER_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL);
188 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL);
191 return APP_MANAGER_ERROR_NONE;
194 static int app_context_retrieve_app_context(const aul_app_info *aul_app_context, void *cb_data)
196 retrieval_context_s *retrieval_context = cb_data;
197 app_state_e app_state;
199 if (aul_app_context != NULL && retrieval_context != NULL && retrieval_context->matched == false) {
200 if (!strcmp(aul_app_context->appid, retrieval_context->app_id)) {
201 app_state = app_context_get_app_status(aul_app_context->status);
203 retrieval_context->pid = aul_app_context->pid;
204 retrieval_context->pkg_id = aul_app_context->pkgid;
205 retrieval_context->app_state = app_state;
206 if (aul_app_context->is_sub_app)
207 retrieval_context->is_sub_app = true;
208 retrieval_context->matched = true;
215 int app_context_get_app_context(const char *app_id, app_context_h *app_context)
217 retrieval_context_s retrieval_context = {
221 .app_state = APP_STATE_UNDEFINED,
226 if (app_id == NULL || app_context == NULL)
227 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
229 if (aul_app_is_running(app_id) == 0)
230 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
232 aul_app_get_running_app_info(app_context_retrieve_app_context, &retrieval_context);
234 if (retrieval_context.matched == false)
235 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
238 return app_context_create(retrieval_context.app_id,
239 retrieval_context.pid,
240 retrieval_context.pkg_id,
241 retrieval_context.app_state,
242 retrieval_context.is_sub_app,
246 static int app_context_create(const char *app_id, pid_t pid, char *pkg_id, app_state_e app_state, bool is_sub_app, app_context_h *app_context)
248 app_context_h app_context_created;
250 if (app_id == NULL || pid <= 0 || pkg_id == NULL || app_context == NULL)
251 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
253 app_context_created = calloc(1, sizeof(struct app_context_s));
254 if (app_context_created == NULL)
255 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
257 app_context_created->app_id = strdup(app_id);
258 if (app_context_created->app_id == NULL) {
259 free(app_context_created);
260 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
263 app_context_created->pkg_id = strdup(pkg_id);
264 if (app_context_created->pkg_id == NULL) {
265 free(app_context_created->app_id);
266 free(app_context_created);
267 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
270 app_context_created->pid = pid;
271 app_context_created->app_state = app_state;
272 app_context_created->is_sub_app = is_sub_app;
274 *app_context = app_context_created;
276 return APP_MANAGER_ERROR_NONE;
279 API int app_context_destroy(app_context_h app_context)
281 if (app_context == NULL)
282 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
284 free(app_context->app_id);
285 free(app_context->pkg_id);
288 return APP_MANAGER_ERROR_NONE;
291 API int app_context_get_package(app_context_h app_context, char **package)
293 /* TODO: this function must be deprecated */
294 return app_context_get_app_id(app_context, package);
298 API int app_context_get_app_id(app_context_h app_context, char **app_id)
302 if (app_context == NULL || app_id == NULL)
303 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
305 app_id_dup = strdup(app_context->app_id);
306 if (app_id_dup == NULL)
307 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
309 *app_id = app_id_dup;
311 return APP_MANAGER_ERROR_NONE;
314 API int app_context_get_pid(app_context_h app_context, pid_t *pid)
316 if (app_context == NULL || pid == NULL)
317 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
319 *pid = app_context->pid;
321 return APP_MANAGER_ERROR_NONE;
324 API int app_context_get_package_id(app_context_h app_context, char **pkg_id)
328 if (app_context == NULL || pkg_id == NULL)
329 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
331 pkg_id_dup = strdup(app_context->pkg_id);
332 if (pkg_id_dup == NULL)
333 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
335 *pkg_id = pkg_id_dup;
337 return APP_MANAGER_ERROR_NONE;
340 API int app_context_get_app_state(app_context_h app_context, app_state_e *state)
342 if (app_context == NULL || state == NULL)
343 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
345 *state = app_context->app_state;
347 return APP_MANAGER_ERROR_NONE;
350 API int app_context_is_terminated(app_context_h app_context, bool *terminated)
352 if (app_context == NULL || terminated == NULL)
353 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
355 if (aul_app_is_running(app_context->app_id) == 1) {
358 char appid[APPID_MAX] = {0, };
360 if (aul_app_get_appid_bypid(app_context->pid, appid, sizeof(appid)) == AUL_R_OK)
366 return APP_MANAGER_ERROR_NONE;
369 API int app_context_is_equal(app_context_h lhs, app_context_h rhs, bool *equal)
371 if (lhs == NULL || rhs == NULL || equal == NULL)
372 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
374 if (!strcmp(lhs->app_id, rhs->app_id) && lhs->pid == rhs->pid)
379 return APP_MANAGER_ERROR_NONE;
382 API int app_context_is_sub_app(app_context_h app_context, bool *is_sub_app)
384 if (app_context == NULL || is_sub_app == NULL)
385 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
387 *is_sub_app = app_context->is_sub_app;
389 return APP_MANAGER_ERROR_NONE;
392 API int app_context_clone(app_context_h *clone, app_context_h app_context)
396 if (clone == NULL || app_context == NULL)
397 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
399 retval = app_context_create(app_context->app_id,
402 app_context->app_state,
403 app_context->is_sub_app,
405 if (retval != APP_MANAGER_ERROR_NONE)
406 return app_manager_error(retval, __FUNCTION__, NULL);
408 return APP_MANAGER_ERROR_NONE;
411 typedef struct _event_cb_context_ {
412 GHashTable *pid_table;
413 app_manager_app_context_event_cb callback;
415 } event_cb_context_s;
417 static pthread_mutex_t event_cb_context_mutex = PTHREAD_MUTEX_INITIALIZER;
418 static event_cb_context_s *event_cb_context = NULL;
420 static void app_context_lock_event_cb_context()
422 pthread_mutex_lock(&event_cb_context_mutex);
425 static void app_context_unlock_event_cb_context()
427 pthread_mutex_unlock(&event_cb_context_mutex);
430 static bool app_context_load_all_app_context_cb_locked(app_context_h app_context, void *user_data)
432 app_context_h app_context_cloned;
434 if (app_context_clone(&app_context_cloned, app_context) == APP_MANAGER_ERROR_NONE) {
435 SECURE_LOGI("[%s] app_id(%s), pid(%d)", __FUNCTION__, app_context->app_id, app_context->pid);
437 if (event_cb_context != NULL && event_cb_context->pid_table != NULL) {
438 g_hash_table_insert(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context_cloned->pid)), app_context_cloned);
440 app_context_destroy(app_context_cloned);
441 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
448 static void app_context_pid_table_entry_destroyed_cb(void * data)
450 app_context_h app_context = data;
452 if (app_context != NULL)
453 app_context_destroy(app_context);
456 static int app_context_get_pkgid_by_appid(const char *app_id, char **pkg_id)
458 pkgmgrinfo_appinfo_h appinfo;
461 if (app_id == NULL || pkg_id == NULL)
462 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
464 if (pkgmgrinfo_appinfo_get_usr_appinfo(app_id, getuid(), &appinfo) < 0)
465 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "fail to get appinfo");
467 if (pkgmgrinfo_appinfo_get_pkgid(appinfo, &pkg_id_dup) < 0) {
468 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
469 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "fail to get pkgid");
472 *pkg_id = strdup(pkg_id_dup);
474 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
475 return APP_MANAGER_ERROR_NONE;
478 static int app_context_launched_event_cb(pid_t pid, const char *app_id, void *data)
480 app_context_h app_context = NULL;
483 if (pid < 0 || app_id == NULL)
484 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
486 if (app_context_get_pkgid_by_appid(app_id, &pkg_id) < 0)
487 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "no such pkg_id");
489 app_context_lock_event_cb_context();
491 if (app_context_create(app_id, pid, pkg_id, APP_STATE_UNDEFINED, false, &app_context) == APP_MANAGER_ERROR_NONE) {
492 if (event_cb_context != NULL && event_cb_context->pid_table != NULL) {
493 g_hash_table_insert(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context->pid)), app_context);
494 event_cb_context->callback(app_context, APP_CONTEXT_EVENT_LAUNCHED, event_cb_context->user_data);
496 app_context_destroy(app_context);
497 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
501 app_context_unlock_event_cb_context();
507 static int app_context_terminated_event_cb(pid_t pid, void *data)
509 app_context_h app_context;
510 int lookup_key = pid;
512 app_context_lock_event_cb_context();
514 if (event_cb_context != NULL && event_cb_context->pid_table != NULL) {
515 app_context = g_hash_table_lookup(event_cb_context->pid_table, GINT_TO_POINTER(&lookup_key));
517 if (app_context != NULL) {
518 event_cb_context->callback(app_context, APP_CONTEXT_EVENT_TERMINATED, event_cb_context->user_data);
519 g_hash_table_remove(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context->pid)));
522 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
525 app_context_unlock_event_cb_context();
530 int app_context_set_event_cb(app_manager_app_context_event_cb callback, void *user_data)
532 if (callback == NULL)
533 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
535 app_context_lock_event_cb_context();
537 if (event_cb_context == NULL) {
538 event_cb_context = calloc(1, sizeof(event_cb_context_s));
540 if (event_cb_context == NULL) {
541 app_context_unlock_event_cb_context();
542 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
545 event_cb_context->pid_table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, app_context_pid_table_entry_destroyed_cb);
546 if (event_cb_context->pid_table == NULL) {
547 free(event_cb_context);
548 event_cb_context = NULL;
549 app_context_unlock_event_cb_context();
550 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "failed to initialize pid-table");
553 app_context_foreach_app_context(app_context_load_all_app_context_cb_locked, NULL);
555 aul_listen_app_dead_signal(app_context_terminated_event_cb, NULL);
556 aul_listen_app_launch_signal_v2(app_context_launched_event_cb, NULL);
560 event_cb_context->callback = callback;
561 event_cb_context->user_data = user_data;
563 app_context_unlock_event_cb_context();
565 return APP_MANAGER_ERROR_NONE;
568 void app_context_unset_event_cb(void)
570 app_context_lock_event_cb_context();
572 if (event_cb_context != NULL) {
573 /* aul_listen_app_dead_signal(NULL, NULL); */
574 /* aul_listen_app_launch_signal(NULL, NULL); */
576 g_hash_table_destroy(event_cb_context->pid_table);
577 free(event_cb_context);
578 event_cb_context = NULL;
581 app_context_unlock_event_cb_context();