Add new apis to get app_status 54/56754/14 accepted/tizen/common/20160301.120618 accepted/tizen/ivi/20160223.232036 accepted/tizen/mobile/20160223.231949 accepted/tizen/tv/20160223.232003 accepted/tizen/wearable/20160223.232020 submit/tizen/20160223.071811 submit/tizen_common/20160229.190608
authorMyungki Lee <mk5004.lee@samsung.com>
Mon, 1 Feb 2016 10:23:40 +0000 (19:23 +0900)
committerMyungKi Lee <mk5004.lee@samsung.com>
Wed, 3 Feb 2016 02:15:04 +0000 (18:15 -0800)
- add api to get the full running app list
- define app state enum
- extend app_context struct
- add api to get app_state, package id
- modify about operation of resume_app

Change-Id: Iec75d64f0abdb0ac6cdc1f9ed7eaa177c48a83ea
Signed-off-by: Myungki Lee <mk5004.lee@samsung.com>
include/app_context.h
include/app_manager.h
src/app_context.c
src/app_manager.c
src/app_manager_internal.h

index 2ed320b..87e54fb 100644 (file)
@@ -54,6 +54,19 @@ typedef enum
 
 
 /**
+ * @brief Enumeration for the application state
+ * @since_tizen 3.0
+ */
+typedef enum {
+    APP_STATE_UNDEFINED, /**< The undefined state */
+    APP_STATE_FOREGROUND, /**< The UI application is running in the foreground. */
+    APP_STATE_BACKGROUND, /**< The UI application is running in the background. */
+    APP_STATE_SERVICE, /**< The Service application is running. */
+    APP_STATE_TERMINATED, /**< The application is terminated. */
+} app_state_e;
+
+
+/**
  * @brief  Destroys the application context handle and releases all its resources.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @param[in]   app_context  The application context handle
@@ -69,11 +82,11 @@ int app_context_destroy(app_context_h app_context);
 
 /**
  * @deprecated Deprecated since 2.3.1. Use app_context_get_app_id() instead.
- * @brief    Gets the package with the given application context.
+ * @brief    Gets the application ID with the given application context.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @remarks You must release @a package using free().
  * @param[in]   app_context  The application context
- * @param[out]  package      The package of the given application context
+ * @param[out]  package      The application ID of the given application context
  * @return      @c 0 on success,
  *              otherwise a negative error value
  * @retval  #APP_MANAGER_ERROR_NONE               Successful
@@ -112,6 +125,39 @@ int app_context_get_pid(app_context_h app_context, pid_t *pid);
 
 
 /**
+ * @brief  Gets the package id with the given application context.
+ * @since_tizen 3.0
+ * @remarks     You must release @a pkg_id using free().
+ * @param[in]   app_context  The application context
+ * @param[out]  pkg_id   The package ID of the given application context
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ * @retval  #APP_MANAGER_ERROR_NONE               Successful
+ * @retval  #APP_MANAGER_ERROR_INVALID_PARAMETER  Invalid parameter
+ * @retval  #APP_MANAGER_ERROR_OUT_OF_MEMORY      Out of memory
+ */
+int app_context_get_package_id(app_context_h app_context, char **pkg_id);
+
+
+/**
+ * @brief  Gets the application state with the given application context.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/packagemanager.info
+ * @remarks Note that application's state might be changed after you get app_context.
+ *          This API just returns the state of application when you get the app_context.
+ * @param[in]   app_context  The application context
+ * @param[out]  state        The application state of the given application context
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ * @retval  #APP_MANAGER_ERROR_NONE               Successful
+ * @retval  #APP_MANAGER_ERROR_INVALID_PARAMETER  Invalid parameter
+ * @retval  #APP_MANAGER_ERROR_PERMISSION_DENIED  Permission denied
+ */
+int app_context_get_app_state(app_context_h app_context, app_state_e *state);
+
+
+/**
  * @brief  Checks whether the application with the given application context is terminated.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @param[in]   app_context  The application context
@@ -141,6 +187,19 @@ int app_context_is_equal(app_context_h lhs, app_context_h rhs, bool *equal);
 
 
 /**
+ * @brief  Checks whether the application is running as a sub application of the application group.
+ * @since_tizen 3.0
+ * @param[in]   app_context  The application context
+ * @param[out]  is_sub_app @c true if the sub application of the group, \n
+ *                    otherwise @c false if the main application of the group
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ * @retval  #APP_MANAGER_ERROR_NONE               Successful
+ * @retval  #APP_MANAGER_ERROR_INVALID_PARAMETER  Invalid parameter
+ */
+int app_context_is_sub_app(app_context_h app_context, bool *is_sub_app);
+
+/**
  * @brief  Clones the application context handle.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @param[out]  clone        The newly created application context handle, if cloning is successful
index 32a798a..d3c30e3 100644 (file)
@@ -133,6 +133,27 @@ void app_manager_unset_app_context_event_cb(void);
  */
 int app_manager_foreach_app_context(app_manager_app_context_cb callback, void *user_data);
 
