add async launch request result 73/45173/6 accepted/tizen/mobile/20150817.134138 accepted/tizen/tv/20150817.134532 accepted/tizen/wearable/20150817.134813 submit/tizen/20150817.084057 submit/tizen_mobile/20150812.025625
authorJiwoong Im <jiwoong.im@samsung.com>
Mon, 3 Aug 2015 08:32:26 +0000 (17:32 +0900)
committerSangyoon Jang <s89.jang@samsung.com>
Tue, 11 Aug 2015 01:55:46 +0000 (18:55 -0700)
add app_control_enable_launch_result_event() api

Change-Id: I0bf5904c1e119765d8f8e6bad1583d239f3dd989
Signed-off-by: Jiwoong Im <jiwoong.im@samsung.com>
app_control/app_control.c
include/app_control.h

index 33c2352..dfe1af2 100644 (file)
@@ -73,7 +73,7 @@ typedef struct app_control_request_context_s {
 
 extern int appsvc_allow_transient_app(bundle *b, unsigned int id);
 extern int appsvc_request_transient_app(bundle *b, unsigned int callee_id, appsvc_host_res_fn cbfunc, void *data);
-
+extern int aul_invoke_caller_cb(int launch_pid);
 static int app_control_create_reply(bundle *data, struct app_control_s **app_control);
 
 static const char* app_control_error_to_string(app_control_error_e error)
@@ -113,6 +113,9 @@ static const char* app_control_error_to_string(app_control_error_e error)
        case APP_CONTROL_ERROR_TIMED_OUT:
                return "TIMED_OUT";
 
+       case APP_CONTROL_ERROR_IO_ERROR:
+               return "IO ERROR";
+
        default :
                return "UNKNOWN";
        }
@@ -126,7 +129,7 @@ int app_control_error(app_control_error_e error, const char* function, const cha
        }
        else
        {
-               if(error == APP_CONTROL_ERROR_KEY_NOT_FOUND)
+               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);
@@ -353,6 +356,12 @@ int app_control_destroy(app_control_h 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, APPSVC_K_LAUNCH_RESULT_APP_STARTED) == NULL)
+       {
+               aul_remove_caller_cb(app_control->launch_pid);
+       }
+
        bundle_free(app_control->data);
        app_control->data = NULL;
        free(app_control);
@@ -743,6 +752,65 @@ int app_control_get_launch_mode(app_control_h app_control,
        return APP_CONTROL_ERROR_NONE;
 }
 
+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;
+}
+
+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 = 0;
+
+       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);
+       }
+
+       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);
+}
+
 int app_control_send_launch_request(app_control_h app_control, app_control_reply_cb callback, void *user_data)
 {
        const char *operation;
@@ -838,6 +906,24 @@ int app_control_send_launch_request(app_control_h app_control, app_control_reply
        }
 
        app_control->launch_pid = launch_pid;
+       /* app_control_enable_app_started_result_event called */
+       if (bundle_get_val(app_control->data, APPSVC_K_LAUNCH_RESULT_APP_STARTED)) {
+               char callee[255] = {0,};
+               if (aul_app_get_appid_bypid(launch_pid, callee, sizeof(callee)) != AUL_R_OK)
+                       LOGE("aul_app_get_appid_bypid failed: %d", launch_pid);
+
+               if (request_context && request_context->app_control)
+                       request_context->app_control->launch_pid = launch_pid;
+
+               aul_add_caller_cb(launch_pid, __handle_launch_result, request_context);
+
+               /* launched without app selector */
+               if (strncmp(callee, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
+                       aul_invoke_caller_cb(launch_pid);
+
+       } else { /* default case */
+               aul_add_caller_cb(launch_pid, __update_launch_pid, app_control);
+       }
 
        return APP_CONTROL_ERROR_NONE;
 }
@@ -850,7 +936,7 @@ int app_control_send_terminate_request(app_control_h 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)
+       if (app_control->type != APP_CONTROL_TYPE_REQUEST || app_control->launch_pid < 0)
        {
                return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
        }
@@ -907,6 +993,11 @@ int app_control_reply_to_launch_request(app_control_h reply, app_control_h reque
                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");
+       }
+
        if (appsvc_create_result_bundle(request->data, &reply_data) != 0)
        {
                return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create a result bundle");
@@ -1133,7 +1224,7 @@ int app_control_is_extra_data_array(app_control_h app_control, const char *key,
        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");
-\r      }
+       }
 
        if (!appsvc_data_is_array(app_control->data, key))
        {
@@ -1378,7 +1469,6 @@ int app_control_export_as_bundle(app_control_h app_control, bundle **data)
        return APP_CONTROL_ERROR_NONE;
 }
 
-
 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;
@@ -1398,3 +1488,21 @@ int app_control_request_transient_app(app_control_h app_control, unsigned int ca
        return APP_CONTROL_ERROR_NONE;
 }
 
+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, APPSVC_K_LAUNCH_RESULT_APP_STARTED);
+
+       if (ret < 0)
+       {
+               return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+       }
+
+       return APP_CONTROL_ERROR_NONE;
+}
index be6427e..b39fe84 100644 (file)
@@ -67,13 +67,15 @@ typedef enum
 
 /**
  * @brief Enumeration for App Control Result.
+ * @see app_control_enable_app_started_result_event()
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  */
 typedef enum
 {
+       APP_CONTROL_RESULT_APP_STARTED = 1, /**< Callee application launched actually (Since 2.4) */
        APP_CONTROL_RESULT_SUCCEEDED = 0, /**< Operation succeeded */
        APP_CONTROL_RESULT_FAILED = -1, /**< Operation failed by the callee */
-       APP_CONTROL_RESULT_CANCELED = -2, /**< Operation canceled by the framework */
+       APP_CONTROL_RESULT_CANCELED = -2, /**< Operation canceled by the platform */
 } app_control_result_e;
 
 /**
@@ -81,8 +83,8 @@ typedef enum
  * @since_tizen 2.4
  */
 typedef enum {
-       APP_CONTROL_LAUNCH_MODE_SINGLE = 0,
-       APP_CONTROL_LAUNCH_MODE_GROUP,
+       APP_CONTROL_LAUNCH_MODE_SINGLE = 0, /**< Prefer to launch an application as single mode */
+       APP_CONTROL_LAUNCH_MODE_GROUP, /**< Prefer to launch an application as group mode */
 } app_control_launch_mode_e;
 
 /**
@@ -288,8 +290,12 @@ typedef enum {
  * @param[in] result The result code of the launch request
  * @param[in] user_data        The user data passed from the callback registration function
  * @pre When the callee replies to the launch request, this callback will be invoked.
+ * @pre Since 2.4, if #APP_CONTROL_RESULT_APP_STARTED event is enabled,
+ *      this callback also will be invoked when the callee app actually launched.
  * @see app_control_send_launch_request()
  * @see app_control_reply_to_launch_request()
+ * @see app_control_enable_app_started_result_event()
+ * @see #APP_CONTROL_RESULT_APP_STARTED
  */
 typedef void (*app_control_reply_cb) (app_control_h request, app_control_h reply, app_control_result_e result, void *user_data);
 
