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_private.h>
37 #define LOG_TAG "TIZEN_N_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)
68 app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
72 if (foreach_context->iteration == true)
74 app_context_h app_context = NULL;
76 if (app_context_create(aul_app_context->pkg_name, aul_app_context->pid, &app_context) == APP_MANAGER_ERROR_NONE)
78 foreach_context->iteration = foreach_context->callback(app_context, foreach_context->user_data);
79 app_context_destroy(app_context);
87 int app_context_foreach_app_context(app_manager_app_context_cb callback, void *user_data)
89 foreach_context_s foreach_context = {
91 .user_data = user_data,
97 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
100 aul_app_get_running_app_info(app_context_foreach_app_context_cb, &foreach_context);
102 return APP_MANAGER_ERROR_NONE;
106 static int app_context_retrieve_app_context(const aul_app_info *aul_app_context, void *cb_data)
108 retrieval_context_s *retrieval_context = cb_data;
110 if (aul_app_context != NULL && retrieval_context != NULL && retrieval_context->matched == false)
112 if (!strcmp(aul_app_context->pkg_name, retrieval_context->app_id))
114 retrieval_context->pid = aul_app_context->pid;
115 retrieval_context->matched = true;
122 int app_context_get_app_context(const char *app_id, app_context_h *app_context)
124 retrieval_context_s retrieval_context = {
130 if (app_id == NULL || app_context == NULL)
132 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
135 if (aul_app_is_running(app_id) == 0)
137 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
140 aul_app_get_running_app_info(app_context_retrieve_app_context, &retrieval_context);
142 if (retrieval_context.matched == false)
144 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
147 return app_context_create(retrieval_context.app_id, retrieval_context.pid, app_context);
150 static int app_context_get_app_context_by_pid(pid_t pid, app_context_h *app_context)
153 char appid[APPID_MAX] = {0, };
155 if (pid < 0 || app_context == NULL)
157 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
160 if (aul_app_get_pkgname_bypid(pid, appid, sizeof(appid)) != AUL_R_OK)
162 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
165 retval = app_context_get_app_context(appid, app_context);
167 if (retval != APP_MANAGER_ERROR_NONE)
169 return app_manager_error(retval, __FUNCTION__, NULL);
172 return APP_MANAGER_ERROR_NONE;
175 static int app_context_create(const char *app_id, pid_t pid, app_context_h *app_context)
177 app_context_h app_context_created;
179 if (app_id == NULL || pid <= 0 || app_context == NULL)
181 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
184 app_context_created = calloc(1, sizeof(struct app_context_s));
186 if (app_context_created == NULL)
188 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
191 app_context_created->app_id = strdup(app_id);
193 if (app_context_created->app_id == NULL)
195 free(app_context_created);
196 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
199 app_context_created->pid = pid;
201 *app_context = app_context_created;
203 return APP_MANAGER_ERROR_NONE;
206 int app_context_destroy(app_context_h app_context)
208 if (app_context == NULL)
210 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
213 free(app_context->app_id);
216 return APP_MANAGER_ERROR_NONE;
219 int app_context_get_package(app_context_h app_context, char **package)
221 // TODO: this function must be deprecated
222 return app_context_get_app_id(app_context, package);
226 int app_context_get_app_id(app_context_h app_context, char **app_id)
230 if (app_context == NULL || app_id == NULL)
232 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
235 app_id_dup = strdup(app_context->app_id);
237 if (app_id_dup == NULL)
239 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
242 *app_id = app_id_dup;
244 return APP_MANAGER_ERROR_NONE;
248 int app_context_get_pid(app_context_h app_context, pid_t *pid)
250 if (app_context == NULL || pid == NULL)
252 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
255 *pid = app_context->pid;
257 return APP_MANAGER_ERROR_NONE;
260 int app_context_is_terminated(app_context_h app_context, bool *terminated)
262 if (app_context == NULL || terminated == NULL)
264 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
267 if (aul_app_is_running(app_context->app_id) == 1)
273 char appid[APPID_MAX] = {0, };
275 if (aul_app_get_pkgname_bypid(app_context->pid, appid, sizeof(appid)) == AUL_R_OK)
285 return APP_MANAGER_ERROR_NONE;
288 int app_context_is_equal(app_context_h lhs, app_context_h rhs, bool *equal)
290 if (lhs == NULL || rhs == NULL || equal == NULL)
292 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
295 if (!strcmp(lhs->app_id, rhs->app_id) && lhs->pid == rhs->pid)
304 return APP_MANAGER_ERROR_NONE;
307 int app_context_clone(app_context_h *clone, app_context_h app_context)
311 if (clone == NULL || app_context == NULL)
313 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
316 retval = app_context_create(app_context->app_id, app_context->pid, clone);
318 if (retval != APP_MANAGER_ERROR_NONE)
320 return app_manager_error(retval, __FUNCTION__, NULL);
323 return APP_MANAGER_ERROR_NONE;
326 typedef struct _event_cb_context_ {
327 GHashTable *pid_table;
328 app_manager_app_context_event_cb callback;
330 } event_cb_context_s;
332 static pthread_mutex_t event_cb_context_mutex = PTHREAD_MUTEX_INITIALIZER;
333 static event_cb_context_s *event_cb_context = NULL;
335 static void app_context_lock_event_cb_context()
337 pthread_mutex_lock(&event_cb_context_mutex);
340 static void app_context_unlock_event_cb_context()
342 pthread_mutex_unlock(&event_cb_context_mutex);
345 static bool app_context_load_all_app_context_cb_locked(app_context_h app_context, void *user_data)
347 app_context_h app_context_cloned;
349 if (app_context_clone(&app_context_cloned, app_context) == APP_MANAGER_ERROR_NONE)
351 LOGI("[%s] app_id(%s), pid(%d)", __FUNCTION__, app_context->app_id, app_context->pid);
353 if (event_cb_context != NULL && event_cb_context->pid_table != NULL)
355 g_hash_table_insert(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context_cloned->pid)), app_context_cloned);
359 app_context_destroy(app_context_cloned);
360 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
367 static void app_context_pid_table_entry_destroyed_cb(void * data)
369 app_context_h app_context = data;
371 if (app_context != NULL)
375 app_context_get_package(app_context, &app_id);
376 app_context_get_pid(app_context, &pid);
377 LOGI("[%s] app_id(%s), pid(%d)", __FUNCTION__, app_context->app_id, app_context->pid);
380 app_context_destroy(app_context);
384 static int app_context_launched_event_cb(pid_t pid, void *data)
386 app_context_h app_context;
388 app_context_lock_event_cb_context();
390 if (app_context_get_app_context_by_pid(pid, &app_context) == APP_MANAGER_ERROR_NONE)
392 if (event_cb_context != NULL && event_cb_context->pid_table != NULL)
394 g_hash_table_insert(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context->pid)), app_context);
395 event_cb_context->callback(app_context, APP_CONTEXT_EVENT_LAUNCHED, event_cb_context->user_data);
399 app_context_destroy(app_context);
400 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
404 app_context_unlock_event_cb_context();
409 static int app_context_terminated_event_cb(pid_t pid, void *data)
411 app_context_h app_context;
412 int lookup_key = pid;
414 app_context_lock_event_cb_context();
416 if (event_cb_context != NULL && event_cb_context->pid_table != NULL)
418 app_context = g_hash_table_lookup(event_cb_context->pid_table, GINT_TO_POINTER(&lookup_key));
420 if (app_context != NULL)
422 event_cb_context->callback(app_context, APP_CONTEXT_EVENT_TERMINATED, event_cb_context->user_data);
423 g_hash_table_remove(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context->pid)));
428 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
431 app_context_unlock_event_cb_context();
436 int app_context_set_event_cb(app_manager_app_context_event_cb callback, void *user_data)
438 if (callback == NULL)
440 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
443 app_context_lock_event_cb_context();
445 if (event_cb_context == NULL)
447 event_cb_context = calloc(1, sizeof(event_cb_context_s));
449 if (event_cb_context == NULL)
451 return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
454 event_cb_context->pid_table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, app_context_pid_table_entry_destroyed_cb);
456 if (event_cb_context->pid_table == NULL)
458 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "failed to initialize pid-table");
461 app_context_foreach_app_context(app_context_load_all_app_context_cb_locked, NULL);
463 aul_listen_app_dead_signal(app_context_terminated_event_cb, NULL);
464 aul_listen_app_launch_signal(app_context_launched_event_cb, NULL);
468 event_cb_context->callback = callback;
469 event_cb_context->user_data = user_data;
471 app_context_unlock_event_cb_context();
473 return APP_MANAGER_ERROR_NONE;
476 void app_context_unset_event_cb(void)
478 app_context_lock_event_cb_context();
480 if (event_cb_context != NULL)
482 //aul_listen_app_dead_signal(NULL, NULL);
483 //aul_listen_app_launch_signal(NULL, NULL);
485 g_hash_table_destroy(event_cb_context->pid_table);
486 free(event_cb_context);
487 event_cb_context = NULL;
490 app_context_unlock_event_cb_context();