From 7b2bad959004e08a2efc2dd9cfdc784795006288 Mon Sep 17 00:00:00 2001 From: huojia Date: Fri, 25 Oct 2024 17:10:07 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AA=97=E5=8F=A3=E4=BE=A7=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E6=8B=89=E8=B5=B7=E6=A0=A1=E9=AA=8C=E5=8A=A0=E5=9B=BA=E6=96=B9?= =?UTF-8?q?=E6=A1=88=20Signed-off-by:=20huojia=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- window_scene/interfaces/include/ws_common.h | 3 + .../js_scene_session.cpp | 65 +++++++++++++--- .../scene_session_manager/js_scene_session.h | 2 + .../session/host/include/scene_session.h | 2 + window_scene/session/host/include/session.h | 5 +- .../session/host/src/scene_session.cpp | 74 ++++++++++++------- window_scene/session/host/src/session.cpp | 13 ++++ 7 files changed, 127 insertions(+), 37 deletions(-) diff --git a/window_scene/interfaces/include/ws_common.h b/window_scene/interfaces/include/ws_common.h index 0e7765b9d2..44b129fcb1 100644 --- a/window_scene/interfaces/include/ws_common.h +++ b/window_scene/interfaces/include/ws_common.h @@ -344,6 +344,9 @@ struct SessionInfo { bool isAtomicService_ = false; bool isBackTransition_ = false; bool needClearInNotShowRecent_ = false; + bool isPcOrPadEnableActivation_ = false; + bool canStartAbilityFromBackground_ = false; + bool isFoundationCall_ = false; /* * UIExtension 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 eb5323bd82..b360cfc049 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 @@ -354,6 +354,8 @@ void JsSceneSession::BindNativeMethod(napi_env env, napi_value objValue, const c JsSceneSession::SetStartingWindowExitAnimationFlag); BindNativeFunction(env, objValue, "setWindowEnableDragBySystem", moduleName, JsSceneSession::SetWindowEnableDragBySystem); + BindNativeFunction(env, objValue, "setIsPendingToBackgroundState", moduleName, + JsSceneSession::SetIsPendingToBackgroundState); } void JsSceneSession::BindNativeMethodForKeyboard(napi_env env, napi_value objValue, const char* moduleName) @@ -2029,6 +2031,13 @@ napi_value JsSceneSession::SetWindowEnableDragBySystem(napi_env env, napi_callba return (me != nullptr) ? me->OnSetWindowEnableDragBySystem(env, info) : nullptr; } +napi_value JsSceneSession::SetIsPendingToBackgroundState(napi_env env, napi_callback_info info) +{ + TLOGD(WmsLogTag::WMS_SCB, "[NAPI]"); + JsSceneSession* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnSetIsPendingToBackgroundState(env, info) : nullptr; +} + bool JsSceneSession::IsCallbackRegistered(napi_env env, const std::string& type, napi_value jsListenerObject) { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsSceneSession::IsCallbackRegistered[%s]", type.c_str()); @@ -3193,31 +3202,41 @@ void JsSceneSession::PendingSessionActivation(SessionInfo& info) void JsSceneSession::PendingSessionActivationInner(std::shared_ptr sessionInfo) { - auto task = [weakThis = wptr(this), persistentId = persistentId_, sessionInfo, env_ref = env_] { + auto task = [weakThis = wptr(this), persistentId = persistentId_, weakSession = weakSession_, + sessionInfo, env = env_] { + auto session = weakSession.promote(); + if (session == nullptr) { + TLOGNE(WmsLogTag::WMS_LIFE, "[NAPI]session is nullptr"); + return; + } + if (session->DisallowActivationFromPendingBackground(sessionInfo->isPcOrPadEnableActivation_, + sessionInfo->isFoundationCall_, sessionInfo->canStartAbilityFromBackground_)) { + return; + } auto jsSceneSession = weakThis.promote(); if (!jsSceneSession || jsSceneSessionMap_.find(persistentId) == jsSceneSessionMap_.end()) { - TLOGE(WmsLogTag::WMS_LIFE, "PendingSessionActivationInner jsSceneSession id:%{public}d has been destroyed", - persistentId); + TLOGNE(WmsLogTag::WMS_LIFE, "PendingSessionActivationInner jsSceneSession " + "id:%{public}d has been destroyed", persistentId); return; } auto jsCallBack = jsSceneSession->GetJSCallback(PENDING_SCENE_CB); if (!jsCallBack) { - TLOGE(WmsLogTag::WMS_LIFE, "[NAPI]jsCallBack is nullptr"); + TLOGNE(WmsLogTag::WMS_LIFE, "[NAPI]jsCallBack is nullptr"); return; } if (sessionInfo == nullptr) { - TLOGE(WmsLogTag::WMS_LIFE, "[NAPI]sessionInfo is nullptr"); + TLOGNE(WmsLogTag::WMS_LIFE, "[NAPI]sessionInfo is nullptr"); return; } - napi_value jsSessionInfo = CreateJsSessionInfo(env_ref, *sessionInfo); + napi_value jsSessionInfo = CreateJsSessionInfo(env, *sessionInfo); if (jsSessionInfo == nullptr) { - TLOGE(WmsLogTag::WMS_LIFE, "[NAPI]target session info is nullptr"); + TLOGNE(WmsLogTag::WMS_LIFE, "[NAPI]target session info is nullptr"); return; } napi_value argv[] = {jsSessionInfo}; - TLOGI(WmsLogTag::WMS_LIFE, "[NAPI]PendingSessionActivationInner task success, id:%{public}d", + TLOGNI(WmsLogTag::WMS_LIFE, "[NAPI]PendingSessionActivationInner task success, id:%{public}d", sessionInfo->persistentId_); - napi_call_function(env_ref, NapiGetUndefined(env_ref), + napi_call_function(env, NapiGetUndefined(env), jsCallBack->GetNapiValue(), ArraySize(argv), argv, nullptr); }; taskScheduler_->PostMainThreadTask(task, "PendingSessionActivationInner"); @@ -4904,4 +4923,32 @@ napi_value JsSceneSession::OnUnSyncScenePanelGlobalPosition(napi_env env, napi_c return NapiGetUndefined(env); } +napi_value JsSceneSession::OnSetIsPendingToBackgroundState(napi_env env, napi_callback_info info) +{ + auto session = weakSession_.promote(); + if (session == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "[NAPI]session is null, id: %{public}d", persistentId_); + return NapiGetUndefined(env); + } + size_t argc = ARGC_FOUR; + napi_value argv[ARGC_FOUR] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc != ARGC_ONE) { + TLOGE(WmsLogTag::WMS_LIFE, "[NAPI]Argc is invalid: %{public}zu", argc); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), "InputInvalid")); + return NapiGetUndefined(env); + } + bool isPendingToBackgroundState = false; + if (GetType(env, argv[0]) == napi_boolean) { + if (!ConvertFromJsValue(env, argv[0], isPendingToBackgroundState)) { + TLOGE(WmsLogTag::WMS_LIFE, "[NAPI]Failed to convert parameter to isPendingToBackgroundState"); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return NapiGetUndefined(env); + } + TLOGD(WmsLogTag::WMS_LIFE, "[NAPI]isPendingToBackgroundState: %{public}u", isPendingToBackgroundState); + } + session->SetIsPendingToBackgroundState(isPendingToBackgroundState); + return NapiGetUndefined(env); +} } // namespace OHOS::Rosen 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 4bd4040202..0cda5a7a30 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 @@ -149,6 +149,7 @@ private: static napi_value CompatibleFullScreenMinimize(napi_env env, napi_callback_info info); static napi_value CompatibleFullScreenClose(napi_env env, napi_callback_info info); static napi_value SetWindowEnableDragBySystem(napi_env env, napi_callback_info info); + static napi_value SetIsPendingToBackgroundState(napi_env env, napi_callback_info info); napi_value OnRegisterCallback(napi_env env, napi_callback_info info); napi_value OnUpdateNativeVisibility(napi_env env, napi_callback_info info); @@ -202,6 +203,7 @@ private: napi_value OnSyncScenePanelGlobalPosition(napi_env env, napi_callback_info info); napi_value OnUnSyncScenePanelGlobalPosition(napi_env env, napi_callback_info info); napi_value OnSetWindowEnableDragBySystem(napi_env env, napi_callback_info info); + napi_value OnSetIsPendingToBackgroundState(napi_env env, napi_callback_info info); bool IsCallbackRegistered(napi_env env, const std::string& type, napi_value jsListenerObject); void ProcessChangeSessionVisibilityWithStatusBarRegister(); diff --git a/window_scene/session/host/include/scene_session.h b/window_scene/session/host/include/scene_session.h index 6b9439b587..666a8cefce 100644 --- a/window_scene/session/host/include/scene_session.h +++ b/window_scene/session/host/include/scene_session.h @@ -198,6 +198,8 @@ public: WSError UpdateClientRect(const WSRect& rect) override; WSError ChangeSessionVisibilityWithStatusBar(const sptr info, bool visible) override; WSError PendingSessionActivation(const sptr info) override; + bool DisallowActivationFromPendingBackground(bool isPcOrPadEnableActivation, bool isFoundationCall, + bool canStartAbilityFromBackground); WSError TerminateSession(const sptr info) override; WSError NotifySessionException( const sptr info, bool needRemoveSession = false) override; diff --git a/window_scene/session/host/include/session.h b/window_scene/session/host/include/session.h index cddfe2638a..3fccf32f24 100644 --- a/window_scene/session/host/include/session.h +++ b/window_scene/session/host/include/session.h @@ -469,6 +469,8 @@ public: // ForegroundInteractiveStatus interface only for event use bool GetForegroundInteractiveStatus() const; virtual void SetForegroundInteractiveStatus(bool interactive); + bool GetIsPendingToBackgroundState() const; + void SetIsPendingToBackgroundState(bool isPendingToBackgroundState); void SetAttachState(bool isAttach, WindowMode windowMode = WindowMode::WINDOW_MODE_UNDEFINED); bool GetAttachState() const; void RegisterDetachCallback(const sptr& callback); @@ -745,7 +747,8 @@ private: bool systemTouchable_ { true }; std::atomic rectChangeBySystem_ { false }; std::atomic_bool foregroundInteractiveStatus_ { true }; - std::atomic isAttach_{ false }; + std::atomic isAttach_ { false }; + std::atomic isPendingToBackgroundState_ { false }; sptr detachCallback_ = nullptr; std::shared_ptr leashWinSurfaceNode_; diff --git a/window_scene/session/host/src/scene_session.cpp b/window_scene/session/host/src/scene_session.cpp index 393f556e05..3a478210d1 100644 --- a/window_scene/session/host/src/scene_session.cpp +++ b/window_scene/session/host/src/scene_session.cpp @@ -3294,7 +3294,7 @@ WSError SceneSession::ChangeSessionVisibilityWithStatusBar( } static SessionInfo MakeSessionInfoDuringPendingActivation(const sptr& abilitySessionInfo, - const sptr& session) + const sptr& session, bool isFoundationCall) { SessionInfo info; info.abilityName_ = abilitySessionInfo->want.GetElement().GetAbilityName(); @@ -3320,6 +3320,9 @@ static SessionInfo MakeSessionInfoDuringPendingActivation(const sptrneedClearInNotShowRecent; info.appInstanceKey_ = abilitySessionInfo->instanceKey; info.isFromIcon_ = abilitySessionInfo->isFromIcon; + info.isPcOrPadEnableActivation_ = session->IsPcOrPadEnableActivation(); + info.canStartAbilityFromBackground_ = abilitySessionInfo->canStartAbilityFromBackground; + info.isFoundationCall_ = isFoundationCall; if (session->IsPcOrPadEnableActivation()) { info.startWindowOption = abilitySessionInfo->startWindowOption; } @@ -3332,15 +3335,13 @@ static SessionInfo MakeSessionInfoDuringPendingActivation(const sptr(WindowMode::WINDOW_MODE_FULLSCREEN)) { info.fullScreenStart_ = true; } - TLOGI(WmsLogTag::WMS_LIFE, "bundleName:%{public}s, moduleName:%{public}s, " - "abilityName:%{public}s, appIndex:%{public}d, affinity:%{public}s. " - "callState:%{public}d, want persistentId:%{public}d, " + TLOGI(WmsLogTag::WMS_LIFE, "bundleName:%{public}s, moduleName:%{public}s, abilityName:%{public}s, " + "appIndex:%{public}d, affinity:%{public}s. callState:%{public}d, want persistentId:%{public}d, " "uiAbilityId:%{public}" PRIu64 ", windowMode:%{public}d, callerId:%{public}d " "needClearInNotShowRecent:%{public}u, appInstanceKey: %{public}s, isFromIcon:%{public}d", info.bundleName_.c_str(), info.moduleName_.c_str(), info.abilityName_.c_str(), info.appIndex_, - info.sessionAffinity.c_str(), info.callState_, info.persistentId_, info.uiAbilityId_, - info.windowMode, info.callerPersistentId_, info.needClearInNotShowRecent_, info.appInstanceKey_.c_str(), - info.isFromIcon_); + info.sessionAffinity.c_str(), info.callState_, info.persistentId_, info.uiAbilityId_, info.windowMode, + info.callerPersistentId_, info.needClearInNotShowRecent_, info.appInstanceKey_.c_str(), info.isFromIcon_); return info; } @@ -3354,36 +3355,23 @@ WSError SceneSession::PendingSessionActivation(const sptr ab auto task = [weakThis = wptr(this), abilitySessionInfo, isFoundationCall]() { auto session = weakThis.promote(); if (!session) { - TLOGE(WmsLogTag::WMS_LIFE, "session is null"); + TLOGNE(WmsLogTag::WMS_LIFE, "session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (abilitySessionInfo == nullptr) { - TLOGE(WmsLogTag::WMS_LIFE, "abilitySessionInfo is null"); + TLOGNE(WmsLogTag::WMS_LIFE, "abilitySessionInfo is null"); return WSError::WS_ERROR_NULLPTR; } - if (!session->IsPcOrPadEnableActivation() && WindowHelper::IsMainWindow(session->GetWindowType())) { - SessionState sessionState = session->GetSessionState(); - TLOGI(WmsLogTag::WMS_LIFE, "sceneSession state:%{public}d, isFoundationCall:%{public}u, " - "canStartAbilityFromBackground:%{public}u, foregroundInteractiveStatus:%{public}u", - sessionState, isFoundationCall, abilitySessionInfo->canStartAbilityFromBackground, - session->GetForegroundInteractiveStatus()); - bool isSessionForeground = sessionState == SessionState::STATE_FOREGROUND || - sessionState == SessionState::STATE_ACTIVE; - if (isSessionForeground && !session->GetForegroundInteractiveStatus()) { - TLOGW(WmsLogTag::WMS_LIFE, "start ability invalid, sceneSession in a non interactive state"); - return WSError::WS_ERROR_INVALID_OPERATION; - } - if (!isSessionForeground && !(isFoundationCall && abilitySessionInfo->canStartAbilityFromBackground)) { - TLOGW(WmsLogTag::WMS_LIFE, "no permission to start ability from Background"); - return WSError::WS_ERROR_INVALID_OPERATION; - } + if (session->DisallowActivationFromPendingBackground(session->IsPcOrPadEnableActivation(), isFoundationCall, + abilitySessionInfo->canStartAbilityFromBackground)) { + return WSError::WS_ERROR_INVALID_OPERATION; } session->sessionInfo_.startMethod = StartMethod::START_CALL; - SessionInfo info = MakeSessionInfoDuringPendingActivation(abilitySessionInfo, session); + SessionInfo info = MakeSessionInfoDuringPendingActivation(abilitySessionInfo, session, isFoundationCall); if (MultiInstanceManager::IsSupportMultiInstance(session->systemConfig_) && MultiInstanceManager::GetInstance().IsMultiInstance(session->GetSessionInfo().bundleName_)) { if (!MultiInstanceManager::GetInstance().MultiInstancePendingSessionActivation(info)) { - TLOGE(WmsLogTag::WMS_LIFE, "multi instance start fail, id:%{public}d instanceKey:%{public}s", + TLOGNE(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; } @@ -3398,6 +3386,38 @@ WSError SceneSession::PendingSessionActivation(const sptr ab return WSError::WS_OK; } +bool SceneSession::DisallowActivationFromPendingBackground(bool isPcOrPadEnableActivation, bool isFoundationCall, + bool canStartAbilityFromBackground) +{ + if (isPcOrPadEnableActivation || !WindowHelper::IsMainWindow(GetWindowType())) { + return false; + } + bool isPendingToBackgroundState = GetIsPendingToBackgroundState(); + bool foregroundInteractiveStatus = GetForegroundInteractiveStatus(); + TLOGI(WmsLogTag::WMS_LIFE, "session state:%{public}d, isFoundationCall:%{public}u, " + "canStartAbilityFromBackground:%{public}u, foregroundInteractiveStatus:%{public}u, " + "isPendingToBackgroundState:%{public}u", + GetSessionState(), isFoundationCall, canStartAbilityFromBackground, foregroundInteractiveStatus, + isPendingToBackgroundState); + bool isSessionForeground = GetSessionState() == SessionState::STATE_FOREGROUND || + GetSessionState() == SessionState::STATE_ACTIVE; + if (isSessionForeground) { + if (isPendingToBackgroundState) { + if (!(isFoundationCall && canStartAbilityFromBackground)) { + TLOGW(WmsLogTag::WMS_LIFE, "no permission to start ability from PendingBackground"); + return true; + } + } else if (!foregroundInteractiveStatus) { + TLOGW(WmsLogTag::WMS_LIFE, "start ability invalid, session in a non interactive state"); + return true; + } + } else if (!(isFoundationCall && canStartAbilityFromBackground)) { + TLOGW(WmsLogTag::WMS_LIFE, "no permission to start ability from Background"); + return true; + } + return false; +} + void SceneSession::HandleCastScreenConnection(SessionInfo& info, sptr session) { ScreenId defScreenId = ScreenSessionManagerClient::GetInstance().GetDefaultScreenId(); diff --git a/window_scene/session/host/src/session.cpp b/window_scene/session/host/src/session.cpp index a70f3b9e87..aca0960e7c 100644 --- a/window_scene/session/host/src/session.cpp +++ b/window_scene/session/host/src/session.cpp @@ -1212,6 +1212,7 @@ WSError Session::Background(bool isFromClient, const std::string& identityToken) return WSError::WS_ERROR_INVALID_SESSION; } UpdateSessionState(SessionState::STATE_BACKGROUND); + SetIsPendingToBackgroundState(false); NotifyBackground(); return WSError::WS_OK; } @@ -1346,6 +1347,18 @@ bool Session::GetForegroundInteractiveStatus() const return foregroundInteractiveStatus_.load(); } +bool Session::GetIsPendingToBackgroundState() const +{ + return isPendingToBackgroundState_.load(); +} + +void Session::SetIsPendingToBackgroundState(bool isPendingToBackgroundState) +{ + TLOGI(WmsLogTag::WMS_LIFE, "id:%{public}d isPendingToBackgroundState:%{public}d", + GetPersistentId(), isPendingToBackgroundState); + return isPendingToBackgroundState_.store(isPendingToBackgroundState); +} + void Session::SetAttachState(bool isAttach, WindowMode windowMode) { isAttach_ = isAttach; -- Gitee