From: Myungki Lee Date: Mon, 1 Feb 2016 10:23:40 +0000 (+0900) Subject: Add new apis to get app_status X-Git-Tag: submit/tizen/20160223.071811^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F54%2F56754%2F14;p=platform%2Fcore%2Fapi%2Fapp-manager.git Add new apis to get app_status - 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 --- diff --git a/include/app_context.h b/include/app_context.h index 2ed320b..87e54fb 100644 --- a/include/app_context.h +++ b/include/app_context.h @@ -53,6 +53,19 @@ typedef enum } app_context_event_e; +/** + * @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 @@ -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 @@ -111,6 +124,39 @@ int app_context_get_app_id(app_context_h app_context, char **app_id); 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 @@ -140,6 +186,19 @@ int app_context_is_terminated(app_context_h app_context, bool *terminated); 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 diff --git a/include/app_manager.h b/include/app_manager.h index 32a798a..d3c30e3 100644 --- a/include/app_manager.h +++ b/include/app_manager.h @@ -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 diff --git a/src/app_context.c b/src/app_context.c index efd27a6..c6d5183 100644 --- a/src/app_context.c +++ b/src/app_context.c @@ -38,11 +38,14 @@ #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); diff --git a/src/app_manager.c b/src/app_manager.c index 906c48d..fdd35a6 100644 --- a/src/app_manager.c +++ b/src/app_manager.c @@ -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); diff --git a/src/app_manager_internal.h b/src/app_manager_internal.h index f428c35..7a5a596 100644 --- a/src/app_manager_internal.h +++ b/src/app_manager_internal.h @@ -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);