Modify app_context_set_status_cb API
[platform/core/api/app-manager.git] / src / app_context.c
index 04d06c8..c312ced 100644 (file)
@@ -39,7 +39,7 @@
 
 #define APPID_MAX 128
 
-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, app_context_h *app_context);
+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);
 
 struct app_context_s {
        char *app_id;
@@ -47,6 +47,7 @@ struct app_context_s {
        char *pkg_id;
        app_state_e app_state;
        bool is_sub_app;
+       char *instance_id;
 };
 
 typedef struct _foreach_context_ {
@@ -62,9 +63,17 @@ typedef struct _retrieval_context_ {
        app_state_e app_state;
        bool is_sub_app;
        bool matched;
+       const char *instance_id;
 } retrieval_context_s;
 
-static app_manager_app_context_status_cb _status_cb;
+struct status_listen_info {
+       status_listen_h handle;
+       char *appid;
+       app_manager_app_context_status_cb callback;
+       void *user_data;
+};
+
+static GList *status_listen_list;
 
 static app_state_e app_context_get_app_status(int status)
 {
@@ -115,6 +124,7 @@ static int app_context_foreach_app_context_cb(const aul_app_info *aul_app_contex
                                        aul_app_context->pkgid,
                                        app_state,
                                        is_sub_app,
+                                       aul_app_context->instance_id,
                                        &app_context) == APP_MANAGER_ERROR_NONE) {
                        foreach_context->iteration = foreach_context->callback(app_context, foreach_context->user_data);
                        app_context_destroy(app_context);
@@ -164,6 +174,7 @@ static int app_context_foreach_running_app_context_cb(const aul_app_info *aul_ap
                                        aul_app_context->pkgid,
                                        app_state,
                                        is_sub_app,
+                                       aul_app_context->instance_id,
                                        &app_context) == APP_MANAGER_ERROR_NONE) {
                        foreach_context->iteration = foreach_context->callback(app_context, foreach_context->user_data);
                        app_context_destroy(app_context);
@@ -198,7 +209,19 @@ static int app_context_retrieve_app_context(const aul_app_info *aul_app_context,
        app_state_e app_state;
 
        if (aul_app_context != NULL && retrieval_context != NULL && retrieval_context->matched == false) {
-               if (!strcmp(aul_app_context->appid, retrieval_context->app_id)) {
+               if (retrieval_context->instance_id && retrieval_context->app_id &&
+                               !strcmp(aul_app_context->instance_id, retrieval_context->instance_id) &&
+                               !strcmp(aul_app_context->appid, retrieval_context->app_id)) {
+                       app_state = app_context_get_app_status(aul_app_context->status);
+
+                       retrieval_context->pid = aul_app_context->pid;
+                       retrieval_context->pkg_id = strdup(aul_app_context->pkgid);
+                       retrieval_context->app_state = app_state;
+                       if (aul_app_context->is_sub_app)
+                               retrieval_context->is_sub_app = true;
+                       retrieval_context->matched = true;
+               } else if (retrieval_context->instance_id == NULL && retrieval_context->app_id &&
+                               !strcmp(aul_app_context->appid, retrieval_context->app_id)) {
                        app_state = app_context_get_app_status(aul_app_context->status);
 
                        retrieval_context->pid = aul_app_context->pid;
@@ -207,6 +230,15 @@ static int app_context_retrieve_app_context(const aul_app_info *aul_app_context,
                        if (aul_app_context->is_sub_app)
                                retrieval_context->is_sub_app = true;
                        retrieval_context->matched = true;
+               } else if (retrieval_context->pid > 0 && retrieval_context->pid == aul_app_context->pid) {
+                       app_state = app_context_get_app_status(aul_app_context->status);
+
+                       retrieval_context->app_id = strdup(aul_app_context->appid);
+                       retrieval_context->pkg_id = strdup(aul_app_context->pkgid);
+                       retrieval_context->app_state = app_state;
+                       if (aul_app_context->is_sub_app)
+                               retrieval_context->is_sub_app = true;
+                       retrieval_context->matched = true;
                }
        }
 
@@ -222,7 +254,8 @@ int app_context_get_app_context(const char *app_id, app_context_h *app_context)
                .pkg_id = NULL,
                .app_state = APP_STATE_UNDEFINED,
                .is_sub_app = false,
-               .matched = false
+               .matched = false,
+               .instance_id = NULL
        };
 
        if (app_id == NULL || app_context == NULL)
@@ -241,13 +274,14 @@ int app_context_get_app_context(const char *app_id, app_context_h *app_context)
                                        retrieval_context.pkg_id,
                                        retrieval_context.app_state,
                                        retrieval_context.is_sub_app,
-                                        app_context);
+                                       retrieval_context.instance_id,
+                                       app_context);
        free(retrieval_context.pkg_id);
 
        return ret;
 }
 
-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, app_context_h *app_context)
+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)
 {
        app_context_h app_context_created;
 
@@ -271,6 +305,16 @@ static int app_context_create(const char *app_id, pid_t pid, const char *pkg_id,
                return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
        }
 
+       if (instance_id) {
+               app_context_created->instance_id = strdup(instance_id);
+               if (app_context_created->instance_id == NULL) {
+                       free(app_context_created->pkg_id);
+                       free(app_context_created->app_id);
+                       free(app_context_created);
+                       return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
+               }
+       }
+
        app_context_created->pid = pid;
        app_context_created->app_state = app_state;
        app_context_created->is_sub_app = is_sub_app;
@@ -287,6 +331,7 @@ API int app_context_destroy(app_context_h app_context)
 
        free(app_context->app_id);
        free(app_context->pkg_id);
+       free(app_context->instance_id);
        free(app_context);
 
        return APP_MANAGER_ERROR_NONE;
@@ -406,6 +451,7 @@ API int app_context_clone(app_context_h *clone, app_context_h app_context)
                                        app_context->pkg_id,
                                        app_context->app_state,
                                        app_context->is_sub_app,
+                                       app_context->instance_id,
                                        clone);
        if (retval != APP_MANAGER_ERROR_NONE)
                return app_manager_error(retval, __FUNCTION__, NULL);
