From 4aecb708fbac8999655041d200d8924e2f25bfbe Mon Sep 17 00:00:00 2001
From: "Piotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics"
Date: Fri, 21 Feb 2020 14:39:13 +0100
Subject: [PATCH] Revert "[Application] Make launch() and launchAppControl()
asynchronous"
This reverts commit b6cff5d0cf62f059dc2cf5e64208d05794d31f5d.
[Verification]
TCT application - 100%
TCT deprecated - 100%
Change-Id: I1d1c42cfa5c5731ce329525b7007127b56de796b
---
src/application/application_manager.cc | 401 +++++++++++++++------------------
src/application/application_manager.h | 3 +-
2 files changed, 182 insertions(+), 222 deletions(-)
diff --git a/src/application/application_manager.cc b/src/application/application_manager.cc
index a4b3057..74273f7 100644
--- a/src/application/application_manager.cc
+++ b/src/application/application_manager.cc
@@ -214,7 +214,7 @@ class TerminateHandler {
return; \
}
-void ApplicationManager::AsyncResponse(const PlatformResult& result,
+void ApplicationManager::AsyncResponse(PlatformResult& result,
std::shared_ptr* response) {
ScopeLogger();
LogAndReportError(result, &(*response)->get());
@@ -376,51 +376,81 @@ void ApplicationManager::Kill(const picojson::value& args) {
kill();
}
-namespace {
-
-PlatformResult PrepareAppControlForLaunchAppControl(const picojson::value& args,
- app_control_h* app_control) {
+void ApplicationManager::Launch(const picojson::value& args) {
ScopeLogger();
- const auto& control = args.get("appControl");
- if (!control.is()) {
- return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+ int callback_id = -1;
+ const auto& callback = args.get(kCallbackId);
+ if (callback.is()) {
+ callback_id = static_cast(callback.get());
}
- const picojson::object& app_control_obj = control.get();
- app_control_h tmp_app_control = nullptr;
- auto result = ApplicationUtils::ApplicationControlToService(app_control_obj, &tmp_app_control);
- std::unique_ptr::type, decltype(&app_control_destroy)>
- app_control_ptr(tmp_app_control, &app_control_destroy);
+ std::shared_ptr response(new picojson::value(picojson::object()));
+ picojson::object& obj = response->get();
+ obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast(callback_id))));
- if (result.IsError()) {
- LoggerE("Application control to service failed.");
- return result;
+ const auto& app_id = args.get("id");
+ if (!app_id.is()) {
+ PlatformResult ret =
+ LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+ AsyncResponse(ret, &response);
+ return;
}
+ const std::string& id = app_id.get();
- std::string app_id;
- const auto& id = args.get("id");
- if (id.is()) {
- app_id = id.get();
- }
+ auto launch = [id](const std::shared_ptr& response) -> void {
+ ScopeLogger("launch");
+ PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+ const char* app_id = id.c_str();
+ const int retry_count = 3;
- if (!app_id.empty()) {
- LoggerD("app_id: %s", app_id.c_str());
+ int retry = 0;
+ int ret = 0;
- int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
+ while (retry < retry_count) {
+ ret = aul_open_app(app_id);
- if (APP_CONTROL_ERROR_NONE != ret) {
- LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
- return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+ if (ret >= 0) {
+ break;
+ }
+
+ // delay 300ms for each retry
+ struct timespec sleep_time = {0, 300L * 1000L * 1000L};
+ nanosleep(&sleep_time, nullptr);
+ ++retry;
+
+ LoggerD("Retry launch request: %d", retry);
}
- }
- *app_control = app_control_ptr.release();
+ if (ret < 0) {
+ result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error has occurred.");
+
+ LoggerD("Aul open return: %d (%s)", ret, get_error_message(ret));
+ switch (ret) {
+ case AUL_R_EINVAL:
+ case AUL_R_ERROR:
+ case AUL_R_ENOAPP:
+ result =
+ LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Launchpad returns not found error.",
+ ("aul_open_app returns Not Found error"));
+ break;
- return PlatformResult(ErrorCode::NO_ERROR);
-}
+ case AUL_R_ECOMM:
+ result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Internal IPC error has occurred.",
+ ("aul_open_app returns internal IPC error"));
+ break;
+ }
-} // namespace
+ LogAndReportError(result, &response->get());
+ } else {
+ LoggerD("Launch request success");
+ ReportSuccess(response->get());
+ }
+ };
+
+ launch(response);
+ Instance::PostMessage(&this->instance_, response->serialize().c_str());
+}
void ApplicationManager::LaunchAppControl(const picojson::value& args) {
ScopeLogger();
@@ -436,227 +466,158 @@ void ApplicationManager::LaunchAppControl(const picojson::value& args) {
response_obj.insert(
std::make_pair(kCallbackId, picojson::value(static_cast(callback_id))));
- app_control_h app_control = nullptr;
- auto prepare_app_control_result = PrepareAppControlForLaunchAppControl(args, &app_control);
- if (prepare_app_control_result.IsError()) {
- AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
+ PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+ const auto& control = args.get("appControl");
+ if (!control.is()) {
+ result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+ AsyncResponse(result, &response);
return;
}
+ const picojson::object& app_control_obj = control.get();
- std::unique_ptr::type, decltype(&app_control_destroy)>
- app_control_ptr(app_control, &app_control_destroy);
-
- std::string reply_callback_id;
- const auto& reply = args.get("replyCallback");
- if (reply.is()) {
- reply_callback_id = reply.get();
+ std::string launch_mode_str;
+ const auto& launch_mode = control.get("launchMode");
+ if (launch_mode.is()) {
+ launch_mode_str = launch_mode.get();
}
- struct LaunchAppControlCallbackData {
- ApplicationInstance* instance;
- std::shared_ptr response;
- std::string reply_callback_id;
- }* launch_app_user_data = new (std::nothrow)
- LaunchAppControlCallbackData{&this->instance_, response, reply_callback_id};
+ app_control_h app_control = nullptr;
+ result = ApplicationUtils::ApplicationControlToService(app_control_obj, &app_control);
+ std::shared_ptr::type> app_control_ptr(
+ app_control, &app_control_destroy); // automatically release the memory
- if (!launch_app_user_data) {
- LoggerE("Memory allocation fail!");
- AsyncResponse(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response);
+ if (result.IsError()) {
+ LoggerE("Application control to service failed.");
+ AsyncResponse(result, &response);
return;
}
- app_control_reply_cb reply_callback = nullptr;
- if (!reply_callback_id.empty()) {
- launch_app_user_data->reply_callback_id = reply_callback_id;
-
- reply_callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
- void* user_data) {
- ScopeLogger("reply_callback");
-
- LaunchAppControlCallbackData* callback_data =
- static_cast(user_data);
- if (!callback_data) {
- LoggerD("reply_callback failed: user_data is nullptr");
- return;
- }
-
- picojson::value return_value = picojson::value(picojson::object());
- picojson::object& return_value_obj = return_value.get();
- return_value_obj.insert(
- std::make_pair(kListenerId, picojson::value(callback_data->reply_callback_id)));
-
- if (APP_CONTROL_RESULT_SUCCEEDED == result) {
- LoggerD("App started");
- return_value_obj.insert(std::make_pair("data", picojson::value(picojson::array())));
- if (!ApplicationUtils::ServiceToApplicationControlDataArray(
- reply, &return_value_obj.find("data")->second.get())) {
- return_value_obj.erase("data");
- }
- ReportSuccess(return_value_obj);
- } else {
- ReportError(return_value_obj);
- }
-
- Instance::PostMessage(callback_data->instance, return_value.serialize().c_str());
- delete callback_data;
- };
- }
-
- app_control_result_cb result_callback = [](app_control_h launch_request,
- app_control_error_e launch_result, void* user_data) {
- ScopeLogger("LaunchAppControl result_callback");
-
- LaunchAppControlCallbackData* callback_data =
- static_cast(user_data);
-
- auto result = ApplicationUtils::TranslateAppControlError(launch_result);
-
- if (result.IsError()) {
- LogAndReportError(result, &(callback_data->response->get()));
- } else {
- ReportSuccess(callback_data->response->get());
- }
-
- Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
-
- if (result.IsError() || (callback_data->reply_callback_id).empty()) {
- delete callback_data;
- }
- };
-
- /*
- * TODO: Observe how often app_control_send_launch_request_async tries to launch the application.
- * Previous implementation, using synchronous app_control_send_launch_request,
- * tries to launch the application 3 times, before reporting an error.
- * New implementation, using app_control_send_launch_request_async makes only one attempt.
- * If problems, such as failed application start occur, multiple attempts may solve the problem.
- */
- auto launch_result = ApplicationUtils::TranslateAppControlError(
- static_cast(app_control_send_launch_request_async(
- app_control_ptr.get(), result_callback, reply_callback, launch_app_user_data)));
-
- if (launch_result.IsError()) {
- delete launch_app_user_data;
- AsyncResponse(launch_result, &response);
- } else {
- LoggerD("App launched");
- }
-}
-
-namespace {
-
-PlatformResult TranslateLaunchError(app_control_error_e return_code) {
- ScopeLogger();
-
- auto result = ApplicationUtils::TranslateAppControlError(return_code);
- if (ErrorCode::SECURITY_ERR == result.error_code()) {
- result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
- }
-
- return result;
-}
-
-PlatformResult PrepareAppControlForLaunch(const picojson::value& args, app_control_h* app_control) {
- ScopeLogger();
-
- const auto& app_id = args.get("id");
- if (!app_id.is()) {
- return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+ std::string app_id;
+ const auto& id = args.get("id");
+ if (id.is()) {
+ app_id = id.get();
}
- const auto app_id_str = app_id.get();
- app_control_h tmp_app_control = nullptr;
- int result = app_control_create(&tmp_app_control);
- if (APP_CONTROL_ERROR_NONE != result) {
- LoggerD("app_control_create() failed: %d (%s)", result, get_error_message(result));
- return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
+ std::string reply_callback;
+ const auto& reply = args.get("replyCallback");
+ if (reply.is()) {
+ reply_callback = reply.get();
}
- std::unique_ptr::type, decltype(&app_control_destroy)>
- app_control_ptr(tmp_app_control, &app_control_destroy);
+ auto launch = [this, app_control_ptr, app_id, launch_mode_str,
+ reply_callback](const std::shared_ptr& response) -> void {
+ ScopeLogger("Entered into asynchronous function, launch");
- if (!app_id_str.empty()) {
- LoggerD("app_id: %s", app_id_str.c_str());
+ if (!app_id.empty()) {
+ LoggerD("app_id: %s", app_id.c_str());
- int ret = app_control_set_app_id(app_control_ptr.get(), app_id_str.c_str());
+ int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
- if (APP_CONTROL_ERROR_NONE != ret) {
- LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
- return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+ if (APP_CONTROL_ERROR_NONE != ret) {
+ LogAndReportError(
+ PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
+ &response->get(),
+ ("Failed to set app id: %d (%s)", ret, get_error_message(ret)));
+ return;
+ }
}
- }
- *app_control = app_control_ptr.release();
+ app_control_reply_cb callback = nullptr;
+ struct ReplayCallbackData {
+ ApplicationInstance* app_instance;
+ std::string reply_callback;
+ };
- return PlatformResult(ErrorCode::NO_ERROR);
-}
+ ReplayCallbackData* user_data = nullptr;
-} // namespace
-void ApplicationManager::Launch(const picojson::value& args) {
- ScopeLogger();
+ if (!reply_callback.empty()) {
+ user_data = new ReplayCallbackData();
+ user_data->app_instance = &this->instance_;
+ user_data->reply_callback = reply_callback;
- int callback_id = -1;
- const auto& callback = args.get(kCallbackId);
- if (callback.is()) {
- callback_id = static_cast(callback.get());
- }
+ callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
+ void* user_data) {
+ LoggerD("send_launch_request callback");
- std::shared_ptr response(new picojson::value(picojson::object()));
- picojson::object& response_obj = response->get();
- response_obj.insert(
- std::make_pair(kCallbackId, picojson::value(static_cast(callback_id))));
+ picojson::value return_value = picojson::value(picojson::object());
+ picojson::object& return_value_obj = return_value.get();
+ ReplayCallbackData* reply_callback = static_cast(user_data);
- app_control_h app_control = nullptr;
- auto prepare_app_control_result = PrepareAppControlForLaunch(args, &app_control);
- if (prepare_app_control_result.IsError()) {
- AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
- return;
- }
+ if (APP_CONTROL_RESULT_SUCCEEDED == result) {
+ const std::string data = "data";
+ return_value_obj.insert(std::make_pair(data, picojson::value(picojson::array())));
+ if (!ApplicationUtils::ServiceToApplicationControlDataArray(
+ reply, &return_value_obj.find(data)->second.get())) {
+ return_value_obj.erase(data);
+ }
+ ReportSuccess(return_value_obj);
+ } else {
+ ReportError(return_value_obj);
+ }
- std::unique_ptr::type, decltype(&app_control_destroy)>
- app_control_ptr(app_control, &app_control_destroy);
+ return_value_obj.insert(
+ std::make_pair("listenerId", picojson::value(reply_callback->reply_callback)));
+ Instance::PostMessage(reply_callback->app_instance, return_value.serialize().c_str());
+ delete reply_callback;
+ };
+ }
- struct LaunchCallbackData {
- ApplicationInstance* instance;
- std::shared_ptr response;
- }* launch_user_data = new (std::nothrow) LaunchCallbackData{&this->instance_, response};
+ const int retry_count = 3;
- app_control_result_cb result_callback = [](app_control_h launch_request,
- app_control_error_e launch_result, void* user_data) {
- ScopeLogger("Launch result_callback");
+ int retry = 0;
+ int ret = 0;
- LaunchCallbackData* callback_data = static_cast(user_data);
+ while (retry < retry_count) {
+ LoggerD("Calling launch request. Attempt number: %d", retry);
- auto result = TranslateLaunchError(launch_result);
+ ret = app_control_send_launch_request(app_control_ptr.get(), callback, user_data);
+ LoggerD("App control launch request returned: %d, %s", ret, get_error_message(ret));
+ if (APP_CONTROL_ERROR_NONE == ret) {
+ break;
+ }
- if (result.IsError()) {
- LogAndReportError(result, &(callback_data->response->get()));
- } else {
- ReportSuccess(callback_data->response->get());
+ // delay 300ms for each retry
+ struct timespec sleep_time = {0, 300L * 1000L * 1000L};
+ nanosleep(&sleep_time, nullptr);
+ ++retry;
}
- Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
-
- delete callback_data;
+ if (APP_CONTROL_ERROR_NONE != ret) {
+ delete user_data;
+
+ switch (ret) {
+ case APP_CONTROL_ERROR_INVALID_PARAMETER:
+ LogAndReportError(
+ PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter returned."),
+ &response->get(),
+ ("app_control_send_launch_request returns APP_CONTROL_ERROR_INVALID_PARAMETER"));
+ return;
+ case APP_CONTROL_ERROR_OUT_OF_MEMORY:
+ LogAndReportError(
+ PlatformResult(ErrorCode::UNKNOWN_ERR, "Out of memory."),
+ &response->get(),
+ ("app_control_send_launch_request returns APP_CONTROL_ERROR_OUT_OF_MEMORY"));
+ return;
+ case APP_CONTROL_ERROR_LAUNCH_REJECTED:
+ case APP_CONTROL_ERROR_APP_NOT_FOUND:
+ LogAndReportError(
+ PlatformResult(ErrorCode::NOT_FOUND_ERR, "No matched application found."),
+ &response->get(),
+ ("app_control_send_launch_request returns APP_CONTROL_ERROR_APP_NOT_FOUND"));
+ return;
+ default:
+ LogAndReportError(
+ PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."),
+ &response->get(),
+ ("app_control_send_launch_request returns: %d (%s)", ret, get_error_message(ret)));
+ return;
+ }
+ }
+ ReportSuccess(response->get());
};
- /*
- * TODO: Observe how often app_control_send_launch_request_async tries to launch the application.
- * Previous implementation, using synchronous app_control_send_launch_request,
- * tries to launch the application 3 times, before reporting an error.
- * New implementation, using app_control_send_launch_request_async makes only one attempt.
- * If problems, such as failed application start occur, multiple attempts may solve the problem.
- */
- auto launch_result =
- TranslateLaunchError(static_cast(app_control_send_launch_request_async(
- app_control_ptr.get(), result_callback, nullptr, launch_user_data)));
-
- if (launch_result.IsError()) {
- delete launch_user_data;
- AsyncResponse(launch_result, &response);
- } else {
- LoggerD("App launched");
- }
+ launch(response);
+ Instance::PostMessage(&this->instance_, response->serialize().c_str());
}
// internal impl of app_control_foreach_app_matched() for handling APP_CONTROL_ERROR_APP_NOT_FOUND
diff --git a/src/application/application_manager.h b/src/application/application_manager.h
index be0ebbf..c1fa8ad 100644
--- a/src/application/application_manager.h
+++ b/src/application/application_manager.h
@@ -64,8 +64,7 @@ class ApplicationManager {
void StartAppInfoEventListener(picojson::object* out);
void StopAppInfoEventListener();
void GetApplicationInformationSize(const picojson::value& args, picojson::object* out);
- void AsyncResponse(const common::PlatformResult& result,
- std::shared_ptr* response);
+ void AsyncResponse(common::PlatformResult& result, std::shared_ptr* response);
void BroadcastEventHelper(const picojson::value& args, picojson::object& out, bool trusted);
common::PlatformResult StartEventListener(const std::string& event_name,
--
2.7.4