From dd11bafd4f753928857e84ce8d94048c5a05d99c Mon Sep 17 00:00:00 2001 From: chyyy0213 Date: Thu, 15 Sep 2022 18:27:57 +0800 Subject: [PATCH] add continuous start and exit Signed-off-by: chyyy0213 Change-Id: Ic81a763e4a14ff3f8dd8313c01f74d194c7a0769 Signed-off-by: chyyy0213 --- utils/include/surface_draw.h | 6 +- utils/src/surface_draw.cpp | 20 +- wmserver/BUILD.gn | 1 + wmserver/include/minimize_app.h | 3 +- wmserver/include/remote_animation.h | 21 + wmserver/include/window_controller.h | 2 +- wmserver/include/window_inner_manager.h | 2 + wmserver/include/window_node.h | 19 +- wmserver/include/window_node_container.h | 8 +- wmserver/include/window_node_state_machine.h | 103 ++++ wmserver/include/window_root.h | 6 +- wmserver/src/minimize_app.cpp | 27 +- wmserver/src/remote_animation.cpp | 515 +++++++++++++++---- wmserver/src/starting_window.cpp | 9 +- wmserver/src/window_controller.cpp | 42 +- wmserver/src/window_dumper.cpp | 1 + wmserver/src/window_inner_manager.cpp | 48 +- wmserver/src/window_manager_service.cpp | 60 ++- wmserver/src/window_node.cpp | 18 - wmserver/src/window_node_container.cpp | 73 ++- wmserver/src/window_node_state_machine.cpp | 158 ++++++ wmserver/src/window_root.cpp | 66 ++- wmserver/test/unittest/minimize_app_test.cpp | 2 +- 23 files changed, 976 insertions(+), 234 deletions(-) create mode 100644 wmserver/include/window_node_state_machine.h create mode 100644 wmserver/src/window_node_state_machine.cpp diff --git a/utils/include/surface_draw.h b/utils/include/surface_draw.h index 205e89c043..48d78147f4 100644 --- a/utils/include/surface_draw.h +++ b/utils/include/surface_draw.h @@ -38,7 +38,7 @@ public: static bool DrawImage(std::shared_ptr surfaceNode, int32_t bufferWidth, int32_t bufferHeight, std::shared_ptr pixelMap); static bool DrawImageRect(std::shared_ptr surfaceNode, Rect winRect, - std::shared_ptr pixelMap, uint32_t bkgColor); + std::shared_ptr pixelMap, uint32_t bkgColor, bool fillWindow = false); static bool GetSurfaceSnapshot(const std::shared_ptr surfaceNode, std::shared_ptr& pixelMap, int32_t timeoutMs, float scaleW = 0.5, float scaleH = 0.5); static bool DrawMasking(std::shared_ptr surfaceNode, Rect screenRect, @@ -53,8 +53,8 @@ private: int32_t bufferHeight); static void DrawPixelmap(Drawing::Canvas &canvas, const std::string& imagePath); static std::unique_ptr DecodeImageToPixelMap(const std::string &imagePath); - static bool DoDrawImageRect(uint8_t *addr, const Rect rect, std::shared_ptr pixelMap, - uint32_t color, int32_t bufferStride); + static bool DoDrawImageRect(sptr buffer, const Rect& rect, + std::shared_ptr pixelMap, uint32_t color, bool fillWindow = false); }; } // Rosen } // OHOS diff --git a/utils/src/surface_draw.cpp b/utils/src/surface_draw.cpp index f1fc4e7aa7..4a7e1d2308 100644 --- a/utils/src/surface_draw.cpp +++ b/utils/src/surface_draw.cpp @@ -263,7 +263,7 @@ bool SurfaceDraw::DoDraw(uint8_t *addr, uint32_t width, uint32_t height, uint32_ } bool SurfaceDraw::DrawImageRect(std::shared_ptr surfaceNode, Rect rect, - std::shared_ptr pixelMap, uint32_t color) + std::shared_ptr pixelMap, uint32_t color, bool fillWindow) { int32_t winHeight = static_cast(rect.height_); int32_t winWidth = static_cast(rect.width_); @@ -276,8 +276,7 @@ bool SurfaceDraw::DrawImageRect(std::shared_ptr surfaceNode, Rect if (buffer == nullptr || buffer->GetVirAddr() == nullptr) { return false; } - auto addr = static_cast(buffer->GetVirAddr()); - if (!DoDrawImageRect(addr, rect, pixelMap, color, buffer->GetStride())) { + if (!DoDrawImageRect(buffer, rect, pixelMap, color, fillWindow)) { WLOGE("draw image rect failed."); return false; } @@ -295,12 +294,13 @@ bool SurfaceDraw::DrawImageRect(std::shared_ptr surfaceNode, Rect return true; } -bool SurfaceDraw::DoDrawImageRect(uint8_t *addr, const Rect rect, std::shared_ptr pixelMap, - uint32_t color, int32_t bufferStride) +bool SurfaceDraw::DoDrawImageRect(sptr buffer, const Rect& rect, + std::shared_ptr pixelMap, uint32_t color, bool fillWindow) { int32_t winWidth = static_cast(rect.width_); int32_t winHeight = static_cast(rect.height_); // actual width of the surface buffer after alignment + auto bufferStride = buffer->GetStride(); int32_t alignWidth = bufferStride / static_cast(IMAGE_BYTES_STRIDE); WLOGFD("drawing image rect win width: %{public}d win height: %{public}d align width:%{public}d.", winWidth, winHeight, alignWidth); @@ -312,16 +312,21 @@ bool SurfaceDraw::DoDrawImageRect(uint8_t *addr, const Rect rect, std::shared_pt WLOGFE("drawing pixel map failed, because width or height is invalid."); return false; } - float xAxis = static_cast(alignWidth) / pixelMap->GetWidth(); + float xAxis = static_cast(winWidth) / pixelMap->GetWidth(); float yAxis = static_cast(winHeight) / pixelMap->GetHeight(); float axis = std::min(xAxis, yAxis); if (axis < 1.0) { // scale when the size of the pixel map is larger than the window // use axis to scale equally pixelMap->scale(axis, axis); + } else if (fillWindow) { + // scale snapshot to whole window + pixelMap->scale(xAxis, yAxis); } - int left = (alignWidth - pixelMap->GetWidth()) / 2; // 2 is the left and right boundaries of the window + int left = (winWidth - pixelMap->GetWidth()) / 2; // 2 is the left and right boundaries of the window int top = (winHeight - pixelMap->GetHeight()) / 2; // 2 is the top and bottom boundaries of the window + WLOGFD("pixelMap width: %{public}d win height: %{public}d left:%{public}d top:%{public}d.", + pixelMap->GetWidth(), pixelMap->GetHeight(), left, top); Drawing::Bitmap bitmap; Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_OPAQUE }; @@ -333,6 +338,7 @@ bool SurfaceDraw::DoDrawImageRect(uint8_t *addr, const Rect rect, std::shared_pt // bufferSize is actual size of the surface buffer after alignment int32_t bufferSize = bufferStride * winHeight; uint8_t* bitmapAddr = static_cast(bitmap.GetPixels()); + auto addr = static_cast(buffer->GetVirAddr()); errno_t ret = memcpy_s(addr, bufferSize, bitmapAddr, bufferSize); if (ret != EOK) { WLOGFE("draw image rect failed, because copy bitmap to buffer failed."); diff --git a/wmserver/BUILD.gn b/wmserver/BUILD.gn index b7df9d1952..6b24da82ae 100644 --- a/wmserver/BUILD.gn +++ b/wmserver/BUILD.gn @@ -56,6 +56,7 @@ ohos_shared_library("libwms") { "src/window_manager_service.cpp", "src/window_node.cpp", "src/window_node_container.cpp", + "src/window_node_state_machine.cpp", "src/window_pair.cpp", "src/window_root.cpp", "src/window_snapshot/snapshot_controller.cpp", diff --git a/wmserver/include/minimize_app.h b/wmserver/include/minimize_app.h index 551c074461..f5eb1e4b24 100644 --- a/wmserver/include/minimize_app.h +++ b/wmserver/include/minimize_app.h @@ -48,8 +48,9 @@ public: static void SetMinimizedByOtherConfig(bool isMinimizedByOther); static void ClearNodesWithReason(MinimizeReason reason); static bool IsNodeNeedMinimize(const sptr& node); - static std::vector> GetNeedMinimizeAppNodes(); + static std::vector> GetNeedMinimizeAppNodesWithReason(MinimizeReason reason); static sptr GetRecoverdNodeFromMinimizeList(); + static bool IsNodeNeedMinimizeWithReason(const sptr& node, MinimizeReason reason); private: static inline bool IsFromUser(MinimizeReason reason) diff --git a/wmserver/include/remote_animation.h b/wmserver/include/remote_animation.h index cda7ea83ed..669fa02d5c 100644 --- a/wmserver/include/remote_animation.h +++ b/wmserver/include/remote_animation.h @@ -22,6 +22,7 @@ #include #include "wm_common.h" +#include "window_controller.h" #include "window_node.h" #include "window_root.h" #include "window_transition_info.h" @@ -61,6 +62,14 @@ public: static void SetMainTaskHandler(std::shared_ptr handler); static void NotifyAnimationTargetsUpdate(std::vector& fullScreenWinIds, std::vector& floatWinIds); + static void SetAnimationFirst(bool animationFirst); + static void SetWindowController(const sptr& windowController); + static bool IsRemoteAnimationEnabledAndFirst(DisplayId displayId = 0); + static void CallbackTimeOutProcess(); + static inline bool IsAnimationFirst() + { + return animationFirst_; + } static bool isRemoteAnimationEnable_; private: static sptr CreateWindowAnimationTarget(sptr info, @@ -68,9 +77,21 @@ private: static WMError NotifyAnimationStartApp(sptr srcInfo, const sptr& srcNode, const sptr& dstNode, sptr& dstTarget, sptr& finishedCallback); + static sptr CreateShowAnimationFinishedCallback( + const sptr& srcNode, const sptr& dstNode); + static sptr CreateHideAnimationFinishedCallback( + const sptr& srcNode, TransitionEvent event); + static void ProcessNodeStateTask(const sptr& node); + static void GetExpectRect(const sptr& dstNode, const sptr& dstTarget); + static void PostProcessShowCallback(const sptr& node); + static void PostFinalStateTask(const sptr& node); + static void GetAnimationTargetsForHome(std::vector>& animationTargets, + std::vector> needMinimizeAppNodes); static sptr windowAnimationController_; static wptr windowRoot_; static std::weak_ptr wmsTaskHandler_; + static wptr windowController_; + static bool animationFirst_; }; } // Rosen } // OHOS diff --git a/wmserver/include/window_controller.h b/wmserver/include/window_controller.h index 41235f8b81..7ca59f7f11 100644 --- a/wmserver/include/window_controller.h +++ b/wmserver/include/window_controller.h @@ -41,7 +41,7 @@ public: const std::shared_ptr& surfaceNode, uint32_t& windowId, sptr token, int32_t pid, int32_t uid); WMError AddWindowNode(sptr& property); - WMError RemoveWindowNode(uint32_t windowId); + WMError RemoveWindowNode(uint32_t windowId, bool fromAnimation = false); WMError NotifyWindowTransition(sptr& fromInfo, sptr& toInfo); WMError GetFocusWindowInfo(sptr& abilityToken); WMError DestroyWindow(uint32_t windowId, bool onlySelf); diff --git a/wmserver/include/window_inner_manager.h b/wmserver/include/window_inner_manager.h index 3708ffb11c..9a16ebc4cb 100644 --- a/wmserver/include/window_inner_manager.h +++ b/wmserver/include/window_inner_manager.h @@ -49,6 +49,8 @@ public: // asynchronously calls the functions of AbilityManager void MinimizeAbility(const wptr &node, bool isFromUser); + void TerminateAbility(const wptr &node); + void CloseAbility(const wptr &node); void ConsumePointerEvent(const std::shared_ptr& pointerEvent); void NotifyDisplayChange(const std::map& displayRectMap); diff --git a/wmserver/include/window_node.h b/wmserver/include/window_node.h index b5de082518..48ce3c6470 100644 --- a/wmserver/include/window_node.h +++ b/wmserver/include/window_node.h @@ -22,21 +22,10 @@ #include #include "zidl/window_interface.h" #include "window_manager_hilog.h" +#include "window_node_state_machine.h" namespace OHOS { namespace Rosen { -enum class WindowNodeState : uint32_t { - INITIAL, - STARTING_CREATED, - SHOW_ANIMATION_PLAYING, - SHOW_ANIMATION_DONE, - HIDE_ANIMATION_PLAYING, - HIDE_ANIMATION_DONE, - SHOWN, - HIDDEN, - DESTROYED -}; - class WindowNode : public RefBase { public: WindowNode(const sptr& property, const sptr& window, @@ -130,8 +119,6 @@ public: uint32_t GetAccessTokenId() const; WindowSizeLimits GetWindowSizeLimits() const; WindowSizeLimits GetWindowUpdatedSizeLimits() const; - bool IsWindowNodeShownOrShowing(); - bool IsWindowNodeHiddenOrHiding(); bool EnableDefaultAnimation(bool propertyEnabled, bool animationPlayed); sptr parent_; @@ -151,10 +138,12 @@ public: bool isPlayAnimationShow_ { false }; // delete when enable state machine bool isPlayAnimationHide_ { false }; // delete when enable state machine bool startingWindowShown_ { false }; + bool firstFrameAvaliable_ { false }; bool isShowingOnMultiDisplays_ { false }; std::vector showingDisplays_; AbilityInfo abilityInfo_; - WindowNodeState state_ = WindowNodeState::INITIAL; + WindowNodeStateMachine stateMachine_; + private: sptr property_ = nullptr; sptr windowToken_ = nullptr; diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index de2f766b8b..18dd38387e 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -38,8 +38,8 @@ public: WindowNodeContainer(const sptr& displayInfo, ScreenId displayGroupId); ~WindowNodeContainer(); WMError ShowStartingWindow(sptr& node); - WMError AddWindowNode(sptr& node, sptr& parentNode); - WMError RemoveWindowNode(sptr& node); + WMError AddWindowNode(sptr& node, sptr& parentNode, bool afterAnimation = false); + WMError RemoveWindowNode(sptr& node, bool fromAnimation = false); WMError HandleRemoveWindow(sptr& node); WMError UpdateWindowNode(sptr& node, WindowUpdateReason reason); WMError DestroyWindowNode(sptr& node, std::vector& windowIds); @@ -123,7 +123,7 @@ public: bool TakeWindowPairSnapshot(DisplayId displayId); void ClearWindowPairSnapshot(DisplayId displayId); bool IsScreenLocked(); - + void LayoutWhenAddWindowNode(sptr& node, bool afterAnimation = false); private: void TraverseWindowNode(sptr& root, std::vector>& windowNodes) const; sptr FindRoot(WindowType type) const; @@ -161,7 +161,7 @@ private: const std::vector& lastShowingDisplays); bool CheckWindowNodeWhetherInWindowTree(const sptr& node) const; void UpdateModeSupportInfoWhenKeyguardChange(const sptr& node, bool up); - + void RemoveFromRsTreeWhenRemoveWindowNode(sptr& node, bool fromAnimation); float displayBrightness_ = UNDEFINED_BRIGHTNESS; uint32_t brightnessWindow_ = INVALID_WINDOW_ID; uint32_t zOrder_ { 0 }; diff --git a/wmserver/include/window_node_state_machine.h b/wmserver/include/window_node_state_machine.h new file mode 100644 index 0000000000..19f19522e6 --- /dev/null +++ b/wmserver/include/window_node_state_machine.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 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_WINDOW_NODE_STATE_MACHINE_H +#define OHOS_ROSEN_WINDOW_NODE_STATE_MACHINE_H + +#include +#include +#include +#include +#include +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + using StateTask = std::function; +} +enum class WindowNodeState : uint32_t { + INITIAL, + STARTING_CREATED, + SHOW_ANIMATION_PLAYING, + SHOW_ANIMATION_DONE, + HIDE_ANIMATION_PLAYING, + HIDE_ANIMATION_DONE, + SHOWN, + HIDDEN, + DESTROYED +}; + +class WindowNodeStateMachine { +public: + WindowNodeStateMachine(); + + ~WindowNodeStateMachine(); + + void TransitionTo(WindowNodeState state); + + void UpdateAnimationTaskCount(bool isAdd); + + int32_t GetAnimationCount(); + + bool IsWindowNodeShownOrShowing(); + + bool IsRemoteAnimationPlaying(); + + bool IsWindowNodeHiddenOrHiding(); + + WindowNodeState GetCurrentState(); + + bool IsShowAnimationPlaying(); + + bool IsHideAnimationPlaying(); + + void SetDestroyTaskParam(bool onlySelf); + + bool GetDestroyTaskParam(); + + void SetDestroyTask(StateTask task); + + bool GetDestroyTask(StateTask& task); + + void ResetAnimationTaskCount(int32_t taskCount); + + // test + void SetWindowId(uint32_t id) + { + windowId_ = id; + } + + void SetWindowType(WindowType type) + { + type_ = type; + } + +private: + std::deque> stateTaskQ_; + WindowNodeState currState_ = WindowNodeState::INITIAL; + int32_t taskCount_ = 0; + std::recursive_mutex mutex_; + bool destroyOnlySelf_ = true; + // just for test + uint32_t windowId_ = 0; + WindowType type_ { WindowType::WINDOW_TYPE_APP_MAIN_WINDOW }; + uint32_t count1 = 0; + uint32_t count2 = 0; + StateTask destroyTask_; +}; +} // namespace Rosen +} // namespace OHOS +#endif \ No newline at end of file diff --git a/wmserver/include/window_root.h b/wmserver/include/window_root.h index ba0f4ee304..78ca7ebd37 100644 --- a/wmserver/include/window_root.h +++ b/wmserver/include/window_root.h @@ -21,6 +21,7 @@ #include "agent_death_recipient.h" #include "display_manager_service_inner.h" +#include "parameters.h" #include "window_node_container.h" #include "zidl/window_manager_agent_interface.h" @@ -47,7 +48,7 @@ public: void AddDeathRecipient(sptr node); sptr FindWindowNodeWithToken(const sptr& token) const; WMError AddWindowNode(uint32_t parentId, sptr& node, bool fromStartingWin = false); - WMError RemoveWindowNode(uint32_t windowId); + WMError RemoveWindowNode(uint32_t windowId, bool fromAnimation = false); WMError DestroyWindow(uint32_t windowId, bool onlySelf); WMError UpdateWindowNode(uint32_t windowId, WindowUpdateReason reason); bool IsVerticalDisplay(sptr& node) const; @@ -113,7 +114,8 @@ public: { return renderMode_ == RenderMode::UNIFIED; } - + void LayoutWhenAddWindowNode(sptr& node, bool afterAnimation = false); + void GetAllAnimationPlayingNodes(std::vector>& windowNodes); private: enum class RenderMode : uint8_t { SEPARATED, diff --git a/wmserver/src/minimize_app.cpp b/wmserver/src/minimize_app.cpp index 1967fff934..7992bcd4ea 100644 --- a/wmserver/src/minimize_app.cpp +++ b/wmserver/src/minimize_app.cpp @@ -28,7 +28,6 @@ namespace { std::map>> MinimizeApp::needMinimizeAppNodes_; bool MinimizeApp::isMinimizedByOtherWindow_ = true; std::recursive_mutex MinimizeApp::mutex_; - void MinimizeApp::AddNeedMinimizeApp(const sptr& node, MinimizeReason reason) { std::lock_guard lock(mutex_); @@ -56,12 +55,12 @@ void MinimizeApp::AddNeedMinimizeApp(const sptr& node, MinimizeReaso needMinimizeAppNodes_[reason].emplace_back(weakNode); } -std::vector> MinimizeApp::GetNeedMinimizeAppNodes() +std::vector> MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason reason) { std::lock_guard lock(mutex_); std::vector> needMinimizeAppNodes; - for (auto& appNodes: needMinimizeAppNodes_) { - for (auto& node : appNodes.second) { + if (needMinimizeAppNodes_.find(reason) != needMinimizeAppNodes_.end()) { + for (auto& node : needMinimizeAppNodes_[reason]) { needMinimizeAppNodes.emplace_back(node); } } @@ -122,6 +121,26 @@ bool MinimizeApp::IsNodeNeedMinimize(const sptr& node) return false; } +bool MinimizeApp::IsNodeNeedMinimizeWithReason(const sptr& node, MinimizeReason reason) +{ + if (node == nullptr) { + WLOGFE("[Minimize] node is nullptr"); + return false; + } + if (needMinimizeAppNodes_.find(reason) == needMinimizeAppNodes_.end()) { + WLOGFD("[Minimize] no need to minimize with id:%{public}u reason:%{public}u", + node->GetWindowId(), reason); + return false; + } + auto nodes = needMinimizeAppNodes_.at(reason); + if (std::find(nodes.begin(), nodes.end(), node) != nodes.end()) { + WLOGFI("[Minimize] id:%{public}u need to minimize with reason:%{public}u", + node->GetWindowId(), reason); + return true; + } + return false; +} + void MinimizeApp::ExecuteMinimizeTargetReason(MinimizeReason reason) { std::lock_guard lock(mutex_); diff --git a/wmserver/src/remote_animation.cpp b/wmserver/src/remote_animation.cpp index 1b839a7f9b..0da05ec9d8 100644 --- a/wmserver/src/remote_animation.cpp +++ b/wmserver/src/remote_animation.cpp @@ -20,6 +20,8 @@ #include #include #include "minimize_app.h" +#include "parameters.h" +#include "surface_draw.h" #include "window_helper.h" #include "window_inner_manager.h" #include "window_manager_hilog.h" @@ -34,6 +36,8 @@ bool RemoteAnimation::isRemoteAnimationEnable_ = true; sptr RemoteAnimation::windowAnimationController_ = nullptr; std::weak_ptr RemoteAnimation::wmsTaskHandler_; wptr RemoteAnimation::windowRoot_; +bool RemoteAnimation::animationFirst_ = false; +wptr RemoteAnimation::windowController_ = nullptr; std::map eventMap_ = { {TransitionReason::CLOSE, TransitionEvent::CLOSE}, @@ -41,6 +45,17 @@ std::map eventMap_ = { {TransitionReason::BACK, TransitionEvent::BACK} }; +void RemoteAnimation::SetAnimationFirst(bool animationFirst) +{ + animationFirst_ = animationFirst; + WLOGFI("RSWindowAnimation:animationFirst: %{public}u!", static_cast(animationFirst_)); +} + +bool RemoteAnimation::IsRemoteAnimationEnabledAndFirst(DisplayId displayId) +{ + return animationFirst_ && CheckRemoteAnimationEnabled(displayId); +} + WMError RemoteAnimation::SetWindowAnimationController(const sptr& controller, const sptr& windowRoot) { @@ -68,6 +83,11 @@ void RemoteAnimation::SetMainTaskHandler(std::shared_ptr& windowController) +{ + windowController_ = windowController; +} + bool RemoteAnimation::CheckAnimationController() { if (windowAnimationController_ == nullptr) { @@ -118,6 +138,9 @@ void RemoteAnimation::OnRemoteDie(const sptr& remoteObject) if (windowAnimationController_ != nullptr && windowAnimationController_->AsObject() == remoteObject) { windowAnimationController_ = nullptr; } + if (animationFirst_) { + CallbackTimeOutProcess(); + } } TransitionEvent RemoteAnimation::GetTransitionEvent(sptr srcInfo, @@ -125,9 +148,10 @@ TransitionEvent RemoteAnimation::GetTransitionEvent(sptr s { auto transitionReason = srcInfo->GetTransitionReason(); // src reason same as dst reason if (srcNode != nullptr && eventMap_.find(transitionReason) != eventMap_.end()) { - if (srcNode->IsWindowNodeHiddenOrHiding()) { - WLOGFE("window id:%{public}u is already hiding or hidden with state:%{public}u", - srcNode->GetWindowId(), static_cast(srcNode->state_)); + WLOGFI("current window:%{public}u state: %{public}u", srcNode->GetWindowId(), + static_cast(srcNode->stateMachine_.GetCurrentState())); + if (srcNode->stateMachine_.IsWindowNodeHiddenOrHiding()) { + WLOGFE("srcNode is hiding or hidden id: %{public}u!", srcNode->GetWindowId()); return TransitionEvent::UNKNOWN; } return eventMap_[transitionReason]; @@ -139,10 +163,12 @@ TransitionEvent RemoteAnimation::GetTransitionEvent(sptr s } return TransitionEvent::UNKNOWN; } else { + WLOGFI("current window:%{public}u state: %{public}u", dstNode->GetWindowId(), + static_cast(dstNode->stateMachine_.GetCurrentState())); if (WindowHelper::IsMainWindow(dstInfo->GetWindowType())) { - if (dstNode->IsWindowNodeShownOrShowing()) { - WLOGFE("window id:%{public}u is already shown or showing with state:%{public}u", - dstNode->GetWindowId(), static_cast(dstNode->state_)); + if (dstNode->stateMachine_.IsWindowNodeShownOrShowing()) { + WLOGFE("dstNode is showing or shown id: %{public}d state:%{public}u!", + dstNode->GetWindowId(), static_cast(dstNode->stateMachine_.GetCurrentState())); return TransitionEvent::UNKNOWN; } return TransitionEvent::APP_TRANSITION; @@ -167,16 +193,12 @@ static sptr GetTransitionFinishedCallback(con } FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), "wms:async:ShowRemoteAnimation"); - if (!weakNode->IsWindowNodeShownOrShowing()) { - WLOGFI("node:%{public}u is not play show animation with state:%{public}d!", - weakNode->GetWindowId(), static_cast(weakNode->state_)); + if (!weakNode->stateMachine_.IsWindowNodeShownOrShowing()) { + WLOGFI("node:%{public}u is not play show animation with state:%{public}u!", weakNode->GetWindowId(), + static_cast(weakNode->stateMachine_.GetCurrentState())); return; } - auto weakSrcNode = weakSrc.promote(); - if (weakSrcNode) { - weakSrcNode->state_ = WindowNodeState::HIDE_ANIMATION_DONE; - } - MinimizeApp::ExecuteMinimizeAll(); + MinimizeApp::ExecuteMinimizeAll(); // minimize execute in show animation RSAnimationTimingProtocol timingProtocol(200); // animation time RSNode::Animate(timingProtocol, RSAnimationTimingCurve::EASE_OUT, [weakNode]() { auto winRect = weakNode->GetWindowRect(); @@ -189,7 +211,7 @@ static sptr GetTransitionFinishedCallback(con weakNode->leashWinSurfaceNode_->SetBounds( winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); RSTransaction::FlushImplicitTransaction(); - weakNode->state_ = WindowNodeState::SHOW_ANIMATION_DONE; + weakNode->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_DONE); }); }; sptr finishedCallback = new(std::nothrow) RSWindowAnimationFinishedCallback( @@ -201,6 +223,10 @@ WMError RemoteAnimation::NotifyAnimationStartApp(sptr srcI const sptr& srcNode, const sptr& dstNode, sptr& dstTarget, sptr& finishedCallback) { + if (animationFirst_) { + // From Recent also need to minimize window + MinimizeApp::ExecuteMinimizeAll(); + } // start app from launcher if (srcNode != nullptr && srcNode->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { WLOGFI("RSWindowAnimation: start app id:%{public}u from launcher!", dstNode->GetWindowId()); @@ -219,28 +245,8 @@ WMError RemoteAnimation::NotifyAnimationStartApp(sptr srcI return WMError::WM_OK; } -WMError RemoteAnimation::NotifyAnimationTransition(sptr srcInfo, - sptr dstInfo, const sptr& srcNode, - const sptr& dstNode) +void RemoteAnimation::GetExpectRect(const sptr& dstNode, const sptr& dstTarget) { - if (!dstNode || !dstNode->startingWindowShown_) { - WLOGFE("RSWindowAnimation: no startingWindow for dst window id:%{public}u!", dstNode->GetWindowId()); - return WMError::WM_ERROR_NO_REMOTE_ANIMATION; - } - WLOGFI("RSWindowAnimation: notify animation transition with dst currId:%{public}u!", dstNode->GetWindowId()); - auto finishedCallback = GetTransitionFinishedCallback(srcNode, dstNode); - if (finishedCallback == nullptr) { - WLOGFE("New RSIWindowAnimationFinishedCallback failed"); - return WMError::WM_ERROR_NO_MEM; - } - - auto dstTarget = CreateWindowAnimationTarget(dstInfo, dstNode); - if (dstTarget == nullptr) { - WLOGFE("RSWindowAnimation: Failed to create dst target!"); - finishedCallback->OnAnimationFinished(); - return WMError::WM_ERROR_NO_MEM; - } - dstNode->state_ = WindowNodeState::SHOW_ANIMATION_PLAYING; // when exit immersive, startingWindow (0,0,w,h), but app need avoid bool needAvoid = (dstNode->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); auto winRoot = windowRoot_.promote(); @@ -254,22 +260,55 @@ WMError RemoteAnimation::NotifyAnimationTransition(sptr sr auto boundsRect = RectF(avoidRect.posX_, avoidRect.posY_, avoidRect.width_, avoidRect.height_); dstTarget->windowBounds_ = RRect(boundsRect, stagingProperties.GetCornerRadius()); if (dstNode->leashWinSurfaceNode_) { - dstNode->leashWinSurfaceNode_->SetBounds( - avoidRect.posX_, avoidRect.posY_, avoidRect.width_, avoidRect.height_); + dstNode->leashWinSurfaceNode_->SetBounds(avoidRect.posX_, avoidRect.posY_, + avoidRect.width_, avoidRect.height_); } } } +} +WMError RemoteAnimation::NotifyAnimationTransition(sptr srcInfo, + sptr dstInfo, const sptr& srcNode, + const sptr& dstNode) +{ + if (!dstNode) { + WLOGFI("id:%{public}u startingWindowShown_:%{public}d", dstNode->GetWindowId(), dstNode->startingWindowShown_); + return WMError::WM_ERROR_NO_REMOTE_ANIMATION; + } + WLOGFI("RSWindowAnimation: notify animation transition with dst currId:%{public}u!", dstNode->GetWindowId()); + auto finishedCallback = CreateShowAnimationFinishedCallback(srcNode, dstNode); + if (finishedCallback == nullptr) { + WLOGFE("New RSIWindowAnimationFinishedCallback failed"); + return WMError::WM_ERROR_NO_MEM; + } + auto dstTarget = CreateWindowAnimationTarget(dstInfo, dstNode); + if (dstTarget == nullptr) { + WLOGFE("RSWindowAnimation: Failed to create dst target!"); + finishedCallback->OnAnimationFinished(); + return WMError::WM_ERROR_NO_MEM; + } + // when exit immersive, startingWindow (0,0,w,h), but app need avoid + GetExpectRect(dstNode, dstTarget); dstNode->isPlayAnimationShow_ = true; - bool needMinimizeSrcNode = MinimizeApp::IsNodeNeedMinimize(srcNode); + // Transition to next state and update task count will success when enable animationFirst_ + dstNode->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_PLAYING); + dstNode->stateMachine_.UpdateAnimationTaskCount(true); + bool needMinimizeSrcNode = MinimizeApp::IsNodeNeedMinimizeWithReason(srcNode, MinimizeReason::OTHER_WINDOW); // from app to app if (needMinimizeSrcNode && srcNode != nullptr) { auto srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode); // to avoid normal animation srcNode->isPlayAnimationHide_ = true; - srcNode->state_ = WindowNodeState::HIDE_ANIMATION_PLAYING; - if (winRoot) { - winRoot->RemoveWindowNode(srcNode->GetWindowId()); + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + srcNode->stateMachine_.UpdateAnimationTaskCount(true); + auto winController = windowController_.promote(); + if (winController) { + winController->RemoveWindowNode(srcNode->GetWindowId(), true); + } + if (animationFirst_) { + // Notify minimize before animation when animationFirst is enable. + // Or notify minimize in animation finished callback. + MinimizeApp::ExecuteMinimizeAll(); } WLOGFI("RSWindowAnimation: app transition from id:%{public}u to id:%{public}u!", srcNode->GetWindowId(), dstNode->GetWindowId()); @@ -287,29 +326,20 @@ WMError RemoteAnimation::NotifyAnimationMinimize(sptr srcI } WLOGFI("RSWindowAnimation: notify animation minimize Id:%{public}u!", srcNode->GetWindowId()); srcNode->isPlayAnimationHide_ = true; - srcNode->state_ = WindowNodeState::HIDE_ANIMATION_PLAYING; - auto winRoot = windowRoot_.promote(); - if (winRoot != nullptr) { - winRoot->RemoveWindowNode(srcNode->GetWindowId()); + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + auto winController = windowController_.promote(); + if (winController) { + winController->RemoveWindowNode(srcNode->GetWindowId(), true); } - wptr weak = srcNode; - auto minimizeFunc = [weak]() { - auto weakNode = weak.promote(); - if (weakNode == nullptr || !weakNode->IsWindowNodeHiddenOrHiding()) { - WLOGFE("windowNode is nullptr or is not play hide animation!"); - return; - } - FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), - "wms:async:ShowRemoteAnimation"); - weakNode->state_ = WindowNodeState::HIDE_ANIMATION_DONE; - WindowInnerManager::GetInstance().MinimizeAbility(weak, true); - }; - sptr finishedCallback = new(std::nothrow) RSWindowAnimationFinishedCallback( - minimizeFunc); + sptr finishedCallback = CreateHideAnimationFinishedCallback( + srcNode, TransitionEvent::MINIMIZE); if (finishedCallback == nullptr) { WLOGFE("New RSIWindowAnimationFinishedCallback failed"); return WMError::WM_ERROR_NO_MEM; } + + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + srcNode->stateMachine_.UpdateAnimationTaskCount(true); windowAnimationController_->OnMinimizeWindow(srcTarget, finishedCallback); return WMError::WM_OK; } @@ -323,53 +353,24 @@ WMError RemoteAnimation::NotifyAnimationClose(sptr srcInfo } WLOGFI("RSWindowAnimation: notify animation close id:%{public}u!", srcNode->GetWindowId()); srcNode->isPlayAnimationHide_ = true; - srcNode->state_ = WindowNodeState::HIDE_ANIMATION_PLAYING; - auto winRoot = windowRoot_.promote(); - if (winRoot != nullptr) { - winRoot->RemoveWindowNode(srcNode->GetWindowId()); + auto winController = windowController_.promote(); + if (winController) { + winController->RemoveWindowNode(srcNode->GetWindowId(), true); } - wptr weak = srcNode; - auto closeFunc = [weak, event]() { - auto weakNode = weak.promote(); - if (weakNode == nullptr || !weakNode->IsWindowNodeHiddenOrHiding()) { - WLOGFE("windowNode is nullptr or is not play hide animation!"); - return; - } - if (weakNode != nullptr && weakNode->abilityToken_ != nullptr) { - if (event == TransitionEvent::CLOSE) { - WLOGFI("close windowId: %{public}u, name:%{public}s", - weakNode->GetWindowId(), weakNode->GetWindowName().c_str()); - weakNode->state_ = WindowNodeState::HIDE_ANIMATION_DONE; - AAFwk::AbilityManagerClient::GetInstance()->CloseAbility(weakNode->abilityToken_); - } else if (event == TransitionEvent::BACK) { - WLOGFI("terminate windowId: %{public}u, name:%{public}s", - weakNode->GetWindowId(), weakNode->GetWindowName().c_str()); - weakNode->state_ = WindowNodeState::HIDE_ANIMATION_DONE; - AAFwk::Want resultWant; - AAFwk::AbilityManagerClient::GetInstance()->TerminateAbility(weakNode->abilityToken_, -1, &resultWant); - } - FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), - "wms:async:ShowRemoteAnimation"); - } - }; - sptr finishedCallback = new(std::nothrow) RSWindowAnimationFinishedCallback( - closeFunc); + sptr finishedCallback = CreateHideAnimationFinishedCallback(srcNode, event); if (finishedCallback == nullptr) { WLOGFE("New RSIWindowAnimationFinishedCallback failed"); return WMError::WM_ERROR_NO_MEM; } + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + srcNode->stateMachine_.UpdateAnimationTaskCount(true); windowAnimationController_->OnCloseWindow(srcTarget, finishedCallback); return WMError::WM_OK; } -WMError RemoteAnimation::NotifyAnimationByHome() +void RemoteAnimation::GetAnimationTargetsForHome(std::vector>& animationTargets, + std::vector> needMinimizeAppNodes) { - if (!CheckAnimationController()) { - return WMError::WM_ERROR_NO_REMOTE_ANIMATION; - } - WLOGFI("RSWindowAnimation: notify animation by home"); - auto needMinimizeAppNodes = MinimizeApp::GetNeedMinimizeAppNodes(); - std::vector> animationTargets; for (auto& weakNode : needMinimizeAppNodes) { auto srcNode = weakNode.promote(); sptr srcInfo = new(std::nothrow) WindowTransitionInfo(); @@ -377,33 +378,70 @@ WMError RemoteAnimation::NotifyAnimationByHome() if (srcTarget == nullptr) { continue; } - if (srcNode->IsWindowNodeHiddenOrHiding()) { - WLOGFE("window id:%{public}u is already hiding or hidden with state:%{public}u", - srcNode->GetWindowId(), static_cast(srcNode->state_)); + WLOGFI("notify animation by home, need minimize id%{public}u", srcNode->GetWindowId()); + if (!WindowHelper::IsMainWindow(srcNode->GetWindowType()) || + srcNode->stateMachine_.IsWindowNodeHiddenOrHiding()) { + WLOGFE("srcNode is already hiding or hidden id: %{public}d!", srcNode->GetWindowId()); continue; } srcNode->isPlayAnimationHide_ = true; - srcNode->state_ = WindowNodeState::HIDE_ANIMATION_PLAYING; - auto winRoot = windowRoot_.promote(); - if (winRoot != nullptr) { - winRoot->RemoveWindowNode(srcNode->GetWindowId()); + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + srcNode->stateMachine_.UpdateAnimationTaskCount(true); + auto winController = windowController_.promote(); + if (winController) { + winController->RemoveWindowNode(srcNode->GetWindowId(), true); } animationTargets.emplace_back(srcTarget); } - auto func = [needMinimizeAppNodes]() { - WLOGFI("NotifyAnimationByHome in animation callback"); +} + +static void GetAnimationHomeFinishCallback(std::function& func, + std::vector> needMinimizeAppNodes) +{ + func = [needMinimizeAppNodes]() { + WLOGFI("NotifyAnimationByHome in animation callback not animationFirst"); for (auto& weakNode : needMinimizeAppNodes) { auto srcNode = weakNode.promote(); - if (srcNode == nullptr || !srcNode->IsWindowNodeHiddenOrHiding()) { + if (srcNode == nullptr || !srcNode->stateMachine_.IsWindowNodeHiddenOrHiding()) { WLOGFE("windowNode is nullptr or is not play hide animation!"); continue; } - srcNode->state_ = WindowNodeState::HIDE_ANIMATION_DONE; + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_DONE); } MinimizeApp::ExecuteMinimizeTargetReason(MinimizeReason::MINIMIZE_ALL); FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), "wms:async:ShowRemoteAnimation"); }; +} + +WMError RemoteAnimation::NotifyAnimationByHome() +{ + if (!CheckAnimationController()) { + return WMError::WM_ERROR_NO_REMOTE_ANIMATION; + } + auto needMinimizeAppNodes = MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_ALL); + WLOGFI("RSWindowAnimation: notify animation by home, need minimize size: %{public}u", + static_cast(needMinimizeAppNodes.size())); + std::vector> animationTargets; + GetAnimationTargetsForHome(animationTargets, needMinimizeAppNodes); + std::function func; + if (animationFirst_) { + MinimizeApp::ExecuteMinimizeTargetReason(MinimizeReason::MINIMIZE_ALL); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + func = [needMinimizeAppNodes]() { + WLOGFI("NotifyAnimationByHome in animation callback in animationFirst with size:%{public}u", + static_cast(needMinimizeAppNodes.size())); + for (auto& weakNode : needMinimizeAppNodes) { + auto srcNode = weakNode.promote(); + ProcessNodeStateTask(srcNode); + } + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + }; + } else { + GetAnimationHomeFinishCallback(func, needMinimizeAppNodes); + } sptr finishedCallback = new(std::nothrow) RSWindowAnimationFinishedCallback( func); if (finishedCallback == nullptr) { @@ -522,5 +560,266 @@ sptr RemoteAnimation::CreateWindowAnimationTarget(sptr< windowAnimationTarget->windowBounds_ = RRect(boundsRect, stagingProperties.GetCornerRadius()); return windowAnimationTarget; } + +void RemoteAnimation::PostProcessShowCallback(const sptr& node) +{ + wptr weak = node; + auto handler = wmsTaskHandler_.lock(); + if (handler != nullptr) { + auto task = [weak] { + auto weakNode = weak.promote(); + if (weakNode == nullptr) { + WLOGFD("windowNode is nullptr!"); + return; + } + auto winRect = weakNode->GetWindowRect(); + if (weakNode->leashWinSurfaceNode_) { + WLOGFD("name:%{public}s id:%{public}u winRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]", + weakNode->GetWindowName().c_str(), weakNode->GetWindowId(), + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + weakNode->leashWinSurfaceNode_->SetBounds( + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + RSTransaction::FlushImplicitTransaction(); + } + }; + handler->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE); + } +} + +void RemoteAnimation::PostFinalStateTask(const sptr& node) +{ + StateTask task = nullptr; + StateTask destroyTask = nullptr; + wptr weakNode = node; + if (node->stateMachine_.IsWindowNodeHiddenOrHiding()) { + // when no task, need remove from rs Tree + task = [weakRoot = windowRoot_, weakNode]() { + auto winRoot = weakRoot.promote(); + auto winNode = weakNode.promote(); + if (winRoot == nullptr || winNode == nullptr) { + WLOGFE("windowRoot or winNode is nullptr"); + return; + } + WLOGFI("execute task removing from rs tree id:%{public}u!", winNode->GetWindowId()); + winRoot->UpdateRsTree(winNode->GetWindowId(), false); + }; + } else if (node->stateMachine_.IsWindowNodeShownOrShowing()) { + task = [weakRoot = windowRoot_, weakNode]() { + auto winRoot = weakRoot.promote(); + auto winNode = weakNode.promote(); + if (winRoot == nullptr || winNode == nullptr) { + WLOGFE("windowRoot or winNode is nullptr"); + return; + } + WLOGFI("execute task layout after show animation id:%{public}u!", winNode->GetWindowId()); + winRoot->LayoutWhenAddWindowNode(winNode, true); + }; + } else { + WLOGFD("current State:%{public}u invalid", static_cast(node->stateMachine_.GetCurrentState())); + } + auto handler = wmsTaskHandler_.lock(); + if (handler != nullptr) { + if (task != nullptr) { + bool ret = handler->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE); + if (!ret) { + WLOGFE("EventHandler PostTask Failed!"); + task(); + } + } + if (node->stateMachine_.GetDestroyTask(destroyTask)) { + bool ret = handler->PostTask(destroyTask, AppExecFwk::EventQueue::Priority::IMMEDIATE); + if (!ret) { + WLOGFE("EventHandler PostTask Failed!"); + destroyTask(); + } + } + } +} + +void RemoteAnimation::CallbackTimeOutProcess() +{ + auto winRoot = windowRoot_.promote(); + if (winRoot == nullptr) { + WLOGFE("windowRoot is nullptr"); + return; + } + std::vector> animationPlayingNodes; + winRoot->GetAllAnimationPlayingNodes(animationPlayingNodes); + WLOGFI("CallbackTimeOutProcess playingNodes:%{public}u", static_cast(animationPlayingNodes.size())); + for (auto& weakNode : animationPlayingNodes) { + auto node = weakNode.promote(); + if (node == nullptr) { + continue; + } + WLOGFI("callback timeout process windowId:%{public}u", node->GetWindowId()); + node->stateMachine_.ResetAnimationTaskCount(1); + ProcessNodeStateTask(node); + } +} + +void RemoteAnimation::ProcessNodeStateTask(const sptr& node) +{ + // when callback come, node maybe destroyed + if (node == nullptr) { + WLOGFI("node is nullptr!"); + return; + } + node->stateMachine_.UpdateAnimationTaskCount(false); + int32_t taskCount = node->stateMachine_.GetAnimationCount(); + WLOGFI("ProcessNodeStateTask windowId: %{public}u, name:%{public}s state: %{public}u, taskCount:%{public}d", + node->GetWindowId(), node->GetWindowName().c_str(), + static_cast(node->stateMachine_.GetCurrentState()), taskCount); + if (taskCount > 0 || taskCount < 0) { + WLOGFI("not last state task of window: %{public}d, %{public}d callback left not be executed!", + node->GetWindowId(), taskCount); + return; + } + PostFinalStateTask(node); + if (node->stateMachine_.IsWindowNodeShownOrShowing()) { + // delete when immersive solution change + PostProcessShowCallback(node); + node->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_DONE); + } else if (node->stateMachine_.IsWindowNodeHiddenOrHiding()) { + node->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_DONE); + } +} + +sptr RemoteAnimation::CreateShowAnimationFinishedCallback( + const sptr& srcNode, const sptr& dstNode) +{ + wptr srcNodeWptr = srcNode; + wptr dstNodeWptr = dstNode; + // need add timeout check + std::function func; + if (!animationFirst_) { + WLOGFI("RSWindowAnimation: not animationFirst use default callback!"); + return GetTransitionFinishedCallback(srcNode, dstNode); + } else { + func = [srcNodeWptr, dstNodeWptr]() { + WLOGFI("RSWindowAnimation: animationFirst use state machine process ShowAnimationFinishedCallback!"); + auto srcNodeSptr = srcNodeWptr.promote(); + auto dstNodeSptr = dstNodeWptr.promote(); + if (dstNodeSptr == nullptr) { + WLOGFE("dstNode is nullptr!"); + return; + } + ProcessNodeStateTask(dstNodeSptr); + // launcher not do this + if (srcNodeSptr!= nullptr && WindowHelper::IsMainWindow(srcNodeSptr->GetWindowType()) && + WindowHelper::IsFullScreenWindow(srcNodeSptr->GetWindowMode())) { + ProcessNodeStateTask(srcNodeSptr); + } + WLOGFI("current window:%{public}u state: %{public}u", dstNodeSptr->GetWindowId(), + static_cast(dstNodeSptr->stateMachine_.GetCurrentState())); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + }; + } + sptr finishedCallback = new(std::nothrow) RSWindowAnimationFinishedCallback( + func); + if (finishedCallback == nullptr) { + WLOGFE("New RSIWindowAnimationFinishedCallback failed"); + return nullptr; + } + return finishedCallback; +} + +static void GetAndDrawSnapShot(const sptr& srcNode) +{ + if (srcNode == nullptr || srcNode->leashWinSurfaceNode_ == nullptr) { + WLOGFD("srcNode or srcNode->leashWinSurfaceNode_ is empty"); + return; + } + if (srcNode->firstFrameAvaliable_) { + std::shared_ptr pixelMap; + // snapshot time out 2000ms + bool snapSucc = SurfaceDraw::GetSurfaceSnapshot(srcNode->surfaceNode_, pixelMap, 2000, 1.0, 1.0); + if (!snapSucc) { + // need to draw starting window when get pixelmap failed + WLOGFE("get surfaceSnapshot failed for window:%{public}u", srcNode->GetWindowId()); + return; + } + SurfaceDraw::DrawImageRect(srcNode->startingWinSurfaceNode_, srcNode->GetWindowRect(), + pixelMap, 0xffffffff, true); + srcNode->leashWinSurfaceNode_->RemoveChild(srcNode->surfaceNode_); + srcNode->leashWinSurfaceNode_->AddChild(srcNode->startingWinSurfaceNode_, -1); + RSTransaction::FlushImplicitTransaction(); + WLOGFI("Draw surface snapshot in starting window for window:%{public}u", srcNode->GetWindowId()); + } else if (srcNode->surfaceNode_) { + srcNode->surfaceNode_->SetIsNotifyUIBufferAvailable(true); + WLOGFI("Draw startingWindow in starting window for window:%{public}u", srcNode->GetWindowId()); + } +} + +static void ProcessAbility(const sptr& srcNode, TransitionEvent event) +{ + switch (event) { + case TransitionEvent::CLOSE: { + WLOGFI("close windowId: %{public}u, name:%{public}s", + srcNode->GetWindowId(), srcNode->GetWindowName().c_str()); + WindowInnerManager::GetInstance().CloseAbility(srcNode); + break; + } + case TransitionEvent::BACK: { + WLOGFI("terminate windowId: %{public}u, name:%{public}s", + srcNode->GetWindowId(), srcNode->GetWindowName().c_str()); + WindowInnerManager::GetInstance().TerminateAbility(srcNode); + break; + } + case TransitionEvent::MINIMIZE: { + WLOGFI("minimize windowId: %{public}u, name:%{public}s", + srcNode->GetWindowId(), srcNode->GetWindowName().c_str()); + WindowInnerManager::GetInstance().MinimizeAbility(srcNode, true); + break; + } + default: + break; + } +} + +sptr RemoteAnimation::CreateHideAnimationFinishedCallback( + const sptr& srcNode, TransitionEvent event) +{ + wptr srcNodeWptr = srcNode; + // need add timeout check + std::function func; + if (!animationFirst_) { + func = [srcNodeWptr, event]() { + WLOGFI("RSWindowAnimation: not animationFirst use default callback!"); + auto weakNode = srcNodeWptr.promote(); + if (weakNode == nullptr || weakNode->abilityToken_ == nullptr) { + WLOGFE("window node or ability token is nullptr"); + return; + } + if (!weakNode->stateMachine_.IsWindowNodeHiddenOrHiding()) { + WLOGFE("window is not playing hide animation"); + return; + } + ProcessAbility(weakNode, event); + weakNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_DONE); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + }; + } else { + if (event != TransitionEvent::MINIMIZE) { + GetAndDrawSnapShot(srcNode); + } + ProcessAbility(srcNode, event); // execute first when animationFirst + func = [srcNodeWptr]() { + WLOGFI("RSWindowAnimation: animationFirst use state machine process HideAnimationFinishedCallback!"); + auto srcNodeSptr = srcNodeWptr.promote(); + ProcessNodeStateTask(srcNodeSptr); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + }; + } + sptr callback = new(std::nothrow) RSWindowAnimationFinishedCallback( + func); + if (callback == nullptr) { + WLOGFE("New RSIWindowAnimationFinishedCallback failed"); + return nullptr; + } + return callback; +} } // Rosen } // OHOS diff --git a/wmserver/src/starting_window.cpp b/wmserver/src/starting_window.cpp index e78be614fe..f6a45e2213 100644 --- a/wmserver/src/starting_window.cpp +++ b/wmserver/src/starting_window.cpp @@ -71,6 +71,8 @@ sptr StartingWindow::CreateWindowNode(const sptrstateMachine_.SetWindowId(winId); node->abilityToken_ = info->GetAbilityToken(); node->SetWindowSizeLimits(info->GetWindowSizeLimits()); node->abilityInfo_.missionId_ = info->GetMissionId(); @@ -83,6 +85,7 @@ sptr StartingWindow::CreateWindowNode(const sptrstateMachine_.TransitionTo(WindowNodeState::STARTING_CREATED); return node; } @@ -142,10 +145,12 @@ void StartingWindow::HandleClientWindowCreate(sptr& node, sptrSetCallingPid(pid); node->SetCallingUid(uid); windowId = node->GetWindowId(); + // test + node->stateMachine_.SetWindowId(windowId); + node->stateMachine_.SetWindowType(property->GetWindowType()); WLOGFI("after set Id:%{public}u, requestRect:[%{public}d, %{public}d, %{public}u, %{public}u]", node->GetWindowId(), node->GetRequestRect().posX_, node->GetRequestRect().posY_, node->GetRequestRect().width_, node->GetRequestRect().height_); - // Register FirstFrame Callback to rs, replace startwin wptr weak = node; auto firstFrameCompleteCallback = [weak]() { @@ -160,9 +165,9 @@ void StartingWindow::HandleClientWindowCreate(sptr& node, sptrGetWindowId()); weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_); weakNode->leashWinSurfaceNode_->AddChild(weakNode->surfaceNode_, -1); - weakNode->startingWinSurfaceNode_ = nullptr; AAFwk::AbilityManagerClient::GetInstance()->CompleteFirstFrameDrawing(weakNode->abilityToken_); RSTransaction::FlushImplicitTransaction(); + weakNode->firstFrameAvaliable_ = true; }; node->surfaceNode_->SetBufferAvailableCallback(firstFrameCompleteCallback); RSTransaction::FlushImplicitTransaction(); diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index 62f60d610d..09732d1d16 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -72,8 +72,9 @@ void WindowController::StartingWindow(sptr info, std::shar UpdateWindowAnimation(node); } } else { - if (isColdStart) { - WLOGFE("windowNode exists but is cold start!"); + if (node->stateMachine_.IsWindowNodeShownOrShowing()) { + WLOGFI("current window is visible, windowId:%{public}u state:%{public}u!", + node->GetWindowId(), static_cast(node->stateMachine_.GetCurrentState())); return; } if (WindowHelper::IsValidWindowMode(info->GetWindowMode()) && @@ -217,6 +218,9 @@ WMError WindowController::CreateWindow(sptr& window, sptrGetWindowName().c_str()); + // test + node->stateMachine_.SetWindowId(windowId); + node->stateMachine_.SetWindowType(property->GetWindowType()); return windowRoot_->SaveWindow(node); } @@ -240,7 +244,6 @@ WMError WindowController::AddWindowNode(sptr& property) property->SetDecoStatus(true); } node->GetWindowProperty()->CopyFrom(property); - // Need 'check permission' // Need 'adjust property' UpdateWindowAnimation(node); @@ -270,12 +273,14 @@ WMError WindowController::AddWindowNode(sptr& property) ResizeSoftInputCallingWindowIfNeed(node); } StopBootAnimationIfNeed(node); - if (node->state_ != WindowNodeState::SHOW_ANIMATION_PLAYING && - node->state_ != WindowNodeState::HIDE_ANIMATION_PLAYING) { - if (WindowHelper::IsMainWindow(node->GetWindowType())) { // system window no need to execute minimize - MinimizeApp::ExecuteMinimizeAll(); // MAX_APP_COUNT/TILE + // when hide with remote animation first and show with default animation, need transform state + // minimize should execute in finish callback when remote animation enabled + if (!node->stateMachine_.IsShowAnimationPlaying()) { + if (WindowHelper::IsMainWindow(node->GetWindowType())) { + MinimizeApp::ExecuteMinimizeAll(); + WLOGFI("id:%{public}u execute minimize all", node->GetWindowId()); } - node->state_ = WindowNodeState::SHOWN; // for normal show which not use remote animation + node->stateMachine_.TransitionTo(WindowNodeState::SHOWN); // for normal show which not use remote animation } return WMError::WM_OK; } @@ -350,15 +355,15 @@ void WindowController::HandleTurnScreenOn(const sptr& node) IPCSkeleton::SetCallingIdentity(identity); } -WMError WindowController::RemoveWindowNode(uint32_t windowId) +WMError WindowController::RemoveWindowNode(uint32_t windowId, bool fromAnimation) { auto windowNode = windowRoot_->GetWindowNode(windowId); if (windowNode == nullptr) { WLOGFE("windowNode is nullptr"); return WMError::WM_ERROR_NULLPTR; } - auto removeFunc = [this, windowId, windowNode]() { - WMError res = windowRoot_->RemoveWindowNode(windowId); + auto removeFunc = [this, windowId, windowNode, fromAnimation]() { + WMError res = windowRoot_->RemoveWindowNode(windowId, fromAnimation); if (res != WMError::WM_OK) { WLOGFE("RemoveWindowNode failed"); return res; @@ -388,9 +393,8 @@ WMError WindowController::RemoveWindowNode(uint32_t windowId) if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { RestoreCallingWindowSizeIfNeed(); } - if (windowNode->state_ != WindowNodeState::SHOW_ANIMATION_PLAYING && - windowNode->state_ != WindowNodeState::HIDE_ANIMATION_PLAYING) { - windowNode->state_ = WindowNodeState::HIDDEN; // for normal hide which not use remote animation + if (!windowNode->stateMachine_.IsHideAnimationPlaying()) { + windowNode->stateMachine_.TransitionTo(WindowNodeState::HIDDEN); } return res; } @@ -400,7 +404,7 @@ WMError WindowController::DestroyWindow(uint32_t windowId, bool onlySelf) DisplayId displayId = DISPLAY_ID_INVALID; auto node = windowRoot_->GetWindowNode(windowId); if (node == nullptr) { - WLOGFE("destroy window failed, because window node is not exist."); + WLOGFE("destroy window id:%{public}u failed, because window node is not exist.", windowId); return WMError::WM_ERROR_NULLPTR; } displayId = node->GetDisplayId(); @@ -417,6 +421,7 @@ WMError WindowController::DestroyWindow(uint32_t windowId, bool onlySelf) } accessibilityConnection_->NotifyAccessibilityWindowInfo(node->GetDisplayId(), nodes, WindowUpdateType::WINDOW_UPDATE_REMOVED); + node->stateMachine_.TransitionTo(WindowNodeState::DESTROYED); return res; } @@ -498,7 +503,12 @@ WMError WindowController::SetWindowMode(uint32_t windowId, WindowMode dstMode) } FlushWindowInfo(windowId); accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY); - MinimizeApp::ExecuteMinimizeAll(); + if (!node->stateMachine_.IsShowAnimationPlaying()) { + if (WindowHelper::IsMainWindow(node->GetWindowType())) { + MinimizeApp::ExecuteMinimizeAll(); + WLOGFI("id:%{public}u execute minimize all", node->GetWindowId()); + } + } return WMError::WM_OK; } diff --git a/wmserver/src/window_dumper.cpp b/wmserver/src/window_dumper.cpp index 9e058979fe..a7a267144b 100644 --- a/wmserver/src/window_dumper.cpp +++ b/wmserver/src/window_dumper.cpp @@ -184,6 +184,7 @@ WMError WindowDumper::DumpSpecifiedWindowInfo(uint32_t windowId, const std::vect oss << "Flag: " << node->GetWindowFlags() << std::endl; oss << "Orientation: " << static_cast(node->GetRequestedOrientation()) << std::endl; oss << "IsStartingWindow: " << isShown_ << std::endl; + oss << "FirstFrameCallbackCalled: " << node->firstFrameAvaliable_ << std::endl; oss << "IsVisible: " << isVisible << std::endl; oss << "WindowRect: " << "[ " << rect.posX_ << ", " << rect.posY_ << ", " << rect.width_ << ", " << rect.height_ diff --git a/wmserver/src/window_inner_manager.cpp b/wmserver/src/window_inner_manager.cpp index 2b052e767a..803854dcbe 100644 --- a/wmserver/src/window_inner_manager.cpp +++ b/wmserver/src/window_inner_manager.cpp @@ -167,8 +167,8 @@ void WindowInnerManager::MinimizeAbility(const wptr &node, bool isFr { // asynchronously calls the MinimizeAbility of AbilityManager auto weakNode = node.promote(); - if (weakNode == nullptr || weakNode->startingWindowShown_) { - WLOGE("minimize ability failed, because node is nullptr or start window node."); + if (weakNode == nullptr) { + WLOGFE("minimize ability failed."); return; } wptr weakToken(weakNode->abilityToken_); @@ -184,6 +184,50 @@ void WindowInnerManager::MinimizeAbility(const wptr &node, bool isFr PostTask(task, "MinimizeAbility"); } +void WindowInnerManager::TerminateAbility(const wptr &node) +{ + // asynchronously calls the TerminateAbility of AbilityManager + auto weakNode = node.promote(); + if (weakNode == nullptr) { + WLOGFE("terminate ability failed."); + return; + } + wptr weakToken(weakNode->abilityToken_); + WLOGFD("terminate window %{public}u", weakNode->GetWindowId()); + auto task = [weakToken]() { + auto token = weakToken.promote(); + if (token == nullptr) { + WLOGE("terminate ability failed, because window token is nullptr."); + return; + } + AAFwk::Want resultWant; + AAFwk::AbilityManagerClient::GetInstance()->TerminateAbility(token, -1, &resultWant); + }; + PostTask(task, "TerminateAbility"); +} + +void WindowInnerManager::CloseAbility(const wptr &node) +{ + // asynchronously calls the CloseAbility of AbilityManager + auto weakNode = node.promote(); + if (weakNode == nullptr) { + WLOGFE("close ability failed."); + return; + } + wptr weakToken(weakNode->abilityToken_); + WLOGFD("close window %{public}u", weakNode->GetWindowId()); + auto task = [weakToken]() { + auto token = weakToken.promote(); + if (token == nullptr) { + WLOGE("close ability failed, because window token is nullptr."); + return; + } + AAFwk::Want resultWant; + AAFwk::AbilityManagerClient::GetInstance()->CloseAbility(token); + }; + PostTask(task, "CloseAbility"); +} + void WindowInnerManager::PostTask(InnerTask &&task, std::string name, EventPriority priority) { if (eventHandler_ == nullptr) { diff --git a/wmserver/src/window_manager_service.cpp b/wmserver/src/window_manager_service.cpp index b09babe777..8b0d70f800 100644 --- a/wmserver/src/window_manager_service.cpp +++ b/wmserver/src/window_manager_service.cpp @@ -75,7 +75,6 @@ WindowManagerService::WindowManagerService() : SystemAbility(WINDOW_MANAGER_SERV if (ret != 0) { WLOGFE("Add watchdog thread failed"); } - // init RSUIDirector, it will handle animation callback rsUiDirector_ = RSUIDirector::Create(); rsUiDirector_->SetUITaskRunner([this](const std::function& task) { PostAsyncTask(task); }); @@ -131,7 +130,6 @@ void WindowManagerService::PostVoidSyncTask(Task task) } } - void WindowManagerService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) { WLOGFI(" %{public}d", systemAbilityId); @@ -719,7 +717,12 @@ WMError WindowManagerService::DestroyWindow(uint32_t windowId, bool onlySelf) WLOGFI("Operation rejected"); return WMError::WM_ERROR_INVALID_OPERATION; } - return PostSyncTask([this, windowId, onlySelf]() { + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + return WMError::WM_ERROR_NULLPTR; + } + node->stateMachine_.SetDestroyTaskParam(onlySelf); + auto func = [this, windowId]() { WLOGFI("[WMS] Destroy: %{public}u", windowId); HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:DestroyWindow(%u)", windowId); WindowInnerManager::GetInstance().NotifyWindowRemovedOrDestroyed(windowId); @@ -727,8 +730,18 @@ WMError WindowManagerService::DestroyWindow(uint32_t windowId, bool onlySelf) if (node != nullptr && node->GetWindowType() == WindowType::WINDOW_TYPE_DRAGGING_EFFECT) { dragController_->FinishDrag(windowId); } - return windowController_->DestroyWindow(windowId, onlySelf); - }); + return windowController_->DestroyWindow(windowId, node->stateMachine_.GetDestroyTaskParam()); + }; + if (RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) && + node->stateMachine_.IsRemoteAnimationPlaying()) { + WLOGFI("SetDestroyTask id:%{public}u", node->GetWindowId()); + node->stateMachine_.SetDestroyTask(func); + return WMError::WM_OK; + } + WLOGFI("DestroyWindow windowId: %{public}u, name:%{public}s state: %{public}u", + node->GetWindowId(), node->GetWindowName().c_str(), + static_cast(node->stateMachine_.GetCurrentState())); + return PostSyncTask(func); } WMError WindowManagerService::RequestFocus(uint32_t windowId) @@ -790,23 +803,48 @@ WMError WindowManagerService::SetWindowAnimationController(const sptrAsObject()->AddDeathRecipient(deathRecipient); + RemoteAnimation::SetWindowController(windowController_); RemoteAnimation::SetMainTaskHandler(handler_); return PostSyncTask([this, &controller]() { - return windowController_->SetWindowAnimationController(controller); + WMError ret = windowController_->SetWindowAnimationController(controller); + RemoteAnimation::SetAnimationFirst(system::GetParameter("persist.window.af.enabled", "1") == "1"); + return ret; }); } void WindowManagerService::OnWindowEvent(Event event, const sptr& remoteObject) { if (event == Event::REMOTE_DIED) { - PostVoidSyncTask([this, &remoteObject, event]() { - uint32_t windowId = windowRoot_->GetWindowIdByObject(remoteObject); + uint32_t windowId = windowRoot_->GetWindowIdByObject(remoteObject); + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFD("window node is nullptr, REMOTE_DIED no need to destroy"); + return; + } + node->stateMachine_.SetDestroyTaskParam(true); + auto func = [this, windowId]() { auto node = windowRoot_->GetWindowNode(windowId); - if (node != nullptr && node->GetWindowType() == WindowType::WINDOW_TYPE_DRAGGING_EFFECT) { + if (node == nullptr) { + WLOGFD("window node is nullptr"); + return; + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DRAGGING_EFFECT) { dragController_->FinishDrag(windowId); } - windowController_->DestroyWindow(windowId, true); - }); + windowController_->DestroyWindow(windowId, node->stateMachine_.GetDestroyTaskParam()); + }; + + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { + PostVoidSyncTask([&remoteObject] { RemoteAnimation::OnRemoteDie(remoteObject); }); + } + if (RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) && + node->stateMachine_.IsRemoteAnimationPlaying()) { + WLOGFI("set destroy task windowId:%{public}u", node->GetWindowId()); + node->stateMachine_.SetDestroyTask(func); + handler_->PostTask(func, "destroyTimeOutTask", 6000); // 6000 is time out 6s + return; + } + return PostVoidSyncTask(func); } } diff --git a/wmserver/src/window_node.cpp b/wmserver/src/window_node.cpp index 6516b42cff..0cee69b918 100644 --- a/wmserver/src/window_node.cpp +++ b/wmserver/src/window_node.cpp @@ -396,23 +396,5 @@ std::shared_ptr WindowNode::GetSnapshot() { return snapshot_; } - -bool WindowNode::IsWindowNodeShownOrShowing() -{ - if (state_ == WindowNodeState::SHOW_ANIMATION_DONE || state_ == WindowNodeState::SHOW_ANIMATION_PLAYING || - state_ == WindowNodeState::SHOWN) { - return true; - } - return false; -} - -bool WindowNode::IsWindowNodeHiddenOrHiding() -{ - if (state_ == WindowNodeState::HIDE_ANIMATION_DONE || state_ == WindowNodeState::HIDE_ANIMATION_PLAYING || - state_ == WindowNodeState::HIDDEN) { - return true; - } - return false; -} } // namespace Rosen } // namespace OHOS diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index b254be9e6a..f38a5f1670 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -169,7 +169,32 @@ AnimationConfig& WindowNodeContainer::GetAnimationConfigRef() return animationConfig_; } -WMError WindowNodeContainer::AddWindowNode(sptr& node, sptr& parentNode) +void WindowNodeContainer::LayoutWhenAddWindowNode(sptr& node, bool afterAnimation) +{ + if (afterAnimation) { + layoutPolicy_->AddWindowNode(node); + return; + } + WLOGFI("AddWindowNode windowId:%{public}u, name:%{public}s currState:%{public}u", + node->GetWindowId(), node->GetWindowName().c_str(), + static_cast(node->stateMachine_.GetCurrentState())); + if (WindowHelper::IsMainWindow(node->GetWindowType()) && + RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) && + node->stateMachine_.IsShowAnimationPlaying()) { + // for first frame callback + auto winRect = node->GetWindowRect(); + if (node->surfaceNode_) { + node->surfaceNode_->SetBounds(0, 0, winRect.width_, winRect.height_); + WLOGFI("notify client and SetBounds id:%{public}u, rect:[%{public}d, %{public}d, %{public}u, %{public}u]", + node->GetWindowId(), winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + layoutPolicy_->UpdateClientRect(node->GetWindowRect(), node, WindowSizeChangeReason::UNDEFINED); + } + } else { + layoutPolicy_->AddWindowNode(node); + } +} + +WMError WindowNodeContainer::AddWindowNode(sptr& node, sptr& parentNode, bool afterAnimation) { if (!node->startingWindowShown_) { WMError res = AddWindowNodeOnWindowTree(node, parentNode); @@ -187,6 +212,7 @@ WMError WindowNodeContainer::AddWindowNode(sptr& node, sptrisPlayAnimationShow_ = false; node->startingWindowShown_ = false; ReZOrderShowWhenLockedWindowIfNeeded(node); + RaiseZOrderForAppWindow(node, parentNode); } auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId()); if (windowPair == nullptr) { @@ -199,7 +225,7 @@ WMError WindowNodeContainer::AddWindowNode(sptr& node, sptrAddWindowNode(node); + LayoutWhenAddWindowNode(node, afterAnimation); NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_ADD); DumpScreenWindowTree(); UpdateCameraFloatWindowStatus(node, true); @@ -250,11 +276,9 @@ WMError WindowNodeContainer::UpdateWindowNode(sptr& node, WindowUpda SwitchLayoutPolicy(WindowLayoutMode::CASCADE, node->GetDisplayId()); } layoutPolicy_->UpdateWindowNode(node); - displayGroupController_->PostProcessWindowNode(node); // Get current displayId and showing displays, update RSTree and displayGroupWindowTree UpdateRSTreeWhenShowingDisplaysChange(node, lastShowingDisplays); - NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_UPDATE); DumpScreenWindowTree(); WLOGFI("UpdateWindowNode windowId: %{public}u end", node->GetWindowId()); @@ -276,7 +300,21 @@ void WindowNodeContainer::RemoveWindowNodeFromWindowTree(sptr& node) node->parent_ = nullptr; } -WMError WindowNodeContainer::RemoveWindowNode(sptr& node) +void WindowNodeContainer::RemoveFromRsTreeWhenRemoveWindowNode(sptr& node, bool fromAnimation) +{ + if (fromAnimation || (RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) && + node->stateMachine_.IsHideAnimationPlaying())) { + WLOGFD("not remove from rs tree id:%{public}u", node->GetWindowId()); + return; + } + // When RemoteAnimation exists, remove node from rs tree after animation + WLOGFD("remove from rs tree id:%{public}u", node->GetWindowId()); + for (auto& displayId : node->GetShowingDisplays()) { + RemoveNodeFromRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_REMOVED, true); + } +} + +WMError WindowNodeContainer::RemoveWindowNode(sptr& node, bool fromAnimation) { if (node == nullptr) { WLOGFE("window node or surface node is nullptr, invalid"); @@ -290,20 +328,7 @@ WMError WindowNodeContainer::RemoveWindowNode(sptr& node) node->requestedVisibility_ = false; node->currentVisibility_ = false; - // When RemoteAnimation exists, Remove node from RSTree after animation - if (!node->isPlayAnimationHide_) { // update rs tree after animation - bool isAnimationPlayed = false; - if (RemoteAnimation::CheckAnimationController() && WindowHelper::IsMainWindow(node->GetWindowType())) { - isAnimationPlayed = true; - } - for (auto& displayId : node->GetShowingDisplays()) { - RemoveNodeFromRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_REMOVED, - isAnimationPlayed); - } - } else { // not update rs tree before animation - node->isPlayAnimationHide_ = false; - } - + RemoveFromRsTreeWhenRemoveWindowNode(node, fromAnimation); displayGroupController_->UpdateDisplayGroupWindowTree(); layoutPolicy_->RemoveWindowNode(node); @@ -405,6 +430,11 @@ void WindowNodeContainer::UpdateWindowTree(sptr& node) WLOGFI("Current window node has no parent: %{public}u", node->GetWindowId()); return; } + auto iter = std::find(parentNode->children_.begin(), parentNode->children_.end(), node); + if (iter != parentNode->children_.end()) { + WLOGFI("node %{public}u is already on window tree, no need to update!", node->GetWindowId()); + return; + } auto position = parentNode->children_.end(); int splitWindowCnt = 0; for (auto iter = parentNode->children_.begin(); iter < parentNode->children_.end(); ++iter) { @@ -1072,6 +1102,10 @@ void WindowNodeContainer::RaiseOrderedWindowToTop(std::vector>& void WindowNodeContainer::RaiseWindowToTop(uint32_t windowId, std::vector>& windowNodes) { + if (windowNodes.empty()) { + WLOGFE("windowNodes is empty!"); + return; + } auto iter = std::find_if(windowNodes.begin(), windowNodes.end(), [windowId](sptr node) { return node->GetWindowId() == windowId; @@ -1266,7 +1300,6 @@ WMError WindowNodeContainer::RaiseZOrderForAppWindow(sptr& node, spt if (node == nullptr) { return WMError::WM_ERROR_NULLPTR; } - if (IsTopWindow(node->GetWindowId(), appWindowNode_) || IsTopWindow(node->GetWindowId(), aboveAppWindowNode_)) { WLOGFI("it is already top app window, id: %{public}u", node->GetWindowId()); return WMError::WM_ERROR_INVALID_TYPE; diff --git a/wmserver/src/window_node_state_machine.cpp b/wmserver/src/window_node_state_machine.cpp new file mode 100644 index 0000000000..107c91dfb9 --- /dev/null +++ b/wmserver/src/window_node_state_machine.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 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 "window_node_state_machine.h" + +#include "parameters.h" +#include "remote_animation.h" +#include "window_helper.h" +#include "window_manager_hilog.h" +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowNodeStateMachine"}; +} // namespace + +WindowNodeStateMachine::WindowNodeStateMachine() +{ +} + +WindowNodeStateMachine::~WindowNodeStateMachine() +{ +} + +void WindowNodeStateMachine::SetDestroyTaskParam(bool onlySelf) +{ + destroyOnlySelf_ &= onlySelf; +} + +bool WindowNodeStateMachine::GetDestroyTaskParam() +{ + return destroyOnlySelf_; +} + +bool WindowNodeStateMachine::GetDestroyTask(StateTask& task) +{ + if (!RemoteAnimation::IsAnimationFirst()) { + return false; + } + std::lock_guard lock(mutex_); + if (destroyTask_ != nullptr) { + task = destroyTask_; + WLOGFI("GetDestroyTask success:%{public}u", windowId_); + return true; + } + return false; +} + +void WindowNodeStateMachine::SetDestroyTask(StateTask task) +{ + std::lock_guard lock(mutex_); + destroyTask_ = task; +} + +void WindowNodeStateMachine::TransitionTo(WindowNodeState state) +{ + std::lock_guard lock(mutex_); + if (WindowHelper::IsSystemWindow(type_)) { + WLOGFI("system window no need to use stateMachine"); + return; + } + currState_ = state; +} + +void WindowNodeStateMachine::UpdateAnimationTaskCount(bool isAdd) +{ + if (!RemoteAnimation::IsAnimationFirst()) { + WLOGFI("not animation first!"); + return; + } + std::lock_guard lock(mutex_); + if (isAdd) { + taskCount_++; + count1++; + WLOGFD("after add UpdateAnimationTaskCount1: %{public}u id:%{public}u", count1, windowId_); + } else { + taskCount_--; + count2++; + WLOGFD("after sub UpdateAnimationTaskCount1: %{public}u id:%{public}u", count2, windowId_); + } +} + +void WindowNodeStateMachine::ResetAnimationTaskCount(int32_t taskCount) +{ + std::lock_guard lock(mutex_); + taskCount_ = taskCount; +} + +int32_t WindowNodeStateMachine::GetAnimationCount() +{ + std::lock_guard lock(mutex_); + return taskCount_; +} + +bool WindowNodeStateMachine::IsRemoteAnimationPlaying() +{ + std::lock_guard lock(mutex_); + WLOGFD("IsRemoteAnimationPlaying id:%{public}u state:%{public}u", windowId_, static_cast(currState_)); + if (currState_ == WindowNodeState::SHOW_ANIMATION_PLAYING || + currState_ == WindowNodeState::HIDE_ANIMATION_PLAYING) { + return true; + } + return false; +} + +bool WindowNodeStateMachine::IsShowAnimationPlaying() +{ + std::lock_guard lock(mutex_); + WLOGFD("IsShowAnimationPlaying id:%{public}u state:%{public}u", windowId_, static_cast(currState_)); + return currState_ == WindowNodeState::SHOW_ANIMATION_PLAYING; +} + +bool WindowNodeStateMachine::IsHideAnimationPlaying() +{ + std::lock_guard lock(mutex_); + WLOGFD("IsHideAnimationPlaying id:%{public}u state:%{public}u", windowId_, static_cast(currState_)); + return currState_ == WindowNodeState::HIDE_ANIMATION_PLAYING; +} + +bool WindowNodeStateMachine::IsWindowNodeShownOrShowing() +{ + std::lock_guard lock(mutex_); + WLOGFD("IsWindowNodeShownOrShowing id:%{public}u state:%{public}u", windowId_, static_cast(currState_)); + if (currState_ == WindowNodeState::SHOW_ANIMATION_PLAYING || + currState_ == WindowNodeState::SHOW_ANIMATION_DONE || currState_ == WindowNodeState::SHOWN) { + return true; // not play show animation again when + } + return false; +} + +bool WindowNodeStateMachine::IsWindowNodeHiddenOrHiding() +{ + std::lock_guard lock(mutex_); + WLOGFD("IsWindowNodeHiddenOrHiding id:%{public}u state:%{public}u", windowId_, static_cast(currState_)); + if (currState_ == WindowNodeState::HIDE_ANIMATION_PLAYING || + currState_ == WindowNodeState::HIDE_ANIMATION_DONE || currState_ == WindowNodeState::HIDDEN) { + return true; // not play show animation again when + } + return false; +} + +WindowNodeState WindowNodeStateMachine::GetCurrentState() +{ + return currState_; +} +} // Rosen +} // OHOS \ No newline at end of file diff --git a/wmserver/src/window_root.cpp b/wmserver/src/window_root.cpp index ecfea14592..b2eae75423 100644 --- a/wmserver/src/window_root.cpp +++ b/wmserver/src/window_root.cpp @@ -537,6 +537,38 @@ Rect WindowRoot::GetDisplayRectWithoutSystemBarAreas(DisplayId displayId) return targetRect; } +void WindowRoot::GetAllAnimationPlayingNodes(std::vector>& windowNodes) +{ + for (const auto& it : windowNodeMap_) { + if (it.second) { + if (!WindowHelper::IsMainWindow(it.second->GetWindowType())) { + continue; + } + WLOGFI("id:%{public}u state:%{public}u", + it.second->GetWindowId(), static_cast(it.second->stateMachine_.GetCurrentState())); + if (it.second->stateMachine_.IsRemoteAnimationPlaying() || + it.second->stateMachine_.GetAnimationCount() > 0) { + windowNodes.emplace_back(it.second); + } + } + } +} + +void WindowRoot::LayoutWhenAddWindowNode(sptr& node, bool afterAnimation) +{ + if (node == nullptr) { + WLOGFE("LayoutWhenAddWindowNode failed, node is nullptr"); + return; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("add window failed, window container could not be found"); + return; + } + container->LayoutWhenAddWindowNode(node, afterAnimation); + return; +} + WMError WindowRoot::AddWindowNode(uint32_t parentId, sptr& node, bool fromStartingWin) { if (node == nullptr) { @@ -554,17 +586,17 @@ WMError WindowRoot::AddWindowNode(uint32_t parentId, sptr& node, boo return WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE; } - if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && - WindowHelper::IsAppWindow(node->GetWindowType()) && !node->isPlayAnimationShow_) { - container->NotifyDockWindowStateChanged(node, false); - WMError res = MinimizeStructuredAppWindowsExceptSelf(node); - if (res != WMError::WM_OK) { - WLOGFE("Minimize other structured window failed"); - MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW); - return res; - } - } if (fromStartingWin) { + if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && + WindowHelper::IsAppWindow(node->GetWindowType()) && !node->isPlayAnimationShow_) { + container->NotifyDockWindowStateChanged(node, false); + WMError res = MinimizeStructuredAppWindowsExceptSelf(node); + if (res != WMError::WM_OK) { + WLOGFE("Minimize other structured window failed"); + MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW); + return res; + } + } WMError res = container->ShowStartingWindow(node); if (res != WMError::WM_OK) { MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW); @@ -586,9 +618,6 @@ WMError WindowRoot::AddWindowNode(uint32_t parentId, sptr& node, boo } WMError res = container->AddWindowNode(node, parentNode); - if (!WindowHelper::IsSystemWindow(node->GetWindowType())) { - DestroyLeakStartingWindow(); - } if (res != WMError::WM_OK) { WLOGFE("AddWindowNode failed with ret: %{public}u", static_cast(res)); return res; @@ -597,7 +626,7 @@ WMError WindowRoot::AddWindowNode(uint32_t parentId, sptr& node, boo return PostProcessAddWindowNode(node, parentNode, container); } -WMError WindowRoot::RemoveWindowNode(uint32_t windowId) +WMError WindowRoot::RemoveWindowNode(uint32_t windowId, bool fromAnimation) { auto node = GetWindowNode(windowId); if (node == nullptr) { @@ -613,7 +642,7 @@ WMError WindowRoot::RemoveWindowNode(uint32_t windowId) UpdateFocusWindowWithWindowRemoved(node, container); auto nextOrientationWindow = UpdateActiveWindowWithWindowRemoved(node, container); UpdateBrightnessWithWindowRemoved(windowId, container); - WMError res = container->RemoveWindowNode(node); + WMError res = container->RemoveWindowNode(node, fromAnimation); if (res == WMError::WM_OK) { for (auto& child : node->children_) { if (child == nullptr) { @@ -759,6 +788,7 @@ WMError WindowRoot::DestroyWindow(uint32_t windowId, bool onlySelf) WLOGFE("destroy window failed, because window node is not exist."); return WMError::WM_ERROR_NULLPTR; } + WLOGFI("destroy window %{public}u, onlySelf:%{public}u.", windowId, onlySelf); WMError res; auto token = node->abilityToken_; auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); @@ -770,8 +800,7 @@ WMError WindowRoot::DestroyWindow(uint32_t windowId, bool onlySelf) if (onlySelf) { for (auto& child : node->children_) { child->parent_ = nullptr; - if ((child != nullptr) && (child->GetWindowToken() != nullptr) && - (child->abilityToken_ != token) && + if ((child != nullptr) && (child->GetWindowToken() != nullptr) && (child->abilityToken_ != token) && (child->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG)) { child->GetWindowToken()->NotifyDestroy(); } @@ -791,8 +820,7 @@ WMError WindowRoot::DestroyWindow(uint32_t windowId, bool onlySelf) HandleKeepScreenOn(id, false); DestroyWindowInner(node); } - if ((node != nullptr) && (node->GetWindowToken() != nullptr) && - (node->abilityToken_ != token) && + if ((node != nullptr) && (node->GetWindowToken() != nullptr) && (node->abilityToken_ != token) && (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG)) { node->GetWindowToken()->NotifyDestroy(); } diff --git a/wmserver/test/unittest/minimize_app_test.cpp b/wmserver/test/unittest/minimize_app_test.cpp index b4580b5ba2..87f89bc035 100644 --- a/wmserver/test/unittest/minimize_app_test.cpp +++ b/wmserver/test/unittest/minimize_app_test.cpp @@ -114,7 +114,7 @@ HWTEST_F(MinimizeAppTest, MinimizeAppTest02, Function | SmallTest | Level2) MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::MINIMIZE_ALL); - auto getNodes = MinimizeApp::GetNeedMinimizeAppNodes(); + auto getNodes = MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_ALL); ASSERT_EQ(node1, getNodes[0]); MinimizeApp::ClearNodesWithReason(MinimizeReason::MINIMIZE_ALL); -- Gitee