@@ -493,7 +539,7 @@ static int app_context_launched_event_cb(pid_t pid, const char *app_id, void *da
 
        app_context_lock_event_cb_context();
 
-       if (app_context_create(app_id, pid, pkg_id, APP_STATE_UNDEFINED, false, &app_context) == APP_MANAGER_ERROR_NONE) {
+       if (app_context_create(app_id, pid, pkg_id, APP_STATE_UNDEFINED, false, NULL, &app_context) == APP_MANAGER_ERROR_NONE) {
                if (event_cb_context != NULL && event_cb_context->pid_table != NULL) {
                        g_hash_table_insert(event_cb_context->pid_table, GINT_TO_POINTER(&(app_context->pid)), app_context);
                        event_cb_context->callback(app_context, APP_CONTEXT_EVENT_LAUNCHED, event_cb_context->user_data);
@@ -575,8 +621,8 @@ void app_context_unset_event_cb(void)
        app_context_lock_event_cb_context();
 
        if (event_cb_context != NULL) {
-               /* aul_listen_app_dead_signal(NULL, NULL); */
-               /* aul_listen_app_launch_signal(NULL, NULL); */
+               aul_listen_app_dead_signal(NULL, NULL);
+               aul_listen_app_launch_signal_v2(NULL, NULL);
 
                g_hash_table_destroy(event_cb_context->pid_table);
                free(event_cb_context);
@@ -586,24 +632,78 @@ void app_context_unset_event_cb(void)
        app_context_unlock_event_cb_context();
 }
 
-static int app_context_status_cb(const char *appid, const char *pkgid, int pid, int status, int is_subapp, void *data)
+static struct status_listen_info *__find_status_listen_info(app_manager_app_context_status_cb callback, const char *appid)
 {
+       struct status_listen_info *info;
+       GList *iter;
+
+       iter = g_list_first(status_listen_list);
+       while (iter) {
+               info = (struct status_listen_info *)iter->data;
+               if (info && info->callback == callback && !strcmp(info->appid, appid))
+                       return info;
+               iter = g_list_next(iter);
+       }
+
+       return NULL;
+}
+
+static struct status_listen_info *__create_status_listen_info(app_manager_app_context_status_cb callback, const char *appid, void *user_data)
+{
+       struct status_listen_info *info;
+
+       info = calloc(1, sizeof(struct status_listen_info));
+       if (info == NULL) {
+               LOGE("Out of memory");
+               return NULL;
+       }
+
+       info->appid = strdup(appid);
+       if (info->appid == NULL) {
+               LOGE("Out of memory");
+               free(info);
+               return NULL;
+       }
+
+       info->callback = callback;
+       info->user_data = user_data;
+
+       return info;
+}
+
+static void __destroy_status_listen_info(struct status_listen_info *info)
+{
+       if (info == NULL)
+               return;
+
+       if (info->appid)
+               free(info->appid);
+       free(info);
+}
+
+static int app_context_status_cb(aul_app_info *aul_app_context, int ctx_status, void *data)
+{
+       struct status_listen_info *info = (struct status_listen_info *)data;
        app_context_h app_context = NULL;
-       app_state_e state;
        app_context_status_e context_status;
        int ret;
 
-       state = app_context_get_app_status(status);
-       if (state == APP_STATE_TERMINATED)
+       if (ctx_status == STATUS_TERMINATE)
                context_status = APP_CONTEXT_STATUS_TERMINATED;
        else
                context_status = APP_CONTEXT_STATUS_LAUNCHED;
 
-       ret = app_context_create(appid, pid, pkgid, state, is_subapp, &app_context);
+       ret = app_context_create(aul_app_context->appid,
+                       aul_app_context->pid,
+                       aul_app_context->pkgid,
+                       app_context_get_app_status(aul_app_context->status),
+                       aul_app_context->is_sub_app,
+                       aul_app_context->instance_id,
+                       &app_context);
        if (ret != APP_MANAGER_ERROR_NONE)
                return app_manager_error(ret, __FUNCTION__, NULL);
 
-       _status_cb(app_context, context_status, data);
+       info->callback(app_context, context_status, info->user_data);
        app_context_destroy(app_context);
 
        return APP_MANAGER_ERROR_NONE;
@@ -612,25 +712,108 @@ static int app_context_status_cb(const char *appid, const char *pkgid, int pid,
 int app_context_set_status_cb(app_manager_app_context_status_cb callback, const char *appid, void *user_data)
 {
        int ret;
+       struct status_listen_info *info;
 
        if (callback == NULL || appid == NULL)
-               return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+               return APP_MANAGER_ERROR_INVALID_PARAMETER;
 
-       _status_cb = callback;
+       info = __find_status_listen_info(callback, appid);
+       if (info) {
+               info->user_data = user_data;
+               return APP_MANAGER_ERROR_NONE;
+       }
 
-       ret = aul_listen_app_status(appid, app_context_status_cb, user_data);
-       switch (ret) {
-       case AUL_R_OK:
-               ret = APP_MANAGER_ERROR_NONE;
-               break;
-       case AUL_R_EINVAL:
-               ret = APP_MANAGER_ERROR_INVALID_PARAMETER;
-               break;
-       default:
-               ret = APP_MANAGER_ERROR_IO_ERROR;
-               break;
+       info = __create_status_listen_info(callback, appid, user_data);
+       if (info == NULL)
+               return APP_MANAGER_ERROR_OUT_OF_MEMORY;
+
+       ret = aul_listen_app_status(appid, app_context_status_cb, info, &info->handle);
+       if (ret != AUL_R_OK) {
+               __destroy_status_listen_info(info);
+               if (ret == AUL_R_EINVAL)
+                       return APP_MANAGER_ERROR_INVALID_PARAMETER;
+
+               return APP_MANAGER_ERROR_IO_ERROR;
        }
 
+       status_listen_list = g_list_append(status_listen_list, info);
+
+       return APP_MANAGER_ERROR_NONE;
+}
+
+int app_context_get_app_context_by_instance_id(const char *app_id, const char *instance_id, app_context_h *app_context)
+{
+       int ret;
+       retrieval_context_s retrieval_context = {
+               .app_id = app_id,
+               .pid = 0,
+               .pkg_id = NULL,
+               .app_state = APP_STATE_UNDEFINED,
+               .is_sub_app = false,
+               .matched = false,
+               .instance_id = instance_id
+       };
+
+       if (app_id == NULL || instance_id == NULL || app_context == NULL)
+               return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+
+       aul_app_get_running_app_instance_info(app_context_retrieve_app_context, &retrieval_context);
+       if (retrieval_context.matched == false)
+               return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
+
+       ret = app_context_create(retrieval_context.app_id,
+                       retrieval_context.pid,
+                       retrieval_context.pkg_id,
+                       retrieval_context.app_state,
+                       retrieval_context.is_sub_app,
+                       retrieval_context.instance_id,
+                       app_context);
+       free(retrieval_context.pkg_id);
+
        return ret;
 }
 
+int app_context_get_instance_id(app_context_h app_context, char **instance_id)
+{
+       if (app_context == NULL || app_context->instance_id == NULL || instance_id == NULL)
+               return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+
+       *instance_id = strdup(app_context->instance_id);
+       if (*instance_id == NULL)
+               return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
+
+       return APP_MANAGER_ERROR_NONE;
+}
+
+int app_context_get_app_context_by_pid(pid_t pid, app_context_h *app_context)
+{
+       int ret;
+       retrieval_context_s retrieval_context = {
+               .app_id = NULL,
+               .pid = pid,
+               .pkg_id = NULL,
+               .app_state = APP_STATE_UNDEFINED,
+               .is_sub_app = false,
+               .matched = false,
+               .instance_id = NULL
+       };
+
+       if (pid <= 0 || app_context == NULL)
+               return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+
+       aul_app_get_running_app_instance_info(app_context_retrieve_app_context, &retrieval_context);
+       if (retrieval_context.matched == false)
+               return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
+
+       ret = app_context_create(retrieval_context.app_id,
+                       retrieval_context.pid,
+                       retrieval_context.pkg_id,
+                       retrieval_context.app_state,
+                       retrieval_context.is_sub_app,
+                       retrieval_context.instance_id,
+                       app_context);
+       free((void *)retrieval_context.app_id);
+       free(retrieval_context.pkg_id);
+
+       return ret;
+}