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.
29 #include "app_context.h"
30 #include "app_manager.h"
31 #include "app_manager_internal.h"
37 #define LOG_TAG "CAPI_APPFW_APP_MANAGER"
41 static int app_context_create(const char *app_id, pid_t pid, app_context_h *app_context);
43 static int app_context_get_app_context_by_pid(pid_t pid, app_context_h *app_context);
45 struct app_context_s {
50 typedef struct _foreach_context_ {
51 app_manager_app_context_cb callback;
56 typedef struct _retrieval_context_ {
60 } retrieval_context_s;
62 static int app_context_foreach_app_context_cb(const aul_app_info *aul_app_context, void *cb_data)
64 foreach_context_s* foreach_context = cb_data;
66 if (foreach_context == NULL) {
67 app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
71 if (foreach_context->iteration == true) {
72 app_context_h app_context = NULL;
74 if (app_context_create(aul_app_context->appid, aul_app_context->pid, &app_context) == APP_MANAGER_ERROR_NONE) {
75 foreach_context->iteration = foreach_context->callback(app_context, foreach_context->user_data);
76 app_context_destroy(app_context);
83 int app_context_foreach_app_context(app_manager_app_context_cb callback, void *user_data)
85 foreach_context_s foreach_context = {
87 .user_data = user_data,
92 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
94 if (aul_app_get_running_app_info(app_context_foreach_app_context_cb, &foreach_context) != AUL_R_OK)
95 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL);
97 return APP_MANAGER_ERROR_NONE;
101 static int app_context_retrieve_app_context(const aul_app_info *aul_app_context, void *cb_data)
103 retrieval_context_s *retrieval_context = cb_data;
105 if (aul_app_context != NULL && retrieval_context != NULL && retrieval_context->matched == false) {
106 if (!strcmp(aul_app_context->appid, retrieval_context->app_id)) {
107 retrieval_context->pid = aul_app_context->pid;
108 retrieval_context->matched = true;
115 int app_context_get_app_context(const char *app_id, app_context_h *app_context)
117 retrieval_context_s retrieval_context = {
123 if (app_id == NULL || app_context == NULL)
124 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
126 if (aul_app_is_running(app_id) == 0)
127 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
129 aul_app_get_running_app_info(app_context_retrieve_app_context, &retrieval_context);
131 if (retrieval_context.matched == false)
132 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
134 return app_context_create(retrieval_context.app_id, retrieval_context.pid, app_context);
137 static int app_context_get_app_context_by_pid(pid_t pid, app_context_h *app_context)
140 char appid[APPID_MAX] = {0, };
142 if (pid < 0 || app_context == NULL)
143 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
145 if (aul_app_get_appid_bypid(pid, appid, sizeof(appid)) != AUL_R_OK)
146 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
148 retval = app_context_get_app_context(appid, app_context);
150 if (retval != APP_MANAGER_ERROR_NONE)
151 return app_manager_error(retval, __FUNCTION__, NULL);
153 return APP_MANAGER_ERROR_NONE;
156 static int app_context_create(const char *app_id, pid_t pid, app_context_h *app_context)
158 app_context_h app_context_created;
160 if (app_id == NULL || pid <= 0 || app_context == NULL)
161 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
163 app_context_created = calloc(1, sizeof(struct app_context_s));
164 if (app_context_created == NULL)
165 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
167 app_context_created->app_id = strdup(app_id);
168 if (app_context_created->app_id == NULL) {
169 free(app_context_created);
170 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
173 app_context_created->pid = pid;
175 *app_context = app_context_created;
177 return APP_MANAGER_ERROR_NONE;
180 API int app_context_destroy(app_context_h app_context)
182 if (app_context == NULL)
183 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
185 free(app_context->app_id);
188 return APP_MANAGER_ERROR_NONE;
191 API int app_context_get_package(app_context_h app_context, char **package)
193 /* TODO: this function must be deprecated */
194 return app_context_get_app_id(app_context, package);
198 API int app_context_get_app_id(app_context_h app_context, char **app_id)
202 if (app_context == NULL || app_id == NULL)
203 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
205 app_id_dup = strdup(app_context->app_id);
206 if (app_id_dup == NULL)
207 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
209 *app_id = app_id_dup;
211 return APP_MANAGER_ERROR_NONE;
214 API int app_context_get_pid(app_context_h app_context, pid_t *pid)
216 if (app_context == NULL || pid == NULL)
217 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
219 *pid = app_context->pid;
221 return APP_MANAGER_ERROR_NONE;
224 API int app_context_is_terminated(app_context_h app_context, bool *terminated)
226 if (app_context == NULL || terminated == NULL)
227 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
229 if (aul_app_is_running(app_context->app_id) == 1) {
232 char appid[APPID_MAX] = {0, };
234 if (aul_app_get_appid_bypid(app_context->pid, appid, sizeof(appid)) == AUL_R_OK)
240 return APP_MANAGER_ERROR_NONE;
243 API int app_context_is_equal(app_context_h lhs, app_context_h rhs, bool *equal)
245 if (lhs == NULL || rhs == NULL || equal == NULL)
246 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
248 if (!strcmp(lhs->app_id, rhs->app_id) && lhs->pid == rhs->pid)
253 return APP_MANAGER_ERROR_NONE;
256 API int app_context_clone(app_context_h *clone, app_context_h app_context)
260 if (clone == NULL || app_context == NULL)
261 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
263 retval = app_context_create(app_context->app_id, app_context->pid, clone);
264 if (retval != APP_MANAGER_ERROR_NONE)
265 return app_manager_error(retval, __FUNCTION__, NULL);
267 return APP_MANAGER_ERROR_NONE;
270 typedef struct _event_cb_context_ {
271 GHashTable *pid_table;
272 app_manager_app_context_event_cb callback;
274 } event_cb_context_s;
276 static pthread_mutex_t event_cb_context_mutex = PTHREAD_MUTEX_INITIALIZER;
277 static event_cb_context_s *event_cb_context = NULL;
279 static void app_context_lock_event_cb_context()
281 pthread_mutex_lock(&event_cb_context_mutex);
284 static void app_context_unlock_event_cb_context()
286 pthread_mutex_unlock(&event_cb_context_mutex);
289 static bool app_context_load_all_app_context_cb_locked(app_context_h app_context, void *user_data)
291 app_context_h app_context_cloned;
293 if (app_context_clone(&app_context_cloned, app_context) == APP_MANAGER_ERROR_NONE) {
294 SECURE_LOGI("[%s] app_id(%s), pid(%d)", __FUNCTION__, app_context->app_id, app_context->pid);
296 if (event_cb_context != NULL && event_cb_context->pid_table != NULL) {
297 g_hash_table_insert(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context_cloned->pid)), app_context_cloned);
299 app_context_destroy(app_context_cloned);
300 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
307 static void app_context_pid_table_entry_destroyed_cb(void * data)
309 app_context_h app_context = data;
311 if (app_context != NULL) {
314 app_context_get_app_id(app_context, &app_id);
315 app_context_get_pid(app_context, &pid);
316 SECURE_LOGI("[%s] app_id(%s), pid(%d)", __FUNCTION__, app_context->app_id, app_context->pid);
319 app_context_destroy(app_context);
323 static int app_context_launched_event_cb(pid_t pid, void *data)
325 app_context_h app_context = NULL;
327 app_context_lock_event_cb_context();
329 if (app_context_get_app_context_by_pid(pid, &app_context) == APP_MANAGER_ERROR_NONE) {
330 if (event_cb_context != NULL && event_cb_context->pid_table != NULL) {
331 g_hash_table_insert(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context->pid)), app_context);
332 event_cb_context->callback(app_context, APP_CONTEXT_EVENT_LAUNCHED, event_cb_context->user_data);
334 app_context_destroy(app_context);
335 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
339 app_context_unlock_event_cb_context();
344 static int app_context_terminated_event_cb(pid_t pid, void *data)
346 app_context_h app_context;
347 int lookup_key = pid;
349 app_context_lock_event_cb_context();
351 if (event_cb_context != NULL && event_cb_context->pid_table != NULL) {
352 app_context = g_hash_table_lookup(event_cb_context->pid_table, GINT_TO_POINTER(&lookup_key));
354 if (app_context != NULL) {
355 event_cb_context->callback(app_context, APP_CONTEXT_EVENT_TERMINATED, event_cb_context->user_data);
356 g_hash_table_remove(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context->pid)));
359 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
362 app_context_unlock_event_cb_context();
367 int app_context_set_event_cb(app_manager_app_context_event_cb callback, void *user_data)
369 if (callback == NULL)
370 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
372 app_context_lock_event_cb_context();
374 if (event_cb_context == NULL) {
375 event_cb_context = calloc(1, sizeof(event_cb_context_s));
377 if (event_cb_context == NULL) {
378 app_context_unlock_event_cb_context();
379 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
382 event_cb_context->pid_table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, app_context_pid_table_entry_destroyed_cb);
383 if (event_cb_context->pid_table == NULL) {
384 free(event_cb_context);
385 event_cb_context = NULL;
386 app_context_unlock_event_cb_context();
387 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "failed to initialize pid-table");
390 app_context_foreach_app_context(app_context_load_all_app_context_cb_locked, NULL);
392 aul_listen_app_dead_signal(app_context_terminated_event_cb, NULL);
393 aul_listen_app_launch_signal(app_context_launched_event_cb, NULL);
397 event_cb_context->callback = callback;
398 event_cb_context->user_data = user_data;
400 app_context_unlock_event_cb_context();
402 return APP_MANAGER_ERROR_NONE;
405 void app_context_unset_event_cb(void)
407 app_context_lock_event_cb_context();
409 if (event_cb_context != NULL) {
410 /* aul_listen_app_dead_signal(NULL, NULL); */
411 /* aul_listen_app_launch_signal(NULL, NULL); */
413 g_hash_table_destroy(event_cb_context->pid_table);
414 free(event_cb_context);
415 event_cb_context = NULL;
418 app_context_unlock_event_cb_context();