+
+/**
+ * @brief  Retrieves all application contexts of running applications including sub apps.
+ * @details You can iterate all the running application contexts using this API.
+ *          This API is similar to app_manager_foreach_app_context() except that this API iterates application contexts including sub apps in application groups.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/packagemanager.info
+ * @param[in]   callback   The callback function to invoke
+ * @param[in]   user_data  The user data to be passed to the callback function
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ * @retval  #APP_MANAGER_ERROR_NONE               Successful
+ * @retval  #APP_MANAGER_ERROR_INVALID_PARAMETER  Invalid parameter
+ * @retval  #APP_MANAGER_ERROR_PERMISSION_DENIED  Permission denied
+ * @post   This function invokes app_manager_app_context_cb() for each application context.
+ * @see app_manager_app_context_cb()
+ */
+int app_manager_foreach_running_app_context(app_manager_app_context_cb callback, void *user_data);
+
+
 /**
  * @brief  Gets the application context for the given ID of the application.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
index efd27a6..c6d5183 100644 (file)
 
 #define APPID_MAX 128
 
-static int app_context_create(const char *app_id, pid_t pid, app_context_h *app_context);
+static int app_context_create(const char *app_id, pid_t pid, char *pkg_id, app_state_e app_state, bool is_sub_app, app_context_h *app_context);
 
 struct app_context_s {
        char *app_id;
        pid_t pid;
+       char *pkg_id;
+       app_state_e app_state;
+       bool is_sub_app;
 };
 
 typedef struct _foreach_context_ {
@@ -54,12 +57,41 @@ typedef struct _foreach_context_ {
 typedef struct _retrieval_context_ {
        const char *app_id;
        pid_t pid;
+       char *pkg_id;
+       app_state_e app_state;
+       bool is_sub_app;
        bool matched;
 } retrieval_context_s;
 
+static app_state_e app_context_get_app_status(int status)
+{
+       app_state_e app_state;
+
+       switch (status) {
+       case STATUS_VISIBLE:
+               app_state = APP_STATE_FOREGROUND;
+               break;
+       case STATUS_LAUNCHING:
+       case STATUS_BG:
+               app_state = APP_STATE_BACKGROUND;
+               break;
+       case STATUS_SERVICE:
+               app_state = APP_STATE_SERVICE;
+               break;
+       default:
+               app_state = APP_STATE_UNDEFINED;
+               break;
+       }
+
+       return app_state;
+}
+
 static int app_context_foreach_app_context_cb(const aul_app_info *aul_app_context, void *cb_data)
 {
        foreach_context_s* foreach_context = cb_data;
+       app_context_h app_context;
+       app_state_e app_state;
+       bool is_sub_app = false;
 
        if (foreach_context == NULL) {
                app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
@@ -67,9 +99,17 @@ static int app_context_foreach_app_context_cb(const aul_app_info *aul_app_contex
        }
 
        if (foreach_context->iteration == true) {
-               app_context_h app_context = NULL;
+               app_state = app_context_get_app_status(aul_app_context->status);
+
+               if (aul_app_context->is_sub_app)
+                       is_sub_app = true;
 
-               if (app_context_create(aul_app_context->appid, aul_app_context->pid, &app_context) == APP_MANAGER_ERROR_NONE) {
+               if (app_context_create(aul_app_context->appid,
+                                       aul_app_context->pid,
+                                       aul_app_context->pkgid,
+                                       app_state,
+                                       is_sub_app,
+                                       &app_context) == APP_MANAGER_ERROR_NONE) {
                        foreach_context->iteration = foreach_context->callback(app_context, foreach_context->user_data);
                        app_context_destroy(app_context);
                }
@@ -95,14 +135,75 @@ int app_context_foreach_app_context(app_manager_app_context_cb callback, void *u
        return APP_MANAGER_ERROR_NONE;
 }
 
+static int app_context_foreach_running_app_context_cb(const aul_app_info *aul_app_context, void *cb_data)
+{
+       foreach_context_s* foreach_context = cb_data;
+       app_context_h app_context;
+       app_state_e app_state;
+       bool is_sub_app = false;
+
+       if (foreach_context == NULL) {
+               app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+               return 0;
+       }
+
+       if (foreach_context->iteration == true) {
+               app_state = app_context_get_app_status(aul_app_context->status);
+
+               if (aul_app_context->is_sub_app)
+                       is_sub_app = true;
+
+               if (app_context_create(aul_app_context->appid,
+                                       aul_app_context->pid,
+                                       aul_app_context->pkgid,
+                                       app_state,
+                                       is_sub_app,
+                                       &app_context) == APP_MANAGER_ERROR_NONE) {
+                       foreach_context->iteration = foreach_context->callback(app_context, foreach_context->user_data);
+                       app_context_destroy(app_context);
+               }
+       }
+
+       return 0;
+}
+
+int app_context_foreach_running_app_context(app_manager_app_context_cb callback, void *user_data)
+{
+       int ret;
+       foreach_context_s foreach_context = {
+               .callback = callback,
+               .user_data = user_data,
+               .iteration = true
+       };
+
+       if (callback == NULL)
+               return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+
+       ret = aul_app_get_all_running_app_info(app_context_foreach_running_app_context_cb, &foreach_context);
+       if (ret != AUL_R_OK) {
+               if (ret == AUL_R_EILLACC)
+                       return app_manager_error(APP_MANAGER_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL);
+               else
+                       return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL);
+       }
+
+       return APP_MANAGER_ERROR_NONE;
+}
 
 static int app_context_retrieve_app_context(const aul_app_info *aul_app_context, void *cb_data)
 {
        retrieval_context_s *retrieval_context = cb_data;
+       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)) {
+                       app_state = app_context_get_app_status(aul_app_context->status);
+
                        retrieval_context->pid = aul_app_context->pid;
+                       retrieval_context->pkg_id = 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;
                }
        }
@@ -115,6 +216,9 @@ int app_context_get_app_context(const char *app_id, app_context_h *app_context)
        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
        };
 
@@ -129,10 +233,16 @@ int app_context_get_app_context(const char *app_id, app_context_h *app_context)
        if (retrieval_context.matched == false)
                return app_manager_error(APP_MANAGER_ERROR_NO_SUCH_APP, __FUNCTION__, NULL);
 
-       return app_context_create(retrieval_context.app_id, retrieval_context.pid, app_context);
+
+       return app_context_create(retrieval_context.app_id,
+                                       retrieval_context.pid,
+                                       retrieval_context.pkg_id,
+                                       retrieval_context.app_state,
+                                       retrieval_context.is_sub_app,
+                                        app_context);
 }
 
-static int app_context_create(const char *app_id, pid_t pid, app_context_h *app_context)
+static int app_context_create(const char *app_id, pid_t pid, char *pkg_id, app_state_e app_state, bool is_sub_app, app_context_h *app_context)
 {
        app_context_h app_context_created;
 
@@ -149,7 +259,16 @@ static int app_context_create(const char *app_id, pid_t pid, app_context_h *app_
                return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
        }
 
+       app_context_created->pkg_id = strdup(pkg_id);
+       if (app_context_created->pkg_id == NULL) {
+               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;
 
        *app_context = app_context_created;
 
@@ -162,6 +281,7 @@ API int app_context_destroy(app_context_h app_context)
                return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
 
        free(app_context->app_id);
+       free(app_context->pkg_id);
        free(app_context);
 
        return APP_MANAGER_ERROR_NONE;
@@ -200,6 +320,32 @@ API int app_context_get_pid(app_context_h app_context, pid_t *pid)
        return APP_MANAGER_ERROR_NONE;
 }
 
+API int app_context_get_package_id(app_context_h app_context, char **pkg_id)
+{
+       char *pkg_id_dup;
+
+       if (app_context == NULL || pkg_id == NULL)
+               return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+
+       pkg_id_dup = strdup(app_context->pkg_id);
+       if (pkg_id_dup == NULL)
+               return app_manager_error(APP_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
+
+       *pkg_id = pkg_id_dup;
+
+       return APP_MANAGER_ERROR_NONE;
+}
+
+API int app_context_get_app_state(app_context_h app_context, app_state_e *state)
+{
+       if (app_context == NULL || state == NULL)
+               return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+
+       *state = app_context->app_state;
+
+       return APP_MANAGER_ERROR_NONE;
+}
+
 API int app_context_is_terminated(app_context_h app_context, bool *terminated)
 {
        if (app_context == NULL || terminated == NULL)
@@ -232,6 +378,16 @@ API int app_context_is_equal(app_context_h lhs, app_context_h rhs, bool *equal)
        return APP_MANAGER_ERROR_NONE;
 }
 
+API int app_context_is_sub_app(app_context_h app_context, bool *is_sub_app)
+{
+       if (app_context == NULL || is_sub_app == NULL)
+               return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+
+       *is_sub_app = app_context->is_sub_app;
+
+       return APP_MANAGER_ERROR_NONE;
+}
+
 API int app_context_clone(app_context_h *clone, app_context_h app_context)
 {
        int retval;
@@ -239,7 +395,12 @@ API int app_context_clone(app_context_h *clone, app_context_h app_context)
        if (clone == NULL || app_context == NULL)
                return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
 
-       retval = app_context_create(app_context->app_id, app_context->pid, clone);
+       retval = app_context_create(app_context->app_id,
+                                       app_context->pid,
+                                       app_context->pkg_id,
+                                       app_context->app_state,
+                                       app_context->is_sub_app,
+                                       clone);
        if (retval != APP_MANAGER_ERROR_NONE)
                return app_manager_error(retval, __FUNCTION__, NULL);
 
@@ -300,7 +461,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, &app_context) == APP_MANAGER_ERROR_NONE) {
+       if (app_context_create(app_id, pid, NULL, APP_STATE_UNDEFINED, false, &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);
index 906c48d..fdd35a6 100644 (file)
@@ -92,6 +92,16 @@ API int app_manager_foreach_app_context(app_manager_app_context_cb callback, voi
                return APP_MANAGER_ERROR_NONE;
 }
 
+API int app_manager_foreach_running_app_context(app_manager_app_context_cb callback, void *user_data)
+{
+       int retval = app_context_foreach_running_app_context(callback, user_data);
+
+       if (retval != APP_MANAGER_ERROR_NONE)
+               return app_manager_error(retval, __FUNCTION__, NULL);
+       else
+               return APP_MANAGER_ERROR_NONE;
+}
+
 API int app_manager_get_app_context(const char *app_id, app_context_h *app_context)
 {
        int retval = app_context_get_app_context(app_id, app_context);
index f428c35..7a5a596 100644 (file)
@@ -40,6 +40,8 @@ int app_manager_error(app_manager_error_e error, const char* function, const cha
 
 int app_context_foreach_app_context(app_manager_app_context_cb callback, void *user_data);
 
+int app_context_foreach_running_app_context(app_manager_app_context_cb callback, void *user_data);
+
 int app_context_get_app_context(const char *app_id, app_context_h *app_context);
 
 int app_context_set_event_cb(app_manager_app_context_event_cb callback, void *user_data);