From ef0571c11b527d542309cfe19d8f6182217ba6e9 Mon Sep 17 00:00:00 2001 From: wangzhen Date: Sat, 21 Jun 2025 14:09:37 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=96=B0=E5=A2=9EStartAbilities=5Fbase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangzhen Change-Id: I6ca5c4ef00248f50f2c8af9dd41b5808edf3ab98 --- .../service_extension_context.js | 7 +- .../ui_extension_context.js | 7 +- .../native/js_service_extension_context.cpp | 84 +++++++ .../js_ui_extension_context.cpp | 84 +++++++ .../ui_extension_context.cpp | 10 + .../service_extension_context.cpp | 10 + .../include/ability_manager_client.h | 11 + .../include/ability_manager_errors.h | 28 +++ .../include/ability_manager_interface.h | 14 ++ .../ability_manager_ipc_interface_code.h | 2 + .../js_ui_extension_context.h | 3 + .../ui_extension_base/ui_extension_context.h | 2 + .../service_extension_context.h | 2 + .../include/ability_manager_proxy.h | 11 + .../include/ability_manager_service.h | 19 ++ .../abilitymgr/include/ability_manager_stub.h | 1 + .../ui_ability_lifecycle_manager.h | 14 ++ .../include/utils/start_ability_utils.h | 3 +- .../abilitymgr/src/ability_manager_client.cpp | 13 + .../abilitymgr/src/ability_manager_proxy.cpp | 50 ++++ .../src/ability_manager_service.cpp | 228 ++++++++++++++++++ .../abilitymgr/src/ability_manager_stub.cpp | 36 +++ .../ui_ability_lifecycle_manager.cpp | 135 +++++++++++ .../src/utils/start_ability_utils.cpp | 10 + services/common/include/app_utils.h | 8 + services/common/src/app_utils.cpp | 11 + 26 files changed, 800 insertions(+), 3 deletions(-) diff --git a/frameworks/js/napi/service_extension_context/service_extension_context.js b/frameworks/js/napi/service_extension_context/service_extension_context.js index c81ba0f5120..67dfc6e56b3 100644 --- a/frameworks/js/napi/service_extension_context/service_extension_context.js +++ b/frameworks/js/napi/service_extension_context/service_extension_context.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device 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 @@ -79,6 +79,11 @@ class ServiceExtensionContext extends ExtensionContext { return this.__context_impl__.startServiceExtensionAbilityWithAccount(want, accountId, callback); } + startAbilities(wantList) { + hilog.sLogI(domainID, TAG, 'startAbilities'); + return this.__context_impl__.startAbilities(wantList); + } + stopServiceExtensionAbility(want, callback) { hilog.sLogI(domainID, TAG, 'stopServiceExtensionAbility'); return this.__context_impl__.stopServiceExtensionAbility(want, callback); diff --git a/frameworks/js/napi/ui_extension_context/ui_extension_context.js b/frameworks/js/napi/ui_extension_context/ui_extension_context.js index cae8c4be3b5..b7892770f8a 100755 --- a/frameworks/js/napi/ui_extension_context/ui_extension_context.js +++ b/frameworks/js/napi/ui_extension_context/ui_extension_context.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device 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 @@ -71,6 +71,11 @@ class UIExtensionContext extends ExtensionContext { return this.__context_impl__.startAbilityForResultAsCaller(want, options, callback); } + startAbilities(wantList) { + hilog.sLogI(domainID, TAG, 'startAbilities'); + return this.__context_impl__.startAbilities(wantList); + } + terminateSelfWithResult(abilityResult, callback) { hilog.sLogI(domainID, TAG, 'terminateSelfWithResult'); return this.__context_impl__.terminateSelfWithResult(abilityResult, callback); diff --git a/frameworks/native/ability/native/js_service_extension_context.cpp b/frameworks/native/ability/native/js_service_extension_context.cpp index 7cb500eb22b..bc867e5164d 100644 --- a/frameworks/native/ability/native/js_service_extension_context.cpp +++ b/frameworks/native/ability/native/js_service_extension_context.cpp @@ -45,6 +45,7 @@ constexpr int32_t INDEX_ZERO = 0; constexpr int32_t INDEX_ONE = 1; constexpr int32_t INDEX_TWO = 2; constexpr int32_t INDEX_THREE = 3; +constexpr int32_t INDEX_FOUR = 4; constexpr int32_t ERROR_CODE_ONE = 1; constexpr int32_t ERROR_CODE_TWO = 2; constexpr size_t ARGC_ZERO = 0; @@ -128,6 +129,11 @@ public: GET_NAPI_INFO_AND_CALL(env, info, JsServiceExtensionContext, OnStartAbilityWithAccount); } + static napi_value StartAbilities(napi_env env, napi_callback_info info) + { + GET_NAPI_INFO_AND_CALL(env, info, JsServiceExtensionContext, OnStartAbilities); + } + static napi_value ConnectAbilityWithAccount(napi_env env, napi_callback_info info) { GET_NAPI_INFO_AND_CALL(env, info, JsServiceExtensionContext, OnConnectAbilityWithAccount); @@ -809,6 +815,83 @@ private: return true; } + napi_value OnStartAbilities(napi_env env, NapiCallbackInfo& info) + { + TAG_LOGI(AAFwkTag::UI_EXT, "call OnStartAbilities"); + if (info.argc < ARGC_ONE) { + TAG_LOGE(AAFwkTag::UI_EXT, "Too few parameters."); + ThrowTooFewParametersError(env); + return CreateJsUndefined(env); + } + + std::vector wantList; + std::string requestKey = std::to_string(std::chrono::duration_cast(std::chrono:: + system_clock::now().time_since_epoch()).count()); + + if (!UnwrapWantList(env, info, wantList)) { + TAG_LOGE(AAFwkTag::UI_EXT, "Unwrap wantList param failed."); + return CreateJsUndefined(env); + } + + TAG_LOGD(AAFwkTag::UI_EXT, "startAbilities wantListLength: %{public}zu", wantList.size()); + + napi_value result = nullptr; + auto innerErrCode = std::make_shared(ERR_OK); + NapiAsyncTask::ExecuteCallback execute = [weak = context_, wantList, requestKey, innerErrCode]() { + auto context = weak.lock(); + if (!context) { + TAG_LOGW(AAFwkTag::UI_EXT, "null context"); + *innerErrCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + *innerErrCode = context->StartAbilities(wantList, requestKey); + }; + + NapiAsyncTask::CompleteCallback complete = [innerErrCode, weak = context_] + (napi_env env, NapiAsyncTask& task, int32_t status) { + TAG_LOGI(AAFwkTag::UI_EXT, "startAbilities complete innerErrCode: %{public}d", *innerErrCode); + if (*innerErrCode == 0) { + task.Resolve(env, CreateJsUndefined(env)); + return; + } + task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode)); + }; + + NapiAsyncTask::ScheduleHighQos("JSUIExtensionConnection::OnStartAbilities", env, + CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result)); + return result; + } + + bool UnwrapWantList(napi_env env, NapiCallbackInfo &info, std::vector &wantList) + { + AppExecFwk::ComplexArrayData jsWantList; + if (!AppExecFwk::UnwrapArrayComplexFromJS(env, info.argv[INDEX_ZERO], jsWantList)) { + TAG_LOGE(AAFwkTag::UI_EXT, "wantList not array."); + ThrowInvalidParamError(env, "wantList not array"); + return false; + } + + size_t jsWantSize = jsWantList.objectList.size(); + if (jsWantSize < INDEX_ONE || jsWantSize > INDEX_FOUR) { + TAG_LOGE(AAFwkTag::UI_EXT, "wantList size not support"); + ThrowInvalidParamError(env, "wantList size error"); + return false; + } + + for (uint32_t index = 0; index < jsWantSize; index++) { + AAFwk::Want curWant; + if (!OHOS::AppExecFwk::UnwrapWant(env, jsWantList.objectList[index], curWant)) { + TAG_LOGE(AAFwkTag::UI_EXT, "startAbilities parse want failed"); + ThrowInvalidParamError(env, "parse want error"); + return false; + } + TAG_LOGD(AAFwkTag::UI_EXT, "startAbilities ability:%{public}s", + curWant.GetElement().GetAbilityName().c_str()); + wantList.emplace_back(curWant); + } + return true; + } + bool CheckConnectAbilityWithAccountInputParam( napi_env env, NapiCallbackInfo& info, AAFwk::Want& want, int32_t& accountId, sptr& connection) const @@ -1470,6 +1553,7 @@ napi_value CreateJsServiceExtensionContext(napi_env env, std::shared_ptr wantList; + std::string requestKey = std::to_string(std::chrono::duration_cast(std::chrono:: + system_clock::now().time_since_epoch()).count()); + + if (!UnwrapWantList(env, info, wantList)) { + TAG_LOGE(AAFwkTag::UI_EXT, "Unwrap wantList param failed."); + return CreateJsUndefined(env); + } + + TAG_LOGD(AAFwkTag::UI_EXT, "startAbilities wantListLength: %{public}zu", wantList.size()); + + napi_value result = nullptr; + auto innerErrCode = std::make_shared(ERR_OK); + NapiAsyncTask::ExecuteCallback execute = [weak = context_, wantList, requestKey, innerErrCode]() { + auto context = weak.lock(); + if (!context) { + TAG_LOGW(AAFwkTag::UI_EXT, "null context"); + *innerErrCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + *innerErrCode = context->StartAbilities(wantList, requestKey); + }; + + NapiAsyncTask::CompleteCallback complete = [innerErrCode, weak = context_] + (napi_env env, NapiAsyncTask& task, int32_t status) { + TAG_LOGI(AAFwkTag::UI_EXT, "startAbilities complete innerErrCode: %{public}d", *innerErrCode); + if (*innerErrCode == 0) { + task.Resolve(env, CreateJsUndefined(env)); + return; + } + task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode)); + }; + + NapiAsyncTask::ScheduleHighQos("JSUIExtensionConnection::OnStartAbilities", env, + CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result)); + return result; +} + +bool JsUIExtensionContext::UnwrapWantList(napi_env env, NapiCallbackInfo &info, std::vector &wantList) +{ + AppExecFwk::ComplexArrayData jsWantList; + if (!AppExecFwk::UnwrapArrayComplexFromJS(env, info.argv[INDEX_ZERO], jsWantList)) { + TAG_LOGE(AAFwkTag::UI_EXT, "wantList not array."); + ThrowInvalidParamError(env, "wantList not array"); + return false; + } + + size_t jsWantSize = jsWantList.objectList.size(); + if (jsWantSize < INDEX_ONE || jsWantSize > INDEX_FOUR) { + TAG_LOGE(AAFwkTag::UI_EXT, "wantList size not support"); + ThrowInvalidParamError(env, "wantList size error"); + return false; + } + + for (uint32_t index = 0; index < jsWantSize; index++) { + AAFwk::Want curWant; + if (!OHOS::AppExecFwk::UnwrapWant(env, jsWantList.objectList[index], curWant)) { + TAG_LOGE(AAFwkTag::UI_EXT, "startAbilities parse want failed"); + ThrowInvalidParamError(env, "parse want error"); + return false; + } + TAG_LOGD(AAFwkTag::UI_EXT, "startAbilities ability:%{public}s", + curWant.GetElement().GetAbilityName().c_str()); + wantList.emplace_back(curWant); + } + return true; +} + napi_value JsUIExtensionContext::OnConnectAbility(napi_env env, NapiCallbackInfo& info) { TAG_LOGD(AAFwkTag::UI_EXT, "called"); @@ -1331,6 +1414,7 @@ napi_value JsUIExtensionContext::CreateJsUIExtensionContext(napi_env env, BindNativeFunction(env, objValue, "startAbilityForResult", moduleName, StartAbilityForResult); BindNativeFunction(env, objValue, "terminateSelfWithResult", moduleName, TerminateSelfWithResult); BindNativeFunction(env, objValue, "startAbilityForResultAsCaller", moduleName, StartAbilityForResultAsCaller); + BindNativeFunction(env, objValue, "startAbilities", moduleName, StartAbilities); BindNativeFunction(env, objValue, "connectServiceExtensionAbility", moduleName, ConnectAbility); BindNativeFunction(env, objValue, "disconnectServiceExtensionAbility", moduleName, DisconnectAbility); BindNativeFunction(env, objValue, "reportDrawnCompleted", moduleName, ReportDrawnCompleted); diff --git a/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp b/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp index 27cfbbf3ed8..1125cb1b89a 100755 --- a/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp +++ b/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp @@ -136,6 +136,16 @@ ErrCode UIExtensionContext::StartServiceExtensionAbility(const AAFwk::Want& want return ret; } +ErrCode UIExtensionContext::StartAbilities(const std::vector &wantList, const std::string &requestKey) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "call StartAbilities"); + ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartAbilities(wantList, requestKey, token_); + if (err != ERR_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "StartAbilities ret=%{public}d", err); + } + return err; +} + ErrCode UIExtensionContext::StartAbilityForResult(const AAFwk::Want &want, int requestCode, RuntimeTask &&task) { TAG_LOGD(AAFwkTag::UI_EXT, "begin"); diff --git a/frameworks/native/appkit/ability_runtime/service_extension_context.cpp b/frameworks/native/appkit/ability_runtime/service_extension_context.cpp index d391de66e5b..7ec3097ad25 100644 --- a/frameworks/native/appkit/ability_runtime/service_extension_context.cpp +++ b/frameworks/native/appkit/ability_runtime/service_extension_context.cpp @@ -154,6 +154,16 @@ ErrCode ServiceExtensionContext::StartAbilityWithAccount( return err; } +ErrCode ServiceExtensionContext::StartAbilities(const std::vector &wantList, const std::string &requestKey) +{ + TAG_LOGD(AAFwkTag::APPKIT, "call StartAbilities"); + ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartAbilities(wantList, requestKey, token_); + if (err != ERR_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "StartAbilities ret=%{public}d", err); + } + return err; +} + ErrCode ServiceExtensionContext::StartServiceExtensionAbility(const AAFwk::Want &want, int32_t accountId) const { TAG_LOGD(AAFwkTag::APPKIT, "begin"); diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_client.h b/interfaces/inner_api/ability_manager/include/ability_manager_client.h index 6088a0b0f4d..00dff09e587 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_client.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_client.h @@ -284,6 +284,17 @@ public: int requestCode = DEFAULT_INVAL_VALUE, int32_t userId = DEFAULT_INVAL_VALUE); + /** + * @brief start abilities simultaneously. + * + * @param wantList a list of want to start abilities. + * @param callerToken current caller ability token. + * @param userId, Designation User ID. + * @return Returns ERR_OK if success. + */ + ErrCode StartAbilities(const std::vector &wantList, + const std::string &requestKey, const sptr &callerToken); + /** * Start ui session ability with extension session info, send session info to ability manager service. * diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_errors.h b/interfaces/inner_api/ability_manager/include/ability_manager_errors.h index 87c485af117..ec0a023c67f 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_errors.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_errors.h @@ -903,6 +903,34 @@ enum { */ ERR_SA_INTERCEPTOR_READ_PARAMS_FAILED = 2097361, + /** + * Result (2097363-2097371) for StartAbilities Error. + */ + START_ABILITIES_NOT_SUPPORT_DLP = 2097363, + + START_ABILITIES_NOT_SUPPORT_START_PLUGIN = 2097364, + + START_ABILITIES_NOT_SUPPORT_CREATE_APP_INSTANCE_KEY = 2097365, + + START_ABILITIES_NOT_SUPPORT_OPERATE_REMOTE = 2097366, + + START_ABILITIES_NOT_SUPPORT_CROSS_USER = 2097367, + + START_ABILITIES_NOT_SUPPORT_IMPLICIT_START = 2097368, + + START_ABILITIES_ONLY_SUPPORT_UI_ABILITY = 2097369, + + START_ABILITIES_INTERCEPTOR_CHECK_FAILED = 2097370, + + START_ABILITIES_WAITTING_SPECIFIED_CODE = 2097371, + + /* + * Result(2097372) for IPC write Int32 failed. + */ + ERR_WRITE_INT32_FAILED = 2097372, + + ERR_WRITE_STRING_FAILED = 2097373, + /** * Native error(3000000) for target bundle not exist. */ diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h index 55dfbf2a9b4..9f3b7b08ced 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h @@ -304,6 +304,20 @@ public: return 0; } + /** + * @brief start abilities simultaneously. + * + * @param wantList a list of want to start abilities. + * @param callerToken current caller ability token. + * @param userId, Designation User ID. + * @return Returns ERR_OK if success. + */ + virtual ErrCode StartAbilities(const std::vector &wantList, + const std::string &requestKey, const sptr &callerToken) + { + return 0; + } + /** * Start ui session ability with extension session info, send session info to ability manager service. * diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h b/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h index de80df5b372..995255357da 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h @@ -417,6 +417,8 @@ enum class AbilityManagerInterfaceCode { CLOSE_UI_EXTENSION_ABILITY_BY_SCB = 1069, SEND_LOCAL_PENDING_WANT_SENDER = 1070, + // ipc id for start abilities + START_ABILITIES = 1071, // ipc id for continue ability(1101) START_CONTINUATION = 1101, diff --git a/interfaces/kits/native/ability/native/ui_extension_base/js_ui_extension_context.h b/interfaces/kits/native/ability/native/ui_extension_base/js_ui_extension_context.h index 041003c4cb1..2255049e3b0 100755 --- a/interfaces/kits/native/ability/native/ui_extension_base/js_ui_extension_context.h +++ b/interfaces/kits/native/ability/native/ui_extension_base/js_ui_extension_context.h @@ -40,6 +40,7 @@ public: static napi_value CreateJsUIExtensionContext(napi_env env, std::shared_ptr context); static napi_value StartAbilityForResult(napi_env env, napi_callback_info info); static napi_value StartAbilityForResultAsCaller(napi_env env, napi_callback_info info); + static napi_value StartAbilities(napi_env env, napi_callback_info info); static napi_value ConnectAbility(napi_env env, napi_callback_info info); static napi_value DisconnectAbility(napi_env env, napi_callback_info info); static napi_value ReportDrawnCompleted(napi_env env, napi_callback_info info); @@ -60,6 +61,7 @@ protected: virtual napi_value OnTerminateSelfWithResult(napi_env env, NapiCallbackInfo& info); virtual napi_value OnStartAbilityForResult(napi_env env, NapiCallbackInfo& info); virtual napi_value OnStartAbilityForResultAsCaller(napi_env env, NapiCallbackInfo &info); + virtual napi_value OnStartAbilities(napi_env env, NapiCallbackInfo& info); virtual napi_value OnConnectAbility(napi_env env, NapiCallbackInfo& info); virtual napi_value OnDisconnectAbility(napi_env env, NapiCallbackInfo& info); virtual napi_value OnReportDrawnCompleted(napi_env env, NapiCallbackInfo& info); @@ -93,6 +95,7 @@ private: const AAFwk::StartOptions &options, size_t unwrapArgc); void AddFreeInstallObserver(napi_env env, const AAFwk::Want &want, napi_value callback, napi_value* result, bool isAbilityResult = false, bool isOpenLink = false); + bool UnwrapWantList(napi_env env, NapiCallbackInfo &info, std::vector &wantList); bool CreateOpenLinkTask(const napi_env &env, const napi_value &lastParam, AAFwk::Want &want, int &requestCode); napi_value OnOpenLink(napi_env env, NapiCallbackInfo& info); diff --git a/interfaces/kits/native/ability/native/ui_extension_base/ui_extension_context.h b/interfaces/kits/native/ability/native/ui_extension_base/ui_extension_context.h index e1d2c24f7e9..2c07bdee592 100755 --- a/interfaces/kits/native/ability/native/ui_extension_base/ui_extension_context.h +++ b/interfaces/kits/native/ability/native/ui_extension_base/ui_extension_context.h @@ -98,6 +98,8 @@ public: */ ErrCode StartServiceExtensionAbility(const AAFwk::Want &want, int32_t accountId = -1); + ErrCode StartAbilities(const std::vector &wantList, const std::string &requestKey); + /** * Start other ability for result. * diff --git a/interfaces/kits/native/appkit/ability_runtime/service_extension_context.h b/interfaces/kits/native/appkit/ability_runtime/service_extension_context.h index bd66558ba3e..e9fbeb957b0 100644 --- a/interfaces/kits/native/appkit/ability_runtime/service_extension_context.h +++ b/interfaces/kits/native/appkit/ability_runtime/service_extension_context.h @@ -122,6 +122,8 @@ public: ErrCode StartAbilityWithAccount( const AAFwk::Want &want, int accountId, const AAFwk::StartOptions &startOptions) const; + + ErrCode StartAbilities(const std::vector &wantList, const std::string &requestKey); ErrCode StartServiceExtensionAbility(const AAFwk::Want &want, int32_t accountId = -1) const; diff --git a/services/abilitymgr/include/ability_manager_proxy.h b/services/abilitymgr/include/ability_manager_proxy.h index 24b52b6f45c..e7071d1c683 100644 --- a/services/abilitymgr/include/ability_manager_proxy.h +++ b/services/abilitymgr/include/ability_manager_proxy.h @@ -216,6 +216,17 @@ public: int requestCode = DEFAULT_INVAL_VALUE, int32_t userId = DEFAULT_INVAL_VALUE) override; + /** + * @brief start abilities simultaneously. + * + * @param wantList a list of want to start abilities. + * @param requestKey, The unique key of this StartAbilities request. + * @param callerToken current caller ability token. + * @return Returns ERR_OK if success. + */ + ErrCode StartAbilities(const std::vector &wantList, + const std::string &requestKey, const sptr &callerToken) override; + /** * Start ui session ability with extension session info, send session info to ability manager service. * diff --git a/services/abilitymgr/include/ability_manager_service.h b/services/abilitymgr/include/ability_manager_service.h index 3861e7a8c29..1a647486cae 100644 --- a/services/abilitymgr/include/ability_manager_service.h +++ b/services/abilitymgr/include/ability_manager_service.h @@ -336,6 +336,18 @@ public: int requestCode = DEFAULT_INVAL_VALUE, int32_t userId = DEFAULT_INVAL_VALUE) override; + + /** + * @brief start abilities simultaneously. + * + * @param wantList a list of want to start abilities. + * @param requestKey, The unique key of this StartAbilities request. + * @param callerToken current caller ability token. + * @return Returns ERR_OK if success. + */ + ErrCode StartAbilities(const std::vector &wantList, + const std::string &requestKey, const sptr &callerToken) override; + /** * Start ui session ability with extension session info, send session info to ability manager service. * @@ -2543,6 +2555,13 @@ private: virtual int RegisterSessionHandler(const sptr &object) override; + int32_t StartAbilitiesHandleWant(std::vector &abilityRequestList, + const Want &want, const sptr &callerToken); + int32_t StartAbilitiesCheckDlp(const Want &want, const sptr &callerToken); + int32_t StartAbilitiesProcessAppIndex(int32_t &appIndex, Want &want, + const sptr &callerToken); + int32_t StartAbilitiesInterceptorCheck(const Want &want, AbilityRequest &abilityRequest, + const sptr &callerToken, int32_t appIndex); /** * Start switch user dialog Extension ability. */ diff --git a/services/abilitymgr/include/ability_manager_stub.h b/services/abilitymgr/include/ability_manager_stub.h index 75ac158a7c0..7894a50b2c1 100644 --- a/services/abilitymgr/include/ability_manager_stub.h +++ b/services/abilitymgr/include/ability_manager_stub.h @@ -296,6 +296,7 @@ private: int StartAbilityForResultAsCallerInner(MessageParcel &data, MessageParcel &reply); int StartAbilityForResultAsCallerForOptionsInner(MessageParcel &data, MessageParcel &reply); + int32_t StartAbilitiesInner(MessageParcel &data, MessageParcel &reply); int32_t StartAbilityOnlyUIAbilityInner(MessageParcel &data, MessageParcel &reply); diff --git a/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h b/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h index 3e52e264ad9..3747cccfb44 100644 --- a/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h +++ b/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h @@ -46,6 +46,7 @@ struct SpecifiedRequest { SpecifiedProcessState specifiedProcessState = SpecifiedProcessState::STATE_NONE; int32_t requestId = 0; int32_t persistentId = 0; + int32_t requestListId = -1; uint32_t sceneFlag = 0; uint32_t callingTokenId = 0; AbilityRequest abilityRequest; @@ -53,6 +54,14 @@ struct SpecifiedRequest { SpecifiedRequest(int32_t requestId, AbilityRequest request) : requestId(requestId), abilityRequest(request) {} }; +struct AbilitiesRequest { + std::vector waitingRequestIdList; + std::vector abilityRequestList; + std::vector> UnsortedSessionInfoList; + + AbilitiesRequest(std::vector abilityRequestList) : abilityRequestList(abilityRequestList) {} +}; + class UIAbilityLifecycleManager : public std::enable_shared_from_this { public: UIAbilityLifecycleManager() = default; @@ -155,6 +164,7 @@ public: void SetRootSceneSession(const sptr &rootSceneSession); int NotifySCBToStartUIAbility(AbilityRequest &abilityRequest); + int32_t NotifySCBToStartUIAbilities(std::vector &abilityRequestList); int NotifySCBToPreStartUIAbility(const AbilityRequest &abilityRequest, sptr &sessionInfo); @@ -428,6 +438,8 @@ private: sptr CreateSessionInfo(const AbilityRequest &abilityRequest) const; int NotifySCBPendingActivation(sptr &sessionInfo, const AbilityRequest &abilityRequest, std::string &errMsg); + int32_t BatchNotifySCBPendingActivation(std::vector> &sessionInfoList, + const std::vector &abilityRequestList, std::string &errMsg); bool IsHookModule(const AbilityRequest &abilityRequest) const; int ResolveAbility(const std::shared_ptr &targetAbility, const AbilityRequest &abilityRequest) const; std::vector> GetAbilityRecordsByNameInner(const AppExecFwk::ElementName &element); @@ -552,6 +564,8 @@ private: std::vector> prepareTerminateByPidRecords_; std::unordered_map> hookSpecifiedMap_; + ffrt::mutex startAbilitiesProcessLock_; + std::map> abilitiesRequestMap_; std::mutex startingPidsMutex_; std::vector startingPids_; }; diff --git a/services/abilitymgr/include/utils/start_ability_utils.h b/services/abilitymgr/include/utils/start_ability_utils.h index f6a62e2cb5f..d615898b049 100644 --- a/services/abilitymgr/include/utils/start_ability_utils.h +++ b/services/abilitymgr/include/utils/start_ability_utils.h @@ -22,6 +22,7 @@ #include "ability_info.h" #include "extension_ability_info.h" #include "want.h" +#include "scene_board_judgement.h" namespace OHOS { namespace AAFwk { @@ -59,7 +60,7 @@ struct StartAbilityUtils { static std::vector GetCloneAppIndexes(const std::string &bundleName, int32_t userId); static bool IsCallFromAncoShellOrBroker(const sptr &callerToken); - + static bool IsSupportStartAbilities(); static thread_local std::shared_ptr startAbilityInfo; static thread_local std::shared_ptr callerAbilityInfo; static thread_local bool skipCrowTest; diff --git a/services/abilitymgr/src/ability_manager_client.cpp b/services/abilitymgr/src/ability_manager_client.cpp index 8047f3f11ec..851293bf136 100644 --- a/services/abilitymgr/src/ability_manager_client.cpp +++ b/services/abilitymgr/src/ability_manager_client.cpp @@ -261,6 +261,19 @@ ErrCode AbilityManagerClient::StartAbilityForResultAsCaller(const Want &want, co return abms->StartAbilityForResultAsCaller(want, startOptions, callerToken, requestCode, userId); } +ErrCode AbilityManagerClient::StartAbilities(const std::vector &wantList, + const std::string &requestKey, const sptr &callerToken) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGI(AAFwkTag::ABILITYMGR, "call StartAbilities"); + auto abms = GetAbilityManager(); + CHECK_POINTER_RETURN_NOT_CONNECTED(abms); + for (const Want &item : wantList) { + HandleDlpApp(const_cast(item)); + } + return abms->StartAbilities(wantList, requestKey, callerToken); +} + ErrCode AbilityManagerClient::StartAbilityByUIContentSession(const Want &want, const StartOptions &startOptions, sptr callerToken, sptr sessionInfo, int requestCode, int32_t userId) diff --git a/services/abilitymgr/src/ability_manager_proxy.cpp b/services/abilitymgr/src/ability_manager_proxy.cpp index 073b5dc74da..cce6d053acb 100644 --- a/services/abilitymgr/src/ability_manager_proxy.cpp +++ b/services/abilitymgr/src/ability_manager_proxy.cpp @@ -43,6 +43,7 @@ using AutoStartupInfo = AbilityRuntime::AutoStartupInfo; constexpr int32_t CYCLE_LIMIT = 1000; constexpr int32_t MAX_AUTO_STARTUP_COUNT = 100; constexpr int32_t MAX_UPDATE_CONFIG_SIZE = 100; +constexpr int32_t MAX_WANT_LIST_SIZE = 4; bool AbilityManagerProxy::WriteInterfaceToken(MessageParcel &data) { if (!data.WriteInterfaceToken(AbilityManagerProxy::GetDescriptor())) { @@ -507,6 +508,55 @@ int AbilityManagerProxy::StartAbilityForResultAsCaller(const Want &want, const S return reply.ReadInt32(); } +ErrCode AbilityManagerProxy::StartAbilities(const std::vector &wantList, + const std::string &requestKey, const sptr &callerToken) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (callerToken == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null callerToken"); + return INVALID_CALLER_TOKEN; + } + if (!WriteInterfaceToken(data)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write token fail"); + return ERR_WRITE_INTERFACE_TOKEN_FAILED; + } + + int32_t size = static_cast(wantList.size()); + if (!(size > 0 && size <= MAX_WANT_LIST_SIZE)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "vector size error"); + return ERR_NATIVE_IPC_PARCEL_FAILED; + } + if (!data.WriteInt32(size)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write size fail"); + return ERR_WRITE_INT32_FAILED; + } + for (const Want &item : wantList) { + if (!data.WriteParcelable(&item)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write want fail"); + return ERR_WRITE_WANT; + } + } + + if (!data.WriteString(requestKey)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write requestKey fail"); + return ERR_WRITE_STRING_FAILED; + } + + if (!data.WriteRemoteObject(callerToken)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write callerToken fail"); + return ERR_WRITE_CALLER_TOKEN_FAILED; + } + + auto error = SendRequest(AbilityManagerInterfaceCode::START_ABILITIES, data, reply, option); + if (error != NO_ERROR) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "request error:%{public}d", error); + return error; + } + return reply.ReadInt32(); +} + int AbilityManagerProxy::CheckUISessionParams(MessageParcel &data, const sptr &callerToken, const sptr &sessionInfo, int32_t userId, int requestCode) { diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index 5ffd3db5c69..358a661bd7f 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -2177,6 +2177,234 @@ int AbilityManagerService::StartAbilityForOptionInner(const Want &want, const St return ret; } +ErrCode AbilityManagerService::StartAbilities(const std::vector &wantList, + const std::string &requestKey, const sptr &callerToken) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + XCOLLIE_TIMER_DEFAULT(__PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::ABILITYMGR, "Call StartAbilities"); + std::vector abilityRequestList; + int32_t oriValidUserId = GetValidUserId(DEFAULT_INVAL_VALUE); + + if (!StartAbilityUtils::IsSupportStartAbilities()) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities is not supported"); + return ERR_CAPABILITY_NOT_SUPPORT; + } + + if (callerToken == nullptr || !VerificationAllToken(callerToken)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities %{public}s verificationAllToken failed", __func__); + return ERR_INVALID_CALLER; + } + + for (const Want &want : wantList) { + int32_t ret = StartAbilitiesHandleWant(abilityRequestList, want, callerToken); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities want process block"); + return ret; + } + } + + TAG_LOGD(AAFwkTag::ABILITYMGR, "StartAbilities ready to NotifySCBToStartUIAbilities"); + for (AbilityRequest &abilityRequest : abilityRequestList) { + auto abilityInfo = abilityRequest.abilityInfo; + ReportEventToRSS(abilityInfo, abilityRequest.callerToken); + abilityRequest.userId = oriValidUserId; + abilityRequest.want.SetParam(ServerConstant::IS_CALL_BY_SCB, false); + } + auto uiAbilityManager = GetUIAbilityManagerByUserId(oriValidUserId); + CHECK_POINTER_AND_RETURN(uiAbilityManager, ERR_INVALID_VALUE); + return uiAbilityManager->NotifySCBToStartUIAbilities(abilityRequestList); +} + +int32_t AbilityManagerService::StartAbilitiesHandleWant(std::vector &abilityRequestList, + const Want &want, const sptr &callerToken) +{ + int32_t userId = DEFAULT_INVAL_VALUE; + int32_t validUserId = GetValidUserId(userId); + uint32_t specifyTokenId = 0; + int32_t requestCode = DEFAULT_INVAL_VALUE; + + AbilityUtil::RemoveShowModeKey(const_cast(want)); + + //intent openlink do not RemoveInsightIntent action + if (!want.HasParameter(AppExecFwk::INSIGHT_INTENT_EXECUTE_OPENLINK_FLAG)) { + InsightIntentExecuteParam::RemoveInsightIntent(const_cast(want)); + } + +#ifdef SUPPORT_SCREEN + DmsUtil::GetInstance().UpdateFlagForCollaboration(want); +#endif + + if (AbilityRuntime::StartupUtil::IsStartPlugin(want)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities not support StartPlugin"); + return START_ABILITIES_NOT_SUPPORT_START_PLUGIN; + } + + AbilityUtil::RemoveWindowModeKey(const_cast(want)); + + if (want.GetBoolParam(Want::CREATE_APP_INSTANCE_KEY, false)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities not support CREATE_APP_INSTANCE_KEY"); + return START_ABILITIES_NOT_SUPPORT_CREATE_APP_INSTANCE_KEY; + } + + int32_t ret = StartAbilitiesCheckDlp(want, callerToken); + if (ret != ERR_OK) { + return ret; + } + + int32_t appIndex = 0; + ret = StartAbilitiesProcessAppIndex(appIndex, const_cast(want), callerToken); + if (ret != ERR_OK) { + return ret; + } + ret = AbilityPermissionUtil::GetInstance().CheckMultiInstanceAndAppClone( + const_cast(want), validUserId, appIndex, callerToken, false); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities CheckMultiInstanceAndAppClone failed"); + return ret; + } + + StartAbilityInfoWrap threadLocalInfo(want, validUserId, appIndex, callerToken); + + if (CheckIfOperateRemote(want)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities not support StartRemoteAbility"); + return START_ABILITIES_NOT_SUPPORT_OPERATE_REMOTE; + } + + if (!JudgeMultiUserConcurrency(validUserId)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities multi-user non-concurrent unsatisfied"); + return START_ABILITIES_NOT_SUPPORT_CROSS_USER; + } +#ifdef SUPPORT_SCREEN + if (ImplicitStartProcessor::IsImplicitStartAction(want)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities not support implicit start"); + return START_ABILITIES_NOT_SUPPORT_IMPLICIT_START; + } +#endif + AbilityRequest abilityRequest; + auto result = GenerateAbilityRequest(want, requestCode, abilityRequest, callerToken, validUserId); + auto abilityRecord = Token::GetAbilityRecordByToken(callerToken); + std::string callerBundleName = abilityRecord ? abilityRecord->GetAbilityInfo().bundleName : ""; + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "generate ability request local error"); + return result; + } + + UpdateCallerInfoUtil::GetInstance().UpdateCallerInfo(abilityRequest.want, callerToken); + + auto abilityInfo = abilityRequest.abilityInfo; + if (abilityInfo.type != AbilityType::PAGE) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities only support UIAbility"); + return START_ABILITIES_ONLY_SUPPORT_UI_ABILITY; + } + + result = CheckStaticCfgPermission(abilityRequest, false, + abilityRequest.want.GetIntParam(Want::PARAM_RESV_CALLER_TOKEN, 0), false, false, false); + if (result != AppExecFwk::Constants::PERMISSION_GRANTED) { + TAG_LOGE(AAFwkTag::ABILITYMGR, + "StartAbilities checkStaticCfgPermission error, result:%{public}d", result); + return ERR_STATIC_CFG_PERMISSION; + } + result = CheckCallPermission(want, abilityInfo, abilityRequest, false, + false, specifyTokenId, callerBundleName); + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, + "StartAbilities checkCallPermission error, result:%{public}d", result); + return result; + } + + result = StartAbilitiesInterceptorCheck(want, abilityRequest, callerToken, appIndex); + if (result != ERR_OK) { + return result; + } + + Want newWant = abilityRequest.want; + bool isReplaceWantExist = newWant.GetBoolParam("queryWantFromErms", false); + newWant.RemoveParam("queryWantFromErms"); + + auto callerTokenId = IPCSkeleton::GetCallingTokenID(); + RemoveUnauthorizedLaunchReasonMessage(want, abilityRequest, callerTokenId); + + if (!IsAbilityControllerStart(want, abilityInfo.bundleName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, + "StartAbilities isAbilityControllerStart failed:%{public}s", abilityInfo.bundleName.c_str()); + return ERR_WOULD_BLOCK; + } + abilityRequest.want.RemoveParam(SPECIFY_TOKEN_ID); + abilityRequest.want.RemoveParam(PARAM_SPECIFIED_PROCESS_FLAG); + abilityRequestList.emplace_back(abilityRequest); + return ERR_OK; +} + +int32_t AbilityManagerService::StartAbilitiesCheckDlp(const Want &want, const sptr &callerToken) +{ +#ifdef WITH_DLP + int32_t userId = DEFAULT_INVAL_VALUE; + if (AbilityUtil::HandleDlpApp(const_cast(want))) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities not support Dlp"); + return START_ABILITIES_NOT_SUPPORT_DLP; + } + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "CHECK_DLP"); + if (!DlpUtils::OtherAppsAccessDlpCheck(callerToken, want) || + VerifyAccountPermission(userId) == CHECK_PERMISSION_FAILED || + !DlpUtils::DlpAccessOtherAppsCheck(callerToken, want)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, + "StartAbilities Dlp %{public}s: permission verification failed", __func__); + return CHECK_PERMISSION_FAILED; + } +#endif // WITH_DLP + return ERR_OK; +} + +int32_t AbilityManagerService::StartAbilitiesProcessAppIndex(int32_t &appIndex, Want &want, + const sptr &callerToken) +{ + SetTargetCloneIndexInSameBundle(want, callerToken); + if (!want.HasParameter(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY)) { + want.SetParam(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY, 0); + } + if (!StartAbilityUtils::GetAppIndex(want, callerToken, appIndex)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities GetAppIndex failed."); + return ERR_APP_CLONE_INDEX_INVALID; + } + return ERR_OK; +} + +int32_t AbilityManagerService::StartAbilitiesInterceptorCheck(const Want &want, AbilityRequest &abilityRequest, + const sptr &callerToken, int32_t appIndex) +{ + int32_t requestCode = DEFAULT_INVAL_VALUE; + Want newWant = abilityRequest.want; + auto abilityInfo = abilityRequest.abilityInfo; + auto shouldBlockFunc = [aams = shared_from_this()]() { return aams->ShouldBlockAllAppStart(); }; + AbilityInterceptorParam interceptorParam = AbilityInterceptorParam(want, requestCode, GetUserId(), + true, nullptr, shouldBlockFunc); + int32_t result = interceptorExecuter_ == nullptr ? ERR_NULL_INTERCEPTOR_EXECUTER : + interceptorExecuter_->DoProcess(interceptorParam); + if (result == ERR_CROWDTEST_EXPIRED) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities ERR_CROWDTEST_EXPIRED"); + return result; + } + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities interceptorExecuter_ null or DoProcess error"); + return START_ABILITIES_INTERCEPTOR_CHECK_FAILED; + } + + AbilityInterceptorParam afterCheckParam = AbilityInterceptorParam(newWant, requestCode, GetUserId(), + true, callerToken, std::make_shared(abilityInfo), false, appIndex); + result = afterCheckExecuter_ == nullptr ? ERR_INVALID_VALUE : + afterCheckExecuter_->DoProcess(afterCheckParam); + if (result == ERR_CROWDTEST_EXPIRED) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities ERR_CROWDTEST_EXPIRED"); + return result; + } + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities afterCheckExecuter_ null or DoProcess error"); + return START_ABILITIES_INTERCEPTOR_CHECK_FAILED; + } + return ERR_OK; +} + int32_t AbilityManagerService::RequestDialogService(const Want &want, const sptr &callerToken) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); diff --git a/services/abilitymgr/src/ability_manager_stub.cpp b/services/abilitymgr/src/ability_manager_stub.cpp index 5b0088dad62..5009e7f9502 100644 --- a/services/abilitymgr/src/ability_manager_stub.cpp +++ b/services/abilitymgr/src/ability_manager_stub.cpp @@ -34,6 +34,7 @@ const std::u16string extensionDescriptor = u"ohos.aafwk.ExtensionManager"; constexpr int32_t CYCLE_LIMIT = 1000; constexpr int32_t MAX_KILL_PROCESS_PID_COUNT = 100; constexpr int32_t MAX_UPDATE_CONFIG_SIZE = 100; +constexpr int32_t MAX_WANT_LIST_SIZE = 4; } // namespace AbilityManagerStub::AbilityManagerStub() {} @@ -578,6 +579,9 @@ int AbilityManagerStub::OnRemoteRequestInnerFourteenth(uint32_t code, MessagePar if (interfaceCode == AbilityManagerInterfaceCode::CLOSE_UI_EXTENSION_ABILITY_BY_SCB) { return CloseUIExtensionAbilityBySCBInner(data, reply); } + if (interfaceCode == AbilityManagerInterfaceCode::START_ABILITIES) { + return StartAbilitiesInner(data, reply); + } return ERR_CODE_NOT_EXIST; } @@ -3862,6 +3866,38 @@ int AbilityManagerStub::StartAbilityForResultAsCallerInner(MessageParcel &data, return NO_ERROR; } +int32_t AbilityManagerStub::StartAbilitiesInner(MessageParcel &data, MessageParcel &reply) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "call StartAbilitiesInner"); + + std::vector wantList; + int32_t size = data.ReadInt32(); + if (!(size > 0 && size <= MAX_WANT_LIST_SIZE)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "vector size error"); + return ERR_NATIVE_IPC_PARCEL_FAILED; + } + for (auto i = 0; i < size; i++) { + std::unique_ptr want(data.ReadParcelable()); + if (want == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null want"); + return ERR_NATIVE_IPC_PARCEL_FAILED; + } + wantList.emplace_back(*want); + } + + std::string requestKey = data.ReadString(); + + sptr callerToken = data.ReadRemoteObject(); + if (callerToken == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null callerToken"); + return INVALID_CALLER_TOKEN; + } + + int32_t result = StartAbilities(wantList, requestKey, callerToken); + reply.WriteInt32(result); + return NO_ERROR; +} + int AbilityManagerStub::StartAbilityForResultAsCallerForOptionsInner(MessageParcel &data, MessageParcel &reply) { TAG_LOGD(AAFwkTag::ABILITYMGR, "called"); diff --git a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp index f5fa7dfb7a7..b066ac4827c 100644 --- a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp +++ b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp @@ -68,6 +68,7 @@ constexpr int32_t MAX_FIND_UIEXTENSION_CALLER_TIMES = 10; constexpr int32_t START_UI_ABILITY_PER_SECOND_UPPER_LIMIT = 20; constexpr int32_t API20 = 20; constexpr int32_t API_VERSION_MOD = 100; +constexpr int32_t REQUEST_LIST_ID_INIT = -1; constexpr const char* IS_CALLING_FROM_DMS = "supportCollaborativeCallingFromDmsInAAFwk"; constexpr int REMOVE_STARTING_BUNDLE_TIMEOUT_MICRO_SECONDS = 5000000; // 5s @@ -641,6 +642,140 @@ int UIAbilityLifecycleManager::NotifySCBToStartUIAbility(AbilityRequest &ability return ret; } +int UIAbilityLifecycleManager::NotifySCBToStartUIAbilities(std::vector &abilityRequestList) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::ABILITYMGR, "StartAbilities Call NotifySCBToStartUIAbilities"); + for (AbilityRequest &abilityRequest : abilityRequestList) { + if (!AddStartCallerTimestamp(abilityRequest.want.GetIntParam(Want::PARAM_RESV_CALLER_UID, -1))) { + return ERR_INVALID_VALUE; + } + abilityRequest.want.SetParam(IS_SHELL_CALL, AAFwk::PermissionVerification::GetInstance()->IsShellCall()); + std::string callerKey = std::to_string(IPCSkeleton::GetCallingPid()) + ":" + + std::to_string(IPCSkeleton::GetCallingUid()); + bool isCallerKilling = IN_PROCESS_CALL(DelayedSingleton::GetInstance()->IsCallerKilling(callerKey)); + if (isCallerKilling) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities caller is killing"); + return ERR_INVALID_VALUE; + } + abilityRequest.want.SetParam(Want::PARAMS_REAL_CALLER_KEY, callerKey); + } + int32_t requestListId; + { + std::lock_guard guard(sessionLock_); + requestListId = GetRequestId(); + } + std::shared_ptr abilitiesRequest = nullptr; + // std::shared_ptr + abilitiesRequest = std::make_shared(abilityRequestList); + // 持锁修改abilitiesRequestMap_ + { + std::lock_guard guard2(startAbilitiesProcessLock_); + abilitiesRequestMap_.emplace(requestListId, abilitiesRequest); + } + // 开始处理分支场景 + for (AbilityRequest &abilityRequest : abilityRequestList) { + if (IsStartSpecifiedProcessRequest(abilityRequest)) { + abilitiesRequestMap_.erase(requestListId); + return ERR_CAPABILITY_NOT_SUPPORT; + } + const auto &abilityInfo = abilityRequest.abilityInfo; + auto requestId = GetRequestId(); + auto isSpecified = (abilityInfo.launchMode == AppExecFwk::LaunchMode::SPECIFIED); + if (isSpecified) { + abilitiesRequestMap_.erase(requestListId); + return ERR_CAPABILITY_NOT_SUPPORT; + } + auto sessionInfo = CreateSessionInfo(abilityRequest); + sessionInfo->requestCode = abilityRequest.requestCode; + sessionInfo->requestId = requestId; + // isCreating 一定是 false 下方场景确认一下 + sessionInfo->persistentId = GetPersistentIdByAbilityRequest(abilityRequest, sessionInfo->reuse); + sessionInfo->userId = userId_; + sessionInfo->isAtomicService = (abilityInfo.applicationInfo.bundleType == AppExecFwk::BundleType::ATOMIC_SERVICE); + TAG_LOGI(AAFwkTag::ABILITYMGR, "Reused sessionId: %{public}d, userId: %{public}d, requestId: %{public}d", + sessionInfo->persistentId, userId_, requestId); + // 将初始化完成的sessionInfo插入对应的abilitiesRequest中 + abilitiesRequest->UnsortedSessionInfoList.emplace_back(sessionInfo); + } + // 判断是否需要等待Specified + if (!abilitiesRequest->waitingRequestIdList.empty()) { + // 新增错误码 返回此错误码表示进入等待 + return START_ABILITIES_WAITTING_SPECIFIED_CODE; + } + // 进入这个分支,SessionInfoList是有序的,不用重排 + std::string errMsg; + TAG_LOGI(AAFwkTag::ABILITYMGR, "StartAbilities normal start. sessionInfoList size: %{public}zu", + abilitiesRequest->UnsortedSessionInfoList.size()); + // sptr sessionInfo0 = &sessionInfoList[0]; + int ret = BatchNotifySCBPendingActivation( + abilitiesRequest->UnsortedSessionInfoList, abilityRequestList, errMsg); + + for (auto sessionInfo : abilitiesRequest->UnsortedSessionInfoList) { + sessionInfo->want.RemoveAllFd(); + } + abilitiesRequestMap_.erase(requestListId); + return ret; +} + +int32_t UIAbilityLifecycleManager::BatchNotifySCBPendingActivation(std::vector> &sessionInfoList, + const std::vector &abilityRequestList, std::string &errMsg) +{ + // process sessionInfoList + for (auto sessionInfo : sessionInfoList) { + if (sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "sessionInfo is nullptr"); + errMsg = "sessionInfo is nullptr"; + return ERR_INVALID_VALUE; + } + bool hasStartWindowOption = (sessionInfo->startWindowOption != nullptr); + bool hasStartWindow = hasStartWindowOption ? sessionInfo->startWindowOption->hasStartWindow : false; + std::string backgroundColor = + hasStartWindowOption ? sessionInfo->startWindowOption->startWindowBackgroundColor : ""; + TAG_LOGI(AAFwkTag::ABILITYMGR, "appCloneIndex:%{public}d, instanceKey:%{public}s, " + "hasStartWindow:%{public}d, backgroundColor:%{public}s", + (sessionInfo->want).GetIntParam(Want::PARAM_APP_CLONE_INDEX_KEY, 0), sessionInfo->instanceKey.c_str(), + hasStartWindow, backgroundColor.c_str()); + } + // 获取caller信息 + std::shared_ptr callerAbilityRecord; + callerAbilityRecord = GetAbilityRecordByToken(abilityRequestList[0].callerToken); + if (callerAbilityRecord == nullptr || callerAbilityRecord->GetRestartAppFlag()) + { + // 使用rootSession启动 callerRecord存在 callerSession不存在 + auto tmpSceneSession = iface_cast(rootSceneSession_); + if (tmpSceneSession == nullptr) { + errMsg = "null tmpSceneSession, scb does not exist"; + TAG_LOGE(AAFwkTag::ABILITYMGR, "%{public}s", errMsg.c_str()); + return ERR_INVALID_VALUE; + } + for (auto sessionInfo : sessionInfoList) { + sessionInfo->canStartAbilityFromBackground = true; + } + TAG_LOGI(AAFwkTag::ABILITYMGR, + "scb call, StartAbilities NotifySCBPendingActivation for rootSceneSession"); + return static_cast(tmpSceneSession->PendingSessionActivation(sessionInfoList[0])); + } + // 处理caller + auto callerSessionInfo = callerAbilityRecord->GetSessionInfo(); + CHECK_POINTER_AND_RETURN(callerSessionInfo, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(callerSessionInfo->sessionToken, ERR_INVALID_VALUE); + auto callerSession = iface_cast(callerSessionInfo->sessionToken); + CHECK_POINTER_AND_RETURN(callerSession, ERR_INVALID_VALUE); + for (auto sessionInfo : sessionInfoList) { + CheckCallerFromBackground(callerAbilityRecord, sessionInfo); + } + for (auto abilityRequest : abilityRequestList) { + auto requestId = abilityRequest.want.GetStringParam(KEY_REQUEST_ID); + if (!requestId.empty()) { + callerAbilityRecord->NotifyAbilityRequestSuccess(requestId, abilityRequest.want.GetElement()); + } + const_cast(abilityRequest).want.RemoveParam(KEY_REQUEST_ID); + } + TAG_LOGI(AAFwkTag::ABILITYMGR, "scb call, StartAbilities BatchNotifySCBPendingActivation for callerSession"); + return static_cast(callerSession->PendingSessionActivation(sessionInfoList[0])); +} + int32_t UIAbilityLifecycleManager::NotifySCBToRecoveryAfterInterception(const AbilityRequest &abilityRequest) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); diff --git a/services/abilitymgr/src/utils/start_ability_utils.cpp b/services/abilitymgr/src/utils/start_ability_utils.cpp index c0638827351..27f0aca8416 100644 --- a/services/abilitymgr/src/utils/start_ability_utils.cpp +++ b/services/abilitymgr/src/utils/start_ability_utils.cpp @@ -395,5 +395,15 @@ bool StartAbilityUtils::IsCallFromAncoShellOrBroker(const sptr &c } return false; } + +bool StartAbilityUtils::IsSupportStartAbilities() +{ + if (!AppUtils::GetInstance().IsSupportStartAbilities() || + !Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartAbilities is not supported"); + return false; + } + return true; +} } } \ No newline at end of file diff --git a/services/common/include/app_utils.h b/services/common/include/app_utils.h index d89cfbafc69..2d8ee786f06 100644 --- a/services/common/include/app_utils.h +++ b/services/common/include/app_utils.h @@ -139,6 +139,13 @@ public: */ bool IsStartOptionsWithAnimation(); + /** + * IsSupportStartAbilities, check whether the StartAbilities API is supported. + * + * @return Whether the StartAbilities API is supported. + */ + bool IsSupportStartAbilities(); + /** * IsStartOptionsWithAnimation, check whether it is a multi-process model. * @@ -416,6 +423,7 @@ private: volatile DeviceConfiguration isConnectSupportCrossUser_ = {false, false}; volatile DeviceConfiguration isSupportAppServiceExtension_ = {false, false}; volatile DeviceConfiguration isGrantTempUriPermission_ = {false, true}; + volatile DeviceConfiguration isSupportStartAbilities_ = {false, false}; DeviceConfiguration>> residentProcessInExtremeMemory_ = {false, {}}; std::mutex residentProcessInExtremeMemoryMutex_; diff --git a/services/common/src/app_utils.cpp b/services/common/src/app_utils.cpp index 144dc9cd005..760554b8dd5 100644 --- a/services/common/src/app_utils.cpp +++ b/services/common/src/app_utils.cpp @@ -44,6 +44,7 @@ constexpr const char* LIMIT_MAXIMUM_OF_RENDER_PROCESS = "persist.sys.abilityms.l constexpr const char* GRANT_PERSIST_URI_PERMISSION = "persist.sys.abilityms.grant_persist_uri_permission"; constexpr const char* GRANT_TEMPORARY_URI_PERMISSION = "persist.sys.abilityms.grant_temporary_uri_permission"; constexpr const char* START_OPTIONS_WITH_ANIMATION = "persist.sys.abilityms.start_options_with_animation"; +constexpr const char* SUPPORT_START_ABILITIES = "persist.sys.abilityms.enable_start_abilities"; constexpr const char* MULTI_PROCESS_MODEL = "persist.sys.abilityms.multi_process_model"; constexpr const char* PARAM_ANCO_APP_IDENTIFIER = "persist.hmos_fusion_mgr.anco_identifier"; constexpr const char* ALLOW_CHILD_PROCESS_IN_MULTI_PROCESS_FEATURE_APP = @@ -227,6 +228,16 @@ bool AppUtils::IsStartOptionsWithAnimation() return isStartOptionsWithAnimation_.value; } +bool AppUtils::IsSupportStartAbilities() +{ + if (!isSupportStartAbilities_.isLoaded) { + isSupportStartAbilities_.value = system::GetBoolParameter(SUPPORT_START_ABILITIES, false); + isSupportStartAbilities_.isLoaded = true; + } + TAG_LOGD(AAFwkTag::DEFAULT, "called %{public}d", isSupportStartAbilities_.value); + return isSupportStartAbilities_.value; +} + bool AppUtils::IsMultiProcessModel() { if (!isMultiProcessModel_.isLoaded) { -- Gitee From 53a5da6dd7a4215d8a72acb0e3fc12bdba75dc8e Mon Sep 17 00:00:00 2001 From: wangzhen Date: Sat, 21 Jun 2025 18:09:43 +0800 Subject: [PATCH 2/3] batch start for specified Signed-off-by: wangzhen Change-Id: I2a1edbeb236490831e8985a1e28201ccbb0e8233 --- frameworks/native/ability/native/BUILD.gn | 2 + .../native/ability/native/ability_thread.cpp | 7 +- .../native/extension_ability_thread.cpp | 26 +++ .../ability/native/js_deferred_callback.cpp | 48 +++++ .../native/js_service_extension_context.cpp | 19 +- .../native/js_start_abilities_observer.cpp | 52 +++++ .../js_ui_extension_context.cpp | 19 +- .../include/ability_manager_errors.h | 2 +- .../include/ability_scheduler_interface.h | 9 +- .../native/ability/native/ability_thread.h | 4 +- .../ability/native/extension_ability_thread.h | 2 + .../ability/native/js_deferred_callback.h | 35 ++++ .../native/js_start_abilities_observer.h | 41 ++++ services/abilitymgr/include/ability_record.h | 1 + .../include/ability_scheduler_proxy.h | 4 +- .../include/ability_scheduler_stub.h | 3 +- services/abilitymgr/include/lifecycle_deal.h | 3 +- .../ui_ability_lifecycle_manager.h | 31 +-- .../src/ability_manager_service.cpp | 2 +- services/abilitymgr/src/ability_record.cpp | 6 + .../src/ability_scheduler_proxy.cpp | 28 ++- .../abilitymgr/src/ability_scheduler_stub.cpp | 12 +- services/abilitymgr/src/lifecycle_deal.cpp | 9 +- .../ui_ability_lifecycle_manager.cpp | 181 +++++++++++------- 24 files changed, 432 insertions(+), 114 deletions(-) create mode 100644 frameworks/native/ability/native/js_deferred_callback.cpp create mode 100644 frameworks/native/ability/native/js_start_abilities_observer.cpp create mode 100644 interfaces/kits/native/ability/native/js_deferred_callback.h create mode 100644 interfaces/kits/native/ability/native/js_start_abilities_observer.h diff --git a/frameworks/native/ability/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn index e073e303653..871ac337090 100644 --- a/frameworks/native/ability/native/BUILD.gn +++ b/frameworks/native/ability/native/BUILD.gn @@ -313,8 +313,10 @@ ohos_shared_library("abilitykit_native") { "${ability_runtime_native_path}/ability/native/free_install_observer_proxy.cpp", "${ability_runtime_native_path}/ability/native/free_install_observer_stub.cpp", "${ability_runtime_native_path}/ability/native/insight_intent_host_client.cpp", + "${ability_runtime_native_path}/ability/native/js_deferred_callback.cpp", "${ability_runtime_native_path}/ability/native/js_free_install_observer.cpp", "${ability_runtime_native_path}/ability/native/js_query_erms_observer.cpp", + "${ability_runtime_native_path}/ability/native/js_start_abilities_observer.cpp", "${ability_runtime_native_path}/ability/native/new_ability_impl.cpp", "${ability_runtime_native_path}/ability/native/query_erms_observer_proxy.cpp", "${ability_runtime_native_path}/ability/native/query_erms_observer_stub.cpp", diff --git a/frameworks/native/ability/native/ability_thread.cpp b/frameworks/native/ability/native/ability_thread.cpp index 4832062a632..c8de6cc3203 100644 --- a/frameworks/native/ability/native/ability_thread.cpp +++ b/frameworks/native/ability/native/ability_thread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device 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 @@ -301,5 +301,10 @@ void AbilityThread::ScheduleAbilityRequestSuccess(const std::string &requestId, { TAG_LOGD(AAFwkTag::ABILITY, "called"); } + +void AbilityThread::ScheduleAbilitiesRequestDone(const std::string &requestKey, int32_t resultCode) +{ + TAG_LOGD(AAFwkTag::ABILITY, "called"); +} } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/native/ability/native/extension_ability_thread.cpp b/frameworks/native/ability/native/extension_ability_thread.cpp index d44ae3c6761..9cbfdb94f24 100644 --- a/frameworks/native/ability/native/extension_ability_thread.cpp +++ b/frameworks/native/ability/native/extension_ability_thread.cpp @@ -22,6 +22,7 @@ #include "freeze_util.h" #include "hilog_tag_wrapper.h" #include "hitrace_meter.h" +#include "js_start_abilities_observer.h" #include "ui_extension_utils.h" namespace OHOS { @@ -576,6 +577,31 @@ void ExtensionAbilityThread::SendResult(int requestCode, int resultCode, const W TAG_LOGD(AAFwkTag::EXT, "End"); } +void ExtensionAbilityThread::ScheduleAbilitiesRequestDone(const std::string &startTime, + const int32_t resultCode) +{ + TAG_LOGD(AAFwkTag::EXT, "ScheduleAbilitiesRequestDone"); + if (abilityHandler_ == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null abilityHandler_"); + return; + } + + wptr weak = this; + auto task = [weak, startTime, resultCode]() { + auto abilityThread = weak.promote(); + if (abilityThread == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null abilityThread"); + return; + } + + JsStartAbilitiesObserver::GetInstance().HandleFinished(startTime, resultCode); + }; + bool ret = abilityHandler_->PostTask(task); + if (!ret) { + TAG_LOGE(AAFwkTag::EXT, "PostTask error"); + } +} + void ExtensionAbilityThread::NotifyMemoryLevel(int32_t level) { TAG_LOGD(AAFwkTag::EXT, "result: %{public}d", level); diff --git a/frameworks/native/ability/native/js_deferred_callback.cpp b/frameworks/native/ability/native/js_deferred_callback.cpp new file mode 100644 index 00000000000..b21a517329e --- /dev/null +++ b/frameworks/native/ability/native/js_deferred_callback.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device 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. + */ + +#include "js_deferred_callback.h" + +#include "ability_manager_errors.h" +#include "ability_business_error.h" +#include "hilog_tag_wrapper.h" +#include "js_error_utils.h" +#include "js_runtime_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +JsDeferredCallback::JsDeferredCallback(napi_env env): env(env) { + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "null env"); + return; + } + napi_create_promise(env, &deferred, &result); +} + +void JsDeferredCallback::operator()(int32_t resultCode) { + if (deferred == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "null deferred"); + return; + } + if (resultCode == ERR_OK) { + napi_value value = CreateJsUndefined(env); + napi_resolve_deferred(env, deferred, value); + } else { + napi_value error = CreateJsError(env, GetJsErrorCodeByNativeError(resultCode)); + napi_reject_deferred(env, deferred, error); + } +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/js_service_extension_context.cpp b/frameworks/native/ability/native/js_service_extension_context.cpp index bc867e5164d..52b19a0398a 100644 --- a/frameworks/native/ability/native/js_service_extension_context.cpp +++ b/frameworks/native/ability/native/js_service_extension_context.cpp @@ -24,8 +24,10 @@ #include "js_extension_context.h" #include "js_error_utils.h" #include "js_data_struct_converter.h" +#include "js_deferred_callback.h" #include "js_runtime.h" #include "js_runtime_utils.h" +#include "js_start_abilities_observer.h" #include "napi/native_api.h" #include "napi_common_ability.h" #include "napi_common_want.h" @@ -835,7 +837,8 @@ private: TAG_LOGD(AAFwkTag::UI_EXT, "startAbilities wantListLength: %{public}zu", wantList.size()); - napi_value result = nullptr; + JsDeferredCallback callback(env); + JsStartAbilitiesObserver::GetInstance().AddObserver(requestKey, callback); auto innerErrCode = std::make_shared(ERR_OK); NapiAsyncTask::ExecuteCallback execute = [weak = context_, wantList, requestKey, innerErrCode]() { auto context = weak.lock(); @@ -847,19 +850,19 @@ private: *innerErrCode = context->StartAbilities(wantList, requestKey); }; - NapiAsyncTask::CompleteCallback complete = [innerErrCode, weak = context_] - (napi_env env, NapiAsyncTask& task, int32_t status) { + NapiAsyncTask::CompleteCallback complete = [innerErrCode, weak = context_, requestKey] + (napi_env, NapiAsyncTask&, int32_t) { TAG_LOGI(AAFwkTag::UI_EXT, "startAbilities complete innerErrCode: %{public}d", *innerErrCode); - if (*innerErrCode == 0) { - task.Resolve(env, CreateJsUndefined(env)); + if (*innerErrCode == AAFwk::START_ABILITIES_WAITING_SPECIFIED_CODE) { + TAG_LOGI(AAFwkTag::SERVICE_EXT, "startAbilities waiting specified."); return; } - task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode)); + JsStartAbilitiesObserver::GetInstance().HandleFinished(requestKey, *innerErrCode); }; NapiAsyncTask::ScheduleHighQos("JSUIExtensionConnection::OnStartAbilities", env, - CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result)); - return result; + CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), nullptr)); + return callback.result; } bool UnwrapWantList(napi_env env, NapiCallbackInfo &info, std::vector &wantList) diff --git a/frameworks/native/ability/native/js_start_abilities_observer.cpp b/frameworks/native/ability/native/js_start_abilities_observer.cpp new file mode 100644 index 00000000000..d6f995cb51a --- /dev/null +++ b/frameworks/native/ability/native/js_start_abilities_observer.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Huawei Device 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. + */ + +#include "js_start_abilities_observer.h" + +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +JsStartAbilitiesObserver &JsStartAbilitiesObserver::GetInstance() +{ + static JsStartAbilitiesObserver instance; + return instance; +} + +void JsStartAbilitiesObserver::AddObserver(const std::string &requestKey, std::function &&callback) +{ + std::lock_guard lock(jsObserverObjectListLock_); + jsObserverObjectList_.emplace(requestKey, std::move(callback)); +} + +void JsStartAbilitiesObserver::HandleFinished(const std::string &requestKey, int32_t resultCode) +{ + std::function callback; + { + std::lock_guard lock(jsObserverObjectListLock_); + auto it = jsObserverObjectList_.find(requestKey); + if (it != jsObserverObjectList_.end()) { + callback = std::move(it->second); + jsObserverObjectList_.erase(it); + } + } + if (callback) { + callback(resultCode); + } else { + TAG_LOGE(AAFwkTag::ABILITY, "null callback"); + } +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/ui_extension_base/js_ui_extension_context.cpp b/frameworks/native/ability/native/ui_extension_base/js_ui_extension_context.cpp index 6b1b795567f..b383a4bc7c9 100755 --- a/frameworks/native/ability/native/ui_extension_base/js_ui_extension_context.cpp +++ b/frameworks/native/ability/native/ui_extension_base/js_ui_extension_context.cpp @@ -26,8 +26,10 @@ #include "js_extension_context.h" #include "js_error_utils.h" #include "js_data_struct_converter.h" +#include "js_deferred_callback.h" #include "js_runtime.h" #include "js_runtime_utils.h" +#include "js_start_abilities_observer.h" #include "js_uiservice_uiext_connection.h" #include "js_ui_service_proxy.h" #include "napi/native_api.h" @@ -590,7 +592,8 @@ napi_value JsUIExtensionContext::OnStartAbilities(napi_env env, NapiCallbackInfo TAG_LOGD(AAFwkTag::UI_EXT, "startAbilities wantListLength: %{public}zu", wantList.size()); - napi_value result = nullptr; + JsDeferredCallback callback(env); + JsStartAbilitiesObserver::GetInstance().AddObserver(requestKey, callback); auto innerErrCode = std::make_shared(ERR_OK); NapiAsyncTask::ExecuteCallback execute = [weak = context_, wantList, requestKey, innerErrCode]() { auto context = weak.lock(); @@ -602,19 +605,19 @@ napi_value JsUIExtensionContext::OnStartAbilities(napi_env env, NapiCallbackInfo *innerErrCode = context->StartAbilities(wantList, requestKey); }; - NapiAsyncTask::CompleteCallback complete = [innerErrCode, weak = context_] - (napi_env env, NapiAsyncTask& task, int32_t status) { + NapiAsyncTask::CompleteCallback complete = [innerErrCode, weak = context_, requestKey] + (napi_env, NapiAsyncTask&, int32_t) { TAG_LOGI(AAFwkTag::UI_EXT, "startAbilities complete innerErrCode: %{public}d", *innerErrCode); - if (*innerErrCode == 0) { - task.Resolve(env, CreateJsUndefined(env)); + if (*innerErrCode == AAFwk::START_ABILITIES_WAITING_SPECIFIED_CODE) { + TAG_LOGI(AAFwkTag::SERVICE_EXT, "startAbilities waiting specified."); return; } - task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode)); + JsStartAbilitiesObserver::GetInstance().HandleFinished(requestKey, *innerErrCode); }; NapiAsyncTask::ScheduleHighQos("JSUIExtensionConnection::OnStartAbilities", env, - CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result)); - return result; + CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), nullptr)); + return callback.result; } bool JsUIExtensionContext::UnwrapWantList(napi_env env, NapiCallbackInfo &info, std::vector &wantList) diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_errors.h b/interfaces/inner_api/ability_manager/include/ability_manager_errors.h index ec0a023c67f..8d93e794971 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_errors.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_errors.h @@ -922,7 +922,7 @@ enum { START_ABILITIES_INTERCEPTOR_CHECK_FAILED = 2097370, - START_ABILITIES_WAITTING_SPECIFIED_CODE = 2097371, + START_ABILITIES_WAITING_SPECIFIED_CODE = 2097371, /* * Result(2097372) for IPC write Int32 failed. diff --git a/interfaces/inner_api/ability_manager/include/ability_scheduler_interface.h b/interfaces/inner_api/ability_manager/include/ability_scheduler_interface.h index a9365cf1c33..f1be91f3373 100644 --- a/interfaces/inner_api/ability_manager/include/ability_scheduler_interface.h +++ b/interfaces/inner_api/ability_manager/include/ability_scheduler_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device 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 @@ -312,6 +312,9 @@ public: virtual void ScheduleAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element) = 0; + virtual void ScheduleAbilitiesRequestDone(const std::string &requestKey, + int32_t resultCode) = 0; + enum { // ipc id for scheduling ability to a state of life cycle SCHEDULE_ABILITY_TRANSACTION = 0, @@ -413,7 +416,9 @@ public: SCHEDULE_ABILITY_REQUEST_FAILURE, - SCHEDULE_ABILITY_REQUEST_SUCCESS + SCHEDULE_ABILITY_REQUEST_SUCCESS, + + SCHEDULE_ABILITIES_REQUEST_DONE, }; }; } // namespace AAFwk diff --git a/interfaces/kits/native/ability/native/ability_thread.h b/interfaces/kits/native/ability/native/ability_thread.h index 6dd0fe9cded..8ce76dc4961 100644 --- a/interfaces/kits/native/ability/native/ability_thread.h +++ b/interfaces/kits/native/ability/native/ability_thread.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device 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 @@ -364,6 +364,8 @@ public: void ScheduleAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element) override; + void ScheduleAbilitiesRequestDone(const std::string &requestKey, int32_t resultCode) override; + sptr token_; std::shared_ptr abilityHandler_ = nullptr; std::shared_ptr runner_ = nullptr; diff --git a/interfaces/kits/native/ability/native/extension_ability_thread.h b/interfaces/kits/native/ability/native/extension_ability_thread.h index 7df082e0835..7b166680de9 100644 --- a/interfaces/kits/native/ability/native/extension_ability_thread.h +++ b/interfaces/kits/native/ability/native/extension_ability_thread.h @@ -135,6 +135,8 @@ public: void ScheduleAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element) override; + void ScheduleAbilitiesRequestDone(const std::string &requestKey, int32_t resultCode) override; + private: /** * @brief Dump Ability Info Inner diff --git a/interfaces/kits/native/ability/native/js_deferred_callback.h b/interfaces/kits/native/ability/native/js_deferred_callback.h new file mode 100644 index 00000000000..a3ccfab760e --- /dev/null +++ b/interfaces/kits/native/ability/native/js_deferred_callback.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device 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 OHOS_ABILITY_RUNTIME_JS_DEFERRED_CALLBACK_H +#define OHOS_ABILITY_RUNTIME_JS_DEFERRED_CALLBACK_H + +#include "native_engine/native_engine.h" + +namespace OHOS { +namespace AbilityRuntime { +struct JsDeferredCallback { +public: + explicit JsDeferredCallback(napi_env env); + void operator()(int32_t resultCode); + + napi_env env = nullptr; + napi_deferred deferred = nullptr; + napi_value result = nullptr; +}; +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_JS_DEFERRED_CALLBACK_H \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/js_start_abilities_observer.h b/interfaces/kits/native/ability/native/js_start_abilities_observer.h new file mode 100644 index 00000000000..1bbce54816a --- /dev/null +++ b/interfaces/kits/native/ability/native/js_start_abilities_observer.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device 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 OHOS_ABILITY_RUNTIME_JS_START_ABILITIES_OBSERVER_H +#define OHOS_ABILITY_RUNTIME_JS_START_ABILITIES_OBSERVER_H + +#include +#include +#include +#include + +namespace OHOS { +namespace AbilityRuntime { +class JsStartAbilitiesObserver { +public: + static JsStartAbilitiesObserver &GetInstance(); + ~JsStartAbilitiesObserver() = default; + void AddObserver(const std::string &requestKey, std::function &&callback); + void HandleFinished(const std::string &requestKey, int32_t resultCode); +protected: + JsStartAbilitiesObserver() = default; +private: + std::mutex jsObserverObjectListLock_; + std::map> jsObserverObjectList_; +}; +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_JS_START_ABILITIES_OBSERVER_H \ No newline at end of file diff --git a/services/abilitymgr/include/ability_record.h b/services/abilitymgr/include/ability_record.h index 1716e57c95f..28e81d81536 100644 --- a/services/abilitymgr/include/ability_record.h +++ b/services/abilitymgr/include/ability_record.h @@ -1181,6 +1181,7 @@ public: const std::string &message); void NotifyAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element); + void NotifyAbilitiesRequestDone(const std::string &requestKey, int32_t resultCode); void ScheduleCollaborate(const Want &want); diff --git a/services/abilitymgr/include/ability_scheduler_proxy.h b/services/abilitymgr/include/ability_scheduler_proxy.h index e25c6ac6597..c1412b08bc6 100644 --- a/services/abilitymgr/include/ability_scheduler_proxy.h +++ b/services/abilitymgr/include/ability_scheduler_proxy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device 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 @@ -338,6 +338,8 @@ public: void ScheduleAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element) override; + void ScheduleAbilitiesRequestDone(const std::string &requestKey, int32_t resultCode) override; + private: bool WriteInterfaceToken(MessageParcel &data); int32_t SendTransactCmd(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); diff --git a/services/abilitymgr/include/ability_scheduler_stub.h b/services/abilitymgr/include/ability_scheduler_stub.h index e85b2d94faa..4c321174706 100644 --- a/services/abilitymgr/include/ability_scheduler_stub.h +++ b/services/abilitymgr/include/ability_scheduler_stub.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device 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 @@ -82,6 +82,7 @@ private: int CollaborateDataInner(MessageParcel &data); int ScheduleAbilityRequestFailureInner(MessageParcel &data); int ScheduleAbilityRequestSuccessInner(MessageParcel &data); + int ScheduleAbilitiesRequestDoneInner(MessageParcel &data); }; /** diff --git a/services/abilitymgr/include/lifecycle_deal.h b/services/abilitymgr/include/lifecycle_deal.h index 85132710b30..f0082b76335 100644 --- a/services/abilitymgr/include/lifecycle_deal.h +++ b/services/abilitymgr/include/lifecycle_deal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device 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 @@ -89,6 +89,7 @@ public: void NotifyAbilityRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, const std::string &message); void NotifyAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element); + void NotifyAbilitiesRequestDone(const std::string &requestKey, int32_t resultCode); private: sptr GetScheduler(); diff --git a/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h b/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h index 3747cccfb44..b0b2e02a6fb 100644 --- a/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h +++ b/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h @@ -55,11 +55,11 @@ struct SpecifiedRequest { }; struct AbilitiesRequest { - std::vector waitingRequestIdList; - std::vector abilityRequestList; - std::vector> UnsortedSessionInfoList; - - AbilitiesRequest(std::vector abilityRequestList) : abilityRequestList(abilityRequestList) {} + int32_t requestListId = -1; + std::string requestKey; + std::vector>> sessionInfoList; + uint32_t doneCount = 0; + sptr callerToken; }; class UIAbilityLifecycleManager : public std::enable_shared_from_this { @@ -164,7 +164,8 @@ public: void SetRootSceneSession(const sptr &rootSceneSession); int NotifySCBToStartUIAbility(AbilityRequest &abilityRequest); - int32_t NotifySCBToStartUIAbilities(std::vector &abilityRequestList); + int32_t NotifySCBToStartUIAbilities(std::vector &abilityRequestList, + const std::string &requestKey); int NotifySCBToPreStartUIAbility(const AbilityRequest &abilityRequest, sptr &sessionInfo); @@ -438,8 +439,8 @@ private: sptr CreateSessionInfo(const AbilityRequest &abilityRequest) const; int NotifySCBPendingActivation(sptr &sessionInfo, const AbilityRequest &abilityRequest, std::string &errMsg); - int32_t BatchNotifySCBPendingActivation(std::vector> &sessionInfoList, - const std::vector &abilityRequestList, std::string &errMsg); + int32_t BatchNotifySCBPendingActivation(const AbilitiesRequest &abilitiesRequest); + void HandleAbilitiesRequestDone(int32_t requestId, int32_t requestListId, sptr sessionInfo); bool IsHookModule(const AbilityRequest &abilityRequest) const; int ResolveAbility(const std::shared_ptr &targetAbility, const AbilityRequest &abilityRequest) const; std::vector> GetAbilityRecordsByNameInner(const AppExecFwk::ElementName &element); @@ -448,11 +449,11 @@ private: void NotifyStartSpecifiedAbility(AbilityRequest &request, const AAFwk::Want &want); void NotifyRestartSpecifiedAbility(const AbilityRequest &request, const sptr &token); - int MoveAbilityToFront(const AbilityRequest &abilityRequest, const std::shared_ptr &abilityRecord, - std::shared_ptr callerAbility, std::shared_ptr startOptions, int32_t requestId); + int32_t MoveAbilityToFront(const SpecifiedRequest &specifiedRequest, + const std::shared_ptr abilityRecord, std::shared_ptr callerAbility); int SendSessionInfoToSCB(std::shared_ptr &callerAbility, sptr &sessionInfo); - int StartAbilityBySpecifed(const AbilityRequest &abilityRequest, std::shared_ptr &callerAbility, - int32_t requestId); + int32_t StartAbilityBySpecifed(const SpecifiedRequest &specifiedRequest, + std::shared_ptr callerAbility); void SetLastExitReason(std::shared_ptr &abilityRecord) const; void SetReceiverInfo(const AbilityRequest &abilityRequest, std::shared_ptr &abilityRecord) const; @@ -508,7 +509,7 @@ private: bool HandleStartSpecifiedCold(AbilityRequest &abilityRequest, sptr sessionInfo, uint32_t sceneFlag); bool HandleColdAcceptWantDone(const AAFwk::Want &want, const std::string &flag, const SpecifiedRequest &specifiedRequest); - void HandleLegacyAcceptWantDone(AbilityRequest &abilityRequest, int32_t requestId, + void HandleLegacyAcceptWantDone(SpecifiedRequest &specifiedRequest, const std::string &flag, const AAFwk::Want &want); std::shared_ptr GetSpecifiedRequest(int32_t requestId); bool CheckPrepareTerminateTokens(const std::vector> &tokens, @@ -523,7 +524,8 @@ private: std::shared_ptr uiAbilityRecord, bool isColdStart); bool TryProcessHookModule(SpecifiedRequest &specifiedRequest, bool isHookModule); bool IsStartSpecifiedProcessRequest(const AbilityRequest &abilityRequest); - int32_t StartSpecifiedProcessRequest(const AbilityRequest &abilityRequest); + int32_t StartSpecifiedProcessRequest(const AbilityRequest &abilityRequest, + std::shared_ptr abilitiesRequest); void RemoveInstanceKey(const AbilityRequest &abilityRequest) const; int32_t userId_ = -1; @@ -564,7 +566,6 @@ private: std::vector> prepareTerminateByPidRecords_; std::unordered_map> hookSpecifiedMap_; - ffrt::mutex startAbilitiesProcessLock_; std::map> abilitiesRequestMap_; std::mutex startingPidsMutex_; std::vector startingPids_; diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index 358a661bd7f..f1feae3850f 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -2213,7 +2213,7 @@ ErrCode AbilityManagerService::StartAbilities(const std::vector &wa } auto uiAbilityManager = GetUIAbilityManagerByUserId(oriValidUserId); CHECK_POINTER_AND_RETURN(uiAbilityManager, ERR_INVALID_VALUE); - return uiAbilityManager->NotifySCBToStartUIAbilities(abilityRequestList); + return uiAbilityManager->NotifySCBToStartUIAbilities(abilityRequestList, requestKey); } int32_t AbilityManagerService::StartAbilitiesHandleWant(std::vector &abilityRequestList, diff --git a/services/abilitymgr/src/ability_record.cpp b/services/abilitymgr/src/ability_record.cpp index 2eb24db7dbf..7df6435a3eb 100644 --- a/services/abilitymgr/src/ability_record.cpp +++ b/services/abilitymgr/src/ability_record.cpp @@ -3876,6 +3876,12 @@ void AbilityRecord::NotifyAbilityRequestSuccess(const std::string &requestId, co lifecycleDeal_->NotifyAbilityRequestSuccess(requestId, element); } +void AbilityRecord::NotifyAbilitiesRequestDone(const std::string &requestKey, int32_t resultCode) +{ + CHECK_POINTER(lifecycleDeal_); + lifecycleDeal_->NotifyAbilitiesRequestDone(requestKey, resultCode); +} + void AbilityRecord::UpdateUIExtensionBindInfo(const WantParams &wantParams) { if (!UIExtensionUtils::IsUIExtension(GetAbilityInfo().extensionAbilityType)) { diff --git a/services/abilitymgr/src/ability_scheduler_proxy.cpp b/services/abilitymgr/src/ability_scheduler_proxy.cpp index 0e5bfb278c4..fd1bac56895 100644 --- a/services/abilitymgr/src/ability_scheduler_proxy.cpp +++ b/services/abilitymgr/src/ability_scheduler_proxy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device 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 @@ -1294,5 +1294,31 @@ void AbilitySchedulerProxy::ScheduleAbilityRequestSuccess(const std::string &req } return; } + +void AbilitySchedulerProxy::ScheduleAbilitiesRequestDone(const std::string &requestKey, int32_t resultCode) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!WriteInterfaceToken(data)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write interface token failed"); + return; + } + + if (!data.WriteString(requestKey)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write requestKey failed"); + return; + } + if (!data.WriteInt32(resultCode)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write resultCode failed"); + return; + } + + int32_t err = SendTransactCmd(IAbilityScheduler::SCHEDULE_ABILITIES_REQUEST_DONE, data, reply, option); + if (err != NO_ERROR) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "fail, err: %{public}d", err); + } + return; +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_scheduler_stub.cpp b/services/abilitymgr/src/ability_scheduler_stub.cpp index 47ee11a0318..43269a019df 100644 --- a/services/abilitymgr/src/ability_scheduler_stub.cpp +++ b/services/abilitymgr/src/ability_scheduler_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device 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 @@ -160,6 +160,8 @@ int AbilitySchedulerStub::OnRemoteRequestInnerThird( return ScheduleAbilityRequestFailureInner(data); case SCHEDULE_ABILITY_REQUEST_SUCCESS: return ScheduleAbilityRequestSuccessInner(data); + case SCHEDULE_ABILITIES_REQUEST_DONE: + return ScheduleAbilitiesRequestDoneInner(data); } return ERR_CODE_NOT_EXIST; } @@ -780,6 +782,14 @@ int AbilitySchedulerStub::ScheduleAbilityRequestSuccessInner(MessageParcel &data return NO_ERROR; } +int AbilitySchedulerStub::ScheduleAbilitiesRequestDoneInner(MessageParcel &data) +{ + std::string requestKey = data.ReadString(); + int32_t resultCode = data.ReadInt32(); + ScheduleAbilitiesRequestDone(requestKey, resultCode); + return NO_ERROR; +} + void AbilitySchedulerRecipient::OnRemoteDied(const wptr &remote) { TAG_LOGE(AAFwkTag::ABILITYMGR, "call"); diff --git a/services/abilitymgr/src/lifecycle_deal.cpp b/services/abilitymgr/src/lifecycle_deal.cpp index 8fc5a020411..adc2c5081a3 100644 --- a/services/abilitymgr/src/lifecycle_deal.cpp +++ b/services/abilitymgr/src/lifecycle_deal.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device 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 @@ -215,5 +215,12 @@ void LifecycleDeal::NotifyAbilityRequestSuccess(const std::string &requestId, co CHECK_POINTER(abilityScheduler); abilityScheduler->ScheduleAbilityRequestSuccess(requestId, element); } + +void LifecycleDeal::NotifyAbilitiesRequestDone(const std::string &requestKey, int32_t resultCode) +{ + auto abilityScheduler = GetScheduler(); + CHECK_POINTER(abilityScheduler); + abilityScheduler->ScheduleAbilitiesRequestDone(requestKey, resultCode); +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp index b066ac4827c..eb68e4ac68f 100644 --- a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp +++ b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp @@ -592,7 +592,7 @@ int UIAbilityLifecycleManager::NotifySCBToStartUIAbility(AbilityRequest &ability return StartWithPersistentIdByDistributed(abilityRequest, persistentId); } if (IsStartSpecifiedProcessRequest(abilityRequest)) { - return StartSpecifiedProcessRequest(abilityRequest); + return StartSpecifiedProcessRequest(abilityRequest, nullptr); } const auto &abilityInfo = abilityRequest.abilityInfo; auto requestId = GetRequestId(); @@ -642,7 +642,8 @@ int UIAbilityLifecycleManager::NotifySCBToStartUIAbility(AbilityRequest &ability return ret; } -int UIAbilityLifecycleManager::NotifySCBToStartUIAbilities(std::vector &abilityRequestList) +int UIAbilityLifecycleManager::NotifySCBToStartUIAbilities(std::vector &abilityRequestList, + const std::string &requestKey) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); TAG_LOGD(AAFwkTag::ABILITYMGR, "StartAbilities Call NotifySCBToStartUIAbilities"); @@ -660,31 +661,32 @@ int UIAbilityLifecycleManager::NotifySCBToStartUIAbilities(std::vector guard(sessionLock_); - requestListId = GetRequestId(); - } - std::shared_ptr abilitiesRequest = nullptr; - // std::shared_ptr - abilitiesRequest = std::make_shared(abilityRequestList); - // 持锁修改abilitiesRequestMap_ - { - std::lock_guard guard2(startAbilitiesProcessLock_); - abilitiesRequestMap_.emplace(requestListId, abilitiesRequest); - } - // 开始处理分支场景 + + std::lock_guard guard2(sessionLock_); + auto abilitiesRequest = std::make_shared(); + int32_t requestListId = GetRequestId(); + abilitiesRequest->requestListId = requestListId; + abilitiesRequestMap_.emplace(requestListId, abilitiesRequest); + abilitiesRequest->requestKey = requestKey; for (AbilityRequest &abilityRequest : abilityRequestList) { + abilitiesRequest->callerToken = abilityRequest.callerToken; if (IsStartSpecifiedProcessRequest(abilityRequest)) { - abilitiesRequestMap_.erase(requestListId); - return ERR_CAPABILITY_NOT_SUPPORT; + auto ret = StartSpecifiedProcessRequest(abilityRequest, abilitiesRequest); + if (ret != ERR_OK) { + return ret; + } + continue; } const auto &abilityInfo = abilityRequest.abilityInfo; auto requestId = GetRequestId(); auto isSpecified = (abilityInfo.launchMode == AppExecFwk::LaunchMode::SPECIFIED); if (isSpecified) { - abilitiesRequestMap_.erase(requestListId); - return ERR_CAPABILITY_NOT_SUPPORT; + auto specifiedRequest = std::make_shared(requestId, abilityRequest); + specifiedRequest->preCreateProcessName = true; + specifiedRequest->requestListId = abilitiesRequest->requestListId; + abilitiesRequest->sessionInfoList.emplace_back(requestId, nullptr); + AddSpecifiedRequest(specifiedRequest); + continue; } auto sessionInfo = CreateSessionInfo(abilityRequest); sessionInfo->requestCode = abilityRequest.requestCode; @@ -696,38 +698,31 @@ int UIAbilityLifecycleManager::NotifySCBToStartUIAbilities(std::vectorpersistentId, userId_, requestId); // 将初始化完成的sessionInfo插入对应的abilitiesRequest中 - abilitiesRequest->UnsortedSessionInfoList.emplace_back(sessionInfo); + abilitiesRequest->sessionInfoList.emplace_back(requestId, sessionInfo); + abilitiesRequest->doneCount++; } // 判断是否需要等待Specified - if (!abilitiesRequest->waitingRequestIdList.empty()) { - // 新增错误码 返回此错误码表示进入等待 - return START_ABILITIES_WAITTING_SPECIFIED_CODE; + if (abilitiesRequest->doneCount < abilityRequestList.size()) { + return START_ABILITIES_WAITING_SPECIFIED_CODE; } - // 进入这个分支,SessionInfoList是有序的,不用重排 - std::string errMsg; - TAG_LOGI(AAFwkTag::ABILITYMGR, "StartAbilities normal start. sessionInfoList size: %{public}zu", - abilitiesRequest->UnsortedSessionInfoList.size()); - // sptr sessionInfo0 = &sessionInfoList[0]; - int ret = BatchNotifySCBPendingActivation( - abilitiesRequest->UnsortedSessionInfoList, abilityRequestList, errMsg); - - for (auto sessionInfo : abilitiesRequest->UnsortedSessionInfoList) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "StartAbilities normal size: %{public}zu", abilityRequestList.size()); + int ret = BatchNotifySCBPendingActivation(*abilitiesRequest); + for (auto &[id, sessionInfo] : abilitiesRequest->sessionInfoList) { sessionInfo->want.RemoveAllFd(); } abilitiesRequestMap_.erase(requestListId); return ret; } -int32_t UIAbilityLifecycleManager::BatchNotifySCBPendingActivation(std::vector> &sessionInfoList, - const std::vector &abilityRequestList, std::string &errMsg) +int32_t UIAbilityLifecycleManager::BatchNotifySCBPendingActivation(const AbilitiesRequest &abilitiesRequest) { - // process sessionInfoList - for (auto sessionInfo : sessionInfoList) { + std::vector> sessionInfoList; + for (const auto &[id, sessionInfo] : abilitiesRequest.sessionInfoList) { if (sessionInfo == nullptr) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "sessionInfo is nullptr"); - errMsg = "sessionInfo is nullptr"; - return ERR_INVALID_VALUE; + TAG_LOGE(AAFwkTag::ABILITYMGR, "sessionInfo nullptr"); + continue; } + sessionInfoList.push_back(sessionInfo); bool hasStartWindowOption = (sessionInfo->startWindowOption != nullptr); bool hasStartWindow = hasStartWindowOption ? sessionInfo->startWindowOption->hasStartWindow : false; std::string backgroundColor = @@ -738,15 +733,12 @@ int32_t UIAbilityLifecycleManager::BatchNotifySCBPendingActivation(std::vector callerAbilityRecord; - callerAbilityRecord = GetAbilityRecordByToken(abilityRequestList[0].callerToken); - if (callerAbilityRecord == nullptr || callerAbilityRecord->GetRestartAppFlag()) - { + auto callerAbilityRecord = GetAbilityRecordByToken(abilitiesRequest.callerToken); + if (callerAbilityRecord == nullptr || callerAbilityRecord->GetRestartAppFlag()) { // 使用rootSession启动 callerRecord存在 callerSession不存在 auto tmpSceneSession = iface_cast(rootSceneSession_); if (tmpSceneSession == nullptr) { - errMsg = "null tmpSceneSession, scb does not exist"; - TAG_LOGE(AAFwkTag::ABILITYMGR, "%{public}s", errMsg.c_str()); + TAG_LOGE(AAFwkTag::ABILITYMGR, "null tmpSceneSession, scb does not exist"); return ERR_INVALID_VALUE; } for (auto sessionInfo : sessionInfoList) { @@ -764,24 +756,52 @@ int32_t UIAbilityLifecycleManager::BatchNotifySCBPendingActivation(std::vectorwant.GetStringParam(KEY_REQUEST_ID); if (!requestId.empty()) { - callerAbilityRecord->NotifyAbilityRequestSuccess(requestId, abilityRequest.want.GetElement()); + callerAbilityRecord->NotifyAbilityRequestSuccess(requestId, sessionInfo->want.GetElement()); } - const_cast(abilityRequest).want.RemoveParam(KEY_REQUEST_ID); + sessionInfo->want.RemoveParam(KEY_REQUEST_ID); } TAG_LOGI(AAFwkTag::ABILITYMGR, "scb call, StartAbilities BatchNotifySCBPendingActivation for callerSession"); return static_cast(callerSession->PendingSessionActivation(sessionInfoList[0])); } +void UIAbilityLifecycleManager::HandleAbilitiesRequestDone(int32_t requestId, int32_t requestListId, + sptr sessionInfo) +{ + auto it = abilitiesRequestMap_.find(requestListId); + if (it == abilitiesRequestMap_.end()) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "requestListId: %{public}d not found", requestListId); + return; + } + auto abilitiesRequest = it->second; + CHECK_POINTER_LOG(abilitiesRequest, "abilitiesRequest nullptr"); + abilitiesRequest->doneCount++; + auto &sessionInfoList = abilitiesRequest->sessionInfoList; + for (auto &item : sessionInfoList) { + if (item.first == requestId) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "requestdone %{public}d", requestId); + item.second = sessionInfo; + } + } + if (abilitiesRequest->doneCount == sessionInfoList.size()) { + int32_t ret = BatchNotifySCBPendingActivation(*abilitiesRequest); + abilitiesRequestMap_.erase(it); + auto callerRecord = Token::GetAbilityRecordByToken(abilitiesRequest->callerToken); + if (callerRecord == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "callerRecord not exist."); + return; + } + callerRecord->NotifyAbilitiesRequestDone(abilitiesRequest->requestKey, ret); + } +} + int32_t UIAbilityLifecycleManager::NotifySCBToRecoveryAfterInterception(const AbilityRequest &abilityRequest) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); std::lock_guard guard(sessionLock_); if (IsStartSpecifiedProcessRequest(abilityRequest)) { - return StartSpecifiedProcessRequest(abilityRequest); + return StartSpecifiedProcessRequest(abilityRequest, nullptr); } const auto &abilityInfo = abilityRequest.abilityInfo; auto isPlugin = StartupUtil::IsStartPlugin(abilityRequest.want); @@ -2246,13 +2266,14 @@ void UIAbilityLifecycleManager::OnAcceptWantResponse(const AAFwk::Want &want, co } } - HandleLegacyAcceptWantDone(request->abilityRequest, requestId, flag, want); + HandleLegacyAcceptWantDone(*request, flag, want); } -void UIAbilityLifecycleManager::HandleLegacyAcceptWantDone(AbilityRequest &abilityRequest, int32_t requestId, +void UIAbilityLifecycleManager::HandleLegacyAcceptWantDone(SpecifiedRequest &specifiedRequest, const std::string &flag, const AAFwk::Want &want) { TAG_LOGI(AAFwkTag::ABILITYMGR, "%{public}s", want.GetElement().GetURI().c_str()); + auto &abilityRequest = specifiedRequest.abilityRequest; auto callerAbility = GetAbilityRecordByToken(abilityRequest.callerToken); abilityRequest.specifiedFlag = flag; if (!flag.empty()) { @@ -2269,13 +2290,13 @@ void UIAbilityLifecycleManager::HandleLegacyAcceptWantDone(AbilityRequest &abili abilityRecord = iter->second; CHECK_POINTER_LOG(abilityRecord, "OnAcceptWantResponse abilityRecord null"); UpdateAbilityRecordLaunchReason(abilityRequest, abilityRecord); - MoveAbilityToFront(abilityRequest, abilityRecord, callerAbility, nullptr, requestId); + MoveAbilityToFront(specifiedRequest, abilityRecord, callerAbility); NotifyRestartSpecifiedAbility(abilityRequest, abilityRecord->GetToken()); return; } } NotifyStartSpecifiedAbility(abilityRequest, want); - StartAbilityBySpecifed(abilityRequest, callerAbility, requestId); + StartAbilityBySpecifed(specifiedRequest, callerAbility); } void UIAbilityLifecycleManager::OnStartSpecifiedAbilityTimeoutResponse(int32_t requestId) @@ -2311,6 +2332,7 @@ void UIAbilityLifecycleManager::OnStartSpecifiedFailed(int32_t requestId) RemoveInstanceKey(curRequest->abilityRequest); } + HandleAbilitiesRequestDone(requestId, curRequest->requestListId, nullptr); auto nextRequest = PopAndGetNextSpecified(requestId); if (nextRequest) { StartSpecifiedRequest(*nextRequest); @@ -2350,6 +2372,10 @@ void UIAbilityLifecycleManager::OnStartSpecifiedProcessResponse(const std::strin (abilityRequest.abilityInfo.applicationInfo.bundleType == AppExecFwk::BundleType::ATOMIC_SERVICE); TAG_LOGI(AAFwkTag::ABILITYMGR, "reused sessionId: %{public}d, userId: %{public}d", sessionInfo->persistentId, abilityRequest.userId); + if (request->requestListId != REQUEST_LIST_ID_INIT) { + HandleAbilitiesRequestDone(requestId, request->requestListId, sessionInfo); + return; + } std::string errMsg; NotifySCBPendingActivation(sessionInfo, abilityRequest, errMsg); } @@ -2362,6 +2388,7 @@ void UIAbilityLifecycleManager::OnStartSpecifiedProcessTimeoutResponse(int32_t r if (request != nullptr) { TAG_LOGI(AAFwkTag::ABILITYMGR, "removing instance key"); RemoveInstanceKey(request->abilityRequest); + HandleAbilitiesRequestDone(requestId, request->requestListId, nullptr); } auto nextRequest = PopAndGetNextSpecified(requestId); if (nextRequest) { @@ -2395,7 +2422,8 @@ bool UIAbilityLifecycleManager::IsStartSpecifiedProcessRequest(const AbilityRequ return true; } -int32_t UIAbilityLifecycleManager::StartSpecifiedProcessRequest(const AbilityRequest &abilityRequest) +int32_t UIAbilityLifecycleManager::StartSpecifiedProcessRequest(const AbilityRequest &abilityRequest, + std::shared_ptr abilitiesRequest) { auto isCreating = abilityRequest.want.GetBoolParam(Want::CREATE_APP_INSTANCE_KEY, false); const auto &abilityInfo = abilityRequest.abilityInfo; @@ -2414,6 +2442,10 @@ int32_t UIAbilityLifecycleManager::StartSpecifiedProcessRequest(const AbilityReq TAG_LOGI(AAFwkTag::ABILITYMGR, "StartSpecifiedProcess, requestId:%{public}d", requestId); auto specifiedRequest = std::make_shared(requestId, abilityRequest); specifiedRequest->specifiedProcessState = SpecifiedProcessState::STATE_PROCESS; + if (abilitiesRequest != nullptr) { + abilitiesRequest->sessionInfoList.emplace_back(requestId, nullptr); + specifiedRequest->requestListId = abilitiesRequest->requestListId; + } AddSpecifiedRequest(specifiedRequest); return ERR_OK; } @@ -2426,7 +2458,7 @@ int32_t UIAbilityLifecycleManager::StartSpecifiedAbilityBySCB(AbilityRequest &ab std::lock_guard guard(sessionLock_); // support specified process mode if (IsStartSpecifiedProcessRequest(abilityRequest)) { - return StartSpecifiedProcessRequest(abilityRequest); + return StartSpecifiedProcessRequest(abilityRequest, nullptr); } AddSpecifiedRequest(std::make_shared(GetRequestId(), abilityRequest)); return ERR_OK; @@ -2473,14 +2505,16 @@ void UIAbilityLifecycleManager::NotifyStartSpecifiedAbility(AbilityRequest &abil } } -int UIAbilityLifecycleManager::MoveAbilityToFront(const AbilityRequest &abilityRequest, - const std::shared_ptr &abilityRecord, std::shared_ptr callerAbility, - std::shared_ptr startOptions, int32_t requestId) +int32_t UIAbilityLifecycleManager::MoveAbilityToFront(const SpecifiedRequest &specifiedRequest, + const std::shared_ptr abilityRecord, std::shared_ptr callerAbility) { if (!abilityRecord) { TAG_LOGE(AAFwkTag::ABILITYMGR, "ability record failed"); return ERR_INVALID_VALUE; } + const auto &abilityRequest = specifiedRequest.abilityRequest; + int32_t requestId = specifiedRequest.requestId; + int32_t requestListId = specifiedRequest.requestListId; sptr sessionInfo = abilityRecord->GetSessionInfo(); CHECK_POINTER_AND_RETURN(sessionInfo, ERR_INVALID_VALUE); sessionInfo->want = abilityRequest.want; @@ -2497,11 +2531,12 @@ int UIAbilityLifecycleManager::MoveAbilityToFront(const AbilityRequest &abilityR sessionInfo->specifiedFlag = abilityRequest.specifiedFlag; TAG_LOGI(AAFwkTag::ABILITYMGR, "MoveAbilityToFront: %{public}d-%{public}s", requestId, abilityRequest.specifiedFlag.c_str()); + if (requestListId != REQUEST_LIST_ID_INIT) { + HandleAbilitiesRequestDone(requestId, requestListId, sessionInfo); + return ERR_OK; + } SendSessionInfoToSCB(callerAbility, sessionInfo); abilityRecord->RemoveWindowMode(); - if (startOptions != nullptr) { - abilityRecord->SetWindowMode(startOptions->GetWindowMode()); - } return ERR_OK; } @@ -2551,11 +2586,12 @@ int UIAbilityLifecycleManager::SendSessionInfoToSCB(std::shared_ptr &callerAbility, int32_t requestId) +int32_t UIAbilityLifecycleManager::StartAbilityBySpecifed(const SpecifiedRequest &specifiedRequest, + std::shared_ptr callerAbility) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call"); sptr sessionInfo = new SessionInfo(); + const auto &abilityRequest = specifiedRequest.abilityRequest; sessionInfo->callerToken = abilityRequest.callerToken; sessionInfo->want = abilityRequest.want; sessionInfo->requestCode = abilityRequest.requestCode; @@ -2563,10 +2599,14 @@ int UIAbilityLifecycleManager::StartAbilityBySpecifed(const AbilityRequest &abil sessionInfo->startWindowOption = abilityRequest.startWindowOption; sessionInfo->instanceKey = abilityRequest.want.GetStringParam(Want::APP_INSTANCE_KEY); sessionInfo->isFromIcon = abilityRequest.isFromIcon; - sessionInfo->requestId = requestId; + sessionInfo->requestId = specifiedRequest.requestId; sessionInfo->specifiedFlag = abilityRequest.specifiedFlag; TAG_LOGI(AAFwkTag::ABILITYMGR, "specified flag:%{public}s", abilityRequest.specifiedFlag.c_str()); - SendSessionInfoToSCB(callerAbility, sessionInfo); + if (specifiedRequest.requestListId != REQUEST_LIST_ID_INIT) { + HandleAbilitiesRequestDone(specifiedRequest.requestId, specifiedRequest.requestListId, sessionInfo); + } else { + SendSessionInfoToSCB(callerAbility, sessionInfo); + } return ERR_OK; } @@ -3746,7 +3786,7 @@ void UIAbilityLifecycleManager::StartSpecifiedRequest(SpecifiedRequest &specifie return; } if (specifiedRequest.specifiedProcessState == SpecifiedProcessState::STATE_NONE && - !IsSpecifiedModuleLoaded(request)) { + specifiedRequest.requestListId == REQUEST_LIST_ID_INIT && !IsSpecifiedModuleLoaded(request)) { specifiedRequest.isCold = true; auto sessionInfo = CreateSessionInfo(request); sessionInfo->requestCode = request.requestCode; @@ -3760,8 +3800,7 @@ void UIAbilityLifecycleManager::StartSpecifiedRequest(SpecifiedRequest &specifie RemoveInstanceKey(request); } sessionInfo->want.RemoveAllFd(); - } - if (!specifiedRequest.isCold) { + } else { DelayedSingleton::GetInstance()->StartSpecifiedAbility(request.want, request.abilityInfo, specifiedRequest.requestId); } -- Gitee From 1cdae605f55cadc6a78d9bb4e38d2183f4bd344c Mon Sep 17 00:00:00 2001 From: wangzhen Date: Sat, 21 Jun 2025 18:43:51 +0800 Subject: [PATCH 3/3] Modify tdd Signed-off-by: wangzhen Change-Id: If24daf81fc88fe4310b4c616d5655a79ab9daf64 --- .../native/ability/native/ability_thread.cpp | 2 +- .../ability_scheduler_mock.h | 1 + .../mock_ui_ability_lifecycle_manager.h | 10 ++--- .../src/mock_ui_ability_lifecycle_manager.cpp | 11 +++--- .../mock_ui_ability_lifecycle_manager.h | 10 ++--- .../src/mock_ui_ability_lifecycle_manager.cpp | 11 +++--- ..._ability_lifecycle_manager_second_test.cpp | 5 ++- .../ui_ability_lifecycle_manager_test.cpp | 38 ++++++++++++++----- ...i_ability_lifecycle_manager_third_test.cpp | 21 +++++----- 9 files changed, 62 insertions(+), 47 deletions(-) diff --git a/frameworks/native/ability/native/ability_thread.cpp b/frameworks/native/ability/native/ability_thread.cpp index c8de6cc3203..33a909ec2b7 100644 --- a/frameworks/native/ability/native/ability_thread.cpp +++ b/frameworks/native/ability/native/ability_thread.cpp @@ -304,7 +304,7 @@ void AbilityThread::ScheduleAbilityRequestSuccess(const std::string &requestId, void AbilityThread::ScheduleAbilitiesRequestDone(const std::string &requestKey, int32_t resultCode) { - TAG_LOGD(AAFwkTag::ABILITY, "called"); + TAG_LOGD(AAFwkTag::ABILITY, "ScheduleAbilitiesRequestDone"); } } // namespace AppExecFwk } // namespace OHOS diff --git a/test/mock/services_abilitymgr_test/libs/ability_scheduler_mock/ability_scheduler_mock.h b/test/mock/services_abilitymgr_test/libs/ability_scheduler_mock/ability_scheduler_mock.h index b74ebd3efab..7f1a55b6049 100644 --- a/test/mock/services_abilitymgr_test/libs/ability_scheduler_mock/ability_scheduler_mock.h +++ b/test/mock/services_abilitymgr_test/libs/ability_scheduler_mock/ability_scheduler_mock.h @@ -48,6 +48,7 @@ public: MOCK_METHOD2(DumpAbilityInfo, void(const std::vector& params, std::vector& info)); MOCK_METHOD1(ScheduleShareData, void(const int32_t &uniqueId)); MOCK_METHOD0(SchedulePrepareTerminateAbility, bool()); + MOCK_METHOD2(SchedulePrepareTerminateAbility, void(const std::string &, int32_t)); int InvokeSendRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) { code_ = code; diff --git a/test/unittest/ability_manager_service_fourteenth_test/mock/include/mock_ui_ability_lifecycle_manager.h b/test/unittest/ability_manager_service_fourteenth_test/mock/include/mock_ui_ability_lifecycle_manager.h index f4b790bee93..183ca7f3dd1 100644 --- a/test/unittest/ability_manager_service_fourteenth_test/mock/include/mock_ui_ability_lifecycle_manager.h +++ b/test/unittest/ability_manager_service_fourteenth_test/mock/include/mock_ui_ability_lifecycle_manager.h @@ -444,11 +444,11 @@ private: void NotifyStartSpecifiedAbility(AbilityRequest &request, const AAFwk::Want &want); void NotifyRestartSpecifiedAbility(const AbilityRequest &request, const sptr &token); - int MoveAbilityToFront(const AbilityRequest &abilityRequest, const std::shared_ptr &abilityRecord, - std::shared_ptr callerAbility, std::shared_ptr startOptions, int32_t requestId); + int MoveAbilityToFront(const SpecifiedRequest &specifiedRequest, + const std::shared_ptr abilityRecord, std::shared_ptr callerAbility); int SendSessionInfoToSCB(std::shared_ptr &callerAbility, sptr &sessionInfo); - int StartAbilityBySpecifed(const AbilityRequest &abilityRequest, std::shared_ptr &callerAbility, - int32_t requestId); + int StartAbilityBySpecifed(const SpecifiedRequest &specifiedRequest, + std::shared_ptr callerAbility); void SetLastExitReason(std::shared_ptr &abilityRecord) const; void SetReceiverInfo(const AbilityRequest &abilityRequest, std::shared_ptr &abilityRecord) const; @@ -504,7 +504,7 @@ private: bool HandleStartSpecifiedCold(AbilityRequest &abilityRequest, sptr sessionInfo, uint32_t sceneFlag); bool HandleColdAcceptWantDone(const AAFwk::Want &want, const std::string &flag, const SpecifiedRequest &specifiedRequest); - void HandleLegacyAcceptWantDone(AbilityRequest &abilityRequest, int32_t requestId, + void HandleLegacyAcceptWantDone(SpecifiedRequest &specifiedRequest, const std::string &flag, const AAFwk::Want &want); std::shared_ptr GetSpecifiedRequest(int32_t requestId); bool CheckPrepareTerminateTokens(const std::vector> &tokens, diff --git a/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ui_ability_lifecycle_manager.cpp b/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ui_ability_lifecycle_manager.cpp index f6579c087f8..7e337de42cc 100644 --- a/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ui_ability_lifecycle_manager.cpp +++ b/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ui_ability_lifecycle_manager.cpp @@ -395,7 +395,7 @@ void UIAbilityLifecycleManager::OnAcceptWantResponse(const AAFwk::Want &want, co { } -void UIAbilityLifecycleManager::HandleLegacyAcceptWantDone(AbilityRequest &abilityRequest, int32_t requestId, +void UIAbilityLifecycleManager::HandleLegacyAcceptWantDone(SpecifiedRequest &specifiedRequest, const std::string &flag, const AAFwk::Want &want) { } @@ -430,9 +430,8 @@ void UIAbilityLifecycleManager::NotifyStartSpecifiedAbility(AbilityRequest &abil { } -int UIAbilityLifecycleManager::MoveAbilityToFront(const AbilityRequest &abilityRequest, - const std::shared_ptr &abilityRecord, std::shared_ptr callerAbility, - std::shared_ptr startOptions, int32_t requestId) +int UIAbilityLifecycleManager::MoveAbilityToFront(const SpecifiedRequest &specifiedRequest, + const std::shared_ptr abilityRecord, std::shared_ptr callerAbility) { return ERR_OK; } @@ -443,8 +442,8 @@ int UIAbilityLifecycleManager::SendSessionInfoToSCB(std::shared_ptr &callerAbility, int32_t requestId) +int UIAbilityLifecycleManager::StartAbilityBySpecifed(const SpecifiedRequest &specifiedRequest, + std::shared_ptr callerAbility) { return ERR_OK; } diff --git a/test/unittest/ability_manager_service_thirteenth_test/mock/include/mock_ui_ability_lifecycle_manager.h b/test/unittest/ability_manager_service_thirteenth_test/mock/include/mock_ui_ability_lifecycle_manager.h index c9045c1fad6..703a16038f0 100644 --- a/test/unittest/ability_manager_service_thirteenth_test/mock/include/mock_ui_ability_lifecycle_manager.h +++ b/test/unittest/ability_manager_service_thirteenth_test/mock/include/mock_ui_ability_lifecycle_manager.h @@ -445,11 +445,11 @@ private: void NotifyStartSpecifiedAbility(AbilityRequest &request, const AAFwk::Want &want); void NotifyRestartSpecifiedAbility(const AbilityRequest &request, const sptr &token); - int MoveAbilityToFront(const AbilityRequest &abilityRequest, const std::shared_ptr &abilityRecord, - std::shared_ptr callerAbility, std::shared_ptr startOptions, int32_t requestId); + int MoveAbilityToFront(const SpecifiedRequest &specifiedRequest, + const std::shared_ptr abilityRecord, std::shared_ptr callerAbility); int SendSessionInfoToSCB(std::shared_ptr &callerAbility, sptr &sessionInfo); - int StartAbilityBySpecifed(const AbilityRequest &abilityRequest, std::shared_ptr &callerAbility, - int32_t requestId); + int StartAbilityBySpecifed(const SpecifiedRequest &specifiedRequest, + std::shared_ptr callerAbility); void SetLastExitReason(std::shared_ptr &abilityRecord) const; void SetReceiverInfo(const AbilityRequest &abilityRequest, std::shared_ptr &abilityRecord) const; @@ -505,7 +505,7 @@ private: bool HandleStartSpecifiedCold(AbilityRequest &abilityRequest, sptr sessionInfo, uint32_t sceneFlag); bool HandleColdAcceptWantDone(const AAFwk::Want &want, const std::string &flag, const SpecifiedRequest &specifiedRequest); - void HandleLegacyAcceptWantDone(AbilityRequest &abilityRequest, int32_t requestId, + void HandleLegacyAcceptWantDone(SpecifiedRequest &specifiedRequest, const std::string &flag, const AAFwk::Want &want); std::shared_ptr GetSpecifiedRequest(int32_t requestId); bool CheckPrepareTerminateTokens(const std::vector> &tokens, diff --git a/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ui_ability_lifecycle_manager.cpp b/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ui_ability_lifecycle_manager.cpp index 7f06502da7f..506b6e0c9d2 100644 --- a/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ui_ability_lifecycle_manager.cpp +++ b/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ui_ability_lifecycle_manager.cpp @@ -395,7 +395,7 @@ void UIAbilityLifecycleManager::OnAcceptWantResponse(const AAFwk::Want &want, co { } -void UIAbilityLifecycleManager::HandleLegacyAcceptWantDone(AbilityRequest &abilityRequest, int32_t requestId, +void UIAbilityLifecycleManager::HandleLegacyAcceptWantDone(SpecifiedRequest &specifiedRequest, const std::string &flag, const AAFwk::Want &want) { } @@ -430,9 +430,8 @@ void UIAbilityLifecycleManager::NotifyStartSpecifiedAbility(AbilityRequest &abil { } -int UIAbilityLifecycleManager::MoveAbilityToFront(const AbilityRequest &abilityRequest, - const std::shared_ptr &abilityRecord, std::shared_ptr callerAbility, - std::shared_ptr startOptions, int32_t requestId) +int UIAbilityLifecycleManager::MoveAbilityToFront(const SpecifiedRequest &specifiedRequest, + const std::shared_ptr abilityRecord, std::shared_ptr callerAbility) { return ERR_OK; } @@ -443,8 +442,8 @@ int UIAbilityLifecycleManager::SendSessionInfoToSCB(std::shared_ptr &callerAbility, int32_t requestId) +int UIAbilityLifecycleManager::StartAbilityBySpecifed(const SpecifiedRequest &specifiedRequest, + std::shared_ptr callerAbility) { return ERR_OK; } diff --git a/test/unittest/ui_ability_lifecycle_manager_second_test/ui_ability_lifecycle_manager_second_test.cpp b/test/unittest/ui_ability_lifecycle_manager_second_test/ui_ability_lifecycle_manager_second_test.cpp index e2f953e6654..6c50eb5f82c 100644 --- a/test/unittest/ui_ability_lifecycle_manager_second_test/ui_ability_lifecycle_manager_second_test.cpp +++ b/test/unittest/ui_ability_lifecycle_manager_second_test/ui_ability_lifecycle_manager_second_test.cpp @@ -126,10 +126,11 @@ HWTEST_F(UIAbilityLifecycleManagerSecondTest, HandleLegacyAcceptWantDone_001, Te bool reuse = false; std::string flag = ""; int32_t requestId = 1; - mgr->HandleLegacyAcceptWantDone(abilityRequest, requestId, flag, want); + SpecifiedRequest specifiedRequest(requestId, abilityRequest); + mgr->HandleLegacyAcceptWantDone(specifiedRequest, flag, want); EXPECT_EQ(abilityRequest.specifiedFlag, ""); flag = "specified"; - mgr->HandleLegacyAcceptWantDone(abilityRequest, requestId, flag, want); + mgr->HandleLegacyAcceptWantDone(specifiedRequest, flag, want); EXPECT_EQ(abilityRequest.specifiedFlag, flag); TAG_LOGI(AAFwkTag::TEST, "HandleLegacyAcceptWantDone_001 end."); } diff --git a/test/unittest/ui_ability_lifecycle_manager_test/ui_ability_lifecycle_manager_test.cpp b/test/unittest/ui_ability_lifecycle_manager_test/ui_ability_lifecycle_manager_test.cpp index 5d24d5c3c3d..51c0a470dcd 100644 --- a/test/unittest/ui_ability_lifecycle_manager_test/ui_ability_lifecycle_manager_test.cpp +++ b/test/unittest/ui_ability_lifecycle_manager_test/ui_ability_lifecycle_manager_test.cpp @@ -2590,19 +2590,19 @@ HWTEST_F(UIAbilityLifecycleManagerTest, MoveAbilityToFront_001, TestSize.Level1) { auto uiAbilityLifecycleManager = std::make_shared(); AbilityRequest abilityRequest; - int res = uiAbilityLifecycleManager->MoveAbilityToFront(abilityRequest, nullptr, nullptr, nullptr, 0); + SpecifiedRequest specifiedRequest(0, abilityRequest); + int res = uiAbilityLifecycleManager->MoveAbilityToFront(specifiedRequest, nullptr, nullptr); EXPECT_EQ(res, ERR_INVALID_VALUE); - abilityRequest.sessionInfo = new SessionInfo(); - abilityRequest.appInfo.bundleName = "com.example.unittest"; - abilityRequest.abilityInfo.name = "MainAbility"; - abilityRequest.abilityInfo.type = AppExecFwk::AbilityType::PAGE; - std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); - res = uiAbilityLifecycleManager->MoveAbilityToFront(abilityRequest, abilityRecord, nullptr, nullptr, 0); + specifiedRequest.abilityRequest.sessionInfo = new SessionInfo(); + specifiedRequest.abilityRequest.appInfo.bundleName = "com.example.unittest"; + specifiedRequest.abilityRequest.abilityInfo.name = "MainAbility"; + specifiedRequest.abilityRequest.abilityInfo.type = AppExecFwk::AbilityType::PAGE; + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(specifiedRequest.abilityRequest); + res = uiAbilityLifecycleManager->MoveAbilityToFront(specifiedRequest, abilityRecord, nullptr); EXPECT_EQ(res, ERR_OK); - auto startOptions = std::make_shared(); - res = uiAbilityLifecycleManager->MoveAbilityToFront(abilityRequest, abilityRecord, nullptr, nullptr, 0); + res = uiAbilityLifecycleManager->MoveAbilityToFront(abilityRequest, abilityRecord, nullptr); EXPECT_EQ(res, ERR_OK); uiAbilityLifecycleManager.reset(); @@ -2661,8 +2661,26 @@ HWTEST_F(UIAbilityLifecycleManagerTest, StartAbilityBySpecifed_001, TestSize.Lev auto uiAbilityLifecycleManager = std::make_shared(); EXPECT_NE(uiAbilityLifecycleManager, nullptr); AbilityRequest request; + SpecifiedRequest specifiedRequest(0, request); + std::shared_ptr callerAbility = nullptr; + uiAbilityLifecycleManager->StartAbilityBySpecifed(specifiedRequest, callerAbility); + uiAbilityLifecycleManager.reset(); +} + +/** + * @tc.name: UIAbilityLifecycleManager_StartAbilityBySpecifed_0200 + * @tc.desc: StartAbilityBySpecifed + * @tc.type: FUNC + */ +HWTEST_F(UIAbilityLifecycleManagerTest, StartAbilityBySpecifed_0200, TestSize.Level1) +{ + auto uiAbilityLifecycleManager = std::make_shared(); + EXPECT_NE(uiAbilityLifecycleManager, nullptr); + AbilityRequest request; + SpecifiedRequest specifiedRequest(0, request); + specifiedRequest.requestListId = 0; std::shared_ptr callerAbility = nullptr; - uiAbilityLifecycleManager->StartAbilityBySpecifed(request, callerAbility, 0); + uiAbilityLifecycleManager->StartAbilityBySpecifed(specifiedRequest, callerAbility); uiAbilityLifecycleManager.reset(); } diff --git a/test/unittest/ui_ability_lifecycle_manager_third_test/ui_ability_lifecycle_manager_third_test.cpp b/test/unittest/ui_ability_lifecycle_manager_third_test/ui_ability_lifecycle_manager_third_test.cpp index d3ba9fc5f9f..8778659abde 100644 --- a/test/unittest/ui_ability_lifecycle_manager_third_test/ui_ability_lifecycle_manager_third_test.cpp +++ b/test/unittest/ui_ability_lifecycle_manager_third_test/ui_ability_lifecycle_manager_third_test.cpp @@ -843,8 +843,8 @@ HWTEST_F(UIAbilityLifecycleManagerThirdTest, MoveAbilityToFront_001, TestSize.Le abilityRequest.abilityInfo.launchMode = AppExecFwk::LaunchMode::SPECIFIED; AppUtils::isStartOptionsWithAnimation_ = true; - - uiAbilityLifecycleManager->MoveAbilityToFront(abilityRequest, abilityRecord, abilityRecord, nullptr, 0); + SpecifiedRequest specifiedRequest(0, abilityRequest); + uiAbilityLifecycleManager->MoveAbilityToFront(specifiedRequest, abilityRecord, abilityRecord); auto sessionInfo = abilityRecord->GetSessionInfo(); EXPECT_NE(sessionInfo->processOptions, nullptr); @@ -868,8 +868,8 @@ HWTEST_F(UIAbilityLifecycleManagerThirdTest, MoveAbilityToFront_002, TestSize.Le abilityRequest.abilityInfo.launchMode = AppExecFwk::LaunchMode::SPECIFIED; AppUtils::isStartOptionsWithAnimation_ = false; - - uiAbilityLifecycleManager->MoveAbilityToFront(abilityRequest, abilityRecord, abilityRecord, nullptr, 0); + SpecifiedRequest specifiedRequest(0, abilityRequest); + uiAbilityLifecycleManager->MoveAbilityToFront(specifiedRequest, abilityRecord, abilityRecord); auto sessionInfo = abilityRecord->GetSessionInfo(); EXPECT_EQ(sessionInfo->processOptions, nullptr); @@ -896,10 +896,9 @@ HWTEST_F(UIAbilityLifecycleManagerThirdTest, MoveAbilityToFront_003, TestSize.Le AppUtils::isStartOptionsWithAnimation_ = false; - auto startOptions = std::make_shared(); - startOptions->windowMode_ = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY; - - uiAbilityLifecycleManager->MoveAbilityToFront(abilityRequest, abilityRecord, abilityRecord, startOptions, 0); + SpecifiedRequest specifiedRequest(0, abilityRequest); + specifiedRequest.requestListId = 0; + uiAbilityLifecycleManager->MoveAbilityToFront(specifiedRequest, abilityRecord, abilityRecord); auto ret = abilityRecord->want_.GetIntParam(Want::PARAM_RESV_WINDOW_MODE, -1); EXPECT_EQ(ret, AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY); @@ -926,10 +925,8 @@ HWTEST_F(UIAbilityLifecycleManagerThirdTest, MoveAbilityToFront_004, TestSize.Le AppUtils::isStartOptionsWithAnimation_ = false; - auto startOptions = std::make_shared(); - startOptions->windowMode_ = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY; - - uiAbilityLifecycleManager->MoveAbilityToFront(abilityRequest, abilityRecord, abilityRecord, nullptr, 0); + SpecifiedRequest specifiedRequest(0, abilityRequest); + uiAbilityLifecycleManager->MoveAbilityToFront(specifiedRequest, abilityRecord, abilityRecord); auto ret = abilityRecord->want_.GetIntParam(Want::PARAM_RESV_WINDOW_MODE, -1); EXPECT_EQ(ret, -1); -- Gitee