diff --git a/interfaces/innerkits/wm/window_manager.h b/interfaces/innerkits/wm/window_manager.h index 9b3bc300e470f7821ce71879fd24828cbc26d822..d12bd0400a655ea6dc02118b5ca2c6e714281bd8 100644 --- a/interfaces/innerkits/wm/window_manager.h +++ b/interfaces/innerkits/wm/window_manager.h @@ -28,6 +28,7 @@ #include "window_visibility_info.h" #include "window_drawing_content_info.h" #include "window.h" +#include "window_pid_visibility_info.h" namespace OHOS { namespace Rosen { @@ -191,6 +192,21 @@ public: virtual void OnWindowStyleUpdate(WindowStyleType styleType) = 0; }; +/** + * @class IWindowPidVisibilityChangedListener + * + * @brief Listener to observe window visibility that in same pid. + */ +class IWindowPidVisibilityChangedListener : virtual public RefBase { +public: + /** + * @brief Notify caller when window style changed. + * + * @param info + */ + virtual void NotifyWindowPidVisibilityChanged(const sptr& info) = 0; +}; + /** * @class AccessibilityWindowInfo * @@ -562,6 +578,24 @@ public: */ WMError UnregisterDisplayInfoChangedListener(const sptr& token, const sptr& listener); + + /** + * @brief Register window in same pid visibility changed listener. + * @caller SA + * @permission SA permission + * + * @param listener IWindowPidVisibilityChangedListener. + * @return WM_OK means register success, others means register failed. + */ + WMError RegisterWindowPidVisibilityChangedListener(const sptr& listener); + + /** + * @brief Unregister window in same pid visibility changed listener. + * + * @param listener IWindowPidVisibilityChangedListener. + * @return WM_OK means unregister success, others means unregister failed. + */ + WMError UnregisterWindowPidVisibilityChangedListener(const sptr& listener); /** * @brief notify display information change. @@ -758,6 +792,7 @@ private: void NotifyGestureNavigationEnabledResult(bool enable) const; void UpdateVisibleWindowNum(const std::vector& visibleWindowNumInfo); WMError NotifyWindowStyleChange(WindowStyleType type); + void NotifyWindowPidVisibilityChanged(const sptr& info) const; }; } // namespace Rosen } // namespace OHOS diff --git a/utils/BUILD.gn b/utils/BUILD.gn index d4ca3c982120891ebf09f9cb20c0ccce39f16878..4b32673e9ca75aca8f8c3f1f51b8a63e23bbf6ed 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -126,6 +126,7 @@ ohos_shared_library("libwmutil_base") { "src/string_util.cpp", "src/unreliable_window_info.cpp", "src/window_drawing_content_info.cpp", + "src/window_pid_visibility_info.cpp", "src/window_visibility_info.cpp", "src/wm_math.cpp", "src/wm_occlusion_region.cpp", diff --git a/utils/include/window_pid_visibility_info.h b/utils/include/window_pid_visibility_info.h new file mode 100644 index 0000000000000000000000000000000000000000..cad12b54591a789cdfac7f0901fde89d2173d984 --- /dev/null +++ b/utils/include/window_pid_visibility_info.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ROSEN_WINDOW_PID_VISIBILITY_INFO_H +#define OHOS_ROSEN_WINDOW_PID_VISIBILITY_INFO_H + +#include "wm_common.h" + +namespace OHOS::Rosen { +/** + * @enum WindowVisibilityState + * + * @brief Visibility state of a window + */ +enum WindowPidVisibilityState : uint32_t { + VISIBILITY_STATE, + INVISIBILITY_STATE, +}; + +class WindowPidVisibilityInfo : public Parcelable { +public: + WindowPidVisibilityInfo() = default; + /** + * @brief Construct of WindowPidVisibilityInfo. + * + * @param pid Process id. + * @param visibility True means window is visible, false means the opposite. + */ + WindowPidVisibilityInfo(int32_t pid, WindowPidVisibilityState visibilityState) : pid_(pid), + visibilityState_(visibilityState) {}; + + ~WindowPidVisibilityInfo() = default; + + virtual bool Marshalling(Parcel& parcel) const override; + + static WindowPidVisibilityInfo* Unmarshalling(Parcel& parcel); + + int32_t pid_ { 0 }; + WindowPidVisibilityState visibilityState_ = INVISIBILITY_STATE; +}; +} // namespace OHOS::Rosen +#endif // OHOS_ROSEN_WINDOW_PID_VISIBILITY_INFO_H \ No newline at end of file diff --git a/utils/src/window_pid_visibility_info.cpp b/utils/src/window_pid_visibility_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a754d19d29a4214bf4bc22be4afbe6d667277a9e --- /dev/null +++ b/utils/src/window_pid_visibility_info.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "window_pid_visibility_info.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { + +bool WindowPidVisibilityInfo::Marshalling(Parcel& parcel) const +{ + return parcel.WriteInt32(pid_) && parcel.WriteUint32(static_cast(visibilityState_)); +} + +WindowPidVisibilityInfo* WindowPidVisibilityInfo::Unmarshalling(Parcel& parcel) +{ + auto windowPidVisibilityInfo = new (std::nothrow) WindowPidVisibilityInfo(); + if (windowPidVisibilityInfo == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "window pid visibility info is nullptr."); + return nullptr; + } + + uint32_t visibilityState = 0; + bool res = parcel.ReadInt32(windowPidVisibilityInfo->pid_) && parcel.ReadUint32(visibilityState); + if (!res) { + return nullptr; + } + windowPidVisibilityInfo->visibilityState_ = static_cast(visibilityState); + return windowPidVisibilityInfo; +} +} // namespace OHOS::Rosen diff --git a/window_scene/session/host/include/scene_session.h b/window_scene/session/host/include/scene_session.h index b13e5cdae37e6f993bd5ad5e6d542c0d6e3d3a4e..eed8d1cf32e56be0718d368a7fbb350227b68568 100644 --- a/window_scene/session/host/include/scene_session.h +++ b/window_scene/session/host/include/scene_session.h @@ -270,7 +270,6 @@ public: bool IsRecovered() const { return isRecovered_; } void SetRecovered(bool isRecovered) { isRecovered_ = isRecovered; } - bool IsVisible() const; bool IsDecorEnable() const; bool IsAppSession() const; bool IsTurnScreenOn() const; @@ -393,6 +392,7 @@ public: void SetMinimizedFlagByUserSwitch(bool isMinimized); bool IsMinimizedByUserSwitch() const; void UnregisterSessionChangeListeners() override; + void SetVisibilityChangedDetectFunc(const VisibilityChangedDetectFunc& func); void SetPcScenePanel(bool isPcScenePanel) { isPcScenePanel_ = isPcScenePanel; } protected: diff --git a/window_scene/session/host/include/session.h b/window_scene/session/host/include/session.h index b74722ca253ee2489c6568b1cb9b8eb5bb85f244..e8e9825953a9919dd62b3b557ef722160fe74d43 100644 --- a/window_scene/session/host/include/session.h +++ b/window_scene/session/host/include/session.h @@ -81,6 +81,8 @@ using NotifySystemSessionKeyEventFunc = std::function; using NotifyContextTransparentFunc = std::function; using NotifyFrameLayoutFinishFunc = std::function; +using VisibilityChangedDetectFunc = std::function; class ILifecycleListener { public: @@ -451,6 +453,7 @@ public: bool GetUIStateDirty() const; void ResetDirtyFlags(); static bool IsScbCoreEnabled(); + bool IsVisible() const; protected: class SessionLifeCycleTask : public virtual RefBase { @@ -556,6 +559,8 @@ protected: NotifySystemSessionKeyEventFunc systemSessionKeyEventFunc_; NotifyContextTransparentFunc contextTransparentFunc_; NotifyFrameLayoutFinishFunc frameLayoutFinishFunc_; + VisibilityChangedDetectFunc visibilityChangedDetectFunc_; + SystemSessionConfig systemConfig_; bool needSnapshot_ = false; float snapshotScale_ = 0.5; diff --git a/window_scene/session/host/src/scene_session.cpp b/window_scene/session/host/src/scene_session.cpp index 1ef2815a085fde91013a6c225d21ff2b413382a4..35be4eb0eeddb614a17cf9e8daaa614e1b3940e5 100644 --- a/window_scene/session/host/src/scene_session.cpp +++ b/window_scene/session/host/src/scene_session.cpp @@ -2345,6 +2345,9 @@ void SceneSession::UpdateNativeVisibility(bool visible) int32_t persistentId = session->GetPersistentId(); WLOGFI("[WMSSCB] name: %{public}s, id: %{public}u, visible: %{public}u", session->sessionInfo_.bundleName_.c_str(), persistentId, visible); + if (session->visibilityChangedDetectFunc_) { + session->visibilityChangedDetectFunc_(session->GetCallingPid(), session->isVisible_, visible); + } session->isVisible_ = visible; if (session->specificCallback_ == nullptr) { WLOGFW("specific callback is null."); @@ -2370,11 +2373,6 @@ void SceneSession::UpdateNativeVisibility(bool visible) PostTask(task, "UpdateNativeVisibility"); } -bool SceneSession::IsVisible() const -{ - return isVisible_; -} - void SceneSession::UpdateRotationAvoidArea() { if (specificCallback_) { @@ -4284,6 +4282,9 @@ bool SceneSession::UpdateVisibilityInner(bool visibility) if (isVisible_ == visibility) { return false; } + if (visibilityChangedDetectFunc_) { + visibilityChangedDetectFunc_(GetCallingPid(), isVisible_, visibility); + } isVisible_ = visibility; return true; } @@ -4480,4 +4481,9 @@ void SceneSession::UnregisterSessionChangeListeners() }; PostTask(task, "UnregisterSessionChangeListeners"); } + +void SceneSession::SetVisibilityChangedDetectFunc(const VisibilityChangedDetectFunc& func) +{ + visibilityChangedDetectFunc_ = func; +} } // namespace OHOS::Rosen diff --git a/window_scene/session/host/src/session.cpp b/window_scene/session/host/src/session.cpp index 0d79273f3e111802daebed94bc472da64e3bd3cb..1255e7e8c3f49fb8d786259477ba00ed24806217 100644 --- a/window_scene/session/host/src/session.cpp +++ b/window_scene/session/host/src/session.cpp @@ -629,6 +629,9 @@ void Session::SetCallingPid(int32_t id) { TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d, callingPid:%{public}u", persistentId_, id); callingPid_ = id; + if (isVisible_) { + visibilityChangedDetectFunc_(callingPid_, false, isVisible_); + } } void Session::SetCallingUid(int32_t id) @@ -903,7 +906,7 @@ __attribute__((no_sanitize("cfi"))) WSError Session::ConnectInner(const sptr& sessionStage, const sptrGetPersistentId(); - callingPid_ = pid; + SetCallingPid(pid); callingUid_ = uid; bufferAvailable_ = true; auto windowRect = property->GetWindowRect(); @@ -1127,6 +1130,9 @@ WSError Session::Disconnect(bool isFromClient) UpdateSessionState(SessionState::STATE_BACKGROUND); UpdateSessionState(SessionState::STATE_DISCONNECT); NotifyDisconnect(); + if (visibilityChangedDetectFunc_) { + visibilityChangedDetectFunc_(GetCallingPid(), isVisible_, false); + } DelayedSingleton::GetInstance()->OnSessionLost(persistentId_); return WSError::WS_OK; } @@ -3151,4 +3157,9 @@ bool Session::IsScbCoreEnabled() { return system::GetParameter("persist.window.scbcore.enable", "1") == "1"; } + +bool Session::IsVisible() const +{ + return isVisible_; +} } // namespace OHOS::Rosen diff --git a/window_scene/session_manager/include/scene_session_manager.h b/window_scene/session_manager/include/scene_session_manager.h index ddbfa63b59e74613e886fa6b2ec99e986bcfe912..35f064c9be63d56bb6cd3452d3ee65df1980662f 100644 --- a/window_scene/session_manager/include/scene_session_manager.h +++ b/window_scene/session_manager/include/scene_session_manager.h @@ -531,6 +531,7 @@ private: void WindowDestroyNotifyVisibility(const sptr& sceneSession); void RegisterSessionExceptionFunc(const sptr& sceneSession); void RegisterSessionSnapshotFunc(const sptr& sceneSession); + void RegisterVisibilityChangedDetectFunc(const sptr& sceneSession); void NotifySessionForCallback(const sptr& scnSession, const bool needRemoveSession); void DumpSessionInfo(const sptr& session, std::ostringstream& oss); void DumpSessionElementInfo(const sptr& session, @@ -572,6 +573,8 @@ private: std::map> sceneSessionMap_; std::map> systemTopSceneSessionMap_; std::map> nonSystemFloatSceneSessionMap_; + std::mutex visibleWindowCountMapMutex_; + std::map visibleWindowCountMap_; sptr scbSessionHandler_; std::shared_ptr listenerController_; std::map, int32_t> remoteObjectMap_; @@ -755,6 +758,7 @@ private: WMError MakeScreenFoldData(const std::vector& screenFoldInfo, ScreenFoldData& screenFoldData); WMError CheckAndReportScreenFoldStatus(ScreenFoldData& data); WMError ReportScreenFoldStatus(const ScreenFoldData& data); + void RecoveryVisibilityPidCount(int32_t pid); RunnableFuture> dumpInfoFuture_; diff --git a/window_scene/session_manager/include/session_manager_agent_controller.h b/window_scene/session_manager/include/session_manager_agent_controller.h index a828060a83ee027718947c1b1f7168afcee929c0..cd48d4b7bb9832e778a56c18c1b481d16e42136b 100644 --- a/window_scene/session_manager/include/session_manager_agent_controller.h +++ b/window_scene/session_manager/include/session_manager_agent_controller.h @@ -23,6 +23,7 @@ #include "zidl/window_manager_agent_interface.h" #include "window_visibility_info.h" #include "window_drawing_content_info.h" +#include "window_pid_visibility_info.h" namespace OHOS { namespace Rosen { @@ -46,6 +47,7 @@ public: void UpdateCameraWindowStatus(uint32_t accessTokenId, bool isShowing); void NotifyGestureNavigationEnabledResult(bool enable); void NotifyWindowStyleChange(WindowStyleType type); + void NotifyWindowPidVisibilityChanged(const sptr& info); private: SessionManagerAgentController() diff --git a/window_scene/session_manager/src/scene_session_manager.cpp b/window_scene/session_manager/src/scene_session_manager.cpp index fa3e1b523470ccbf5af945dd77aa12cdbc438bd7..1b069460974f94f4214c1cfd9f07c32f066d8b85 100644 --- a/window_scene/session_manager/src/scene_session_manager.cpp +++ b/window_scene/session_manager/src/scene_session_manager.cpp @@ -64,6 +64,7 @@ #include "res_type.h" #include "anomaly_detection.h" #include "hidump_controller.h" +#include "window_pid_visibility_info.h" #ifdef MEMMGR_WINDOW_ENABLE #include "mem_mgr_client.h" @@ -1538,6 +1539,7 @@ void SceneSessionManager::InitSceneSession(sptr& sceneSession, con sessionInfo.want == nullptr ? "nullptr" : sessionInfo.want->ToString().c_str()); } RegisterSessionExceptionFunc(sceneSession); + RegisterVisibilityChangedDetectFunc(sceneSession); // Skip FillSessionInfo when atomicService free-install start. if (!IsAtomicServiceFreeInstall(sessionInfo)) { FillSessionInfo(sceneSession); @@ -3792,6 +3794,59 @@ void SceneSessionManager::RegisterSessionExceptionFunc(const sptr& TLOGD(WmsLogTag::WMS_LIFE, "success, id: %{public}d", sceneSession->GetPersistentId()); } +void SceneSessionManager::RegisterVisibilityChangedDetectFunc(const sptr& sceneSession) +{ + if (sceneSession == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "session is nullptr"); + return; + } + VisibilityChangedDetectFunc func = [this](const int32_t pid, const bool isVisible, const bool newIsVisible) { + if (isVisible == newIsVisible || pid == -1) { + return; + } + sptr windowPidVisibilityInfo = sptr::MakeSptr(); + windowPidVisibilityInfo->pid_ = pid; + int32_t count = 0; + int32_t beforeCount = 0; + { + std::unique_lock lock(visibleWindowCountMapMutex_); + if (visibleWindowCountMap_.find(pid) != visibleWindowCountMap_.end()) { + beforeCount = visibleWindowCountMap_[pid]; + } else { + visibleWindowCountMap_[pid] = 0; + } + visibleWindowCountMap_[pid] = newIsVisible ? visibleWindowCountMap_[pid] + 1 : + visibleWindowCountMap_[pid] - 1; + count = visibleWindowCountMap_[pid]; + } + if (beforeCount > 0 && count == 0) { + TLOGI(WmsLogTag::WMS_LIFE, "The windows of pid %{public}d change to invisibility.", pid); + windowPidVisibilityInfo->visibilityState_ = WindowPidVisibilityState::INVISIBILITY_STATE; + SessionManagerAgentController::GetInstance().NotifyWindowPidVisibilityChanged(windowPidVisibilityInfo); + } else if (beforeCount == 0 && count == 1) { + TLOGI(WmsLogTag::WMS_LIFE, "The windows of pid %{public}d change to visibility.", pid); + windowPidVisibilityInfo->visibilityState_ = WindowPidVisibilityState::VISIBILITY_STATE; + SessionManagerAgentController::GetInstance().NotifyWindowPidVisibilityChanged(windowPidVisibilityInfo); + } else if (count < 0) { + TLOGE(WmsLogTag::WMS_LIFE, "The count of visible windows in same pid:%{public}d is less than 0.", pid); + RecoveryVisibilityPidCount(pid); + } + }; + sceneSession->SetVisibilityChangedDetectFunc(func); +} + +void SceneSessionManager::RecoveryVisibilityPidCount(int32_t pid) +{ + std::shared_lock lock(sceneSessionMapMutex_); + visibleWindowCountMap_[pid] = 0; + for (const auto& iter : sceneSessionMap_) { + auto& session = iter.second; + if (session && session->GetCallingPid() == pid && session->IsVisible()) { + visibleWindowCountMap_[pid]++; + } + } +} + void SceneSessionManager::RegisterSessionSnapshotFunc(const sptr& sceneSession) { if (sceneSession == nullptr) { @@ -6619,7 +6674,8 @@ WMError SceneSessionManager::RegisterWindowManagerAgent(WindowManagerAgentType t type == WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_DRAWING_STATE || type == WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_VISIBLE_WINDOW_NUM || type == WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_FOCUS || - type == WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_MODE) { + type == WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_MODE || + type == WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_PID_VISIBILITY) { if (!SessionPermission::IsSACalling()) { TLOGE(WmsLogTag::WMS_LIFE, "permission denied!"); return WMError::WM_ERROR_INVALID_PERMISSION; diff --git a/window_scene/session_manager/src/session_manager_agent_controller.cpp b/window_scene/session_manager/src/session_manager_agent_controller.cpp index deca47a17a51ea93b33480d29e3c9e11add4f32f..e6a93c67d11ba5cf16bec95ba8b4f18dab14cafe 100644 --- a/window_scene/session_manager/src/session_manager_agent_controller.cpp +++ b/window_scene/session_manager/src/session_manager_agent_controller.cpp @@ -219,5 +219,16 @@ void SessionManagerAgentController::NotifyWindowStyleChange(WindowStyleType type } } +void SessionManagerAgentController::NotifyWindowPidVisibilityChanged( + const sptr& info) +{ + for (auto& agent : smAgentContainer_.GetAgentsByType( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_PID_VISIBILITY)) { + if (agent != nullptr) { + agent->NotifyWindowPidVisibilityChanged(info); + } + } +} + } // namespace Rosen } // namespace OHOS \ No newline at end of file diff --git a/window_scene/test/unittest/scene_session_manager_lifecycle_test.cpp b/window_scene/test/unittest/scene_session_manager_lifecycle_test.cpp index c297af0c242d0d459e42d272431d6f91ac8203de..ff9e272ff2bc9caf014fcc723eac5fdf3de448cf 100644 --- a/window_scene/test/unittest/scene_session_manager_lifecycle_test.cpp +++ b/window_scene/test/unittest/scene_session_manager_lifecycle_test.cpp @@ -874,6 +874,52 @@ HWTEST_F(SceneSessionManagerLifecycleTest, ClearSession, Function | SmallTest | EXPECT_EQ(WSError::WS_ERROR_INVALID_SESSION, ssm_->ClearSession(nullptr)); EXPECT_EQ(WSError::WS_ERROR_INVALID_SESSION, ssm_->ClearSession(sceneSession)); } + +/** + * @tc.name: RegisterVisibilityChangedDetectFunc + * @tc.desc: RegisterVisibilityChangedDetectFunc + * @tc.type: FUNC +*/ +HWTEST_F(SceneSessionManagerLifecycleTest, RegisterVisibilityChangedDetectFunc, Function | SmallTest | Level3) +{ + ASSERT_NE(nullptr, ssm_); + SessionInfo info; + info.abilityName_ = "VisibilityChanged"; + sptr sceneSession = sptr::MakeSptr(info, nullptr); + ASSERT_NE(sceneSession, nullptr); + + ssm_->RegisterVisibilityChangedDetectFunc(nullptr); + + ssm_->RegisterVisibilityChangedDetectFunc(sceneSession); + EXPECT_NE(nullptr, sceneSession->visibilityChangedDetectFunc_); +} + +/** + * @tc.name: RecoveryVisibilityPidCount + * @tc.desc: RecoveryVisibilityPidCount + * @tc.type: FUNC +*/ +HWTEST_F(SceneSessionManagerLifecycleTest, RecoveryVisibilityPidCount, Function | SmallTest | Level3) +{ + ASSERT_NE(nullptr, ssm_); + int32_t pid = 10; + SessionInfo info; + info.abilityName_ = "VisibilityChanged"; + sptr sceneSession = sptr::MakeSptr(info, nullptr); + ASSERT_NE(sceneSession, nullptr); + ssm_->sceneSessionMap_.insert({1, sceneSession}); + sceneSession->SetCallingPid(pid); + + sptr sceneSession2 = sptr::MakeSptr(info, nullptr); + ASSERT_NE(sceneSession2, nullptr); + ssm_->sceneSessionMap_.insert({2, sceneSession2}); + + sceneSession2->SetCallingPid(pid); + sceneSession2->isVisible_ = true; + + ssm_->RecoveryVisibilityPidCount(pid); + EXPECT_EQ(1, ssm_->visibleWindowCountMap_[pid]); +} } } // namespace Rosen } // namespace OHOS diff --git a/wm/include/window_manager_agent.h b/wm/include/window_manager_agent.h index 682709520e2b4d36e1ec36acc047404972994dad..ac9643df9bd0f8a50498206bbbebb4c07698d7f2 100644 --- a/wm/include/window_manager_agent.h +++ b/wm/include/window_manager_agent.h @@ -40,6 +40,7 @@ public: void NotifyGestureNavigationEnabledResult(bool enable) override; void UpdateCameraWindowStatus(uint32_t accessTokenId, bool isShowing) override {}; void NotifyWindowStyleChange(WindowStyleType type) override; + void NotifyWindowPidVisibilityChanged(const sptr& info) override; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/include/window_manager_agent_lite.h b/wm/include/window_manager_agent_lite.h index bf0a916f0236a64e55cb3a7324e18e3a48fc9dd1..dbc95d9e1eb7c0a1ecca1a3ecff8cabcd0b6aa62 100644 --- a/wm/include/window_manager_agent_lite.h +++ b/wm/include/window_manager_agent_lite.h @@ -40,6 +40,7 @@ public: void NotifyGestureNavigationEnabledResult(bool enable) override {}; void UpdateCameraWindowStatus(uint32_t accessTokenId, bool isShowing) override; void NotifyWindowStyleChange(WindowStyleType type) override; + void NotifyWindowPidVisibilityChanged(const sptr& info) override {}; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/include/zidl/window_manager_agent_interface.h b/wm/include/zidl/window_manager_agent_interface.h index dc0df1ed97c79b5147959cd7cdc60178621bd47e..7fe302ce73f76395adb02abab3e1ee1fa6f420d8 100644 --- a/wm/include/zidl/window_manager_agent_interface.h +++ b/wm/include/zidl/window_manager_agent_interface.h @@ -35,6 +35,7 @@ enum class WindowManagerAgentType : uint32_t { WINDOW_MANAGER_AGENT_TYPE_CAMERA_WINDOW, WINDOW_MANAGER_AGENT_TYPE_WINDOW_MODE, WINDOW_MANAGER_AGENT_TYPE_WINDOW_STYLE, + WINDOW_MANAGER_AGENT_TYPE_WINDOW_PID_VISIBILITY, }; class IWindowManagerAgent : public IRemoteBroker { @@ -54,6 +55,7 @@ public: TRANS_ID_UPDATE_CAMERA_WINDOW_STATUS, TRANS_ID_UPDATE_WINDOW_MODE_TYPE, TRANS_ID_UPDATE_WINDOW_STYLE_TYPE, + TRANS_ID_NOTIFY_WINDOW_PID_VISIBILITY, }; virtual void UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) = 0; @@ -70,6 +72,7 @@ public: virtual void NotifyGestureNavigationEnabledResult(bool enable) = 0; virtual void UpdateCameraWindowStatus(uint32_t accessTokenId, bool isShowing) = 0; virtual void NotifyWindowStyleChange(WindowStyleType type) = 0; + virtual void NotifyWindowPidVisibilityChanged(const sptr& info) = 0; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/include/zidl/window_manager_agent_proxy.h b/wm/include/zidl/window_manager_agent_proxy.h index f89ddac8b19a6219e6b5180037c5240a075b6dde..071ffe8d4f0e5ed8e51ca737a392e33ead0e300d 100644 --- a/wm/include/zidl/window_manager_agent_proxy.h +++ b/wm/include/zidl/window_manager_agent_proxy.h @@ -41,6 +41,7 @@ public: void NotifyGestureNavigationEnabledResult(bool enable) override; void UpdateCameraWindowStatus(uint32_t accessTokenId, bool isShowing) override; void NotifyWindowStyleChange(WindowStyleType type) override; + void NotifyWindowPidVisibilityChanged(const sptr& info) override; private: static inline BrokerDelegator delegator_; diff --git a/wm/src/window_manager.cpp b/wm/src/window_manager.cpp index c26372eb8beb2dbd047e30eb308c5c06921a7c53..effb31c3df85c8a222e6e4212920bf5fc1865300 100644 --- a/wm/src/window_manager.cpp +++ b/wm/src/window_manager.cpp @@ -65,6 +65,7 @@ public: void NotifyDisplayInfoChanged(const sptr& token, DisplayId displayId, float density, DisplayOrientation orientation); void NotifyWindowStyleChange(WindowStyleType type); + void NotifyWindowPidVisibilityChanged(const sptr& info); static inline SingletonDelegator delegator_; @@ -94,6 +95,8 @@ public: sptr windowStyleListenerAgent_; std::map, std::vector>> displayInfoChangedListeners_; + std::vector> windowPidVisibilityListeners_; + sptr windowPidVisibilityListenerAgent_; }; void WindowManager::Impl::NotifyWMSConnected(int32_t userId, int32_t screenId) @@ -340,6 +343,21 @@ void WindowManager::Impl::NotifyWindowStyleChange(WindowStyleType type) } } +void WindowManager::Impl::NotifyWindowPidVisibilityChanged( + const sptr& info) +{ + std::vector> windowPidVisibilityListeners; + { + std::unique_lock lock(listenerMutex_); + windowPidVisibilityListeners = windowPidVisibilityListeners_; + } + for (auto &listener : windowPidVisibilityListeners) { + if (listener != nullptr) { + listener->NotifyWindowPidVisibilityChanged(info); + } + } +} + WindowManager::WindowManager() : pImpl_(std::make_unique()) { } @@ -945,6 +963,63 @@ WMError WindowManager::UnregisterDisplayInfoChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "listener could not be null"); + return WMError::WM_ERROR_NULLPTR; + } + std::unique_lock lock(pImpl_->listenerMutex_); + WMError ret = WMError::WM_OK; + if (pImpl_->windowPidVisibilityListenerAgent_ == nullptr) { + pImpl_->windowPidVisibilityListenerAgent_ = sptr::MakeSptr(); + } + ret = SingletonContainer::Get().RegisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_PID_VISIBILITY, + pImpl_->windowPidVisibilityListenerAgent_); + if (ret != WMError::WM_OK) { + TLOGE(WmsLogTag::WMS_LIFE, "RegisterWindowManagerAgent failed!"); + pImpl_->windowPidVisibilityListenerAgent_ = nullptr; + } else { + auto iter = std::find(pImpl_->windowPidVisibilityListeners_.begin(), + pImpl_->windowPidVisibilityListeners_.end(), listener); + if (iter != pImpl_->windowPidVisibilityListeners_.end()) { + WLOGI("Listener is already registered."); + return WMError::WM_OK; + } + pImpl_->windowPidVisibilityListeners_.emplace_back(listener); + } + return ret; +} + +WMError WindowManager::UnregisterWindowPidVisibilityChangedListener( + const sptr& listener) +{ + if (listener == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "listener could not be null"); + return WMError::WM_ERROR_NULLPTR; + } + std::unique_lock lock(pImpl_->listenerMutex_); + auto iter = std::find(pImpl_->windowPidVisibilityListeners_.begin(), + pImpl_->windowPidVisibilityListeners_.end(), listener); + if (iter == pImpl_->windowPidVisibilityListeners_.end()) { + WLOGFE("could not find this listener"); + return WMError::WM_OK; + } + pImpl_->windowPidVisibilityListeners_.erase(iter); + WMError ret = WMError::WM_OK; + if (pImpl_->windowPidVisibilityListeners_.empty() && pImpl_->windowPidVisibilityListenerAgent_ != nullptr) { + ret = SingletonContainer::Get().UnregisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_PID_VISIBILITY, + pImpl_->windowPidVisibilityListenerAgent_); + if (ret == WMError::WM_OK) { + pImpl_->windowPidVisibilityListenerAgent_ = nullptr; + } + } + return ret; +} + WMError WindowManager::NotifyDisplayInfoChange(const sptr& token, DisplayId displayId, float density, DisplayOrientation orientation) { @@ -1114,6 +1189,11 @@ void WindowManager::NotifyGestureNavigationEnabledResult(bool enable) const pImpl_->NotifyGestureNavigationEnabledResult(enable); } +void WindowManager::NotifyWindowPidVisibilityChanged(const sptr& info) const +{ + pImpl_->NotifyWindowPidVisibilityChanged(info); +} + WMError WindowManager::RaiseWindowToTop(int32_t persistentId) { WMError ret = SingletonContainer::Get().RaiseWindowToTop(persistentId); diff --git a/wm/src/window_manager_agent.cpp b/wm/src/window_manager_agent.cpp index e8a7d159c547f7e8b66957390e68c9362528dc9e..80245531f6810d2b04d5a05d506e1370ab7ab017 100644 --- a/wm/src/window_manager_agent.cpp +++ b/wm/src/window_manager_agent.cpp @@ -78,5 +78,10 @@ void WindowManagerAgent::NotifyWindowStyleChange(WindowStyleType type) SingletonContainer::Get().NotifyWindowStyleChange(type); } +void WindowManagerAgent::NotifyWindowPidVisibilityChanged(const sptr& info) +{ + SingletonContainer::Get().NotifyWindowPidVisibilityChanged(info); +} + } // namespace Rosen } // namespace OHOS diff --git a/wm/src/zidl/window_manager_agent_proxy.cpp b/wm/src/zidl/window_manager_agent_proxy.cpp index 150c88e86ff67c28cc2f95f991bcf8ffaa1c233d..0a0e325166b5a82318196d33848857d29a806bcc 100644 --- a/wm/src/zidl/window_manager_agent_proxy.cpp +++ b/wm/src/zidl/window_manager_agent_proxy.cpp @@ -381,6 +381,37 @@ void WindowManagerAgentProxy::NotifyWindowStyleChange(WindowStyleType type) } } +void WindowManagerAgentProxy::NotifyWindowPidVisibilityChanged(const sptr& info) +{ + MessageParcel data; + if (info == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "Invalid window pid visibility info."); + return; + } + + if (!data.WriteInterfaceToken(GetDescriptor())) { + TLOGE(WmsLogTag::WMS_LIFE, "WriteInterfaceToken failed"); + return; + } + + if (!data.WriteParcelable(info)) { + TLOGE(WmsLogTag::WMS_LIFE, "Write windowPidVisibilityInfo failed"); + return; + } + + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + sptr remote = Remote(); + if (remote == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "remote is null"); + return; + } + if (remote->SendRequest(static_cast(WindowManagerAgentMsg::TRANS_ID_NOTIFY_WINDOW_PID_VISIBILITY), + data, reply, option) != ERR_NONE) { + TLOGE(WmsLogTag::WMS_LIFE, "SendRequest failed"); + } +} + } // namespace Rosen } // namespace OHOS diff --git a/wm/src/zidl/window_manager_agent_stub.cpp b/wm/src/zidl/window_manager_agent_stub.cpp index 5c0b24eecae45122fa7a3a523a0870d57eb4f284..27e3670323a85d221d5b7ca41ddb4d751f1b81e7 100644 --- a/wm/src/zidl/window_manager_agent_stub.cpp +++ b/wm/src/zidl/window_manager_agent_stub.cpp @@ -149,6 +149,15 @@ int WindowManagerAgentStub::OnRemoteRequest(uint32_t code, MessageParcel& data, NotifyWindowStyleChange(type); break; } + case WindowManagerAgentMsg::TRANS_ID_NOTIFY_WINDOW_PID_VISIBILITY: { + sptr info = data.ReadParcelable(); + if (info == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "windowPidVisibilityInfo is null."); + return ERR_INVALID_DATA; + } + NotifyWindowPidVisibilityChanged(info); + break; + } default: WLOGFW("unknown transaction code %{public}d", code); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); diff --git a/wm/test/unittest/window_manager_agent_proxy_test.cpp b/wm/test/unittest/window_manager_agent_proxy_test.cpp index bc92ff8e22f532f97f0e8a7a81ac6a875246a111..78f0ea06dd17d3885b5c6bfcc45ef970884f7c80 100644 --- a/wm/test/unittest/window_manager_agent_proxy_test.cpp +++ b/wm/test/unittest/window_manager_agent_proxy_test.cpp @@ -380,6 +380,32 @@ HWTEST_F(WindowManagerAgentProxyTest, NotifyWindowStyleChange, Function | SmallT ASSERT_EQ(resultValue, 1); } +/** + * @tc.name: NotifyWindowPidVisibilityChanged + * @tc.desc: test NotifyWindowPidVisibilityChanged + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentProxyTest, NotifyWindowPidVisibilityChanged, Function | SmallTest | Level2) +{ + SingletonContainer::Get().InitDMSProxy(); + sptr impl = SingletonContainer::Get().displayManagerServiceProxy_->AsObject(); + ASSERT_TRUE(impl != nullptr); + + sptr windowManagerAgentProxy = new (std::nothrow) WindowManagerAgentProxy(impl); + ASSERT_TRUE(windowManagerAgentProxy != nullptr); + + sptr info = new WindowPidVisibilityInfo(); + + int resultValue = 0; + std::function func = [&]() + { + windowManagerAgentProxy->NotifyWindowPidVisibilityChanged(info); + resultValue = 1; + }; + func(); + ASSERT_EQ(resultValue, 1); +} + } // namespace } // namespace Rosen } // namespace OHOS \ No newline at end of file diff --git a/wm/test/unittest/window_manager_test.cpp b/wm/test/unittest/window_manager_test.cpp index e883804c039d09e8918daa86ae2702f5fe1ea8cd..30b5134876920c3b00bb84227973baa9ca859a6d 100644 --- a/wm/test/unittest/window_manager_test.cpp +++ b/wm/test/unittest/window_manager_test.cpp @@ -132,6 +132,14 @@ public: } }; +class TestWindowPidVisibilityChangedListener : public IWindowPidVisibilityChangedListener { +public: + void NotifyWindowPidVisibilityChanged(const sptr& info) + { + TLOGI(WmsLogTag::DMS, "TestWindowPidVisibilityChangedListener"); + } +}; + class WindowManagerTest : public testing::Test { public: static void SetUpTestCase(); @@ -1366,6 +1374,51 @@ HWTEST_F(WindowManagerTest, NotifyVisibleWindowNumChanged01, Function | SmallTes WindowManager::GetInstance().pImpl_->visibleWindowNumChangedListeners_.push_back(listener); WindowManager::GetInstance().pImpl_->NotifyVisibleWindowNumChanged(visibleWindowNumInfo); } + +/** + * @tc.name: RegisterWindowPidVisibilityChangedListener + * @tc.desc: check RegisterWindowPidVisibilityChangedListener + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, RegisterWindowPidVisibilityChangedListener, Function | SmallTest | Level2) +{ + WMError ret; + sptr listener = new (std::nothrow) TestWindowPidVisibilityChangedListener(); + ASSERT_NE(nullptr, listener); + ret = WindowManager::GetInstance().RegisterWindowPidVisibilityChangedListener(listener); + ASSERT_EQ(WMError::WM_OK, ret); + + ret = WindowManager::GetInstance().RegisterWindowPidVisibilityChangedListener(nullptr); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, ret); +} + +/** + * @tc.name: UnregisterWindowPidVisibilityChangedListener + * @tc.desc: check UnregisterWindowPidVisibilityChangedListener + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, UnregisterWindowPidVisibilityChangedListener, Function | SmallTest | Level2) +{ + WMError ret; + sptr listener = new (std::nothrow) TestWindowPidVisibilityChangedListener(); + ret = WindowManager::GetInstance().UnregisterWindowPidVisibilityChangedListener(listener); + ASSERT_EQ(WMError::WM_OK, ret); + + ret = WindowManager::GetInstance().UnregisterWindowPidVisibilityChangedListener(nullptr); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, ret); +} + +/** + * @tc.name: NotifyWindowPidVisibilityChanged + * @tc.desc: NotifyWindowPidVisibilityChanged + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, NotifyWindowPidVisibilityChanged, Function | SmallTest | Level2) +{ + sptr info = new WindowPidVisibilityInfo(); + WindowManager::GetInstance().NotifyWindowPidVisibilityChanged(info); + ASSERT_NE(info, nullptr); +} } } // namespace Rosen } // namespace OHOS \ No newline at end of file