From a6c3080a6ea3b71f3e4a8c6e0adab9a3a8aa2712 Mon Sep 17 00:00:00 2001 From: jiangxiaofeng20 Date: Wed, 27 Aug 2025 11:25:48 +0800 Subject: [PATCH] startUIAbilitiesInSplitWindowMode Signed-off-by: jiangxiaofeng20 --- .../ui_extension_context.js | 5 + .../js_ui_extension_context.cpp | 69 ++++++++ .../ui_extension_context.cpp | 11 ++ .../include/ability_manager_client.h | 13 ++ .../include/ability_manager_interface.h | 14 ++ .../ability_manager_ipc_interface_code.h | 2 + .../js_ui_extension_context.h | 4 + .../ui_extension_base/ui_extension_context.h | 1 + .../include/ability_manager_proxy.h | 13 +- .../include/ability_manager_service.h | 10 ++ .../abilitymgr/include/ability_manager_stub.h | 1 + services/abilitymgr/include/ability_record.h | 2 + .../ui_ability_lifecycle_manager.h | 3 + .../abilitymgr/src/ability_manager_client.cpp | 11 ++ .../abilitymgr/src/ability_manager_proxy.cpp | 39 +++++ .../src/ability_manager_service.cpp | 152 ++++++++++++++++++ .../abilitymgr/src/ability_manager_stub.cpp | 22 +++ .../ui_ability_lifecycle_manager.cpp | 101 ++++++++++++ 18 files changed, 472 insertions(+), 1 deletion(-) 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 182bd61c1eb..4986e0b0aea 100755 --- a/frameworks/js/napi/ui_extension_context/ui_extension_context.js +++ b/frameworks/js/napi/ui_extension_context/ui_extension_context.js @@ -70,6 +70,11 @@ class UIExtensionContext extends ExtensionContext { hilog.sLogI(domainID, TAG, 'startAbilityForResultAsCaller'); return this.__context_impl__.startAbilityForResultAsCaller(want, options, callback); } + + startUIAbilitiesInSplitWindowMode(primaryWindowId, secondaryWant) { + hilog.sLogI(domainID, TAG, 'startUIAbilitiesInSplitWindowMode'); + return this.__context_impl__.startUIAbilitiesInSplitWindowMode(primaryWindowId, secondaryWant); + } startUIAbilities(wantList) { hilog.sLogI(domainID, TAG, 'startUIAbilities'); 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 bb48409d762..0aa4fe4c132 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 @@ -147,6 +147,11 @@ napi_value JsUIExtensionContext::StartAbilityForResultAsCaller(napi_env env, nap GET_NAPI_INFO_AND_CALL(env, info, JsUIExtensionContext, OnStartAbilityForResultAsCaller); } +napi_value JsUIExtensionContext::StartUIAbilitiesInSplitWindowMode(napi_env env, napi_callback_info info) +{ + GET_NAPI_INFO_AND_CALL(env, info, JsUIExtensionContext, OnStartUIAbilitiesInSplitWindowMode); +} + napi_value JsUIExtensionContext::StartUIAbilities(napi_env env, napi_callback_info info) { GET_NAPI_INFO_AND_CALL(env, info, JsUIExtensionContext, OnStartUIAbilities); @@ -572,6 +577,50 @@ napi_value JsUIExtensionContext::OnStartAbilityForResultAsCaller(napi_env env, N return result; } +napi_value JsUIExtensionContext::OnStartUIAbilitiesInSplitWindowMode(napi_env env, NapiCallbackInfo& info) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGI(AAFwkTag::UI_EXT, "call OnStartUIAbilitiesInSplitWindowMode"); + if (info.argc < ARGC_TWO) { + TAG_LOGE(AAFwkTag::UI_EXT, "Too few parameters."); + ThrowTooFewParametersError(env); + return CreateJsUndefined(env); + } + int32_t primaryWindowId = 0; + AAFwk::Want secondaryWant; + if (!CheckStartUIAbilitiesInSplitWindowModeInputParam(env, info, primaryWindowId, secondaryWant)) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed, input param type invalid"); + ThrowInvalidParamError(env, "Parse param want failed, want must be Want"); + return CreateJsUndefined(env); + } + + auto innerErrCode = std::make_shared(ERR_OK); + NapiAsyncTask::ExecuteCallback execute = [weak = context_, primaryWindowId, secondaryWant, innerErrCode]() { + auto context = weak.lock(); + TAG_LOGD(AAFwkTag::UI_EXT, "startAbility begin"); + if (!context) { + TAG_LOGE(AAFwkTag::UI_EXT, "context is released"); + *innerErrCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + *innerErrCode = context->StartUIAbilitiesInSplitWindowMode(primaryWindowId, secondaryWant); + }; + NapiAsyncTask::CompleteCallback complete = + [innerErrCode](napi_env env, NapiAsyncTask& task, int32_t status) { + if (*innerErrCode == ERR_OK) { + task.ResolveWithNoError(env, CreateJsUndefined(env)); + } else if (*innerErrCode == static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)) { + task.Reject(env, CreateJsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + } else { + task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode)); + } + }; + napi_value result = nullptr; + NapiAsyncTask::ScheduleHighQos("JSUIExtensionContext OnStartUIAbilitiesInSplitWindowMode", + env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result)); + return result; +} + napi_value JsUIExtensionContext::OnStartUIAbilities(napi_env env, NapiCallbackInfo& info) { TAG_LOGI(AAFwkTag::UI_EXT, "call OnStartUIAbilities"); @@ -620,6 +669,25 @@ napi_value JsUIExtensionContext::OnStartUIAbilities(napi_env env, NapiCallbackIn return callback.result; } +bool JsUIExtensionContext::CheckStartUIAbilitiesInSplitWindowModeInputParam(napi_env env, + NapiCallbackInfo &info, int32_t &primaryWindowId, AAFwk::Want &want) +{ + if (info.argc < ARGC_TWO) { + return false; + } + if (!want.HasParameter(Want::PARAM_BACK_TO_OTHER_MISSION_STACK)) { + want.SetParam(Want::PARAM_BACK_TO_OTHER_MISSION_STACK, true); + } + if (!ConvertFromJsValue(env, info.argv[INDEX_ZERO], primaryWindowId) || primaryWindowId <= 0) { + return false; + } + // Check input want + if (!AppExecFwk::UnwrapWant(env, info.argv[INDEX_ONE], want)) { + return false; + } + return true; +} + bool JsUIExtensionContext::UnwrapWantList(napi_env env, NapiCallbackInfo &info, std::vector &wantList) { AppExecFwk::ComplexArrayData jsWantList; @@ -1417,6 +1485,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, "startUIAbilitiesInSplitWindowMode", moduleName, StartUIAbilitiesInSplitWindowMode); BindNativeFunction(env, objValue, "startUIAbilities", moduleName, StartUIAbilities); BindNativeFunction(env, objValue, "connectServiceExtensionAbility", moduleName, ConnectAbility); BindNativeFunction(env, objValue, "disconnectServiceExtensionAbility", moduleName, DisconnectAbility); 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 d8f1a0a551a..77275fba921 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 @@ -66,6 +66,17 @@ ErrCode UIExtensionContext::StartAbility(const AAFwk::Want &want, const AAFwk::S return err; } +ErrCode UIExtensionContext::StartUIAbilitiesInSplitWindowMode(int32_t primaryWindowId, const AAFwk::Want &secondaryWant) const +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGI(AAFwkTag::UI_EXT, "StartUIAbilitiesInSplitWindowMode begin"); + ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartUIAbilitiesInSplitWindowMode(primaryWindowId, secondaryWant, token_); + if (err != ERR_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "ret = %{public}d", err); + } + return err; +} + ErrCode UIExtensionContext::StartUIServiceExtension(const AAFwk::Want& want, int32_t accountId) const { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); 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 60e6e80a814..41bd729c7ef 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,19 @@ public: int requestCode = DEFAULT_INVAL_VALUE, int32_t userId = DEFAULT_INVAL_VALUE); + /** + * Start ui session ability with windowId and want, send windowId and want to ability manager service. + * + * @param primaryWindowId the id of sourceWindow. + * @param secondaryWant the want of the ability to start. + * @param callerToken current caller ability token. + * @return Returns ERR_OK if success. + */ + ErrCode StartUIAbilitiesInSplitWindowMode( + int32_t primaryWindowId, + const AAFwk::Want &secondaryWant, + sptr callerToken); + /** * Start UI abilities simultaneously. * 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 c04c88ea43a..2e885941527 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; } + /** + * Start ui session ability with windowId and want. + * + * @param primaryWindowId the id of sourceWindow. + * @param secondaryWant the want of the ability to start. + * @param callerToken current caller ability token. + * @return Returns ERR_OK if success. + */ + virtual ErrCode StartUIAbilitiesInSplitWindowMode(int32_t primaryWindowId, const AAFwk::Want &secondaryWant, + sptr callerToken) + { + return 0; + } + /** * Start UI abilities simultaneously. * 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 35e5e45d499..061678c7f85 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 @@ -425,6 +425,8 @@ enum class AbilityManagerInterfaceCode { // ipc id for start UI abilities START_UI_ABILITIES = 1073, + START_UI_ABILITIES_IN_SPLIT_WINDOW_MODE = 1074, + // 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 41e074b89ae..0d0dbecd5d4 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 StartUIAbilitiesInSplitWindowMode(napi_env env, napi_callback_info info); static napi_value StartUIAbilities(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); @@ -61,6 +62,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 OnStartUIAbilitiesInSplitWindowMode(napi_env env, NapiCallbackInfo& info); virtual napi_value OnStartUIAbilities(napi_env env, NapiCallbackInfo& info); virtual napi_value OnConnectAbility(napi_env env, NapiCallbackInfo& info); virtual napi_value OnDisconnectAbility(napi_env env, NapiCallbackInfo& info); @@ -91,6 +93,8 @@ private: bool CheckStartAbilityInputParam(napi_env env, NapiCallbackInfo& info, AAFwk::Want& want, AAFwk::StartOptions& startOptions, size_t& unwrapArgc) const; + bool CheckStartUIAbilitiesInSplitWindowModeInputParam(napi_env env, NapiCallbackInfo &info, + int32_t &primaryWindowId, AAFwk::Want &secondaryWant); napi_value OpenAtomicServiceInner(napi_env env, NapiCallbackInfo& info, AAFwk::Want &want, const AAFwk::StartOptions &options, size_t unwrapArgc); void AddFreeInstallObserver(napi_env env, const AAFwk::Want &want, napi_value callback, napi_value* result, 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 8dcd4477f0e..88929248516 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 @@ -56,6 +56,7 @@ public: virtual ErrCode StartAbility(const AAFwk::Want &want) const; virtual ErrCode StartAbility(const AAFwk::Want &want, const AAFwk::StartOptions &startOptions) const; virtual ErrCode StartAbility(const AAFwk::Want &want, int requestCode) const; + virtual ErrCode StartUIAbilitiesInSplitWindowMode(int32_t primaryWindowId, const AAFwk::Want &secondaryWant) const; virtual ErrCode StartUIServiceExtension(const AAFwk::Want& want, int32_t accountId = -1) const; /** * @brief Destroys the current ui extension ability. diff --git a/services/abilitymgr/include/ability_manager_proxy.h b/services/abilitymgr/include/ability_manager_proxy.h index 90aa5002ea4..d202640d422 100644 --- a/services/abilitymgr/include/ability_manager_proxy.h +++ b/services/abilitymgr/include/ability_manager_proxy.h @@ -215,7 +215,18 @@ public: const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE, int32_t userId = DEFAULT_INVAL_VALUE) override; - + + /** + * Start ui session ability with windowId and want. + * + * @param primaryWindowId the id of sourceWindow. + * @param secondaryWant the want of the ability to start. + * @param callerToken current caller ability token. + * @return Returns ERR_OK if success. + */ + ErrCode StartUIAbilitiesInSplitWindowMode(int32_t primaryWindowId, const AAFwk::Want &secondaryWant, + sptr callerToken) override; + /** * Start UI abilities simultaneously. * diff --git a/services/abilitymgr/include/ability_manager_service.h b/services/abilitymgr/include/ability_manager_service.h index 6f775ac5653..440a491f507 100644 --- a/services/abilitymgr/include/ability_manager_service.h +++ b/services/abilitymgr/include/ability_manager_service.h @@ -339,6 +339,16 @@ public: int requestCode = DEFAULT_INVAL_VALUE, int32_t userId = DEFAULT_INVAL_VALUE) override; + /** + * Start ui session ability with windowId and want. + * + * @param primaryWindowId the id of sourceWindow. + * @param secondaryWant the want of the ability to start. + * @param callerToken current caller ability token. + * @return Returns ERR_OK if success. + */ + ErrCode StartUIAbilitiesInSplitWindowMode(int32_t primaryWindowId, const AAFwk::Want &secondaryWant, + sptr callerToken) override; /** * Start UI abilities simultaneously. * diff --git a/services/abilitymgr/include/ability_manager_stub.h b/services/abilitymgr/include/ability_manager_stub.h index d98997a8075..3ccbe413052 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 StartUIAbilitiesInSplitWindowModeInner(MessageParcel &data, MessageParcel &reply); int32_t StartUIAbilitiesInner(MessageParcel &data, MessageParcel &reply); int32_t StartAbilityOnlyUIAbilityInner(MessageParcel &data, MessageParcel &reply); diff --git a/services/abilitymgr/include/ability_record.h b/services/abilitymgr/include/ability_record.h index 79b765ebba5..a5a465dd1d4 100644 --- a/services/abilitymgr/include/ability_record.h +++ b/services/abilitymgr/include/ability_record.h @@ -244,6 +244,7 @@ enum CollaboratorType { }; struct AbilityRequest { + bool isStartInSplitMode = false; bool restart = false; bool startRecent = false; bool uriReservedFlag = false; @@ -254,6 +255,7 @@ struct AbilityRequest { bool isEmbeddedAllowed = false; bool callSpecifiedFlagTimeout = false; bool hideStartWindow = false; + int32_t primaryWindowId = -1; int32_t restartCount = -1; int32_t uid = 0; int32_t collaboratorType = CollaboratorType::DEFAULT_TYPE; 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 8f0e6bdcc56..1243aa92476 100644 --- a/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h +++ b/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h @@ -442,6 +442,7 @@ private: sptr CreateSessionInfo(const AbilityRequest &abilityRequest, int32_t requestId) const; int NotifySCBPendingActivation(sptr &sessionInfo, const AbilityRequest &abilityRequest, std::string &errMsg); + int NotifySCBPendingActivationInSplitMode(sptr &sessionInfo, const AbilityRequest &abilityRequest); int32_t BatchNotifySCBPendingActivations(const AbilitiesRequest &abilitiesRequest); void HandleAbilitiesRequestDone(int32_t requestId, int32_t requestListId, sptr sessionInfo); bool IsHookModule(const AbilityRequest &abilityRequest) const; @@ -452,6 +453,8 @@ private: int32_t MoveAbilityToFront(const SpecifiedRequest &specifiedRequest, const std::shared_ptr abilityRecord, std::shared_ptr callerAbility); + int SendSessionInfoToSCBInSplitMode(int primaryWindowId, std::shared_ptr &callerAbility, + sptr &sessionInfo); int SendSessionInfoToSCB(std::shared_ptr &callerAbility, sptr &sessionInfo); int32_t StartAbilityBySpecifed(const SpecifiedRequest &specifiedRequest, std::shared_ptr callerAbility); diff --git a/services/abilitymgr/src/ability_manager_client.cpp b/services/abilitymgr/src/ability_manager_client.cpp index bc5b52dd421..4be6ea28df5 100644 --- a/services/abilitymgr/src/ability_manager_client.cpp +++ b/services/abilitymgr/src/ability_manager_client.cpp @@ -261,6 +261,17 @@ ErrCode AbilityManagerClient::StartAbilityForResultAsCaller(const Want &want, co return abms->StartAbilityForResultAsCaller(want, startOptions, callerToken, requestCode, userId); } +ErrCode AbilityManagerClient::StartUIAbilitiesInSplitWindowMode(int32_t primaryWindowId, const AAFwk::Want &secondaryWant, + sptr callerToken) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGI(AAFwkTag::ABILITYMGR, "call StartUIAbilitiesInSplitWindowMode"); + auto abms = GetAbilityManager(); + CHECK_POINTER_RETURN_NOT_CONNECTED(abms); + HandleDlpApp(const_cast(secondaryWant)); + return abms->StartUIAbilitiesInSplitWindowMode(primaryWindowId, secondaryWant, callerToken); +} + ErrCode AbilityManagerClient::StartUIAbilities(const std::vector &wantList, const std::string &requestKey, sptr callerToken) { diff --git a/services/abilitymgr/src/ability_manager_proxy.cpp b/services/abilitymgr/src/ability_manager_proxy.cpp index b00f2ff330f..a8320464c23 100644 --- a/services/abilitymgr/src/ability_manager_proxy.cpp +++ b/services/abilitymgr/src/ability_manager_proxy.cpp @@ -554,6 +554,45 @@ int AbilityManagerProxy::StartAbilityForResultAsCaller(const Want &want, const S return reply.ReadInt32(); } +ErrCode AbilityManagerProxy::StartUIAbilitiesInSplitWindowMode(int32_t primaryWindowId, const AAFwk::Want &secondaryWant, + sptr callerToken) +{ + TAG_LOGI(AAFwkTag::ABILITYMGR, "call StartUIAbilitiesInSplitWindowMode"); + if (AppUtils::GetInstance().IsForbidStart()) { + TAG_LOGW(AAFwkTag::ABILITYMGR, "forbid start abilities"); + return INNER_ERR; + } + 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; + } + if (!data.WriteInt32(primaryWindowId)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write sourceWindowId fail"); + return ERR_WRITE_INT32_FAILED; + } + if (!data.WriteParcelable(&secondaryWant)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write want fail"); + return ERR_WRITE_WANT; + } + if (!data.WriteRemoteObject(callerToken)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write callerToken fail"); + return ERR_WRITE_CALLER_TOKEN_FAILED; + } + auto error = SendRequest(AbilityManagerInterfaceCode::START_MULTI_UI_ABILITIES, data, reply, option); + if (error != NO_ERROR) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "request error:%{public}d", error); + return error; + } + return reply.ReadInt32(); +} + ErrCode AbilityManagerProxy::StartUIAbilities(const std::vector &wantList, const std::string &requestKey, sptr callerToken) { diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index 12392c6a031..cd0f7b01e55 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -328,6 +328,7 @@ constexpr const char* LIFE_CYCLE_MINIMIZE = "minimize"; constexpr const char* LIFE_CYCLE_TERMINATE = "terminate"; constexpr const char* LIFE_CYCLE_PRELOAD = "preload"; constexpr uint32_t TARGET_TYPE_INIT = 100; +constexpr const char* SUPPORT_LINKAGE_SCENE = "const.window.supportLinkageScene"; const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(DelayedSingleton::GetInstance().get()); @@ -2294,6 +2295,157 @@ int AbilityManagerService::StartAbilityForOptionInner(const Want &want, const St return ret; } +ErrCode AbilityManagerService::StartUIAbilitiesInSplitWindowMode(int32_t primaryWindowId, + const AAFwk::Want &secondaryWant, sptr callerToken) +{ + TAG_LOGI(AAFwkTag::ABILITYMGR, "Call StartUIAbilitiesInSplitWindowMode"); + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (!system::GetBoolParameter(SUPPORT_LINKAGE_SCENE, false)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "capability not support"); + return ERR_CAPABILITY_NOT_SUPPORT; + } + + if (!AAFwk::PermissionVerification::GetInstance()->IsSystemAppCall()) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "permission verification failed"); + return ERR_NOT_SYSTEM_APP; + } + + if (!Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode is not supported"); + return ERR_CAPABILITY_NOT_SUPPORT; + } + + if (callerToken == nullptr || !VerificationAllToken(callerToken)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode %{public}s verificationAllToken failed", __func__); + return ERR_INVALID_CALLER; + } + + int32_t userId = DEFAULT_INVAL_VALUE; + int32_t validUserId = GetValidUserId(userId); + int32_t oriValidUserId = GetValidUserId(userId); + uint32_t specifyTokenId = 0; + int32_t requestCode = DEFAULT_INVAL_VALUE; + + AbilityUtil::RemoveShowModeKey(const_cast(secondaryWant)); + + if (AbilityRuntime::StartupUtil::IsStartPlugin(secondaryWant)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode not support StartPlugin"); + return START_UI_ABILITIES_NOT_SUPPORT_START_PLUGIN; + } + AbilityUtil::RemoveWindowModeKey(const_cast(secondaryWant)); + + if (secondaryWant.GetBoolParam(Want::CREATE_APP_INSTANCE_KEY, false)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode not support CREATE_APP_INSTANCE_KEY"); + return START_UI_ABILITIES_NOT_SUPPORT_CREATE_APP_INSTANCE_KEY; + } +#ifdef WITH_DLP + if (AbilityUtil::HandleDlpApp(const_cast(secondaryWant))) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode not support Dlp"); + return START_UI_ABILITIES_NOT_SUPPORT_DLP; + } + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "CHECK_DLP"); + if (!DlpUtils::OtherAppsAccessDlpCheck(callerToken, secondaryWant) || + VerifyAccountPermission(validUserId) == CHECK_PERMISSION_FAILED || + !DlpUtils::DlpAccessOtherAppsCheck(callerToken, secondaryWant)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, + "StartUIAbilitiesInSplitWindowMode Dlp %{public}s: permission verification failed", __func__); + return CHECK_PERMISSION_FAILED; + } +#endif + int32_t appIndex = 0; + StartAbilityUtils::SetTargetCloneIndexInSameBundle(secondaryWant, callerToken); + if (!StartAbilityUtils::GetAppIndex(secondaryWant, callerToken, appIndex)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode GetAppIndex failed"); + return ERR_APP_CLONE_INDEX_INVALID; + } + + auto checkRet = AbilityPermissionUtil::GetInstance().CheckMultiInstanceAndAppClone(const_cast(secondaryWant), + validUserId, appIndex, callerToken, false); + if (checkRet != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "CheckMultiInstanceAndAppClone failed: %{public}d", checkRet); + return checkRet; + } + + StartAbilityInfoWrap threadLocalInfo(secondaryWant, validUserId, appIndex, callerToken); + + if (CheckIfOperateRemote(secondaryWant)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode not support StartRemoteAbility"); + return START_UI_ABILITIES_NOT_SUPPORT_OPERATE_REMOTE; + } + + if (!JudgeMultiUserConcurrency(validUserId)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode multi-user non-concurrent unsatisfied"); + return ERR_CROSS_USER; + } + +#ifdef SUPPORT_SCREEN + if (ImplicitStartProcessor::IsImplicitStartAction(secondaryWant)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode not support implicit start"); + return START_UI_ABILITIES_NOT_SUPPORT_IMPLICIT_START; + } +#endif + AbilityRequest abilityRequest; + auto result = GenerateAbilityRequest(secondaryWant, requestCode, abilityRequest, callerToken, validUserId); + auto abilityRecord = Token::GetAbilityRecordByToken(callerToken); + std::string callerBundleName = abilityRecord ? abilityRecord->GetAbilityInfo().bundleName : ""; + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode generate ability request local error"); + return result; + } + + UpdateCallerInfoUtil::GetInstance().UpdateCallerInfoFromToken(abilityRequest.want, callerToken); + + auto abilityInfo = abilityRequest.abilityInfo; + if (abilityInfo.type != AbilityType::PAGE) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartUIAbilitiesInSplitWindowMode ability type no UIAbility"); + return RESOLVE_ABILITY_ERR; + } + + 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, + "StartUIAbilitiesInSplitWindowMode checkStaticCfgPermission error, result:%{public}d", result); + return ERR_STATIC_CFG_PERMISSION; + } + result = CheckCallPermission(secondaryWant, abilityInfo, abilityRequest, false, + false, specifyTokenId, callerBundleName); + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, + "StartUIAbilitiesInSplitWindowMode checkCallPermission error, result:%{public}d", result); + return result; + } + + result = StartUIAbilitiesInterceptorCheck(secondaryWant, abilityRequest, callerToken, appIndex); + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "InterceptorCheck error, result:%{public}d", result); + return result; + } + + Want newWant = abilityRequest.want; + bool isReplaceWantExist = newWant.GetBoolParam("queryWantFromErms", false); + newWant.RemoveParam("queryWantFromErms"); + + auto callerTokenId = IPCSkeleton::GetCallingTokenID(); + RemoveUnauthorizedLaunchReasonMessage(secondaryWant, abilityRequest, callerTokenId); + + if (!IsAbilityControllerStart(secondaryWant, abilityInfo.bundleName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, + "StartUIAbilitiesInSplitWindowMode 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); + + abilityRequest.userId = oriValidUserId; + abilityRequest.want.SetParam(ServerConstant::IS_CALL_BY_SCB, false); + auto uiAbilityManager = GetUIAbilityManagerByUserId(oriValidUserId); + CHECK_POINTER_AND_RETURN(uiAbilityManager, ERR_INVALID_VALUE); + abilityRequest.primaryWindowId = primaryWindowId; + abilityRequest.isStartInSplitMode = true; + return uiAbilityManager->NotifySCBToStartUIAbility(abilityRequest); +} + ErrCode AbilityManagerService::StartUIAbilities(const std::vector &wantList, const std::string &requestKey, sptr callerToken) { diff --git a/services/abilitymgr/src/ability_manager_stub.cpp b/services/abilitymgr/src/ability_manager_stub.cpp index 8a29991ffe3..d98a4008e9f 100644 --- a/services/abilitymgr/src/ability_manager_stub.cpp +++ b/services/abilitymgr/src/ability_manager_stub.cpp @@ -586,6 +586,9 @@ int AbilityManagerStub::OnRemoteRequestInnerFourteenth(uint32_t code, MessagePar if (interfaceCode == AbilityManagerInterfaceCode::START_UI_ABILITIES) { return StartUIAbilitiesInner(data, reply); } + if (interfaceCode == AbilityManagerInterfaceCode::START_UI_ABILITIES_IN_SPLIT_WINDOW_MODE) { + return StartUIAbilitiesInSplitWindowModeInner(data, reply); + } return ERR_CODE_NOT_EXIST; } @@ -3880,6 +3883,25 @@ int AbilityManagerStub::StartAbilityForResultAsCallerInner(MessageParcel &data, return NO_ERROR; } +int32_t AbilityManagerStub::StartUIAbilitiesInSplitWindowModeInner(MessageParcel &data, MessageParcel &reply) +{ + TAG_LOGI(AAFwkTag::ABILITYMGR, "call StartUIAbilitiesInSplitWindowModeInner"); + int32_t sourceWindowId = data.ReadInt32(); + std::unique_ptr want(data.ReadParcelable()); + if (want == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "want null"); + return ERR_INVALID_VALUE; + } + sptr callerToken = data.ReadRemoteObject(); + if (callerToken == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null callerToken"); + return INVALID_CALLER_TOKEN; + } + int32_t result = StartUIAbilitiesInSplitWindowMode(sourceWindowId, *want, callerToken); + reply.WriteInt32(result); + return NO_ERROR; +} + int32_t AbilityManagerStub::StartUIAbilitiesInner(MessageParcel &data, MessageParcel &reply) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call StartUIAbilitiesInner"); 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 26947e330cc..8f450e3d98c 100644 --- a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp +++ b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp @@ -1533,6 +1533,47 @@ sptr UIAbilityLifecycleManager::CreateSessionInfo(const AbilityRequ return sessionInfo; } +int UIAbilityLifecycleManager::NotifySCBPendingActivationInSplitMode(sptr &sessionInfo, + const AbilityRequest &abilityRequest) +{ + std::vector> sessionInfoList; + sptr sourceSessionInfo = new SessionInfo(); + sourceSessionInfo->persistentId = abilityRequest.primaryWindowId; + sessionInfoList.push_back(sourceSessionInfo); + sessionInfoList.push_back(sessionInfo); + std::vector configs; + Rosen::PendingSessionActivationConfig sourceConfig = {false, false}; + Rosen::PendingSessionActivationConfig targetConfig = {true, true}; + configs.push_back(sourceConfig); + configs.push_back(targetConfig); + + bool hasStartWindowOption = (sessionInfo->startWindowOption != nullptr); + bool hasStartWindow = hasStartWindowOption ? sessionInfo->startWindowOption->hasStartWindow : false; + std::string backgroundColor = + hasStartWindowOption ? sessionInfo->startWindowOption->startWindowBackgroundColor : ""; + sessionInfo->hideStartWindow = abilityRequest.hideStartWindow; + sessionInfo->windowCreateParams = abilityRequest.startOptions.windowCreateParams_; + + auto tmpSceneSession = iface_cast(rootSceneSession_); + if (tmpSceneSession == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null tmpSceneSession, scb does not exist"); + return ERR_INVALID_VALUE; + } + auto abilityRecord = Token::GetAbilityRecordByToken(abilityRequest.callerToken); + if (abilityRecord != nullptr) { + auto requestId = abilityRequest.want.GetStringParam(KEY_REQUEST_ID); + if (!requestId.empty()) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "notify request success, requestId:%{public}s", requestId.c_str()); + abilityRecord->NotifyAbilityRequestSuccess(requestId, abilityRequest.want.GetElement()); + } + const_cast(abilityRequest).want.RemoveParam(KEY_REQUEST_ID); + } + for (auto sessionInfo : sessionInfoList) { + sessionInfo->canStartAbilityFromBackground = true; + } + return static_cast(tmpSceneSession->BatchPendingSessionsActivation(sessionInfoList, configs)); +} + int UIAbilityLifecycleManager::NotifySCBPendingActivation(sptr &sessionInfo, const AbilityRequest &abilityRequest, std::string &errMsg) { @@ -1547,6 +1588,9 @@ int UIAbilityLifecycleManager::NotifySCBPendingActivation(sptr &ses (sessionInfo->want).GetIntParam(Want::PARAM_RESV_WINDOW_HEIGHT, 0), (sessionInfo->want).GetIntParam(Want::PARAM_RESV_WINDOW_MODE, 0), (sessionInfo->supportWindowModes).size(), sessionInfo->specifiedFlag.c_str()); + if (abilityRequest.isStartInSplitMode) { + return NotifySCBPendingActivationInSplitMode(sessionInfo, abilityRequest); + } bool hasStartWindowOption = (sessionInfo->startWindowOption != nullptr); bool hasStartWindow = hasStartWindowOption ? sessionInfo->startWindowOption->hasStartWindow : false; std::string backgroundColor = @@ -2602,6 +2646,58 @@ int UIAbilityLifecycleManager::SendSessionInfoToSCB(std::shared_ptr &callerAbility, sptr &sessionInfo) +{ + CHECK_POINTER_AND_RETURN(sessionInfo, ERR_INVALID_VALUE); + + std::vector> sessionInfoList; + sptr sourceSessionInfo = new SessionInfo(); + sourceSessionInfo->persistentId = primaryWindowId; + sessionInfoList.push_back(sourceSessionInfo); + sessionInfoList.push_back(sessionInfo); + + std::vector configs; + Rosen::PendingSessionActivationConfig sourceConfig = {false, false}; + Rosen::PendingSessionActivationConfig targetConfig = {true, true}; + configs.push_back(sourceConfig); + configs.push_back(targetConfig); + + auto tmpSceneSession = iface_cast(rootSceneSession_); + sptr callerSessionInfo = nullptr; + if (callerAbility != nullptr && (callerSessionInfo = callerAbility->GetSessionInfo()) != nullptr && + callerSessionInfo->sessionToken != nullptr) { + auto callerSession = iface_cast(callerSessionInfo->sessionToken); + CHECK_POINTER_AND_RETURN(callerSession, ERR_INVALID_VALUE); + CheckCallerFromBackground(callerAbility, sessionInfo); + auto requestId = sessionInfo->want.GetStringParam(KEY_REQUEST_ID); + if (!requestId.empty()) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "notify request success, requestId:%{public}s", requestId.c_str()); + callerAbility->NotifyAbilityRequestSuccess(requestId, sessionInfo->want.GetElement()); + } + sessionInfo->want.RemoveParam(KEY_REQUEST_ID); + TAG_LOGI(AAFwkTag::ABILITYMGR, "scb call, NotifySCBPendingActivation for callerSession, target: %{public}s", + sessionInfo->want.GetElement().GetAbilityName().c_str()); + callerSession->BatchPendingSessionsActivation(sessionInfoList, configs); + return ERR_OK; + } + CHECK_POINTER_AND_RETURN(tmpSceneSession, ERR_INVALID_VALUE); + sessionInfo->canStartAbilityFromBackground = true; + auto abilityRecord = Token::GetAbilityRecordByToken(sessionInfo->callerToken); + if (abilityRecord != nullptr) { + auto requestId = sessionInfo->want.GetStringParam(KEY_REQUEST_ID); + if (!requestId.empty()) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "notify request success, requestId:%{public}s", requestId.c_str()); + abilityRecord->NotifyAbilityRequestSuccess(requestId, sessionInfo->want.GetElement()); + } + sessionInfo->want.RemoveParam(KEY_REQUEST_ID); + } + TAG_LOGI(AAFwkTag::ABILITYMGR, "scb call, NotifySCBPendingActivation for rootSceneSession, target: %{public}s", + sessionInfo->want.GetElement().GetAbilityName().c_str()); + tmpSceneSession->BatchPendingSessionsActivation(sessionInfoList, configs); + return ERR_OK; +} + int32_t UIAbilityLifecycleManager::StartAbilityBySpecifed(const SpecifiedRequest &specifiedRequest, std::shared_ptr callerAbility) { @@ -2615,6 +2711,11 @@ int32_t UIAbilityLifecycleManager::StartAbilityBySpecifed(const SpecifiedRequest if (specifiedRequest.requestListId != REQUEST_LIST_ID_INIT) { HandleAbilitiesRequestDone(specifiedRequest.requestId, specifiedRequest.requestListId, sessionInfo); } else { + if (specifiedRequest.abilityRequest.isStartInSplitMode) { + SendSessionInfoToSCBInSplitMode(specifiedRequest.abilityRequest.primaryWindowId, + callerAbility, sessionInfo); + return ERR_OK; + } SendSessionInfoToSCB(callerAbility, sessionInfo); } return ERR_OK; -- Gitee