• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/stage/stage_manager.h"
17 
18 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
19 #include "base/log/ace_checker.h"
20 #include "base/perfmonitor/perf_constants.h"
21 #include "base/perfmonitor/perf_monitor.h"
22 #include "core/common/ime/input_method_manager.h"
23 #include "base/ressched/ressched_report.h"
24 
25 #if !defined(ACE_UNITTEST)
26 #include "core/components_ng/base/transparent_node_detector.h"
27 #endif
28 
29 #include "core/components_ng/pattern/stage/page_pattern.h"
30 
31 namespace OHOS::Ace::NG {
32 std::string KEY_PAGE_TRANSITION_PROPERTY = "pageTransitionProperty";
33 namespace {
34 constexpr char EMPTY_PAGE_INFO[] = "NA";
35 
FirePageTransition(const RefPtr<FrameNode> & page,PageTransitionType transitionType)36 void FirePageTransition(const RefPtr<FrameNode>& page, PageTransitionType transitionType)
37 {
38     CHECK_NULL_VOID(page);
39     auto pagePattern = page->GetPattern<PagePattern>();
40     CHECK_NULL_VOID(pagePattern);
41     auto eventHub = page->GetEventHub<EventHub>();
42     CHECK_NULL_VOID(eventHub);
43     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
44         if (transitionType == PageTransitionType::EXIT_POP) {
45             eventHub->SetEnabled(false);
46         }
47     } else {
48         eventHub->SetEnabled(false);
49     }
50     pagePattern->SetPageInTransition(true);
51     auto context = PipelineContext::GetCurrentContext();
52     CHECK_NULL_VOID(context);
53     auto stageManager = context->GetStageManager();
54     CHECK_NULL_VOID(stageManager);
55     stageManager->SetStageInTrasition(true);
56     pagePattern->SetAnimationId(stageManager->GetAnimationId());
57     if (transitionType == PageTransitionType::EXIT_PUSH || transitionType == PageTransitionType::EXIT_POP) {
58         pagePattern->TriggerPageTransition([weakPattern = WeakPtr<PagePattern>(pagePattern),
59             animationId = stageManager->GetAnimationId(), transitionType]() {
60                 auto pagePattern = weakPattern.Upgrade();
61                 CHECK_NULL_VOID(pagePattern);
62                 pagePattern->FinishOutPage(animationId, transitionType);
63             }, transitionType);
64         pagePattern->RemoveJsChildImmediately(page, transitionType);
65         return;
66     }
67     ACE_SCOPED_TRACE_COMMERCIAL("Router Page Transition Start");
68     PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
69     pagePattern->TriggerPageTransition(
70         [weak = WeakPtr<PagePattern>(pagePattern), animationId = stageManager->GetAnimationId(), transitionType]() {
71             auto pagePattern = weak.Upgrade();
72             CHECK_NULL_VOID(pagePattern);
73             auto page = pagePattern->GetHost();
74             CHECK_NULL_VOID(page);
75             TAG_LOGI(AceLogTag::ACE_ANIMATION, "pageTransition in finish, nodeId:%{public}d", page->GetId());
76             pagePattern->FinishInPage(animationId, transitionType);
77         }, transitionType);
78 }
79 } // namespace
80 
StartTransition(const RefPtr<FrameNode> & srcPage,const RefPtr<FrameNode> & destPage,RouteType type)81 void StageManager::StartTransition(const RefPtr<FrameNode>& srcPage, const RefPtr<FrameNode>& destPage, RouteType type)
82 {
83     auto pipeline = PipelineContext::GetCurrentContext();
84     CHECK_NULL_VOID(pipeline);
85     auto sharedManager = pipeline->GetSharedOverlayManager();
86     CHECK_NULL_VOID(sharedManager);
87     sharedManager->StartSharedTransition(srcPage, destPage);
88     animationSrcPage_ = srcPage;
89     destPageNode_ = destPage;
90     TAG_LOGI(AceLogTag::ACE_ANIMATION, "start pageTransition, from node %{public}d to %{public}d",
91         srcPage ? srcPage->GetId() : -1, destPage ? destPage->GetId() : -1);
92     // don't need to add animation id when routeType is none
93     if (type == RouteType::NONE) {
94         return;
95     }
96     animationId_++;
97     if (type == RouteType::PUSH) {
98         pushAnimations_.clear();
99         FirePageTransition(srcPage, PageTransitionType::EXIT_PUSH);
100         FirePageTransition(destPage, PageTransitionType::ENTER_PUSH);
101     } else if (type == RouteType::POP) {
102         popAnimations_.clear();
103         FirePageTransition(srcPage, PageTransitionType::EXIT_POP);
104         FirePageTransition(destPage, PageTransitionType::ENTER_POP);
105     }
106 }
107 
StageManager(const RefPtr<FrameNode> & stage)108 StageManager::StageManager(const RefPtr<FrameNode>& stage) : stageNode_(stage)
109 {
110     CHECK_NULL_VOID(stageNode_);
111     stagePattern_ = DynamicCast<StagePattern>(stageNode_->GetPattern());
112 }
113 
PageChangeCloseKeyboard()114 void StageManager::PageChangeCloseKeyboard()
115 {
116     // close keyboard
117 #if defined (ENABLE_STANDARD_INPUT)
118     if (Container::CurrentId() == CONTAINER_ID_DIVIDE_SIZE) {
119         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "StageManager FrameNode notNeedSoftKeyboard.");
120         auto container = Container::Current();
121         if (!container) {
122             return;
123         }
124         if (!container->IsScenceBoardWindow()) {
125             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Container not ScenceBoardWindow.");
126             InputMethodManager::GetInstance()->CloseKeyboard();
127         }
128     }
129 #endif
130 }
131 
PushPage(const RefPtr<FrameNode> & node,bool needHideLast,bool needTransition)132 bool StageManager::PushPage(const RefPtr<FrameNode>& node, bool needHideLast, bool needTransition)
133 {
134     CHECK_NULL_RETURN(stageNode_, false);
135     CHECK_NULL_RETURN(node, false);
136     int64_t startTime = GetSysTimestamp();
137     auto pipeline = AceType::DynamicCast<NG::PipelineContext>(PipelineBase::GetCurrentContext());
138     CHECK_NULL_RETURN(pipeline, false);
139     StopPageTransition(needTransition);
140     const auto& children = stageNode_->GetChildren();
141     RefPtr<FrameNode> outPageNode;
142     needTransition &= !children.empty();
143     if (children.empty()) {
144         auto pagePattern = node->GetPattern<NG::PagePattern>();
145         CHECK_NULL_RETURN(pagePattern, false);
146         auto pageInfo = pagePattern->GetPageInfo();
147         CHECK_NULL_RETURN(pageInfo, false);
148         auto pagePath = pageInfo->GetFullPath();
149         ACE_SCOPED_TRACE_COMMERCIAL("Router Main Page: %s", pagePath.c_str());
150         UiSessionManager::GetInstance()->OnRouterChange(pagePath, "routerPushPage");
151     }
152     if (needTransition) {
153         pipeline->FlushPipelineImmediately();
154     }
155     RefPtr<UINode> hidePageNode;
156     auto isNewLifecycle = AceApplicationInfo::GetInstance()
157         .GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE);
158     if (!children.empty() && needHideLast) {
159         hidePageNode = srcPageNode_.Upgrade();
160         outPageNode = AceType::DynamicCast<FrameNode>(hidePageNode);
161         FireAutoSave(outPageNode, node);
162         if (!isNewLifecycle) {
163             FirePageHide(hidePageNode, needTransition ? PageTransitionType::EXIT_PUSH : PageTransitionType::NONE);
164         }
165 
166     }
167     auto rect = stageNode_->GetGeometryNode()->GetFrameRect();
168     rect.SetOffset({});
169     node->GetRenderContext()->SyncGeometryProperties(rect);
170     // mount to parent and mark build render tree.
171     node->MountToParent(stageNode_);
172     // then build the total child. Build will trigger page create and onAboutToAppear
173     node->Build(nullptr);
174     // fire new lifecycle
175     if (hidePageNode && needHideLast && isNewLifecycle) {
176         FirePageHide(hidePageNode, needTransition ? PageTransitionType::EXIT_PUSH : PageTransitionType::NONE);
177     }
178     stageNode_->RebuildRenderContextTree();
179     FirePageShow(node, needTransition ? PageTransitionType::ENTER_PUSH : PageTransitionType::NONE);
180 
181     auto pagePattern = node->GetPattern<PagePattern>();
182     CHECK_NULL_RETURN(pagePattern, false);
183     stagePattern_->SetCurrentPageIndex(pagePattern->GetPageInfo()->GetPageId());
184     if (AceChecker::IsPerformanceCheckEnabled()) {
185         // After completing layout tasks at all nodes on the page, perform performance testing and management
186         pipeline->AddAfterLayoutTask([weakStage = WeakClaim(this), weakNode = WeakPtr<FrameNode>(node), startTime]() {
187             auto stage = weakStage.Upgrade();
188             CHECK_NULL_VOID(stage);
189             auto pageNode = weakNode.Upgrade();
190             int64_t endTime = GetSysTimestamp();
191             auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
192             CHECK_NULL_VOID(pagePattern);
193             auto pageInfo = pagePattern->GetPageInfo();
194             CHECK_NULL_VOID(pageInfo);
195             auto pagePath = pageInfo->GetFullPath();
196             stage->PerformanceCheck(pageNode, endTime - startTime, pagePath);
197         });
198     }
199 #if !defined(ACE_UNITTEST)
200     auto pageInfo = pagePattern->GetPageInfo();
201     std::string pageUrl = "";
202     if (pageInfo) {
203         pageUrl = pageInfo->GetFullPath();
204     }
205     TransparentNodeDetector::GetInstance().PostCheckNodeTransparentTask(node, pageUrl);
206 #endif
207 
208     // close keyboard
209     PageChangeCloseKeyboard();
210     AddPageTransitionTrace(outPageNode, node);
211     if (needTransition) {
212         pipeline->AddAfterLayoutTask([weakStage = WeakClaim(this), weakIn = WeakPtr<FrameNode>(node),
213                                          weakOut = WeakPtr<FrameNode>(outPageNode)]() {
214             auto stage = weakStage.Upgrade();
215             CHECK_NULL_VOID(stage);
216             auto inPageNode = weakIn.Upgrade();
217             auto outPageNode = weakOut.Upgrade();
218             stage->StartTransition(outPageNode, inPageNode, RouteType::PUSH);
219         });
220     }
221 
222     // flush layout task.
223     if (!stageNode_->GetGeometryNode()->GetMarginFrameSize().IsPositive()) {
224         // in first load case, wait for window size.
225         return true;
226     }
227     stageNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
228     node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
229 
230     return true;
231 }
232 
InsertPage(const RefPtr<FrameNode> & node,bool bellowTopOrBottom)233 bool StageManager::InsertPage(const RefPtr<FrameNode>& node, bool bellowTopOrBottom)
234 {
235     CHECK_NULL_RETURN(stageNode_, false);
236     CHECK_NULL_RETURN(node, false);
237 
238     const auto& children = stageNode_->GetChildren();
239     if (children.empty()) {
240         return false;
241     }
242 
243     RefPtr<FrameNode> targetNode = nullptr;
244     if (bellowTopOrBottom) {
245         targetNode = AceType::DynamicCast<FrameNode>(children.back());
246     } else {
247         targetNode = AceType::DynamicCast<FrameNode>(children.front());
248     }
249     auto rect = stageNode_->GetGeometryNode()->GetFrameRect();
250     rect.SetOffset({});
251     node->GetRenderContext()->SyncGeometryProperties(rect);
252     // mount to parent and mark build render tree.
253     stageNode_->AddChildBefore(node, targetNode);
254     // then build the total child. Build will trigger page create and onAboutToAppear
255     node->Build(nullptr);
256 
257     stageNode_->RebuildRenderContextTree();
258 
259     stageNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
260     node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
261     return true;
262 }
263 
PerformanceCheck(const RefPtr<FrameNode> & pageNode,int64_t vsyncTimeout,std::string path)264 void StageManager::PerformanceCheck(const RefPtr<FrameNode>& pageNode, int64_t vsyncTimeout, std::string path)
265 {
266     CHECK_NULL_VOID(pageNode);
267     PerformanceCheckNodeMap nodeMap;
268     pageNode->GetPerformanceCheckData(nodeMap);
269     AceScopedPerformanceCheck::RecordPerformanceCheckData(nodeMap, vsyncTimeout, path);
270 }
271 
PopPage(const RefPtr<FrameNode> & inPage,bool needShowNext,bool needTransition)272 bool StageManager::PopPage(const RefPtr<FrameNode>& inPage, bool needShowNext, bool needTransition)
273 {
274     auto pipeline = PipelineContext::GetCurrentContext();
275     CHECK_NULL_RETURN(pipeline, false);
276     CHECK_NULL_RETURN(stageNode_, false);
277     StopPageTransition(needTransition);
278     const auto& children = stageNode_->GetChildren();
279     if (children.empty()) {
280         TAG_LOGI(AceLogTag::ACE_ROUTER, "router pop page start, children is empty");
281         return false;
282     }
283     auto pageNode = srcPageNode_.Upgrade();
284     const size_t transitionPageSize = 2;
285     needTransition &= (children.size() >= transitionPageSize);
286     if (needTransition) {
287         pipeline->FlushPipelineImmediately();
288     }
289     auto outPageNode = AceType::DynamicCast<FrameNode>(pageNode);
290     auto inPageNode = needShowNext ? inPage : nullptr;
291     pipeline->GetMemoryManager()->RebuildImageByPage(inPageNode);
292     FireAutoSave(outPageNode, inPageNode);
293     FirePageHide(pageNode, needTransition ? PageTransitionType::EXIT_POP : PageTransitionType::NONE);
294     FirePageShow(inPageNode, needTransition ? PageTransitionType::ENTER_POP : PageTransitionType::NONE);
295 
296     // close keyboard
297     PageChangeCloseKeyboard();
298 
299     AddPageTransitionTrace(outPageNode, inPageNode);
300     if (needTransition) {
301         StartTransition(outPageNode, inPageNode, RouteType::POP);
302         if (inPageNode) {
303             inPageNode->OnAccessibilityEvent(AccessibilityEventType::CHANGE);
304         }
305         return true;
306     }
307     if (pageNode) {
308         stageNode_->RemoveChild(pageNode);
309         pageNode->SetChildrenInDestroying();
310     }
311     stageNode_->RebuildRenderContextTree();
312     pipeline->RequestFrame();
313     return true;
314 }
315 
PopPageToIndex(int32_t index,bool needShowNext,bool needTransition)316 bool StageManager::PopPageToIndex(int32_t index, bool needShowNext, bool needTransition)
317 {
318     auto pipeline = PipelineContext::GetCurrentContext();
319     CHECK_NULL_RETURN(pipeline, false);
320     CHECK_NULL_RETURN(stageNode_, false);
321     StopPageTransition(needTransition);
322     const auto& children = stageNode_->GetChildren();
323     if (children.empty()) {
324         return false;
325     }
326     int32_t popSize = static_cast<int32_t>(children.size()) - index - 1;
327     if (popSize < 0) {
328         return false;
329     }
330     if (popSize == 0) {
331         return true;
332     }
333     auto outPageNode = AceType::DynamicCast<FrameNode>(srcPageNode_.Upgrade());
334     if (needTransition) {
335         pipeline->FlushPipelineImmediately();
336     }
337     bool firstPageTransition = true;
338     auto iter = children.rbegin();
339     for (int32_t current = 0; current < popSize; ++current) {
340         auto pageNode = *iter;
341         if (!needTransition|| !CheckPageInTransition(pageNode)) {
342             FirePageHide(
343                 pageNode,
344                 firstPageTransition && needTransition ?PageTransitionType::EXIT_POP : PageTransitionType::NONE);
345             firstPageTransition = false;
346         }
347         ++iter;
348     }
349 
350     RefPtr<FrameNode> inPageNode;
351     if (needShowNext) {
352         const auto& newPageNode = *iter;
353         FirePageShow(newPageNode, needTransition ? PageTransitionType::ENTER_POP : PageTransitionType::NONE);
354         inPageNode = AceType::DynamicCast<FrameNode>(newPageNode);
355         pipeline->GetMemoryManager()->RebuildImageByPage(inPageNode);
356     }
357     PageChangeCloseKeyboard();
358     AddPageTransitionTrace(outPageNode, inPageNode);
359 
360     FireAutoSave(outPageNode, inPageNode);
361     if (needTransition) {
362         // from the penultimate node, (popSize - 1) nodes are deleted.
363         // the last node will be deleted after pageTransition
364         for (int32_t current = 1; current < popSize; ++current) {
365             auto pageNode = *(++children.rbegin());
366             if (CheckPageInTransition(pageNode)) {
367                 UpdatePageNeedRemove(pageNode);
368             } else {
369                 stageNode_->RemoveChild(pageNode);
370             }
371         }
372         stageNode_->RebuildRenderContextTree();
373         StartTransition(outPageNode, inPageNode, RouteType::POP);
374         if (inPageNode) {
375             inPageNode->OnAccessibilityEvent(AccessibilityEventType::CHANGE);
376         }
377         return true;
378     }
379     for (int32_t current = 0; current < popSize; ++current) {
380         auto pageNode = children.back();
381         stageNode_->RemoveChild(pageNode);
382     }
383     stageNode_->RebuildRenderContextTree();
384     pipeline->RequestFrame();
385     return true;
386 }
387 
CleanPageStack()388 bool StageManager::CleanPageStack()
389 {
390     auto pipeline = PipelineContext::GetCurrentContext();
391     CHECK_NULL_RETURN(pipeline, false);
392     CHECK_NULL_RETURN(stageNode_, false);
393     const auto& children = stageNode_->GetChildren();
394     if (children.size() <= 1) {
395         return false;
396     }
397     auto popSize = static_cast<int32_t>(children.size()) - 1;
398     for (int32_t count = 1; count <= popSize; ++count) {
399         auto pageNode = children.front();
400         // mark pageNode child as destroying
401         pageNode->SetChildrenInDestroying();
402         stageNode_->RemoveChild(pageNode);
403     }
404     pipeline->GetMemoryManager()->RebuildImageByPage(AceType::DynamicCast<FrameNode>(children.back()));
405     stageNode_->RebuildRenderContextTree();
406     pipeline->RequestFrame();
407     return true;
408 }
409 
MovePageToFront(const RefPtr<FrameNode> & node,bool needHideLast,bool needTransition)410 bool StageManager::MovePageToFront(const RefPtr<FrameNode>& node, bool needHideLast, bool needTransition)
411 {
412     auto pipeline = PipelineContext::GetCurrentContext();
413     CHECK_NULL_RETURN(pipeline, false);
414     CHECK_NULL_RETURN(stageNode_, false);
415     StopPageTransition(needTransition);
416     const auto& children = stageNode_->GetChildren();
417     if (children.empty()) {
418         return false;
419     }
420     const auto& lastPage = children.back();
421     if (lastPage == node) {
422         return true;
423     }
424     if (needTransition) {
425         pipeline->FlushPipelineImmediately();
426     }
427     if (needHideLast) {
428         FirePageHide(lastPage, needTransition ? PageTransitionType::EXIT_PUSH : PageTransitionType::NONE);
429     }
430     node->MovePosition(static_cast<int32_t>(stageNode_->GetChildren().size()) - 1);
431     auto pattern = node->GetPattern<PagePattern>();
432     if  (pattern) {
433         pattern->ResetPageTransitionEffect();
434     }
435     FirePageShow(node, needTransition ? PageTransitionType::ENTER_PUSH : PageTransitionType::NONE);
436 
437     stageNode_->RebuildRenderContextTree();
438     auto outPageNode = AceType::DynamicCast<FrameNode>(lastPage);
439     AddPageTransitionTrace(outPageNode, node);
440     FireAutoSave(outPageNode, node);
441     if (needTransition) {
442         StartTransition(outPageNode, node, RouteType::PUSH);
443         if (node) {
444             node->OnAccessibilityEvent(AccessibilityEventType::CHANGE);
445         }
446     }
447     pipeline->RequestFrame();
448     return true;
449 }
450 
FirePageHide(const RefPtr<UINode> & node,PageTransitionType transitionType)451 void StageManager::FirePageHide(const RefPtr<UINode>& node, PageTransitionType transitionType)
452 {
453     auto pageNode = DynamicCast<FrameNode>(node);
454     CHECK_NULL_VOID(pageNode);
455     auto pagePattern = pageNode->GetPattern<PagePattern>();
456     CHECK_NULL_VOID(pagePattern);
457     pagePattern->FocusViewHide();
458     pagePattern->OnHide();
459     if (transitionType == PageTransitionType::NONE) {
460         // If there is a page transition, this function should execute after page transition,
461         // otherwise the page will not be visible
462         pagePattern->ProcessHideState();
463     }
464 
465     auto context = PipelineContext::GetCurrentContext();
466     CHECK_NULL_VOID(context);
467     context->MarkNeedFlushMouseEvent();
468 }
469 
FirePageShow(const RefPtr<UINode> & node,PageTransitionType transitionType,bool needFocus)470 void StageManager::FirePageShow(const RefPtr<UINode>& node, PageTransitionType transitionType, bool needFocus)
471 {
472     auto pageNode = DynamicCast<FrameNode>(node);
473     CHECK_NULL_VOID(pageNode);
474     auto layoutProperty = pageNode->GetLayoutProperty();
475 
476     auto pagePattern = pageNode->GetPattern<PagePattern>();
477     CHECK_NULL_VOID(pagePattern);
478     if (needFocus) {
479         pagePattern->FocusViewShow();
480     }
481     pagePattern->OnShow();
482     // With or without a page transition, we need to make the coming page visible first
483     pagePattern->ProcessShowState();
484 
485     auto context = PipelineContext::GetCurrentContext();
486     CHECK_NULL_VOID(context);
487     context->MarkNeedFlushMouseEvent();
488 #ifdef UICAST_COMPONENT_SUPPORTED
489     do {
490         auto container = Container::Current();
491         CHECK_NULL_BREAK(container);
492         auto distributedUI = container->GetDistributedUI();
493         CHECK_NULL_BREAK(distributedUI);
494         distributedUI->OnPageChanged(node->GetPageId());
495     } while (false);
496 #endif
497 }
498 
FireAutoSave(const RefPtr<FrameNode> & outPageNode,const RefPtr<FrameNode> & inPageNode)499 void StageManager::FireAutoSave(const RefPtr<FrameNode>& outPageNode, const RefPtr<FrameNode>& inPageNode)
500 {
501     CHECK_NULL_VOID(outPageNode);
502     auto outPagePattern = outPageNode->GetPattern<PagePattern>();
503     CHECK_NULL_VOID(outPagePattern);
504     auto onUIExtNodeDestroy = [weak = WeakPtr<FrameNode>(inPageNode)]() {
505         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "UIExtNodeDestroy called.");
506         auto page = weak.Upgrade();
507         CHECK_NULL_VOID(page);
508         auto pattern = page->GetPattern<PagePattern>();
509         CHECK_NULL_VOID(pattern);
510         pattern->SetIsModalCovered(false);
511     };
512     auto onUIExtNodeBindingCompleted = [weak = WeakPtr<FrameNode>(inPageNode)]() {
513         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "UIExtNodeBindingCompleted called.");
514         auto page = weak.Upgrade();
515         CHECK_NULL_VOID(page);
516         auto pattern = page->GetPattern<PagePattern>();
517         CHECK_NULL_VOID(pattern);
518         pattern->SetIsModalCovered(true);
519     };
520     outPagePattern->ProcessAutoSave(onUIExtNodeDestroy, onUIExtNodeBindingCompleted);
521 }
522 
GetLastPage() const523 RefPtr<FrameNode> StageManager::GetLastPage() const
524 {
525     CHECK_NULL_RETURN(stageNode_, nullptr);
526     const auto& children = stageNode_->GetChildren();
527     if (children.empty()) {
528         return nullptr;
529     }
530     return DynamicCast<FrameNode>(children.back());
531 }
532 
GetPageById(int32_t pageId)533 RefPtr<FrameNode> StageManager::GetPageById(int32_t pageId)
534 {
535     CHECK_NULL_RETURN(stageNode_, nullptr);
536     const auto& children = stageNode_->GetChildren();
537     for (const auto& child : children) {
538         if (child->GetPageId() == pageId) {
539             return DynamicCast<FrameNode>(child);
540         }
541     }
542     return nullptr;
543 }
544 
ReloadStage()545 void StageManager::ReloadStage()
546 {
547     CHECK_NULL_VOID(stageNode_);
548     const auto& children = stageNode_->GetChildren();
549     for (const auto& child : children) {
550         auto frameNode = DynamicCast<FrameNode>(child);
551         if (!frameNode) {
552             continue;
553         }
554         auto pagePattern = frameNode->GetPattern<PagePattern>();
555         if (!pagePattern) {
556             continue;
557         }
558         pagePattern->ReloadPage();
559     }
560 }
561 
GetLastPageWithTransition() const562 RefPtr<FrameNode> StageManager::GetLastPageWithTransition() const
563 {
564     CHECK_NULL_RETURN(stageNode_, nullptr);
565     const auto& children = stageNode_->GetChildren();
566     if (children.empty()) {
567         return nullptr;
568     }
569     auto lastChildFrame = DynamicCast<FrameNode>(children.back());
570     auto pagePattern = lastChildFrame->GetPattern<PagePattern>();
571     if (pagePattern && pagePattern->GetPageInTransition()) {
572         return DynamicCast<FrameNode>(destPageNode_.Upgrade());
573     }
574     return lastChildFrame;
575 }
576 
GetPrevPageWithTransition() const577 RefPtr<FrameNode> StageManager::GetPrevPageWithTransition() const
578 {
579     CHECK_NULL_RETURN(stageNode_, nullptr);
580     const auto& children = stageNode_->GetChildren();
581     if (children.empty()) {
582         return nullptr;
583     }
584     if (stageInTrasition_) {
585         return DynamicCast<FrameNode>(animationSrcPage_.Upgrade());
586     }
587     return DynamicCast<FrameNode>(children.front());
588 }
589 
AddPageTransitionTrace(const RefPtr<FrameNode> & srcPage,const RefPtr<FrameNode> & destPage)590 void StageManager::AddPageTransitionTrace(const RefPtr<FrameNode>& srcPage, const RefPtr<FrameNode>& destPage)
591 {
592     if (!destPage) {
593         CHECK_NULL_VOID(srcPage);
594         // when replace with pop first, destPage node info is empty, record srcPage info and use it when push happen.
595         auto srcPattern = srcPage->GetPattern<NG::PagePattern>();
596         CHECK_NULL_VOID(srcPattern);
597         auto srcPageInfo = srcPattern->GetPageInfo();
598         CHECK_NULL_VOID(srcPageInfo);
599         replaceSrcPageInfo_ = srcPageInfo->GetFullPath();
600         TAG_LOGD(AceLogTag::ACE_ROUTER, "replace router page with pop first, record srcPage info %{public}s",
601             replaceSrcPageInfo_.c_str());
602         return;
603     }
604 
605     std::string srcFullPath = GetSrcPageInfo(srcPage);
606     if (srcFullPath.empty()) {
607         srcFullPath = replaceSrcPageInfo_.empty() ? EMPTY_PAGE_INFO : replaceSrcPageInfo_;
608         replaceSrcPageInfo_.clear();
609     }
610 
611     auto destPattern = destPage->GetPattern<NG::PagePattern>();
612     CHECK_NULL_VOID(destPattern);
613     auto destPageInfo = destPattern->GetPageInfo();
614     CHECK_NULL_VOID(destPageInfo);
615     auto destFullPath = destPageInfo->GetFullPath();
616 
617     ResSchedReport::GetInstance().HandlePageTransition(GetPagePath(srcPage), destPageInfo->GetPagePath(), "Rounter");
618     ACE_SCOPED_TRACE_COMMERCIAL("Router Page from %s to %s", srcFullPath.c_str(), destFullPath.c_str());
619 }
620 
SyncPageSafeArea(bool keyboardSafeArea)621 void StageManager::SyncPageSafeArea(bool keyboardSafeArea)
622 {
623     auto changeType = keyboardSafeArea ? PROPERTY_UPDATE_LAYOUT : PROPERTY_UPDATE_MEASURE;
624     auto lastPage = GetLastPageWithTransition();
625     CHECK_NULL_VOID(lastPage);
626     lastPage->MarkDirtyNode(changeType);
627     auto lastPageOverlay = lastPage->GetPattern<PagePattern>();
628     CHECK_NULL_VOID(lastPageOverlay);
629     lastPageOverlay->MarkDirtyOverlay();
630 
631     auto prevPage = GetPrevPageWithTransition();
632     CHECK_NULL_VOID(prevPage);
633     auto prevPageOverlay = prevPage->GetPattern<PagePattern>();
634     CHECK_NULL_VOID(prevPageOverlay);
635     prevPageOverlay->MarkDirtyOverlay();
636 }
637 
CheckPageFocus()638 bool StageManager::CheckPageFocus()
639 {
640     auto pageNode = GetLastPage();
641     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
642         pageNode = GetLastPageWithTransition();
643     }
644     CHECK_NULL_RETURN(pageNode, true);
645     return pageNode->GetFocusHub() && pageNode->GetFocusHub()->IsCurrentFocus();
646 }
647 
AbortAnimation()648 void StageManager::AbortAnimation()
649 {
650     if (!pushAnimations_.empty()) {
651         for (const auto& animation : pushAnimations_) {
652             if (animation) {
653                 AnimationUtils::StopAnimation(animation);
654             }
655         }
656         pushAnimations_.clear();
657     }
658     if (!popAnimations_.empty()) {
659         for (const auto& animation : popAnimations_) {
660             if (animation) {
661                 AnimationUtils::StopAnimation(animation);
662             }
663         }
664         popAnimations_.clear();
665     }
666 }
667 
GetSrcPageInfo(const RefPtr<FrameNode> & srcPage)668 std::string StageManager::GetSrcPageInfo(const RefPtr<FrameNode>& srcPage)
669 {
670     CHECK_NULL_RETURN(srcPage, "");
671     auto srcPattern = srcPage->GetPattern<NG::PagePattern>();
672     CHECK_NULL_RETURN(srcPattern, "");
673     auto srcPageInfo = srcPattern->GetPageInfo();
674     CHECK_NULL_RETURN(srcPageInfo, "");
675     return srcPageInfo->GetFullPath();
676 }
677 
CheckPageInTransition(const RefPtr<UINode> & pageNode)678 bool StageManager::CheckPageInTransition(const RefPtr<UINode>& pageNode)
679 {
680     auto frameNode = AceType::DynamicCast<FrameNode>(pageNode);
681     CHECK_NULL_RETURN(frameNode, false);
682     auto pagePattern = frameNode->GetPattern<PagePattern>();
683     CHECK_NULL_RETURN(pagePattern, false);
684     return pagePattern->GetPageInTransition();
685 }
686 
UpdatePageNeedRemove(const RefPtr<UINode> & pageNode)687 void StageManager::UpdatePageNeedRemove(const RefPtr<UINode>& pageNode)
688 {
689     auto frameNode = AceType::DynamicCast<FrameNode>(pageNode);
690     CHECK_NULL_VOID(frameNode);
691     auto pagePattern = frameNode->GetPattern<PagePattern>();
692     CHECK_NULL_VOID(pagePattern);
693     pagePattern->SetIsNeedRemove(true);
694 }
695 
StopPageTransition(bool needTransition)696 void StageManager::StopPageTransition(bool needTransition)
697 {
698     if (needTransition) {
699         return;
700     }
701     auto srcNode = animationSrcPage_.Upgrade();
702     if (srcNode) {
703         auto pattern = srcNode->GetPattern<PagePattern>();
704         pattern->StopPageTransition();
705         animationSrcPage_ = nullptr;
706     }
707     auto destNode = destPageNode_.Upgrade();
708     if (destNode) {
709         auto pattern = destNode->GetPattern<PagePattern>();
710         pattern->StopPageTransition();
711         destPageNode_ = nullptr;
712     }
713 }
714 
GetTopPagesWithTransition() const715 std::vector<RefPtr<FrameNode>> StageManager::GetTopPagesWithTransition() const
716 {
717     std::vector<RefPtr<FrameNode>> pages;
718     auto page = GetLastPageWithTransition();
719     if (page) {
720         pages.emplace_back(page);
721     }
722     return pages;
723 }
724 
GetTopPagePaths() const725 std::vector<std::string> StageManager::GetTopPagePaths() const
726 {
727     std::vector<std::string> paths;
728     auto pages = GetTopPagesWithTransition();
729     for (auto& page : pages) {
730         paths.emplace_back("");
731         CHECK_NULL_CONTINUE(page);
732         auto pattern = page->GetPattern<PagePattern>();
733         CHECK_NULL_CONTINUE(pattern);
734         auto info = pattern->GetPageInfo();
735         CHECK_NULL_CONTINUE(info);
736         CHECK_NULL_CONTINUE(getPagePathCallback_);
737         paths.back() = getPagePathCallback_(info->GetPageUrl());
738     }
739     return paths;
740 }
741 
GetPagePath(const RefPtr<FrameNode> & pageNode)742 std::string StageManager::GetPagePath(const RefPtr<FrameNode>& pageNode)
743 {
744     CHECK_NULL_RETURN(pageNode, "");
745     auto pattern = pageNode->GetPattern<NG::PagePattern>();
746     CHECK_NULL_RETURN(pattern, "");
747     auto info = pattern->GetPageInfo();
748     CHECK_NULL_RETURN(info, "");
749     return info->GetPagePath();
750 }
751 
752 } // namespace OHOS::Ace::NG
753