Refactor AppControl API 36/255336/19
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 17 Mar 2021 05:52:55 +0000 (14:52 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Mon, 5 Apr 2021 23:35:13 +0000 (08:35 +0900)
Change-Id: I4b2270c3aac3663da9b21165d4bea765f9ef7bc7
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
25 files changed:
include/app_control.h
include/app_control_internal.h
src/app-control/CMakeLists.txt
src/app-control/app_control.c [deleted file]
src/app-control/app_control.cc [new file with mode: 0644]
src/app-control/app_control.hh [new file with mode: 0644]
src/app-control/app_control_action.cc [new file with mode: 0644]
src/app-control/app_control_action.hh [new file with mode: 0644]
src/app-control/app_control_broker.cc [new file with mode: 0644]
src/app-control/app_control_broker.hh [new file with mode: 0644]
src/app-control/error.hh [new file with mode: 0644]
src/app-control/exception.hh [new file with mode: 0644]
src/app-control/launch_mode.hh [new file with mode: 0644]
src/app-control/log_private.hh [new file with mode: 0644]
src/app-control/pending_item.cc [new file with mode: 0644]
src/app-control/pending_item.hh [new file with mode: 0644]
src/app-control/request_context.cc [new file with mode: 0644]
src/app-control/request_context.hh [new file with mode: 0644]
src/app-control/result.hh [new file with mode: 0644]
src/app-control/stub.cc [new file with mode: 0644]
src/app-control/util.cc [new file with mode: 0644]
src/app-control/util.hh [new file with mode: 0644]
test/unit_tests/app_control_unittest.cc
test/unit_tests/mock/aul_mock.cc
test/unit_tests/mock/aul_mock.hh

index b9ecae6f7604dbabdbe4eeacf652a041088fca62..2600f0a542c2e9885b120f193b493b173dd67c0c 100644 (file)
@@ -39,7 +39,7 @@ extern "C" {
  * @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;
 
 
 /**
@@ -738,7 +738,7 @@ typedef void (*app_control_result_cb)(app_control_h request, app_control_error_e
  * @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.
index 60c6b7a8b7459dbca470a89cb79a07a86f67122c..5a959e0421d24f24059d701827c18bf4bcbfb7c5 100644 (file)
@@ -34,6 +34,10 @@ extern "C" {
  * @{
  */
 
+#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.
@@ -149,7 +153,7 @@ int app_control_to_bundle(app_control_h app_control, bundle **data);
  * @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.
@@ -164,7 +168,7 @@ int app_control_set_window(app_control_h app_control, unsigned int id);
  * @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);
 
@@ -182,7 +186,7 @@ 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
index b478318dc059cfd89e031f041308320dea23cbf1..61b25b09590951098e6c864805d09fe7128b3b7d 100644 (file)
@@ -5,7 +5,9 @@ SET_TARGET_PROPERTIES(${TARGET_APP_CONTROL} PROPERTIES SOVERSION ${MAJORVER})
 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
diff --git a/src/app-control/app_control.c b/src/app-control/app_control.c
deleted file mode 100644 (file)
index 657a109..0000000
+++ /dev/null
@@ -1,2505 +0,0 @@
-/*
- * 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;
-}
diff --git a/src/app-control/app_control.cc b/src/app-control/app_control.cc
new file mode 100644 (file)
index 0000000..59c497d
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ * 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
diff --git a/src/app-control/app_control.hh b/src/app-control/app_control.hh
new file mode 100644 (file)
index 0000000..1d33b69
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * 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_
diff --git a/src/app-control/app_control_action.cc b/src/app-control/app_control_action.cc
new file mode 100644 (file)
index 0000000..9529047
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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
diff --git a/src/app-control/app_control_action.hh b/src/app-control/app_control_action.hh
new file mode 100644 (file)
index 0000000..e9546e0
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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_
diff --git a/src/app-control/app_control_broker.cc b/src/app-control/app_control_broker.cc
new file mode 100644 (file)
index 0000000..5162d4c
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * 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
diff --git a/src/app-control/app_control_broker.hh b/src/app-control/app_control_broker.hh
new file mode 100644 (file)
index 0000000..0416d41
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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_
diff --git a/src/app-control/error.hh b/src/app-control/error.hh
new file mode 100644 (file)
index 0000000..f0d9c3b
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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_
diff --git a/src/app-control/exception.hh b/src/app-control/exception.hh
new file mode 100644 (file)
index 0000000..05ab5d3
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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_
diff --git a/src/app-control/launch_mode.hh b/src/app-control/launch_mode.hh
new file mode 100644 (file)
index 0000000..7a89e47
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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_
diff --git a/src/app-control/log_private.hh b/src/app-control/log_private.hh
new file mode 100644 (file)
index 0000000..65ffa06
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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_
diff --git a/src/app-control/pending_item.cc b/src/app-control/pending_item.cc
new file mode 100644 (file)
index 0000000..37819d8
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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
diff --git a/src/app-control/pending_item.hh b/src/app-control/pending_item.hh
new file mode 100644 (file)
index 0000000..20c79e9
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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_
diff --git a/src/app-control/request_context.cc b/src/app-control/request_context.cc
new file mode 100644 (file)
index 0000000..4a9f96d
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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
diff --git a/src/app-control/request_context.hh b/src/app-control/request_context.hh
new file mode 100644 (file)
index 0000000..852095f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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_
diff --git a/src/app-control/result.hh b/src/app-control/result.hh
new file mode 100644 (file)
index 0000000..df423da
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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_
diff --git a/src/app-control/stub.cc b/src/app-control/stub.cc
new file mode 100644 (file)
index 0000000..4dc0081
--- /dev/null
@@ -0,0 +1,1215 @@
+/*
+ * 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;
+}
+
diff --git a/src/app-control/util.cc b/src/app-control/util.cc
new file mode 100644 (file)
index 0000000..5d980cf
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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
diff --git a/src/app-control/util.hh b/src/app-control/util.hh
new file mode 100644 (file)
index 0000000..e252ac2
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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_
index 3bfbd19a534a3f4399c14b1bc4a4eefece24bc6c..bb01752e3aedc9fea2c74a0cff4bffe7a3dfbcc4 100644 (file)
@@ -141,9 +141,11 @@ int fake_aul_svc_send_result_AUL_SVC_RET_ERROR(bundle* b,
   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;
 }
 
@@ -1145,8 +1147,8 @@ TEST_F(AppControlTest, app_control_foreach_app_matched_P) {
   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_,
index a53406616c35dc7562456409544f7b4dd7ff4941..0d7524a3b6b9c16aba04ebaddaf40084de1d0662 100644 (file)
@@ -51,9 +51,10 @@ extern "C" int aul_svc_send_result(bundle* b, aul_svc_result_val result) {
   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,
index 73e86b922df8bd3a0e3e728b7a3ef002c51ef0fe..2a3912de6c402fbbb1aac0ef6831631eeba3794a 100644 (file)
@@ -37,8 +37,8 @@ class AulMock : public virtual ModuleMock {
   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,