diff --git a/dm/include/display_manager_adapter.h b/dm/include/display_manager_adapter.h index f6848a4b..dbce206e 100644 --- a/dm/include/display_manager_adapter.h +++ b/dm/include/display_manager_adapter.h @@ -65,6 +65,7 @@ public: virtual bool SetDisplayState(DisplayState state); virtual DisplayState GetDisplayState(DisplayId displayId); virtual void NotifyDisplayEvent(DisplayEvent event); + virtual bool SetFreeze(std::vector displayIds, bool isFreeze); virtual sptr GetDisplayInfo(DisplayId displayId); private: static inline SingletonDelegator delegator; diff --git a/dm/src/display_manager.cpp b/dm/src/display_manager.cpp index 72008614..689ea2e9 100644 --- a/dm/src/display_manager.cpp +++ b/dm/src/display_manager.cpp @@ -627,4 +627,24 @@ void DisplayManager::NotifyDisplayEvent(DisplayEvent event) WLOGFI("DisplayEvent:%{public}u", event); SingletonContainer::Get().NotifyDisplayEvent(event); } + +bool DisplayManager::Freeze(std::vector displayIds) +{ + WLOGFD("freeze display"); + if (displayIds.size() == 0) { + WLOGFE("freeze display fail, num of display is 0"); + return false; + } + return SingletonContainer::Get().SetFreeze(displayIds, true); +} + +bool DisplayManager::Unfreeze(std::vector displayIds) +{ + WLOGFD("unfreeze display"); + if (displayIds.size() == 0) { + WLOGFE("unfreeze display fail, num of display is 0"); + return false; + } + return SingletonContainer::Get().SetFreeze(displayIds, false); +} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/display_manager_adapter.cpp b/dm/src/display_manager_adapter.cpp index 1bc18135..5e2ae403 100644 --- a/dm/src/display_manager_adapter.cpp +++ b/dm/src/display_manager_adapter.cpp @@ -202,6 +202,12 @@ void DisplayManagerAdapter::NotifyDisplayEvent(DisplayEvent event) displayManagerServiceProxy_->NotifyDisplayEvent(event); } +bool DisplayManagerAdapter::SetFreeze(std::vector displayIds, bool isFreeze) +{ + INIT_PROXY_CHECK_RETURN(false); + return displayManagerServiceProxy_->SetFreeze(displayIds, isFreeze); +} + bool BaseAdapter::InitDMSProxy() { std::lock_guard lock(mutex_); diff --git a/dmserver/include/abstract_display.h b/dmserver/include/abstract_display.h index 567ae736..e69200ee 100644 --- a/dmserver/include/abstract_display.h +++ b/dmserver/include/abstract_display.h @@ -22,6 +22,11 @@ #include "display_info.h" namespace OHOS::Rosen { +enum class FreezeFlag : uint32_t { + FREEZING, + UNFREEZING, +}; + class AbstractDisplay : public RefBase { public: constexpr static int32_t DEFAULT_WIDTH = 720; @@ -45,6 +50,8 @@ public: bool BindAbstractScreen(ScreenId dmsScreenId); bool BindAbstractScreen(sptr abstractDisplay); sptr ConvertToDisplayInfo() const; + Rotation GetRotation() const; + FreezeFlag GetFreezeFlag() const; void SetId(DisplayId displayId); void SetWidth(int32_t width); @@ -53,7 +60,7 @@ public: void SetVirtualPixelRatio(float virtualPixelRatio); void SetOrientation(Orientation orientation); bool RequestRotation(Rotation rotation); - Rotation GetRotation(); + void SetFreezeFlag(FreezeFlag); private: DisplayId id_ { DISPLAY_ID_INVALID }; @@ -64,6 +71,7 @@ private: float virtualPixelRatio_ { 1.0 }; Rotation rotation_ { Rotation::ROTATION_0 }; Orientation orientation_ { Orientation::UNSPECIFIED }; + FreezeFlag freezeFlag_ { FreezeFlag::UNFREEZING }; }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_ABSTRACT_DISPLAY_H \ No newline at end of file diff --git a/dmserver/include/abstract_display_controller.h b/dmserver/include/abstract_display_controller.h index ed2f8c5f..1d4595ef 100644 --- a/dmserver/include/abstract_display_controller.h +++ b/dmserver/include/abstract_display_controller.h @@ -44,6 +44,7 @@ public: sptr GetAbstractDisplayByScreen(ScreenId screenId) const; std::vector GetAllDisplayIds() const; void AddDisplayForExpandScreen(sptr absScreen); + void SetFreeze(std::vector displayIds, bool isFreeze); private: void OnAbstractScreenConnect(sptr absScreen); diff --git a/dmserver/include/display_manager_interface.h b/dmserver/include/display_manager_interface.h index 2e56c4b8..8dde58d9 100644 --- a/dmserver/include/display_manager_interface.h +++ b/dmserver/include/display_manager_interface.h @@ -48,6 +48,7 @@ public: TRANS_ID_GET_DISPLAY_STATE, TRANS_ID_GET_ALL_DISPLAYIDS, TRANS_ID_NOTIFY_DISPLAY_EVENT, + TRANS_ID_SET_FREEZE_EVENT, TRANS_ID_SCREEN_BASE = 1000, TRANS_ID_CREATE_VIRTUAL_SCREEN = TRANS_ID_SCREEN_BASE, TRANS_ID_DESTROY_VIRTUAL_SCREEN, @@ -101,6 +102,7 @@ public: virtual DisplayState GetDisplayState(DisplayId displayId) = 0; virtual std::vector GetAllDisplayIds() = 0; virtual void NotifyDisplayEvent(DisplayEvent event) = 0; + virtual bool SetFreeze(std::vector displayIds, bool isFreeze) = 0; virtual sptr GetScreenInfoById(ScreenId screenId) = 0; virtual sptr GetScreenGroupInfoById(ScreenId screenId) = 0; virtual std::vector> GetAllScreenInfos() = 0; diff --git a/dmserver/include/display_manager_proxy.h b/dmserver/include/display_manager_proxy.h index 74c28b6d..63ec9140 100644 --- a/dmserver/include/display_manager_proxy.h +++ b/dmserver/include/display_manager_proxy.h @@ -62,6 +62,7 @@ public: std::vector GetAllDisplayIds() override; DisplayState GetDisplayState(DisplayId displayId) override; void NotifyDisplayEvent(DisplayEvent event) override; + bool SetFreeze(std::vector displayIds, bool isFreeze) override; ScreenId MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) override; sptr GetScreenInfoById(ScreenId screenId) override; sptr GetScreenGroupInfoById(ScreenId screenId) override; diff --git a/dmserver/include/display_manager_service.h b/dmserver/include/display_manager_service.h index fb609dd1..52f921d3 100644 --- a/dmserver/include/display_manager_service.h +++ b/dmserver/include/display_manager_service.h @@ -79,6 +79,7 @@ public: DisplayState GetDisplayState(DisplayId displayId) override; void NotifyDisplayEvent(DisplayEvent event) override; + bool SetFreeze(std::vector displayIds, bool isFreeze) override; sptr GetAbstractDisplay(DisplayId displayId); sptr GetAbstractScreenController(); diff --git a/dmserver/include/display_manager_service_inner.h b/dmserver/include/display_manager_service_inner.h index e9292285..1e67bcb2 100644 --- a/dmserver/include/display_manager_service_inner.h +++ b/dmserver/include/display_manager_service_inner.h @@ -17,6 +17,8 @@ #define FOUNDATION_DMSERVER_DISPLAY_MANAGER_SERVICE_INNER_H #include + +#include #include #include "abstract_display.h" @@ -37,6 +39,7 @@ public: ScreenId GetRSScreenId(DisplayId displayId) const; const sptr GetScreenInfoByDisplayId(DisplayId displayId) const; const sptr GetScreenModesByDisplayId(DisplayId displayId); + std::shared_ptr GetDisplaySnapshot(DisplayId); void UpdateRSTree(DisplayId displayId, std::shared_ptr& surfaceNode, bool isAdd); void RegisterDisplayChangeListener(sptr listener); }; diff --git a/dmserver/src/abstract_display.cpp b/dmserver/src/abstract_display.cpp index c2e9b36b..bb31e388 100644 --- a/dmserver/src/abstract_display.cpp +++ b/dmserver/src/abstract_display.cpp @@ -114,11 +114,21 @@ bool AbstractDisplay::RequestRotation(Rotation rotation) return true; } -Rotation AbstractDisplay::GetRotation() +Rotation AbstractDisplay::GetRotation() const { return rotation_; } +void AbstractDisplay::SetFreezeFlag(FreezeFlag freezeFlag) +{ + freezeFlag_ = freezeFlag; +} + +FreezeFlag AbstractDisplay::GetFreezeFlag() const +{ + return freezeFlag_; +} + bool AbstractDisplay::BindAbstractScreen(ScreenId dmsScreenId) { sptr screenController diff --git a/dmserver/src/abstract_display_controller.cpp b/dmserver/src/abstract_display_controller.cpp index 6a561eb1..b89e81a4 100644 --- a/dmserver/src/abstract_display_controller.cpp +++ b/dmserver/src/abstract_display_controller.cpp @@ -55,7 +55,7 @@ void AbstractDisplayController::Init(sptr abstractScre abstractScreenController_->ScreenConnectionInDisplayInit(abstractScreenCallback_); abstractScreenController->RegisterAbstractScreenCallback(abstractScreenCallback_); - // TODO: Active the code after "rsDisplayNode_->SetScreenId(rsScreenId)" is provided. + // Active the code after "rsDisplayNode_->SetScreenId(rsScreenId)" is provided. /*std::lock_guard lock(mutex_); if (dummyDisplay_ == nullptr) { sptr display = new AbstractDisplay(this, displayCount_.fetch_add(1), SCREEN_ID_INVALID, @@ -423,4 +423,42 @@ void AbstractDisplayController::AddDisplayForExpandScreen(sptr a absScreen->dmsId_); AddScreenToExpandLocked(absScreen); } + + +void AbstractDisplayController::SetFreeze(std::vector displayIds, bool toFreeze) +{ + WM_SCOPED_TRACE("dms:SetAllFreeze"); + DisplayStateChangeType type = toFreeze ? DisplayStateChangeType::FREEZE : DisplayStateChangeType::UNFREEZE; + DisplayChangeEvent event + = toFreeze ? DisplayChangeEvent::DISPLAY_FREEZED : DisplayChangeEvent::DISPLAY_UNFREEZED; + for (DisplayId displayId : displayIds) { + sptr abstractDisplay; + WM_SCOPED_TRACE("dms:SetFreeze(%" PRIu64")", displayId); + { + WLOGI("setfreeze display %{public}" PRIu64"", displayId); + std::lock_guard lock(mutex_); + auto iter = abstractDisplayMap_.find(displayId); + if (iter == abstractDisplayMap_.end()) { + WLOGI("setfreeze fail, cannot get display %{public}" PRIu64"", displayId); + continue; + } + abstractDisplay = iter->second; + FreezeFlag curFlag = abstractDisplay->GetFreezeFlag(); + if ((toFreeze && (curFlag == FreezeFlag::FREEZING)) + || (!toFreeze && (curFlag == FreezeFlag::UNFREEZING))) { + WLOGI("setfreeze fail, display %{public}" PRIu64" freezeflag is %{public}u", + displayId, curFlag); + continue; + } + FreezeFlag flag = toFreeze ? FreezeFlag::FREEZING : FreezeFlag::UNFREEZING; + abstractDisplay->SetFreezeFlag(flag); + } + + // Notify freeze event to WMS + DisplayManagerService::GetInstance().NotifyDisplayStateChange(displayId, type); + // Notify freeze event to DisplayManager + sptr displayInfo = abstractDisplay->ConvertToDisplayInfo(); + DisplayManagerAgentController::GetInstance().OnDisplayChange(displayInfo, event); + } +} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dmserver/src/display_manager_proxy.cpp b/dmserver/src/display_manager_proxy.cpp index 645c0ee5..920ac103 100644 --- a/dmserver/src/display_manager_proxy.cpp +++ b/dmserver/src/display_manager_proxy.cpp @@ -686,6 +686,31 @@ void DisplayManagerProxy::NotifyDisplayEvent(DisplayEvent event) } } +bool DisplayManagerProxy::SetFreeze(std::vector displayIds, bool isFreeze) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + if (!data.WriteUInt64Vector(displayIds)) { + WLOGFE("set freeze fail: write displayId failed."); + return false; + } + if (!data.WriteBool(isFreeze)) { + WLOGFE("set freeze fail: write freeze flag failed."); + return false; + } + + if (Remote()->SendRequest(TRANS_ID_SET_FREEZE_EVENT, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return false; + } + return true; +} + ScreenId DisplayManagerProxy::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) { sptr remote = Remote(); diff --git a/dmserver/src/display_manager_service.cpp b/dmserver/src/display_manager_service.cpp index 5142e474..a18e185f 100644 --- a/dmserver/src/display_manager_service.cpp +++ b/dmserver/src/display_manager_service.cpp @@ -345,6 +345,11 @@ void DisplayManagerService::NotifyDisplayEvent(DisplayEvent event) displayPowerController_->NotifyDisplayEvent(event); } +bool DisplayManagerService::SetFreeze(std::vector displayIds, bool isFreeze) +{ + abstractDisplayController_->SetFreeze(displayIds, isFreeze); + return true; +} std::shared_ptr DisplayManagerService::GetRSDisplayNodeByDisplayId(DisplayId displayId) const { diff --git a/dmserver/src/display_manager_service_inner.cpp b/dmserver/src/display_manager_service_inner.cpp index a347ea07..21dc9e72 100644 --- a/dmserver/src/display_manager_service_inner.cpp +++ b/dmserver/src/display_manager_service_inner.cpp @@ -110,6 +110,11 @@ const sptr DisplayManagerServiceInner::GetScreenModesByDis return abstractScreen->GetActiveScreenMode(); } +std::shared_ptr DisplayManagerServiceInner::GetDisplaySnapshot(DisplayId displayId) +{ + return DisplayManagerService::GetInstance().abstractDisplayController_->GetScreenSnapshot(displayId); +} + void DisplayManagerServiceInner::RegisterDisplayChangeListener(sptr listener) { DisplayManagerService::GetInstance().RegisterDisplayChangeListener(listener); diff --git a/dmserver/src/display_manager_stub.cpp b/dmserver/src/display_manager_stub.cpp index e5d4fb69..731ec850 100644 --- a/dmserver/src/display_manager_stub.cpp +++ b/dmserver/src/display_manager_stub.cpp @@ -166,6 +166,12 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, NotifyDisplayEvent(event); break; } + case TRANS_ID_SET_FREEZE_EVENT: { + std::vector ids; + data.ReadUInt64Vector(&ids); + SetFreeze(ids, data.ReadBool()); + break; + } case TRANS_ID_SCREEN_MAKE_MIRROR: { ScreenId mainScreenId = static_cast(data.ReadUint64()); std::vector mirrorScreenId; diff --git a/interfaces/innerkits/dm/display_manager.h b/interfaces/innerkits/dm/display_manager.h index 20305a7f..dd4e542a 100644 --- a/interfaces/innerkits/dm/display_manager.h +++ b/interfaces/innerkits/dm/display_manager.h @@ -60,6 +60,8 @@ public: bool SetScreenBrightness(uint64_t screenId, uint32_t level); uint32_t GetScreenBrightness(uint64_t screenId) const; void NotifyDisplayEvent(DisplayEvent event); + bool Freeze(std::vector displayIds); + bool Unfreeze(std::vector displayIds); constexpr static int32_t MAX_RESOLUTION_SIZE_SCREENSHOT = 3840; // max resolution, 4K private: diff --git a/interfaces/innerkits/dm/dm_common.h b/interfaces/innerkits/dm/dm_common.h index efb81c04..95ed87b9 100644 --- a/interfaces/innerkits/dm/dm_common.h +++ b/interfaces/innerkits/dm/dm_common.h @@ -121,6 +121,8 @@ enum class Orientation : uint32_t { enum class DisplayChangeEvent : uint32_t { UPDATE_ORIENTATION, DISPLAY_SIZE_CHANGED, + DISPLAY_FREEZED, + DISPLAY_UNFREEZED, UNKNOWN, }; } diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index 04c679fd..688fcea5 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -56,6 +56,7 @@ enum class WindowType : uint32_t { WINDOW_TYPE_LAUNCHER_RECENT, WINDOW_TYPE_LAUNCHER_DOCK, WINDOW_TYPE_BOOT_ANIMATION, + WINDOW_TYPE_FREEZE_DISPLAY, ABOVE_APP_SYSTEM_WINDOW_END, SYSTEM_WINDOW_END = ABOVE_APP_SYSTEM_WINDOW_END, diff --git a/utils/include/display_change_listener.h b/utils/include/display_change_listener.h index 8db28b46..83304a32 100644 --- a/utils/include/display_change_listener.h +++ b/utils/include/display_change_listener.h @@ -25,7 +25,9 @@ enum class DisplayStateChangeType : uint32_t { BEFORE_UNLOCK, UPDATE_ROTATION, SIZE_CHANGE, - DESTROY + DESTROY, + FREEZE, + UNFREEZE, }; class IDisplayChangeListener : public RefBase { public: diff --git a/wmserver/BUILD.gn b/wmserver/BUILD.gn index 1563bd66..35b69afc 100644 --- a/wmserver/BUILD.gn +++ b/wmserver/BUILD.gn @@ -48,6 +48,7 @@ ohos_shared_library("libwms") { "../wm/src/zidl/window_manager_agent_proxy.cpp", "src/avoid_area_controller.cpp", "src/drag_controller.cpp", + "src/freeze_controller.cpp", "src/input_window_monitor.cpp", "src/window_controller.cpp", "src/window_inner_manager.cpp", diff --git a/wmserver/include/freeze_controller.h b/wmserver/include/freeze_controller.h new file mode 100644 index 00000000..ba64988d --- /dev/null +++ b/wmserver/include/freeze_controller.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022-2022 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_FREEZE_CONTROLLER_H +#define OHOS_ROSEN_FREEZE_CONTROLLER_H + +#include + +#include +#include +#ifdef ACE_ENABLE_GL +#include +#endif +#include +#include + +#include "display.h" +#include "window.h" + +namespace OHOS { +namespace Rosen { +class FreezeController : public RefBase { +public: + FreezeController() {}; + ~FreezeController() = default; + + bool FreezeDisplay(DisplayId displayId); + bool UnfreezeDisplay(DisplayId displayId); + +private: + sptr CreateCoverWindow(DisplayId displayId); + SkImageInfo MakeSkImageInfoFromPixelMap(std::shared_ptr& pixmap); + bool DrawSkImage(std::shared_ptr& rsSurface, + uint32_t width, uint32_t height, std::shared_ptr pixelMap); + + std::map> coverWindowMap_; +#ifdef ACE_ENABLE_GL + RenderContext* rc_ = nullptr; +#endif +}; +} +} +#endif // OHOS_ROSEN_FREEZE_CONTROLLER_H + diff --git a/wmserver/include/window_manager_service.h b/wmserver/include/window_manager_service.h index 2c5512e8..8a043494 100644 --- a/wmserver/include/window_manager_service.h +++ b/wmserver/include/window_manager_service.h @@ -24,6 +24,7 @@ #include #include "display_change_listener.h" #include "drag_controller.h" +#include "freeze_controller.h" #include "singleton_delegator.h" #include "wm_single_instance.h" #include "window_controller.h" @@ -91,6 +92,7 @@ private: sptr inputWindowMonitor_; sptr snapshotController_; sptr dragController_; + sptr freezeDisplayController_; }; } } diff --git a/wmserver/include/window_zorder_policy.h b/wmserver/include/window_zorder_policy.h index 17e87476..ec0b92a4 100644 --- a/wmserver/include/window_zorder_policy.h +++ b/wmserver/include/window_zorder_policy.h @@ -60,6 +60,7 @@ private: { WindowType::WINDOW_TYPE_DRAGGING_EFFECT, 115 }, { WindowType::WINDOW_TYPE_POINTER, 116 }, { WindowType::WINDOW_TYPE_BOOT_ANIMATION, 117 }, + { WindowType::WINDOW_TYPE_FREEZE_DISPLAY, 118 }, }; }; } diff --git a/wmserver/src/freeze_controller.cpp b/wmserver/src/freeze_controller.cpp new file mode 100644 index 00000000..13974824 --- /dev/null +++ b/wmserver/src/freeze_controller.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2022-2022 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 "freeze_controller.h" + +#include + +#include +#include +#include + +#include "display_manager_service_inner.h" +#include "window_manager_hilog.h" +#include "window_option.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "FreezeController"}; +} + +bool FreezeController::FreezeDisplay(DisplayId displayId) +{ + sptr window = CreateCoverWindow(displayId); + if (window == nullptr) { + return false; + } + + WMError res = window->Show(); + if (res != WMError::WM_OK) { + WLOGFE("Show window failed"); + return false; + } + +#ifdef ACE_ENABLE_GL + WLOGFI("Draw cover window on gpu"); + // init render context + static bool hasInitRC = false; + if (!hasInitRC) { + rc_ = RenderContextFactory::GetInstance().CreateEngine(); + if (rc_ != nullptr) { + rc_->InitializeEglContext(); + hasInitRC = true; + } else { + WLOGFE("InitilizeEglContext failed"); + return false; + } + } +#endif + + std::shared_ptr surfaceNode = window->GetSurfaceNode(); + if (surfaceNode == nullptr) { + WLOGFE("RSSurfaceNode is null"); + return false; + } + Rect winRect = window->GetRect(); + WLOGFI("freeze window rect, x : %{public}d, y : %{public}d, width: %{public}u, height: %{public}u", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + + std::shared_ptr rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode); + if (rsSurface == nullptr) { + WLOGFE("RSSurface is null"); + return false; + } + +#ifdef ACE_ENABLE_GL + rsSurface->SetRenderContext(rc_); +#endif + + std::shared_ptr pixelMap = DisplayManagerServiceInner::GetInstance().GetDisplaySnapshot(displayId); + if (pixelMap == nullptr) { + WLOGE("freeze display fail, pixel map is null. display %{public}" PRIu64"", displayId); + return false; + } + return DrawSkImage(rsSurface, winRect.width_, winRect.height_, pixelMap); +} + +bool FreezeController::UnfreezeDisplay(DisplayId displayId) +{ + auto iter = coverWindowMap_.find(displayId); + if (iter == coverWindowMap_.end()) { + WLOGW("unfreeze fail, no cover window. display %{public}" PRIu64"", displayId); + return false; + } + sptr window = iter->second; + if (window == nullptr) { + WLOGW("unfreeze fail, window is null. display %{public}" PRIu64"", displayId); + return false; + } + return WMError::WM_OK == window->Destroy(); +} + +sptr FreezeController::CreateCoverWindow(DisplayId displayId) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_FREEZE_DISPLAY); + option->SetFocusable(false); + option->RemoveWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + option->SetDisplayId(displayId); + sptr window = Window::Create("freeze" + std::to_string(displayId), option); + if (window == nullptr) { + WLOGFE("cover window is null"); + return nullptr; + } + coverWindowMap_[displayId] = window; + return window; +} + +bool FreezeController::DrawSkImage(std::shared_ptr& rsSurface, + uint32_t width, uint32_t height, std::shared_ptr pixelmap) +{ + // Get canvas + WLOGFD("start to draw bitmap"); + std::unique_ptr frame = rsSurface->RequestFrame(width, height); + if (frame == nullptr) { + WLOGFE("fail to request frame"); + return false; + } + auto canvas = frame->GetCanvas(); + if (canvas == nullptr) { + WLOGFE("fail to get canvas"); + return false; + } + canvas->clear(SK_ColorTRANSPARENT); + + // Create SkPixmap from PixelMap + auto imageInfo = MakeSkImageInfoFromPixelMap(pixelmap); + SkPixmap imagePixmap(imageInfo, reinterpret_cast(pixelmap->GetPixels()), pixelmap->GetRowBytes()); + + // Create SkImage from SkPixmap + sk_sp skImage = SkImage::MakeFromRaster(imagePixmap, nullptr, nullptr); + if (!skImage) { + WLOGFE("sk image is null"); + return false; + } + + SkPaint paint; + sk_sp colorSpace = skImage->refColorSpace(); +#ifdef USE_SYSTEM_SKIA + paint.setColor4f(paint.getColor4f(), colorSpace.get()); +#else + paint.setColor(paint.getColor4f(), colorSpace.get()); +#endif + auto skSrcRect = SkRect::MakeXYWH(0, 0, pixelmap->GetWidth(), pixelmap->GetHeight()); + auto skDstRect = SkRect::MakeXYWH(0, 0, width, height); + canvas->drawImageRect(skImage, skSrcRect, skDstRect, &paint); + frame->SetDamageRegion(0, 0, width, height); + if (!rsSurface->FlushFrame(frame)) { + WLOGFE("fail to flush frame"); + return false; + } + return true; +} + +SkImageInfo FreezeController::MakeSkImageInfoFromPixelMap(std::shared_ptr& pixmap) +{ + SkColorType colorType = kN32_SkColorType; + SkAlphaType alphaType = SkAlphaType::kOpaque_SkAlphaType; + sk_sp colorSpace = SkColorSpace::MakeSRGB(); + return SkImageInfo::Make(pixmap->GetWidth(), pixmap->GetHeight(), colorType, alphaType, colorSpace); +} +} +} \ No newline at end of file diff --git a/wmserver/src/window_manager_service.cpp b/wmserver/src/window_manager_service.cpp index fcc3ac67..068c1c31 100644 --- a/wmserver/src/window_manager_service.cpp +++ b/wmserver/src/window_manager_service.cpp @@ -48,6 +48,7 @@ WindowManagerService::WindowManagerService() : SystemAbility(WINDOW_MANAGER_SERV windowController_ = new WindowController(windowRoot_, inputWindowMonitor_); snapshotController_ = new SnapshotController(windowRoot_); dragController_ = new DragController(windowRoot_); + freezeDisplayController_ = new FreezeController(); } void WindowManagerService::OnStart() @@ -274,8 +275,14 @@ void WindowManagerService::OnWindowEvent(Event event, uint32_t windowId) void WindowManagerService::NotifyDisplayStateChange(DisplayId id, DisplayStateChangeType type) { WM_SCOPED_TRACE("wms:NotifyDisplayStateChange(%u)", type); - std::lock_guard lock(mutex_); - return windowController_->NotifyDisplayStateChange(id, type); + if (type == DisplayStateChangeType::FREEZE) { + freezeDisplayController_->FreezeDisplay(id); + } else if (type == DisplayStateChangeType::UNFREEZE) { + freezeDisplayController_->UnfreezeDisplay(id); + } else { + std::lock_guard lock(mutex_); + return windowController_->NotifyDisplayStateChange(id, type); + } } void DisplayChangeListener::OnDisplayStateChange(DisplayId id, DisplayStateChangeType type)