2 * Copyright (c) 2011 - 2020 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.
25 #include <aul_app_event.h>
26 #include <aul_app_manager.h>
27 #include <aul_window.h>
29 #include "app_context.h"
30 #include "app_manager.h"
31 #include "app_manager_internal.h"
32 #include "log_private.h"
34 #define HANDLE_TO_AUL_HANDLE(h) ((aul_app_context_h)(app_context_h)(h))
35 #define AUL_HANDLE_TO_HANDLE(h) ((app_context_h)(aul_app_context_h)(h))
37 typedef struct app_event_info_s {
38 aul_app_event_h handle;
40 app_manager_app_context_status_cb callback;
44 static GList *__event_info_list;
46 static int __aul_error_convert(int res)
50 return APP_MANAGER_ERROR_INVALID_PARAMETER;
53 return APP_MANAGER_ERROR_NO_SUCH_APP;
55 return APP_MANAGER_ERROR_OUT_OF_MEMORY;
57 return APP_MANAGER_ERROR_PERMISSION_DENIED;
59 return APP_MANAGER_ERROR_IO_ERROR;
63 static app_state_e app_context_get_app_status(int status)
65 app_state_e app_state;
69 app_state = APP_STATE_FOREGROUND;
71 case STATUS_LAUNCHING:
73 app_state = APP_STATE_BACKGROUND;
76 app_state = APP_STATE_SERVICE;
78 case STATUS_TERMINATE:
79 app_state = APP_STATE_TERMINATED;
82 app_state = APP_STATE_UNDEFINED;
89 int app_context_foreach_app_context(app_manager_app_context_cb callback,
95 _E("Invalid parameter");
96 return APP_MANAGER_ERROR_INVALID_PARAMETER;
99 ret = aul_app_manager_foreach_app_context(
100 (aul_app_manager_app_context_cb)callback,
102 if (ret != AUL_R_OK) {
103 _E("Failed to retrieve app context. error(%d)", ret);
104 return APP_MANAGER_ERROR_IO_ERROR;
107 return APP_MANAGER_ERROR_NONE;
110 int app_context_foreach_running_app_context(app_manager_app_context_cb callback,
116 _E("Invalid parameter");
117 return APP_MANAGER_ERROR_INVALID_PARAMETER;
120 ret = aul_app_manager_foreach_all_app_context(
121 (aul_app_manager_app_context_cb)callback,
123 if (ret != AUL_R_OK) {
124 _E("Failed to retrieve all app context. error(%d)", ret);
125 return APP_MANAGER_ERROR_IO_ERROR;
128 return APP_MANAGER_ERROR_NONE;
131 int app_context_get_app_context(const char *app_id, app_context_h *app_context)
133 aul_app_context_h handle;
136 if (!app_id || !app_context) {
137 _E("Invalid parameter");
138 return APP_MANAGER_ERROR_INVALID_PARAMETER;
141 ret = aul_app_context_create(app_id, &handle);
142 if (ret != AUL_R_OK) {
143 _E("Failed to create app context. error(%d)", ret);
144 return __aul_error_convert(ret);
147 *app_context = AUL_HANDLE_TO_HANDLE(handle);
152 API int app_context_destroy(app_context_h app_context)
154 aul_app_context_h handle = HANDLE_TO_AUL_HANDLE(app_context);
157 _E("Invalid parameter");
158 return APP_MANAGER_ERROR_INVALID_PARAMETER;
161 aul_app_context_destroy(handle);
163 return APP_MANAGER_ERROR_NONE;
166 API int app_context_get_package(app_context_h app_context, char **package)
168 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.");
169 /* TODO: this function must be deprecated */
170 return app_context_get_app_id(app_context, package);
173 API int app_context_get_app_id(app_context_h app_context, char **app_id)
175 aul_app_context_h handle = HANDLE_TO_AUL_HANDLE(app_context);
178 if (!app_context || !app_id) {
179 _E("Invalid parameter");
180 return APP_MANAGER_ERROR_INVALID_PARAMETER;
183 ret = aul_app_context_get_app_id(handle, app_id);
185 return __aul_error_convert(ret);
187 return APP_MANAGER_ERROR_NONE;
190 API int app_context_get_pid(app_context_h app_context, pid_t *pid)
192 aul_app_context_h handle = HANDLE_TO_AUL_HANDLE(app_context);
195 if (!app_context || !pid) {
196 _E("Invalid parameter");
197 return APP_MANAGER_ERROR_INVALID_PARAMETER;
200 ret = aul_app_context_get_pid(handle, pid);
202 return __aul_error_convert(ret);
204 return APP_MANAGER_ERROR_NONE;
207 API int app_context_get_package_id(app_context_h app_context, char **pkg_id)
209 aul_app_context_h handle = HANDLE_TO_AUL_HANDLE(app_context);
212 if (!app_context || !pkg_id) {
213 _E("Invalid parameter");
214 return APP_MANAGER_ERROR_INVALID_PARAMETER;
217 ret = aul_app_context_get_pkg_id(handle, pkg_id);
219 return __aul_error_convert(ret);
221 return APP_MANAGER_ERROR_NONE;
224 API int app_context_get_app_state(app_context_h app_context, app_state_e *state)
226 aul_app_context_h handle = HANDLE_TO_AUL_HANDLE(app_context);
230 if (!app_context || !state) {
231 _E("Invalid parameter");
232 return APP_MANAGER_ERROR_INVALID_PARAMETER;
235 ret = aul_app_context_get_status(handle, &status);
237 return __aul_error_convert(ret);
239 *state = app_context_get_app_status(status);
241 return APP_MANAGER_ERROR_NONE;
244 API int app_context_is_terminated(app_context_h app_context, bool *terminated)
246 aul_app_context_h handle = HANDLE_TO_AUL_HANDLE(app_context);
250 if (!app_context || !terminated) {
251 _E("Invalid parameter");
252 return APP_MANAGER_ERROR_INVALID_PARAMETER;
255 ret = aul_app_context_is_running(handle, &is_running);
257 return __aul_error_convert(ret);
264 return APP_MANAGER_ERROR_NONE;
267 API int app_context_is_equal(app_context_h lhs, app_context_h rhs, bool *equal)
269 aul_app_context_h lh = HANDLE_TO_AUL_HANDLE(lhs);
270 aul_app_context_h rh = HANDLE_TO_AUL_HANDLE(rhs);
273 if (!lhs || !rhs || !equal) {
274 _E("Invalid parameter");
275 return APP_MANAGER_ERROR_INVALID_PARAMETER;
278 ret = aul_app_context_is_equal(lh, rh, equal);
280 return __aul_error_convert(ret);
282 return APP_MANAGER_ERROR_NONE;
285 API int app_context_is_sub_app(app_context_h app_context, bool *is_sub_app)
287 aul_app_context_h handle = HANDLE_TO_AUL_HANDLE(app_context);
290 if (!app_context || !is_sub_app) {
291 _E("Invalid parameter");
292 return APP_MANAGER_ERROR_INVALID_PARAMETER;
295 ret = aul_app_context_is_sub_app(handle, is_sub_app);
297 return __aul_error_convert(ret);
299 return APP_MANAGER_ERROR_NONE;
302 API int app_context_clone(app_context_h *clone, app_context_h app_context)
304 aul_app_context_h handle = HANDLE_TO_AUL_HANDLE(app_context);
305 aul_app_context_h new_handle;
308 if (!clone || !app_context) {
309 _E("Invalid parameter");
310 return APP_MANAGER_ERROR_INVALID_PARAMETER;
313 ret = aul_app_context_clone(handle, &new_handle);
315 return __aul_error_convert(ret);
317 *clone = AUL_HANDLE_TO_HANDLE(new_handle);
319 return APP_MANAGER_ERROR_NONE;
322 typedef struct _event_cb_context_ {
323 aul_app_event_h handle;
324 GHashTable *pid_table;
325 app_manager_app_context_event_cb callback;
327 } event_cb_context_s;
329 static pthread_mutex_t event_cb_context_mutex = PTHREAD_MUTEX_INITIALIZER;
330 static event_cb_context_s *event_cb_context = NULL;
332 static void app_context_lock_event_cb_context()
334 pthread_mutex_lock(&event_cb_context_mutex);
337 static void app_context_unlock_event_cb_context()
339 pthread_mutex_unlock(&event_cb_context_mutex);
342 static bool __load_all_app_context_cb_locked(app_context_h app_context,
349 app_context_get_app_id(app_context, &app_id);
350 app_context_get_pid(app_context, &pid);
351 app_context_is_sub_app(app_context, &sub_app);
352 SECURE_LOGI("app_id(%s), pid(%d), sub_app(%s)",
353 app_id, pid, sub_app ? "true" : "false");
356 g_hash_table_insert(event_cb_context->pid_table, GINT_TO_POINTER(pid),
357 GINT_TO_POINTER(pid));
361 static void __app_context_launched_event_cb(aul_app_context_h app_context,
366 aul_app_context_get_pid(app_context, &pid);
367 app_context_lock_event_cb_context();
368 if (event_cb_context && event_cb_context->pid_table) {
369 g_hash_table_insert(event_cb_context->pid_table,
370 GINT_TO_POINTER(pid), GINT_TO_POINTER(pid));
371 event_cb_context->callback((app_context_h)app_context,
372 APP_CONTEXT_EVENT_LAUNCHED,
373 event_cb_context->user_data);
375 _E("Invalid context. pid(%d)", pid);
377 app_context_unlock_event_cb_context();
380 static void __app_context_terminated_event_cb(aul_app_context_h app_context,
385 aul_app_context_get_pid(app_context, &pid);
386 app_context_lock_event_cb_context();
387 if (event_cb_context && event_cb_context->pid_table) {
388 if (g_hash_table_contains(event_cb_context->pid_table,
389 GINT_TO_POINTER(pid))) {
390 event_cb_context->callback(app_context,
391 APP_CONTEXT_EVENT_TERMINATED,
392 event_cb_context->user_data);
393 g_hash_table_remove(event_cb_context->pid_table,
394 GINT_TO_POINTER(pid));
397 _E("Invalid context. pid(%d)", pid);
399 app_context_unlock_event_cb_context();
402 static void __event_cb_context_fini(void)
404 if (!event_cb_context)
407 if (event_cb_context->handle)
408 aul_app_event_destroy(event_cb_context->handle);
410 if (event_cb_context->pid_table)
411 g_hash_table_destroy(event_cb_context->pid_table);
413 free(event_cb_context);
414 event_cb_context = NULL;
417 static int __event_cb_context_init(void)
421 if (event_cb_context)
422 return APP_MANAGER_ERROR_NONE;
424 event_cb_context = calloc(1, sizeof(event_cb_context_s));
425 if (event_cb_context == NULL) {
427 return APP_MANAGER_ERROR_OUT_OF_MEMORY;
430 event_cb_context->pid_table = g_hash_table_new(g_direct_hash,
432 if (event_cb_context->pid_table == NULL) {
433 _E("Failed to create hash table");
434 __event_cb_context_fini();
435 return APP_MANAGER_ERROR_OUT_OF_MEMORY;
438 app_context_foreach_app_context(__load_all_app_context_cb_locked, NULL);
440 ret = aul_app_event_create(__app_context_launched_event_cb,
441 __app_context_terminated_event_cb,
443 &event_cb_context->handle);
444 if (ret != AUL_R_OK) {
445 _E("aul_app_context_create() is failed. error(%d)", ret);
446 __event_cb_context_fini();
447 return APP_MANAGER_ERROR_IO_ERROR;
450 return APP_MANAGER_ERROR_NONE;
453 int app_context_set_event_cb(app_manager_app_context_event_cb callback,
459 _E("Invalid parameter");
460 return APP_MANAGER_ERROR_INVALID_PARAMETER;
463 app_context_lock_event_cb_context();
465 ret = __event_cb_context_init();
466 if (ret != APP_MANAGER_ERROR_NONE) {
467 app_context_unlock_event_cb_context();
471 event_cb_context->callback = callback;
472 event_cb_context->user_data = user_data;
474 app_context_unlock_event_cb_context();
476 return APP_MANAGER_ERROR_NONE;
479 void app_context_unset_event_cb(void)
481 app_context_lock_event_cb_context();
482 __event_cb_context_fini();
483 app_context_unlock_event_cb_context();
486 static void __destroy_app_event_info(gpointer data)
488 app_event_info_t *info = data;
497 static app_event_info_t *__create_app_event_info(const char *appid,
498 app_manager_app_context_status_cb callback,
501 app_event_info_t *info;
503 info = calloc(1, sizeof(app_event_info_t));
509 info->appid = strdup(appid);
511 _E("Failed to duplicate application ID(%s)", appid);
512 __destroy_app_event_info(info);
516 info->callback = callback;
517 info->user_data = user_data;
522 static app_event_info_t *__pop_app_event_info(const char *appid,
523 app_manager_app_context_status_cb callback)
525 app_event_info_t *info;
528 app_context_lock_event_cb_context();
529 iter = __event_info_list;
531 info = (app_event_info_t *)iter->data;
532 iter = g_list_next(iter);
533 if (info->callback == callback &&
534 !strcmp(info->appid, appid)) {
535 __event_info_list = g_list_remove(
536 __event_info_list, info);
537 app_context_unlock_event_cb_context();
541 app_context_unlock_event_cb_context();
546 static void __push_app_event_info(app_event_info_t *info)
548 app_context_lock_event_cb_context();
549 __event_info_list = g_list_append(__event_info_list, info);
550 app_context_unlock_event_cb_context();
553 static bool __exist_app_event_info(app_event_info_t *info)
557 app_context_lock_event_cb_context();
558 found = g_list_find(__event_info_list, info);
559 app_context_unlock_event_cb_context();
567 static void __aul_app_event_launched_cb(aul_app_context_h app_context,
570 app_event_info_t *info = user_data;
572 if (!__exist_app_event_info(info)) {
573 _E("Invalid context");
577 info->callback(AUL_HANDLE_TO_HANDLE(app_context),
578 APP_CONTEXT_STATUS_LAUNCHED,
582 static void __aul_app_event_terminated_cb(aul_app_context_h app_context,
585 app_event_info_t *info = user_data;
587 if (!__exist_app_event_info(info)) {
588 _E("Invalid context");
592 info->callback(AUL_HANDLE_TO_HANDLE(app_context),
593 APP_CONTEXT_STATUS_TERMINATED,
597 int app_context_set_status_cb(app_manager_app_context_status_cb callback,
598 const char *appid, void *user_data)
600 app_event_info_t *info;
603 if (!callback || !appid) {
604 _E("Invalid parameter");
605 return APP_MANAGER_ERROR_INVALID_PARAMETER;
608 info = __create_app_event_info(appid, callback, user_data);
610 return APP_MANAGER_ERROR_OUT_OF_MEMORY;
612 ret = aul_app_event_create_with_appid(appid,
613 __aul_app_event_launched_cb,
614 __aul_app_event_terminated_cb,
617 if (ret != AUL_R_OK) {
618 __destroy_app_event_info(info);
619 return __aul_error_convert(ret);
622 __push_app_event_info(info);
624 return APP_MANAGER_ERROR_NONE;
627 int app_context_unset_status_cb(app_manager_app_context_status_cb callback,
630 app_event_info_t *info;
632 if (!callback || !appid) {
633 _E("Invalid parameter");
634 return APP_MANAGER_ERROR_INVALID_PARAMETER;
637 info = __pop_app_event_info(appid, callback);
639 return APP_MANAGER_ERROR_INVALID_PARAMETER;
641 aul_app_event_destroy(info->handle);
642 __destroy_app_event_info(info);
644 return APP_MANAGER_ERROR_NONE;
647 int app_context_get_app_context_by_instance_id(const char *app_id,
648 const char *instance_id,
649 app_context_h *app_context)
651 aul_app_context_h handle;
654 if (!app_id || !instance_id || !app_context) {
655 _E("Invalid parameter");
656 return APP_MANAGER_ERROR_INVALID_PARAMETER;
659 ret = aul_app_context_create_with_inst_id(app_id, instance_id, &handle);
661 return __aul_error_convert(ret);
663 *app_context = AUL_HANDLE_TO_HANDLE(handle);
665 return APP_MANAGER_ERROR_NONE;
668 int app_context_get_instance_id(app_context_h app_context, char **instance_id)
670 aul_app_context_h handle = HANDLE_TO_AUL_HANDLE(app_context);
673 if (!app_context || !instance_id) {
674 _E("Invalid parameter");
675 return APP_MANAGER_ERROR_INVALID_PARAMETER;
678 ret = aul_app_context_get_inst_id(handle, instance_id);
680 return __aul_error_convert(ret);
682 return APP_MANAGER_ERROR_NONE;
685 int app_context_get_app_context_by_pid(pid_t pid, app_context_h *app_context)
687 aul_app_context_h handle;
690 if (pid <= 0 || !app_context) {
691 _E("Invalid parameter");
692 return APP_MANAGER_ERROR_INVALID_PARAMETER;
695 ret = aul_app_context_create_with_pid(pid, &handle);
697 return __aul_error_convert(ret);
699 *app_context = AUL_HANDLE_TO_HANDLE(handle);
704 static void __foreach_window_info_cb(aul_window_info_h info, void *data)
706 GList **list = (GList **)data;
711 if (info == NULL || list == NULL) {
712 LOGE("Invalid parameter");
716 ret = aul_window_info_get_visibility(info, &visibility);
718 LOGE("Failed to get window visibility");
722 if (visibility < 0 || visibility > 1)
725 ret = aul_window_info_get_pid(info, &pid);
727 LOGE("Failed to get pid");
731 *list = g_list_append(*list, GINT_TO_POINTER(pid));
734 static bool __foreach_app_context_cb(aul_app_context_h aul_app_context,
737 GHashTable *app_context_table = (GHashTable *)user_data;
738 aul_app_context_h app_context;
742 ret = aul_app_context_clone(aul_app_context, &app_context);
743 if (ret != AUL_R_OK) {
744 _E("Failed to clone app con text. error(%d)", ret);
748 aul_app_context_get_pid(aul_app_context, &pid);
749 g_hash_table_insert(app_context_table, GINT_TO_POINTER(pid),
755 int app_context_foreach_visible_app_context(app_manager_app_context_cb callback,
758 aul_window_stack_h handle = NULL;
759 GHashTable *app_context_table;
760 app_context_h app_context;
761 GList *pid_list = NULL;
765 if (callback == NULL)
766 return APP_MANAGER_ERROR_INVALID_PARAMETER;
768 app_context_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
769 NULL, (GDestroyNotify)app_context_destroy);
770 if (app_context_table == NULL)
771 return APP_MANAGER_ERROR_OUT_OF_MEMORY;
773 ret = aul_app_manager_foreach_all_app_context(__foreach_app_context_cb,
775 if (ret != AUL_R_OK) {
776 g_hash_table_destroy(app_context_table);
777 return APP_MANAGER_ERROR_IO_ERROR;
780 ret = aul_window_stack_get(&handle);
782 g_hash_table_destroy(app_context_table);
783 return APP_MANAGER_ERROR_IO_ERROR;
786 ret = aul_window_stack_foreach(handle,
787 __foreach_window_info_cb, &pid_list);
789 aul_window_stack_del(handle);
790 g_hash_table_destroy(app_context_table);
791 return APP_MANAGER_ERROR_IO_ERROR;
793 aul_window_stack_del(handle);
795 iter = g_list_first(pid_list);
797 app_context = (app_context_h)g_hash_table_lookup(
798 app_context_table, iter->data);
800 if (!callback(app_context, user_data))
803 iter = g_list_next(iter);
805 g_list_free(pid_list);
806 g_hash_table_destroy(app_context_table);
808 return APP_MANAGER_ERROR_NONE;