Add a new API for sending launch request synchronously 49/195749/7
authorHwankyu Jhun <h.jhun@samsung.com>
Tue, 18 Dec 2018 00:31:04 +0000 (09:31 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Tue, 8 Jan 2019 09:45:18 +0000 (18:45 +0900)
The functions supports to send the launch request synchronously.
If the callee application is not replied, the function returns
a negative error value.

Adds:
 - app_control_send_launch_request_sync()

Requires:
 - https://review.tizen.org/gerrit/#/c/platform/core/api/app-control/+/195749/
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/aul-1/+/195971/
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/amd/+/196292/

Change-Id: I1cb8dfc7cc74bb76a5c265714afe61a6e46dbed9
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
include/app_control.h
src/app_control.c

index ad694f8..174e7f7 100755 (executable)
@@ -1306,6 +1306,37 @@ int app_control_send_launch_request_async(app_control_h app_control,
                void *user_data);
 
 /**
+ * @brief Sends the launch request synchronously.
+ *
+ * @details The operation is mandatory information for the launch request. \n
+ *          If the operation is not specified, #APP_CONTROL_OPERATION_DEFAULT is used by default.
+ *          If the operation is #APP_CONTROL_OPERATION_DEFAULT, the application ID is mandatory to explicitly launch the application.
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/appmanager.launch
+ * @remarks The function returns #APP_CONTROL_ERROR_LAUNCH_REJECTED if the operation value is #APP_CONTROL_OPERATION_LAUNCH_ON_EVENT, which is only for handling the event from the platform or other applications, refer to the @ref Event Module.
+ * @remarks The platform does not allow launching service applications from packages other than the requesting application's package. Also, implicit launch requests are NOT delivered to service applications since @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif. To launch a service application, an explicit launch request with application ID set by app_control_set_app_id() must be sent.
+ * @remarks If the callee application doesn't respond, the function returns a negative error value.
+ * @remarks The @a reply must be released using app_control_destroy().
+ * @param[in] app_control The app_control handle
+ * @param[out] reply The app_control handle in which the results of the callee are contained
+ * @param[out] result The result code of the launch request
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #APP_CONTROL_ERROR_NONE Successful
+ * @retval #APP_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #APP_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #APP_CONTROL_ERROR_APP_NOT_FOUND The application to run the given launch request is not found
+ * @retval #APP_CONTROL_ERROR_LAUNCH_REJECTED The application cannot be launched in current context
+ * @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
+ * @see app_control_destroy()
+ */
+int app_control_send_launch_request_sync(app_control_h app_control,
+               app_control_h *reply, app_control_result_e *result);
+
+/**
  * @}
  */
 
index 5a3c4e6..99f0241 100644 (file)
@@ -83,6 +83,8 @@ struct launch_request_s {
        app_control_result_cb result_cb;
        app_control_reply_cb reply_cb;
        void *user_data;
+       app_control_h reply;
+       app_control_result_e result;
 };
 
 typedef int (*launch_request_handler)(struct launch_request_s *req);
@@ -168,6 +170,29 @@ int app_control_validate_internal_key(const char *key)
        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)
 {
@@ -190,21 +215,7 @@ static void app_control_request_reply_broker(bundle *appsvc_bundle, int appsvc_r
 
        request_context = appsvc_data;
        request = request_context->app_control;
-
-       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;
-       }
+       result = __get_app_control_result(appsvc_result);
 
        user_data = request_context->user_data;
        reply_cb = request_context->reply_cb;
@@ -938,7 +949,9 @@ static int __send_launch_request(app_control_h app_control,
                .app_control = app_control,
                .result_cb = result_cb,
                .reply_cb = reply_cb,
-               .user_data = user_data
+               .user_data = user_data,
+               .reply = NULL,
+               .result = APP_CONTROL_RESULT_FAILED,
        };
        int ret;
        int i;
@@ -1476,3 +1489,96 @@ int app_control_send_launch_request_async(app_control_h app_control,
 
        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,
+                       request->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;
+
+       if (app_control_create_reply(reply_bundle, &req->reply) != 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);
+       }
+
+       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;
+}
+
+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);
+}