Taskmanager / src /
data.c
/*
* Copyright (c) 2016 Samsung Electronics Co., Ltd
*
* Licensed under the Flora License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://floralicense.org/license/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <package_manager.h>
#include <app_common.h>
#include <app_manager.h>
#include <Elementary.h>
#include "data.h"
#include "$(appName).h"
#include "item.h"
#include "defines.h"
static struct data_info {
app_info_filter_h app_info_filter;
Eina_List *apps_list;
char *taskmgr_id;
} s_info = {
.app_info_filter = NULL,
.apps_list = NULL,
.taskmgr_id = NULL
};
app_item_t *_item_create(const char *app_id, const char *icon_path);
static void _clear_application_list(void);
static bool _app_info_cb(app_info_h app_info, void *user_data);
static int _compare_strings(char *app_id1, char *app_id2);
static int _compare_items_cb(const void *data1, const void *data2);
static void _remove_app_from_list(char *app_id);
/**
* @brief Initialization function for data module.
*/
void data_initialize(void)
{
if (app_info_filter_create(&s_info.app_info_filter) != APP_MANAGER_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to create app info filter");
return;
}
if (app_info_filter_add_bool(s_info.app_info_filter, PACKAGE_INFO_PROP_APP_NODISPLAY, false) != APP_MANAGER_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to set nodisplay property for filter");
return;
}
if (app_get_id(&s_info.taskmgr_id) != APP_ERROR_NONE)
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get taskmgr id");
}
/**
* @brief Finalization function for data module.
*/
void data_finalize(void)
{
if (app_info_filter_destroy(s_info.app_info_filter) != APP_MANAGER_ERROR_NONE)
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to destroy filter handle");
s_info.app_info_filter = NULL;
_clear_application_list();
}
/**
* @brief Function which obtains a list of all the running applications.
* For each found running application, an additional data is acquired:
* - application identifier,
* - application icon path.
* These information is wrapped with app_item_t structure and packed into
* a list.
* @return This function returns the applications list if it was successfully
* created, otherwise NULL is returned.
*/
Eina_List * data_application_mgr_get_running_apps(void)
{
if (s_info.apps_list)
_clear_application_list();
if (!s_info.app_info_filter) {
dlog_print(DLOG_ERROR, LOG_TAG, "App info filter not initialized");
return NULL;
}
if (app_info_filter_foreach_appinfo(s_info.app_info_filter, _app_info_cb, NULL) != APP_MANAGER_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to execute callback for each filtered application");
return NULL;
}
s_info.apps_list = eina_list_sort(s_info.apps_list, 0, _compare_items_cb);
return s_info.apps_list;
}
/**
* @brief Function which terminates an application with given identifier.
* @param[in] app_id The identifier of the application to be terminated.
* @return This function returns 'true' if a requested application was successfully
* terminated, otherwise 'false' is returned.
*/
bool data_application_mgr_terminate_app(char *app_id)
{
app_context_h app_context = NULL;
if (!app_id) {
dlog_print(DLOG_ERROR, LOG_TAG, "Invalid parameter");
return false;
}
if (app_manager_get_app_context(app_id, &app_context) != APP_MANAGER_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get app context");
return false;
}
if (app_manager_request_terminate_bg_app(app_context) != APP_MANAGER_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to terminate app");
return false;
}
if (app_context_destroy(app_context) != APP_MANAGER_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to destroy context handle");
return false;
}
_remove_app_from_list(app_id);
return true;
}
/**
* @brief Function which resumes an application with given identifier.
* @param[in] app_id The identifier of the application to be resumed.
* @return This function returns 'true' if a requested application was successfully
* resumed, otherwise 'false' is returned.
*/
bool data_application_mgr_resume_app(char *app_id)
{
app_context_h app_context = NULL;
if (!app_id) {
dlog_print(DLOG_ERROR, LOG_TAG, "Invalid parameter");
return false;
}
if (app_manager_get_app_context(app_id, &app_context) != APP_MANAGER_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get app context");
return false;
}
if (app_manager_resume_app(app_context) != APP_MANAGER_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to resume app");
return false;
}
if (app_context_destroy(app_context) != APP_MANAGER_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to destroy context handle");
return false;
}
return true;
}
/**
* @brief Internal function which creates an item for application's information
* display (icon and application's identifier).
* @param[in] app_id The identifier of an application which is to be displayed.
* @param[in] icon_path The path to the application's icon to be displayed.
* @return This function returns an allocated app_item_t structure with provided
* data stored. If the function fails, then NULL is returned.
*/
app_item_t *_item_create(const char *app_id, const char *icon_path)
{
app_item_t *item;
if (!app_id || !icon_path) {
dlog_print(DLOG_ERROR, LOG_TAG, "Invalid parameter");
return NULL;
}
item = (app_item_t *)calloc(1, sizeof(app_item_t));
if (!item) {
dlog_print(DLOG_ERROR, LOG_TAG, "Allocation failed");
return NULL;
}
item->app_id = strdup(app_id);
item->icon_path = strdup(icon_path);
return item;
}
/**
* @brief Internal function which clears the applications list from all the
* app_item_t structures.
*/
static void _clear_application_list(void)
{
Eina_List *it = NULL;
app_item_t *item = NULL;
EINA_LIST_FOREACH(s_info.apps_list, it, item)
{
free(item->app_id);
free(item->icon_path);
free(item);
}
eina_list_free(s_info.apps_list);
s_info.apps_list = NULL;
}
/**
* @brief Internal callback function responsible for applications list creation.
* This callback function is attached with app_info_filter_foreach_appinfo() function
* and is invoked for each installed application which does not have 'no display' flag set.
* Once this callback function is invoked, it obtains the application identifier,
* associated icon's path and running state. If the running state is set to 'false',
* then this function ends its execution, otherwise all the acquired information
* is stored in a list in a form of app_item_t structure.
* @param[in] app_info The application information handle which is used for application's
* identifier and icon's path acquisition.
* @param[in] user_data The user data passed to the app_info_filter_foreach_appinfo() function.
* @return This function returns 'true' if provided app_info represents running application,
* otherwise 'false' is returned.
*/
static bool _app_info_cb(app_info_h app_info, void *user_data)
{
char *app_id = NULL;
char *app_icon = NULL;
bool running = false;
app_item_t *new_item = NULL;
if (app_info_get_app_id(app_info, &app_id) != APP_MANAGER_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get app id");
return false;
}
if (app_info_get_icon(app_info, &app_icon) != APP_MANAGER_ERROR_NONE) {
char *res_path = app_get_shared_resource_path();
if(!res_path) {
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get app icon");
return false;
}
const char *common_icon = "taskmanager.png";
app_icon = (char*)malloc(1 + strlen(res_path) + strlen(common_icon));
sprintf(app_icon, "%s%s", res_path, common_icon);
}
if (app_manager_is_running(app_id, &running) != APP_MANAGER_ERROR_NONE) {
free(app_id);
free(app_icon);
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get running state");
return false;
}
if (running && _compare_strings(app_id, s_info.taskmgr_id)) {
new_item = _item_create(app_id, app_icon);
if (!new_item) {
free(app_id);
free(app_icon);
dlog_print(DLOG_ERROR, LOG_TAG, "Failed to create new item");
return false;
}
s_info.apps_list = eina_list_append(s_info.apps_list, new_item);
}
free(app_id);
free(app_icon);
return true;
}
/**
* @brief Internal function which performs two strings comparison with length checking.
* @param[in] app_id1 The first string.
* @param[in] app_id2 The second string.
* @return This function returns:
* - -1 if the first character that does not match has a lower value in app_id1 than in app_id2
* or if both strings are equal,
* - 1 if the first character that does not match has a greater value in app_id1 than in app_id2.
*/
static int _compare_strings(char *app_id1, char *app_id2)
{
int ret = strncmp(app_id1, app_id2, ITEM_APP_ID_STR_MAX_LENGTH);
if (strlen(app_id1) == strlen(app_id2) && !ret)
return 0;
else
return ret > 0 ? 1 : -1;
}
/**
* @brief Internal callback function responsible for two app_item_t structures comparison.
* This function is attached with the eina_list_sort() function and is used for list
* items sorting.
* @param[in] data1 The first data object to compare.
* @param[in] data2 The second data object to compare.
* @return This function returns:
* - -1 if the first character that does not match has a lower value in app_id1 than in app_id2
* or if both strings are equal,
* - 1 if the first character that does not match has a greater value in app_id1 than in app_id2.
*/
static int _compare_items_cb(const void *data1, const void *data2)
{
app_item_t *item1 = NULL;
app_item_t *item2 = NULL;
if (!data1 || !data2) {
dlog_print(DLOG_ERROR, LOG_TAG, "Invalid parameter");
return 0;
}
item1 = (app_item_t *)data1;
item2 = (app_item_t *)data2;
return _compare_strings(item1->app_id, item2->app_id);
}
/**
* @brief Internal function responsible for app_item structure with given application
* identifier removal from the list.
* @param[in] app_id The application identifier which structure is to be removed.
*/
static void _remove_app_from_list(char *app_id)
{
Eina_List *it = NULL;
app_item_t *item = NULL;
EINA_LIST_FOREACH(s_info.apps_list, it, item)
if (!_compare_strings(item->app_id, app_id)) {
s_info.apps_list = eina_list_remove(s_info.apps_list, item);
free(item->app_id);
free(item->icon_path);
free(item);
break;
}
}