Modify app_manager_resume_app API
[platform/core/api/app-manager.git] / src / app_context.c
1 /*
2  * Copyright (c) 2011 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <pthread.h>
23
24 #include <glib.h>
25
26 #include <aul.h>
27 #include <dlog.h>
28 #include <pkgmgr-info.h>
29
30 #include "app_context.h"
31 #include "app_manager.h"
32 #include "app_manager_internal.h"
33
34 #ifdef LOG_TAG
35 #undef LOG_TAG
36 #endif
37
38 #define LOG_TAG "CAPI_APPFW_APP_MANAGER"
39
40 #define APPID_MAX 128
41
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);
43
44 struct app_context_s {
45         char *app_id;
46         pid_t pid;
47         char *pkg_id;
48         app_state_e app_state;
49         bool is_sub_app;
50         char *instance_id;
51 };
52
53 typedef struct _foreach_context_ {
54         app_manager_app_context_cb callback;
55         void *user_data;
56         bool iteration;
57 } foreach_context_s;
58
59 typedef struct _retrieval_context_ {
60         const char *app_id;
61         pid_t pid;
62         char *pkg_id;
63         app_state_e app_state;
64         bool is_sub_app;
65         bool matched;
66         const char *instance_id;
67 } retrieval_context_s;
68
69 static app_manager_app_context_status_cb _status_cb;
70
71 static app_state_e app_context_get_app_status(int status)
72 {
73         app_state_e app_state;
74
75         switch (status) {
76         case STATUS_VISIBLE:
77                 app_state = APP_STATE_FOREGROUND;
78                 break;
79         case STATUS_LAUNCHING:
80         case STATUS_BG:
81                 app_state = APP_STATE_BACKGROUND;
82                 break;
83         case STATUS_SERVICE:
84                 app_state = APP_STATE_SERVICE;
85                 break;
86         case STATUS_TERMINATE:
87                 app_state = APP_STATE_TERMINATED;
88                 break;
89         default:
90                 app_state = APP_STATE_UNDEFINED;
91                 break;
92         }
93
94         return app_state;
95 }
96
97 static int app_context_foreach_app_context_cb(const aul_app_info *aul_app_context, void *cb_data)
98 {
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;
103
104         if (foreach_context == NULL) {
105                 app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
106                 return 0;
107         }
108
109         if (foreach_context->iteration == true) {
110                 app_state = app_context_get_app_status(aul_app_context->status);
111
112                 if (aul_app_context->is_sub_app)
113                         is_sub_app = true;
114
115                 if (app_context_create(aul_app_context->appid,
116                                         aul_app_context->pid,
117                                         aul_app_context->pkgid,
118                                         app_state,
119                                         is_sub_app,
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);
124                 }
125         }
126
127         return 0;
128 }
129
130 int app_context_foreach_app_context(app_manager_app_context_cb callback, void *user_data)
131 {
132         foreach_context_s foreach_context = {
133                 .callback = callback,
134                 .user_data = user_data,
135                 .iteration = true
136         };
137
138         if (callback == NULL)
139                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
140
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);
143
144         return APP_MANAGER_ERROR_NONE;
145 }
146
147 static int app_context_foreach_running_app_context_cb(const aul_app_info *aul_app_context, void *cb_data)
148 {
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;
153
154         if (foreach_context == NULL) {
155                 app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
156                 return 0;
157         }
158
159         if (foreach_context->iteration == true) {
160                 app_state = app_context_get_app_status(aul_app_context->status);
161
162                 if (aul_app_context->is_sub_app)
163                         is_sub_app = true;
164
165                 if (app_context_create(aul_app_context->appid,
166                                         aul_app_context->pid,
167                                         aul_app_context->pkgid,
168                                         app_state,
169                                         is_sub_app,
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);
174                 }
175         }
176
177         return 0;
178 }
179
180 int app_context_foreach_running_app_context(app_manager_app_context_cb callback, void *user_data)
181 {
182         int ret;
183         foreach_context_s foreach_context = {
184                 .callback = callback,
185                 .user_data = user_data,
186                 .iteration = true
187         };
188
189         if (callback == NULL)
190                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
191
192         ret = aul_app_get_all_running_app_info(app_context_foreach_running_app_context_cb, &foreach_context);
193         if (ret != AUL_R_OK)
194                 return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL);
195
196         return APP_MANAGER_ERROR_NONE;
197 }
198
199 static int app_context_retrieve_app_context(const aul_app_info *aul_app_context, void *cb_data)
200 {
201         retrieval_context_s *retrieval_context = cb_data;
202         app_state_e app_state;
203
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);
209
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);
219
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;
226                 }
227         }
228
229         return 0;
230 }
231
232 int app_context_get_app_context(const char *app_id, app_context_h *app_context)
233 {
234         int ret;
235         retrieval_context_s retrieval_context =  {
236                 .app_id = app_id,
237                 .pid = 0,
238                 .pkg_id = NULL,
239                 .app_state = APP_STATE_UNDEFINED,
240                 .is_sub_app = false,
241                 .matched = false,
242                 .instance_id = NULL
243         };
244
245         if (app_id == NULL || app_context == NULL)
246                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
247
248         if (aul_app_is_running(app_id) == 0)
249                 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
250
251         aul_app_get_running_app_info(app_context_retrieve_app_context, &retrieval_context);
252
253         if (retrieval_context.matched == false)
254                 return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
255
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,
262                                         app_context);
263         free(retrieval_context.pkg_id);
264
265         return ret;
266 }
267
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)
269 {
270         app_context_h app_context_created;
271
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);
274
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);
278
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);
283         }
284
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);
290         }
291
292         if (instance_id) {
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);
299                 }
300         }
301
302         app_context_created->pid = pid;
303         app_context_created->app_state = app_state;
304         app_context_created->is_sub_app = is_sub_app;
305
306         *app_context = app_context_created;
307
308         return APP_MANAGER_ERROR_NONE;
309 }
310
311 API int app_context_destroy(app_context_h app_context)
312 {
313         if (app_context == NULL)
314                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
315
316         free(app_context->app_id);
317         free(app_context->pkg_id);
318         free(app_context->instance_id);
319         free(app_context);
320
321         return APP_MANAGER_ERROR_NONE;
322 }
323
324 API int app_context_get_package(app_context_h app_context, char **package)
325 {
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);
329 }
330
331
332 API int app_context_get_app_id(app_context_h app_context, char **app_id)
333 {
334         char *app_id_dup;
335
336         if (app_context == NULL || app_id == NULL)
337                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
338
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);
342
343         *app_id = app_id_dup;
344
345         return APP_MANAGER_ERROR_NONE;
346 }
347
348 API int app_context_get_pid(app_context_h app_context, pid_t *pid)
349 {
350         if (app_context == NULL || pid == NULL)
351                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
352
353         *pid = app_context->pid;
354
355         return APP_MANAGER_ERROR_NONE;
356 }
357
358 API int app_context_get_package_id(app_context_h app_context, char **pkg_id)
359 {
360         char *pkg_id_dup;
361
362         if (app_context == NULL || pkg_id == NULL)
363                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
364
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);
368
369         *pkg_id = pkg_id_dup;
370
371         return APP_MANAGER_ERROR_NONE;
372 }
373
374 API int app_context_get_app_state(app_context_h app_context, app_state_e *state)
375 {
376         if (app_context == NULL || state == NULL)
377                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
378
379         *state = app_context->app_state;
380
381         return APP_MANAGER_ERROR_NONE;
382 }
383
384 API int app_context_is_terminated(app_context_h app_context, bool *terminated)
385 {
386         char appid[APPID_MAX] = {0, };
387
388         if (app_context == NULL || terminated == NULL)
389                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
390
391         if (aul_app_is_running(app_context->app_id) == 1) {
392                 *terminated = false;
393         } else {
394                 if (aul_app_get_appid_bypid(app_context->pid, appid, sizeof(appid)) == AUL_R_OK)
395                         *terminated = false;
396                 else
397                         *terminated = true;
398         }
399
400         return APP_MANAGER_ERROR_NONE;
401 }
402
403 API int app_context_is_equal(app_context_h lhs, app_context_h rhs, bool *equal)
404 {
405         if (lhs == NULL || rhs == NULL || equal == NULL)
406                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
407
408         if (!strcmp(lhs->app_id, rhs->app_id) && lhs->pid == rhs->pid)
409                 *equal = true;
410         else
411                 *equal = false;
412
413         return APP_MANAGER_ERROR_NONE;
414 }
415
416 API int app_context_is_sub_app(app_context_h app_context, bool *is_sub_app)
417 {
418         if (app_context == NULL || is_sub_app == NULL)
419                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
420
421         *is_sub_app = app_context->is_sub_app;
422
423         return APP_MANAGER_ERROR_NONE;
424 }
425
426 API int app_context_clone(app_context_h *clone, app_context_h app_context)
427 {
428         int retval;
429
430         if (clone == NULL || app_context == NULL)
431                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
432
433         retval = app_context_create(app_context->app_id,
434                                         app_context->pid,
435                                         app_context->pkg_id,
436                                         app_context->app_state,
437                                         app_context->is_sub_app,
438                                         app_context->instance_id,
439                                         clone);
440         if (retval != APP_MANAGER_ERROR_NONE)
441                 return app_manager_error(retval, __FUNCTION__, NULL);
442
443         return APP_MANAGER_ERROR_NONE;
444 }
445
446 typedef struct _event_cb_context_ {
447         GHashTable *pid_table;
448         app_manager_app_context_event_cb callback;
449         void *user_data;
450 } event_cb_context_s;
451
452 static pthread_mutex_t event_cb_context_mutex = PTHREAD_MUTEX_INITIALIZER;
453 static event_cb_context_s *event_cb_context = NULL;
454
455 static void app_context_lock_event_cb_context()
456 {
457         pthread_mutex_lock(&event_cb_context_mutex);
458 }
459
460 static void app_context_unlock_event_cb_context()
461 {
462         pthread_mutex_unlock(&event_cb_context_mutex);
463 }
464
465 static bool app_context_load_all_app_context_cb_locked(app_context_h app_context, void *user_data)
466 {
467         app_context_h app_context_cloned;
468
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);
471
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);
474                 } else {
475                         app_context_destroy(app_context_cloned);
476                         app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
477                 }
478         }
479
480         return true;
481 }
482
483 static void app_context_pid_table_entry_destroyed_cb(void *data)
484 {
485         app_context_h app_context = data;
486
487         if (app_context != NULL)
488                 app_context_destroy(app_context);
489 }
490
491 static int app_context_get_pkgid_by_appid(const char *app_id, char **pkg_id)
492 {
493         pkgmgrinfo_appinfo_h appinfo;
494         char *pkg_id_dup;
495
496         if (app_id == NULL || pkg_id == NULL)
497                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
498
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");
501
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");
505         }
506
507         *pkg_id = strdup(pkg_id_dup);
508
509         pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
510         return APP_MANAGER_ERROR_NONE;
511 }
512
513 static int app_context_launched_event_cb(pid_t pid, const char *app_id, void *data)
514 {
515         app_context_h app_context = NULL;
516         char *pkg_id = NULL;
517
518         if (pid < 0 || app_id == NULL)
519                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
520
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");
523
524         app_context_lock_event_cb_context();
525
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);
530                 } else {
531                         app_context_destroy(app_context);
532                         app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
533                 }
534         }
535
536         app_context_unlock_event_cb_context();
537
538         free(pkg_id);
539         return 0;
540 }
541
542 static int app_context_terminated_event_cb(pid_t pid, void *data)
543 {
544         app_context_h app_context;
545         int lookup_key = pid;
546
547         app_context_lock_event_cb_context();
548
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));
551
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)));
555                 }
556         } else {
557                 app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, "invalid callback context");
558         }
559
560         app_context_unlock_event_cb_context();
561
562         return 0;
563 }
564
565 int app_context_set_event_cb(app_manager_app_context_event_cb callback, void *user_data)
566 {
567         if (callback == NULL)
568                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
569
570         app_context_lock_event_cb_context();
571
572         if (event_cb_context == NULL) {
573                 event_cb_context = calloc(1, sizeof(event_cb_context_s));
574
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);
578                 }
579
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");
586                 }
587
588                 app_context_foreach_app_context(app_context_load_all_app_context_cb_locked, NULL);
589
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);
592
593         }
594
595         event_cb_context->callback = callback;
596         event_cb_context->user_data = user_data;
597
598         app_context_unlock_event_cb_context();
599
600         return APP_MANAGER_ERROR_NONE;
601 }
602
603 void app_context_unset_event_cb(void)
604 {
605         app_context_lock_event_cb_context();
606
607         if (event_cb_context != NULL) {
608                 /* aul_listen_app_dead_signal(NULL, NULL); */
609                 /* aul_listen_app_launch_signal(NULL, NULL); */
610
611                 g_hash_table_destroy(event_cb_context->pid_table);
612                 free(event_cb_context);
613                 event_cb_context = NULL;
614         }
615
616         app_context_unlock_event_cb_context();
617 }
618
619 static int app_context_status_cb(const char *appid, const char *pkgid, int pid, int status, int is_subapp, void *data)
620 {
621         app_context_h app_context = NULL;
622         app_state_e state;
623         app_context_status_e context_status;
624         int ret;
625
626         state = app_context_get_app_status(status);
627         if (state == APP_STATE_TERMINATED)
628                 context_status = APP_CONTEXT_STATUS_TERMINATED;
629         else
630                 context_status = APP_CONTEXT_STATUS_LAUNCHED;
631
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);
635
636         _status_cb(app_context, context_status, data);
637         app_context_destroy(app_context);
638
639         return APP_MANAGER_ERROR_NONE;
640 }
641
642 int app_context_set_status_cb(app_manager_app_context_status_cb callback, const char *appid, void *user_data)
643 {
644         int ret;
645
646         if (callback == NULL || appid == NULL)
647                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
648
649         _status_cb = callback;
650
651         ret = aul_listen_app_status(appid, app_context_status_cb, user_data);
652         switch (ret) {
653         case AUL_R_OK:
654                 ret = APP_MANAGER_ERROR_NONE;
655                 break;
656         case AUL_R_EINVAL:
657                 ret = APP_MANAGER_ERROR_INVALID_PARAMETER;
658                 break;
659         default:
660                 ret = APP_MANAGER_ERROR_IO_ERROR;
661                 break;
662         }
663
664         return ret;
665 }
666
667 int app_context_get_app_context_by_instance_id(const char *app_id, const char *instance_id, app_context_h *app_context)
668 {
669         int ret;
670         retrieval_context_s retrieval_context = {
671                 .app_id = app_id,
672                 .pid = 0,
673                 .pkg_id = NULL,
674                 .app_state = APP_STATE_UNDEFINED,
675                 .is_sub_app = false,
676                 .matched = false,
677                 .instance_id = instance_id
678         };
679
680         if (app_id == NULL || instance_id == NULL || app_context == NULL)
681                 return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
682
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);
686
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,
693                         app_context);
694         free(retrieval_context.pkg_id);
695
696         return ret;
697 }
698
699 int app_context_get_instance_id(app_context_h app_context, char **instance_id)
700 {
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);
703
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);
707
708         return APP_MANAGER_ERROR_NONE;
709 }