diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.cpp b/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.cpp index ea6e6db7f71de2e5b1fee2895dfd38e59e58b71f..d02ef8365fe82c5116382b4e0a994f5e4d1141cc 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.cpp +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.cpp @@ -30,6 +30,11 @@ using namespace AbilityRuntime; namespace { constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "JsRootSceneSession" }; const std::string PENDING_SCENE_CB = "pendingSceneSessionActivation"; +const std::string BATCH_PENDING_SCENE_ACTIVE_CB = "batchPendingSceneSessionsActivation"; +const std::unordered_map ListenerFuncMap { + {PENDING_SCENE_CB, RootListenerFuncType::PENDING_SCENE_CB}, + {BATCH_PENDING_SCENE_ACTIVE_CB, RootListenerFuncType::BATCH_PENDING_SCENE_ACTIVE_CB}, +}; } // namespace JsRootSceneSession::JsRootSceneSession(napi_env env, const sptr& rootSceneSession) @@ -108,6 +113,12 @@ napi_value JsRootSceneSession::OnRegisterCallback(napi_env env, napi_callback_in "Input parameter is missing or invalid")); return NapiGetUndefined(env); } + auto iterFunctionType = ListenerFuncMap.find(cbType); + if (iterFunctionType == ListenerFuncMap.end()) { + TLOGE(WmsLogTag::WMS_MAIN, "callback type is not supported, type=%{public}s", cbType.c_str()); + return NapiGetUndefined(env); + } + RootListenerFuncType rootlistenerFuncType = iterFunctionType->second; if (IsCallbackRegistered(env, cbType, value)) { return NapiGetUndefined(env); } @@ -117,10 +128,6 @@ napi_value JsRootSceneSession::OnRegisterCallback(napi_env env, napi_callback_in env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), "Root scene session is null!")); return NapiGetUndefined(env); } - - rootSceneSession_->SetPendingSessionActivationEventListener([this](SessionInfo& info) { - this->PendingSessionActivation(info); - }); std::shared_ptr callbackRef; napi_ref result = nullptr; napi_create_reference(env, value, 1, &result); @@ -130,10 +137,41 @@ napi_value JsRootSceneSession::OnRegisterCallback(napi_env env, napi_callback_in std::unique_lock lock(jsCbMapMutex_); jsCbMap_[cbType] = callbackRef; } + ProcessRegisterCallback(rootlistenerFuncType); WLOGFD("End, type=%{public}s", cbType.c_str()); return NapiGetUndefined(env); } +void JsRootSceneSession::ProcessRegisterCallback(RootListenerFuncType rootlistenerFuncType) +{ + switch (static_cast(rootlistenerFuncType)) { + case static_cast(RootListenerFuncType::PENDING_SCENE_CB): + ProcessPendingSceneSessionActivationRegister(); + break; + case static_cast(RootListenerFuncType::BATCH_PENDING_SCENE_ACTIVE_CB): + ProcessBatchPendingSceneSessionsActivationRegister(); + break; + default: + break; + } +} + +void JsRootSceneSession::ProcessPendingSceneSessionActivationRegister() +{ + rootSceneSession_->SetPendingSessionActivationEventListener([this](SessionInfo& info) { + this->PendingSessionActivation(info); + }); +} + +void JsRootSceneSession::ProcessBatchPendingSceneSessionsActivationRegister() +{ + rootSceneSession_->SetBatchPendingSessionsActivationEventListener([this] + (const std::vector>& sessionInfos) { + this->BatchPendingSessionsActivation(sessionInfos); + }); + TLOGD(WmsLogTag::WMS_LIFE, "success"); +} + napi_value JsRootSceneSession::OnLoadContent(napi_env env, napi_callback_info info) { TLOGD(WmsLogTag::WMS_LIFE, "[NAPI]"); @@ -265,6 +303,53 @@ void JsRootSceneSession::PendingSessionActivationInner(std::shared_ptrPostMainThreadTask(task, "PendingSessionActivationInner"); } +napi_value JsRootSceneSession::CreateSessionInfosNapiValue( + napi_env env, const std::vector>& sessionInfos) +{ + napi_value arrayValue = nullptr; + napi_create_array_with_length(env, sessionInfos.size(), &arrayValue); + + if (arrayValue == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "Failed to create napi array"); + return NapiGetUndefined(env); + } + + int32_t index = 0; + for (const auto& sessionInfo : sessionInfos) { + napi_value objValue = nullptr; + napi_create_object(env, &objValue); + if (objValue == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "failed to create napi object"); + return NapiGetUndefined(env); + } + napi_set_element(env, arrayValue, index++, CreateJsSessionInfo(env, *sessionInfo)); + } + return arrayValue; +} + +void JsRootSceneSession::BatchPendingSessionsActivationInner( + const std::vector>& sessionInfos) +{ + const char* const where = __func__; + auto task = [jsCallBack = GetJSCallback(BATCH_PENDING_SCENE_ACTIVE_CB), sessionInfos, env = env_, where] { + if (!jsCallBack) { + TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s jsCallBack is nullptr", where); + return; + } + + napi_value jsSessionInfos = CreateSessionInfosNapiValue(env, sessionInfos); + if (jsSessionInfos == nullptr) { + TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s target session info is nullptr", where); + return; + } + napi_value argv[] = {jsSessionInfos}; + TLOGNI(WmsLogTag::WMS_LIFE, "%{public}s task success", where); + napi_call_function(env, NapiGetUndefined(env), + jsCallBack->GetNapiValue(), ArraySize(argv), argv, nullptr); + }; + taskScheduler_->PostMainThreadTask(task, "BatchPendingSessionsActivationInner"); +} + static int32_t GetRealCallerSessionId(const sptr& sceneSession) { int32_t realCallerSessionId = SceneSessionManager::GetInstance().GetFocusedSessionId(); @@ -329,6 +414,66 @@ void JsRootSceneSession::PendingSessionActivation(SessionInfo& info) } } +void JsRootSceneSession::BatchPendingSessionsActivation(const std::vector>& sessionInfos) +{ + std::vector> sceneSessions; + for (auto& info : sessionInfos) { + if (info == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "sessionInfo is null"); + return; + } + TLOGI(WmsLogTag::WMS_LIFE, "bundleName %{public}s, moduleName %{public}s, abilityName %{public}s, " + "appIndex %{public}d, reuse %{public}d, requestId %{public}d, specifiedFlag %{public}s", + info->bundleName_.c_str(), info->moduleName_.c_str(), + info->abilityName_.c_str(), info->appIndex_, info->reuse, info->requestId, info->specifiedFlag_.c_str()); + auto sceneSession = GenSceneSession(*info); + if (sceneSession == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "GenSceneSession failed"); + return; + } + + if (info->want != nullptr) { + bool isNeedBackToOther = info->want->GetBoolParam(AAFwk::Want::PARAM_BACK_TO_OTHER_MISSION_STACK, false); + TLOGI(WmsLogTag::WMS_LIFE, "session: %{public}d isNeedBackToOther: %{public}d", + sceneSession->GetPersistentId(), isNeedBackToOther); + if (isNeedBackToOther) { + info->callerPersistentId_ = GetRealCallerSessionId(sceneSession); + VerifyCallerToken(*info); + } else { + info->callerPersistentId_ = INVALID_SESSION_ID; + } + + auto focusedOnShow = info->want->GetBoolParam(AAFwk::Want::PARAM_RESV_WINDOW_FOCUSED, true); + sceneSession->SetFocusedOnShow(focusedOnShow); + + std::string continueSessionId = + info->want->GetStringParam(Rosen::PARAM_KEY::PARAM_DMS_CONTINUE_SESSION_ID_KEY); + if (!continueSessionId.empty()) { + info->continueSessionId_ = continueSessionId; + TLOGI(WmsLogTag::WMS_LIFE, "continueSessionId from ability manager: %{public}s", + continueSessionId.c_str()); + } + + // app continue report for distributed scheduled service + if (info->want->GetIntParam(Rosen::PARAM_KEY::PARAM_DMS_PERSISTENT_ID_KEY, 0) > 0) { + TLOGI(WmsLogTag::WMS_LIFE, "Continue app with persistentId: %{public}d", info->persistentId_); + SingletonContainer::Get().ReportContinueApp(true, static_cast(WSError::WS_OK)); + } + } else { + TLOGI(WmsLogTag::WMS_LIFE, "session: %{public}d want is empty", sceneSession->GetPersistentId()); + sceneSession->SetFocusedOnShow(true); + } + + sceneSession->SetSessionInfo(*info); + std::shared_ptr sessionInfo = std::make_shared(*info); + if (info->fullScreenStart_) { + sceneSession->NotifySessionFullScreen(true); + } + sceneSessions.emplace_back(sceneSession); + } + BatchPendingSessionsActivationInner(sessionInfos); +} + void JsRootSceneSession::VerifyCallerToken(SessionInfo& info) { auto callerSession = SceneSessionManager::GetInstance().GetSceneSession(info.callerPersistentId_); diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.h b/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.h index db524e845c72b571bbb2dc12b5748505a2aa8e3f..e3fe23af615f1b1b5a28480715237a8d70a08f1d 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.h +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.h @@ -22,6 +22,11 @@ #include "js_scene_utils.h" namespace OHOS::Rosen { +enum class RootListenerFuncType : uint32_t { + PENDING_SCENE_CB, + BATCH_PENDING_SCENE_ACTIVE_CB, +}; + class JsRootSceneSession : public RefBase { public: JsRootSceneSession(napi_env env, const sptr& rootSceneSession); @@ -41,7 +46,17 @@ private: void PendingSessionActivationInner(std::shared_ptr sessionInfo); sptr GenSceneSession(SessionInfo& info); std::shared_ptr GetJSCallback(const std::string& functionName) const; + void ProcessRegisterCallback(RootListenerFuncType rootlistenerFuncType); + /* + * Window Lifecycle + */ + void ProcessPendingSceneSessionActivationRegister(); + void ProcessBatchPendingSceneSessionsActivationRegister(); + void BatchPendingSessionsActivation(const std::vector>& sessionInfos); + void BatchPendingSessionsActivationInner(const std::vector>& sessionInfos); + static napi_value CreateSessionInfosNapiValue( + napi_env env, const std::vector>& sessionInfos); napi_env env_; std::map> jsCbMap_; mutable std::shared_mutex jsCbMapMutex_; diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp index a6aee2e2d7f18c0bab0f9c22ac843bacfd9ecb90..1d6748c1079b281a51cf6c952d56ce5e187d5849 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp @@ -109,6 +109,7 @@ const std::string USE_IMPLICITANIMATION_CB = "useImplicitAnimationChange"; const std::string SET_WINDOW_SHADOWS_CB = "setWindowShadows"; const std::string SET_SUB_WINDOW_SOURCE_CB = "setSubWindowSource"; const std::string ANIMATE_TO_CB = "animateToTargetProperty"; +const std::string BATCH_PENDING_SCENE_ACTIVE_CB = "batchPendingSceneSessionsActivation"; constexpr int ARG_COUNT_1 = 1; constexpr int ARG_COUNT_2 = 2; @@ -208,6 +209,7 @@ const std::map ListenerFuncMap { {SET_WINDOW_SHADOWS_CB, ListenerFuncType::SET_WINDOW_SHADOWS_CB}, {SET_SUB_WINDOW_SOURCE_CB, ListenerFuncType::SET_SUB_WINDOW_SOURCE_CB}, {ANIMATE_TO_CB, ListenerFuncType::ANIMATE_TO_CB}, + {BATCH_PENDING_SCENE_ACTIVE_CB, ListenerFuncType::BATCH_PENDING_SCENE_ACTIVE_CB}, {FLOATING_BALL_UPDATE_CB, ListenerFuncType::FLOATING_BALL_UPDATE_CB}, {FLOATING_BALL_STOP_CB, ListenerFuncType::FLOATING_BALL_STOP_CB}, {FLOATING_BALL_RESTORE_MAIN_WINDOW_CB, ListenerFuncType::FLOATING_BALL_RESTORE_MAIN_WINDOW_CB}, @@ -657,6 +659,26 @@ void JsSceneSession::ProcessPendingSceneSessionActivationRegister() TLOGD(WmsLogTag::WMS_LIFE, "success"); } +void JsSceneSession::ProcessBatchPendingSceneSessionsActivationRegister() +{ + auto session = weakSession_.promote(); + if (session == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "session is nullptr, id:%{public}d", persistentId_); + return; + } + const char* const where = __func__; + session->SetBatchPendingSessionsActivationEventListener( + [weakThis = wptr(this), where](std::vector>& sessionInfos) { + auto jsSceneSession = weakThis.promote(); + if (!jsSceneSession) { + TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s jsSceneSession is null", where); + return; + } + jsSceneSession->BatchPendingSessionsActivation(sessionInfos); + }); + TLOGD(WmsLogTag::WMS_LIFE, "success"); +} + void JsSceneSession::ProcessWindowDragHotAreaRegister() { TLOGD(WmsLogTag::DEFAULT, "[NAPI]"); @@ -3080,6 +3102,9 @@ void JsSceneSession::ProcessRegisterCallback(ListenerFuncType listenerFuncType) case static_cast(ListenerFuncType::ANIMATE_TO_CB): ProcessAnimateToTargetPropertyRegister(); break; + case static_cast(ListenerFuncType::BATCH_PENDING_SCENE_ACTIVE_CB): + ProcessBatchPendingSceneSessionsActivationRegister(); + break; case static_cast(ListenerFuncType::FLOATING_BALL_UPDATE_CB): ProcessFloatingBallUpdateRegister(); break; @@ -4577,6 +4602,103 @@ void JsSceneSession::PendingSessionActivationInner(std::shared_ptr taskScheduler_->PostMainThreadTask(task, "PendingSessionActivationInner"); } +napi_value JsSceneSession::CreateSessionInfosNapiValue( + napi_env env, const std::vector>& sessionInfos) +{ + napi_value arrayValue = nullptr; + napi_create_array_with_length(env, sessionInfos.size(), &arrayValue); + + if (arrayValue == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "Failed to create napi array"); + return NapiGetUndefined(env); + } + + int32_t index = 0; + for (const auto& sessionInfo : sessionInfos) { + napi_value objValue = nullptr; + napi_create_object(env, &objValue); + if (objValue == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "failed to create napi object"); + return NapiGetUndefined(env); + } + napi_set_element(env, arrayValue, index++, CreateJsSessionInfo(env, *sessionInfo)); + } + return arrayValue; +} + +void JsSceneSession::BatchPendingSessionsActivation(const std::vector>& sessionInfos) +{ + std::vector> sceneSessions; + for (auto& info : sessionInfos) { + if (info == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "sessioninfo is null"); + return; + } + TLOGI(WmsLogTag::WMS_LIFE, "bundleName %{public}s, moduleName %{public}s, abilityName %{public}s, " + "appIndex %{public}d, reuse %{public}d, requestId %{public}d, specifiedFlag %{public}s", + info->bundleName_.c_str(), info->moduleName_.c_str(), + info->abilityName_.c_str(), info->appIndex_, info->reuse, info->requestId, info->specifiedFlag_.c_str()); + auto sceneSession = GenSceneSession(*info); + if (sceneSession == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "GenSceneSession failed"); + return; + } + if (info->want != nullptr) { + auto focusedOnShow = info->want->GetBoolParam(AAFwk::Want::PARAM_RESV_WINDOW_FOCUSED, true); + sceneSession->SetFocusedOnShow(focusedOnShow); + } else { + sceneSession->SetFocusedOnShow(true); + } + auto callerSession = SceneSessionManager::GetInstance().GetSceneSession(info->callerPersistentId_); + if (callerSession != nullptr) { + info->isCalledRightlyByCallerId_ = (info->callerToken_ == callerSession->GetAbilityToken()) && + SessionPermission::VerifyPermissionByBundleName(info->bundleName_, + "ohos.permission.CALLED_TRANSITION_ON_LOCK_SCREEN", + SceneSessionManager::GetInstance().GetCurrentUserId()); + TLOGI(WmsLogTag::WMS_SCB, + "isCalledRightlyByCallerId result is: %{public}d", info->isCalledRightlyByCallerId_); + } + if (info->fullScreenStart_) { + sceneSession->NotifySessionFullScreen(true); + } + sceneSessions.emplace_back(sceneSession); + } + BatchPendingSessionsActivationInner(sessionInfos); +} + +void JsSceneSession::BatchPendingSessionsActivationInner(const std::vector>& sessionInfos) +{ + const char* const where = __func__; + auto task = [weakThis = wptr(this), persistentId = persistentId_, weakSession = weakSession_, + sessionInfos, env = env_, where] { + auto session = weakSession.promote(); + if (session == nullptr) { + TLOGNE(WmsLogTag::WMS_LIFE, "session is nullptr"); + return; + } + auto jsSceneSession = weakThis.promote(); + if (!jsSceneSession || jsSceneSessionMap_.find(persistentId) == jsSceneSessionMap_.end()) { + TLOGNE(WmsLogTag::WMS_LIFE, "jsSceneSession id:%{public}d has been destroyed", persistentId); + return; + } + auto jsCallBack = jsSceneSession->GetJSCallback(BATCH_PENDING_SCENE_ACTIVE_CB); + if (!jsCallBack) { + TLOGNE(WmsLogTag::WMS_LIFE, "jsCallBack is nullptr"); + return; + } + napi_value jsSessionInfos = CreateSessionInfosNapiValue(env, sessionInfos); + if (jsSessionInfos == nullptr) { + TLOGNE(WmsLogTag::WMS_LIFE, "target session info is nullptr"); + return; + } + napi_value argv[] = { jsSessionInfos }; + TLOGNI(WmsLogTag::WMS_LIFE, "%{public}s task success, id:%{public}d", where, persistentId); + napi_call_function(env, NapiGetUndefined(env), + jsCallBack->GetNapiValue(), ArraySize(argv), argv, nullptr); + }; + taskScheduler_->PostMainThreadTask(task, "BatchPendingSessionsActivationInner"); +} + void JsSceneSession::OnBackPressed(bool needMoveToBackground) { TLOGI(WmsLogTag::DEFAULT, "%{public}d", needMoveToBackground); diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h index 38d2290f4a106765a1c97cf4ab19518444566947..c198904a4b8ae599194c3f3d63324a957a5cbcb9 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h @@ -106,6 +106,7 @@ enum class ListenerFuncType : uint32_t { SET_SUB_WINDOW_SOURCE_CB, ANIMATE_TO_CB, PENDING_SESSION_TO_BACKGROUND_CB, + BATCH_PENDING_SCENE_ACTIVE_CB, FLOATING_BALL_UPDATE_CB, FLOATING_BALL_STOP_CB, FLOATING_BALL_RESTORE_MAIN_WINDOW_CB, @@ -127,6 +128,7 @@ private: * Window Lifecycle */ void ProcessPendingSceneSessionActivationRegister(); + void ProcessBatchPendingSceneSessionsActivationRegister(); void ProcessSessionStateChangeRegister(); void ProcessUpdateTransitionAnimationRegister(); void ProcessSessionEventRegister(); @@ -143,6 +145,8 @@ private: sptr GenSceneSession(SessionInfo& info); void PendingSessionActivation(SessionInfo& info); void PendingSessionActivationInner(std::shared_ptr sessionInfo); + void BatchPendingSessionsActivation(const std::vector>& sessionInfos); + void BatchPendingSessionsActivationInner(const std::vector>& sessionInfos); void OnSessionStateChange(const SessionState& state); void OnUpdateTransitionAnimation(const WindowTransitionType& type, const TransitionAnimation& animation); void OnSessionEvent(uint32_t eventId, const SessionEventParam& param); @@ -243,6 +247,8 @@ private: static napi_value SetSidebarBlurMaximize(napi_env env, napi_callback_info info); static napi_value RequestSpecificSessionClose(napi_env env, napi_callback_info info); static napi_value SendFbActionEvent(napi_env env, napi_callback_info info); + static napi_value CreateSessionInfosNapiValue( + napi_env env, const std::vector>& sessionInfos); /* * PC Window diff --git a/window_scene/session/host/include/scene_session.h b/window_scene/session/host/include/scene_session.h index 78d06a87e40bdd079c978e182ab9268a9fff714e..256bbf85bfd9077dce455f54df4150c2d5abf371 100644 --- a/window_scene/session/host/include/scene_session.h +++ b/window_scene/session/host/include/scene_session.h @@ -273,6 +273,10 @@ public: bool isKeyboardShow, const WindowAnimationInfo& animationInfo) {} WSError ChangeSessionVisibilityWithStatusBar(const sptr info, bool visible) override; WSError PendingSessionActivation(const sptr info) override; + WSError BatchPendingSessionsActivation(const std::vector>& abilitySessionInfos) override; + WSError DoBatchPendingSessionsActivation( + const std::vector>& abilitySessionInfos, sptr& session, + bool isFoundationCall); bool DisallowActivationFromPendingBackground(bool isPcOrPadEnableActivation, bool isFoundationCall, bool canStartAbilityFromBackground, bool isFromAncoAndToAnco); WSError TerminateSession(const sptr info) override; diff --git a/window_scene/session/host/include/session.h b/window_scene/session/host/include/session.h index d083ae9ab779e89300e9c08e62cb3b973f902c9e..ba77498192a83108d5ef5aa1c54d7d8ced626728 100644 --- a/window_scene/session/host/include/session.h +++ b/window_scene/session/host/include/session.h @@ -59,6 +59,7 @@ using NotifyStopFloatingBallFunc = std::function; using NotifyRestoreFloatingBallMainWindowFunc = std::function& want)>; using NotifySessionDisplayIdChangeFunc = std::function; using NotifyPendingSessionActivationFunc = std::function; +using NotifyBatchPendingSessionsActivationFunc = std::function>& info)>; using NotifyChangeSessionVisibilityWithStatusBarFunc = std::function; using NotifySessionStateChangeFunc = std::function; using NotifyBufferAvailableChangeFunc = std::function; @@ -187,6 +188,7 @@ public: bool RegisterLifecycleListener(const std::shared_ptr& listener); bool UnregisterLifecycleListener(const std::shared_ptr& listener); void SetPendingSessionActivationEventListener(NotifyPendingSessionActivationFunc&& func); + void SetBatchPendingSessionsActivationEventListener(NotifyBatchPendingSessionsActivationFunc&& func); void SetTerminateSessionListener(NotifyTerminateSessionFunc&& func); void SetTerminateSessionListenerNew(NotifyTerminateSessionFuncNew&& func); void SetSessionExceptionListener(NotifySessionExceptionFunc&& func, bool fromJsScene); @@ -845,6 +847,7 @@ protected: * Window LifeCycle */ NotifyPendingSessionActivationFunc pendingSessionActivationFunc_; + NotifyBatchPendingSessionsActivationFunc batchPendingSessionsActivationFunc_; NotifyPendingSessionToForegroundFunc pendingSessionToForegroundFunc_; NotifyPendingSessionToBackgroundFunc pendingSessionToBackgroundFunc_; NotifyPendingSessionToBackgroundForDelegatorFunc pendingSessionToBackgroundForDelegatorFunc_; diff --git a/window_scene/session/host/include/zidl/session_ipc_interface_code.h b/window_scene/session/host/include/zidl/session_ipc_interface_code.h index f17e366911548fd7bc4c48396b6b8fbe4bbf940a..45a3f3323177ab9df0bde557755b040037146d7a 100644 --- a/window_scene/session/host/include/zidl/session_ipc_interface_code.h +++ b/window_scene/session/host/include/zidl/session_ipc_interface_code.h @@ -32,6 +32,7 @@ enum class SessionInterfaceCode { TRANS_ID_EXCEPTION, TRANS_ID_DRAWING_COMPLETED, TRANS_ID_APP_REMOVE_STARTING_WINDOW, + TRANS_ID_BATCH_ACTIVE_PENDING_SESSION, // Scene TRANS_ID_SESSION_EVENT = 100, diff --git a/window_scene/session/host/include/zidl/session_proxy.h b/window_scene/session/host/include/zidl/session_proxy.h index e770039ea9d27f78627e4a401a49b27fce671367..419704ebe6d0a9dd500441e873c636a37b14545b 100644 --- a/window_scene/session/host/include/zidl/session_proxy.h +++ b/window_scene/session/host/include/zidl/session_proxy.h @@ -42,6 +42,7 @@ public: WSError ChangeSessionVisibilityWithStatusBar(const sptr abilitySessionInfo, bool visible) override; WSError PendingSessionActivation(const sptr abilitySessionInfo) override; + WSError BatchPendingSessionsActivation(const std::vector>& abilitySessionInfos) override; WSError TerminateSession(const sptr abilitySessionInfo) override; WSError NotifySessionException( const sptr abilitySessionInfo, const ExceptionInfo& exceptionInfo) override; @@ -80,6 +81,8 @@ public: WSError SetSessionLabelAndIcon(const std::string& label, const std::shared_ptr& icon) override; WSError SetSubWindowSource(SubWindowSource source) override; + WSError WriteOneSessionInfo(MessageParcel& data, const sptr& abilitySessionInfo); + WSError WriteOneSessionInfoPart(MessageParcel& data, const sptr& abilitySessionInfo); /* * UIExtension diff --git a/window_scene/session/host/include/zidl/session_stub.h b/window_scene/session/host/include/zidl/session_stub.h index a300e340951eb6393f1e8f6e3c89ad1445a72ca2..477d72e2759cd6c081dd5b8fb7c4b7ac2f4a7022 100644 --- a/window_scene/session/host/include/zidl/session_stub.h +++ b/window_scene/session/host/include/zidl/session_stub.h @@ -63,6 +63,7 @@ private: int HandleRaiseAppMainWindowToTop(MessageParcel& data, MessageParcel& reply); int HandleChangeSessionVisibilityWithStatusBar(MessageParcel& data, MessageParcel& reply); int HandlePendingSessionActivation(MessageParcel& data, MessageParcel& reply); + int HandleBatchPendingSessionsActivation(MessageParcel& data, MessageParcel& reply); int HandleTerminateSession(MessageParcel& data, MessageParcel& reply); int HandleSessionException(MessageParcel& data, MessageParcel& reply); int HandleProcessPointDownSession(MessageParcel& data, MessageParcel& reply); @@ -95,6 +96,7 @@ private: int HandleUpdateScreenshotAppEventRegistered(MessageParcel& data, MessageParcel& reply); int HandleUpdateAcrossDisplaysChangeRegistered(MessageParcel& data, MessageParcel& reply); int HandleGetIsHighlighted(MessageParcel& data, MessageParcel& reply); + int ReadOneAbilitySessionInfo(MessageParcel& data, sptr abilitySessionInfo); // extension extension int HandleTransferAbilityResult(MessageParcel& data, MessageParcel& reply); diff --git a/window_scene/session/host/src/scene_session.cpp b/window_scene/session/host/src/scene_session.cpp index af15df2cb68d49aa1a9c7381eefa01d54eaa9c47..38d3a61e506faa53a4ac1a2eb76885cf7fe7219f 100644 --- a/window_scene/session/host/src/scene_session.cpp +++ b/window_scene/session/host/src/scene_session.cpp @@ -5488,6 +5488,78 @@ WSError SceneSession::PendingSessionActivation(const sptr ab return WSError::WS_OK; } +WSError SceneSession::DoBatchPendingSessionsActivation( + const std::vector>& abilitySessionInfos, + sptr& session, bool isFoundationCall) +{ + std::vector> sessionInfos; + for (auto& abilitySessionInfo : abilitySessionInfos) { + if (abilitySessionInfo == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "abilitySessionInfo is null"); + return WSError::WS_ERROR_NULLPTR; + } + bool isFromAncoAndToAnco = session->IsAnco() && AbilityInfoManager::GetInstance().IsAnco( + abilitySessionInfo->want.GetElement().GetBundleName(), + abilitySessionInfo->want.GetElement().GetAbilityName(), abilitySessionInfo->want.GetModuleName()); + if (session->DisallowActivationFromPendingBackground(session->IsPcOrPadEnableActivation(), isFoundationCall, + abilitySessionInfo->canStartAbilityFromBackground, isFromAncoAndToAnco)) { + return WSError::WS_ERROR_INVALID_OPERATION; + } + std::shared_ptr info = + std::make_shared( + MakeSessionInfoDuringPendingActivation(abilitySessionInfo, session, isFoundationCall)); + sessionInfos.emplace_back(info); + if (MultiInstanceManager::IsSupportMultiInstance(session->systemConfig_) && + MultiInstanceManager::GetInstance().IsMultiInstance(info->bundleName_)) { + if (!MultiInstanceManager::GetInstance().MultiInstancePendingSessionActivation(*info)) { + TLOGE(WmsLogTag::WMS_LIFE, + "multi instance start fail, id:%{public}d instanceKey:%{public}s", + session->GetPersistentId(), info->appInstanceKey_.c_str()); + return WSError::WS_ERROR_INVALID_PARAM; + } + } + session->sessionInfo_.reuseDelegatorWindow = abilitySessionInfo->reuseDelegatorWindow; + session->HandleCastScreenConnection(*info, session); + } + session->sessionInfo_.startMethod = StartMethod::START_CALL; + if (session->batchPendingSessionsActivationFunc_) { + session->batchPendingSessionsActivationFunc_(sessionInfos); + } + return WSError::WS_OK; +} + +WSError SceneSession::BatchPendingSessionsActivation(const std::vector>& abilitySessionInfos) +{ + TLOGI(WmsLogTag::WMS_LIFE, "Batch pending session activations size: %{public}zu", abilitySessionInfos.size()); + if (!SessionPermission::IsSystemAppCall() && !SessionPermission::IsSACalling()) { + TLOGE(WmsLogTag::WMS_LIFE, "The caller is neither a system app nor an SA."); + return WSError::WS_ERROR_INVALID_PERMISSION; + } + if (!SessionPermission::VerifyCallingPermission(PermissionConstants::PERMISSION_MANAGE_MISSION)) { + TLOGE(WmsLogTag::WMS_LIFE, "The caller has not permission granted"); + return WSError::WS_ERROR_INVALID_PERMISSION; + } + + bool isFoundationCall = SessionPermission::IsFoundationCall(); + PostTask([weakThis = wptr(this), abilitySessionInfos, isFoundationCall, where = __func__] { + auto session = weakThis.promote(); + if (!session) { + TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is null", where); + return WSError::WS_ERROR_DESTROYED_OBJECT; + } + if (abilitySessionInfos.empty()) { + TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s abilitySessionInfo is null", where); + return WSError::WS_ERROR_NULLPTR; + } + if (session->sessionInfo_.reuseDelegatorWindow) { + TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s not support hook", where); + WSError::WS_ERROR_INVALID_PARAM; + } + return session->DoBatchPendingSessionsActivation(abilitySessionInfos, session, isFoundationCall); + }, __func__); + return WSError::WS_OK; +} + bool SceneSession::DisallowActivationFromPendingBackground(bool isPcOrPadEnableActivation, bool isFoundationCall, bool canStartAbilityFromBackground, bool isFromAncoAndToAnco) { diff --git a/window_scene/session/host/src/session.cpp b/window_scene/session/host/src/session.cpp index 93333f58fef33e906d691abfeaad75907e6a10e6..92c026539c4ebd0f44ad83ea84782c8287617350 100644 --- a/window_scene/session/host/src/session.cpp +++ b/window_scene/session/host/src/session.cpp @@ -1781,6 +1781,19 @@ void Session::SetPendingSessionActivationEventListener(NotifyPendingSessionActiv }, where); } +void Session::SetBatchPendingSessionsActivationEventListener(NotifyBatchPendingSessionsActivationFunc&& func) +{ + const char* const where = __func__; + PostTask([weakThis = wptr(this), func = std::move(func), where] { + auto session = weakThis.promote(); + if (!session) { + TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where); + return; + } + session->batchPendingSessionsActivationFunc_ = std::move(func); + }, where); +} + void Session::SetBackPressedListenser(NotifyBackPressedFunc&& func) { const char* const where = __func__; diff --git a/window_scene/session/host/src/zidl/session_proxy.cpp b/window_scene/session/host/src/zidl/session_proxy.cpp index 4aa198abd49f177183da5230a8946a43b4db968f..6697af8a6b457209abbdfe5853a0b7b07981872c 100644 --- a/window_scene/session/host/src/zidl/session_proxy.cpp +++ b/window_scene/session/host/src/zidl/session_proxy.cpp @@ -549,6 +549,131 @@ WSError SessionProxy::PendingSessionActivation(sptr abilityS return static_cast(ret); } +WSError SessionProxy::BatchPendingSessionsActivation(const std::vector>& abilitySessionInfos) +{ + if (abilitySessionInfos.empty()) { + TLOGE(WmsLogTag::WMS_LIFE, "abilitySessionInfos is empty"); + return WSError::WS_ERROR_INVALID_PARAM; + } + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + TLOGE(WmsLogTag::WMS_LIFE, "Write interfaceToken failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (!data.WriteInt32(static_cast(abilitySessionInfos.size()))) { + TLOGE(WmsLogTag::WMS_LIFE, "Write ability session info list size failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + for (auto abilitySessionInfo : abilitySessionInfos) { + WSError writeRet = WriteOneSessionInfo(data, abilitySessionInfo); + if (writeRet != WSError::WS_OK) { + return writeRet; + } + } + sptr remote = Remote(); + if (remote == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "remote is null"); + return WSError::WS_ERROR_IPC_FAILED; + } + TLOGI(WmsLogTag::WMS_LIFE, "batch pending session activations size: %{public}zu", abilitySessionInfos.size()); + if (remote->SendRequest(static_cast(SessionInterfaceCode::TRANS_ID_BATCH_ACTIVE_PENDING_SESSION), + data, reply, option) != ERR_NONE) { + TLOGE(WmsLogTag::WMS_LIFE, "SendRequest failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +WSError SessionProxy::WriteOneSessionInfo(MessageParcel& data, const sptr& abilitySessionInfo) +{ + if (!WriteAbilitySessionInfoBasic(data, abilitySessionInfo)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write abilitySessionInfoBasic failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (!data.WriteBool(abilitySessionInfo->canStartAbilityFromBackground)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write canStartAbilityFromBackground failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (!data.WriteBool(abilitySessionInfo->isAtomicService) || + !data.WriteBool(abilitySessionInfo->isBackTransition) || + !data.WriteBool(abilitySessionInfo->needClearInNotShowRecent)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write isAtomicService or isBackTransition or needClearInNotShowRecent failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (abilitySessionInfo->callerToken) { + if (!data.WriteBool(true) || !data.WriteRemoteObject(abilitySessionInfo->callerToken)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write callerToken info failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + } else { + if (!data.WriteBool(false)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write has not callerToken info failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + } + if (abilitySessionInfo->startSetting) { + if (!data.WriteBool(true) || !data.WriteParcelable(abilitySessionInfo->startSetting.get())) { + TLOGE(WmsLogTag::WMS_LIFE, "Write startSetting failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + } else { + if (!data.WriteBool(false)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write has not startSetting failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + } + return WriteOneSessionInfoPart(data, abilitySessionInfo); +} + +WSError SessionProxy::WriteOneSessionInfoPart(MessageParcel& data, const sptr& abilitySessionInfo) +{ + if (abilitySessionInfo->startWindowOption) { + if (!data.WriteBool(true) || !data.WriteParcelable(abilitySessionInfo->startWindowOption.get())) { + TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "Write startWindowOption failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + } else { + if (!data.WriteBool(false)) { + TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "Write has not startWindowOption failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + } + if (!data.WriteString(abilitySessionInfo->instanceKey)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write instanceKey failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (!data.WriteBool(abilitySessionInfo->isFromIcon)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write isFromIcon failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + auto size = abilitySessionInfo->supportWindowModes.size(); + if (size > 0 && size <= WINDOW_SUPPORT_MODE_MAX_SIZE) { + if (!data.WriteUint32(static_cast(size))) { + return WSError::WS_ERROR_IPC_FAILED; + } + for (decltype(size) i = 0; i < size; i++) { + if (!data.WriteInt32(static_cast(abilitySessionInfo->supportWindowModes[i]))) { + return WSError::WS_ERROR_IPC_FAILED; + } + } + } else { + if (!data.WriteUint32(0)) { + return WSError::WS_ERROR_IPC_FAILED; + } + } + if (!data.WriteString(abilitySessionInfo->specifiedFlag)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write specifiedFlag failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (!data.WriteBool(abilitySessionInfo->reuseDelegatorWindow)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write reuseDelegatorWindow failed."); + return WSError::WS_ERROR_IPC_FAILED; + } + return WSError::WS_OK; +} + WSError SessionProxy::TerminateSession(const sptr abilitySessionInfo) { if (abilitySessionInfo == nullptr) { diff --git a/window_scene/session/host/src/zidl/session_stub.cpp b/window_scene/session/host/src/zidl/session_stub.cpp index 7e4b147d1c514d665d7c7fab19f0528c13158e3c..a80e4dd2c764370c135068353f03fd86b4bb59be 100644 --- a/window_scene/session/host/src/zidl/session_stub.cpp +++ b/window_scene/session/host/src/zidl/session_stub.cpp @@ -37,6 +37,7 @@ class AccessibilityEventInfo; namespace OHOS::Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "SessionStub" }; +constexpr int32_t MAX_ABILITY_SESSION_INFOS = 4; int ReadBasicAbilitySessionInfo(MessageParcel& data, sptr abilitySessionInfo) { @@ -158,6 +159,8 @@ int SessionStub::ProcessRemoteRequest(uint32_t code, MessageParcel& data, Messag return HandleChangeSessionVisibilityWithStatusBar(data, reply); case static_cast(SessionInterfaceCode::TRANS_ID_ACTIVE_PENDING_SESSION): return HandlePendingSessionActivation(data, reply); + case static_cast(SessionInterfaceCode::TRANS_ID_BATCH_ACTIVE_PENDING_SESSION): + return HandleBatchPendingSessionsActivation(data, reply); case static_cast(SessionInterfaceCode::TRANS_ID_RESTORE_MAIN_WINDOW): return HandleRestoreMainWindow(data, reply); case static_cast(SessionInterfaceCode::TRANS_ID_TERMINATE): @@ -804,6 +807,104 @@ int SessionStub::HandlePendingSessionActivation(MessageParcel& data, MessageParc return ERR_NONE; } +int SessionStub::HandleBatchPendingSessionsActivation(MessageParcel& data, MessageParcel& reply) +{ + TLOGD(WmsLogTag::WMS_LIFE, "In!"); + int32_t size = 0; + if (!data.ReadInt32(size) || size < 0 || size > MAX_ABILITY_SESSION_INFOS) { + TLOGE(WmsLogTag::WMS_LIFE, "Read ability session info size failed"); + return ERR_INVALID_DATA; + } + std::vector> abilitySessionInfos; + for (int32_t i = 0; i < size; i++) { + sptr abilitySessionInfo = sptr::MakeSptr(); + int readRet = ReadOneAbilitySessionInfo(data, abilitySessionInfo); + if (readRet != ERR_NONE) { + return readRet; + } + abilitySessionInfos.emplace_back(abilitySessionInfo); + } + WSError errCode = BatchPendingSessionsActivation(abilitySessionInfos); + if (!reply.WriteUint32(static_cast(errCode))) { + TLOGE(WmsLogTag::WMS_LIFE, "Write errCode failed"); + } + return ERR_NONE; +} + +int SessionStub::ReadOneAbilitySessionInfo(MessageParcel& data, sptr abilitySessionInfo) +{ + int32_t readResult = ReadBasicAbilitySessionInfo(data, abilitySessionInfo); + if (readResult == ERR_INVALID_DATA) { + return ERR_INVALID_DATA; + } + if (!data.ReadBool(abilitySessionInfo->canStartAbilityFromBackground)) { + TLOGE(WmsLogTag::WMS_LIFE, "Read canStartAbilityFromBackground failed."); + return ERR_INVALID_DATA; + } + if (!data.ReadBool(abilitySessionInfo->isAtomicService)) { + TLOGE(WmsLogTag::WMS_LIFE, "Read isAtomicService failed."); + return ERR_INVALID_DATA; + } + if (!data.ReadBool(abilitySessionInfo->isBackTransition)) { + TLOGE(WmsLogTag::WMS_LIFE, "Read isBackTransition failed."); + return ERR_INVALID_DATA; + } + if (!data.ReadBool(abilitySessionInfo->needClearInNotShowRecent)) { + TLOGE(WmsLogTag::WMS_LIFE, "Read needClearInNotShowRecent failed."); + return ERR_INVALID_DATA; + } + bool hasCallerToken = false; + if (!data.ReadBool(hasCallerToken)) { + TLOGE(WmsLogTag::WMS_LIFE, "Read hasCallerToken failed."); + return ERR_INVALID_DATA; + } + if (hasCallerToken) { + abilitySessionInfo->callerToken = data.ReadRemoteObject(); + } + bool hasStartSetting = false; + if (!data.ReadBool(hasStartSetting)) { + TLOGE(WmsLogTag::WMS_LIFE, "Read hasStartSetting failed."); + return ERR_INVALID_DATA; + } + if (hasStartSetting) { + abilitySessionInfo->startSetting.reset(data.ReadParcelable()); + } + bool hasStartWindowOption = false; + if (!data.ReadBool(hasStartWindowOption)) { + TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "Read hasStartWindowOption failed."); + return ERR_INVALID_DATA; + } + if (hasStartWindowOption) { + auto startWindowOption = data.ReadParcelable(); + abilitySessionInfo->startWindowOption.reset(startWindowOption); + } + if (!data.ReadString(abilitySessionInfo->instanceKey)) { + TLOGE(WmsLogTag::WMS_LIFE, "Read instanceKey failed."); + return ERR_INVALID_VALUE; + } + if (!data.ReadBool(abilitySessionInfo->isFromIcon)) { + TLOGE(WmsLogTag::WMS_LIFE, "Read isFromIcon failed."); + return ERR_INVALID_DATA; + } + uint32_t size = data.ReadUint32(); + if (size > 0 && size <= WINDOW_SUPPORT_MODE_MAX_SIZE) { + abilitySessionInfo->supportWindowModes.reserve(size); + for (uint32_t i = 0; i < size; i++) { + abilitySessionInfo->supportWindowModes.push_back( + static_cast(data.ReadInt32())); + } + } + if (!data.ReadString(abilitySessionInfo->specifiedFlag)) { + TLOGE(WmsLogTag::WMS_LIFE, "Read specifiedFlag failed."); + return ERR_INVALID_DATA; + } + if (!data.ReadBool(abilitySessionInfo->reuseDelegatorWindow)) { + TLOGE(WmsLogTag::WMS_LIFE, "Read reuseDelegatorWindow failed."); + return ERR_INVALID_DATA; + } + return ERR_NONE; +} + /** @note @window.layout */ int SessionStub::HandleUpdateSessionRect(MessageParcel& data, MessageParcel& reply) {