Merge branch 'tizen_5.0' into tizen_5.5 16/225916/1 accepted/tizen/5.5/unified/20200225.140242 submit/tizen_5.5/20200225.093909
authorPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Tue, 25 Feb 2020 08:22:45 +0000 (09:22 +0100)
committerPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Tue, 25 Feb 2020 09:12:04 +0000 (10:12 +0100)
Change-Id: I87da3bb68de8658d2330fe09dcd736acc5d809dd

1  2 
packaging/webapi-plugins.spec
src/application/application_manager.cc

@@@ -6,11 -6,9 +6,11 @@@
  %define crosswalk_extensions tizen-extensions-crosswalk
  
  %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions}
 +%define tizen_ut_build 0
 +
  
  Name:       webapi-plugins
- Version:    2.59
 -Version:    2.47
++Version:    2.60
  Release:    0
  License:    Apache-2.0 and BSD-3-Clause and MIT
  Group:      Development/Libraries
@@@ -691,9 -689,6 +691,9 @@@ GYP_OPTIONS="--depth=. -Dtizen=1 -Dexte
  GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
  GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
  
 +# ut flags
 +GYP_OPTIONS="$GYP_OPTIONS -Dtizen_ut_build=%{tizen_ut_build}"
 +
  # feature flags
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_mobile_feature_account_support}"
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_mobile_feature_alarm_support}"
@@@ -781,9 -776,6 +781,9 @@@ GYP_OPTIONS="--depth=. -Dtizen=1 -Dexte
  GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
  GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
  
 +# ut flags
 +GYP_OPTIONS="$GYP_OPTIONS -Dtizen_ut_build=%{tizen_ut_build}"
 +
  # feature flags
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_mobile_feature_account_support}"
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_mobile_feature_alarm_support}"
@@@ -859,9 -851,6 +859,9 @@@ GYP_OPTIONS="--depth=. -Dtizen=1 -Dexte
  GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
  GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
  
 +# ut flags
 +GYP_OPTIONS="$GYP_OPTIONS -Dtizen_ut_build=%{tizen_ut_build}"
 +
  # feature flags
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_wearable_feature_account_support}"
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_wearable_feature_alarm_support}"
@@@ -944,9 -933,6 +944,9 @@@ GYP_OPTIONS="--depth=. -Dtizen=1 -Dexte
  GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
  GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
  
 +# ut flags
 +GYP_OPTIONS="$GYP_OPTIONS -Dtizen_ut_build=%{tizen_ut_build}"
 +
  # feature flags
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_wearable_feature_account_support}"
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_wearable_feature_alarm_support}"
@@@ -1022,9 -1008,6 +1022,9 @@@ GYP_OPTIONS="--depth=. -Dtizen=1 -Dexte
  GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
  GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
  
 +# ut flags
 +GYP_OPTIONS="$GYP_OPTIONS -Dtizen_ut_build=%{tizen_ut_build}"
 +
  # feature flags
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_tv_feature_account_support}"
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_tv_feature_alarm_support}"
@@@ -1098,9 -1081,6 +1098,9 @@@ GYP_OPTIONS="--depth=. -Dtizen=1 -Dexte
  GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
  GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
  
 +# ut flags
 +GYP_OPTIONS="$GYP_OPTIONS -Dtizen_ut_build=%{tizen_ut_build}"
 +
  # feature flags
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_common_feature_account_support}"
  GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_common_feature_alarm_support}"
