From 64c31bbd942b4778d3948b271334ebb934214aef Mon Sep 17 00:00:00 2001 From: realice Date: Mon, 11 Jul 2022 12:25:45 +0800 Subject: [PATCH] add interface:1.screenshot listener 2.window snapshot Change-Id: I92d98da9bb60446bbadf39d3fc94b575893fcaac Signed-off-by: realice --- .../include/abstract_display_controller.h | 31 --------- dmserver/include/display_manager_service.h | 1 + dmserver/src/abstract_display_controller.cpp | 6 +- dmserver/src/display_manager_service.cpp | 13 +++- interfaces/innerkits/wm/window.h | 9 +++ interfaces/kits/napi/window_runtime/BUILD.gn | 1 + .../napi/window_runtime/api/@ohos.window.d.ts | 32 ++++++++++ .../window_runtime/window_napi/js_window.cpp | 56 ++++++++++++++++- .../window_runtime/window_napi/js_window.h | 2 + .../window_napi/js_window_listener.cpp | 20 ++++++ .../window_napi/js_window_listener.h | 5 +- .../js_window_register_manager.cpp | 20 +++++- .../window_napi/js_window_register_manager.h | 1 + utils/include/display_change_listener.h | 1 + utils/include/surface_capture_future.h | 55 ++++++++++++++++ wm/BUILD.gn | 1 + wm/include/window_agent.h | 1 + wm/include/window_impl.h | 5 ++ wm/include/zidl/window_interface.h | 2 + wm/include/zidl/window_proxy.h | 1 + wm/src/window_agent.cpp | 10 +++ wm/src/window_impl.cpp | 63 ++++++++++++++++++- wm/src/zidl/window_proxy.cpp | 16 +++++ wm/src/zidl/window_stub.cpp | 4 ++ wm/test/fuzztest/window_fuzzer/BUILD.gn | 6 +- .../unittest/avoid_area_controller_test.cpp | 1 + wmserver/include/window_controller.h | 3 + wmserver/include/window_manager_service.h | 2 + .../window_snapshot/snapshot_controller.h | 31 +-------- wmserver/src/window_controller.cpp | 37 +++++++++-- wmserver/src/window_manager_service.cpp | 12 ++++ .../window_snapshot/snapshot_controller.cpp | 7 +-- 32 files changed, 373 insertions(+), 82 deletions(-) create mode 100644 utils/include/surface_capture_future.h diff --git a/dmserver/include/abstract_display_controller.h b/dmserver/include/abstract_display_controller.h index 697a5a16..4c09e9ba 100644 --- a/dmserver/include/abstract_display_controller.h +++ b/dmserver/include/abstract_display_controller.h @@ -26,7 +26,6 @@ #include "screen.h" #include "abstract_display.h" #include "display_change_listener.h" -#include "transaction/rs_interfaces.h" #include "future.h" namespace OHOS::Rosen { @@ -76,36 +75,6 @@ private: sptr abstractScreenCallback_; OHOS::Rosen::RSInterfaces& rsInterface_; DisplayStateChangeListener displayStateChangeListener_; - - class ScreenshotCallback : public SurfaceCaptureCallback, public Future> { - public: - ScreenshotCallback() = default; - ~ScreenshotCallback() {}; - void OnSurfaceCapture(std::shared_ptr pixelmap) override - { - FutureCall(pixelmap); - } - - protected: - void Call(std::shared_ptr pixelmap) override - { - if (!flag_) { - flag_ = true; - pixelMap_ = pixelmap; - } - } - bool IsReady() override - { - return flag_; - } - std::shared_ptr FetchResult() override - { - return pixelMap_; - } - private: - bool flag_ = false; - std::shared_ptr pixelMap_ = nullptr; - }; }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_ABSTRACT_DISPLAY_CONTROLLER_H \ No newline at end of file diff --git a/dmserver/include/display_manager_service.h b/dmserver/include/display_manager_service.h index 1611bbc5..915b12bf 100644 --- a/dmserver/include/display_manager_service.h +++ b/dmserver/include/display_manager_service.h @@ -105,6 +105,7 @@ private: bool Init(); void NotifyDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, const std::map>& displayInfoMap, DisplayStateChangeType type); + void NotifyScreenshot(DisplayId displayId); ScreenId GetScreenIdByDisplayId(DisplayId displayId) const; std::shared_ptr GetRSDisplayNodeByDisplayId(DisplayId displayId) const; void ConfigureDisplayManagerService(); diff --git a/dmserver/src/abstract_display_controller.cpp b/dmserver/src/abstract_display_controller.cpp index 86abf0f6..2ec62f19 100644 --- a/dmserver/src/abstract_display_controller.cpp +++ b/dmserver/src/abstract_display_controller.cpp @@ -22,6 +22,7 @@ #include "display_manager_agent_controller.h" #include "display_manager_service.h" #include "screen_group.h" +#include "surface_capture_future.h" #include "window_manager_hilog.h" namespace OHOS::Rosen { @@ -113,10 +114,11 @@ std::shared_ptr AbstractDisplayController::GetScreenSnapshot(Di } ScreenId dmsScreenId = abstractDisplay->GetAbstractScreenId(); std::shared_ptr displayNode = abstractScreenController_->GetRSDisplayNodeByScreenId(dmsScreenId); + std::lock_guard lock(mutex_); - std::shared_ptr callback = std::make_shared(); + std::shared_ptr callback = std::make_shared(); rsInterface_.TakeSurfaceCapture(displayNode, callback); - std::shared_ptr screenshot = callback->GetResult(2000); // wait for 2000ms + std::shared_ptr screenshot = callback->GetResult(2000); // wait for <= 2000ms if (screenshot == nullptr) { WLOGFE("Failed to get pixelmap from RS, return nullptr!"); } diff --git a/dmserver/src/display_manager_service.cpp b/dmserver/src/display_manager_service.cpp index d3052bd0..78dae738 100644 --- a/dmserver/src/display_manager_service.cpp +++ b/dmserver/src/display_manager_service.cpp @@ -140,6 +140,13 @@ void DisplayManagerService::GetWindowPreferredOrientation(DisplayId displayId, O } } +void DisplayManagerService::NotifyScreenshot(DisplayId displayId) +{ + if (displayChangeListener_ != nullptr) { + displayChangeListener_->OnScreenshot(displayId); + } +} + sptr DisplayManagerService::GetDefaultDisplayInfo() { ScreenId dmsScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); @@ -225,7 +232,11 @@ std::shared_ptr DisplayManagerService::GetDisplaySnapshot(Displ HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:GetDisplaySnapshot(%" PRIu64")", displayId); if (Permission::CheckCallingPermission("ohos.permission.CAPTURE_SCREEN") || Permission::IsStartByHdcd()) { - return abstractDisplayController_->GetScreenSnapshot(displayId); + auto res = abstractDisplayController_->GetScreenSnapshot(displayId); + if (res != nullptr) { + NotifyScreenshot(displayId); + } + return res; } return nullptr; } diff --git a/interfaces/innerkits/wm/window.h b/interfaces/innerkits/wm/window.h index bfe4fd7d..ff066415 100644 --- a/interfaces/innerkits/wm/window.h +++ b/interfaces/innerkits/wm/window.h @@ -18,6 +18,7 @@ #include #include +#include #include "wm_common.h" #include "window_option.h" @@ -140,6 +141,11 @@ public: virtual void AnimationForHidden() = 0; }; +class IScreenshotListener : virtual public RefBase { +public: + virtual void OnScreenshot() = 0; +}; + class Window : public RefBase { public: /** @@ -242,6 +248,8 @@ public: virtual void RegisterTouchOutsideListener(const sptr& listener) = 0; virtual void UnregisterTouchOutsideListener(const sptr& listener) = 0; virtual void RegisterAnimationTransitionController(const sptr& listener) = 0; + virtual void RegisterScreenshotListener(const sptr& listener) = 0; + virtual void UnregisterScreenshotListener(const sptr& listener) = 0; virtual void SetAceAbilityHandler(const sptr& handler) = 0; virtual WMError SetUIContent(const std::string& contentInfo, NativeEngine* engine, NativeValue* storage, bool isDistributed = false, AppExecFwk::Ability* ability = nullptr) = 0; @@ -269,6 +277,7 @@ public: virtual ColorSpace GetColorSpace() = 0; virtual void DumpInfo(const std::vector& params, std::vector& info) = 0; + virtual std::shared_ptr Snapshot() = 0; }; } } diff --git a/interfaces/kits/napi/window_runtime/BUILD.gn b/interfaces/kits/napi/window_runtime/BUILD.gn index f141e3fe..75fc7791 100644 --- a/interfaces/kits/napi/window_runtime/BUILD.gn +++ b/interfaces/kits/napi/window_runtime/BUILD.gn @@ -62,6 +62,7 @@ ohos_shared_library("window_native_kit") { "bundle_framework:appexecfwk_base", "hiviewdfx_hilog_native:libhilog", "ipc:ipc_core", + "multimedia_image_standard:image", "napi:ace_napi", "utils_base:utils", ] diff --git a/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts b/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts index f5fbf52a..3bdda6c0 100644 --- a/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts +++ b/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts @@ -15,6 +15,8 @@ import { AsyncCallback, Callback } from './basic' ; import { Context } from './app/context'; import { ContenStorage } from './@internal/component/ets/stateManagement' +import image from './@ohos.multimedia.image'; + /** * Window manager. * @syscap SystemCapability.WindowManager.WindowManager.Core @@ -888,6 +890,22 @@ declare namespace window { */ off(type: 'avoidAreaChange', callback?: Callback<{ type: AvoidAreaType, area: AvoidArea }>): void; + /** + * register the callback of screenshotEvent, only the focused window called back + * @param type: 'screenshotEvent' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + on(type: 'screenshotEvent', callback: Callback): void; + + /** + * unregister the callback of screenshotEvent + * @param type: 'screenshotEvent' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + off(type: 'screenshotEvent', callback?: Callback): void; + /** * Whether the window supports thr wide gamut setting. * @since 8 @@ -1133,6 +1151,20 @@ declare namespace window { * @since 9 */ getTransitionControllerSync(): TransitionController; + + /** + * Obtains snapshot of window + * @syscap SystemCapability.WindowManager.WindowManager.Cor + * @since 9 + */ + snapshot(callback: AsyncCallback): void; + + /** + * Obtains snapshot of window + * @syscap SystemCapability.WindowManager.WindowManager.Co + * @since 9 + */ + snapshot(): Promise; } /** * Transition Context diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp index 1e5f41e7..b8786b0b 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp @@ -22,6 +22,9 @@ #include "window_helper.h" #include "window_manager_hilog.h" #include "window_option.h" +#include "pixel_map.h" +#include "pixel_map_napi.h" + namespace OHOS { namespace Rosen { using namespace AbilityRuntime; @@ -1726,6 +1729,13 @@ NativeValue* JsWindow::OnDump(NativeEngine& engine, NativeCallbackInfo& info) return dumpInfoValue; } +NativeValue* JsWindow::Snapshot(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFI("[NAPI]Snapshot"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSnapshot(*engine, *info) : nullptr; +} + NativeValue* JsWindow::OnSetForbidSplitMove(NativeEngine& engine, NativeCallbackInfo& info) { WMError errCode = WMError::WM_OK; @@ -1769,7 +1779,50 @@ NativeValue* JsWindow::OnSetForbidSplitMove(NativeEngine& engine, NativeCallback NativeValue* lastParam = (info.argc <= 1) ? nullptr : (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); NativeValue* result = nullptr; - AsyncTask::Schedule("JsWindow::OnDump", + AsyncTask::Schedule("JsWindow::OnSetForbidSplitMove", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSnapshot(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc > 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + + std::shared_ptr pixelMap = weakWindow->Snapshot(); + if (pixelMap == nullptr) { + task.Reject(engine, CreateJsError(engine, static_cast(WMError::WM_ERROR_NULLPTR))); + WLOGFE("[NAPI]window snapshot get pixelmap is null"); + return; + } + + auto nativePixelMap = reinterpret_cast( + Media::PixelMapNapi::CreatePixelMap(reinterpret_cast(&engine), pixelMap)); + if (nativePixelMap == nullptr) { + WLOGFE("[NAPI]window snapshot get nativePixelMap is null"); + } + task.Resolve(engine, nativePixelMap); + WLOGFI("[NAPI]Window [%{public}u, %{public}s] OnSnapshot, WxH=%{public}dx%{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), + pixelMap->GetWidth(), pixelMap->GetHeight()); + }; + + NativeValue* lastParam = (info.argc == 0) ? nullptr : + (info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSnapshot", engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); return result; } @@ -2098,6 +2151,7 @@ void BindFunctions(NativeEngine& engine, NativeObject* object) BindNativeFunction(engine, *object, "setRotateSync", JsWindow::SetRotateSync); BindNativeFunction(engine, *object, "setTranslateSync", JsWindow::SetTranslateSync); BindNativeFunction(engine, *object, "getTransitionControllerSync", JsWindow::GetTransitionControllerSync); + BindNativeFunction(engine, *object, "snapshot", JsWindow::Snapshot); } } // namespace Rosen } // namespace OHOS diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window.h b/interfaces/kits/napi/window_runtime/window_napi/js_window.h index 30a2b36f..45b92e78 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.h +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.h @@ -70,6 +70,7 @@ public: static NativeValue* GetColorSpace(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* Dump(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* SetForbidSplitMove(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* Snapshot(NativeEngine* engine, NativeCallbackInfo* info); // animation config static NativeValue* SetOpacitySync(NativeEngine* engine, NativeCallbackInfo* info); @@ -120,6 +121,7 @@ private: NativeValue* OnDisableWindowDecor(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnDump(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnSetForbidSplitMove(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSnapshot(NativeEngine& engine, NativeCallbackInfo& info); // animation Config NativeValue* OnSetOpacitySync(NativeEngine& engine, NativeCallbackInfo& info); diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp b/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp index e9e9954a..f0bead10 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp @@ -210,6 +210,7 @@ void JsWindowListener::OnSizeChange(const sptr& info) void JsWindowListener::OnTouchOutside() const { + WLOGFI("CALLED"); std::unique_ptr complete = std::make_unique ( [self = weakRef_] (NativeEngine &engine, AsyncTask &task, int32_t status) { auto thisListener = self.promote(); @@ -225,7 +226,26 @@ void JsWindowListener::OnTouchOutside() const std::unique_ptr execute = nullptr; AsyncTask::Schedule("JsWindowListener::OnOutsidePressed", *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::OnScreenshot() +{ WLOGFI("CALLED"); + std::unique_ptr complete = std::make_unique ( + [self = wptr(this)] (NativeEngine &engine, AsyncTask &task, int32_t status) { + auto thisListener = self.promote(); + if (thisListener == nullptr) { + WLOGFE("[NAPI]this listener is nullptr"); + return; + } + thisListener->CallJsMethod(SCREENSHOT_EVENT_CB.c_str(), nullptr, 0); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsWindowListener::OnScreenshot", + *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); } } // namespace Rosen } // namespace OHOS diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h b/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h index 617a1be2..b220388b 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h @@ -38,13 +38,15 @@ const std::string LIFECYCLE_EVENT_CB = "lifeCycleEvent"; const std::string WINDOW_STAGE_EVENT_CB = "windowStageEvent"; const std::string KEYBOARD_HEIGHT_CHANGE_CB = "keyboardHeightChange"; const std::string TOUCH_OUTSIDE_CB = "touchOutside"; +const std::string SCREENSHOT_EVENT_CB = "screenshotEvent"; class JsWindowListener : public IWindowChangeListener, public ISystemBarChangedListener, public IAvoidAreaChangedListener, public IWindowLifeCycle, public IOccupiedAreaChangeListener, - public ITouchOutsideListener { + public ITouchOutsideListener, + public IScreenshotListener { public: JsWindowListener(NativeEngine* engine, std::shared_ptr callback) : engine_(engine), jsCallBack_(callback), weakRef_(wptr (this)) {} @@ -59,6 +61,7 @@ public: void AfterUnfocused() override; void OnSizeChange(const sptr& info) override; void OnTouchOutside() const override; + void OnScreenshot() override; void CallJsMethod(const char* methodName, NativeValue* const* argv = nullptr, size_t argc = 0); private: void LifeCycleCallBack(LifeCycleEventType eventType); diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp b/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp index 79a81276..049ed08b 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp @@ -35,7 +35,8 @@ JsWindowRegisterManager::JsWindowRegisterManager() { AVOID_AREA_CHANGE_CB, &JsWindowRegisterManager::ProcessAvoidAreaChangeRegister }, { LIFECYCLE_EVENT_CB, &JsWindowRegisterManager::ProcessLifeCycleEventRegister }, { KEYBOARD_HEIGHT_CHANGE_CB, &JsWindowRegisterManager::ProcessOccupiedAreaChangeRegister }, - { TOUCH_OUTSIDE_CB, &JsWindowRegisterManager::ProcessTouchOutsideRegister } + { TOUCH_OUTSIDE_CB, &JsWindowRegisterManager::ProcessTouchOutsideRegister }, + { SCREENSHOT_EVENT_CB, &JsWindowRegisterManager::ProcessScreenshotRegister } }; // white register list for window stage listenerProcess_[CaseType::CASE_STAGE] = { @@ -160,6 +161,23 @@ bool JsWindowRegisterManager::ProcessTouchOutsideRegister(sptr return true; } +bool JsWindowRegisterManager::ProcessScreenshotRegister(sptr listener, + sptr window, bool isRegister) +{ + WLOGFI("called"); + if (window == nullptr) { + WLOGFE("%{public}sregister screenshot listener failed. window is null", isRegister? "" : "un"); + return false; + } + sptr thisListener(listener); + if (isRegister) { + window->RegisterScreenshotListener(thisListener); + } else { + window->UnregisterScreenshotListener(thisListener); + } + return true; +} + bool JsWindowRegisterManager::IsCallbackRegistered(std::string type, NativeValue* jsListenerObject) { if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h b/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h index fe5d4851..6b4cb0de 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h @@ -46,6 +46,7 @@ private: bool ProcessOccupiedAreaChangeRegister(sptr listener, sptr window, bool isRegister); bool ProcessSystemBarChangeRegister(sptr listener, sptr window, bool isRegister); bool ProcessTouchOutsideRegister(sptr listener, sptr window, bool isRegister); + bool ProcessScreenshotRegister(sptr listener, sptr window, bool isRegister); using Func_t = bool(JsWindowRegisterManager::*)(sptr, sptr window, bool); std::map, sptr>> jsCbMap_; std::mutex mtx_; diff --git a/utils/include/display_change_listener.h b/utils/include/display_change_listener.h index abd0c7af..128e3dd0 100644 --- a/utils/include/display_change_listener.h +++ b/utils/include/display_change_listener.h @@ -36,6 +36,7 @@ public: virtual void OnDisplayStateChange(DisplayId defaultDisplayId, sptr info, const std::map>& displayInfoMap, DisplayStateChangeType type) = 0; virtual void OnGetWindowPreferredOrientation(DisplayId displayId, Orientation &orientation) = 0; + virtual void OnScreenshot(DisplayId displayId) = 0; }; } } diff --git a/utils/include/surface_capture_future.h b/utils/include/surface_capture_future.h new file mode 100644 index 00000000..e3e16049 --- /dev/null +++ b/utils/include/surface_capture_future.h @@ -0,0 +1,55 @@ +/* + * 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 SURFACE_CAPTURE_FUTURE_H +#define SURFACE_CAPTURE_FUTURE_H + +#include "future.h" +#include "pixel_map.h" +#include "transaction/rs_render_service_client.h" + +namespace OHOS { +namespace Rosen { +class SurfaceCaptureFuture : public SurfaceCaptureCallback, public Future> { +public: + SurfaceCaptureFuture() = default; + ~SurfaceCaptureFuture() {}; + void OnSurfaceCapture(std::shared_ptr pixelmap) override + { + FutureCall(pixelmap); + } +protected: + void Call(std::shared_ptr pixelmap) override + { + if (!flag_) { + pixelMap_ = pixelmap; + flag_ = true; + } + } + bool IsReady() override + { + return flag_; + } + std::shared_ptr FetchResult() override + { + return pixelMap_; + } +private: + bool flag_ = false; + std::shared_ptr pixelMap_ = nullptr; +}; +} // Rosen +} // OHOS +#endif // SURFACE_CAPTURE_FUTURE_H \ No newline at end of file diff --git a/wm/BUILD.gn b/wm/BUILD.gn index b8f2ee18..b22236c2 100644 --- a/wm/BUILD.gn +++ b/wm/BUILD.gn @@ -83,6 +83,7 @@ ohos_shared_library("libwm") { "input:libmmi-client", "inputmethod_native:inputmethod_client", "ipc:ipc_core", + "multimedia_image_standard:image", "multimedia_image_standard:image_native", "napi:ace_napi", diff --git a/wm/include/window_agent.h b/wm/include/window_agent.h index 78a350bf..c126584e 100644 --- a/wm/include/window_agent.h +++ b/wm/include/window_agent.h @@ -39,6 +39,7 @@ public: void UpdateActiveStatus(bool isActive) override; sptr GetWindowProperty() override; void NotifyTouchOutside() override; + void NotifyScreenshot() override; void DumpInfo(const std::vector& params, std::vector& info) override; private: sptr window_; diff --git a/wm/include/window_impl.h b/wm/include/window_impl.h index 9b1ebe97..8ee30a5e 100644 --- a/wm/include/window_impl.h +++ b/wm/include/window_impl.h @@ -193,6 +193,8 @@ public: virtual void RegisterTouchOutsideListener(const sptr& listener) override; virtual void UnregisterTouchOutsideListener(const sptr& listener) override; virtual void RegisterAnimationTransitionController(const sptr& listener) override; + virtual void RegisterScreenshotListener(const sptr& listener) override; + virtual void UnregisterScreenshotListener(const sptr& listener) override; virtual void SetAceAbilityHandler(const sptr& handler) override; virtual void SetRequestModeSupportInfo(uint32_t modeSupportInfo) override; void UpdateRect(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason); @@ -220,6 +222,7 @@ public: void NotifyModeChange(WindowMode mode); void NotifyDragEvent(const PointInfo& point, DragEvent event); void NotifyTouchOutside(); + void NotifyScreenshot(); virtual WMError SetUIContent(const std::string& contentInfo, NativeEngine* engine, NativeValue* storage, bool isdistributed, AppExecFwk::Ability* ability) override; @@ -239,6 +242,7 @@ public: virtual ColorSpace GetColorSpace() override; virtual void DumpInfo(const std::vector& params, std::vector& info) override; + virtual std::shared_ptr Snapshot() override; void PostListenerTask(ListenerTaskCallback &&callback, Priority priority = Priority::LOW, const std::string taskName = ""); private: @@ -374,6 +378,7 @@ private: WindowState state_ { WindowState::STATE_INITIAL }; WindowTag windowTag_; sptr aceAbilityHandler_; + std::vector> screenshotListeners_; std::vector> touchOutsideListeners_; std::vector> lifecycleListeners_; std::vector> windowChangeListeners_; diff --git a/wm/include/zidl/window_interface.h b/wm/include/zidl/window_interface.h index e8836552..f227aaeb 100644 --- a/wm/include/zidl/window_interface.h +++ b/wm/include/zidl/window_interface.h @@ -41,6 +41,7 @@ public: TRANS_ID_UPDATE_ACTIVE_STATUS, TRANS_ID_GET_WINDOW_PROPERTY, TRANS_ID_NOTIFY_OUTSIDE_PRESSED, + TRANS_ID_NOTIFY_SCREEN_SHOT, TRANS_ID_DUMP_INFO, }; @@ -56,6 +57,7 @@ public: virtual void UpdateActiveStatus(bool isActive) = 0; virtual sptr GetWindowProperty() = 0; virtual void NotifyTouchOutside() = 0; + virtual void NotifyScreenshot() = 0; virtual void DumpInfo(const std::vector& params, std::vector& info) = 0; }; } // namespace Rosen diff --git a/wm/include/zidl/window_proxy.h b/wm/include/zidl/window_proxy.h index c0990ada..5c178544 100644 --- a/wm/include/zidl/window_proxy.h +++ b/wm/include/zidl/window_proxy.h @@ -40,6 +40,7 @@ public: void UpdateActiveStatus(bool isActive) override; sptr GetWindowProperty() override; void NotifyTouchOutside() override; + void NotifyScreenshot() override; void DumpInfo(const std::vector& params, std::vector& info) override; private: static inline BrokerDelegator delegator_; diff --git a/wm/src/window_agent.cpp b/wm/src/window_agent.cpp index 46c91c3d..4c97acf1 100644 --- a/wm/src/window_agent.cpp +++ b/wm/src/window_agent.cpp @@ -137,6 +137,16 @@ void WindowAgent::NotifyTouchOutside() window_->NotifyTouchOutside(); } +void WindowAgent::NotifyScreenshot() +{ + if (window_ == nullptr) { + WLOGFE("notify screenshot failed: window is null."); + return; + } + WLOGFI("called"); + window_->NotifyScreenshot(); +} + void WindowAgent::DumpInfo(const std::vector& params, std::vector& info) { if (window_ == nullptr) { diff --git a/wm/src/window_impl.cpp b/wm/src/window_impl.cpp index 1977c965..d9ffa8ec 100755 --- a/wm/src/window_impl.cpp +++ b/wm/src/window_impl.cpp @@ -20,11 +20,13 @@ #include #include -#include "ipc_skeleton.h" +#include +#include #include "color_parser.h" #include "display_manager.h" #include "singleton_container.h" +#include "surface_capture_future.h" #include "window_adapter.h" #include "window_agent.h" #include "window_helper.h" @@ -41,8 +43,8 @@ namespace { } const WindowImpl::ColorSpaceConvertMap WindowImpl::colorSpaceConvertMap[] = { - { ColorSpace::COLOR_SPACE_DEFAULT, COLOR_GAMUT_SRGB }, - { ColorSpace::COLOR_SPACE_WIDE_GAMUT, COLOR_GAMUT_DCI_P3 }, + { ColorSpace::COLOR_SPACE_DEFAULT, ColorGamut::COLOR_GAMUT_SRGB }, + { ColorSpace::COLOR_SPACE_WIDE_GAMUT, ColorGamut::COLOR_GAMUT_DCI_P3 }, }; std::map>> WindowImpl::windowMap_; @@ -546,6 +548,20 @@ ColorSpace WindowImpl::GetColorSpace() return GetColorSpaceFromSurfaceGamut(surfaceGamut); } +std::shared_ptr WindowImpl::Snapshot() +{ + WLOGFI("WMS-Clinet Snapshot"); + std::shared_ptr callback = std::make_shared(); + RSInterfaces::GetInstance().TakeSurfaceCapture(surfaceNode_, callback); + std::shared_ptr pixelMap = callback->GetResult(2000); // wait for <= 2000ms + if (pixelMap != nullptr) { + WLOGFI("WMS-Clinet Save WxH = %{public}dx%{public}d", pixelMap->GetWidth(), pixelMap->GetHeight()); + } else { + WLOGFE("Failed to get pixelmap, return nullptr!"); + } + return pixelMap; +} + void WindowImpl::DumpInfo(const std::vector& params, std::vector& info) { if (params.size() == 1 && params[0] == PARAM_DUMP_HELP) { // 1: params num @@ -1662,6 +1678,7 @@ void WindowImpl::RegisterTouchOutsideListener(const sptr& void WindowImpl::UnregisterTouchOutsideListener(const sptr& listener) { + std::lock_guard lock(mutex_); touchOutsideListeners_.erase(std::remove_if(touchOutsideListeners_.begin(), touchOutsideListeners_.end(), [listener](sptr registeredListener) { return registeredListener == listener; @@ -1677,6 +1694,30 @@ void WindowImpl::RegisterAnimationTransitionController(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener is nullptr"); + return; + } + std::lock_guard lock(mutex_); + if (std::find(screenshotListeners_.begin(), screenshotListeners_.end(), listener) != + screenshotListeners_.end()) { + WLOGFE("Listener already registered"); + return; + } + screenshotListeners_.emplace_back(listener); +} + +void WindowImpl::UnregisterScreenshotListener(const sptr& listener) +{ + std::lock_guard lock(mutex_); + screenshotListeners_.erase(std::remove_if(screenshotListeners_.begin(), + screenshotListeners_.end(), [listener](sptr registeredListener) { + return registeredListener == listener; + }), screenshotListeners_.end()); +} + void WindowImpl::SetAceAbilityHandler(const sptr& handler) { if (handler == nullptr) { @@ -2347,6 +2388,22 @@ void WindowImpl::UpdateActiveStatus(bool isActive) } } +void WindowImpl::NotifyScreenshot() +{ + std::vector> screenshotListeners; + { + std::lock_guard lock(mutex_); + screenshotListeners = screenshotListeners_; + } + PostListenerTask([screenshotListeners]() { + for (auto& screenshotListener : screenshotListeners) { + if (screenshotListener != nullptr) { + screenshotListener->OnScreenshot(); + } + } + }); +} + void WindowImpl::NotifyTouchOutside() { std::vector> touchOutsideListeners; diff --git a/wm/src/zidl/window_proxy.cpp b/wm/src/zidl/window_proxy.cpp index 1d3cd3e4..2412dce1 100644 --- a/wm/src/zidl/window_proxy.cpp +++ b/wm/src/zidl/window_proxy.cpp @@ -277,6 +277,22 @@ void WindowProxy::NotifyTouchOutside() } } +void WindowProxy::NotifyScreenshot() +{ + MessageParcel data; + MessageParcel replay; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_NOTIFY_SCREEN_SHOT), + data, replay, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + void WindowProxy::DumpInfo(const std::vector& params, std::vector& info) { MessageParcel data; diff --git a/wm/src/zidl/window_stub.cpp b/wm/src/zidl/window_stub.cpp index fdb2ae7d..00b85fd8 100644 --- a/wm/src/zidl/window_stub.cpp +++ b/wm/src/zidl/window_stub.cpp @@ -99,6 +99,10 @@ int WindowStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParce NotifyTouchOutside(); break; } + case WindowMessage::TRANS_ID_NOTIFY_SCREEN_SHOT: { + NotifyScreenshot(); + break; + } case WindowMessage::TRANS_ID_DUMP_INFO: { std::vector params; if (!data.ReadStringVector(¶ms)) { diff --git a/wm/test/fuzztest/window_fuzzer/BUILD.gn b/wm/test/fuzztest/window_fuzzer/BUILD.gn index c2fac720..e9ad4eb7 100644 --- a/wm/test/fuzztest/window_fuzzer/BUILD.gn +++ b/wm/test/fuzztest/window_fuzzer/BUILD.gn @@ -36,8 +36,10 @@ ohos_fuzztest("WindowFuzzTest") { "//foundation/windowmanager/wm:libwm", "//utils/native/base:utils", ] - - external_deps = [ "ipc:ipc_core" ] + external_deps = [ + "ipc:ipc_core", + "multimedia_image_standard:image", + ] } ############################################################################### diff --git a/wm/test/unittest/avoid_area_controller_test.cpp b/wm/test/unittest/avoid_area_controller_test.cpp index 84cce068..a7bd9aef 100644 --- a/wm/test/unittest/avoid_area_controller_test.cpp +++ b/wm/test/unittest/avoid_area_controller_test.cpp @@ -69,6 +69,7 @@ public: return nullptr; } void NotifyTouchOutside() override {} + void NotifyScreenshot() override {} void DumpInfo(const std::vector& params, std::vector& info) override {} RunnableFuture statusBarAvoidAreaFuture_; RunnableFuture keyboardAvoidAreaFuture_; diff --git a/wmserver/include/window_controller.h b/wmserver/include/window_controller.h index 1308713c..2bab9012 100644 --- a/wmserver/include/window_controller.h +++ b/wmserver/include/window_controller.h @@ -63,6 +63,7 @@ public: void MinimizeWindowsByLauncher(std::vector& windowIds, bool isAnimated, sptr& finishCallback); Orientation GetWindowPreferredOrientation(DisplayId displayId); + void OnScreenshot(DisplayId displayId); private: uint32_t GenWindowId(); void FlushWindowInfo(uint32_t windowId); @@ -87,6 +88,8 @@ private: void NotifyTouchOutside(const sptr& node); uint32_t GetEmbedNodeId(const std::vector>& windowNodes, const sptr& node); void NotifyWindowPropertyChanged(const sptr& node); + WMError GetFocusWindowNode(DisplayId displayId, sptr& windowNode); + sptr windowRoot_; sptr inputWindowMonitor_; std::atomic windowId_ { INVALID_WINDOW_ID }; diff --git a/wmserver/include/window_manager_service.h b/wmserver/include/window_manager_service.h index d59ef1c6..3a83e079 100644 --- a/wmserver/include/window_manager_service.h +++ b/wmserver/include/window_manager_service.h @@ -44,6 +44,7 @@ public: virtual void OnDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, const std::map>& displayInfoMap, DisplayStateChangeType type) override; virtual void OnGetWindowPreferredOrientation(DisplayId displayId, Orientation &orientation) override; + virtual void OnScreenshot(DisplayId displayId) override; }; class WindowManagerServiceHandler : public AAFwk::WindowManagerServiceHandlerStub { @@ -108,6 +109,7 @@ public: void GetWindowPreferredOrientation(DisplayId displayId, Orientation &orientation); void OnAccountSwitched() const; WMError UpdateRsTree(uint32_t windowId, bool isAdd) override; + void OnScreenshot(DisplayId displayId); protected: WindowManagerService(); virtual ~WindowManagerService() = default; diff --git a/wmserver/include/window_snapshot/snapshot_controller.h b/wmserver/include/window_snapshot/snapshot_controller.h index f45dfb0f..cf7cf3c4 100644 --- a/wmserver/include/window_snapshot/snapshot_controller.h +++ b/wmserver/include/window_snapshot/snapshot_controller.h @@ -19,8 +19,8 @@ #include #include #include "future.h" -#include "window_root.h" #include "snapshot_stub.h" +#include "window_root.h" #include "window_manager_hilog.h" namespace OHOS { @@ -42,35 +42,6 @@ private: RSInterfaces& rsInterface_; WMError TakeSnapshot(const std::shared_ptr& surfaceNode, AAFwk::Snapshot& snapshot); - - class GetSurfaceCapture : public SurfaceCaptureCallback, public Future> { - public: - GetSurfaceCapture() = default; - ~GetSurfaceCapture() {}; - void OnSurfaceCapture(std::shared_ptr pixelmap) override - { - FutureCall(pixelmap); - } - protected: - void Call(std::shared_ptr pixelmap) override - { - if (!flag_) { - pixelMap_ = pixelmap; - flag_ = true; - } - } - bool IsReady() override - { - return flag_; - } - std::shared_ptr FetchResult() override - { - return pixelMap_; - } - private: - bool flag_ = false; - std::shared_ptr pixelMap_ = nullptr; - }; }; } } diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index f62a70d8..693acba7 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -148,25 +148,35 @@ WMError WindowController::NotifyWindowTransition(sptr& src return WMError::WM_OK; } -WMError WindowController::GetFocusWindowInfo(sptr& abilityToken) +WMError WindowController::GetFocusWindowNode(DisplayId displayId, sptr& windowNode) { - DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); if (windowNodeContainer == nullptr) { WLOGFE("windowNodeContainer is null, displayId: %{public}" PRIu64"", displayId); return WMError::WM_ERROR_NULLPTR; } uint32_t focusWindowId = windowNodeContainer->GetFocusWindow(); - auto windowNode = windowRoot_->GetWindowNode(focusWindowId); - if (windowNode == nullptr || !windowNode->currentVisibility_) { + WLOGFI("focusWindowId: %{public}u", focusWindowId); + auto thisWindowNode = windowRoot_->GetWindowNode(focusWindowId); + if (thisWindowNode == nullptr || !thisWindowNode->currentVisibility_) { WLOGFE("focusWindowNode is null or invisible, focusWindowId: %{public}u", focusWindowId); return WMError::WM_ERROR_INVALID_WINDOW; } - abilityToken = windowNode->abilityToken_; - WLOGFI("focusWindowId: %{public}u", focusWindowId); + windowNode = thisWindowNode; return WMError::WM_OK; } +WMError WindowController::GetFocusWindowInfo(sptr& abilityToken) +{ + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + sptr windowNode; + WMError res = GetFocusWindowNode(displayId, windowNode); + if (res == WMError::WM_OK) { + abilityToken = windowNode->abilityToken_; + } + return res; +} + WMError WindowController::CreateWindow(sptr& window, sptr& property, const std::shared_ptr& surfaceNode, uint32_t& windowId, sptr token, int32_t pid, int32_t uid) @@ -1045,5 +1055,20 @@ Orientation WindowController::GetWindowPreferredOrientation(DisplayId displayId) } return Orientation::UNSPECIFIED; } + +void WindowController::OnScreenshot(DisplayId displayId) +{ + sptr windowNode; + WMError res = GetFocusWindowNode(displayId, windowNode); + if (res != WMError::WM_OK) { + return; + } + auto windowToken = windowNode->GetWindowToken(); + if (windowToken == nullptr) { + WLOGFE("notify screenshot failed: window token is null."); + return; + } + windowToken->NotifyScreenshot(); +} } // namespace OHOS } // namespace Rosen diff --git a/wmserver/src/window_manager_service.cpp b/wmserver/src/window_manager_service.cpp index 2e92fcb5..cd55527b 100644 --- a/wmserver/src/window_manager_service.cpp +++ b/wmserver/src/window_manager_service.cpp @@ -548,6 +548,11 @@ void DisplayChangeListener::OnGetWindowPreferredOrientation(DisplayId displayId, WindowManagerService::GetInstance().GetWindowPreferredOrientation(displayId, orientation); } +void DisplayChangeListener::OnScreenshot(DisplayId displayId) +{ + WindowManagerService::GetInstance().OnScreenshot(displayId); +} + void WindowManagerService::ProcessPointDown(uint32_t windowId, bool isStartDrag) { return wmsTaskLooper_->PostTask([this, windowId, isStartDrag]() { @@ -685,5 +690,12 @@ WMError WindowManagerService::UpdateRsTree(uint32_t windowId, bool isAdd) return windowRoot_->UpdateRsTree(windowId, isAdd); }).get(); } + +void WindowManagerService::OnScreenshot(DisplayId displayId) +{ + wmsTaskLooper_->PostTask([this, displayId]() { + windowController_->OnScreenshot(displayId); + }); +} } // namespace Rosen } // namespace OHOS diff --git a/wmserver/src/window_snapshot/snapshot_controller.cpp b/wmserver/src/window_snapshot/snapshot_controller.cpp index c11638be..f9bc727c 100644 --- a/wmserver/src/window_snapshot/snapshot_controller.cpp +++ b/wmserver/src/window_snapshot/snapshot_controller.cpp @@ -17,6 +17,7 @@ #include +#include "surface_capture_future.h" #include "window_manager_hilog.h" #include "wm_common.h" @@ -33,11 +34,9 @@ void SnapshotController::Init(sptr& root) WMError SnapshotController::TakeSnapshot(const std::shared_ptr& surfaceNode, Snapshot& snapshot) { - std::shared_ptr callback = std::make_shared(); + std::shared_ptr callback = std::make_shared(); rsInterface_.TakeSurfaceCapture(surfaceNode, callback, scaleW, scaleH); - - std::shared_ptr pixelMap = callback->GetResult(2000); // wait for 2000ms - + std::shared_ptr pixelMap = callback->GetResult(2000); // wait for <= 2000ms if (pixelMap == nullptr) { WLOGFE("Failed to get pixelmap, return nullptr!"); return WMError::WM_ERROR_NULLPTR;