* @brief The application control handle.
* @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
*/
-typedef struct app_control_s *app_control_h;
+typedef void *app_control_h;
/**
* @brief The application control action handle.
* @since_tizen 5.5
*/
-typedef struct app_control_action_s *app_control_action_h;
+typedef void *app_control_action_h;
/**
* @brief Called when another application sends a launch request to the application.
* @{
*/
+#ifndef DEPRECATED_API
+#define DEPRECATED_API __attribute__((__visibility__("default"), deprecated))
+#endif
+
/**
* @brief Definition for the app_control data: Connects the previous application with the next application when the sub-application is terminated.
* @details If a sub-application is terminated, the framework will connect the previous application with the next application.
* @retval #APP_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
* @see app_control_get_window()
*/
-int app_control_set_window(app_control_h app_control, unsigned int id);
+int app_control_set_window(app_control_h app_control, unsigned int id) DEPRECATED_API;
/**
* @brief Gets the window ID of the application.
* @retval #APP_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
* @see app_control_set_app_id()
*/
-int app_control_get_window(app_control_h app_control, unsigned int *id);
+int app_control_get_window(app_control_h app_control, unsigned int *id) DEPRECATED_API;
typedef int (*app_control_host_res_fn)(void *data);
* @retval #APP_CONTROL_ERROR_NONE Successful
* @retval #APP_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
*/
-int app_control_request_transient_app(app_control_h app_control, unsigned int callee_id, app_control_host_res_fn cbfunc, void *data);
+int app_control_request_transient_app(app_control_h app_control, unsigned int callee_id, app_control_host_res_fn cbfunc, void *data) DEPRECATED_API;
/**
* @platform
SET_TARGET_PROPERTIES(${TARGET_APP_CONTROL} PROPERTIES VERSION ${FULLVER})
TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CONTROL} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/
${CMAKE_CURRENT_SOURCE_DIR}/../
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../
${CMAKE_CURRENT_SOURCE_DIR}/../../include)
APPLY_PKG_CONFIG(${TARGET_APP_CONTROL} PUBLIC
+++ /dev/null
-/*
- * Copyright (c) 2011 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <pthread.h>
-
-#include <glib.h>
-#include <bundle.h>
-#include <bundle_internal.h>
-#include <aul.h>
-#include <aul_svc.h>
-#include <dlog.h>
-#include <appcore_base_control.h>
-
-#include <app_control.h>
-#include <app_control_internal.h>
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#define LOG_TAG "CAPI_APPFW_APP_CONTROL"
-
-#ifndef TIZEN_PATH_MAX
-#define TIZEN_PATH_MAX 1024
-#endif
-
-#define BUNDLE_KEY_PREFIX_AUL "__AUL_"
-#define BUNDLE_KEY_PREFIX_SERVICE "__APP_SVC_"
-
-#define BUNDLE_KEY_OPERATION "__APP_SVC_OP_TYPE__"
-#define BUNDLE_KEY_URI "__APP_SVC_URI__"
-#define BUNDLE_KEY_MIME "__APP_SVC_MIME_TYPE__"
-#define BUNDLE_KEY_DATA "__APP_SVC_DATA__"
-#define BUNDLE_KEY_PACKAGE "__APP_SVC_PKG_NAME__"
-#define BUNDLE_KEY_WINDOW "__APP_SVC_K_WIN_ID__"
-#define BUNDLE_KEY_CATEGORY "__APP_SVC_CATEGORY__"
-
-#define LAUNCH_MODE_SIZE 8
-#define LAUNCH_MODE_SINGLE "single"
-#define LAUNCH_MODE_GROUP "group"
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-
-#undef EXPORT_API
-#define EXPORT_API __attribute__ ((visibility("default")))
-
-typedef enum {
- APP_CONTROL_TYPE_REQUEST,
- APP_CONTROL_TYPE_EVENT,
- APP_CONTROL_TYPE_REPLY,
-} app_control_type_e;
-
-struct app_control_s {
- int id;
- app_control_type_e type;
- bundle *data;
- int launch_pid;
-};
-
-typedef struct app_control_request_context_s {
- app_control_h app_control;
- app_control_result_cb result_cb;
- app_control_reply_cb reply_cb;
- void *user_data;
-} *app_control_request_context_h;
-
-struct launch_request_s {
- int id;
- bool implicit_default_operation;
- app_control_request_context_h request_context;
- app_control_h app_control;
- app_control_result_cb result_cb;
- app_control_reply_cb reply_cb;
- void *user_data;
- app_control_h reply;
- app_control_result_e result;
-};
-
-struct app_control_action_s {
- char *action;
- appcore_base_control_h handle;
- app_control_action_cb callback;
- void *user_data;
-};
-
-struct reply_info_s {
- bundle *b;
- aul_svc_result_val result;
- void *user_data;
-};
-
-struct result_info_s {
- int result;
- void *user_data;
-};
-
-struct pending_item_s {
- int id;
- struct reply_info_s *reply_info;
- struct result_info_s *result_info;
-};
-
-typedef int (*launch_request_handler)(struct launch_request_s *req);
-
-static int app_control_create_reply(bundle *data, struct app_control_s **app_control);
-static void app_control_request_reply_broker(bundle *appsvc_bundle,
- int appsvc_request_code, aul_svc_result_val appsvc_result,
- void *appsvc_data);
-static void app_control_request_result_broker(int request_code, int result,
- void *user_data);
-
-static pthread_mutex_t __mutex = PTHREAD_MUTEX_INITIALIZER;
-static GList *__pending_list;
-
-static int __generate_request_id(void)
-{
- static int id;
-
- g_atomic_int_inc(&id);
- return id;
-}
-
-static void __destroy_result_info(gpointer data)
-{
- struct result_info_s *info = data;
-
- if (!info)
- return;
-
- free(info);
-}
-
-static struct result_info_s *__create_result_info(int result,
- void *user_data)
-{
- struct result_info_s *info;
-
- info = calloc(1, sizeof(struct result_info_s));
- if (!info) {
- LOGE("Out of memory");
- return NULL;
- }
-
- info->result = result;
- info->user_data = user_data;
-
- return info;
-}
-
-static void __destroy_reply_info(gpointer data)
-{
- struct reply_info_s *info = data;
-
- if (!info)
- return;
-
- if (info->b)
- bundle_free(info->b);
-
- free(info);
-}
-
-static struct reply_info_s *__create_reply_info(bundle *b,
- aul_svc_result_val result, void *user_data)
-{
- struct reply_info_s *info;
-
- info = calloc(1, sizeof(struct reply_info_s));
- if (!info) {
- LOGE("Out of memory");
- return NULL;
- }
-
- info->b = bundle_dup(b);
- if (!info->b) {
- LOGE("Failed to duplicate bundle");
- free(info);
- return NULL;
- }
-
- info->result = result;
- info->user_data = user_data;
-
- return info;
-}
-
-static void __destroy_pending_item(gpointer data)
-{
- struct pending_item_s *item = data;
-
- if (!item)
- return;
-
- if (item->reply_info)
- __destroy_reply_info(item->reply_info);
-
- if (item->result_info)
- __destroy_result_info(item->result_info);
-
- free(item);
-}
-
-static struct pending_item_s *__create_pending_item(int id)
-{
- struct pending_item_s *item;
-
- item = calloc(1, sizeof(struct pending_item_s));
- if (!item) {
- LOGE("Out of memory");
- return NULL;
- }
-
- item->id = id;
-
- return item;
-}
-
-static void __add_pending_item(int id)
-{
- struct pending_item_s *item;
-
- item = __create_pending_item(id);
- if (!item)
- return;
-
- pthread_mutex_lock(&__mutex);
- __pending_list = g_list_prepend(__pending_list, item);
- pthread_mutex_unlock(&__mutex);
-}
-
-static void __remove_pending_item(int id)
-{
- struct pending_item_s *item;
- GList *iter;
-
- pthread_mutex_lock(&__mutex);
- iter = __pending_list;
- while (iter) {
- item = (struct pending_item_s *)iter->data;
- iter = g_list_next(iter);
- if (item->id == id) {
- __pending_list = g_list_remove(__pending_list, item);
- __destroy_pending_item(item);
- break;
- }
- }
- pthread_mutex_unlock(&__mutex);
-}
-
-static struct pending_item_s *__pop_pending_item(int id)
-{
- struct pending_item_s *item;
- GList *iter;
-
- pthread_mutex_lock(&__mutex);
- iter = __pending_list;
- while (iter) {
- item = (struct pending_item_s *)iter->data;
- iter = g_list_next(iter);
- if (item->id == id) {
- __pending_list = g_list_remove(__pending_list, item);
- pthread_mutex_unlock(&__mutex);
- return item;
- }
- }
- pthread_mutex_unlock(&__mutex);
-
- return NULL;
-}
-
-static gboolean __process_pending_item(gpointer data)
-{
- struct pending_item_s *item = data;
- struct result_info_s *result_info;
- struct reply_info_s *reply_info;
-
- if (!item)
- return G_SOURCE_REMOVE;
-
- if (item->result_info) {
- result_info = item->result_info;
- app_control_request_result_broker(item->id,
- result_info->result, result_info->user_data);
- __destroy_result_info(result_info);
- item->result_info = NULL;
- return G_SOURCE_CONTINUE;
- }
-
- if (item->reply_info) {
- reply_info = item->reply_info;
- app_control_request_reply_broker(reply_info->b, item->id,
- reply_info->result, reply_info->user_data);
- __destroy_reply_info(reply_info);
- item->reply_info = NULL;
- }
- __destroy_pending_item(item);
-
- return G_SOURCE_REMOVE;
-}
-
-static void __flush_pending_item(int id)
-{
- struct pending_item_s *item;
-
- item = __pop_pending_item(id);
- if (!item)
- return;
-
- if (!item->reply_info && !item->result_info) {
- __destroy_pending_item(item);
- return;
- }
-
- g_idle_add(__process_pending_item, item);
-}
-
-static bool __exist_pending_item(int id)
-{
- struct pending_item_s *item;
- GList *iter;
-
- pthread_mutex_lock(&__mutex);
- iter = __pending_list;
- while (iter) {
- item = (struct pending_item_s *)iter->data;
- iter = g_list_next(iter);
- if (item->id == id) {
- pthread_mutex_unlock(&__mutex);
- return true;
- }
- }
- pthread_mutex_unlock(&__mutex);
-
- return false;
-}
-
-static int __pending_item_set_reply_info(int id, struct reply_info_s *info)
-{
- struct pending_item_s *item;
- GList *iter;
-
- pthread_mutex_lock(&__mutex);
- iter = __pending_list;
- while (iter) {
- item = (struct pending_item_s *)iter->data;
- iter = g_list_next(iter);
- if (item->id == id) {
- item->reply_info = info;
- pthread_mutex_unlock(&__mutex);
- return 0;
- }
- }
- pthread_mutex_unlock(&__mutex);
-
- return -1;
-}
-
-static int __pending_item_set_result_info(int id, struct result_info_s *info)
-{
- struct pending_item_s *item;
- GList *iter;
-
- pthread_mutex_lock(&__mutex);
- iter = __pending_list;
- while (iter) {
- item = (struct pending_item_s *)iter->data;
- iter = g_list_next(iter);
- if (item->id == id) {
- item->result_info = info;
- pthread_mutex_unlock(&__mutex);
- return 0;
- }
- }
- pthread_mutex_unlock(&__mutex);
-
- return -1;
-}
-
-static const char *app_control_error_to_string(app_control_error_e error)
-{
- switch (error) {
- case APP_CONTROL_ERROR_NONE:
- return "NONE";
- case APP_CONTROL_ERROR_INVALID_PARAMETER:
- return "INVALID_PARAMETER";
- case APP_CONTROL_ERROR_OUT_OF_MEMORY:
- return "OUT_OF_MEMORY";
- case APP_CONTROL_ERROR_APP_NOT_FOUND:
- return "APP_NOT_FOUND";
- case APP_CONTROL_ERROR_KEY_NOT_FOUND:
- return "KEY_NOT_FOUND";
- case APP_CONTROL_ERROR_KEY_REJECTED:
- return "KEY_REJECTED";
- case APP_CONTROL_ERROR_INVALID_DATA_TYPE:
- return "INVALID_DATA_TYPE";
- case APP_CONTROL_ERROR_LAUNCH_REJECTED:
- return "LAUNCH_REJECTED";
- case APP_CONTROL_ERROR_PERMISSION_DENIED:
- return "PERMISSION_DENIED";
- case APP_CONTROL_ERROR_LAUNCH_FAILED:
- return "LAUNCH_FAILED";
- case APP_CONTROL_ERROR_TIMED_OUT:
- return "TIMED_OUT";
- case APP_CONTROL_ERROR_IO_ERROR:
- return "IO ERROR";
- default:
- return "UNKNOWN";
- }
-}
-
-static int app_control_error(app_control_error_e error, const char *function, const char *description)
-{
- if (description)
- LOGE("[%s] %s(0x%08x) : %s", function, app_control_error_to_string(error), error, description);
- else {
- if (error == APP_CONTROL_ERROR_KEY_NOT_FOUND)
- LOGW("[%s] %s(0x%08x)", function, app_control_error_to_string(error), error);
- else
- LOGE("[%s] %s(0x%08x)", function, app_control_error_to_string(error), error);
- }
-
- return error;
-}
-
-static int app_control_validate_extra_data(const char *data)
-{
- if (data == NULL || data[0] == '\0')
- return APP_CONTROL_ERROR_INVALID_PARAMETER;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-static int app_control_validate(app_control_h app_control)
-{
- if (app_control == NULL || app_control->data == NULL)
- return APP_CONTROL_ERROR_INVALID_PARAMETER;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-static int app_control_new_id(void)
-{
- static int sid;
-
- g_atomic_int_inc(&sid);
- return sid;
-}
-
-int app_control_validate_internal_key(const char *key)
-{
- if (strncmp(BUNDLE_KEY_PREFIX_AUL, key, strlen(BUNDLE_KEY_PREFIX_AUL)) == 0)
- return -1;
-
- if (strncmp(BUNDLE_KEY_PREFIX_SERVICE, key, strlen(BUNDLE_KEY_PREFIX_SERVICE)) == 0)
- return -1;
-
- return 0;
-}
-
-static app_control_result_e __get_app_control_result(
- aul_svc_result_val appsvc_result)
-{
- app_control_result_e result;
-
- switch (appsvc_result) {
- case AUL_SVC_RES_OK:
- result = APP_CONTROL_RESULT_SUCCEEDED;
- break;
- case AUL_SVC_RES_NOT_OK:
- result = APP_CONTROL_RESULT_FAILED;
- break;
- case AUL_SVC_RES_CANCEL:
- result = APP_CONTROL_RESULT_CANCELED;
- break;
- default:
- result = APP_CONTROL_RESULT_CANCELED;
- break;
- }
-
- return result;
-}
-
-/* LCOV_EXCL_START */
-static void app_control_request_reply_broker(bundle *appsvc_bundle, int appsvc_request_code, aul_svc_result_val appsvc_result, void *appsvc_data)
-{
- app_control_request_context_h request_context;
- app_control_h request;
- app_control_h reply = NULL;
- app_control_result_e result;
- void *user_data;
- app_control_reply_cb reply_cb;
- struct reply_info_s *info;
- int ret;
-
- if (appsvc_data == NULL) {
- app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid app_control reply");
- return;
- }
-
- if (__exist_pending_item(appsvc_request_code)) {
- info = __create_reply_info(appsvc_bundle,
- appsvc_result, appsvc_data);
- if (info) {
- ret = __pending_item_set_reply_info(appsvc_request_code,
- info);
- if (ret == 0) {
- LOGW("Reply info is pending");
- return;
- }
- __destroy_reply_info(info);
- }
- }
-
- if (app_control_create_reply(appsvc_bundle, &reply) != 0) {
- app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create app_control reply");
- return;
- }
-
- request_context = appsvc_data;
- request = request_context->app_control;
- result = __get_app_control_result(appsvc_result);
-
- user_data = request_context->user_data;
- reply_cb = request_context->reply_cb;
-
- if (reply_cb != NULL) {
- reply_cb(request, reply, result, user_data);
- request_context->reply_cb = NULL;
- } else {
- app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid callback ");
- }
-
- app_control_destroy(reply);
-
- if (request_context->result_cb)
- return;
-
- if (request_context->app_control != NULL)
- app_control_destroy(request_context->app_control);
-
- free(request_context);
-}
-/* LCOV_EXCL_STOP */
-
-EXPORT_API int app_control_create_request(bundle *data, app_control_h *app_control)
-{
- struct app_control_s *app_control_request;
-
- if (app_control == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- app_control_request = malloc(sizeof(struct app_control_s));
- if (app_control_request == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a app_control handle");
-
- app_control_request->type = APP_CONTROL_TYPE_REQUEST;
-
- if (data != NULL)
- app_control_request->data = bundle_dup(data);
- else
- app_control_request->data = bundle_create();
-
- if (app_control_request->data == NULL) {
- free(app_control_request);
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a bundle");
- }
-
- app_control_request->id = app_control_new_id();
- app_control_request->launch_pid = -1;
-
- *app_control = app_control_request;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_create(app_control_h *app_control)
-{
- return app_control_create_request(NULL, app_control);
-}
-
-EXPORT_API int app_control_create_with_parameters(app_control_h *app_control,
- const char *operation, const char *uri, const char *mime,
- const char *category, const char *app_id,
- app_control_launch_mode_e mode, int extra_data_count, ...)
-{
- app_control_h tmp_control;
- int ret;
- va_list vl;
- char *val;
- char *key;
-
- if (app_control == NULL) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Invalid prameter");
- }
-
- ret = app_control_create_request(NULL, &tmp_control);
- if (ret != APP_CONTROL_ERROR_NONE)
- return ret;
-
- ret = app_control_set_operation(tmp_control, operation);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_set_uri(tmp_control, uri);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_set_mime(tmp_control, mime);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_set_category(tmp_control, category);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_set_app_id(tmp_control, app_id);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_set_launch_mode(tmp_control, mode);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- va_start(vl, extra_data_count);
- for (int i = 0; i < extra_data_count; i++) {
- key = va_arg(vl, char *);
- ret = app_control_validate_extra_data(key);
- if (ret != APP_CONTROL_ERROR_NONE) {
- va_end(vl);
- app_control_destroy(tmp_control);
- return ret;
- }
-
- val = va_arg(vl, char *);
- ret = app_control_validate_extra_data(val);
- if (ret != APP_CONTROL_ERROR_NONE) {
- va_end(vl);
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_add_extra_data(tmp_control, key, val);
- if (ret != APP_CONTROL_ERROR_NONE) {
- va_end(vl);
- app_control_destroy(tmp_control);
- return ret;
- }
- }
- va_end(vl);
- *app_control = tmp_control;
-
- return ret;
-}
-
-static bool uri_query_cb(const char *key, const char *val, void *user_data)
-{
- int ret;
-
- app_control_h *app_control = (app_control_h *)user_data;
-
- ret = app_control_add_extra_data(*app_control, key, val);
- if (ret != APP_CONTROL_ERROR_NONE) {
- LOGE("app_control_add_extra_data failed: %d[%s,%s]", ret, key, val);
- return false;
- }
-
- return true;
-}
-
-EXPORT_API int app_control_create_from_uri_handle(app_control_h *app_control,
- app_control_uri_h uri)
-{
- app_control_h tmp_control;
- const char *scheme;
- const char *auth;
- const char *path;
- const char *fragment;
- app_control_uri_query_h query;
- char *uri_str;
- int uri_str_len = 0;
- int ret;
-
- if (app_control == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- ret = app_control_create_request(NULL, &tmp_control);
- if (ret != APP_CONTROL_ERROR_NONE)
- return ret;
-
- ret = app_control_set_operation(tmp_control,
- APP_CONTROL_OPERATION_INTENT);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_uri_get_scheme(uri, &scheme);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_uri_get_authority(uri, &auth);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_uri_get_path(uri, &path);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_uri_get_fragment(uri, &fragment);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_add_extra_data(tmp_control,
- APP_CONTROL_DATA_URI_PATH, path);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_add_extra_data(tmp_control,
- APP_CONTROL_DATA_URI_FRAGMENT, fragment);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_uri_get_query(uri, &query);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- ret = app_control_uri_query_foreach(query, uri_query_cb,
- &tmp_control);
- if (ret != APP_CONTROL_ERROR_NONE) {
- app_control_destroy(tmp_control);
- return ret;
- }
-
- uri_str_len = strlen(scheme) + strlen(auth) + 2;
- uri_str = malloc(sizeof(char) * uri_str_len);
- if (uri_str == NULL) {
- app_control_destroy(tmp_control);
- free(uri_str);
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
- }
-
- snprintf(uri_str, uri_str_len, "%s:%s", scheme, auth);
- if (aul_svc_set_uri(tmp_control->data, uri_str) != 0) {
- app_control_destroy(tmp_control);
- free(uri_str);
- return app_control_error(APP_CONTROL_ERROR_IO_ERROR, __FUNCTION__, "invalid URI");
- }
-
- free(uri_str);
-
- *app_control = tmp_control;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_create_event(bundle *data, struct app_control_s **app_control)
-{
- struct app_control_s *app_control_event;
-
- const char *operation;
-
- if (data == NULL || app_control == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- app_control_event = malloc(sizeof(struct app_control_s));
- if (app_control_event == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a app_control handle");
-
- app_control_event->type = APP_CONTROL_TYPE_EVENT;
- app_control_event->data = bundle_dup(data);
- if (app_control_event->data == NULL) {
- free(app_control_event);
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to copy bundle data");
- }
-
- app_control_event->id = app_control_new_id();
- operation = aul_svc_get_operation(app_control_event->data);
- if (operation == NULL)
- aul_svc_set_operation(app_control_event->data, APP_CONTROL_OPERATION_DEFAULT);
-
- *app_control = app_control_event;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-/* LCOV_EXCL_START */
-static int app_control_create_reply(bundle *data, struct app_control_s **app_control)
-{
- struct app_control_s *app_control_reply;
-
- if (data == NULL || app_control == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- app_control_reply = malloc(sizeof(struct app_control_s));
- if (app_control_reply == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a app_control handle");
-
- app_control_reply->type = APP_CONTROL_TYPE_REPLY;
- app_control_reply->data = bundle_dup(data);
- app_control_reply->id = app_control_new_id();
-
- *app_control = app_control_reply;
-
- return APP_CONTROL_ERROR_NONE;
-}
-/* LCOV_EXCL_STOP */
-
-EXPORT_API int app_control_destroy(app_control_h app_control)
-{
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control->type == APP_CONTROL_TYPE_REQUEST && app_control->launch_pid > 0
- && bundle_get_val(app_control->data, AUL_SVC_K_LAUNCH_RESULT_APP_STARTED) == NULL)
- aul_remove_caller_cb(app_control->launch_pid, app_control);
-
- bundle_free(app_control->data);
- app_control->data = NULL;
- free(app_control);
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_to_bundle(app_control_h app_control, bundle **data)
-{
- if (app_control_validate(app_control) || data == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- *data = app_control->data;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_operation(app_control_h app_control, const char *operation)
-{
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (operation != NULL) {
- if (aul_svc_set_operation(app_control->data, operation) != 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid operation");
- } else {
- bundle_del(app_control->data, BUNDLE_KEY_OPERATION);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_operation(app_control_h app_control, char **operation)
-{
- const char *operation_value;
-
- if (app_control_validate(app_control) || operation == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- operation_value = aul_svc_get_operation(app_control->data);
- if (operation_value) {
- *operation = strdup(operation_value);
- if (*operation == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
- } else {
- *operation = NULL;
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_uri(app_control_h app_control, const char *uri)
-{
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (uri != NULL) {
- if (aul_svc_set_uri(app_control->data, uri) != 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid URI");
- } else {
- bundle_del(app_control->data, BUNDLE_KEY_URI);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_uri(app_control_h app_control, char **uri)
-{
- const char *uri_value;
-
- if (app_control_validate(app_control) || uri == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- uri_value = aul_svc_get_uri(app_control->data);
- if (uri_value) {
- *uri = strdup(uri_value);
- if (*uri == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
- } else {
- *uri = NULL;
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_uri_by_handle(app_control_h app_control, app_control_uri_h uri)
-{
- const char *scheme;
- const char *auth;
- char *uri_str;
- int uri_str_len = 0;
-
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control_uri_get_scheme(uri, &scheme))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control_uri_get_authority(uri, &auth))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- uri_str_len = strlen(scheme) + strlen(auth) + 2;
- uri_str = malloc(sizeof(char) * uri_str_len);
- if (uri_str == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
-
- snprintf(uri_str, uri_str_len, "%s:%s", scheme, auth);
- if (aul_svc_set_uri(app_control->data, uri_str) != 0) {
- free(uri_str);
- return app_control_error(APP_CONTROL_ERROR_IO_ERROR, __FUNCTION__, "invalid URI");
- }
-
- free(uri_str);
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_mime(app_control_h app_control, const char *mime)
-{
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (mime != NULL) {
- if (aul_svc_set_mime(app_control->data, mime) != 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid MIME type");
- } else {
- bundle_del(app_control->data, BUNDLE_KEY_MIME);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_mime(app_control_h app_control, char **mime)
-{
- const char *mime_value;
-
- if (app_control_validate(app_control) || mime == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- mime_value = aul_svc_get_mime(app_control->data);
- if (mime_value) {
- *mime = strdup(mime_value);
- if (*mime == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
- } else {
- *mime = NULL;
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_category(app_control_h app_control, const char *category)
-{
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (category != NULL) {
- if (aul_svc_set_category(app_control->data, category) != 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid Category");
- } else {
- bundle_del(app_control->data, BUNDLE_KEY_CATEGORY);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_category(app_control_h app_control, char **category)
-{
- const char *category_value;
-
- if (app_control_validate(app_control) || category == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- category_value = aul_svc_get_category(app_control->data);
- if (category_value) {
- *category = strdup(category_value);
- if (*category == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
- } else {
- *category = NULL;
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-int app_control_set_package(app_control_h app_control, const char *package)
-{
- /* TODO: this function must be deprecated */
- return app_control_set_app_id(app_control, package);
-}
-
-int app_control_get_package(app_control_h app_control, char **package)
-{
- /* TODO: this function must be deprecated */
- return app_control_get_app_id(app_control, package);
-}
-
-EXPORT_API int app_control_set_app_id(app_control_h app_control, const char *app_id)
-{
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_id != NULL) {
- if (aul_svc_set_appid(app_control->data, app_id) != 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid application ID");
- } else {
- bundle_del(app_control->data, BUNDLE_KEY_PACKAGE);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_app_id(app_control_h app_control, char **app_id)
-{
- const char *app_id_value;
-
- if (app_control_validate(app_control) || app_id == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- app_id_value = aul_svc_get_appid(app_control->data);
- if (app_id_value) {
- *app_id = strdup(app_id_value);
- if (*app_id == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
- } else {
- *app_id = NULL;
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_window(app_control_h app_control, unsigned int id)
-{
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (id > 0) {
- if (aul_svc_allow_transient_app(app_control->data, id) != 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid id");
- } else {
- bundle_del(app_control->data, BUNDLE_KEY_WINDOW);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_window(app_control_h app_control, unsigned int *id)
-{
- const char *window_id;
-
- if (app_control_validate(app_control) || id == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- window_id = bundle_get_val(app_control->data, BUNDLE_KEY_WINDOW);
- if (window_id != NULL)
- *id = atoi(window_id);
- else
- *id = 0;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_clone(app_control_h *clone, app_control_h app_control)
-{
- app_control_h app_control_clone;
-
- if (app_control_validate(app_control) || clone == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- app_control_clone = malloc(sizeof(struct app_control_s));
- if (app_control_clone == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a app_control handle");
-
- app_control_clone->id = app_control_new_id();
- app_control_clone->type = app_control->type;
- app_control_clone->data = bundle_dup(app_control->data);
- app_control_clone->launch_pid = app_control->launch_pid;
-
- *clone = app_control_clone;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_launch_mode(app_control_h app_control,
- app_control_launch_mode_e mode)
-{
- char launch_mode[LAUNCH_MODE_SIZE] = { 0, };
-
- if (app_control_validate(app_control)) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, NULL);
- }
-
- switch (mode) {
- case APP_CONTROL_LAUNCH_MODE_SINGLE:
- strncpy(launch_mode, LAUNCH_MODE_SINGLE, sizeof(launch_mode) - 1);
- break;
- case APP_CONTROL_LAUNCH_MODE_GROUP:
- strncpy(launch_mode, LAUNCH_MODE_GROUP, sizeof(launch_mode) - 1);
- break;
- default:
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "invalid mode");
- }
-
- return aul_svc_set_launch_mode(app_control->data, launch_mode);
-}
-
-EXPORT_API int app_control_get_launch_mode(app_control_h app_control,
- app_control_launch_mode_e *mode)
-{
- const char *launch_mode;
-
- if (app_control_validate(app_control)) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, NULL);
- }
-
- launch_mode = aul_svc_get_launch_mode(app_control->data);
- if (launch_mode == NULL) {
- *mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
- } else {
- if (!strcmp(launch_mode, LAUNCH_MODE_SINGLE)) {
- *mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
- } else if (!strcmp(launch_mode, LAUNCH_MODE_GROUP)) {
- *mode = APP_CONTROL_LAUNCH_MODE_GROUP;
- } else {
- *mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "launch_mode is not matched");
- }
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_defapp(app_control_h app_control, const char *app_id)
-{
- int ret;
-
- if (app_control_validate(app_control) || app_id == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- ret = aul_svc_set_appid(app_control->data, app_id);
- if (ret < 0)
- return app_control_error(APP_CONTROL_ERROR_IO_ERROR, __FUNCTION__, NULL);
-
- ret = aul_set_default_app_by_operation(app_control->data);
- if (ret < 0) {
- if (ret == AUL_R_EILLACC)
- return app_control_error(APP_CONTROL_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL);
- else
- return app_control_error(APP_CONTROL_ERROR_IO_ERROR, __FUNCTION__, NULL);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_unset_defapp(const char *app_id)
-{
- int ret;
-
- if (app_id == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- ret = aul_unset_default_app_by_operation(app_id);
- if (ret < 0) {
- if (ret == AUL_R_EILLACC)
- return app_control_error(APP_CONTROL_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL);
- else
- return app_control_error(APP_CONTROL_ERROR_IO_ERROR, __FUNCTION__, NULL);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-/* LCOV_EXCL_START */
-static void __update_launch_pid(int launched_pid, void *data)
-{
- app_control_h app_control;
-
- if (data == NULL)
- return;
-
- app_control = data;
-
- app_control->launch_pid = launched_pid;
-}
-/* LCOV_EXCL_STOP */
-
-static void __handle_launch_result(int launched_pid, void *data)
-{
- app_control_request_context_h request_context;
- app_control_h reply = NULL;
- app_control_h request;
- app_control_result_e result;
- app_control_reply_cb reply_cb;
- void *user_data;
- char callee[255] = {0, };
- int ret;
-
- if (data == NULL)
- return;
-
- request_context = (app_control_request_context_h)data;
-
- if (app_control_create_event(request_context->app_control->data, &reply) != 0) {
- app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create app_control event");
- return;
- }
-
- ret = aul_app_get_appid_bypid(launched_pid, callee, sizeof(callee));
- if (ret < 0)
- LOGE("aul_app_get_appid_bypid failed: %d", launched_pid);
- else
- app_control_set_app_id(reply, callee);
-
- LOGI("app control async result callback callee pid:%d", launched_pid);
-
- result = APP_CONTROL_RESULT_APP_STARTED;
- request = request_context->app_control;
- user_data = request_context->user_data;
- reply_cb = request_context->reply_cb;
-
- if (reply_cb != NULL)
- reply_cb(request, reply, result, user_data);
- else
- app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid callback ");
-
- app_control_destroy(reply);
-}
-
-static app_control_error_e __launch_request_convert_error(int res)
-{
- switch (res) {
- case AUL_SVC_RET_OK:
- return APP_CONTROL_ERROR_NONE;
- case AUL_SVC_RET_ENOMATCH:
- return APP_CONTROL_ERROR_APP_NOT_FOUND;
- case AUL_SVC_RET_EILLACC:
- return APP_CONTROL_ERROR_PERMISSION_DENIED;
- case AUL_SVC_RET_EINVAL:
- return APP_CONTROL_ERROR_INVALID_PARAMETER;
- default:
- return APP_CONTROL_ERROR_LAUNCH_REJECTED;
- }
-}
-
-static void __handle_app_started_result(app_control_h app_control,
- app_control_request_context_h request_context)
-{
- char callee[256] = { 0, };
- const char *str;
- int ret;
-
- str = bundle_get_val(app_control->data,
- AUL_SVC_K_LAUNCH_RESULT_APP_STARTED);
- if (!str) {
- aul_add_caller_cb(app_control->launch_pid,
- __update_launch_pid, app_control);
- return;
- }
-
- ret = aul_app_get_appid_bypid(app_control->launch_pid,
- callee, sizeof(callee));
- if (ret != AUL_R_OK) {
- LOGE("Failed to get appliation ID. pid(%d)",
- app_control->launch_pid);
- }
-
- if (request_context && request_context->app_control) {
- request_context->app_control->launch_pid =
- app_control->launch_pid;
- }
-
- aul_add_caller_cb(app_control->launch_pid,
- __handle_launch_result, request_context);
-
- if (strcmp(callee, APP_SELECTOR) &&
- strcmp(callee, SHARE_PANEL))
- aul_invoke_caller_cb(request_context);
-}
-
-static void app_control_request_result_broker(int request_code, int result,
- void *user_data)
-{
- app_control_request_context_h request_context;
- app_control_error_e error = APP_CONTROL_ERROR_NONE;
- app_control_h app_control;
- struct result_info_s *info;
- int ret;
-
- if (__exist_pending_item(request_code)) {
- info = __create_result_info(result, user_data);
- if (info) {
- ret = __pending_item_set_result_info(request_code,
- info);
- if (ret == 0) {
- LOGW("Result info is pending");
- return;
- }
- __destroy_result_info(info);
- }
- }
-
- request_context = (app_control_request_context_h)user_data;
- if (request_context == NULL) {
- LOGE("Invalid request");
- return;
- }
-
- app_control = request_context->app_control;
- app_control->launch_pid = result;
- if (request_context->result_cb) {
- if (result < 0)
- error = __launch_request_convert_error(result);
- request_context->result_cb(app_control, error,
- request_context->user_data);
- request_context->result_cb = NULL;
- }
-
- if (result < 0 || !request_context->reply_cb) {
- app_control_destroy(request_context->app_control);
- free(request_context);
- return;
- }
-
- __handle_app_started_result(app_control,
- request_context->reply_cb ? request_context : NULL);
-}
-
-static int __launch_request_verify_operation(struct launch_request_s *req)
-{
- app_control_h app_control = req->app_control;
- const char *operation;
- const char *appid;
-
- operation = aul_svc_get_operation(app_control->data);
- if (!operation) {
- req->implicit_default_operation = true;
- operation = APP_CONTROL_OPERATION_DEFAULT;
- }
-
- if (!strcmp(operation, APP_CONTROL_OPERATION_LAUNCH_ON_EVENT)) {
- return app_control_error(APP_CONTROL_ERROR_LAUNCH_REJECTED,
- __FUNCTION__, "Not supported operation value");
- }
-
- if (!strcmp(operation, APP_CONTROL_OPERATION_DEFAULT)) {
- appid = aul_svc_get_appid(app_control->data);
- if (!appid) {
- return app_control_error(APP_CONTROL_ERROR_APP_NOT_FOUND,
- __FUNCTION__,
- "Application ID must be specified");
- }
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-static int __launch_request_prepare_request_context(struct launch_request_s *req)
-{
- app_control_h app_control = req->app_control;
- app_control_h request_clone;
- int ret;
-
- if (!req->result_cb && !req->reply_cb)
- return APP_CONTROL_ERROR_NONE;
-
- req->request_context = calloc(1,
- sizeof(struct app_control_request_context_s));
- if (!req->request_context) {
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY,
- __FUNCTION__, "Ouf of memory");
- }
-
- ret = app_control_clone(&request_clone, app_control);
- if (ret != APP_CONTROL_ERROR_NONE) {
- return app_control_error(ret, __FUNCTION__,
- "Failed to duplicate app control handle");
- }
-
- req->request_context->app_control = request_clone;
- req->request_context->result_cb = req->result_cb;
- req->request_context->reply_cb = req->reply_cb;
- req->request_context->user_data = req->user_data;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-static int __launch_request_send(struct launch_request_s *req)
-{
- app_control_h app_control = req->app_control;
- aul_svc_res_fn reply_cb;
- aul_svc_err_cb result_cb;
- int ret;
-
- reply_cb = req->reply_cb ? app_control_request_reply_broker : NULL;
- result_cb = req->result_cb ? app_control_request_result_broker : NULL;
-
- if (req->implicit_default_operation) {
- aul_svc_set_operation(app_control->data,
- APP_CONTROL_OPERATION_DEFAULT);
- }
-
- if (req->request_context)
- __add_pending_item(req->id);
-
- if (req->result_cb) {
- ret = aul_svc_send_launch_request_for_uid(app_control->data,
- req->id, reply_cb, result_cb,
- req->request_context, getuid());
- } else {
- ret = aul_svc_run_service_for_uid(app_control->data,
- req->id, reply_cb,
- req->request_context, getuid());
- }
-
- if (req->implicit_default_operation)
- bundle_del(req->app_control->data, BUNDLE_KEY_OPERATION);
-
- if (ret < 0) {
- if (req->request_context)
- __remove_pending_item(req->id);
- return app_control_error(__launch_request_convert_error(ret),
- __FUNCTION__, NULL);
- }
-
- app_control->launch_pid = ret;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-static void __copy_callee_info(app_control_h dst, app_control_h src)
-{
- const char *id;
-
- if (!dst || !src)
- return;
-
- id = bundle_get_val(src->data, AUL_K_APPID);
- if (id) {
- bundle_del(dst->data, AUL_K_APPID);
- bundle_add(dst->data, AUL_K_APPID, id);
- }
-
- id = bundle_get_val(src->data, AUL_K_INSTANCE_ID);
- if (id) {
- bundle_del(dst->data, AUL_K_INSTANCE_ID);
- bundle_add(dst->data, AUL_K_INSTANCE_ID, id);
- }
-}
-
-static int __launch_request_complete(struct launch_request_s *req)
-{
- app_control_h app_control = req->app_control;
- app_control_request_context_h request_context = req->request_context;
-
- if (request_context)
- __copy_callee_info(request_context->app_control, app_control);
-
- if (req->result_cb) {
- __flush_pending_item(req->id);
- return APP_CONTROL_ERROR_NONE;
- }
-
- if (!request_context)
- return APP_CONTROL_ERROR_NONE;
-
- __handle_app_started_result(app_control,
- request_context->reply_cb ? request_context : NULL);
- __flush_pending_item(req->id);
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-static int __send_launch_request(app_control_h app_control,
- app_control_result_cb result_cb,
- app_control_reply_cb reply_cb,
- void *user_data)
-{
- static launch_request_handler handlers[] = {
- __launch_request_verify_operation,
- __launch_request_prepare_request_context,
- __launch_request_send,
- __launch_request_complete,
- };
- struct launch_request_s req = {
- .implicit_default_operation = false,
- .request_context = NULL,
- .app_control = app_control,
- .result_cb = result_cb,
- .reply_cb = reply_cb,
- .user_data = user_data,
- .reply = NULL,
- .result = APP_CONTROL_RESULT_FAILED,
- };
- int ret;
- int i;
-
- if (app_control_validate(app_control)) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, NULL);
- }
-
- req.id = __generate_request_id();
- for (i = 0; i < ARRAY_SIZE(handlers); i++) {
- if (handlers[i]) {
- ret = handlers[i](&req);
- if (ret != APP_CONTROL_ERROR_NONE)
- break;
- }
- }
-
- if (ret != APP_CONTROL_ERROR_NONE && req.request_context) {
- if (req.request_context->app_control)
- app_control_destroy(req.request_context->app_control);
-
- free(req.request_context);
- }
-
- return ret;
-}
-
-EXPORT_API int app_control_send_launch_request(app_control_h app_control,
- app_control_reply_cb callback, void *user_data)
-{
- int ret;
-
- ret = __send_launch_request(app_control, NULL, callback, user_data);
-
- return ret;
-}
-
-EXPORT_API int app_control_send_terminate_request(app_control_h app_control)
-{
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control->type != APP_CONTROL_TYPE_REQUEST || app_control->launch_pid < 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- aul_svc_subapp_terminate_request(app_control->data,
- app_control->launch_pid);
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-/* LCOV_EXCL_START */
-static bool app_control_copy_reply_data_cb(app_control_h app_control, const char *key, void *user_data)
-{
- bundle *reply_data = user_data;
- char *value = NULL;
- char **value_array = NULL;
- int value_array_length = 0;
- int value_array_index = 0;
-
- if (reply_data == NULL) {
- app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
- return false;
- }
-
- if (aul_svc_data_is_array(app_control->data, key)) {
- app_control_get_extra_data_array(app_control, key, &value_array, &value_array_length);
- aul_svc_add_data_array(reply_data, key, (const char **)value_array, value_array_length);
-
- for (value_array_index = 0; value_array_index < value_array_length; value_array_index++)
- free(value_array[value_array_index]);
-
- free(value_array);
- } else {
- app_control_get_extra_data(app_control, key, &value);
- aul_svc_add_data(reply_data, key, value);
- free(value);
- }
-
- return true;
-}
-/* LCOV_EXCL_STOP */
-
-EXPORT_API int app_control_reply_to_launch_request(app_control_h reply, app_control_h request, app_control_result_e result)
-{
- bundle *reply_data;
- int appsvc_result;
- int ret = 0;
-
- if (app_control_validate(reply) || app_control_validate(request))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (result == APP_CONTROL_RESULT_APP_STARTED)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "APP_CONTROL_RESULT_APP_STARTED is not allowed to use");
-
- ret = aul_svc_create_result_bundle(request->data, &reply_data);
- if (ret != 0) {
- if (ret == AUL_SVC_RET_ECANCELED)
- return APP_CONTROL_ERROR_NONE;
-
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create a result bundle");
- }
-
- app_control_foreach_extra_data(reply, app_control_copy_reply_data_cb, reply_data);
-
- switch (result) {
- case APP_CONTROL_RESULT_SUCCEEDED:
- appsvc_result = AUL_SVC_RES_OK;
- break;
- case APP_CONTROL_RESULT_FAILED:
- appsvc_result = AUL_SVC_RES_NOT_OK;
- break;
- case APP_CONTROL_RESULT_CANCELED:
- appsvc_result = AUL_SVC_RES_CANCEL;
- break;
- default:
- appsvc_result = AUL_SVC_RES_CANCEL;
- break;
- }
-
- ret = aul_svc_send_result(reply_data, appsvc_result);
- bundle_free(reply_data);
- if (ret < 0) {
- if (ret == AUL_SVC_RET_EINVAL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
- else
- return app_control_error(APP_CONTROL_ERROR_LAUNCH_REJECTED, __FUNCTION__, NULL);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_add_extra_data(app_control_h app_control, const char *key, const char *value)
-{
- if (app_control_validate(app_control) || app_control_validate_extra_data(key) || app_control_validate_extra_data(value))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control_validate_internal_key(key))
- return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
-
- if (aul_svc_get_data(app_control->data, key) != NULL) {
- /* overwrite any existing value */
- bundle_del(app_control->data, key);
- }
-
- if (aul_svc_add_data(app_control->data, key, value) != 0)
- return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "failed to add data to the appsvc handle");
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_add_extra_data_array(app_control_h app_control, const char *key, const char* value[], int length)
-{
- if (app_control_validate(app_control) || app_control_validate_extra_data(key))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (value == NULL || length <= 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid array");
-
- if (app_control_validate_internal_key(key))
- return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
-
- if (aul_svc_get_data_array(app_control->data, key, NULL) != NULL) {
- /* overwrite any existing value */
- bundle_del(app_control->data, key);
- }
-
- if (aul_svc_add_data_array(app_control->data, key, value, length) != 0)
- return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "failed to add array data to the appsvc handle");
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_remove_extra_data(app_control_h app_control, const char *key)
-{
- if (app_control_validate(app_control) || app_control_validate_extra_data(key))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control_validate_internal_key(key))
- return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
-
- if (bundle_del(app_control->data, key))
- return app_control_error(APP_CONTROL_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL);
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_extra_data(app_control_h app_control, const char *key, char **value)
-{
- const char *data_value;
-
- if (app_control_validate(app_control) || app_control_validate_extra_data(key) || value == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control_validate_internal_key(key))
- return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
-
- data_value = aul_svc_get_data(app_control->data, key);
- if (data_value == NULL) {
- if (errno == ENOTSUP)
- return app_control_error(APP_CONTROL_ERROR_INVALID_DATA_TYPE, __FUNCTION__, NULL);
- else
- return app_control_error(APP_CONTROL_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL);
- }
-
- *value = strdup(data_value);
- if (*value == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_extra_data_array(app_control_h app_control, const char *key, char ***value, int *length)
-{
- const char **array_data;
- int array_data_length;
- char **array_data_clone;
- int i;
-
- if (app_control_validate(app_control) || app_control_validate_extra_data(key))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (value == NULL || length == 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control_validate_internal_key(key))
- return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
-
- array_data = aul_svc_get_data_array(app_control->data, key, &array_data_length);
- if (array_data == NULL) {
- if (errno == ENOTSUP)
- return app_control_error(APP_CONTROL_ERROR_INVALID_DATA_TYPE, __FUNCTION__, NULL);
- else
- return app_control_error(APP_CONTROL_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL);
- }
-
- array_data_clone = calloc(array_data_length, sizeof(char *));
- if (array_data_clone == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
-
- for (i = 0; i < array_data_length; i++) {
- if (array_data[i] != NULL) {
- array_data_clone[i] = strdup(array_data[i]);
- if (array_data_clone[i] == NULL)
- goto error_oom;
- }
- }
-
- *value = array_data_clone;
- *length = array_data_length;
-
- return APP_CONTROL_ERROR_NONE;
-
-error_oom:
- for (i = 0; i < array_data_length; i++) {
- if (array_data_clone[i])
- free(array_data_clone[i]);
- }
- free(array_data_clone);
-
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
-}
-
-EXPORT_API int app_control_is_extra_data_array(app_control_h app_control, const char *key, bool *array)
-{
- if (app_control_validate(app_control) || app_control_validate_extra_data(key) || array == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control_validate_internal_key(key))
- return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
-
- if (!aul_svc_data_is_array(app_control->data, key))
- *array = false;
- else
- *array = true;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-typedef struct {
- app_control_h app_control;
- app_control_extra_data_cb callback;
- void *user_data;
- bool foreach_break;
-} foreach_context_extra_data_t;
-
-static void app_control_cb_broker_bundle_iterator(const char *key, const int type, const bundle_keyval_t *kv, void *user_data)
-{
- foreach_context_extra_data_t *foreach_context = NULL;
- app_control_extra_data_cb extra_data_cb;
-
- if (key == NULL || !(type == BUNDLE_TYPE_STR || type == BUNDLE_TYPE_STR_ARRAY))
- return;
-
- foreach_context = (foreach_context_extra_data_t *)user_data;
- if (foreach_context->foreach_break == true)
- return;
-
- if (app_control_validate_internal_key(key))
- return;
-
- extra_data_cb = foreach_context->callback;
-
- if (extra_data_cb != NULL) {
- bool stop_foreach = false;
-
- stop_foreach = !extra_data_cb(foreach_context->app_control, key, foreach_context->user_data);
-
- foreach_context->foreach_break = stop_foreach;
- }
-}
-
-EXPORT_API int app_control_foreach_extra_data(app_control_h app_control, app_control_extra_data_cb callback, void *user_data)
-{
- foreach_context_extra_data_t foreach_context = {
- .app_control = app_control,
- .callback = callback,
- .user_data = user_data,
- .foreach_break = false
- };
-
- if (app_control_validate(app_control) || callback == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- bundle_foreach(app_control->data, app_control_cb_broker_bundle_iterator, &foreach_context);
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-typedef struct {
- app_control_h app_control;
- app_control_app_matched_cb callback;
- void *user_data;
- bool foreach_break;
-} foreach_context_launchable_app_t;
-
-/* LCOV_EXCL_START */
-int app_control_cb_broker_foreach_app_matched(const char *package, void *data)
-{
- foreach_context_launchable_app_t *foreach_context;
- app_control_app_matched_cb app_matched_cb;
-
- if (package == NULL || data == NULL) {
- app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
- return -1;
- }
-
- foreach_context = (foreach_context_launchable_app_t *)data;
- if (foreach_context->foreach_break == true)
- return -1;
-
- app_matched_cb = foreach_context->callback;
- if (app_matched_cb != NULL) {
- bool stop_foreach = false;
-
- stop_foreach = !app_matched_cb(foreach_context->app_control, package, foreach_context->user_data);
-
- foreach_context->foreach_break = stop_foreach;
- }
-
- return 0;
-}
-/* LCOV_EXCL_STOP */
-
-EXPORT_API int app_control_foreach_app_matched(app_control_h app_control, app_control_app_matched_cb callback, void *user_data)
-{
- foreach_context_launchable_app_t foreach_context = {
- .app_control = app_control,
- .callback = callback,
- .user_data = user_data,
- .foreach_break = false
- };
-
- if (app_control_validate(app_control) || callback == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- aul_svc_get_list_for_uid(app_control->data, app_control_cb_broker_foreach_app_matched, &foreach_context, getuid());
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_caller(app_control_h app_control, char **package)
-{
- const char *bundle_value;
- char *package_dup;
-
- if (app_control_validate(app_control) || package == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control->type != APP_CONTROL_TYPE_EVENT)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid app_control handle type");
-
- bundle_value = bundle_get_val(app_control->data, AUL_K_CALLER_APPID);
- if (bundle_value == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to retrieve the appid of the caller");
-
- package_dup = strdup(bundle_value);
- if (package_dup == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
-
- *package = package_dup;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_is_reply_requested(app_control_h app_control, bool *requested)
-{
- const char *bundle_value;
-
- if (app_control_validate(app_control) || requested == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (app_control->type != APP_CONTROL_TYPE_EVENT)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid app_control handle type");
-
- bundle_value = bundle_get_val(app_control->data, AUL_K_WAIT_RESULT);
- if (bundle_value != NULL)
- *requested = true;
- else
- *requested = false;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_import_from_bundle(app_control_h app_control, bundle *data)
-{
- bundle *data_dup = NULL;
-
- if (app_control_validate(app_control) || data == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- data_dup = bundle_dup(data);
- if (data_dup == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to duplicate the bundle");
-
- if (app_control->data != NULL)
- bundle_free(app_control->data);
-
- app_control->data = data_dup;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_export_as_bundle(app_control_h app_control, bundle **data)
-{
- bundle *data_dup = NULL;
-
- if (app_control_validate(app_control) || data == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- data_dup = bundle_dup(app_control->data);
- if (data_dup == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to duplicate the bundle");
-
- *data = data_dup;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_request_transient_app(app_control_h app_control, unsigned int callee_id, app_control_host_res_fn cbfunc, void *data)
-{
- int ret;
-
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- ret = aul_svc_request_transient_app(app_control->data, callee_id, (aul_svc_host_res_fn)cbfunc, data);
- if (ret < 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_enable_app_started_result_event(app_control_h app_control)
-{
- int ret;
-
- if (app_control_validate(app_control))
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- ret = aul_svc_subscribe_launch_result(app_control->data, AUL_SVC_K_LAUNCH_RESULT_APP_STARTED);
- if (ret < 0)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_instance_id(app_control_h app_control, const char *instance_id)
-{
- int ret;
-
- if (app_control_validate(app_control) || instance_id == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- ret = aul_svc_set_instance_id(app_control->data, instance_id);
- if (ret < 0)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "Out of memory");
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_instance_id(app_control_h app_control, char **instance_id)
-{
- const char *id;
-
- if (app_control_validate(app_control) || instance_id == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- id = aul_svc_get_instance_id(app_control->data);
- if (id == NULL)
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "Failed to get the instance id");
-
- *instance_id = strdup(id);
- if (*instance_id == NULL)
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "Failed to duplicate the instance id");
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_send_launch_request_async(app_control_h app_control,
- app_control_result_cb result_cb,
- app_control_reply_cb reply_cb,
- void *user_data)
-{
- int ret;
-
- if (!app_control || !result_cb) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Invalid parameter");
- }
-
- ret = __send_launch_request(app_control, result_cb,
- reply_cb, user_data);
-
- return ret;
-}
-
-static int __launch_request_send_sync(struct launch_request_s *req)
-{
- app_control_h request = req->app_control;
- bundle *reply_bundle = NULL;
- aul_svc_result_val appsvc_result;
- int ret;
-
- if (req->implicit_default_operation) {
- aul_svc_set_operation(request->data,
- APP_CONTROL_OPERATION_DEFAULT);
- }
-
- ret = aul_svc_send_launch_request_sync_for_uid(request->data,
- req->id, &reply_bundle, &appsvc_result, getuid());
-
- if (req->implicit_default_operation)
- bundle_del(request->data, BUNDLE_KEY_OPERATION);
-
- if (ret < 0) {
- return app_control_error(__launch_request_convert_error(ret),
- __FUNCTION__, NULL);
- }
-
- request->launch_pid = ret;
-
- ret = app_control_create_reply(reply_bundle, &req->reply);
- bundle_free(reply_bundle);
- if (ret != 0) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Failed to create reply handle");
- }
-
- req->result = __get_app_control_result(appsvc_result);
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-static int __send_launch_request_sync(app_control_h request,
- app_control_h *reply, app_control_result_e *result)
-{
- static launch_request_handler handlers[] = {
- __launch_request_verify_operation,
- __launch_request_send_sync,
- };
- struct launch_request_s req = {
- .implicit_default_operation = false,
- .request_context = NULL,
- .app_control = request,
- .result_cb = NULL,
- .reply_cb = NULL,
- .user_data = NULL,
- .reply = NULL,
- .result = APP_CONTROL_RESULT_FAILED,
- };
- int ret;
- int i;
-
- if (app_control_validate(request)) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, NULL);
- }
-
- req.id = __generate_request_id();
- for (i = 0; i < ARRAY_SIZE(handlers); i++) {
- if (handlers[i]) {
- ret = handlers[i](&req);
- if (ret != APP_CONTROL_ERROR_NONE)
- break;
- }
- }
-
- if (ret == APP_CONTROL_ERROR_NONE) {
- if (reply) {
- *reply = req.reply;
- } else {
- app_control_destroy(req.reply);
- }
-
- if (result)
- *result = req.result;
- }
-
- return ret;
-}
-
-EXPORT_API int app_control_send_launch_request_sync(app_control_h app_control,
- app_control_h *reply, app_control_result_e *result)
-{
- if (!app_control || !reply || !result) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Invalid parameter");
- }
-
- return __send_launch_request_sync(app_control, reply, result);
-}
-
-static void __appcore_base_control_cb(bundle *b, void *user_data)
-{
- struct app_control_action_s *h;
- app_control_h app_control;
- int r;
-
- h = (struct app_control_action_s *)user_data;
- r = app_control_create_event(b, &app_control);
- if (r != APP_CONTROL_ERROR_NONE) {
- LOGE("Failed to create app-control handle");
- return;
- }
-
- h->callback(h->action, app_control, h->user_data);
- app_control_destroy(app_control);
-}
-
-EXPORT_API int app_control_add_action_handler(const char *action,
- app_control_action_cb callback, void *user_data,
- app_control_action_h *handle)
-{
- struct app_control_action_s *h;
- int r;
-
- if (!action || !callback || !handle) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Invalid parameter");
- }
-
- h = calloc(1, sizeof(struct app_control_action_s));
- if (!h) {
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY,
- __FUNCTION__, "Out of memory");
- }
-
- h->action = strdup(action);
- if (!h->action) {
- free(h);
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY,
- __FUNCTION__,
- "Failed to duplicate app-control action");
- }
-
- r = appcore_base_control_add(h->action, __appcore_base_control_cb, h,
- &h->handle);
- if (r != APPCORE_BASE_ERROR_NONE) {
- free(h->action);
- free(h);
- switch (r) {
- case APPCORE_BASE_ERROR_INVALID_PARAMETER:
- return app_control_error(
- APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__,
- "Invalid parameter");
- case APPCORE_BASE_ERROR_KEY_NOT_FOUND:
- return app_control_error(
- APP_CONTROL_ERROR_KEY_NOT_FOUND,
- __FUNCTION__,
- "AppControl ID is not found");
- case APPCORE_BASE_ERROR_IO_ERROR:
- return app_control_error(
- APP_CONTROL_ERROR_IO_ERROR,
- __FUNCTION__,
- "IO error");
- default:
- return app_control_error(
- APP_CONTROL_ERROR_OUT_OF_MEMORY,
- __FUNCTION__,
- "Out of memory");
- }
- }
-
- h->callback = callback;
- h->user_data = user_data;
-
- *handle = h;
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_remove_action_handler(app_control_action_h handle)
-{
- if (!handle) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Invalid parameter");
- }
-
- if (handle->handle)
- appcore_base_control_remove(handle->handle);
-
- if (handle->action)
- free(handle->action);
-
- free(handle);
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_caller_instance_id(app_control_h app_control,
- const char *instance_id)
-{
- int r;
-
- if (app_control_validate(app_control)) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Invalid parameter");
- }
-
- if (instance_id != NULL) {
- r = aul_svc_set_caller_instance_id(app_control->data,
- instance_id);
- if (r != AUL_SVC_RET_OK) {
- return app_control_error(
- APP_CONTROL_ERROR_OUT_OF_MEMORY,
- __FUNCTION__, "Out of memory");
- }
- } else {
- aul_svc_set_caller_instance_id(app_control->data, instance_id);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_set_component_id(app_control_h app_control,
- const char *component_id)
-{
- int r;
-
- if (app_control_validate(app_control)) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Invalid parameter");
- }
-
- r = aul_svc_set_comp_id(app_control->data, component_id);
- if (r != AUL_SVC_RET_OK && component_id != NULL) {
- return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY,
- __FUNCTION__, "Out of memory");
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-EXPORT_API int app_control_get_component_id(app_control_h app_control,
- char **component_id)
-{
- const char *comp_id;
-
- if (app_control_validate(app_control) || !component_id) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Invalid parameter");
- }
-
- comp_id = aul_svc_get_comp_id(app_control->data);
- if (comp_id) {
- *component_id = strdup(comp_id);
- if (*component_id == NULL) {
- return app_control_error(
- APP_CONTROL_ERROR_OUT_OF_MEMORY,
- __FUNCTION__, "Out of memory");
- }
- } else {
- *component_id = NULL;
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-static int __resume_request_verify_appid(struct launch_request_s *req)
-{
- app_control_h app_control = req->app_control;
- const char *appid;
-
- appid = aul_svc_get_appid(app_control->data);
- if (!appid) {
- return app_control_error(APP_CONTROL_ERROR_APP_NOT_FOUND,
- __FUNCTION__,
- "Application ID must be specified");
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-static int __resume_request_send(struct launch_request_s *req)
-{
- app_control_h app_control = req->app_control;
- aul_svc_err_cb result_cb = app_control_request_result_broker;
- int ret;
-
- __add_pending_item(req->id);
-
- ret = aul_svc_send_resume_request_for_uid(app_control->data,
- req->id, result_cb, req->request_context, getuid());
-
- if (ret < 0) {
- __remove_pending_item(req->id);
- return app_control_error(__launch_request_convert_error(ret),
- __FUNCTION__, NULL);
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
-
-static int __send_resume_request(app_control_h app_control,
- app_control_result_cb result_cb,
- void *user_data)
-{
- static launch_request_handler handlers[] = {
- __resume_request_verify_appid,
- __launch_request_prepare_request_context,
- __resume_request_send,
- __launch_request_complete,
- };
- struct launch_request_s req = {
- .implicit_default_operation = false,
- .request_context = NULL,
- .app_control = app_control,
- .result_cb = result_cb,
- .reply_cb = NULL,
- .user_data = user_data,
- .reply = NULL,
- .result = APP_CONTROL_RESULT_FAILED,
- };
- int ret;
- int i;
-
- if (app_control_validate(app_control)) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, NULL);
- }
-
- req.id = __generate_request_id();
- for (i =0; i < ARRAY_SIZE(handlers); i++) {
- if (handlers[i]) {
- ret = handlers[i](&req);
- if (ret != APP_CONTROL_ERROR_NONE)
- break;
- }
- }
-
- if (ret != APP_CONTROL_ERROR_NONE && req.request_context) {
- if (req.request_context->app_control)
- app_control_destroy(req.request_context->app_control);
-
- free(req.request_context);
- }
-
- return ret;
-}
-
-EXPORT_API int app_control_send_resume_request(app_control_h app_control,
- app_control_result_cb result_cb,
- void *user_data)
-{
- if (!app_control || !result_cb) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Invalid parameter");
- }
-
- return __send_resume_request(app_control, result_cb, user_data);
-}
-
-static int __convert_aul_error(int result)
-{
- switch (result) {
- case AUL_R_EINVAL:
- return APP_CONTROL_ERROR_INVALID_PARAMETER;
- case AUL_R_ENOMEM:
- return APP_CONTROL_ERROR_OUT_OF_MEMORY;
- case AUL_R_EILLACC:
- return APP_CONTROL_ERROR_PERMISSION_DENIED;
- default:
- return APP_CONTROL_ERROR_IO_ERROR;
- }
-}
-
-EXPORT_API int app_control_prepare_app_defined_loader(app_control_h app_control,
- const char *loader_id)
-{
- const char *loader_name = loader_id; /* for readability */
- int ret;
-
- if (!app_control || !loader_name) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Inivalid parameter");
- }
-
- if (app_control_validate(app_control)) {
- return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER,
- __FUNCTION__, "Invalid parameter");
- }
-
- ret = aul_prepare_app_defined_loader(loader_name);
- if (ret < 0) {
- return app_control_error(__convert_aul_error(ret),
- __FUNCTION__,
- "Failed to prepare app defined loader");
- }
-
- bundle_del(app_control->data, AUL_K_APP_DEFINED_LOADER);
- bundle_add(app_control->data, AUL_K_APP_DEFINED_LOADER, loader_name);
-
- ret = aul_svc_set_loader_id(app_control->data, ret);
- if (ret < 0) {
- if (ret == AUL_SVC_RET_EINVAL)
- ret = APP_CONTROL_ERROR_INVALID_PARAMETER;
- else
- ret = APP_CONTROL_ERROR_OUT_OF_MEMORY;
-
- return app_control_error(ret, __FUNCTION__,
- "Failed to set loader id");
- }
-
- return APP_CONTROL_ERROR_NONE;
-}
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 <aul.h>
+#include <aul_svc.h>
+#include <aul_svc_internal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "app-control/app_control.hh"
+#include "app-control/app_control_broker.hh"
+#include "app-control/exception.hh"
+#include "app-control/log_private.hh"
+#include "app-control/util.hh"
+
+namespace app_control {
+namespace {
+
+const char kBundlePrefixAul[] = "__AUL_";
+const char kBundlePrefixService[] = "__APP_SVC_";
+const char kBundlePkgName[] = "__APP_SVC_PKG_NAME__";
+
+} // namespace
+
+AppControl::AppControl(Type type) : type_(type) {
+}
+
+AppControl::AppControl(tizen_base::Bundle data, Type type)
+ : data_(std::move(data)), type_(type) {
+}
+
+AppControl::~AppControl() {
+ if (data_.GetType(AUL_SVC_K_LAUNCH_RESULT_APP_STARTED) != BUNDLE_TYPE_NONE) {
+ if (type_ == Type::Request && launched_pid_ > 0)
+ aul_remove_caller_cb(launched_pid_, this);
+ }
+}
+
+AppControl::AppControl(const AppControl& app_control) {
+ data_ = app_control.data_;
+ type_ = app_control.type_;
+ launched_pid_ = app_control.launched_pid_;
+}
+
+AppControl& AppControl::operator = (const AppControl& app_control) {
+ if (this != &app_control) {
+ data_ = app_control.data_;
+ type_ = app_control.type_;
+ launched_pid_ = app_control.launched_pid_;
+ }
+
+ return *this;
+}
+
+AppControl::AppControl(AppControl&& app_control) noexcept {
+ data_ = std::move(app_control.data_);
+
+ type_ = app_control.type_;
+ app_control.type_ = Type::None;
+
+ launched_pid_ = app_control.launched_pid_;
+ app_control.launched_pid_ = -1;
+}
+
+AppControl& AppControl::operator = (AppControl&& app_control) noexcept {
+ if (this != &app_control) {
+ data_ = std::move(app_control.data_);
+
+ type_ = app_control.type_;
+ app_control.type_ = Type::None;
+
+ launched_pid_ = app_control.launched_pid_;
+ app_control.launched_pid_ = -1;
+ }
+
+ return *this;
+}
+
+void AppControl::SetOperation(const std::string& operation) {
+ int ret = aul_svc_set_operation(data_.GetHandle(), operation.c_str());
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::SetUri(const std::string& uri) {
+ int ret = aul_svc_set_uri(data_.GetHandle(), uri.c_str());
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::SetMime(const std::string& mime) {
+ int ret = aul_svc_set_mime(data_.GetHandle(), mime.c_str());
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::SetCategory(const std::string& category) {
+ int ret = aul_svc_set_category(data_.GetHandle(), category.c_str());
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::SetAppId(const std::string& app_id) {
+ int ret = aul_svc_set_appid(data_.GetHandle(), app_id.c_str());
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::SetComponentId(const std::string& component_id) {
+ int ret = aul_svc_set_comp_id(data_.GetHandle(), component_id.c_str());
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::SetLaunchMode(LaunchMode launch_mode) {
+ if (launch_mode != LaunchMode::Single && launch_mode != LaunchMode::Group)
+ THROW(Error::InvalidParameter);
+
+ int ret = aul_svc_set_launch_mode(data_.GetHandle(),
+ launch_mode == LaunchMode::Group ? "group" : "single");
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::SetInstanceId(const std::string& instance_id) {
+ int ret = aul_svc_set_instance_id(data_.GetHandle(), instance_id.c_str());
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::SetCallerInstanceId(const std::string& instance_id) {
+ int ret = aul_svc_set_caller_instance_id(data_.GetHandle(),
+ instance_id.c_str());
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::SetLoaderId(int loader_id) {
+ int ret = aul_svc_set_loader_id(data_.GetHandle(), loader_id);
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::SetAppDefinedLoader(const std::string& loader_name) {
+ data_.Delete(AUL_K_APP_DEFINED_LOADER);
+ data_.Add(AUL_K_APP_DEFINED_LOADER, loader_name);
+}
+
+std::string AppControl::GetOperation() const {
+ const char* operation = aul_svc_get_operation(data_.GetHandle());
+ if (operation == nullptr)
+ THROW(static_cast<int>(Error::KeyNotFound));
+
+ return std::string(operation);
+}
+
+std::string AppControl::GetUri() const {
+ const char* uri = aul_svc_get_uri(data_.GetHandle());
+ if (uri == nullptr)
+ THROW(static_cast<int>(Error::KeyNotFound));
+
+ return std::string(uri);
+}
+
+std::string AppControl::GetMime() const {
+ const char* mime = aul_svc_get_mime(data_.GetHandle());
+ if (mime == nullptr)
+ THROW(static_cast<int>(Error::KeyNotFound));
+
+ return std::string(mime);
+}
+
+std::string AppControl::GetCategory() const {
+ const char* category = aul_svc_get_category(data_.GetHandle());
+ if (category == nullptr)
+ THROW(static_cast<int>(Error::KeyNotFound));
+
+ return std::string(category);
+}
+
+std::string AppControl::GetAppId() const {
+ const char* app_id = aul_svc_get_appid(data_.GetHandle());
+ if (app_id == nullptr)
+ THROW(static_cast<int>(Error::KeyNotFound));
+
+ return std::string(app_id);
+}
+
+std::string AppControl::GetCaller() const {
+ if (type_ != Type::Event)
+ THROW(static_cast<int>(Error::InvalidParameter));
+
+ std::string caller = data_.GetString(AUL_K_CALLER_APPID);
+ if (caller.empty())
+ THROW(static_cast<int>(Error::KeyNotFound));
+
+ return caller;
+}
+
+std::string AppControl::GetComponentId() const {
+ const char* component_id = aul_svc_get_comp_id(data_.GetHandle());
+ if (component_id == nullptr)
+ THROW(static_cast<int>(Error::KeyNotFound));
+
+ return std::string(component_id);
+}
+
+std::string AppControl::GetInstanceId() const {
+ const char* instance_id = aul_svc_get_instance_id(data_.GetHandle());
+ if (instance_id == nullptr)
+ THROW(static_cast<int>(Error::KeyNotFound));
+
+ return std::string(instance_id);
+}
+
+LaunchMode AppControl::GetLaunchMode() const {
+ const char* launch_mode = aul_svc_get_launch_mode(data_.GetHandle());
+ if (launch_mode == nullptr)
+ return LaunchMode::Single;
+
+ if (!strcmp(launch_mode, "group"))
+ return LaunchMode::Group;
+ else if (!strcmp(launch_mode, "single"))
+ return LaunchMode::Single;
+ else
+ THROW(static_cast<int>(Error::InvalidParameter));
+}
+
+void AppControl::RemoveOperation() {
+ aul_svc_set_operation(data_.GetHandle(), nullptr);
+}
+
+void AppControl::RemoveUri() {
+ aul_svc_set_uri(data_.GetHandle(), nullptr);
+}
+
+void AppControl::RemoveMime() {
+ aul_svc_set_mime(data_.GetHandle(), nullptr);
+}
+
+void AppControl::RemoveCategory() {
+ aul_svc_set_category(data_.GetHandle(), nullptr);
+}
+
+void AppControl::RemoveAppId() {
+ data_.Delete(kBundlePkgName);
+}
+
+void AppControl::RemoveComponentId() {
+ aul_svc_set_comp_id(data_.GetHandle(), nullptr);
+}
+
+void AppControl::RemoveInstanceId() {
+ aul_svc_set_instance_id(data_.GetHandle(), nullptr);
+}
+
+void AppControl::RemoveCallerInstanceId() {
+ aul_svc_set_caller_instance_id(data_.GetHandle(), nullptr);
+}
+
+void AppControl::AddExtraData(const std::string& key,
+ const std::string& value) {
+ if (key.empty() || value.empty())
+ THROW(static_cast<int>(Error::InvalidParameter));
+
+ if (!ValidateInternalKey(key))
+ THROW(static_cast<int>(Error::KeyRejected));
+
+ int ret = aul_svc_add_data(data_.GetHandle(), key.c_str(), value.c_str());
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::AddExtraDataArray(const std::string& key,
+ const std::vector<std::string>& value) {
+ if (key.empty() || value.size() == 0)
+ THROW(static_cast<int>(Error::InvalidParameter));
+
+ if (!ValidateInternalKey(key))
+ THROW(static_cast<int>(Error::KeyRejected));
+
+ std::vector<const char*> value_array;
+ int value_size = value.size();
+ for (auto i = 0; i < value_size; ++i)
+ value_array.push_back(value[i].c_str());
+
+ int ret = aul_svc_add_data_array(data_.GetHandle(), key.c_str(),
+ value_array.data(), value_array.size());
+ if (ret != AUL_SVC_RET_OK)
+ THROW(Util::AulSvcErrorConvert(ret));
+}
+
+void AppControl::RemoveExtraData(const std::string& key) {
+ if (key.empty())
+ THROW(static_cast<int>(Error::InvalidParameter));
+
+ if (!ValidateInternalKey(key))
+ THROW(static_cast<int>(Error::KeyRejected));
+
+ if (data_.Delete(key) != BUNDLE_ERROR_NONE)
+ THROW(static_cast<int>(Error::KeyNotFound));
+}
+
+std::string AppControl::GetExtraData(const std::string& key) const {
+ if (key.empty())
+ THROW(static_cast<int>(Error::InvalidParameter));
+
+ if (!ValidateInternalKey(key))
+ THROW(static_cast<int>(Error::KeyRejected));
+
+ const char* value = aul_svc_get_data(data_.GetHandle(), key.c_str());
+ if (value == nullptr) {
+ if (get_last_result() == BUNDLE_ERROR_KEY_NOT_AVAILABLE)
+ THROW(static_cast<int>(Error::KeyNotFound));
+ else
+ THROW(static_cast<int>(Error::InvalidDataType));
+ }
+
+ return std::string(value);
+}
+
+std::vector<std::string> AppControl::GetExtraDataArray(
+ const std::string& key) const {
+ if (key.empty())
+ THROW(static_cast<int>(Error::InvalidParameter));
+
+ if (!ValidateInternalKey(key))
+ THROW(static_cast<int>(Error::KeyRejected));
+
+ int len = 0;
+ const char** value_array = aul_svc_get_data_array(data_.GetHandle(),
+ key.c_str(), &len);
+ if (value_array == nullptr) {
+ if (get_last_result() == BUNDLE_ERROR_KEY_NOT_AVAILABLE)
+ THROW(static_cast<int>(Error::KeyNotFound));
+ else
+ THROW(static_cast<int>(Error::InvalidDataType));
+ }
+
+ std::vector<std::string> v;
+ for (int i = 0; i < len; ++i)
+ v.emplace_back(value_array[i]);
+
+ return v;
+}
+
+bool AppControl::IsExtraDataArray(const std::string& key) const {
+ if (key.empty())
+ THROW(static_cast<int>(Error::InvalidParameter));
+
+ if (!ValidateInternalKey(key))
+ THROW(static_cast<int>(Error::KeyRejected));
+
+ if (aul_svc_data_is_array(data_.GetHandle(), key.c_str()))
+ return true;
+
+ return false;
+}
+
+std::vector<std::string> AppControl::GetExtraDataKeys() {
+ std::vector<std::string> keys;
+ for (auto& key_info : data_.GetKeys()) {
+ if (!ValidateInternalKey(key_info.GetName()))
+ continue;
+
+ keys.emplace_back(key_info.GetName());
+ }
+
+ return keys;
+}
+
+std::vector<std::string> AppControl::GetMatchedAppIds() {
+ char** appid_array = nullptr;
+ unsigned int len = 0;
+ int ret = aul_svc_get_appid_array(data_.GetHandle(), getuid(),
+ &appid_array, &len);
+ if (ret != AUL_SVC_RET_OK)
+ return {};
+
+ std::vector<std::string> app_ids;
+ for (unsigned int i = 0; i < len; ++i)
+ app_ids.push_back(appid_array[i]);
+
+ aul_svc_free_appid_array(appid_array, len);
+ return app_ids;
+}
+
+bool AppControl::IsReplyRequested() const {
+ if (type_ != Type::Event)
+ THROW(static_cast<int>(Error::InvalidParameter));
+
+ if (data_.GetType(AUL_K_WAIT_RESULT) != BUNDLE_TYPE_NONE)
+ return true;
+
+ return false;
+}
+
+void AppControl::EnableAppStartedResultEvent() {
+ int ret = aul_svc_subscribe_launch_result(data_.GetHandle(),
+ AUL_SVC_K_LAUNCH_RESULT_APP_STARTED);
+ if (ret != AUL_SVC_RET_OK)
+ THROW(static_cast<int>(Error::InvalidParameter));
+}
+
+bool AppControl::HasAppStartedResultEvent() const {
+ bundle_type type = data_.GetType(AUL_SVC_K_LAUNCH_RESULT_APP_STARTED);
+ if (type != BUNDLE_TYPE_NONE)
+ return true;
+
+ return false;
+}
+
+void AppControl::SetLaunchedPid(int launched_pid) {
+ launched_pid_ = launched_pid;
+}
+
+int AppControl::GetLaunchedPid() const {
+ return launched_pid_;
+}
+
+AppControl::Type AppControl::GetType() const {
+ return type_;
+}
+
+void AppControl::SetBundle(tizen_base::Bundle data) {
+ data_ = std::move(data);
+}
+
+bundle* AppControl::ToBundle() const {
+ return data_.GetHandle();
+}
+
+bool AppControl::ValidateInternalKey(const std::string& key) {
+ if (key.compare(0, strlen(kBundlePrefixAul),
+ kBundlePrefixAul) == 0)
+ return false;
+
+ if (key.compare(0, strlen(kBundlePrefixService),
+ kBundlePrefixService) == 0)
+ return false;
+
+ return true;
+}
+
+} // namespace app_control
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_APP_CONTROL_HH_
+#define APP_CONTROL_APP_CONTROL_HH_
+
+#include <bundle_cpp.h>
+
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include "app-control/error.hh"
+#include "app-control/launch_mode.hh"
+#include "app-control/result.hh"
+
+namespace app_control {
+
+class AppControl {
+ public:
+ enum Type {
+ None,
+ Request,
+ Event,
+ Reply,
+ };
+
+ AppControl(Type type = Type::Request);
+ AppControl(tizen_base::Bundle data, Type type = Type::Request);
+ virtual ~AppControl();
+
+ AppControl(const AppControl& app_control);
+ AppControl& operator = (const AppControl& app_control);
+
+ AppControl(AppControl&& app_control) noexcept;
+ AppControl& operator = (AppControl&& app_control) noexcept;
+
+ void SetOperation(const std::string& operation);
+ void SetUri(const std::string& uri);
+ void SetMime(const std::string& mime);
+ void SetCategory(const std::string& category);
+ void SetAppId(const std::string& app_id);
+ void SetComponentId(const std::string& component_id);
+ void SetLaunchMode(LaunchMode launch_mode);
+ void SetInstanceId(const std::string& instance_id);
+ void SetCallerInstanceId(const std::string& instance_id);
+ void SetLoaderId(int loader_id);
+ void SetAppDefinedLoader(const std::string& loader_name);
+
+ std::string GetOperation() const;
+ std::string GetUri() const;
+ std::string GetMime() const;
+ std::string GetCategory() const;
+ std::string GetAppId() const;
+ std::string GetCaller() const;
+ std::string GetComponentId() const;
+ std::string GetInstanceId() const;
+ LaunchMode GetLaunchMode() const;
+
+ void RemoveOperation();
+ void RemoveUri();
+ void RemoveMime();
+ void RemoveCategory();
+ void RemoveAppId();
+ void RemoveComponentId();
+ void RemoveInstanceId();
+ void RemoveCallerInstanceId();
+
+ void AddExtraData(const std::string& key, const std::string& value);
+ void AddExtraDataArray(const std::string& key,
+ const std::vector<std::string>& value);
+ void RemoveExtraData(const std::string& key);
+ std::string GetExtraData(const std::string& key) const;
+ std::vector<std::string> GetExtraDataArray(const std::string& key) const;
+ bool IsExtraDataArray(const std::string& key) const;
+ std::vector<std::string> GetExtraDataKeys();
+ std::vector<std::string> GetMatchedAppIds();
+
+ bool IsReplyRequested() const;
+ void EnableAppStartedResultEvent();
+ bool HasAppStartedResultEvent() const;
+
+ void SetLaunchedPid(int pid);
+ int GetLaunchedPid() const;
+
+ Type GetType() const;
+
+ void SetBundle(tizen_base::Bundle data);
+ bundle* ToBundle() const;
+
+ private:
+ static bool ValidateInternalKey(const std::string& key);
+
+ private:
+ tizen_base::Bundle data_;
+ Type type_;
+ int launched_pid_ = -1;
+};
+
+} // namespace app_control
+
+#endif // APP_CONTROL_APP_CONTROL_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 "app-control/app_control_action.hh"
+#include "app-control/error.hh"
+#include "app-control/exception.hh"
+#include "app-control/log_private.hh"
+
+namespace app_control {
+
+AppControlAction::AppControlAction(std::string action, IEvent* listener)
+ : action_(std::move(action)), listener_(listener) {
+ int ret = appcore_base_control_add(action_.c_str(),
+ AppcoreBaseControlCb, this, &handle_);
+ if (ret != APPCORE_BASE_ERROR_NONE)
+ THROW(AppcoreBaseErrorConvert(ret));
+}
+
+AppControlAction::~AppControlAction() {
+ if (handle_ != nullptr)
+ appcore_base_control_remove(handle_);
+}
+
+const std::string& AppControlAction::GetAction() const {
+ return action_;
+}
+
+void AppControlAction::AppcoreBaseControlCb(bundle* b, void* user_data) {
+ auto* handle = static_cast<AppControlAction*>(user_data);
+ auto* listener = handle->listener_;
+ listener->OnAction(handle->action_, b);
+}
+
+int AppControlAction::AppcoreBaseErrorConvert(int ret) {
+ switch (ret) {
+ case APPCORE_BASE_ERROR_INVALID_PARAMETER:
+ return static_cast<int>(Error::InvalidParameter);
+ case APPCORE_BASE_ERROR_KEY_NOT_FOUND:
+ return static_cast<int>(Error::KeyNotFound);
+ case APPCORE_BASE_ERROR_IO_ERROR:
+ return static_cast<int>(Error::IOError);
+ default:
+ return static_cast<int>(Error::OutOfMemory);
+ }
+}
+
+} // namespace app_control
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_APP_CONTROL_ACTION_HH_
+#define APP_CONTROL_APP_CONTROL_ACTION_HH_
+
+#include <appcore_base_control.h>
+
+#include <string>
+
+namespace app_control {
+
+class AppControlAction {
+ public:
+ class IEvent {
+ public:
+ virtual void OnAction(const std::string& action, bundle* data) = 0;
+ };
+
+ AppControlAction(std::string action, IEvent* listener);
+ virtual ~AppControlAction();
+
+ const std::string& GetAction() const;
+
+ private:
+ static void AppcoreBaseControlCb(bundle* b, void* user_data);
+ static int AppcoreBaseErrorConvert(int ret);
+
+ private:
+ std::string action_;
+ IEvent* listener_;
+ appcore_base_control_h handle_ = nullptr;
+};
+
+} // namespace app_control
+
+#endif // APP_CONTROL_APP_CONTROL_ACTION_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 <bundle_cpp.h>
+#include <glib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "app-control/app_control_broker.hh"
+#include "app-control/exception.hh"
+#include "app-control/util.hh"
+
+namespace app_control {
+
+std::atomic<AppControlBroker*> AppControlBroker::inst_;
+std::mutex AppControlBroker::mutex_;
+
+AppControlBroker* AppControlBroker::GetInst() {
+ AppControlBroker* inst = inst_.load(std::memory_order_acquire);
+ if (inst == nullptr) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ inst = inst_.load(std::memory_order_relaxed);
+ if (inst == nullptr) {
+ inst = new AppControlBroker();
+ inst_.store(inst, std::memory_order_release);
+ }
+ }
+
+ return inst;
+}
+
+void AppControlBroker::AddRequestContext(
+ std::shared_ptr<RequestContext> request_context) {
+ std::lock_guard<std::recursive_mutex> lock(GetRecMutex());
+ contexts_[request_context->GetRequestId()] = request_context;
+}
+
+void AppControlBroker::RemoveRequestContext(int id) {
+ std::lock_guard<std::recursive_mutex> lock(GetRecMutex());
+ auto found = contexts_.find(id);
+ if (found == contexts_.end())
+ return;
+
+ contexts_.erase(found);
+}
+
+std::shared_ptr<RequestContext> AppControlBroker::FindRequestContext(int id) {
+ std::lock_guard<std::recursive_mutex> lock(GetRecMutex());
+ auto found = contexts_.find(id);
+ if (found == contexts_.end())
+ return nullptr;
+
+ return found->second;
+}
+
+void AppControlBroker::PushPendingItem(std::shared_ptr<PendingItem> item) {
+ std::lock_guard<std::recursive_mutex> lock(GetRecMutex());
+ items_[item->GetId()] = item;
+}
+
+std::shared_ptr<PendingItem> AppControlBroker::PopPendingItem(int id) {
+ std::lock_guard<std::recursive_mutex> lock(GetRecMutex());
+ auto found = items_.find(id);
+ if (found == items_.end())
+ return nullptr;
+
+ auto item = found->second;
+ items_.erase(found);
+ return item;
+}
+
+std::shared_ptr<PendingItem> AppControlBroker::FindPendingItem(int id) {
+ std::lock_guard<std::recursive_mutex> lock(GetRecMutex());
+ auto found = items_.find(id);
+ if (found == items_.end())
+ return nullptr;
+
+ return found->second;
+}
+
+std::recursive_mutex& AppControlBroker::GetRecMutex() const {
+ return rec_mutex_;
+}
+
+void AppControlBroker::FlushPendingItem(int id) {
+ auto item = FindPendingItem(id);
+ if (item == nullptr)
+ return;
+
+ g_idle_add([](gpointer data) -> gboolean {
+ int req_id = GPOINTER_TO_INT(data);
+ auto* broker = AppControlBroker::GetInst();
+ auto item = broker->FindPendingItem(req_id);
+ if (item == nullptr)
+ return G_SOURCE_REMOVE;
+
+ auto result_info = item->GetResultInfo();
+ if (result_info != nullptr) {
+ AppControlResultBroker(req_id, result_info->GetResult(),
+ result_info->GetData());
+ item->SetResultInfo(nullptr);
+ return G_SOURCE_CONTINUE;
+ }
+
+ auto reply_info = item->GetReplyInfo();
+ if (reply_info != nullptr) {
+ AppControlReplyBroker(reply_info->GetBundle().GetHandle(), req_id,
+ static_cast<aul_svc_result_val>(reply_info->GetResult()),
+ reply_info->GetData());
+ item->SetReplyInfo(nullptr);
+ }
+
+ broker->PopPendingItem(req_id);
+ return G_SOURCE_REMOVE;
+ }, GINT_TO_POINTER(id));
+}
+
+void AppControlBroker::AppControlResultBroker(int req_id, int result,
+ void* user_data) {
+ auto* broker = AppControlBroker::GetInst();
+ auto request_context = broker->FindRequestContext(req_id);
+ if (request_context == nullptr) {
+ _E("Invalid request");
+ return;
+ }
+
+ auto app_control = request_context->GetAppControl();
+ app_control->SetLaunchedPid(result);
+ auto result_cb = request_context->GetResultCb();
+ if (result_cb != nullptr) {
+ int error = APP_CONTROL_ERROR_NONE;
+ if (result < 0)
+ error = Util::AulSvcErrorConvert(result);
+
+ result_cb(app_control.get(), static_cast<app_control_error_e>(error),
+ request_context->GetUserData());
+ }
+
+ if (result < 0 || request_context->GetReplyCb() == nullptr) {
+ broker->RemoveRequestContext(req_id);
+ return;
+ }
+
+ HandleAppStartedResult(app_control.get(), req_id);
+}
+
+void AppControlBroker::AppControlResultCb(int req_id, int result,
+ void* user_data) {
+ auto* broker = AppControlBroker::GetInst();
+ auto item = broker->FindPendingItem(req_id);
+ if (item != nullptr) {
+ item->SetResultInfo(std::make_shared<ResultInfo>(result, user_data));
+ _W("Result info is pending");
+ return;
+ }
+
+ AppControlResultBroker(req_id, result, user_data);
+}
+
+void AppControlBroker::AppControlReplyBroker(bundle* b, int req_id,
+ aul_svc_result_val result, void* user_data) {
+ auto* broker = AppControlBroker::GetInst();
+ auto request_context = broker->FindRequestContext(req_id);
+ if (request_context == nullptr)
+ return;
+
+ auto reply_cb = request_context->GetReplyCb();
+ if (reply_cb == nullptr) {
+ _E("Invalid callback");
+ return;
+ }
+
+ auto request = request_context->GetAppControl();
+ app_control_result_e res = Util::AulSvcResultConvert(result);
+ AppControl reply(tizen_base::Bundle(b), AppControl::Type::Reply);
+ reply_cb(request.get(), &reply, res, request_context->GetUserData());
+ broker->RemoveRequestContext(req_id);
+}
+
+void AppControlBroker::AppControlReplyCb(bundle* b, int req_id,
+ aul_svc_result_val result, void* user_data) {
+ auto* broker = AppControlBroker::GetInst();
+ auto item = broker->FindPendingItem(req_id);
+ if (item != nullptr) {
+ item->SetReplyInfo(std::make_shared<ReplyInfo>(
+ tizen_base::Bundle(b, true, true),
+ static_cast<int>(result), user_data));
+ _W("Reply info is pending");
+ return;
+ }
+
+ AppControlReplyBroker(b, req_id, result, user_data);
+}
+
+void AppControlBroker::HandleAppStartedResult(AppControl* app_control,
+ int req_id) {
+ int launched_pid = app_control->GetLaunchedPid();
+ if (!app_control->HasAppStartedResultEvent()) {
+ aul_add_caller_cb(launched_pid,
+ [](int launched_pid, void* data) {
+ AppControl* control = static_cast<AppControl*>(data);
+ if (control == nullptr)
+ return;
+
+ control->SetLaunchedPid(launched_pid);
+ }, static_cast<void*>(app_control));
+ return;
+ }
+
+ char callee[256] = { 0, };
+ int ret = aul_app_get_appid_bypid(launched_pid, callee, sizeof(callee));
+ if (ret != AUL_R_OK)
+ _E("Failed to get application ID. pid(%d)", launched_pid);
+
+ auto* broker = AppControlBroker::GetInst();
+ auto request_context = broker->FindRequestContext(req_id);
+ if (request_context != nullptr)
+ request_context->GetAppControl()->SetLaunchedPid(launched_pid);
+
+ aul_add_caller_cb(launched_pid,
+ [](int launched_pid, void* data) {
+ int req_id = GPOINTER_TO_INT(data);
+ auto* broker = AppControlBroker::GetInst();
+ auto request_context = broker->FindRequestContext(req_id);
+ if (request_context == nullptr)
+ return;
+
+ _I("AppControl async result callback. callee_pid(%d)", launched_pid);
+ auto reply_cb = request_context->GetReplyCb();
+ if (reply_cb == nullptr) {
+ _E("Invalid callback");
+ return;
+ }
+
+ auto app_control = request_context->GetAppControl();
+ AppControl reply(tizen_base::Bundle(app_control->ToBundle()),
+ AppControl::Type::Event);
+
+ char callee[256] = { 0, };
+ int ret = aul_app_get_appid_bypid(launched_pid, callee, sizeof(callee));
+ if (ret != AUL_R_OK)
+ _E("Failed to get application ID. pid(%d)", launched_pid);
+ else
+ reply.SetAppId(callee);
+
+ reply_cb(app_control.get(), &reply, APP_CONTROL_RESULT_APP_STARTED,
+ request_context->GetUserData());
+ }, GINT_TO_POINTER(req_id));
+
+ if (strcmp(callee, APP_SELECTOR) && strcmp(callee, SHARE_PANEL))
+ aul_invoke_caller_cb(GINT_TO_POINTER(req_id));
+}
+
+int AppControlBroker::CheckAppControl(AppControl* app_control) {
+ std::string operation;
+ try {
+ operation = app_control->GetOperation();
+ } catch (Exception& e) {
+ operation = APP_CONTROL_OPERATION_DEFAULT;
+ }
+
+ if (operation == APP_CONTROL_OPERATION_LAUNCH_ON_EVENT) {
+ _E("Not supported operation value");
+ return APP_CONTROL_ERROR_LAUNCH_REJECTED;
+ }
+
+ if (operation == APP_CONTROL_OPERATION_DEFAULT) {
+ try {
+ std::string app_id = app_control->GetAppId();
+ } catch (Exception& e) {
+ _E("Application ID MUST be specified");
+ return APP_CONTROL_ERROR_APP_NOT_FOUND;
+ }
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+void AppControlBroker::CopyCalleeInfo(AppControl* dst, AppControl* src) {
+ try {
+ auto app_id = src->GetAppId();
+ dst->SetAppId(app_id);
+ } catch (Exception& e) {
+ SECURE_LOGD("Failed to get application ID");
+ }
+
+ try {
+ auto instance_id = src->GetInstanceId();
+ dst->SetInstanceId(instance_id);
+ } catch (Exception& e) {
+ SECURE_LOGD("Failed to get instance ID");
+ }
+}
+
+void AppControlBroker::SendLaunchRequest(AppControl* app_control,
+ std::shared_ptr<RequestContext> context) {
+ int ret = CheckAppControl(app_control);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ THROW(ret);
+
+ int req_id = context->GetRequestId();
+ aul_svc_res_fn reply_cb =
+ context->GetReplyCb() ? AppControlReplyCb : nullptr;
+ aul_svc_err_cb result_cb =
+ context->GetResultCb() ? AppControlResultCb : nullptr;
+
+ if (reply_cb != nullptr || result_cb != nullptr) {
+ AddRequestContext(context);
+ PushPendingItem(std::make_shared<PendingItem>(req_id));
+ }
+
+ if (result_cb != nullptr) {
+ ret = aul_svc_send_launch_request_for_uid(app_control->ToBundle(),
+ req_id, reply_cb, result_cb, nullptr, getuid());
+ } else {
+ ret = aul_svc_run_service_for_uid(app_control->ToBundle(),
+ req_id, reply_cb, nullptr, getuid());
+ }
+
+ if (ret < 0) {
+ _E("Failed to send launch request. error(%d)", ret);
+ PopPendingItem(req_id);
+ RemoveRequestContext(req_id);
+ THROW(Util::AulSvcErrorConvert(ret));
+ }
+
+ app_control->SetLaunchedPid(ret);
+ if (context->GetAppControl() != nullptr)
+ CopyCalleeInfo(context->GetAppControl().get(), app_control);
+
+ if (result_cb != nullptr) {
+ FlushPendingItem(req_id);
+ return;
+ }
+
+ if (reply_cb == nullptr)
+ return;
+
+ HandleAppStartedResult(app_control, req_id);
+ FlushPendingItem(req_id);
+}
+
+void AppControlBroker::SendLaunchRequest(AppControl* app_control,
+ AppControl** reply, app_control_result_e* result) {
+ int ret = CheckAppControl(app_control);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ THROW(ret);
+
+ bundle* b = nullptr;
+ aul_svc_result_val res;
+ int req_id = RequestContext::GenerateId();
+ ret = aul_svc_send_launch_request_sync_for_uid(app_control->ToBundle(),
+ req_id, &b, &res, getuid());
+ if (ret < 0) {
+ _E("Failed to send launch request. error(%d)", ret);
+ THROW(Util::AulSvcErrorConvert(ret));
+ }
+
+ app_control->SetLaunchedPid(ret);
+ *reply = new (std::nothrow) AppControl(
+ tizen_base::Bundle(b, false, true), AppControl::Type::Reply);
+ if (*reply == nullptr) {
+ _E("Failed to create reply handle");
+ THROW(APP_CONTROL_ERROR_OUT_OF_MEMORY);
+ }
+
+ *result = Util::AulSvcResultConvert(res);
+}
+
+void AppControlBroker::SendResumeRequest(AppControl* app_control,
+ std::shared_ptr<RequestContext> context) {
+ try {
+ std::string app_id = app_control->GetAppId();
+ } catch (Exception& e) {
+ _E("Application ID MUST be specified");
+ THROW(APP_CONTROL_ERROR_APP_NOT_FOUND);
+ }
+
+ int req_id = context->GetRequestId();
+ AddRequestContext(context);
+ PushPendingItem(std::make_shared<PendingItem>(req_id));
+ aul_svc_err_cb result_cb = AppControlResultCb;
+
+ int ret = aul_svc_send_resume_request_for_uid(app_control->ToBundle(),
+ req_id, result_cb, nullptr, getuid());
+ if (ret < 0) {
+ _E("Failed to send resume request. error(%d)", ret);
+ PopPendingItem(req_id);
+ RemoveRequestContext(req_id);
+ THROW(Util::AulSvcErrorConvert(ret));
+ }
+
+ CopyCalleeInfo(context->GetAppControl().get(), app_control);
+ FlushPendingItem(req_id);
+}
+
+} // namespace app_control
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_APP_CONTROL_BROKER_HH_
+#define APP_CONTROL_APP_CONTROL_BROKER_HH_
+
+#include <aul.h>
+#include <aul_svc.h>
+#include <bundle_cpp.h>
+
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <map>
+
+#include "app-control/request_context.hh"
+#include "app-control/pending_item.hh"
+#include "include/app_control.h"
+
+namespace app_control {
+
+class AppControlBroker {
+ private:
+ AppControlBroker() = default;
+ ~AppControlBroker() = default;
+
+ public:
+ static AppControlBroker* GetInst();
+
+ void SendLaunchRequest(AppControl* app_control,
+ std::shared_ptr<RequestContext> request_context);
+ void SendLaunchRequest(AppControl* app_control,
+ AppControl** reply, app_control_result_e* result);
+ void SendResumeRequest(AppControl* app_control,
+ std::shared_ptr<RequestContext> request_context);
+
+ private:
+ void AddRequestContext(std::shared_ptr<RequestContext> request_context);
+ void RemoveRequestContext(int id);
+ std::shared_ptr<RequestContext> FindRequestContext(int id);
+
+ void PushPendingItem(std::shared_ptr<PendingItem> item);
+ std::shared_ptr<PendingItem> PopPendingItem(int id);
+ std::shared_ptr<PendingItem> FindPendingItem(int id);
+ void FlushPendingItem(int id);
+
+ std::recursive_mutex& GetRecMutex() const;
+
+ static void AppControlResultBroker(int req_id, int result, void* user_data);
+ static void AppControlResultCb(int req_id, int result, void* user_data);
+ static void AppControlReplyBroker(bundle* b, int req_id,
+ aul_svc_result_val result, void* user_data);
+ static void AppControlReplyCb(bundle* b, int req_id,
+ aul_svc_result_val result, void* user_data);
+ static void HandleAppStartedResult(AppControl* app_control, int req_id);
+ static int CheckAppControl(AppControl* app_control);
+ static void CopyCalleeInfo(AppControl* dst, AppControl* src);
+
+ private:
+ static std::atomic<AppControlBroker*> inst_;
+ static std::mutex mutex_;
+
+ private:
+ std::map<int, std::shared_ptr<RequestContext>> contexts_;
+ std::map<int, std::shared_ptr<PendingItem>> items_;
+ mutable std::recursive_mutex rec_mutex_;
+};
+
+} // namespace app_control
+
+#endif // APP_CONTROL_APP_CONTROL_BROKER_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_ERROR_HH_
+#define APP_CONTROL_ERROR_HH_
+
+#include <tizen.h>
+
+namespace app_control {
+
+enum Error : int {
+ None = TIZEN_ERROR_NONE,
+ InvalidParameter = TIZEN_ERROR_INVALID_PARAMETER,
+ OutOfMemory = TIZEN_ERROR_OUT_OF_MEMORY,
+ AppNotFound = TIZEN_ERROR_APPLICATION | 0x21,
+ KeyNotFound = TIZEN_ERROR_KEY_NOT_AVAILABLE,
+ KeyRejected = TIZEN_ERROR_KEY_REJECTED,
+ InvalidDataType = TIZEN_ERROR_APPLICATION | 0x22,
+ LaunchRejected = TIZEN_ERROR_APPLICATION | 0x23,
+ PermissionDenied = TIZEN_ERROR_PERMISSION_DENIED,
+ LaunchFailed = TIZEN_ERROR_APPLICATION | 0x24,
+ TimedOut = TIZEN_ERROR_TIMED_OUT,
+ IOError = TIZEN_ERROR_IO_ERROR,
+};
+
+} // namespace app_control
+
+#endif // APP_CONTROL_ERROR_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_EXCEPTION_HH_
+#define APP_CONTROL_EXCEPTION_HH_
+
+#include <string>
+#include <exception>
+
+#include "app-control/log_private.hh"
+
+#define THROW(error_code) throw Exception(error_code, __FUNCTION__, __LINE__)
+
+namespace app_control {
+
+class Exception : public std::exception {
+ public:
+ explicit Exception(int error_code, std::string file = __FILE__,
+ int line = __LINE__ ) {
+ error_code_ = error_code;
+ message_ = file.substr(file.find_last_of("/") + 1) + ":"
+ + std::to_string(line) + " code:" + std::to_string(error_code_);
+ }
+
+ virtual ~Exception() {}
+
+ virtual const char *what(void) const noexcept {
+ return message_.c_str();
+ }
+
+ int GetErrorCode() {
+ return error_code_;
+ }
+
+ private:
+ int error_code_;
+ std::string message_;
+};
+
+} // namespace app_control
+
+#endif // APP_CONTROL_EXCEPTION_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_LAUNCH_MODE_HH_
+#define APP_CONTROL_LAUNCH_MODE_HH_
+
+namespace app_control {
+
+enum LaunchMode : int {
+ Single,
+ Group,
+};
+
+} // namespace app_control
+
+#endif // APP_CONTROL_LAUNCH_MODE_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_LOG_PRIVATE_HH_
+#define APP_CONTROL_LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "CAPI_APPFW_APP_CONTROL"
+
+#undef _E
+#define _E LOGE
+
+#undef _W
+#define _W LOGW
+
+#undef _I
+#define _I LOGI
+
+#undef _D
+#define _D LOGD
+
+#endif // APP_CONTROL_LOG_PRIVATE_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 "app-control/pending_item.hh"
+
+namespace app_control {
+
+ReplyInfo::ReplyInfo(tizen_base::Bundle b, int result, void* data)
+ : b_(std::move(b)), result_(result), data_(data) {
+}
+
+ReplyInfo::~ReplyInfo() = default;
+
+tizen_base::Bundle ReplyInfo::GetBundle() const {
+ return b_;
+}
+
+int ReplyInfo::GetResult() const {
+ return result_;
+}
+
+void* ReplyInfo::GetData() const {
+ return data_;
+}
+
+ResultInfo::ResultInfo(int result, void* data)
+ : result_(result), data_(data) {
+}
+
+ResultInfo::~ResultInfo() = default;
+
+int ResultInfo::GetResult() const {
+ return result_;
+}
+
+void* ResultInfo::GetData() const {
+ return data_;
+}
+
+PendingItem::PendingItem(int id) : id_(id) {
+}
+
+PendingItem::~PendingItem() = default;
+
+int PendingItem::GetId() const {
+ return id_;
+}
+
+void PendingItem::SetReplyInfo(std::shared_ptr<ReplyInfo> reply_info) {
+ reply_info_ = std::move(reply_info);
+}
+
+std::shared_ptr<ReplyInfo> PendingItem::GetReplyInfo() const {
+ return reply_info_;
+}
+
+void PendingItem::SetResultInfo(std::shared_ptr<ResultInfo> result_info) {
+ result_info_ = std::move(result_info);
+}
+
+std::shared_ptr<ResultInfo> PendingItem::GetResultInfo() const {
+ return result_info_;
+}
+
+} // namespace app_control
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_PENDING_ITEM_HH_
+#define APP_CONTROL_PENDING_ITEM_HH_
+
+#include <bundle_cpp.h>
+
+namespace app_control {
+
+class ReplyInfo {
+ public:
+ ReplyInfo(tizen_base::Bundle b, int result, void* data);
+ virtual ~ReplyInfo();
+
+ tizen_base::Bundle GetBundle() const;
+ int GetResult() const;
+ void* GetData() const;
+
+ private:
+ tizen_base::Bundle b_;
+ int result_;
+ void* data_;
+};
+
+class ResultInfo {
+ public:
+ ResultInfo(int result, void* data);
+ virtual ~ResultInfo();
+
+ int GetResult() const;
+ void* GetData() const;
+
+ private:
+ int result_;
+ void* data_;
+};
+
+class PendingItem {
+ public:
+ PendingItem(int id);
+ virtual ~PendingItem();
+
+ int GetId() const;
+
+ void SetReplyInfo(std::shared_ptr<ReplyInfo> reply_info);
+ std::shared_ptr<ReplyInfo> GetReplyInfo() const;
+
+ void SetResultInfo(std::shared_ptr<ResultInfo> result_info);
+ std::shared_ptr<ResultInfo> GetResultInfo() const;
+
+ private:
+ int id_;
+ std::shared_ptr<ReplyInfo> reply_info_;
+ std::shared_ptr<ResultInfo> result_info_;
+};
+
+} // namespace app_control
+
+#endif // APP_CONTROL_PENDING_ITEM_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 <atomic>
+
+#include "app-control/request_context.hh"
+
+namespace app_control {
+
+RequestContext::RequestContext(std::shared_ptr<AppControl> app_control,
+ app_control_result_cb result_cb, app_control_reply_cb reply_cb,
+ void* user_data)
+ : request_id_(GenerateId()),
+ app_control_(std::move(app_control)),
+ result_cb_(result_cb),
+ reply_cb_(reply_cb),
+ user_data_(user_data) {
+}
+
+int RequestContext::GetRequestId() const {
+ return request_id_;
+}
+
+std::shared_ptr<AppControl> RequestContext::GetAppControl() const {
+ return app_control_;
+}
+
+app_control_result_cb RequestContext::GetResultCb() const {
+ return result_cb_;
+}
+
+app_control_reply_cb RequestContext::GetReplyCb() const {
+ return reply_cb_;
+}
+
+void* RequestContext::GetUserData() const {
+ return user_data_;
+}
+
+int RequestContext::GenerateId() {
+ static std::atomic<int> id { 0 };
+ if (id + 1 < 0)
+ id.exchange(0);
+
+ return ++id;
+}
+
+} // namespace app_control
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_REQUEST_CONTEXT_HH_
+#define APP_CONTROL_REQUEST_CONTEXT_HH_
+
+#include <memory>
+
+#include "app-control/app_control.hh"
+#include "include/app_control.h"
+
+namespace app_control {
+
+class RequestContext {
+ public:
+ RequestContext(std::shared_ptr<AppControl> app_control,
+ app_control_result_cb result_cb, app_control_reply_cb reply_cb,
+ void* user_data);
+
+ int GetRequestId() const;
+ std::shared_ptr<AppControl> GetAppControl() const;
+ app_control_result_cb GetResultCb() const;
+ app_control_reply_cb GetReplyCb() const;
+ void* GetUserData() const;
+
+ static int GenerateId();
+
+ private:
+ int request_id_;
+ std::shared_ptr<AppControl> app_control_;
+ app_control_result_cb result_cb_;
+ app_control_reply_cb reply_cb_;
+ void* user_data_;
+};
+
+} // namespace app_control
+
+#endif // APP_CONTROL_REQUEST_CONTEXT_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_RESULT_HH_
+#define APP_CONTROL_RESULT_HH_
+
+namespace app_control {
+
+enum Result : int {
+ AppStarted = 1,
+ Succeeded = 0,
+ Failed = -1,
+ Canceled = -2,
+};
+
+} // namespace app_control
+
+#endif // APP_CONTROL_RESULT_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 <aul.h>
+#include <aul_svc.h>
+#include <bundle.h>
+#include <glib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <memory>
+
+#include "app-control/app_control.hh"
+#include "app-control/app_control_action.hh"
+#include "app-control/app_control_broker.hh"
+#include "app-control/exception.hh"
+#include "app-control/log_private.hh"
+#include "app-control/util.hh"
+#include "include/app_control.h"
+#include "include/app_control_internal.h"
+
+#undef EXPORT
+#define EXPORT extern "C" __attribute__((visibility("default")))
+
+#undef DEPRECATION_WARNING
+#define DEPRECATION_WARNING() do { \
+ dlog_print(DLOG_WARN, LOG_TAG, \
+ "DEPRECATION WARNING: %s() is deprecated and " \
+ "will be removed from next release.", __FUNCTION__); \
+} while (0)
+
+using namespace app_control;
+
+namespace {
+
+class ActionExt : public AppControlAction,
+ public AppControlAction::IEvent {
+ public:
+ ActionExt(std::string action) : AppControlAction(action, this) {
+ }
+
+ virtual ~ActionExt() {
+ }
+
+ void SetActionCb(app_control_action_cb cb, void* user_data) {
+ cb_ = cb;
+ user_data_ = user_data;
+ }
+
+ private:
+ void OnAction(const std::string& action, bundle* data) override {
+ app_control_h app_control;
+ int ret = app_control_create_event(data, &app_control);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ _E("Failed to create app-control handle. error(%d)", ret);
+ return;
+ }
+
+ cb_(action.c_str(), app_control, user_data_);
+ app_control_destroy(app_control);
+ }
+
+ private:
+ app_control_action_cb cb_;
+ void* user_data_;
+};
+
+} // namespace
+
+EXPORT int app_control_create_request(bundle* data,
+ app_control_h* app_control) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ tizen_base::Bundle b;
+ if (data != nullptr)
+ b = tizen_base::Bundle(data, true, true);
+
+ auto* handle = new (std::nothrow) AppControl(b);
+ if (handle == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ *app_control = static_cast<app_control_h>(handle);
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_create(app_control_h* app_control) {
+ return app_control_create_request(nullptr, app_control);
+}
+
+EXPORT int app_control_create_with_parameters(app_control_h* app_control,
+ const char* operation, const char* uri, const char* mime,
+ const char* category, const char* app_id, app_control_launch_mode_e mode,
+ int extra_data_count, ...) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ app_control_h handle;
+ int ret = app_control_create(&handle);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ auto ptr = std::unique_ptr<std::remove_pointer<app_control_h>::type,
+ decltype(app_control_destroy)*>(handle, app_control_destroy);
+
+ if (operation != nullptr) {
+ ret = app_control_set_operation(handle, operation);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+ }
+
+ if (uri != nullptr) {
+ ret = app_control_set_uri(handle, uri);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+ }
+
+ if (mime != nullptr) {
+ ret = app_control_set_mime(handle, mime);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+ }
+
+ if (category != nullptr) {
+ ret = app_control_set_category(handle, category);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+ }
+
+ if (app_id != nullptr) {
+ ret = app_control_set_app_id(handle, app_id);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+ }
+
+ ret = app_control_set_launch_mode(handle, mode);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ va_list vl;
+ va_start(vl, extra_data_count);
+ for (int i = 0; i < extra_data_count; ++i) {
+ char* key = va_arg(vl, char*);
+ char* value = va_arg(vl, char*);
+ ret = app_control_add_extra_data(handle, key, value);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ va_end(vl);
+ return ret;
+ }
+ }
+ va_end(vl);
+
+ *app_control = ptr.release();
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_create_from_uri_handle(app_control_h* app_control,
+ app_control_uri_h uri) {
+ if (app_control == nullptr || uri == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ app_control_h handle;
+ int ret = app_control_create(&handle);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ auto ptr = std::unique_ptr<std::remove_pointer<app_control_h>::type,
+ decltype(app_control_destroy)*>(handle, app_control_destroy);
+
+ ret = app_control_set_operation(handle, APP_CONTROL_OPERATION_INTENT);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ ret = app_control_set_uri_by_handle(handle, uri);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ const char* path;
+ ret = app_control_uri_get_path(uri, &path);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ ret = app_control_add_extra_data(handle, APP_CONTROL_DATA_URI_PATH, path);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ const char* fragment;
+ ret = app_control_uri_get_fragment(uri, &fragment);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ ret = app_control_add_extra_data(handle, APP_CONTROL_DATA_URI_FRAGMENT,
+ fragment);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ app_control_uri_query_h query;
+ ret = app_control_uri_get_query(uri, &query);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ ret = app_control_uri_query_foreach(query,
+ [](const char* key, const char* value, void* user_data) -> bool {
+ auto* handle = static_cast<app_control_h>(user_data);
+ int ret = app_control_add_extra_data(handle, key, value);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ _E("app_control_add_extra_data(%p, %s, %s) is failed. error(%d)",
+ handle, key, value, ret);
+ return false;
+ }
+
+ return true;
+ }, handle);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ *app_control = ptr.release();
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_create_event(bundle* data,
+ app_control_h* app_control) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ tizen_base::Bundle b(data, true, true);
+ auto* handle = new (std::nothrow) AppControl(b, AppControl::Type::Event);
+ if (handle == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ try {
+ std::string operation = handle->GetOperation();
+ } catch (Exception& e) {
+ handle->SetOperation(APP_CONTROL_OPERATION_DEFAULT);
+ }
+
+ *app_control = static_cast<app_control_h>(handle);
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_destroy(app_control_h app_control) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ delete handle;
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_to_bundle(app_control_h app_control, bundle** data) {
+ if (app_control == nullptr || data == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ *data = handle->ToBundle();
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_operation(app_control_h app_control,
+ const char* operation) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ if (operation != nullptr) {
+ try {
+ handle->SetOperation(operation);
+ } catch (Exception& e) {
+ _E("Invalid operation");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ handle->RemoveOperation();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_operation(app_control_h app_control,
+ char** operation) {
+ if (app_control == nullptr || operation == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::string value = handle->GetOperation();
+ *operation = strdup(value.c_str());
+ if (*operation == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } catch (Exception& e) {
+ *operation = nullptr;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_uri(app_control_h app_control, const char* uri) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ if (uri != nullptr) {
+ try {
+ handle->SetUri(uri);
+ } catch (Exception& e) {
+ _E("Invalid uri");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ handle->RemoveUri();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_uri(app_control_h app_control, char** uri) {
+ if (app_control == nullptr || uri == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::string value = handle->GetUri();
+ *uri = strdup(value.c_str());
+ if (*uri == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } catch (Exception& e) {
+ *uri = nullptr;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_uri_by_handle(app_control_h app_control,
+ app_control_uri_h uri) {
+ if (app_control == nullptr || uri == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ const char* scheme;
+ int ret = app_control_uri_get_scheme(uri, &scheme);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+
+ const char* authority;
+ ret = app_control_uri_get_authority(uri, &authority);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+
+ std::string uri_str = std::string(scheme) + ":" + std::string(authority);
+ ret = app_control_set_uri(app_control, uri_str.c_str());
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_mime(app_control_h app_control, const char* mime) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ if (mime != nullptr) {
+ try {
+ handle->SetMime(mime);
+ } catch (Exception& e) {
+ _E("Invalid MIME Type");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ handle->RemoveMime();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_mime(app_control_h app_control, char** mime) {
+ if (app_control == nullptr || mime == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::string value = handle->GetMime();
+ *mime = strdup(value.c_str());
+ if (*mime == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } catch (Exception& e) {
+ *mime = nullptr;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_category(app_control_h app_control,
+ const char* category) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ if (category != nullptr) {
+ try {
+ handle->SetCategory(category);
+ } catch (Exception& e) {
+ _E("Invalid category");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ handle->RemoveCategory();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_category(app_control_h app_control,
+ char** category) {
+ if (app_control == nullptr || category == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::string value = handle->GetCategory();
+ *category = strdup(value.c_str());
+ if (*category == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } catch (Exception& e) {
+ *category = nullptr;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_app_id(app_control_h app_control,
+ const char* app_id) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ if (app_id != nullptr) {
+ try {
+ handle->SetAppId(app_id);
+ } catch (Exception& e) {
+ _E("Invalid application ID");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ handle->RemoveAppId();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_app_id(app_control_h app_control, char** app_id) {
+ if (app_control == nullptr || app_id == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::string value = handle->GetAppId();
+ *app_id = strdup(value.c_str());
+ if (*app_id == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } catch (Exception& e) {
+ *app_id = nullptr;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_clone(app_control_h* clone, app_control_h app_control) {
+ if (clone == nullptr || app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* control = static_cast<AppControl*>(app_control);
+ auto* handle = new (std::nothrow) AppControl(*control);
+ if (handle == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ *clone = static_cast<app_control_h>(handle);
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_launch_mode(app_control_h app_control,
+ app_control_launch_mode_e mode) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (mode != APP_CONTROL_LAUNCH_MODE_SINGLE &&
+ mode != APP_CONTROL_LAUNCH_MODE_GROUP) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ LaunchMode launch_mode = (mode == APP_CONTROL_LAUNCH_MODE_SINGLE) ?
+ LaunchMode::Single : LaunchMode::Group;
+ auto* handle = static_cast<AppControl*>(app_control);
+ handle->SetLaunchMode(launch_mode);
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_launch_mode(app_control_h app_control,
+ app_control_launch_mode_e* mode) {
+ if (app_control == nullptr || mode == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ LaunchMode launch_mode = handle->GetLaunchMode();
+ if (launch_mode == LaunchMode::Group)
+ *mode = APP_CONTROL_LAUNCH_MODE_GROUP;
+ else
+ *mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
+ } catch (Exception& e) {
+ _W("Launch mode is not matched");
+ *mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_defapp(app_control_h app_control,
+ const char* app_id) {
+ if (app_control == nullptr || app_id == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ int ret = app_control_set_app_id(app_control, app_id);
+ if (ret != APP_CONTROL_ERROR_NONE)
+ return ret;
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ ret = aul_set_default_app_by_operation(handle->ToBundle());
+ if (ret != AUL_R_OK) {
+ _E("Failed to set default application. app_id(%s), error(%d)", app_id, ret);
+ if (ret == AUL_R_EILLACC)
+ return APP_CONTROL_ERROR_PERMISSION_DENIED;
+
+ return APP_CONTROL_ERROR_IO_ERROR;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_unset_defapp(const char* app_id) {
+ if (app_id == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ int ret = aul_unset_default_app_by_operation(app_id);
+ if (ret != AUL_R_OK) {
+ _E("Failed to unset default application. app_id(%s), error(%d)",
+ app_id, ret);
+ if (ret == AUL_R_EILLACC)
+ return APP_CONTROL_ERROR_PERMISSION_DENIED;
+
+ return APP_CONTROL_ERROR_IO_ERROR;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_add_extra_data(app_control_h app_control,
+ const char* key, const char* value) {
+ if (app_control == nullptr || key == nullptr || value == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ try {
+ handle->AddExtraData(key, value);
+ } catch (Exception& e) {
+ _E("Failed to add extra data. error(%d)", e.GetErrorCode());
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_add_extra_data_array(app_control_h app_control,
+ const char* key, const char* value[], int length) {
+ if (app_control == nullptr || key == nullptr ||
+ value == nullptr || length <= 0) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::vector<std::string> values(value, value + length);
+ handle->AddExtraDataArray(key, values);
+ } catch (Exception& e) {
+ _E("Failed to add extra data array. error(%d)", e.GetErrorCode());
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_remove_extra_data(app_control_h app_control,
+ const char* key) {
+ if (app_control == nullptr || key == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ handle->RemoveExtraData(key);
+ } catch (Exception& e) {
+ _E("Failed to remove extra data. error(%d)", e.GetErrorCode());
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_extra_data(app_control_h app_control,
+ const char* key, char** value) {
+ if (app_control == nullptr || key == nullptr || value == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::string extra_data = handle->GetExtraData(key);
+ *value = strdup(extra_data.c_str());
+ if (*value == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } catch (Exception& e) {
+ _E("Failed to get extra data. error(%d)", e.GetErrorCode());
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_extra_data_array(app_control_h app_control,
+ const char* key, char*** value, int* length) {
+ if (app_control == nullptr || key == nullptr ||
+ value == nullptr || length == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ char** array_data = nullptr;
+ int array_data_length = 0;
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::vector<std::string> values = handle->GetExtraDataArray(key);
+ array_data = reinterpret_cast<char**>(calloc(values.size(), sizeof(char*)));
+ if (array_data == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ array_data_length = values.size();
+ for (int i = 0; i < array_data_length; ++i)
+ array_data[i] = strdup(values[i].c_str());
+ } catch (Exception& e) {
+ _E("Failed to get extra data array. error(%d)", e.GetErrorCode());
+ return e.GetErrorCode();
+ }
+
+ *value = array_data;
+ *length = array_data_length;
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_is_extra_data_array(app_control_h app_control,
+ const char* key, bool* array) {
+ if (app_control == nullptr || key == nullptr || array == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ *array = handle->IsExtraDataArray(key);
+ } catch (Exception& e) {
+ _E("Failed to check whether the data is array or not. key(%s), error(%d)",
+ key, e.GetErrorCode());
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_foreach_extra_data(app_control_h app_control,
+ app_control_extra_data_cb callback, void* user_data) {
+ if (app_control == nullptr || callback == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ for (auto& key : handle->GetExtraDataKeys()) {
+ if (!callback(app_control, key.c_str(), user_data))
+ break;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_foreach_app_matched(app_control_h app_control,
+ app_control_app_matched_cb callback, void* user_data) {
+ if (app_control == nullptr || callback == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ for (auto& app_id : handle->GetMatchedAppIds()) {
+ if (!callback(app_control, app_id.c_str(), user_data))
+ break;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_caller(app_control_h app_control, char** app_id) {
+ if (app_control == nullptr || app_id == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::string caller = handle->GetCaller();
+ *app_id = strdup(caller.c_str());
+ if (*app_id == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } catch (Exception& e) {
+ _E("Failed to find caller appid. error(%d)", e.GetErrorCode());
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_is_reply_requested(app_control_h app_control,
+ bool* requested) {
+ if (app_control == nullptr || requested == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ *requested = handle->IsReplyRequested();
+ } catch (Exception& e) {
+ _E("Invalid app-control handle");
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_import_from_bundle(app_control_h app_control,
+ bundle* data) {
+ if (app_control == nullptr || data == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ tizen_base::Bundle b(data, true, true);
+ handle->SetBundle(b);
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_export_as_bundle(app_control_h app_control,
+ bundle** data) {
+ if (app_control == nullptr || data == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ auto* b = handle->ToBundle();
+ *data = bundle_dup(b);
+ if (*data == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_enable_app_started_result_event(
+ app_control_h app_control) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ handle->EnableAppStartedResultEvent();
+ } catch (Exception& e) {
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_instance_id(app_control_h app_control,
+ const char* instance_id) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ if (instance_id != nullptr) {
+ try {
+ handle->SetInstanceId(instance_id);
+ } catch (Exception& e) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ handle->RemoveInstanceId();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_instance_id(app_control_h app_control,
+ char** instance_id) {
+ if (app_control == nullptr || instance_id == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::string value = handle->GetInstanceId();
+ *instance_id = strdup(value.c_str());
+ if (*instance_id == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } catch (Exception& e) {
+ _E("Failed to get instance ID");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_add_action_handler(const char* action,
+ app_control_action_cb callback, void* user_data,
+ app_control_action_h* handle) {
+ if (action == nullptr || callback == nullptr || handle == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ ActionExt* p = nullptr;
+ try {
+ p = new (std::nothrow) ActionExt(action);
+ } catch (Exception& e) {
+ _E("Failed to create action handle. action(%s), error(%d)",
+ action, e.GetErrorCode());
+ return e.GetErrorCode();
+ }
+
+ p->SetActionCb(callback, user_data);
+ *handle = static_cast<app_control_action_h>(p);
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_remove_action_handler(app_control_action_h handle) {
+ if (handle == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* p = static_cast<ActionExt*>(handle);
+ delete p;
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_caller_instance_id(app_control_h app_control,
+ const char* instance_id) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ if (instance_id != nullptr) {
+ try {
+ handle->SetCallerInstanceId(instance_id);
+ } catch (Exception& e) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ handle->RemoveCallerInstanceId();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_component_id(app_control_h app_control,
+ const char* component_id) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ if (component_id != nullptr) {
+ try {
+ handle->SetComponentId(component_id);
+ } catch (Exception& e) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ handle->RemoveComponentId();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_component_id(app_control_h app_control,
+ char** component_id) {
+ if (app_control == nullptr || component_id == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ std::string value = handle->GetComponentId();
+ *component_id = strdup(value.c_str());
+ if (*component_id == nullptr) {
+ _E("Out of memory");
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ } catch (Exception& e) {
+ *component_id = nullptr;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_prepare_app_defined_loader(app_control_h app_control,
+ const char* loader_name) {
+ if (app_control == nullptr || loader_name == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ int loader_id = aul_prepare_app_defined_loader(loader_name);
+ if (loader_id < 0) {
+ _E("Failed to prepare app defined loader. loader_name(%s), error(%d)",
+ loader_name, loader_id);
+ return Util::AulErrorConvert(loader_id);
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ handle->SetAppDefinedLoader(loader_name);
+ handle->SetLoaderId(loader_id);
+ } catch (Exception& e) {
+ _E("Failed to set loader id. loader_id(%s), error(%d)",
+ loader_name, e.GetErrorCode());
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_send_terminate_request(app_control_h app_control) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(app_control);
+ if (handle->GetType() != AppControl::Type::Request ||
+ handle->GetLaunchedPid() < 0) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ aul_svc_subapp_terminate_request(handle->ToBundle(),
+ handle->GetLaunchedPid());
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_reply_to_launch_request(app_control_h reply,
+ app_control_h request, app_control_result_e result) {
+ if (reply == nullptr || request ==nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (result == APP_CONTROL_RESULT_APP_STARTED) {
+ _E("APP_CONTROL_RESULT_APP_STARTED is not allowed");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* handle = static_cast<AppControl*>(request);
+ bundle* reply_data;
+ int ret = aul_svc_create_result_bundle(handle->ToBundle(), &reply_data);
+ if (ret != AUL_SVC_RET_OK) {
+ if (ret == AUL_SVC_RET_ECANCELED)
+ return APP_CONTROL_ERROR_NONE;
+
+ _E("Failed to create a result bundle");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ AppControl app_control(tizen_base::Bundle(reply_data, false, true));
+ auto* reply_handle = static_cast<AppControl*>(reply);
+ for (auto& key : reply_handle->GetExtraDataKeys()) {
+ if (reply_handle->IsExtraDataArray(key)) {
+ app_control.AddExtraDataArray(key, reply_handle->GetExtraDataArray(key));
+ } else {
+ app_control.AddExtraData(key, reply_handle->GetExtraData(key));
+ }
+ }
+
+ ret = aul_svc_send_result(app_control.ToBundle(),
+ Util::AppControlResultConvert(result));
+ if (ret != AUL_SVC_RET_OK) {
+ if (ret == AUL_SVC_RET_EINVAL)
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+
+ return APP_CONTROL_ERROR_LAUNCH_REJECTED;
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_send_launch_request(app_control_h app_control,
+ app_control_reply_cb callback, void* user_data) {
+ if (app_control == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ auto request_context = std::make_shared<RequestContext>(
+ std::shared_ptr<AppControl>(new AppControl(*handle)),
+ nullptr, callback, user_data);
+ auto* broker = AppControlBroker::GetInst();
+ broker->SendLaunchRequest(handle, request_context);
+ } catch (Exception& e) {
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_send_launch_request_async(app_control_h app_control,
+ app_control_result_cb result_cb, app_control_reply_cb reply_cb,
+ void* user_data) {
+ if (app_control == nullptr || result_cb == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ auto request_context = std::make_shared<RequestContext>(
+ std::shared_ptr<AppControl>(new AppControl(*handle)),
+ result_cb, reply_cb, user_data);
+ auto* broker = AppControlBroker::GetInst();
+ broker->SendLaunchRequest(handle, request_context);
+ } catch (Exception& e) {
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_send_launch_request_sync(app_control_h app_control,
+ app_control_h* reply, app_control_result_e* result) {
+ if (app_control == nullptr || reply == nullptr || result == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ AppControl* reply_handle = nullptr;
+ auto* handle = static_cast<AppControl*>(app_control);
+ auto* broker = AppControlBroker::GetInst();
+ broker->SendLaunchRequest(handle, &reply_handle, result);
+ *reply = static_cast<app_control_h>(reply_handle);
+ } catch (Exception& e) {
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_send_resume_request(app_control_h app_control,
+ app_control_result_cb result_cb, void* user_data) {
+ if (app_control == nullptr || result_cb == nullptr) {
+ _E("Invalid parameter");
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ try {
+ auto* handle = static_cast<AppControl*>(app_control);
+ auto request_context = std::make_shared<RequestContext>(
+ std::shared_ptr<AppControl>(new AppControl(*handle)),
+ result_cb, nullptr, user_data);
+ auto* broker = AppControlBroker::GetInst();
+ broker->SendResumeRequest(handle, request_context);
+ } catch (Exception& e) {
+ return e.GetErrorCode();
+ }
+
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_set_window(app_control_h app_control, unsigned int id) {
+ DEPRECATION_WARNING();
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_get_window(app_control_h app_control, unsigned int* id) {
+ DEPRECATION_WARNING();
+ return APP_CONTROL_ERROR_NONE;
+}
+
+EXPORT int app_control_request_transient_app(app_control_h app_control,
+ unsigned int callee_id, app_control_host_res_fn cbfunc, void* data) {
+ DEPRECATION_WARNING();
+ return APP_CONTROL_ERROR_NONE;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 "app-control/util.hh"
+
+namespace app_control {
+
+int Util::AulErrorConvert(int ret) {
+ switch (ret) {
+ case AUL_R_EINVAL:
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ case AUL_R_ENOMEM:
+ return APP_CONTROL_ERROR_OUT_OF_MEMORY;
+ case AUL_R_EILLACC:
+ return APP_CONTROL_ERROR_PERMISSION_DENIED;
+ default:
+ return APP_CONTROL_ERROR_IO_ERROR;
+ }
+}
+
+app_control_result_e Util::AulSvcResultConvert(aul_svc_result_val result) {
+ switch (result) {
+ case AUL_SVC_RES_OK:
+ return APP_CONTROL_RESULT_SUCCEEDED;
+ case AUL_SVC_RES_NOT_OK:
+ return APP_CONTROL_RESULT_FAILED;
+ default:
+ return APP_CONTROL_RESULT_CANCELED;
+ }
+}
+
+aul_svc_result_val Util::AppControlResultConvert(app_control_result_e result) {
+ switch (result) {
+ case APP_CONTROL_RESULT_SUCCEEDED:
+ return AUL_SVC_RES_OK;
+ case APP_CONTROL_RESULT_FAILED:
+ return AUL_SVC_RES_NOT_OK;
+ default:
+ return AUL_SVC_RES_CANCEL;
+ }
+}
+
+int Util::AulSvcErrorConvert(int res) {
+ switch (res) {
+ case AUL_SVC_RET_OK:
+ return APP_CONTROL_ERROR_NONE;
+ case AUL_SVC_RET_ENOMATCH:
+ return APP_CONTROL_ERROR_APP_NOT_FOUND;
+ case AUL_SVC_RET_EILLACC:
+ return APP_CONTROL_ERROR_PERMISSION_DENIED;
+ case AUL_SVC_RET_EINVAL:
+ return APP_CONTROL_ERROR_INVALID_PARAMETER;
+ default:
+ return APP_CONTROL_ERROR_LAUNCH_REJECTED;
+ }
+}
+
+} // namespace app_control
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef APP_CONTROL_UTIL_HH_
+#define APP_CONTROL_UTIL_HH_
+
+#include <aul.h>
+#include <aul_svc.h>
+#include <tizen.h>
+
+#include "include/app_control.h"
+
+namespace app_control {
+
+class Util {
+ public:
+ static int AulErrorConvert(int ret);
+ static app_control_result_e AulSvcResultConvert(aul_svc_result_val result);
+ static aul_svc_result_val AppControlResultConvert(
+ app_control_result_e result);
+ static int AulSvcErrorConvert(int res);
+};
+
+} // namespace app_control
+
+#endif // APP_CONTROL_UTIL_HH_
return AUL_SVC_RET_ERROR;
}
-int fake_aul_svc_get_list_for_uid_AUL_SVC_RET_OK(bundle* b,
- aul_svc_info_iter_fn iter_fn, void* data, uid_t uid) {
- iter_fn("org.example.call", data);
+int fake_aul_svc_get_appid_array_AUL_SVC_RET_OK(bundle* b,
+ uid_t uid, char*** appid_array, unsigned int* len) {
+ *appid_array = reinterpret_cast<char**>(calloc(1, sizeof(char*)));
+ (*appid_array)[0] = strdup("org.example.call");
+ *len = 1;
return AUL_SVC_RET_OK;
}
app_control_set_operation(app_control_, APP_CONTROL_OPERATION_CALL);
app_control_set_uri(app_control_, "tel:010-2345-6789");
- EXPECT_CALL(GetMock<AulMock>(), aul_svc_get_list_for_uid(_, _, _, _)).
- WillOnce(Invoke(fake_aul_svc_get_list_for_uid_AUL_SVC_RET_OK));
+ EXPECT_CALL(GetMock<AulMock>(), aul_svc_get_appid_array(_, _, _, _)).
+ WillOnce(Invoke(fake_aul_svc_get_appid_array_AUL_SVC_RET_OK));
bool touch = false;
int ret = app_control_foreach_app_matched(app_control_,
return MOCK_HOOK_P2(AulMock, aul_svc_send_result, b, result);
}
-extern "C" int aul_svc_get_list_for_uid(bundle* b, aul_svc_info_iter_fn iter_fn,
- void* data, uid_t uid) {
- return MOCK_HOOK_P4(AulMock, aul_svc_get_list_for_uid, b, iter_fn, data, uid);
+extern "C" int aul_svc_get_appid_array(bundle* b, uid_t uid,
+ char*** appid_array, unsigned int* len) {
+ return MOCK_HOOK_P4(AulMock, aul_svc_get_appid_array, b, uid, appid_array,
+ len);
}
extern "C" int aul_svc_send_launch_request_sync_for_uid(bundle* b, int id,
MOCK_METHOD2(aul_svc_subapp_terminate_request, int (bundle*, int));
MOCK_METHOD2(aul_svc_create_result_bundle, int (bundle*, bundle**));
MOCK_METHOD2(aul_svc_send_result, int (bundle*, aul_svc_result_val));
- MOCK_METHOD4(aul_svc_get_list_for_uid,
- int (bundle*, aul_svc_info_iter_fn, void*, uid_t));
+ MOCK_METHOD4(aul_svc_get_appid_array,
+ int (bundle*, uid_t, char***, unsigned int *));
MOCK_METHOD5(aul_svc_send_launch_request_sync_for_uid,
int (bundle*, int, bundle**, aul_svc_result_val*, uid_t));
MOCK_METHOD5(aul_svc_send_resume_request_for_uid,