@@@ -1197,13 -1177,6 +1197,13 @@@ install -p -m 644 plugins.json %{buildr
  
  %if "%{?unified_build}" == "1" || "%{?profile}" == "mobile"
  mkdir -p %{buildroot}%{crosswalk_extensions_path}/mobile
 +
 +# tizen ut mobile
 +%if "%{?tizen_ut_build}"  == "1"
 +mkdir -p %{buildroot}/usr/bin
 +install -p -m 755 out/bin_mobile/webapi_common_tests %{buildroot}/usr/bin/
 +%endif
 +
  install -p -m 644 out/bin_mobile/libtizen*.so %{buildroot}%{crosswalk_extensions_path}/mobile
  # execute desc_gentool
  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{crosswalk_extensions_path}/mobile out/Default/desc_gentool \
@@@ -1280,9 -1253,9 +1280,9 @@@ install -p -m 644 plugins.json %{buildr
  
  # devel files
  mkdir -p %{buildroot}%{_libdir}/pkgconfig
 -sed -i s,__LIB_DIR__,%{crosswalk_extensions_path},g packaging/%{name}.pc.in
 -sed -i s,__INCLUDE_DIR__,%{_includedir}/%{name}/src,g packaging/%{name}.pc.in
  cp packaging/%{name}.pc.in %{buildroot}%{_libdir}/pkgconfig/%{name}.pc
 +sed -i s,__LIB_DIR__,%{crosswalk_extensions_path},g %{buildroot}%{_libdir}/pkgconfig/%{name}.pc
 +sed -i s,__INCLUDE_DIR__,%{_includedir}/%{name}/src,g %{buildroot}%{_libdir}/pkgconfig/%{name}.pc
  mkdir -p %{buildroot}%{_includedir}/%{name}/src/common
  mkdir -p %{buildroot}%{_includedir}/%{name}/src/common/filesystem
  install -p -m 644 src/common/*.h %{buildroot}%{_includedir}/%{name}/src/common
@@@ -1292,6 -1265,7 +1292,6 @@@ install -p -m 644 src/common/XW_Extensi
  mkdir -p %{buildroot}%{_includedir}/%{name}/tools
  install -p -m 644 tools/generate_api.py %{buildroot}%{_includedir}/%{name}/tools
  install -p -m 644 tools/mergejs.py %{buildroot}%{_includedir}/%{name}/tools
 -install -p -m 644 tools/js_minimize.py %{buildroot}%{_includedir}/%{name}/tools
  cp -a tools/gyp %{buildroot}%{_includedir}/%{name}/tools/gyp
  cp -a tools/slimit %{buildroot}%{_includedir}/%{name}/tools/slimit
  cp -a out/Default/desc_gentool %{buildroot}%{_includedir}/%{name}/tools/desc_gentool
  %{crosswalk_extensions_path}/mobile/plugins.json
  %manifest webapi-plugins.manifest
  
 +# UT files
 +%if "%{?tizen_ut_build}" == "1"
 +%license GTEST.BSD-3-Clause
 +/usr/bin/webapi_common_tests
 +%endif
 +
  # mobile-extension-emulator
  %ifarch %{ix86} x86_64
  %post mobile-extension-emulator
@@@ -150,7 -150,7 +150,7 @@@ void ApplicationManager::GetCurrentAppl
    picojson::value app_info = picojson::value(picojson::object());
    picojson::object& app_info_obj = app_info.get<picojson::object>();
  
 -  ApplicationUtils::CreateApplicationInformation(handle, &app_info_obj);
 +  utils::CreateApplicationInformation(handle, &app_info_obj);
    pkgmgrinfo_appinfo_destroy_appinfo(handle);
  
    picojson::value result = picojson::value(picojson::object());
@@@ -214,7 -214,7 +214,7 @@@ class TerminateHandler 
      return;                                                        \
    }
  
 -void ApplicationManager::AsyncResponse(PlatformResult& result,
 +void ApplicationManager::AsyncResponse(const PlatformResult& result,
                                         std::shared_ptr<picojson::value>* response) {
    ScopeLogger();
    LogAndReportError(result, &(*response)->get<picojson::object>());
@@@ -376,52 -376,82 +376,52 @@@ void ApplicationManager::Kill(const pic
    kill();
  }
  
 -void ApplicationManager::Launch(const picojson::value& args) {
 +namespace {
 +
 +PlatformResult PrepareAppControlForLaunchAppControl(const picojson::value& args,
 +                                                    app_control_h* app_control) {
    ScopeLogger();
  
 -  int callback_id = -1;
 -  const auto& callback = args.get(kCallbackId);
 -  if (callback.is<double>()) {
 -    callback_id = static_cast<int>(callback.get<double>());
 +  const auto& control = args.get("appControl");
 +  if (!control.is<picojson::object>()) {
 +    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
    }
 +  const picojson::object& app_control_obj = control.get<picojson::object>();
  
 -  std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
 -  picojson::object& obj = response->get<picojson::object>();
 -  obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
 +  app_control_h tmp_app_control = nullptr;
 +  auto result = utils::ApplicationControlToService(app_control_obj, &tmp_app_control);
 +  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
 +      app_control_ptr(tmp_app_control, &app_control_destroy);
  
 -  const auto& app_id = args.get("id");
 -  if (!app_id.is<std::string>()) {
 -    PlatformResult ret =
 -        LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
 -    AsyncResponse(ret, &response);
 -    return;
 +  if (result.IsError()) {
 +    LoggerE("Application control to service failed.");
 +    return result;
    }
 -  const std::string& id = app_id.get<std::string>();
  
 -  auto launch = [id](const std::shared_ptr<picojson::value>& response) -> void {
 -    ScopeLogger("launch");
 -    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
 -    const char* app_id = id.c_str();
 -    const int retry_count = 3;
 +  std::string app_id;
 +  const auto& id = args.get("id");
 +  if (id.is<std::string>()) {
 +    app_id = id.get<std::string>();
 +  }
  
 -    int retry = 0;
 -    int ret = 0;
 +  if (!app_id.empty()) {
 +    LoggerD("app_id: %s", app_id.c_str());
  
 -    while (retry < retry_count) {
 -      ret = aul_open_app(app_id);
 +    int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
  
 -      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);
 +    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) {
 -      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;
 -
 -        case AUL_R_ECOMM:
 -          result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Internal IPC error has occurred.",
 -                                      ("aul_open_app returns internal IPC error"));
 -          break;
 -      }
 -
 -      LogAndReportError(result, &response->get<picojson::object>());
 -    } else {
 -      LoggerD("Launch request success");
 -      ReportSuccess(response->get<picojson::object>());
 -    }
 -  };
 +  *app_control = app_control_ptr.release();
  
 -  launch(response);
 -  Instance::PostMessage(&this->instance_, response->serialize().c_str());
 +  return PlatformResult(ErrorCode::NO_ERROR);
  }
  
 +}  // namespace
 +
  void ApplicationManager::LaunchAppControl(const picojson::value& args) {
    ScopeLogger();
  
    response_obj.insert(
        std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
  
 -  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
 -  const auto& control = args.get("appControl");
 -  if (!control.is<picojson::object>()) {
 -    result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
 -    AsyncResponse(result, &response);
 -    return;
 -  }
 -  const picojson::object& app_control_obj = control.get<picojson::object>();
 -
 -  std::string launch_mode_str;
 -  const auto& launch_mode = control.get("launchMode");
 -  if (launch_mode.is<std::string>()) {
 -    launch_mode_str = launch_mode.get<std::string>();
 -  }
 -
    app_control_h app_control = nullptr;
 -  result = ApplicationUtils::ApplicationControlToService(app_control_obj, &app_control);
 -  std::shared_ptr<std::remove_pointer<app_control_h>::type> app_control_ptr(
 -      app_control, &app_control_destroy);  // automatically release the memory
 -
 -  if (result.IsError()) {
 -    LoggerE("Application control to service failed.");
 -    AsyncResponse(result, &response);
 +  auto prepare_app_control_result = PrepareAppControlForLaunchAppControl(args, &app_control);
 +  if (prepare_app_control_result.IsError()) {
 +    AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
      return;
    }
  
 -  std::string app_id;
 -  const auto& id = args.get("id");
 -  if (id.is<std::string>()) {
 -    app_id = id.get<std::string>();
 -  }
 +  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
 +      app_control_ptr(app_control, &app_control_destroy);
  
 -  std::string reply_callback;
 +  std::string reply_callback_id;
    const auto& reply = args.get("replyCallback");
    if (reply.is<std::string>()) {
 -    reply_callback = reply.get<std::string>();
 +    reply_callback_id = reply.get<std::string>();
    }
  
 -  auto launch = [this, app_control_ptr, app_id, launch_mode_str,
 -                 reply_callback](const std::shared_ptr<picojson::value>& response) -> void {
 -    ScopeLogger("Entered into asynchronous function, launch");
 +  struct LaunchAppControlCallbackData {
 +    ApplicationInstance* instance;
 +    std::shared_ptr<picojson::value> response;
 +    std::string reply_callback_id;
 +  }* launch_app_user_data = new (std::nothrow)
 +      LaunchAppControlCallbackData{&this->instance_, response, reply_callback_id};
 +
 +  if (!launch_app_user_data) {
 +    LoggerE("Memory allocation fail!");
 +    AsyncResponse(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response);
 +    return;
 +  }
  
 -    if (!app_id.empty()) {
 -      LoggerD("app_id: %s", app_id.c_str());
 +  app_control_reply_cb reply_callback = nullptr;
 +  if (!reply_callback_id.empty()) {
 +    launch_app_user_data->reply_callback_id = reply_callback_id;
  
 -      int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
 +    reply_callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
 +                        void* user_data) {
 +      ScopeLogger("reply_callback");
  
 -      if (APP_CONTROL_ERROR_NONE != ret) {
 -        LogAndReportError(
 -            PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
 -            &response->get<picojson::object>(),
 -            ("Failed to set app id: %d (%s)", ret, get_error_message(ret)));
 +      LaunchAppControlCallbackData* callback_data =
 +          static_cast<LaunchAppControlCallbackData*>(user_data);
 +      if (!callback_data) {
 +        LoggerD("reply_callback failed: user_data is nullptr");
          return;
        }
 -    }
  
 -    app_control_reply_cb callback = nullptr;
 -    struct ReplayCallbackData {
 -      ApplicationInstance* app_instance;
 -      std::string reply_callback;
 +      picojson::value return_value = picojson::value(picojson::object());
 +      picojson::object& return_value_obj = return_value.get<picojson::object>();
 +      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 (!utils::ServiceToApplicationControlDataArray(
 +                reply, &return_value_obj.find("data")->second.get<picojson::array>())) {
 +          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;
      };
 +  }
  
 -    ReplayCallbackData* user_data = nullptr;
 +  app_control_result_cb result_callback = [](app_control_h launch_request,
 +                                             app_control_error_e launch_result, void* user_data) {
 +    ScopeLogger("LaunchAppControl result_callback");
  
 -    if (!reply_callback.empty()) {
 -      user_data = new ReplayCallbackData();
 -      user_data->app_instance = &this->instance_;
 -      user_data->reply_callback = reply_callback;
 +    LaunchAppControlCallbackData* callback_data =
 +        static_cast<LaunchAppControlCallbackData*>(user_data);
  
 -      callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
 -                    void* user_data) {
 -        LoggerD("send_launch_request callback");
 +    auto result = utils::TranslateAppControlError(launch_result);
  
 -        picojson::value return_value = picojson::value(picojson::object());
 -        picojson::object& return_value_obj = return_value.get<picojson::object>();
 -        ReplayCallbackData* reply_callback = static_cast<ReplayCallbackData*>(user_data);
 +    if (result.IsError()) {
 +      LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
 +    } else {
 +      ReportSuccess(callback_data->response->get<picojson::object>());
 +    }
  
 -        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<picojson::array>())) {
 -            return_value_obj.erase(data);
 -          }
 -          ReportSuccess(return_value_obj);
 -        } else {
 -          ReportError(return_value_obj);
 -        }
 +    Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
  
 -        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;
 -      };
 +    if (result.IsError() || (callback_data->reply_callback_id).empty()) {
 +      delete callback_data;
      }
 +  };
  
 -    const int retry_count = 3;
 +  /*
 +   * 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 = utils::TranslateAppControlError(
 +      static_cast<app_control_error_e>(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");
 +  }
 +}
  
 -    int retry = 0;
 -    int ret = 0;
 +namespace {
  
 -    while (retry < retry_count) {
 -      LoggerD("Calling launch request. Attempt number: %d", retry);
 +PlatformResult TranslateLaunchError(app_control_error_e return_code) {
 +  ScopeLogger();
  
 -      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;
 -      }
 +  auto result = utils::TranslateAppControlError(return_code);
 +  if (ErrorCode::SECURITY_ERR == result.error_code()) {
 +    result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
 +  }
  
 -      // delay 300ms for each retry
 -      struct timespec sleep_time = {0, 300L * 1000L * 1000L};
 -      nanosleep(&sleep_time, nullptr);
 -      ++retry;
 -    }
 +  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<std::string>()) {
 +    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
 +  }
 +  const auto app_id_str = app_id.get<std::string>();
 +
 +  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::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
 +      app_control_ptr(tmp_app_control, &app_control_destroy);
 +
 +  if (!app_id_str.empty()) {
 +    LoggerD("app_id: %s", app_id_str.c_str());
 +
 +    int ret = app_control_set_app_id(app_control_ptr.get(), app_id_str.c_str());
  
      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<picojson::object>(),
 -              ("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<picojson::object>(),
 -              ("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<picojson::object>(),
 -              ("app_control_send_launch_request returns APP_CONTROL_ERROR_APP_NOT_FOUND"));
 -          return;
 -        default:
 -          LogAndReportError(
 -              PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."),
 -              &response->get<picojson::object>(),
 -              ("app_control_send_launch_request returns: %d (%s)", ret, get_error_message(ret)));
 -          return;
 -      }
 +      LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
 +      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
      }
 -    ReportSuccess(response->get<picojson::object>());
 +  }
 +
 +  *app_control = app_control_ptr.release();
 +
 +  return PlatformResult(ErrorCode::NO_ERROR);
 +}
 +
 +}  // namespace
 +void ApplicationManager::Launch(const picojson::value& args) {
 +  ScopeLogger();
 +
 +  int callback_id = -1;
 +  const auto& callback = args.get(kCallbackId);
 +  if (callback.is<double>()) {
 +    callback_id = static_cast<int>(callback.get<double>());
 +  }
 +
 +  std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
 +  picojson::object& response_obj = response->get<picojson::object>();
 +  response_obj.insert(
 +      std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
 +
 +  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;
 +  }
 +
 +  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
 +      app_control_ptr(app_control, &app_control_destroy);
 +
 +  struct LaunchCallbackData {
 +    ApplicationInstance* instance;
 +    std::shared_ptr<picojson::value> response;
 +  }* launch_user_data = new (std::nothrow) LaunchCallbackData{&this->instance_, response};
 +
 +  app_control_result_cb result_callback = [](app_control_h launch_request,
 +                                             app_control_error_e launch_result, void* user_data) {
 +    ScopeLogger("Launch result_callback");
 +
 +    LaunchCallbackData* callback_data = static_cast<LaunchCallbackData*>(user_data);
 +
 +    auto result = TranslateLaunchError(launch_result);
 +
 +    if (result.IsError()) {
 +      LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
 +    } else {
 +      ReportSuccess(callback_data->response->get<picojson::object>());
 +    }
 +
 +    Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
 +
 +    delete callback_data;
    };
  
 -  launch(response);
 -  Instance::PostMessage(&this->instance_, response->serialize().c_str());
 +  /*
 +   * 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_error_e>(app_control_send_resume_request(
-           app_control_ptr.get(), result_callback, launch_user_data)));
++  auto launch_result = TranslateLaunchError(static_cast<app_control_error_e>(
++      app_control_send_resume_request(app_control_ptr.get(), result_callback, launch_user_data)));
 +
 +  if (launch_result.IsError()) {
 +    delete launch_user_data;
 +    AsyncResponse(launch_result, &response);
 +  } else {
 +    LoggerD("App launched");
 +  }
  }
  
  // internal impl of app_control_foreach_app_matched() for handling APP_CONTROL_ERROR_APP_NOT_FOUND
@@@ -753,7 -714,7 +752,7 @@@ void ApplicationManager::FindAppControl
    const picojson::object& app_control_obj = control.get<picojson::object>();
  
    app_control_h app_control = nullptr;
 -  result = ApplicationUtils::ApplicationControlToService(app_control_obj, &app_control);
 +  result = utils::ApplicationControlToService(app_control_obj, &app_control);
    std::shared_ptr<std::remove_pointer<app_control_h>::type> app_control_ptr(
        app_control, &app_control_destroy);  // automatically release the memory
  
          picojson::array* array = static_cast<picojson::array*>(user_data);
          array->push_back(picojson::value(picojson::object()));
  
 -        ApplicationUtils::CreateApplicationInformation(handle,
 -                                                       &array->back().get<picojson::object>());
 +        utils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
          pkgmgrinfo_appinfo_destroy_appinfo(handle);
        }
  
@@@ -857,7 -819,8 +856,7 @@@ void ApplicationManager::GetAppsContext
        picojson::array* array = static_cast<picojson::array*>(user_data);
        array->push_back(picojson::value(picojson::object()));
  
 -      if (!ApplicationUtils::CreateApplicationContext(app_context,
 -                                                      &array->back().get<picojson::object>())) {
 +      if (!utils::CreateApplicationContext(app_context, &array->back().get<picojson::object>())) {
          array->pop_back();
          return false;
        }
@@@ -933,7 -896,7 +932,7 @@@ void ApplicationManager::GetAppContext(
    }
  
    picojson::value result = picojson::value(picojson::object());
 -  ApplicationUtils::CreateApplicationContext(pid, app_id, &result.get<picojson::object>());
 +  utils::CreateApplicationContext(pid, app_id, &result.get<picojson::object>());
  
    ReportSuccess(result, *out);
  }
@@@ -965,7 -928,8 +964,7 @@@ void ApplicationManager::GetAppsInfo(co
        picojson::array* array = static_cast<picojson::array*>(user_data);
        array->push_back(picojson::value(picojson::object()));
  
 -      ApplicationUtils::CreateApplicationInformation(handle,
 -                                                     &array->back().get<picojson::object>());
 +      utils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
  
        return 0;
      };
@@@ -1004,7 -968,7 +1003,7 @@@ void ApplicationManager::GetAppInfo(con
    }
  
    picojson::value result = picojson::value(picojson::object());
 -  ApplicationUtils::CreateApplicationInformation(handle, &result.get<picojson::object>());
 +  utils::CreateApplicationInformation(handle, &result.get<picojson::object>());
    pkgmgrinfo_appinfo_destroy_appinfo(handle);
  
    ReportSuccess(result, *out);
@@@ -1101,8 -1065,8 +1100,8 @@@ void ApplicationManager::GetAppCerts(co
      picojson::array* array = static_cast<picojson::array*>(user_data);
      array->push_back(picojson::value(picojson::object()));
  
 -    ApplicationUtils::CreateApplicationCertificate(cert_name, cert_value,
 -                                                   &array->back().get<picojson::object>());
 +    utils::CreateApplicationCertificate(cert_name, cert_value,
 +                                        &array->back().get<picojson::object>());
  
      return true;
    };
@@@ -1448,7 -1412,8 +1447,7 @@@ void ApplicationManager::GetAppMetaData
      picojson::array* array = static_cast<picojson::array*>(user_data);
      array->push_back(picojson::value(picojson::object()));
  
 -    ApplicationUtils::CreateApplicationMetaData(meta_key, meta_value,
 -                                                &array->back().get<picojson::object>());
 +    utils::CreateApplicationMetaData(meta_key, meta_value, &array->back().get<picojson::object>());
      return 0;
    };
  
@@@ -1568,7 -1533,8 +1567,7 @@@ class ApplicationListChangedBroker 
              continue;
            }
            auto info = data_obj.insert(std::make_pair(kData, picojson::value(picojson::object())));
 -          ApplicationUtils::CreateApplicationInformation(
 -              handle, &info.first->second.get<picojson::object>());
 +          utils::CreateApplicationInformation(handle, &info.first->second.get<picojson::object>());
            pkgmgrinfo_appinfo_destroy_appinfo(handle);
          } break;
          case Event::kUninstalled:
        return;
      }
  
 -    ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_ALLAPP,
 +    ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_APP_COMPONENT_TYPE_ALL,
                                                  ApplicationIdCallback, this);
      if (PACKAGE_MANAGER_ERROR_NONE != ret) {
        LoggerE("Failed to get application IDs: %d (%s)", ret, get_error_message(ret));