@@ -725,9 +731,10 @@ int app_control_foreach_app_matched(app_control_h app_control, app_control_app_m
  * @retval #APP_CONTROL_ERROR_LAUNCH_FAILED Failed to launch the application
  * @retval #APP_CONTROL_ERROR_TIMED_OUT Failed due to timeout. The application that handles @a app_control may be busy
  * @retval #APP_CONTROL_ERROR_PERMISSION_DENIED Permission denied
- * @post If the launch request is sent for the result, the result will come back through app_control_reply_cb() from the callee application.
+ * @post If the launch request is sent for the result, the result will come back through app_control_reply_cb() from the callee application. Additional replies may be delivered on app_control_enable_app_started_result_event() called.
  * @see app_control_reply_to_launch_request()
  * @see app_control_reply_cb()
+ * @see app_control_enable_app_started_result_event()
  */
 int app_control_send_launch_request(app_control_h app_control, app_control_reply_cb callback, void *user_data);
 
@@ -735,6 +742,9 @@ int app_control_send_launch_request(app_control_h app_control, app_control_reply
 /**
  * @brief Sends the terminate request to the application that is launched by app_control. This API is only effective for some applications that are provided by default for handling platform default app_controls. You are not allowed to terminate other general applications using this API.
  *
+ * @remarks Since Tizen 2.4, this API can be used to terminate sub-applications which were launched as group mode by caller application.
+ *          Once callee application is being terminated by this API, other applications which were launched by callee application as group mode will be terminated as well.
+ *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @param[in] app_control The app_control handle
  * @return @c 0 on success,
@@ -743,6 +753,7 @@ int app_control_send_launch_request(app_control_h app_control, app_control_reply
  * @retval #APP_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #APP_CONTROL_ERROR_PERMISSION_DENIED Permission denied
  * @see app_control_send_launch_request()
+ * @see app_control_set_launch_mode()
  */
 int app_control_send_terminate_request(app_control_h app_control);
 
@@ -752,6 +763,7 @@ int app_control_send_terminate_request(app_control_h app_control);
  * @details If the caller application sent the launch request to receive the result, the callee application can return the result back to the caller.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @remarks The function is not allowed to send reply #APP_CONTROL_RESULT_APP_STARTED as @a result which is reserved for platform developers.
  * @param[in] reply The app_control handle in which the results of the callee are contained
  * @param[in] request The app_control handle sent by the caller
  * @param[in] result  The result code of the launch request
@@ -821,6 +833,11 @@ int app_control_is_reply_requested(app_control_h app_control, bool *requested);
 /**
  * @brief Sets the launch mode of the application.
  *
+ * @details This function allows callee application to be launched as group or single mode.
+ * @remarks Although launch_mode were set as #APP_CONTROL_LAUNCH_MODE_GROUP, callee application would be launched as single mode if the manifest file of callee application defined the launch mode as "single".
+ *          This function can just set the preference of caller application to launch an application.
+ * @remarks Sub-applications which were launched as group mode always have own process.
+ *
  * @since_tizen 2.4
  * @param[in] app_control The app_control handle
  * @param[in] launch_mode The launch mode of app
@@ -849,6 +866,22 @@ int app_control_set_launch_mode(app_control_h app_control,
  */
 int app_control_get_launch_mode(app_control_h app_control,
                app_control_launch_mode_e *mode);
+
+/**
+ * @brief Enables additional launch result event on launch request.
+ *
+ * @details The function allows to receive #APP_CONTROL_RESULT_APP_STARTED event on\n
+ *         application get launched by app_control.
+ * @remarks app_control_reply_cb() will be called on APP_CONTROL_RESULT_APP_STARTED event received.
+ * @since_tizen 2.4
+ * @param[in] app_control The app_control handle
+ * @return 0 on success, otherwise a negative error value
+ * @retval #APP_CONTROL_ERROR_NONE Successful
+ * @retval #APP_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see app_control_send_launch_request()
+ * @see #APP_CONTROL_RESULT_APP_STARTED
+ */
+int app_control_enable_app_started_result_event(app_control_h app_control);
 /**
  * @}
  */