• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "rs_sub_thread_cache.h"
17 #include "rs_trace.h"
18 
19 #include "common/rs_common_hook.h"
20 #include "common/rs_optional_trace.h"
21 #include "display_engine/rs_luminance_control.h"
22 #include "drawable/rs_surface_render_node_drawable.h"
23 #include "feature/uifirst/rs_sub_thread_manager.h"
24 #include "feature/uifirst/rs_uifirst_manager.h"
25 #include "feature/uifirst/rs_uifirst_frame_rate_control.h"
26 #include "feature_cfg/graphic_feature_param_manager.h"
27 #include "memory/rs_memory_manager.h"
28 #include "params/rs_screen_render_params.h"
29 #include "pipeline/render_thread/rs_uni_render_util.h"
30 #include "pipeline/rs_canvas_render_node.h"
31 #include "pipeline/rs_root_render_node.h"
32 #include "pipeline/main_thread/rs_main_thread.h"
33 #include "platform/common/rs_log.h"
34 
35 #undef LOG_TAG
36 #define LOG_TAG "RSUifirstManager"
37 
38 // use in mainthread, post subthread, not affect renderthread
39 namespace OHOS {
40 namespace Rosen {
41 namespace {
42     constexpr int EVENT_START_TIMEOUT = 500;
43     constexpr int EVENT_STOP_TIMEOUT = 150;
44     constexpr int EVENT_DISABLE_UIFIRST_GAP = 100;
45     constexpr int CLEAR_CACHE_DELAY = 400;
46     const std::string CLEAR_CACHE_TASK_PREFIX = "uifirst_clear_cache_";
47     constexpr std::string_view ARKTSCARDNODE_NAME = "ArkTSCardNode";
48     constexpr std::string_view EVENT_DISABLE_UIFIRST = "APP_LIST_FLING";
49     constexpr int UIFIRST_TASKSKIP_PRIO_THRESHOLD = 3;
50     constexpr int UIFIRST_POSTTASK_HIGHPRIO_MAX = 6;
51     constexpr int SUBTHREAD_CONTROL_FRAMERATE_NODE_LIMIT = 10;
52     constexpr int CACHED_SURFACE_IS_TRANSPARENT = 0;
GetCurSysTime()53     inline int64_t GetCurSysTime()
54     {
55         auto curTime = std::chrono::system_clock::now().time_since_epoch();
56         return std::chrono::duration_cast<std::chrono::milliseconds>(curTime).count();
57     }
58 };
59 
Instance()60 RSUifirstManager& RSUifirstManager::Instance()
61 {
62     static RSUifirstManager instance; // store in mainthread instance ?
63     return instance;
64 }
65 
GetSurfaceDrawableByID(NodeId id)66 std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> RSUifirstManager::GetSurfaceDrawableByID(NodeId id)
67 {
68     if (const auto cacheIt = subthreadProcessingNode_.find(id); cacheIt != subthreadProcessingNode_.end()) {
69         const auto ptr = cacheIt->second;
70         if (ptr && ptr->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
71             return std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(ptr);
72         }
73     }
74     // unlikely
75     auto ptr = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
76     if (ptr && ptr->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
77         return std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(ptr);
78     }
79     return nullptr;
80 }
81 
SetUifirstNodeEnableParam(RSSurfaceRenderNode & node,MultiThreadCacheType type)82 bool RSUifirstManager::SetUifirstNodeEnableParam(RSSurfaceRenderNode& node, MultiThreadCacheType type)
83 {
84     auto ret = node.SetUifirstNodeEnableParam(type); // update drawable param
85     auto isType = type == MultiThreadCacheType::LEASH_WINDOW || type == MultiThreadCacheType::NONFOCUS_WINDOW;
86     if (node.IsLeashWindow() && type != MultiThreadCacheType::ARKTS_CARD) {
87         for (auto& child : *(node.GetChildren())) {
88             if (!child) {
89                 continue;
90             }
91             auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
92             if (!surfaceChild) {
93                 continue;
94             }
95             if (surfaceChild->IsMainWindowType()) {
96                 surfaceChild->SetIsParentUifirstNodeEnableParam(isType);
97                 continue;
98             }
99         }
100     }
101     return ret;
102 }
103 
104 // unref in sub when cache done
AddProcessDoneNode(NodeId id)105 void RSUifirstManager::AddProcessDoneNode(NodeId id)
106 {
107     // mutex
108     if (id == INVALID_NODEID) {
109         return;
110     }
111     RS_OPTIONAL_TRACE_NAME_FMT("sub done %" PRIu64"", id);
112     std::lock_guard<std::mutex> lock(childernDrawableMutex_);
113     subthreadProcessDoneNode_.push_back(id);
114 }
115 
AddProcessSkippedNode(NodeId id)116 void RSUifirstManager::AddProcessSkippedNode(NodeId id)
117 {
118     if (id == INVALID_NODEID) {
119         return;
120     }
121     RS_OPTIONAL_TRACE_NAME_FMT("sub skipped %" PRIu64, id);
122     std::lock_guard<std::mutex> lock(skippedNodeMutex_);
123     subthreadProcessSkippedNode_.insert(id);
124 }
125 
NeedNextDrawForSkippedNode()126 bool RSUifirstManager::NeedNextDrawForSkippedNode()
127 {
128     std::lock_guard<std::mutex> lock(skippedNodeMutex_);
129     return !subthreadProcessSkippedNode_.empty();
130 }
131 
ResetUifirstNode(std::shared_ptr<RSSurfaceRenderNode> & nodePtr)132 void RSUifirstManager::ResetUifirstNode(std::shared_ptr<RSSurfaceRenderNode>& nodePtr)
133 {
134     if (!nodePtr) {
135         return;
136     }
137     RS_TRACE_NAME_FMT("ResetUifirstNode name:%s,id:%" PRIu64 ",isOnTheTree:%d,"
138         "toBeCaptured:%d", nodePtr->GetName().c_str(), nodePtr->GetId(), nodePtr->IsOnTheTree(),
139         nodePtr->IsNodeToBeCaptured());
140     RS_LOGI("ResetUifirstNode name:%{public}s,id:%{public}" PRIu64 ",isOnTheTree:%{public}d,"
141         "toBeCaptured:%{public}d", nodePtr->GetName().c_str(), nodePtr->GetId(), nodePtr->IsOnTheTree(),
142         nodePtr->IsNodeToBeCaptured());
143     pendingPostNodes_.erase(nodePtr->GetId());
144     pendingPostCardNodes_.erase(nodePtr->GetId());
145     nodePtr->SetUifirstUseStarting(false);
146     if (SetUifirstNodeEnableParam(*nodePtr, MultiThreadCacheType::NONE)) {
147         // enable ->disable
148         SetNodeNeedForceUpdateFlag(true);
149         pendingForceUpdateNode_.push_back(nodePtr->GetId());
150     }
151     RSMainThread::Instance()->GetContext().AddPendingSyncNode(nodePtr);
152 
153     auto drawable = GetSurfaceDrawableByID(nodePtr->GetId());
154     if (!drawable) {
155         return;
156     }
157     auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
158     if (!nodePtr->IsOnTheTree() && nodePtr->IsNodeToBeCaptured()) {
159         rsSubThreadCache.ResetUifirst(true);
160         auto taskName = CLEAR_CACHE_TASK_PREFIX + std::to_string(nodePtr->GetId());
161         auto releaseTask = [drawable] {
162             auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
163             if (surfaceParams && surfaceParams->GetUifirstNodeEnableParam() == MultiThreadCacheType::NONE) {
164                 RS_TRACE_NAME_FMT("ResetUifirstNode clearCache id:%llu", surfaceParams->GetId());
165                 drawable->GetRsSubThreadCache().ResetUifirst();
166             }
167         };
168         RSUniRenderThread::Instance().PostTask(releaseTask, taskName, CLEAR_CACHE_DELAY);
169     } else {
170         nodePtr->SetIsNodeToBeCaptured(false);
171         rsSubThreadCache.ResetUifirst();
172     }
173 }
174 
ResetWindowCache(std::shared_ptr<RSSurfaceRenderNode> & nodePtr)175 void RSUifirstManager::ResetWindowCache(std::shared_ptr<RSSurfaceRenderNode>& nodePtr)
176 {
177     if (!nodePtr) {
178         RS_LOGE("ResetWindowCache nodePtr is null");
179         return;
180     }
181     auto drawable = GetSurfaceDrawableByID(nodePtr->GetId());
182     if (!drawable) {
183         RS_LOGE("ResetWindowCache drawable is null");
184         return;
185     }
186     // run in RT thread
187     drawable->GetRsSubThreadCache().ResetWindowCache();
188 }
189 
MergeOldDirty(NodeId id)190 void RSUifirstManager::MergeOldDirty(NodeId id)
191 {
192     if (!mainThread_) {
193         return;
194     }
195     auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
196         mainThread_->GetContext().GetNodeMap().GetRenderNode(id));
197     if (!node) {
198         return;
199     }
200     if (node->IsAppWindow() &&
201         !RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node->GetParent().lock())) {
202         auto& curDirtyManager = node->GetDirtyManagerForUifirst();
203         if (curDirtyManager) {
204             curDirtyManager->SetUifirstFrameDirtyRect(node->GetOldDirty());
205         }
206         return;
207     }
208     bool hasAppWindow = false;
209     for (auto& child : * node-> GetSortedChildren()) {
210         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
211         if (surfaceNode && surfaceNode->IsAppWindow()) {
212             hasAppWindow = true;
213             auto& curDirtyManager = surfaceNode->GetDirtyManagerForUifirst();
214             if (curDirtyManager) {
215                 curDirtyManager->SetUifirstFrameDirtyRect(surfaceNode->GetOldDirty());
216             }
217             break;
218         }
219     }
220     if (!hasAppWindow) {
221         auto& curDirtyManager = node->GetDirtyManagerForUifirst();
222         if (curDirtyManager) {
223             curDirtyManager->SetUifirstFrameDirtyRect(node->GetOldDirty());
224         }
225     }
226 }
227 
MergeOldDirtyToDirtyManager(std::shared_ptr<RSSurfaceRenderNode> & node)228 void RSUifirstManager::MergeOldDirtyToDirtyManager(std::shared_ptr<RSSurfaceRenderNode>& node)
229 {
230     auto& curDirtyManager = node->GetDirtyManagerForUifirst();
231     if (!curDirtyManager) {
232         RS_LOGE("MergeOldDirtyToDirtyManager curDirtyManager is nullptr");
233         return;
234     }
235     auto curDirtyRegion = curDirtyManager->GetCurrentFrameDirtyRegion();
236     auto uifirstDirtyRegion = curDirtyManager->GetUifirstFrameDirtyRegion();
237     curDirtyManager->MergeDirtyRect(uifirstDirtyRegion);
238     curDirtyManager->SetUifirstFrameDirtyRect(curDirtyRegion);
239     RS_OPTIONAL_TRACE_NAME_FMT("MergeOldDirtyToDirtyManager %" PRIu64","
240         " curDirtyRegion[%d %d %d %d], uifirstDirtyRegion[%d %d %d %d]",
241         node->GetId(), curDirtyRegion.left_, curDirtyRegion.top_, curDirtyRegion.width_, curDirtyRegion.height_,
242         uifirstDirtyRegion.left_, uifirstDirtyRegion.top_, uifirstDirtyRegion.width_, uifirstDirtyRegion.height_);
243     if (!uifirstDirtyRegion.IsEmpty()) {
244         node->AddToPendingSyncList();
245     }
246 }
247 
RenderGroupUpdate(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable)248 void RSUifirstManager::RenderGroupUpdate(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable)
249 {
250     if (mainThread_ == nullptr) {
251         return;
252     }
253     auto nodeSp = mainThread_->GetContext().GetNodeMap().GetRenderNode(drawable->GetId());
254     if (nodeSp == nullptr) {
255         return;
256     }
257     auto surfaceNode = std::static_pointer_cast<const RSSurfaceRenderNode>(nodeSp);
258     if (surfaceNode == nullptr) {
259         return;
260     }
261     // mark all parent rendergroup need update; planning: mark autoCache need update
262     auto node = surfaceNode->GetParent().lock();
263 
264     while (node != nullptr) {
265         if (node->GetType() == RSRenderNodeType::SCREEN_NODE) {
266             break;
267         }
268         if (node->IsSuggestedDrawInGroup()) {
269             RS_OPTIONAL_TRACE_NAME_FMT("cache_changed by uifirst card %" PRIu64"", node->GetId());
270             node->SetDrawingCacheChanged(true);
271             node->AddToPendingSyncList();
272         }
273         node = node->GetParent().lock();
274     }
275 }
276 
ProcessForceUpdateNode()277 void RSUifirstManager::ProcessForceUpdateNode()
278 {
279     if (!mainThread_) {
280         return;
281     }
282     std::vector<std::shared_ptr<RSRenderNode>> toDirtyNodes;
283     for (auto id : pendingForceUpdateNode_) {
284         auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(id);
285         if (!node || node->GetLastFrameUifirstFlag() != MultiThreadCacheType::ARKTS_CARD) {
286             continue;
287         }
288         toDirtyNodes.push_back(node);
289         if (!node->IsDirty() && !node->IsSubTreeDirty()) {
290             markForceUpdateByUifirst_.push_back(node);
291             node->SetForceUpdateByUifirst(true);
292         }
293     }
294     for (auto& node : toDirtyNodes) {
295         node->SetDirty(true);
296     }
297     pendingForceUpdateNode_.clear();
298 }
299 
NotifyUIStartingWindow(NodeId id,bool wait)300 void RSUifirstManager::NotifyUIStartingWindow(NodeId id, bool wait)
301 {
302     if (mainThread_ == nullptr) {
303         return;
304     }
305     auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
306         mainThread_->GetContext().GetNodeMap().GetRenderNode(id));
307     if (node == nullptr || !node->IsLeashWindow()) {
308         return;
309     }
310     for (auto& child : *node->GetChildren()) {
311         if (!child) {
312             continue;
313         }
314         auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
315         if (surfaceChild && surfaceChild->IsMainWindowType()) {
316             surfaceChild->SetWaitUifirstFirstFrame(wait);
317         }
318     }
319 }
320 
ProcessDoneNodeInner()321 void RSUifirstManager::ProcessDoneNodeInner()
322 {
323     std::vector<NodeId> tmp;
324     {
325         std::lock_guard<std::mutex> lock(childernDrawableMutex_);
326         if (subthreadProcessDoneNode_.size() == 0) {
327             return;
328         }
329         std::swap(tmp, subthreadProcessDoneNode_);
330     }
331     RS_TRACE_NAME_FMT("ProcessDoneNode num:%d", tmp.size());
332     for (auto& id : tmp) {
333         RS_OPTIONAL_TRACE_NAME_FMT("Done %" PRIu64"", id);
334         auto drawable = GetSurfaceDrawableByID(id);
335         if (drawable && drawable->GetRsSubThreadCache().GetCacheSurfaceNeedUpdated() &&
336             drawable->GetRsSubThreadCache().CheckCacheSurface()) {
337             drawable->GetRsSubThreadCache().UpdateCompletedCacheSurface();
338             RenderGroupUpdate(drawable);
339             SetNodeNeedForceUpdateFlag(true);
340             pendingForceUpdateNode_.push_back(id);
341         }
342         NotifyUIStartingWindow(id, false);
343         subthreadProcessingNode_.erase(id);
344     }
345 }
346 
ProcessSkippedNode()347 void RSUifirstManager::ProcessSkippedNode()
348 {
349     std::unordered_set<NodeId> tmp;
350     {
351         std::lock_guard<std::mutex> lock(skippedNodeMutex_);
352         if (subthreadProcessSkippedNode_.empty()) {
353             return;
354         }
355         std::swap(tmp, subthreadProcessSkippedNode_);
356     }
357     RS_TRACE_NAME_FMT("ProcessSkippedNode num %zu", tmp.size());
358     for (auto& id : tmp) {
359         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
360             mainThread_->GetContext().GetNodeMap().GetRenderNode(id));
361         if (UNLIKELY(!surfaceNode)) {
362             continue;
363         }
364         // If node not on the tree, do not draw it.
365         if (UNLIKELY(!surfaceNode->IsOnTheTree())) {
366             RS_TRACE_NAME_FMT("ProcessSkippedNode %s %" PRIu64 " not OnTheTree", surfaceNode->GetName().c_str(), id);
367             continue;
368         }
369         // If node not enable uifirst, do not draw it in subThread.
370         if (UNLIKELY(surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE)) {
371             RS_TRACE_NAME_FMT("ProcessSkippedNode %s %" PRIu64 " disabled", surfaceNode->GetName().c_str(), id);
372             continue;
373         }
374         if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD) {
375             if (pendingPostCardNodes_.find(id) == pendingPostCardNodes_.end()) {
376                 pendingPostCardNodes_.emplace(id, surfaceNode);
377                 surfaceNode->SetForceDrawWithSkipped(true);
378                 RS_TRACE_NAME_FMT("ProcessSkippedCardNode %" PRIu64 " added", id);
379                 RS_LOGI("ProcessSkippedCardNode %{public}" PRIu64 " added", id);
380             }
381         } else {
382             if (pendingPostNodes_.find(id) == pendingPostNodes_.end()) {
383                 pendingPostNodes_.emplace(id, surfaceNode);
384                 surfaceNode->SetForceDrawWithSkipped(true);
385                 RS_TRACE_NAME_FMT("ProcessSkippedNode %s %" PRIu64 " Type %d added", surfaceNode->GetName().c_str(), id,
386                     static_cast<int>(surfaceNode->GetLastFrameUifirstFlag()));
387             }
388         }
389     }
390 }
391 
ProcessDoneNode()392 void RSUifirstManager::ProcessDoneNode()
393 {
394 #ifdef RS_ENABLE_PREFETCH
395     __builtin_prefetch(&pendingResetNodes_, 0, 1);
396 #endif
397     SetNodeNeedForceUpdateFlag(false);
398     ProcessDoneNodeInner();
399 
400     // reset node when node is not doing
401     for (auto it = capturedNodes_.begin(); it != capturedNodes_.end();) {
402         if (mainThread_ && subthreadProcessingNode_.find(*it) == subthreadProcessingNode_.end()) {
403             // reset uifirst
404             auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
405                 mainThread_->GetContext().GetNodeMap().GetRenderNode(*it));
406             if (node == nullptr) {
407                 it = capturedNodes_.erase(it);
408                 continue;
409             }
410             node->SetIsNodeToBeCaptured(false);
411             if (node->GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE) {
412                 ResetUifirstNode(node);
413             }
414             it = capturedNodes_.erase(it);
415         } else {
416             it++;
417         }
418     }
419     for (auto it = pendingResetNodes_.begin(); it != pendingResetNodes_.end();) {
420         if (subthreadProcessingNode_.find(it->first) == subthreadProcessingNode_.end()) {
421             ResetUifirstNode(it->second);
422             it = pendingResetNodes_.erase(it);
423         } else {
424             it++;
425         }
426     }
427     for (auto& surfaceNode : pendingResetWindowCachedNodes_) {
428         ResetWindowCache(surfaceNode);
429     }
430     pendingResetWindowCachedNodes_.clear();
431 
432     for (auto it = subthreadProcessingNode_.begin(); it != subthreadProcessingNode_.end();) {
433         auto id = it->first;
434         auto drawable = GetSurfaceDrawableByID(id);
435         if (!drawable) {
436             ++it;
437             continue;
438         }
439         auto cacheStatus = drawable->GetRsSubThreadCache().GetCacheSurfaceProcessedStatus();
440         if (cacheStatus == CacheProcessStatus::SKIPPED) {
441             it = subthreadProcessingNode_.erase(it);
442             continue;
443         }
444         RS_LOGI("erase processingNode %{public}" PRIu64, id);
445         RS_TRACE_NAME_FMT("erase processingNode %s %" PRIu64, drawable->GetName().c_str(), id);
446         pendingPostNodes_.erase(it->first); // dele doing node in pendingpostlist
447         pendingPostCardNodes_.erase(it->first);
448         // skipped by doing, need update cache because the doing cache is too old
449         RSUifirstManager::Instance().AddProcessSkippedNode(it->first);
450         ++it;
451     }
452 }
453 
SyncHDRDisplayParam(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable,const GraphicColorGamut & colorGamut)454 void RSUifirstManager::SyncHDRDisplayParam(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable,
455     const GraphicColorGamut& colorGamut)
456 {
457 #ifdef RS_ENABLE_GPU
458     auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
459     if (!surfaceParams || !surfaceParams->GetAncestorScreenNode().lock()) {
460         return;
461     }
462     auto ancestor = surfaceParams->GetAncestorScreenNode().lock()->ReinterpretCastTo<RSScreenRenderNode>();
463     if (!ancestor) {
464         return;
465     }
466     auto screenParams = static_cast<RSScreenRenderParams*>(ancestor->GetRenderParams().get());
467     if (!screenParams) {
468         return;
469     }
470     bool isHdrOn = screenParams->GetHDRPresent();
471     ScreenId id = screenParams->GetScreenId();
472     auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
473     rsSubThreadCache.SetHDRPresent(isHdrOn);
474     bool isScRGBEnable = RSSystemParameters::IsNeedScRGBForP3(screenParams->GetNewColorSpace()) &&
475         GetUiFirstSwitch();
476     bool changeColorSpace = rsSubThreadCache.GetTargetColorGamut() != colorGamut;
477     if (isHdrOn || isScRGBEnable || changeColorSpace) {
478         // When ScRGB or Adaptive P3 is enabled, some operations may cause the window color gamut to change.
479         // In this case, the uifirst cache needs to be cleared.
480         if ((isScRGBEnable || ColorGamutParam::IsAdaptiveColorGamutEnabled()) && changeColorSpace) {
481             RS_LOGI("UIFirstHDR SyncDisplayParam: ColorSpace change, ClearCacheSurface,"
482                 "nodeID: [%{public}" PRIu64"]", id);
483             RS_TRACE_NAME_FMT("UIFirstHDR SyncScreenParam: ColorSpace change, ClearCacheSurface,"
484                 "nodeID: [%{public}" PRIu64"]", id);
485             drawable->GetRsSubThreadCache().ClearCacheSurfaceInThread();
486         }
487         rsSubThreadCache.SetScreenId(id);
488         rsSubThreadCache.SetTargetColorGamut(colorGamut);
489     }
490     RS_LOGD("UIFirstHDR SyncDisplayParam:%{public}d, ratio:%{public}f", rsSubThreadCache.GetHDRPresent(),
491         surfaceParams->GetBrightnessRatio());
492 #endif
493 }
494 
CurSurfaceHasVisibleDirtyRegion(const std::shared_ptr<RSSurfaceRenderNode> & node)495 bool RSUifirstManager::CurSurfaceHasVisibleDirtyRegion(const std::shared_ptr<RSSurfaceRenderNode>& node)
496 {
497     auto visibleRegion = node->GetVisibleRegion();
498     if (visibleRegion.IsEmpty()) {
499         RS_OPTIONAL_TRACE_NAME_FMT("curSurface name:%s id:%" PRIu64" visibleRegion is IsEmpty",
500             node->GetName().c_str(), node->GetId());
501         return false;
502     }
503     auto drawable = node->GetRenderDrawable();
504     if (!drawable) {
505         RS_TRACE_NAME_FMT("node id:%" PRIu64" drawable is nullptr", node->GetId());
506         return true;
507     }
508     auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
509     if (!surfaceDrawable) {
510         RS_TRACE_NAME_FMT("node id:%" PRIu64" surfaceDrawable is nullptr", node->GetId());
511         return true;
512     }
513     auto surfaceDirtyManager = surfaceDrawable->GetSyncDirtyManager();
514     if (!surfaceDirtyManager) {
515         RS_TRACE_NAME_FMT("node id:%" PRIu64" surfaceDirtyManager is nullptr", node->GetId());
516         return true;
517     }
518     auto surfaceDirtyRect = surfaceDirtyManager->GetUifirstFrameDirtyRegion();
519     RS_TRACE_NAME_FMT("uifirstFrameDirtyRegion %" PRIu64", surfaceDirtyRegion[%d %d %d %d]",
520             surfaceDrawable->GetId(),
521             surfaceDirtyRect.left_, surfaceDirtyRect.top_, surfaceDirtyRect.width_, surfaceDirtyRect.height_);
522     Occlusion::Region surfaceDirtyRegion { { surfaceDirtyRect.left_, surfaceDirtyRect.top_,
523         surfaceDirtyRect.GetRight(), surfaceDirtyRect.GetBottom() } };
524     Occlusion::Region surfaceVisibleDirtyRegion = surfaceDirtyRegion.And(visibleRegion);
525     if (surfaceVisibleDirtyRegion.IsEmpty()) {
526         RS_OPTIONAL_TRACE_NAME_FMT("curSurface name:%s id:%" PRIu64" visibleDirtyRegion is IsEmpty",
527             node->GetName().c_str(), node->GetId());
528         return false;
529     }
530     return true;
531 }
532 
CheckVisibleDirtyRegionIsEmpty(const std::shared_ptr<RSSurfaceRenderNode> & node)533 bool RSUifirstManager::CheckVisibleDirtyRegionIsEmpty(const std::shared_ptr<RSSurfaceRenderNode>& node)
534 {
535     if (GetUiFirstMode() != UiFirstModeType::MULTI_WINDOW_MODE) {
536         return false;
537     }
538     if (ROSEN_EQ(node->GetGlobalAlpha(), 0.0f) &&
539         RSMainThread::Instance()->GetSystemAnimatedScenes() == SystemAnimatedScenes::LOCKSCREEN_TO_LAUNCHER &&
540         node->IsLeashWindow()) {
541         RS_TRACE_NAME_FMT("Doing LOCKSCREEN_TO_LAUNCHER, fullTransparent node[%s] skips", node->GetName().c_str());
542         return true;
543     }
544     if (node->GetUifirstContentDirty()) {
545         return false;
546     }
547     bool hasSurfaceVisibleDirtyRegion = CurSurfaceHasVisibleDirtyRegion(node);
548     std::vector<std::pair<NodeId, std::weak_ptr<RSSurfaceRenderNode>>> allSubSurfaceNodes;
549     node->GetAllSubSurfaceNodes(allSubSurfaceNodes);
550     for (auto& [id, subSurfaceNode] : allSubSurfaceNodes) {
551         if (hasSurfaceVisibleDirtyRegion) {
552             break;
553         }
554         auto subSurfaceNodePtr = subSurfaceNode.lock();
555         if (!subSurfaceNodePtr) {
556             continue;
557         }
558         hasSurfaceVisibleDirtyRegion =
559             hasSurfaceVisibleDirtyRegion || CurSurfaceHasVisibleDirtyRegion(subSurfaceNodePtr);
560     }
561     RS_TRACE_NAME_FMT("allSurface name:%s id:%" PRIu64" hasSurfaceVisibleDirtyRegion:%d",
562             node->GetName().c_str(), node->GetId(), hasSurfaceVisibleDirtyRegion);
563     if (!hasSurfaceVisibleDirtyRegion) {
564         return true;
565     }
566     return false;
567 }
568 
SubThreadControlFrameRate(NodeId id,std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> & drawable,std::shared_ptr<RSSurfaceRenderNode> & node)569 bool RSUifirstManager::SubThreadControlFrameRate(NodeId id,
570     std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable>& drawable,
571     std::shared_ptr<RSSurfaceRenderNode>& node)
572 {
573     if (!RSSystemProperties::GetSubThreadControlFrameRate()) {
574         return false;
575     }
576 
577     auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
578     bool hasAvailableTexture = rsSubThreadCache.HasCachedTexture() &&
579         rsSubThreadCache.GetCacheSurfaceAlphaInfo() != CACHED_SURFACE_IS_TRANSPARENT &&
580         rsSubThreadCache.GetCacheSurfaceProcessedNodes() > SUBTHREAD_CONTROL_FRAMERATE_NODE_LIMIT;
581     bool isLeashWindow = node->GetLastFrameUifirstFlag() == MultiThreadCacheType::LEASH_WINDOW;
582 
583     return purgeEnable_ && hasAvailableTexture && isLeashWindow &&
584         RSUifirstFrameRateControl::Instance().NeedRSUifirstControlFrameDrop(*node) &&
585         (subthreadProcessingNode_.find(id) == subthreadProcessingNode_.end()) &&
586         !drawable->GetRsSubThreadCache().IsSubThreadSkip();
587 }
588 
NeedPurgeByBehindWindow(NodeId id,bool hasTexture,const std::shared_ptr<RSSurfaceRenderNode> & node)589 bool RSUifirstManager::NeedPurgeByBehindWindow(NodeId id, bool hasTexture,
590     const std::shared_ptr<RSSurfaceRenderNode>& node)
591 {
592     if (GetUiFirstMode() != UiFirstModeType::MULTI_WINDOW_MODE) {
593         return false;
594     }
595     if (!RSSystemProperties::GetUIFirstBehindWindowEnabled()) {
596         RS_LOGD("Behind window control framerate switch is off");
597         return false;
598     }
599     bool isBehindWindowOcclusion = IsBehindWindowOcclusion(node);
600     return purgeEnable_ && hasTexture &&
601         node->GetLastFrameUifirstFlag() == MultiThreadCacheType::NONFOCUS_WINDOW && isBehindWindowOcclusion;
602 }
603 
HandlePurgeBehindWindow(std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>>::iterator & it,std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>> & pendingNode)604 void RSUifirstManager::HandlePurgeBehindWindow(
605     std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>::iterator& it,
606     std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>& pendingNode)
607 {
608     auto id = it->first;
609     auto node = it->second;
610     uint64_t currentTime = GetMainThreadVsyncTime();
611     uint64_t timeDiffInMilliseconds = GetTimeDiffBehindWindow(currentTime, id);
612     // control the frequency of purge as the designed time
613     if (timeDiffInMilliseconds >= PURGE_BEHIND_WINDOW_TIME || pendingNodeBehindWindow_[id].isFirst) {
614         ++it;
615         pendingNodeBehindWindow_[id].curTime = currentTime;
616         pendingNodeBehindWindow_[id].isFirst = false;
617         RS_OPTIONAL_TRACE_NAME_FMT("Don't Purge by behind window %s", node->GetName().c_str());
618     } else {
619         RS_TRACE_NAME_FMT("Purge by behind window %s", node->GetName().c_str());
620         it = pendingNode.erase(it);
621     }
622 }
623 
DoPurgePendingPostNodes(std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>> & pendingNode)624 void RSUifirstManager::DoPurgePendingPostNodes(std::unordered_map<NodeId,
625     std::shared_ptr<RSSurfaceRenderNode>>& pendingNode)
626 {
627     for (auto it = pendingNode.begin(); it != pendingNode.end();) {
628         auto id = it->first;
629         auto drawable = GetSurfaceDrawableByID(id);
630         auto node = it->second;
631         if (!drawable || !node) {
632             ++it;
633             continue;
634         }
635         auto forceDraw = node->GetForceDrawWithSkipped();
636         node->SetForceDrawWithSkipped(false);
637         SyncHDRDisplayParam(drawable, node->GetFirstLevelNodeColorGamut());
638         auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
639         if (!surfaceParams) {
640             ++it;
641             continue;
642         }
643 
644         if (!node->IsOnTheTree() && subthreadProcessingNode_.find(id) == subthreadProcessingNode_.end()) {
645             it = pendingNode.erase(it);
646             continue;
647         }
648 
649         if (forceDraw) {
650             RS_TRACE_NAME_FMT("Purge GetForceDrawWithSkipped name: %s %" PRIu64,
651                 surfaceParams->GetName().c_str(), drawable->GetId());
652             ++it;
653             continue;
654         }
655 
656         auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
657         bool staticContent = surfaceParams->GetSurfaceCacheContentStatic();
658         RS_TRACE_NAME_FMT("Purge node name: %s, PurgeEnable:%d, HasCachedTexture:%d, staticContent: %d %" PRIu64,
659             surfaceParams->GetName().c_str(), purgeEnable_,
660             rsSubThreadCache.HasCachedTexture(), staticContent, drawable->GetId());
661         if (purgeEnable_ && rsSubThreadCache.HasCachedTexture() &&
662             (staticContent || CheckVisibleDirtyRegionIsEmpty(node)) &&
663             (subthreadProcessingNode_.find(id) == subthreadProcessingNode_.end()) &&
664             !rsSubThreadCache.IsSubThreadSkip()) {
665             RS_OPTIONAL_TRACE_NAME_FMT("Purge node name %s", surfaceParams->GetName().c_str());
666             it = pendingNode.erase(it);
667         } else if (SubThreadControlFrameRate(id, drawable, node)) {
668             RS_OPTIONAL_TRACE_NAME_FMT("Purge frame drop node name %s", surfaceParams->GetName().c_str());
669             it = pendingNode.erase(it);
670         } else if (NeedPurgeByBehindWindow(id, rsSubThreadCache.HasCachedTexture(), node)) {
671             RS_OPTIONAL_TRACE_NAME_FMT("Decide Whether to Purge node by behind window or not");
672             HandlePurgeBehindWindow(it, pendingNode);
673         } else {
674             ++it;
675         }
676     }
677 }
678 
IsBehindWindowOcclusion(const std::shared_ptr<RSSurfaceRenderNode> & node)679 bool RSUifirstManager::IsBehindWindowOcclusion(const std::shared_ptr<RSSurfaceRenderNode>& node)
680 {
681     std::vector<std::pair<NodeId, std::weak_ptr<RSSurfaceRenderNode>>> allSubSurfaceNodes;
682     node->GetAllSubSurfaceNodes(allSubSurfaceNodes);
683     auto nodeVisibleRegion = node->GetVisibleRegion();
684     auto nodeVisibleRegionBehindWindow = node->GetVisibleRegionBehindWindow();
685 
686     for (const auto &[subId, subSurfaceNode] : allSubSurfaceNodes) {
687         const auto subNodePtr = subSurfaceNode.lock();
688         if (subNodePtr) {
689             auto visibleRegion = nodeVisibleRegion.OrSelf(subNodePtr->GetVisibleRegion());
690             auto visibleRegionBehindWindow =
691                 nodeVisibleRegionBehindWindow.OrSelf(subNodePtr->GetVisibleRegionBehindWindow());
692             RS_OPTIONAL_TRACE_NAME_FMT("visibleRegion is [%s], visibleRegionBehindWindow is [%s]",
693                 visibleRegion.GetRegionInfo().c_str(),
694                 visibleRegionBehindWindow.GetRegionInfo().c_str());
695 
696             if (visibleRegionBehindWindow.IsEmpty() && !visibleRegion.IsEmpty()) {
697                 return true;
698             }
699         }
700     }
701     return false;
702 }
703 
GetTimeDiffBehindWindow(uint64_t currentTime,NodeId id)704 uint64_t RSUifirstManager::GetTimeDiffBehindWindow(uint64_t currentTime, NodeId id)
705 {
706     uint64_t timeDiff = currentTime - pendingNodeBehindWindow_[id].curTime;
707     RS_OPTIONAL_TRACE_NAME_FMT("timeDiff is %lu", timeDiff);
708     return timeDiff;
709 }
710 
GetMainThreadVsyncTime()711 uint64_t RSUifirstManager::GetMainThreadVsyncTime()
712 {
713     uint64_t mainThreadVsyncTime = RSMainThread::Instance()->GetCurrentVsyncTime();
714     uint64_t mainThreadVsyncTimeMS = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(
715         std::chrono::nanoseconds(mainThreadVsyncTime)).count());
716     return mainThreadVsyncTimeMS;
717 }
718 
PurgePendingPostNodes()719 void RSUifirstManager::PurgePendingPostNodes()
720 {
721     RS_OPTIONAL_TRACE_NAME_FMT("PurgePendingPostNodes");
722     DoPurgePendingPostNodes(pendingPostNodes_);
723     DoPurgePendingPostNodes(pendingPostCardNodes_);
724     ProcessMarkedNodeSubThreadCache();
725     for (auto& node : markForceUpdateByUifirst_) {
726         node->SetForceUpdateByUifirst(false);
727     }
728     markForceUpdateByUifirst_.clear();
729     for (auto id : pendingForceUpdateNode_) {
730         MergeOldDirty(id);
731     }
732 }
733 
PostSubTask(NodeId id)734 void RSUifirstManager::PostSubTask(NodeId id)
735 {
736     RS_TRACE_NAME_FMT("post UpdateCacheSurface %" PRIu64"", id);
737     if (subthreadProcessingNode_.find(id) != subthreadProcessingNode_.end()) { // drawable is doing, do not send
738         RS_TRACE_NAME_FMT("node %" PRIu64" is doing", id);
739         RS_LOGE("RSUifirstManager ERROR: post task twice");
740         return;
741     }
742 
743     // 1.find in cache list(done to dele) 2.find in global list
744     auto drawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
745     if (drawable) {
746         auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
747         if (surfaceNodeDrawable) {
748             surfaceNodeDrawable->GetRsSubThreadCache().UpdateUifirstDirtyManager(surfaceNodeDrawable.get());
749         }
750         // ref drawable
751         subthreadProcessingNode_.emplace(id, drawable);
752         // post task
753         RS_OPTIONAL_TRACE_NAME_FMT("Post_SubTask_s %" PRIu64"", id);
754         RSSubThreadManager::Instance()->ScheduleRenderNodeDrawable(
755             std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable));
756     }
757 }
758 
TryReleaseTextureForIdleThread()759 void RSUifirstManager::TryReleaseTextureForIdleThread()
760 {
761     if (noUifirstNodeFrameCount_.load() <= CLEAR_RES_THRESHOLD) {
762         return;
763     }
764     RSSubThreadManager::Instance()->TryReleaseTextureForIdleThread();
765 }
766 
PostReleaseCacheSurfaceSubTasks()767 void RSUifirstManager::PostReleaseCacheSurfaceSubTasks()
768 {
769     for (auto& cardNode : collectedCardNodes_) {
770         PostReleaseCacheSurfaceSubTask(cardNode);
771     }
772 }
773 
PostReleaseCacheSurfaceSubTask(NodeId id)774 void RSUifirstManager::PostReleaseCacheSurfaceSubTask(NodeId id)
775 {
776     RS_OPTIONAL_TRACE_NAME_FMT("post ReleaseCacheSurface %d", id);
777 
778     if (subthreadProcessingNode_.find(id) != subthreadProcessingNode_.end()) { // drawable is doing, do not send
779         RS_TRACE_NAME_FMT("node %" PRIu64" is doing", id);
780         RS_LOGE("RSUifirstManager ERROR: try to clean running node");
781         return;
782     }
783 
784     // 1.find in cache list(done to dele) 2.find in global list
785     auto drawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
786     if (drawable) {
787         // post task
788         RS_OPTIONAL_TRACE_NAME_FMT("Post_SubTask_s %" PRIu64"", id);
789         RSSubThreadManager::Instance()->ScheduleReleaseCacheSurfaceOnly(
790             std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable));
791     }
792 }
793 
UpdateSkipSyncNode()794 void RSUifirstManager::UpdateSkipSyncNode()
795 {
796     processingNodeSkipSync_.clear();
797     processingNodePartialSync_.clear();
798     processingCardNodeSkipSync_.clear();
799     RS_OPTIONAL_TRACE_NAME_FMT("UpdateSkipSyncNode doning%d", subthreadProcessingNode_.size());
800     if (subthreadProcessingNode_.size() == 0) {
801         return;
802     }
803     if (!mainThread_) {
804         return;
805     }
806     for (auto it = subthreadProcessingNode_.begin(); it != subthreadProcessingNode_.end(); it++) {
807         RS_OPTIONAL_TRACE_NAME_FMT("doning%" PRIu64"", it->first);
808         auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(it->first);
809         if (!node) {
810             continue;
811         }
812         auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>();
813         if (!surfaceNode) {
814             continue;
815         }
816         // ArkTSCard
817         if (NodeIsInCardWhiteList(*node)) {
818             if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD) {
819                 processingCardNodeSkipSync_.insert(it->first);
820                 continue;
821             }
822         }
823 
824         // leash window
825         processingNodePartialSync_.insert(it->first); // partial sync
826         std::vector<std::pair<NodeId, std::weak_ptr<RSSurfaceRenderNode>>> allSubSurfaceNodes;
827         surfaceNode->GetAllSubSurfaceNodes(allSubSurfaceNodes);
828         for (auto& [id, subSurfaceNode] : allSubSurfaceNodes) {
829             processingNodeSkipSync_.insert(id); // skip sync
830         }
831     }
832 }
833 
ProcessSubDoneNode()834 void RSUifirstManager::ProcessSubDoneNode()
835 {
836     RS_OPTIONAL_TRACE_NAME_FMT("ProcessSubDoneNode");
837     ProcessSkippedNode(); // try rescheduale skipped node
838     ProcessDoneNode(); // release finish drawable
839     UpdateSkipSyncNode();
840     RestoreSkipSyncNode();
841     ResetCurrentFrameDeletedCardNodes();
842 }
843 
SetUifirstSkipPartialSync(const std::shared_ptr<RSRenderNode> & node,bool needSync)844 static inline void SetUifirstSkipPartialSync(const std::shared_ptr<RSRenderNode> &node, bool needSync)
845 {
846     // node not null in caller
847     if (!needSync) {
848         return;
849     }
850     node->SetUifirstSkipPartialSync(true);
851 }
852 
GetUifirstCachedState(NodeId id)853 CacheProcessStatus& RSUifirstManager::GetUifirstCachedState(NodeId id)
854 {
855     auto ret = uifirstCacheState_.insert({ id, CacheProcessStatus::UNKNOWN });
856     auto& curRootIdState = ret.first->second;
857     if (curRootIdState == CacheProcessStatus::UNKNOWN) {
858         /* first time to get the state of uifirstRoot, and cache the state for the remaining other times */
859         auto uifirstRootNodeDrawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
860         if (uifirstRootNodeDrawable && uifirstRootNodeDrawable->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
861             auto drawableNode =
862                 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(uifirstRootNodeDrawable);
863             curRootIdState = drawableNode->GetRsSubThreadCache().GetCacheSurfaceProcessedStatus();
864         }
865     }
866     return curRootIdState;
867 }
868 
CollectSkipSyncNodeWithDrawableState(const std::shared_ptr<RSRenderNode> & node)869 RSUifirstManager::SkipSyncState RSUifirstManager::CollectSkipSyncNodeWithDrawableState(
870     const std::shared_ptr<RSRenderNode>& node)
871 {
872     auto isPreDoing = IsPreFirstLevelNodeDoingAndTryClear(node);
873     auto drawable = node->GetRenderDrawable();
874     if (UNLIKELY(!drawable || !drawable->GetRenderParams())) {
875         RS_LOGE("CollectSkipSyncNode drawable/params nullptr");
876         // must not be in the DOING state with the invalid drawable.
877         return SkipSyncState::STATE_NOT_SKIP;
878     }
879     auto& params = drawable->GetRenderParams();
880     if (params->GetStartingWindowFlag()) {
881         RS_LOGD("starting node %{public}" PRIu64 " not skipsync", params->GetId());
882         RS_TRACE_NAME_FMT("starting node %" PRIu64 " not skipsync", params->GetId());
883         return SkipSyncState::STATE_NOT_SKIP;
884     }
885     // if node's UifirstRootNodeId is valid (e.g. ArkTsCard), use it first
886     auto uifirstRootId = params->GetUifirstRootNodeId() != INVALID_NODEID ?
887         params->GetUifirstRootNodeId() : params->GetFirstLevelNodeId();
888     auto& curRootIdState = GetUifirstCachedState(uifirstRootId);
889     RS_OPTIONAL_TRACE_NAME_FMT("node[%" PRIu64 " %" PRIu64 "] drawable[%"
890         PRIu64 " %" PRIu64 "] and curNodeId [%" PRIu64"] cacheState[%d]",
891         node->GetStagingRenderParams()->GetUifirstRootNodeId(), node->GetStagingRenderParams()->GetFirstLevelNodeId(),
892         params->GetUifirstRootNodeId(), params->GetFirstLevelNodeId(), node->GetId(), curRootIdState);
893 
894     if (curRootIdState == CacheProcessStatus::DOING || curRootIdState == CacheProcessStatus::WAITING ||
895         /* unknow state to check prefirstLevelNode */
896         (uifirstRootId == INVALID_NODEID && isPreDoing)) {
897         pendingSyncForSkipBefore_[uifirstRootId].push_back(node);
898         auto isUifirstRootNode = (uifirstRootId == node->GetId());
899         RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
900             isUifirstRootNode ? "set partial_sync" : "CollectSkipSyncNode", node->GetId(), uifirstRootId);
901         SetUifirstSkipPartialSync(node, isUifirstRootNode);
902         return isUifirstRootNode ? SkipSyncState::STATE_NOT_SKIP : SkipSyncState::STATE_NEED_SKIP;
903     }
904     return SkipSyncState::STATE_NEED_CHECK;
905 }
906 
CollectSkipSyncNode(const std::shared_ptr<RSRenderNode> & node)907 CM_INLINE bool RSUifirstManager::CollectSkipSyncNode(const std::shared_ptr<RSRenderNode>& node)
908 {
909     if (!node) {
910         return false;
911     }
912     if (pendingPostNodes_.find(node->GetId()) != pendingPostNodes_.end() ||
913         pendingPostCardNodes_.find(node->GetId()) != pendingPostCardNodes_.end()) {
914         node->SetUifirstSyncFlag(true);
915     }
916 
917     auto ret = CollectSkipSyncNodeWithDrawableState(node);
918     if (ret != SkipSyncState::STATE_NEED_CHECK) {
919         return ret == SkipSyncState::STATE_NEED_SKIP;
920     }
921     if (NodeIsInCardWhiteList(*node) && processingCardNodeSkipSync_.count(node->GetUifirstRootNodeId())) {
922         pendingSyncForSkipBefore_[node->GetUifirstRootNodeId()].push_back(node);
923         auto isUifirstRootNode = (node->GetUifirstRootNodeId() == node->GetId());
924         RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
925             isUifirstRootNode ? "set partial_sync card" : "CollectSkipSyncNode card",
926             node->GetId(), node->GetInstanceRootNodeId());
927         SetUifirstSkipPartialSync(node, isUifirstRootNode);
928         return !isUifirstRootNode;
929     }
930     if (processingNodePartialSync_.count(node->GetInstanceRootNodeId()) > 0) {
931         pendingSyncForSkipBefore_[node->GetInstanceRootNodeId()].push_back(node);
932         auto isInstanceRootNode = (node->GetInstanceRootNodeId() == node->GetId());
933         RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
934             isInstanceRootNode ? "set partial_sync" : "CollectSkipSyncNode",
935             node->GetId(), node->GetInstanceRootNodeId());
936         SetUifirstSkipPartialSync(node, isInstanceRootNode);
937         return !isInstanceRootNode;
938     } else if (processingNodeSkipSync_.count(node->GetInstanceRootNodeId()) > 0) {
939         RS_OPTIONAL_TRACE_NAME_FMT("CollectSkipSyncNode root %" PRIu64", node %" PRIu64,
940             node->GetInstanceRootNodeId(), node->GetId());
941         pendingSyncForSkipBefore_[node->GetInstanceRootNodeId()].push_back(node);
942         return true;
943     } else {
944         return false;
945     }
946 }
947 
RestoreSkipSyncNode()948 void RSUifirstManager::RestoreSkipSyncNode()
949 {
950     std::vector<NodeId> todele;
951     for (auto& it : pendingSyncForSkipBefore_) {
952         if (processingNodeSkipSync_.count(it.first) == 0 && processingNodePartialSync_.count(it.first) == 0 &&
953             processingCardNodeSkipSync_.count(it.first) == 0) {
954             todele.push_back(it.first);
955             RS_OPTIONAL_TRACE_NAME_FMT("RestoreSkipSyncNode %" PRIu64" num%d", it.first, it.second.size());
956             for (auto& node : it.second) {
957                 node->SetUifirstSkipPartialSync(false);
958                 node->AddToPendingSyncList();
959             }
960         }
961     }
962     for (auto id : todele) {
963         pendingSyncForSkipBefore_.erase(id);
964         if (!mainThread_) {
965             continue;
966         }
967         auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(id);
968         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node);
969         if (!surfaceNode) {
970             continue;
971         }
972         if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD &&
973             surfaceNode->GetUifirstRootNodeId() == surfaceNode->GetId() &&
974             pendingPostCardNodes_.find(surfaceNode->GetId()) == pendingPostCardNodes_.end()) {
975             pendingPostCardNodes_[surfaceNode->GetId()] = surfaceNode;
976             RS_OPTIONAL_TRACE_NAME_FMT("RestoreSkipSyncNode AddPendingPostCard %llu", id);
977         }
978     }
979 }
980 
ClearSubthreadRes()981 void RSUifirstManager::ClearSubthreadRes()
982 {
983     RS_OPTIONAL_TRACE_NAME_FMT("ClearSubthreadRes");
984     if (subthreadProcessingNode_.size() == 0 &&
985         pendingSyncForSkipBefore_.size() == 0) {
986         noUifirstNodeFrameCount_.fetch_add(1);
987         if (noUifirstNodeFrameCount_.load() == CLEAR_RES_THRESHOLD) {
988             RSSubThreadManager::Instance()->ResetSubThreadGrContext();
989             PostReleaseCacheSurfaceSubTasks();
990         }
991     } else {
992         noUifirstNodeFrameCount_.store(0);
993     }
994 }
995 
ForceClearSubthreadRes()996 void RSUifirstManager::ForceClearSubthreadRes()
997 {
998     noUifirstNodeFrameCount_.store(0);
999     RSSubThreadManager::Instance()->ReleaseTexture();
1000 }
1001 
IsPreFirstLevelNodeDoingAndTryClear(std::shared_ptr<RSRenderNode> node)1002 bool RSUifirstManager::IsPreFirstLevelNodeDoingAndTryClear(std::shared_ptr<RSRenderNode> node)
1003 {
1004     if (!node) {
1005         return true;
1006     }
1007     auto& preFirstLevelNodeIdSet = node->GetMutablePreFirstLevelNodeIdSet();
1008     for (auto it = preFirstLevelNodeIdSet.begin(); it != preFirstLevelNodeIdSet.end();
1009          it = preFirstLevelNodeIdSet.erase(it)) {
1010         const auto& curRootIdState = GetUifirstCachedState(*it);
1011         if (curRootIdState == CacheProcessStatus::DOING || curRootIdState == CacheProcessStatus::WAITING) {
1012             return true;
1013         }
1014     }
1015     return false;
1016 }
1017 
SetNodePriorty(std::list<NodeId> & result,std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>> & pendingNode)1018 void RSUifirstManager::SetNodePriorty(std::list<NodeId>& result,
1019     std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>& pendingNode)
1020 {
1021     auto isFocusId = RSMainThread::Instance()->GetFocusNodeId();
1022     auto isLeashId = RSMainThread::Instance()->GetFocusLeashWindowId();
1023     int32_t postOrder = 0;
1024     for (auto& item : pendingNode) {
1025         postOrder++;
1026         auto const& [id, value] = item;
1027         if (IsPreFirstLevelNodeDoingAndTryClear(value)) {
1028             continue;
1029         }
1030         auto drawable = GetSurfaceDrawableByID(id);
1031         if (!drawable) {
1032             continue;
1033         }
1034         auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
1035         if (rsSubThreadCache.HasCachedTexture()) {
1036             rsSubThreadCache.SetRenderCachePriority(NodePriorityType::SUB_LOW_PRIORITY);
1037         } else {
1038             rsSubThreadCache.SetRenderCachePriority(NodePriorityType::SUB_HIGH_PRIORITY);
1039         }
1040         if (rsSubThreadCache.GetCacheSurfaceProcessedStatus() == CacheProcessStatus::WAITING) {
1041             rsSubThreadCache.SetRenderCachePriority(NodePriorityType::SUB_HIGH_PRIORITY);
1042         }
1043         auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
1044         if (surfaceParams && surfaceParams->GetPreSubHighPriorityType()) {
1045             rsSubThreadCache.SetRenderCachePriority(NodePriorityType::SUB_VIDEO_PRIORITY);
1046         }
1047         // focusWindow is highest priority.
1048         if (!isFocusNodeFound_) {
1049             if (id == isFocusId || id == isLeashId) {
1050                 // for resolving response latency
1051                 rsSubThreadCache.SetRenderCachePriority(NodePriorityType::SUB_FOCUSNODE_PRIORITY);
1052                 isFocusNodeFound_ = true;
1053                 focusNodeThreadIndex_ = rsSubThreadCache.GetLastFrameUsedThreadIndex();
1054             }
1055         }
1056         if (RSSystemProperties::GetUIFirstOptScheduleEnabled() &&
1057             rsSubThreadCache.GetSurfaceSkipCount() >= UIFIRST_TASKSKIP_PRIO_THRESHOLD) {
1058             postOrder += rsSubThreadCache.GetSurfaceSkipPriority();
1059         }
1060         rsSubThreadCache.SetUifirstPostOrder(postOrder);
1061         rsSubThreadCache.SetHighPostPriority(false);
1062         sortedSubThreadNodeIds_.emplace_back(id);
1063     }
1064     RS_TRACE_NAME_FMT("SetNodePriorty result [%zu] pendingNode [%zu]", result.size(), pendingNode.size());
1065 }
1066 
SortSubThreadNodesPriority()1067 void RSUifirstManager::SortSubThreadNodesPriority()
1068 {
1069     sortedSubThreadNodeIds_.clear();
1070     isFocusNodeFound_ = false;
1071     focusNodeThreadIndex_ = UINT32_MAX;
1072     SetNodePriorty(sortedSubThreadNodeIds_, pendingPostNodes_);
1073     SetNodePriorty(sortedSubThreadNodeIds_, pendingPostCardNodes_);
1074     RS_LOGD("SetNodePriorty result [%{public}zu] pendingNode [%{public}zu] pendingCardNode [%{public}zu]",
1075         sortedSubThreadNodeIds_.size(), pendingPostNodes_.size(), pendingPostCardNodes_.size());
1076     sortedSubThreadNodeIds_.sort([this](const auto& first, const auto& second) -> bool {
1077         auto drawable1 = GetSurfaceDrawableByID(first);
1078         auto drawable2 = GetSurfaceDrawableByID(second);
1079         if (drawable1 == nullptr || drawable2 == nullptr) {
1080             ROSEN_LOGE("SortSubThreadNodesPriority sort nullptr found in pendingPostNodes_, "
1081                 "this should not happen");
1082             return false;
1083         }
1084         auto surfaceParams1 = static_cast<RSSurfaceRenderParams*>(drawable1->GetRenderParams().get());
1085         if (!surfaceParams1) {
1086             RS_LOGE("sortsubthread params1 is nullptr");
1087             return false;
1088         }
1089         auto surfaceParams2 = static_cast<RSSurfaceRenderParams*>(drawable2->GetRenderParams().get());
1090         if (!surfaceParams2) {
1091             RS_LOGE("sortsubthread params2 is nullptr");
1092             return false;
1093         }
1094         auto& rsSubThreadCache1 = drawable1->GetRsSubThreadCache();
1095         auto& rsSubThreadCache2 = drawable2->GetRsSubThreadCache();
1096         if (rsSubThreadCache1.GetRenderCachePriority() == rsSubThreadCache2.GetRenderCachePriority()) {
1097             return rsSubThreadCache1.GetUifirstPostOrder() > rsSubThreadCache2.GetUifirstPostOrder();
1098         } else {
1099             return rsSubThreadCache1.GetRenderCachePriority() < rsSubThreadCache2.GetRenderCachePriority();
1100         }
1101     });
1102 }
1103 
MarkPostNodesPriority()1104 void RSUifirstManager::MarkPostNodesPriority()
1105 {
1106     if (!RSSystemProperties::GetUIFirstOptScheduleEnabled()) {
1107         return;
1108     }
1109     int postTaskCount = 0;
1110     for (auto& id : sortedSubThreadNodeIds_) {
1111         auto drawable = GetSurfaceDrawableByID(id);
1112         if (!drawable) {
1113             continue;
1114         }
1115         auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
1116         postTaskCount++;
1117         if (rsSubThreadCache.GetRenderCachePriority() > NodePriorityType::SUB_LOW_PRIORITY) {
1118             rsSubThreadCache.SetHighPostPriority(true);
1119             continue;
1120         }
1121         if (!isFocusNodeFound_) {
1122             if (postTaskCount < UIFIRST_POSTTASK_HIGHPRIO_MAX) {
1123                 rsSubThreadCache.SetHighPostPriority(true);
1124             } else {
1125                 rsSubThreadCache.SetHighPostPriority(false);
1126             }
1127         } else {
1128             if (focusNodeThreadIndex_ == rsSubThreadCache.GetLastFrameUsedThreadIndex()) {
1129                 rsSubThreadCache.SetHighPostPriority(true);
1130             } else {
1131                 rsSubThreadCache.SetHighPostPriority(false);
1132             }
1133         }
1134     }
1135 }
1136 
1137 // post in drawframe sync time
PostUifistSubTasks()1138 void RSUifirstManager::PostUifistSubTasks()
1139 {
1140     // if screen is power-off, uifirst sub thread can be suspended.
1141     if (RSUniRenderUtil::CheckRenderSkipIfScreenOff()) {
1142         return;
1143     }
1144     PurgePendingPostNodes();
1145     SortSubThreadNodesPriority();
1146     MarkPostNodesPriority();
1147     if (sortedSubThreadNodeIds_.size() > 0) {
1148         RS_TRACE_NAME_FMT("PostUifistSubTasks %zu", sortedSubThreadNodeIds_.size());
1149         for (auto& id : sortedSubThreadNodeIds_) {
1150             PostSubTask(id);
1151         }
1152         pendingPostNodes_.clear();
1153         pendingPostCardNodes_.clear();
1154         sortedSubThreadNodeIds_.clear();
1155     } else {
1156         ClearSubthreadRes();
1157     }
1158     UifirstCurStateClear();
1159 }
1160 
IsInLeashWindowTree(RSSurfaceRenderNode & node,NodeId instanceRootId)1161 bool RSUifirstManager::IsInLeashWindowTree(RSSurfaceRenderNode& node, NodeId instanceRootId)
1162 {
1163     if (node.GetInstanceRootNodeId() == instanceRootId) {
1164         return true;
1165     }
1166     if (!node.IsLeashWindow()) {
1167         return false;
1168     }
1169     for (auto& child : *(node.GetChildren())) {
1170         if (!child) {
1171             continue;
1172         }
1173         auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1174         if (!surfaceChild) {
1175             continue;
1176         }
1177         if (surfaceChild->GetInstanceRootNodeId() == instanceRootId) {
1178             return true;
1179         }
1180     }
1181     return false;
1182 }
1183 
LeashWindowContainMainWindow(RSSurfaceRenderNode & node)1184 static inline bool LeashWindowContainMainWindow(RSSurfaceRenderNode& node)
1185 {
1186     if (node.IsLeashWindow() && node.HasSubSurfaceNodes()) {
1187         return true;
1188     }
1189     return false;
1190 }
1191 
LeashWindowContainMainWindowAndStarting(RSSurfaceRenderNode & node)1192 NodeId RSUifirstManager::LeashWindowContainMainWindowAndStarting(RSSurfaceRenderNode& node)
1193 {
1194     if (!node.IsLeashWindow()) {
1195         return INVALID_NODEID;
1196     }
1197     int mainwindowNum = 0;
1198     int canvasNodeNum = 0;
1199     bool support = true;
1200     std::shared_ptr<RSRenderNode> startingWindow = nullptr;
1201     for (auto& child : *(node.GetSortedChildren())) {
1202         if (!child) {
1203             continue;
1204         }
1205         RS_TRACE_NAME_FMT("nID:%" PRIu64" , nType:%d, support:%d, canvasNodeNum:%d, mainwindowNum:%d",
1206             child->GetId(), static_cast<int>(child->GetType()), support, canvasNodeNum, mainwindowNum);
1207         auto canvasChild = child->ReinterpretCastTo<RSCanvasRenderNode>();
1208         if (canvasChild && canvasChild->GetChildrenCount() == 0 && mainwindowNum > 0) {
1209             canvasNodeNum++;
1210             if (startingWindow != nullptr) {
1211                 startingWindow->SetStartingWindowFlag(false);
1212             }
1213             startingWindow = canvasChild;
1214             continue;
1215         }
1216         auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1217         if (surfaceChild && surfaceChild->IsMainWindowType() && canvasNodeNum == 0) {
1218             mainwindowNum++;
1219             continue;
1220         }
1221         support = false;
1222     }
1223     RS_TRACE_NAME_FMT("uifirst_node support:%d, canvasNodeNum:%d, mainwindowNum:%d, hasStartingWindow:%d",
1224         support, canvasNodeNum, mainwindowNum, startingWindow != nullptr);
1225     if (support && canvasNodeNum == 1 && mainwindowNum > 0 && startingWindow) { // starting window & appwindow
1226         startingWindow->SetStartingWindowFlag(true);
1227         return startingWindow->GetId();
1228     } else {
1229         if (startingWindow) {
1230             startingWindow->SetStartingWindowFlag(false);
1231         }
1232         return INVALID_NODEID;
1233     }
1234 }
1235 
HasStartingWindow(RSSurfaceRenderNode & node)1236 bool RSUifirstManager::HasStartingWindow(RSSurfaceRenderNode& node)
1237 {
1238     auto startingWindowId = LeashWindowContainMainWindowAndStarting(node);
1239     if (startingWindowId != INVALID_NODEID) { // has starting window
1240         node.SetUifirstUseStarting(startingWindowId);
1241         // block first frame callback
1242         NotifyUIStartingWindow(node.GetId(), true);
1243         return true;
1244     }
1245     return false;
1246 }
1247 
AddPendingPostNode(NodeId id,std::shared_ptr<RSSurfaceRenderNode> & node,MultiThreadCacheType currentFrameCacheType)1248 void RSUifirstManager::AddPendingPostNode(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node,
1249     MultiThreadCacheType currentFrameCacheType)
1250 {
1251     if (id == INVALID_NODEID || !node) {
1252         return;
1253     }
1254 
1255     // process for uifirst node
1256     UpdateChildrenDirtyRect(*node);
1257     node->SetHwcChildrenDisabledState();
1258     RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " children disabled by uifirst",
1259         node->GetName().c_str(), node->GetId());
1260     node->AddToPendingSyncList();
1261 
1262     if (currentFrameCacheType == MultiThreadCacheType::LEASH_WINDOW ||
1263         currentFrameCacheType == MultiThreadCacheType::NONFOCUS_WINDOW) {
1264         if (isRecentTaskScene_.load() && !node->IsNodeToBeCaptured() &&
1265             currentFrameCacheType == MultiThreadCacheType::LEASH_WINDOW) {
1266             node->SetIsNodeToBeCaptured(true);
1267         } else if (!isRecentTaskScene_.load()) {
1268             node->SetIsNodeToBeCaptured(false);
1269         }
1270         // delete card node in leashwindow tree
1271         for (auto it = pendingPostCardNodes_.begin(); it != pendingPostCardNodes_.end();) {
1272             auto surfaceNode = it->second;
1273             if (surfaceNode && IsInLeashWindowTree(*node, surfaceNode->GetInstanceRootNodeId())) {
1274                 DisableUifirstNode(*surfaceNode);
1275                 it = pendingPostCardNodes_.erase(it);
1276             } else {
1277                 it++;
1278             }
1279         }
1280         pendingPostNodes_[id] = node;
1281         AddPendingNodeBehindWindow(id, node, currentFrameCacheType);
1282         RS_OPTIONAL_TRACE_NAME_FMT("Add pending id:%" PRIu64 " size:%d", node->GetId(), pendingPostNodes_.size());
1283     } else if (currentFrameCacheType == MultiThreadCacheType::ARKTS_CARD) {
1284         pendingPostCardNodes_[id] = node;
1285     }
1286 
1287     pendingResetNodes_.erase(id); // enable uifirst when waiting for reset
1288 }
1289 
AddPendingNodeBehindWindow(NodeId id,std::shared_ptr<RSSurfaceRenderNode> & node,MultiThreadCacheType currentFrameCacheType)1290 void RSUifirstManager::AddPendingNodeBehindWindow(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node,
1291     MultiThreadCacheType currentFrameCacheType)
1292 {
1293     if (currentFrameCacheType == MultiThreadCacheType::NONFOCUS_WINDOW &&
1294         RSSystemProperties::GetUIFirstBehindWindowEnabled()) {
1295         auto temp_it = pendingNodeBehindWindow_.find(id);
1296         if (temp_it == pendingNodeBehindWindow_.end()) {
1297             RS_OPTIONAL_TRACE_NAME_FMT("Add to pendingNodeBehindWindow id:%" PRIu64 " name:%s", node->GetId(),
1298                 node->GetName().c_str());
1299             pendingNodeBehindWindow_[id] = NodeDataBehindWindow{.curTime = GetMainThreadVsyncTime()};
1300         }
1301     }
1302 }
1303 
AddPendingResetNode(NodeId id,std::shared_ptr<RSSurfaceRenderNode> & node)1304 void RSUifirstManager::AddPendingResetNode(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node)
1305 {
1306     if (id == INVALID_NODEID) {
1307         return;
1308     }
1309     pendingResetNodes_[id] = node;
1310 }
1311 
GetNodeStatus(NodeId id)1312 CacheProcessStatus RSUifirstManager::GetNodeStatus(NodeId id)
1313 {
1314     auto drawable = GetSurfaceDrawableByID(id);
1315     if (drawable) {
1316         return drawable->GetRsSubThreadCache().GetCacheSurfaceProcessedStatus();
1317     }
1318     return CacheProcessStatus::UNKNOWN;
1319 }
1320 
UpdateCompletedSurface(NodeId id)1321 void RSUifirstManager::UpdateCompletedSurface(NodeId id)
1322 {
1323     auto drawable = GetSurfaceDrawableByID(id);
1324     if (drawable) {
1325         drawable->GetRsSubThreadCache().UpdateCompletedCacheSurface();
1326     }
1327 }
1328 
OnProcessEventResponse(DataBaseRs & info)1329 void RSUifirstManager::OnProcessEventResponse(DataBaseRs& info)
1330 {
1331     RSReclaimMemoryManager::Instance().InterruptReclaimTask(info.sceneId);
1332     RS_OPTIONAL_TRACE_NAME_FMT("uifirst uniqueId:%" PRId64", appPid:%" PRId32", sceneId:%s",
1333         info.uniqueId, info.appPid, info.sceneId.c_str());
1334     EventInfo eventInfo = {GetCurSysTime(), 0, info.uniqueId, info.appPid, info.sceneId, {}};
1335     std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1336     for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
1337         it->disableNodes.clear();
1338     }
1339     globalFrameEvent_.push_back(std::move(eventInfo));
1340     currentFrameCanSkipFirstWait_ = EventsCanSkipFirstWait(globalFrameEvent_);
1341 }
1342 
OnProcessEventComplete(DataBaseRs & info)1343 void RSUifirstManager::OnProcessEventComplete(DataBaseRs& info)
1344 {
1345     int64_t curSysTime = GetCurSysTime();
1346     std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1347     for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
1348         if (it->uniqueId == info.uniqueId && it->sceneId == info.sceneId) {
1349             // delay delete for animation continue
1350             it->stopTime = curSysTime;
1351             break;
1352         }
1353     }
1354 }
1355 
EventDisableLeashWindowCache(NodeId id,EventInfo & info)1356 void RSUifirstManager::EventDisableLeashWindowCache(NodeId id, EventInfo& info)
1357 {
1358     std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1359     for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
1360         if (it->uniqueId == info.uniqueId && it->sceneId == info.sceneId) {
1361             it->disableNodes.insert(id);
1362             break;
1363         }
1364     }
1365 }
1366 
PrepareCurrentFrameEvent()1367 void RSUifirstManager::PrepareCurrentFrameEvent()
1368 {
1369     int64_t curSysTime = GetCurSysTime();
1370     currentFrameEvent_.clear();
1371     if (!mainThread_) {
1372         mainThread_ = RSMainThread::Instance();
1373     }
1374     if (mainThread_) {
1375         const auto& nodeMap = mainThread_->GetContext().GetNodeMap();
1376         entryViewNodeId_ = nodeMap.GetEntryViewNodeId();
1377         negativeScreenNodeId_ = nodeMap.GetNegativeScreenNodeId();
1378         scbPid_ = ExtractPid(entryViewNodeId_);
1379     }
1380     {
1381         std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1382         for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end();) {
1383             if (it->stopTime != 0 &&
1384                 ((curSysTime > it->stopTime) && (curSysTime - it->stopTime) > EVENT_STOP_TIMEOUT)) {
1385                 it = globalFrameEvent_.erase(it);
1386                 continue;
1387             }
1388 
1389             if ((curSysTime > it->startTime) && (curSysTime - it->startTime) > EVENT_START_TIMEOUT) {
1390                 it = globalFrameEvent_.erase(it);
1391                 continue;
1392             }
1393             it++;
1394         }
1395         if (globalFrameEvent_.empty()) {
1396             currentFrameCanSkipFirstWait_ = false;
1397             return;
1398         }
1399         // copy global to current, judge leashwindow stop
1400         currentFrameEvent_.assign(globalFrameEvent_.begin(), globalFrameEvent_.end());
1401     }
1402     currentFrameCanSkipFirstWait_ = EventsCanSkipFirstWait(currentFrameEvent_);
1403 }
1404 
OnProcessAnimateScene(SystemAnimatedScenes systemAnimatedScene)1405 void RSUifirstManager::OnProcessAnimateScene(SystemAnimatedScenes systemAnimatedScene)
1406 {
1407     RS_TRACE_NAME_FMT("OnProcessAnimateScene systemAnimatedScene:%d", systemAnimatedScene);
1408     RS_LOGD("OnProcessAnimateScene SystemAnimatedScene:[%{public}d]", systemAnimatedScene);
1409     switch (systemAnimatedScene) {
1410         // recent task scene for phone
1411         case SystemAnimatedScenes::ENTER_RECENTS:
1412             isRecentTaskScene_.store(true);
1413             break;
1414         case SystemAnimatedScenes::EXIT_RECENTS:
1415             isRecentTaskScene_.store(false);
1416             break;
1417         // enter and exit mission center are two independent animations, the same goes for enter and exit split screen
1418         // enter and exit mission center or enter and exit split screen animation starts for PC
1419         case SystemAnimatedScenes::ENTER_MISSION_CENTER:
1420         case SystemAnimatedScenes::EXIT_MISSION_CENTER:
1421             isMissionCenterScene_.store(true);
1422             break;
1423         case SystemAnimatedScenes::ENTER_SPLIT_SCREEN:
1424         case SystemAnimatedScenes::EXIT_SPLIT_SCREEN:
1425             isSplitScreenScene_.store(true);
1426             break;
1427         case SystemAnimatedScenes::SNAPSHOT_ROTATION:
1428             isSnapshotRotationScene_.store(true);
1429             break;
1430         // enter and exit mission center or enter and exit split screen animation ends for PC
1431         case SystemAnimatedScenes::OTHERS:
1432             isMissionCenterScene_.store(false);
1433             isSplitScreenScene_.store(false);
1434             isSnapshotRotationScene_.store(false);
1435             break;
1436         default:
1437             isSnapshotRotationScene_.store(false);
1438             break;
1439     }
1440 }
1441 
NodeIsInCardWhiteList(RSRenderNode & node)1442 bool RSUifirstManager::NodeIsInCardWhiteList(RSRenderNode& node)
1443 {
1444     if ((entryViewNodeId_ != INVALID_NODEID) && (negativeScreenNodeId_ != INVALID_NODEID)) {
1445         auto instanceRootId = node.GetInstanceRootNodeId();
1446         if (instanceRootId == entryViewNodeId_ || instanceRootId == negativeScreenNodeId_) {
1447             return true;
1448         }
1449     }
1450     return false;
1451 }
1452 
IsCardSkipFirstWaitScene(std::string & scene,int32_t appPid)1453 bool RSUifirstManager::IsCardSkipFirstWaitScene(std::string& scene, int32_t appPid)
1454 {
1455     if (appPid != scbPid_) {
1456         return false;
1457     }
1458     for (auto& item : cardCanSkipFirstWaitScene_) {
1459         if ((scene.find(item) != std::string::npos)) {
1460             return true;
1461         }
1462     }
1463     return false;
1464 }
1465 
EventsCanSkipFirstWait(std::vector<EventInfo> & events)1466 bool RSUifirstManager::EventsCanSkipFirstWait(std::vector<EventInfo>& events)
1467 {
1468     if (events.empty()) {
1469         return false;
1470     }
1471     if (isCurrentFrameHasCardNodeReCreate_) {
1472         RS_OPTIONAL_TRACE_NAME("uifirst current frame can't skip wait");
1473         return false;
1474     }
1475     for (auto& item : events) {
1476         if (IsCardSkipFirstWaitScene(item.sceneId, item.appPid)) {
1477             return true;
1478         }
1479     }
1480     return false;
1481 }
1482 
1483 // exit uifirst when leash has APP_LIST_FLING event.
CheckIfAppWindowHasAnimation(RSSurfaceRenderNode & node)1484 bool RSUifirstManager::CheckIfAppWindowHasAnimation(RSSurfaceRenderNode& node)
1485 {
1486     if (currentFrameEvent_.empty()) {
1487         return false;
1488     }
1489 
1490     std::set<int32_t> appPids;
1491     if (node.IsAppWindow()) {
1492         appPids.insert(ExtractPid(node.GetId()));
1493     } else if (node.IsLeashWindow()) {
1494         for (auto& child : *(node.GetChildren())) {
1495             if (!child) {
1496                 continue;
1497             }
1498             auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1499             if (!surfaceChild) {
1500                 continue;
1501             }
1502             if (surfaceChild->IsAppWindow()) {
1503                 appPids.insert(ExtractPid(surfaceChild->GetId()));
1504             }
1505         }
1506     }
1507 
1508     if (appPids.empty()) {
1509         return false;
1510     }
1511     for (auto& item : currentFrameEvent_) {
1512         if (item.disableNodes.count(node.GetId())) {
1513             return true;
1514         }
1515         if (appPids.count(item.appPid) && (node.GetUifirstStartTime() > 0) &&
1516             (node.GetUifirstStartTime() < (item.startTime - EVENT_DISABLE_UIFIRST_GAP)) &&
1517             (item.sceneId.find(EVENT_DISABLE_UIFIRST) != std::string::npos)) {
1518             EventDisableLeashWindowCache(node.GetId(), item);
1519             return true; // app has animation, stop leashwindow uifirst
1520         }
1521     }
1522     return false;
1523 }
1524 
HasBgNodeBelowRootNode(RSSurfaceRenderNode & appNode) const1525 bool RSUifirstManager::HasBgNodeBelowRootNode(RSSurfaceRenderNode& appNode) const
1526 {
1527     auto appFirstChildren = appNode.GetFirstChild();
1528     if (!appFirstChildren) {
1529         return false;
1530     }
1531     auto rootNode = RSBaseRenderNode::ReinterpretCast<RSRootRenderNode>(appFirstChildren);
1532     if (!rootNode) {
1533         return false;
1534     }
1535     auto rootFirstChildren = rootNode->GetFirstChild();
1536     if (!rootFirstChildren) {
1537         return false;
1538     }
1539     auto bgColorNode = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(rootFirstChildren);
1540     if (!bgColorNode) {
1541         return false;
1542     }
1543     auto backgroundColor =
1544         static_cast<Drawing::ColorQuad>(bgColorNode->GetRenderProperties().GetBackgroundColor().AsArgbInt());
1545     if (Drawing::Color::ColorQuadGetA(backgroundColor) != Drawing::Color::COLOR_TRANSPARENT) {
1546         return true;
1547     }
1548     return false;
1549 }
1550 
CheckHasTransAndFilter(RSSurfaceRenderNode & node)1551 bool RSUifirstManager::CheckHasTransAndFilter(RSSurfaceRenderNode& node)
1552 {
1553     if (!node.IsLeashWindow()) {
1554         return false;
1555     }
1556     bool childHasVisibleFilter = node.ChildHasVisibleFilter();
1557     bool hasTransparent = false;
1558     RectI mainAppSurfaceRect = {};
1559     bool isMainAppSurface = false;
1560     bool hasChildOutOfMainAppSurface = false;
1561     for (auto &child : *node.GetSortedChildren()) {
1562         auto childSurface = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1563         if (childSurface == nullptr || hasChildOutOfMainAppSurface) {
1564             continue;
1565         }
1566         if (!isMainAppSurface && childSurface->IsAppWindow()) {
1567             bool isBgColorTrans = HasBgNodeBelowRootNode(*childSurface);
1568             hasTransparent |= (childSurface->IsTransparent() && !isBgColorTrans);
1569             mainAppSurfaceRect = childSurface->GetAbsDrawRect();
1570             isMainAppSurface = true;
1571             RS_OPTIONAL_TRACE_NAME_FMT("Id:%" PRIu64 " name[%s] isTrans:%d isBgTrans:%d, hasTrans:%d",
1572                 childSurface->GetId(), childSurface->GetName().c_str(),
1573                 childSurface->IsTransparent(), isBgColorTrans, hasTransparent);
1574             continue;
1575         }
1576         if (childSurface->IsTransparent() && !childSurface->GetAbsDrawRect().IsInsideOf(mainAppSurfaceRect)) {
1577             RS_OPTIONAL_TRACE_NAME_FMT("Id:%" PRIu64 " name[%s] absDrawRect is outof mainAppNode",
1578                 childSurface->GetId(), childSurface->GetName().c_str());
1579             hasChildOutOfMainAppSurface = true;
1580         }
1581     }
1582     hasTransparent |= hasChildOutOfMainAppSurface;
1583     RS_TRACE_NAME_FMT("CheckHasTransAndFilter node:%" PRIu64 " hasTransparent: %d, childHasVisibleFilter: %d",
1584         node.GetId(), hasTransparent, childHasVisibleFilter);
1585     return hasTransparent && childHasVisibleFilter;
1586 }
1587 
ProcessFirstFrameCache(RSSurfaceRenderNode & node,MultiThreadCacheType cacheType)1588 void RSUifirstManager::ProcessFirstFrameCache(RSSurfaceRenderNode& node, MultiThreadCacheType cacheType)
1589 {
1590     // purpose: to avoid that RT waits uifirst cache long time when switching to uifirst first frame,
1591     // draw and cache win in RT on first frame, then use RT thread cache to draw until uifirst cache ready.
1592     if (node.GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE &&
1593         !node.GetSubThreadAssignable()) {
1594         RS_TRACE_NAME_FMT("AssignMainThread selfAndParentShouldPaint: %d, skipDraw: %d",
1595             node.GetSelfAndParentShouldPaint(), node.GetSkipDraw());
1596         UifirstStateChange(node, MultiThreadCacheType::NONE); // mark as draw win in RT thread
1597         if (node.GetSelfAndParentShouldPaint() && !node.GetSkipDraw()) {
1598             node.SetSubThreadAssignable(true); // mark as assignable to uifirst next frame
1599             node.SetNeedCacheSurface(true); // mark as that needs cache win in RT
1600             auto parent = node.GetParent().lock();
1601             if (parent != nullptr && cacheType == MultiThreadCacheType::ARKTS_CARD) {
1602                 // disable render group for card
1603                 parent->SetDrawingCacheType(RSDrawingCacheType::DISABLED_CACHE);
1604             }
1605             node.SetHwcChildrenDisabledState();
1606             RS_OPTIONAL_TRACE_FMT("name:%s id:%" PRIu64 " children disabled by uifirst first frame",
1607                 node.GetName().c_str(), node.GetId());
1608             // delte caches when node is not on the tree.
1609             auto func = &RSUifirstManager::ProcessTreeStateChange;
1610             node.RegisterTreeStateChangeCallback(func);
1611         }
1612     } else {
1613         UifirstStateChange(node, cacheType);
1614     }
1615 }
1616 
IsArkTsCardCache(RSSurfaceRenderNode & node,bool animation)1617 bool RSUifirstManager::IsArkTsCardCache(RSSurfaceRenderNode& node, bool animation) // maybe canvas node ?
1618 {
1619     auto baseNode = node.GetAncestorScreenNode().lock();
1620     if (!baseNode) {
1621         RS_LOGE("surfaceNode GetAncestorScreenNode().lock() return nullptr");
1622         return false;
1623     }
1624     auto curScreenNode = baseNode->ReinterpretCastTo<RSScreenRenderNode>();
1625     if (curScreenNode == nullptr) {
1626         RS_LOGE("surfaceNode GetAncestorScreenNode().lock() return nullptr");
1627         return false;
1628     }
1629     // card node only enabled uifirst on phone
1630     if (RSUifirstManager::Instance().GetUiFirstMode() != UiFirstModeType::SINGLE_WINDOW_MODE ||
1631         node.GetSurfaceNodeType() != RSSurfaceNodeType::ABILITY_COMPONENT_NODE ||
1632         node.GetName().find(ARKTSCARDNODE_NAME) == std::string::npos) {
1633         return false;
1634     }
1635     bool isWhiteListCard = RSUifirstManager::Instance().NodeIsInCardWhiteList(node);
1636     bool shouldPaint = node.ShouldPaint();
1637     bool isNeedAssignToSubThread = isWhiteListCard && shouldPaint;
1638     RS_TRACE_NAME_FMT("IsArkTsCardCache toSubThread[%d] whiteListCard[%d] shouldPaint[%d]",
1639         isNeedAssignToSubThread, isWhiteListCard, shouldPaint);
1640     return isNeedAssignToSubThread;
1641 }
1642 
1643 // animation first, may reuse last image cache
IsLeashWindowCache(RSSurfaceRenderNode & node,bool animation)1644 bool RSUifirstManager::IsLeashWindowCache(RSSurfaceRenderNode& node, bool animation)
1645 {
1646     if ((RSUifirstManager::Instance().GetUiFirstMode() == UiFirstModeType::MULTI_WINDOW_MODE) ||
1647         (node.GetFirstLevelNodeId() != node.GetId()) ||
1648         (RSUifirstManager::Instance().NodeIsInCardWhiteList(node)) ||
1649         (RSUifirstManager::Instance().CheckIfAppWindowHasAnimation(node))) {
1650         return false;
1651     }
1652     if (!node.IsLeashWindow()) {
1653         return false;
1654     }
1655     // check transparent and childHasVisibleFilter
1656     if (RSUifirstManager::Instance().CheckHasTransAndFilter(node)) {
1657         return false;
1658     }
1659 
1660     bool isNeedAssignToSubThread = false;
1661     bool isScale = node.IsScale();
1662     bool hasFilter = node.HasFilter();
1663     bool isRotate = RSUifirstManager::Instance().rotationChanged_ &&
1664         !RSUifirstManager::Instance().IsSnapshotRotationScene();
1665     bool isRecentScene = RSUifirstManager::Instance().IsRecentTaskScene();
1666     if (isRecentScene) {
1667         isNeedAssignToSubThread = isScale && LeashWindowContainMainWindow(node);
1668     } else {
1669         isNeedAssignToSubThread = animation;
1670     }
1671     isNeedAssignToSubThread = (isNeedAssignToSubThread ||
1672         (node.GetForceUIFirst() || node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_ENABLE_LIMIT)) &&
1673         !hasFilter && !isRotate;
1674 
1675     bool needFilterSCB = IS_SCB_WINDOW_TYPE(node.GetSurfaceWindowType());
1676     if (needFilterSCB || node.IsSelfDrawingType()) {
1677         RS_TRACE_NAME_FMT("IsLeashWindowCache: needFilterSCB [%d]", needFilterSCB);
1678         return false;
1679     }
1680     RS_TRACE_NAME_FMT("IsLeashWindowCache: toSubThread[%d] IsScale[%d]"
1681         " filter:[%d] rotate[%d] captured[%d] snapshotRotation[%d]",
1682         isNeedAssignToSubThread, node.IsScale(),
1683         node.HasFilter(), RSUifirstManager::Instance().rotationChanged_, node.IsNodeToBeCaptured(),
1684         RSUifirstManager::Instance().IsSnapshotRotationScene());
1685     RS_LOGD("IsLeashWindowCache: toSubThread[%{public}d] recent[%{public}d] scale[%{public}d] filter[%{public}d] "
1686         "rotate[%{public}d] snapshotRotation[%{public}d]", isNeedAssignToSubThread, isRecentScene, isScale, hasFilter,
1687         isRotate, RSUifirstManager::Instance().IsSnapshotRotationScene());
1688     return isNeedAssignToSubThread;
1689 }
1690 
1691 // Vm app not use uifirst when it is focused
IsVMSurfaceName(std::string surfaceName)1692 bool RSUifirstManager::IsVMSurfaceName(std::string surfaceName)
1693 {
1694     for (auto& item : vmAppNameSet_) {
1695         if (surfaceName.find(item) != std::string::npos) {
1696             return true;
1697         }
1698     }
1699 
1700     return false;
1701 }
1702 
1703 // NonFocusWindow, may reuse last image cache
IsNonFocusWindowCache(RSSurfaceRenderNode & node,bool animation)1704 bool RSUifirstManager::IsNonFocusWindowCache(RSSurfaceRenderNode& node, bool animation)
1705 {
1706     if (RSUifirstManager::Instance().IsExceededWindowsThreshold(node)) {
1707         RS_TRACE_NAME_FMT("exceededThreshold id:%" PRIu64 ", threshold:%d, curUifirstWindowNums:%d", node.GetId(),
1708             RSUifirstManager::Instance().uifirstWindowsNumThreshold_,
1709             RSUifirstManager::Instance().curUifirstWindowNums_);
1710         return false;
1711     }
1712     bool isDisplayRotation = RSUifirstManager::Instance().rotationChanged_;
1713     if ((RSUifirstManager::Instance().GetUiFirstMode() != UiFirstModeType::MULTI_WINDOW_MODE) ||
1714         (node.GetFirstLevelNodeId() != node.GetId()) ||
1715         (RSUifirstManager::Instance().NodeIsInCardWhiteList(node))) {
1716         return false;
1717     }
1718 
1719     std::string surfaceName = node.GetName();
1720     bool needFilterSCB = IS_SCB_WINDOW_TYPE(node.GetSurfaceWindowType());
1721     if (!(node.GetForceUIFirst() || node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_ENABLE_LIMIT)
1722         && (needFilterSCB || node.IsSelfDrawingType())) {
1723         return false;
1724     }
1725     bool focus = RSUifirstManager::Instance().IsFocusedNode(node);
1726     // open app with modal window animation, close uifirst
1727     bool modalAnimation = animation && node.GetUIFirstSwitch() == RSUIFirstSwitch::MODAL_WINDOW_CLOSE;
1728     bool optFocus = focus || UNLIKELY(node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_DISABLE_NONFOCUS);
1729     if (optFocus && (node.GetHasSharedTransitionNode() ||
1730         (RSUifirstManager::Instance().IsVMSurfaceName(surfaceName) && !animation) ||
1731         !animation || modalAnimation)) {
1732         RS_TRACE_NAME_FMT("IsNonFocusWindowCache: surfaceName[%s] focus:%d optFocus:%d animation:%d switch:%d",
1733             surfaceName.c_str(), focus, optFocus, animation, node.GetUIFirstSwitch());
1734         return false;
1735     }
1736     // disable uifirst when leash window has no app window at recent task scene or split screen scene
1737     if (node.IsLeashWindow() && node.IsScale() && !LeashWindowContainMainWindow(node) &&
1738         (RSUifirstManager::Instance().IsMissionCenterScene() || RSUifirstManager::Instance().IsSplitScreenScene())) {
1739         RS_TRACE_NAME("leash window has no app window, disable uifirst");
1740         return false;
1741     }
1742     return RSUifirstManager::Instance().QuerySubAssignable(node, isDisplayRotation);
1743 }
1744 
IsToSubByAppAnimation() const1745 CM_INLINE bool RSUifirstManager::IsToSubByAppAnimation() const
1746 {
1747     for (auto& it : currentFrameEvent_) {
1748         if (std::find(toSubByAppAnimation_.begin(), toSubByAppAnimation_.end(), it.sceneId) !=
1749             toSubByAppAnimation_.end()) {
1750             return true;
1751         }
1752     }
1753     return false;
1754 }
1755 
GetSubNodeIsTransparent(RSSurfaceRenderNode & node,std::string & dfxMsg)1756 bool RSUifirstManager::GetSubNodeIsTransparent(RSSurfaceRenderNode& node, std::string& dfxMsg)
1757 {
1758     bool hasTransparent = false;
1759     if (node.IsLeashWindow()) {
1760         for (auto &child : *node.GetSortedChildren()) {
1761             auto childSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1762             if (childSurfaceNode == nullptr) {
1763                 continue;
1764             }
1765             hasTransparent |= childSurfaceNode->IsAlphaTransparent() || (childSurfaceNode->NeedDrawBehindWindow() &&
1766                 !RSSystemProperties::GetUIFirstBehindWindowFilterEnabled());
1767             if (hasTransparent) {
1768                 dfxMsg = "childSurfaceNode_NeedDrawBehindWindow: " +
1769                     std::to_string(childSurfaceNode->NeedDrawBehindWindow());
1770                 break;
1771             }
1772         }
1773     } else {
1774         hasTransparent = node.IsAlphaTransparent() || (node.NeedDrawBehindWindow() &&
1775             !RSSystemProperties::GetUIFirstBehindWindowFilterEnabled());
1776         dfxMsg = "NeedDrawBehindWindow: " + std::to_string(node.NeedDrawBehindWindow());
1777     }
1778     if (!hasTransparent || !IsToSubByAppAnimation()) {
1779         // if not transparent, no need to check IsToSubByAppAnimation;
1780         return hasTransparent;
1781     }
1782 
1783     bool isAbilityBgColorTransparent = true;
1784     if (node.IsLeashWindow()) {
1785         for (auto &child : *node.GetSortedChildren()) {
1786             auto childSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1787             if (childSurfaceNode == nullptr) {
1788                 continue;
1789             }
1790             if (childSurfaceNode->GetAbilityBgAlpha() < UINT8_MAX) {
1791                 isAbilityBgColorTransparent = true;
1792                 dfxMsg = "AbBgAlpha: " + std::to_string(childSurfaceNode->GetAbilityBgAlpha());
1793                 break;
1794             } else {
1795                 isAbilityBgColorTransparent = false;
1796             }
1797         }
1798     } else {
1799         isAbilityBgColorTransparent = node.GetAbilityBgAlpha() < UINT8_MAX;
1800         dfxMsg = "AbBgAlpha: " + std::to_string(node.GetAbilityBgAlpha());
1801     }
1802     return isAbilityBgColorTransparent;
1803 }
1804 
QuerySubAssignable(RSSurfaceRenderNode & node,bool isRotation)1805 bool RSUifirstManager::QuerySubAssignable(RSSurfaceRenderNode& node, bool isRotation)
1806 {
1807     if (!node.IsFirstLevelNode()) {
1808         return false;
1809     }
1810 
1811     auto childHasVisibleFilter = node.ChildHasVisibleFilter();
1812     auto hasFilter = node.HasFilter();
1813     auto globalAlpha = node.GetGlobalAlpha();
1814     auto hasProtectedLayer = node.GetSpecialLayerMgr().Find(SpecialLayerType::HAS_PROTECTED);
1815     std::string dfxMsg;
1816     auto hasTransparentSurface = GetSubNodeIsTransparent(node, dfxMsg);
1817 
1818     RS_TRACE_NAME_FMT("SubThreadAssignable node[%lld] hasTransparent: %d, childHasVisibleFilter: %d, hasFilter: %d,"
1819         "isRotation: %d & %d globalAlpha[%f], hasProtectedLayer: %d %s", node.GetId(), hasTransparentSurface,
1820         childHasVisibleFilter, hasFilter, isRotation, RSSystemProperties::GetCacheOptimizeRotateEnable(), globalAlpha,
1821         hasProtectedLayer, dfxMsg.c_str());
1822     bool rotateOptimize = RSSystemProperties::GetCacheOptimizeRotateEnable() ?
1823         !(isRotation && ROSEN_EQ(globalAlpha, 0.0f)) : !isRotation;
1824     return !(hasTransparentSurface && childHasVisibleFilter) && !hasFilter && rotateOptimize && !hasProtectedLayer;
1825 }
1826 
ForceUpdateUifirstNodes(RSSurfaceRenderNode & node)1827 bool RSUifirstManager::ForceUpdateUifirstNodes(RSSurfaceRenderNode& node)
1828 {
1829     bool isForceDisabled = (node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_DISABLE);
1830     bool hasProtectedLayer = node.GetSpecialLayerMgr().Find(SpecialLayerType::HAS_PROTECTED);
1831     if (!isUiFirstOn_ || !node.GetUifirstSupportFlag() || isForceDisabled || hasProtectedLayer) {
1832         RS_LOGD("uifirst disabled. id:%{public}" PRIu64 ",uifirstOn:%{public}d,support:%{public}d,"
1833             "forceDisabled:%{public}d,protectLayer:%{public}d",
1834             node.GetId(), isUiFirstOn_, node.GetUifirstSupportFlag(), isForceDisabled, hasProtectedLayer);
1835         UifirstStateChange(node, MultiThreadCacheType::NONE);
1836         // This branch will be discarded
1837         if (!node.isUifirstNode_) {
1838             node.isUifirstDelay_++;
1839             if (node.isUifirstDelay_ > EVENT_STOP_TIMEOUT) {
1840                 node.isUifirstNode_ = true;
1841             }
1842         }
1843         return true;
1844     }
1845     // This branch will be discarded
1846     if (node.isForceFlag_ && node.IsLeashWindow()) {
1847         RS_OPTIONAL_TRACE_NAME_FMT("ForceUpdateUifirstNodes: isUifirstEnable: %d", node.isUifirstEnable_);
1848         if (!node.isUifirstEnable_) {
1849             UifirstStateChange(node, MultiThreadCacheType::NONE);
1850             return true;
1851         }
1852         UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1853         return true;
1854     }
1855     if (node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_ENABLE && node.IsLeashWindow()) {
1856         RS_OPTIONAL_TRACE_NAME_FMT("ForceUpdateUifirstNodes: nodeName: %s, uiFirstSwitch: %d",
1857             node.GetName().c_str(), node.GetUIFirstSwitch());
1858         if (RSUifirstManager::Instance().GetUiFirstMode() == UiFirstModeType::MULTI_WINDOW_MODE) {
1859             UifirstStateChange(node, MultiThreadCacheType::NONFOCUS_WINDOW);
1860         } else {
1861             UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1862         }
1863         return true;
1864     }
1865     return false;
1866 }
1867 
UpdateUifirstNodes(RSSurfaceRenderNode & node,bool ancestorNodeHasAnimation)1868 void RSUifirstManager::UpdateUifirstNodes(RSSurfaceRenderNode& node, bool ancestorNodeHasAnimation)
1869 {
1870     RS_TRACE_NAME_FMT("UpdateUifirstNodes: Id[%llu] name[%s] FLId[%llu] Ani[%d] Support[%d] isUiFirstOn[%d],"
1871         " isForceFlag:[%d], hasProtectedLayer:[%d] switch:[%d] curUifirstWindowNum:[%d] threshold:[%d]", node.GetId(),
1872         node.GetName().c_str(), node.GetFirstLevelNodeId(), ancestorNodeHasAnimation, node.GetUifirstSupportFlag(),
1873         isUiFirstOn_, node.isForceFlag_, node.GetSpecialLayerMgr().Find(SpecialLayerType::HAS_PROTECTED),
1874         node.GetUIFirstSwitch(), curUifirstWindowNums_, uifirstWindowsNumThreshold_);
1875     if (ForceUpdateUifirstNodes(node)) {
1876         return;
1877     }
1878     if (RSUifirstManager::IsLeashWindowCache(node, ancestorNodeHasAnimation)) {
1879         if (RSSystemParameters::GetUIFirstStartingWindowCacheEnabled()) {
1880             if (node.GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE && HasStartingWindow(node)) {
1881                 UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1882             } else {
1883                 ProcessFirstFrameCache(node, MultiThreadCacheType::LEASH_WINDOW);
1884             }
1885         } else {
1886             UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1887         }
1888         return;
1889     }
1890     if (RSUifirstManager::IsNonFocusWindowCache(node, ancestorNodeHasAnimation)) {
1891         ProcessFirstFrameCache(node, MultiThreadCacheType::NONFOCUS_WINDOW);
1892         return;
1893     }
1894     if (RSUifirstManager::IsArkTsCardCache(node, ancestorNodeHasAnimation)) {
1895         ProcessFirstFrameCache(node, MultiThreadCacheType::ARKTS_CARD);
1896         return;
1897     }
1898     UifirstStateChange(node, MultiThreadCacheType::NONE);
1899 }
1900 
UifirstStateChange(RSSurfaceRenderNode & node,MultiThreadCacheType currentFrameCacheType)1901 void RSUifirstManager::UifirstStateChange(RSSurfaceRenderNode& node, MultiThreadCacheType currentFrameCacheType)
1902 {
1903     auto lastFrameCacheType = node.GetLastFrameUifirstFlag();
1904     if ((lastFrameCacheType != MultiThreadCacheType::NONE) && (lastFrameCacheType != currentFrameCacheType)) {
1905         // not support cache type switch, just disable multithread cache
1906         currentFrameCacheType = MultiThreadCacheType::NONE;
1907     }
1908     if (lastFrameCacheType == MultiThreadCacheType::NONE) { // likely branch: last is disable
1909         if (currentFrameCacheType != MultiThreadCacheType::NONE) { // switch: disable -> enable
1910             auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
1911             if (!surfaceNode) {
1912                 RS_LOGE("UifirstStateChange surfaceNode is nullptr");
1913                 return;
1914             }
1915             RS_TRACE_NAME_FMT("UIFirst_switch disable -> enable %" PRIu64, node.GetId());
1916             RS_LOGI("uifirst disable -> enable. %{public}s id:%{public}" PRIu64, node.GetName().c_str(), node.GetId());
1917             SetUifirstNodeEnableParam(node, currentFrameCacheType);
1918             if (currentFrameCacheType == MultiThreadCacheType::ARKTS_CARD) { // now only update ArkTSCardNode
1919                 node.UpdateTreeUifirstRootNodeId(node.GetId());
1920             }
1921             auto func = &RSUifirstManager::ProcessTreeStateChange;
1922             node.RegisterTreeStateChangeCallback(func);
1923             node.SetUifirstStartTime(GetCurSysTime());
1924             AddPendingPostNode(node.GetId(), surfaceNode, currentFrameCacheType); // clear pending reset status
1925             AddCardNodes(node.GetId(), currentFrameCacheType);
1926             node.SetSubThreadAssignable(true);
1927             node.SetNeedCacheSurface(false);
1928             IncreaseUifirstWindowCount(node);
1929         } else { // keep disable
1930             RS_OPTIONAL_TRACE_NAME_FMT("UIFirst_keep disable  %" PRIu64, node.GetId());
1931             node.SetSubThreadAssignable(false);
1932             node.SetNeedCacheSurface(false);
1933         }
1934     } else { // last is enable
1935         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
1936         if (currentFrameCacheType != MultiThreadCacheType::NONE) { // keep enable
1937             RS_OPTIONAL_TRACE_NAME_FMT("UIFirst_keep enable  %" PRIu64, node.GetId());
1938             RS_LOGD("uifirst keep enable. %{public}s id:%{public}" PRIu64, node.GetName().c_str(), node.GetId());
1939             AddPendingPostNode(node.GetId(), surfaceNode, currentFrameCacheType);
1940             IncreaseUifirstWindowCount(node);
1941         } else { // switch: enable -> disable
1942             RS_TRACE_NAME_FMT("UIFirst_switch enable -> disable %" PRIu64, node.GetId());
1943             RS_LOGI("uifirst enable -> disable. %{public}s id:%{public}" PRIu64, node.GetName().c_str(), node.GetId());
1944             node.SetUifirstStartTime(-1); // -1: default start time
1945             AddPendingResetNode(node.GetId(), surfaceNode); // set false onsync when task done
1946             RemoveCardNodes(node.GetId());
1947             node.SetSubThreadAssignable(false);
1948             node.SetNeedCacheSurface(false);
1949 
1950             auto tempNodeToClear = pendingNodeBehindWindow_.find(node.GetId());
1951             if (tempNodeToClear != pendingNodeBehindWindow_.end()) {
1952                 RS_OPTIONAL_TRACE_NAME_FMT("clear node in pendingNodeBehindWindow %{public}s id:%{public}" PRIu64,
1953                     node.GetName().c_str(), node.GetId());
1954                 pendingNodeBehindWindow_.erase(tempNodeToClear);
1955             }
1956             DecreaseUifirstWindowCount(node);
1957         }
1958     }
1959     node.SetLastFrameUifirstFlag(currentFrameCacheType);
1960 }
1961 
1962 // appwindow will not be traversed in process when cache leashwindow
UpdateChildrenDirtyRect(RSSurfaceRenderNode & node)1963 void RSUifirstManager::UpdateChildrenDirtyRect(RSSurfaceRenderNode& node)
1964 {
1965     RectI rect(0, 0, 0, 0);
1966     if (node.IsLeashWindow()) {
1967         for (auto& child : *(node.GetChildren())) {
1968             if (!child) {
1969                 continue;
1970             }
1971             auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1972             if (!surfaceChild) {
1973                 continue;
1974             }
1975             if (surfaceChild->IsMainWindowType()) {
1976                 rect = rect.JoinRect(surfaceChild->GetOldDirtyInSurface());
1977                 continue;
1978             }
1979         }
1980     }
1981     node.SetUifirstChildrenDirtyRectParam(rect);
1982 }
1983 
ProcessTreeStateChange(RSSurfaceRenderNode & node)1984 void RSUifirstManager::ProcessTreeStateChange(RSSurfaceRenderNode& node)
1985 {
1986     RSUifirstManager::Instance().CheckCurrentFrameHasCardNodeReCreate(node);
1987     // Planning: do not clear complete image for card
1988     if (node.IsOnTheTree()) {
1989         return;
1990     }
1991     RSUifirstManager::Instance().DisableUifirstNode(node);
1992     RSUifirstManager::Instance().ForceClearSubthreadRes();
1993     RSUifirstManager::Instance().RemoveCardNodes(node.GetId());
1994 }
1995 
DisableUifirstNode(RSSurfaceRenderNode & node)1996 void RSUifirstManager::DisableUifirstNode(RSSurfaceRenderNode& node)
1997 {
1998     RS_TRACE_NAME_FMT("DisableUifirstNode node[%lld] %s", node.GetId(), node.GetName().c_str());
1999     UifirstStateChange(node, MultiThreadCacheType::NONE);
2000 
2001     auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
2002     pendingResetWindowCachedNodes_.emplace_back(surfaceNode);
2003 }
2004 
AddCapturedNodes(NodeId id)2005 void RSUifirstManager::AddCapturedNodes(NodeId id)
2006 {
2007     capturedNodes_.push_back(id);
2008 }
2009 
ResetCurrentFrameDeletedCardNodes()2010 void RSUifirstManager::ResetCurrentFrameDeletedCardNodes()
2011 {
2012     currentFrameDeletedCardNodes_.clear();
2013     isCurrentFrameHasCardNodeReCreate_ = false;
2014 }
2015 
CheckCurrentFrameHasCardNodeReCreate(const RSSurfaceRenderNode & node)2016 void RSUifirstManager::CheckCurrentFrameHasCardNodeReCreate(const RSSurfaceRenderNode& node)
2017 {
2018     if (node.GetSurfaceNodeType() != RSSurfaceNodeType::ABILITY_COMPONENT_NODE ||
2019         node.GetName().find(ARKTSCARDNODE_NAME) == std::string::npos) {
2020         return;
2021     }
2022     if (!node.IsOnTheTree()) {
2023         currentFrameDeletedCardNodes_.emplace_back(node.GetId());
2024     } else if (std::find(currentFrameDeletedCardNodes_.begin(), currentFrameDeletedCardNodes_.end(),
2025         node.GetId()) != currentFrameDeletedCardNodes_.end()) {
2026         isCurrentFrameHasCardNodeReCreate_ = true;
2027     }
2028 }
2029 
CheckMatchAndWaitNotify(const RSRenderParams & params,bool checkMatch)2030 bool RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(const RSRenderParams& params, bool checkMatch)
2031 {
2032     if (checkMatch && IsCurFirstLevelMatch(params)) {
2033         return true;
2034     }
2035     return CheckAndWaitPreFirstLevelDrawableNotify(params);
2036 }
2037 
CheckAndWaitPreFirstLevelDrawableNotify(const RSRenderParams & params)2038 bool RSUiFirstProcessStateCheckerHelper::CheckAndWaitPreFirstLevelDrawableNotify(const RSRenderParams& params)
2039 {
2040     auto firstLevelNodeId = params.GetFirstLevelNodeId();
2041     auto uifirstRootNodeId = params.GetUifirstRootNodeId();
2042     auto rootId = uifirstRootNodeId != INVALID_NODEID ? uifirstRootNodeId : firstLevelNodeId;
2043     if (rootId == INVALID_NODEID) {
2044         /* uifirst will not draw with no firstlevel node, and there's no need to check and wait for uifirst onDraw */
2045         RS_LOGD("uifirst node %{public}" PRIu64 " uifirstrootNodeId is INVALID_NODEID", params.GetId());
2046         return true;
2047     }
2048 
2049     auto uifirstRootNodeDrawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(rootId);
2050     if (!uifirstRootNodeDrawable) {
2051         // drawable may release when node off tree
2052         // uifirst will not draw with null uifirstRootNodeDrawable
2053         RS_LOGW("uifirstnode %{public}" PRIu64 " uifirstroot %{public}" PRIu64 " nullptr", params.GetId(), rootId);
2054         return true;
2055     }
2056 
2057     if (UNLIKELY(uifirstRootNodeDrawable->GetNodeType() != RSRenderNodeType::SURFACE_NODE)) {
2058         RS_LOGE("uifirst invalid uifirstrootNodeId %{public}" PRIu64, rootId);
2059         return false;
2060     }
2061     auto uifirstRootSurfaceNodeDrawable =
2062         std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(uifirstRootNodeDrawable);
2063 
2064     RS_TRACE_NAME_FMT("CheckAndWaitPreFirstLevelDrawableNotify %" PRIu64 " wait for %" PRIu64 "",
2065         params.GetId(), uifirstRootSurfaceNodeDrawable->GetId());
2066 
2067     static constexpr auto TIME_OUT = std::chrono::milliseconds(500); // 500ms for timeout
2068     auto pred = [uifirstRootSurfaceNodeDrawable] {
2069         auto curState = uifirstRootSurfaceNodeDrawable->GetRsSubThreadCache().GetCacheSurfaceProcessedStatus();
2070         return curState == CacheProcessStatus::DONE || curState == CacheProcessStatus::UNKNOWN ||
2071             curState == CacheProcessStatus::SKIPPED;
2072     };
2073     std::unique_lock<std::mutex> lock(notifyMutex_);
2074     notifyCv_.wait_for(lock, TIME_OUT, pred);
2075     auto ret = pred();
2076     if (!ret) {
2077         RS_LOGE("uifirst nodeId %{public}" PRIu64
2078             " wait uifirstrootNodeId %{public}" PRIu64 " until 500ms timeout", params.GetId(), rootId);
2079     }
2080     return ret;
2081 }
2082 
IsCurFirstLevelMatch(const RSRenderParams & params)2083 bool RSUiFirstProcessStateCheckerHelper::IsCurFirstLevelMatch(const RSRenderParams& params)
2084 {
2085     auto uifirstRootNodeId = params.GetUifirstRootNodeId();
2086     auto firstLevelNodeId = params.GetFirstLevelNodeId();
2087 
2088     RS_OPTIONAL_TRACE_NAME_FMT("RSUiFirstProcessStateCheckerHelper IsCurFirstLevelMatch In node[%"
2089         PRIu64 "  %" PRIu64"] cur[%" PRIu64 "  %" PRIu64 "] in nodeId[%" PRIu64 "]",
2090         uifirstRootNodeId, firstLevelNodeId, curUifirstRootNodeId_, curFirstLevelNodeId_, params.GetId());
2091 
2092     if (curUifirstRootNodeId_ == INVALID_NODEID && curFirstLevelNodeId_ == INVALID_NODEID) {
2093         // should draw because uifirst may not inited
2094         return true;
2095     }
2096     auto uiFirstCheckRet = uifirstRootNodeId == curUifirstRootNodeId_ && curUifirstRootNodeId_ != INVALID_NODEID;
2097     auto firstLevelCheckRet = firstLevelNodeId == curFirstLevelNodeId_ && curFirstLevelNodeId_ != INVALID_NODEID;
2098     if (uiFirstCheckRet || firstLevelCheckRet) {
2099         return true;
2100     }
2101     return false;
2102 }
2103 
GetCacheSurfaceProcessedStatus(const RSSurfaceRenderParams & surfaceParams)2104 CacheProcessStatus RSUifirstManager::GetCacheSurfaceProcessedStatus(const RSSurfaceRenderParams& surfaceParams)
2105 {
2106     CacheProcessStatus curRootIdState = CacheProcessStatus::UNKNOWN;
2107     auto uifirstRootId = surfaceParams.GetUifirstRootNodeId() != INVALID_NODEID ?
2108         surfaceParams.GetUifirstRootNodeId() : surfaceParams.GetFirstLevelNodeId();
2109     auto uifirstRootNodeDrawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(uifirstRootId);
2110     if (uifirstRootNodeDrawable && uifirstRootNodeDrawable->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
2111         auto drawableNode = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(uifirstRootNodeDrawable);
2112         curRootIdState = drawableNode->GetRsSubThreadCache().GetCacheSurfaceProcessedStatus();
2113     }
2114     return curRootIdState;
2115 }
2116 
GetUiFirstMode()2117 UiFirstModeType RSUifirstManager::GetUiFirstMode()
2118 {
2119     if (uifirstType_ == UiFirstCcmType::SINGLE) {
2120         return UiFirstModeType::SINGLE_WINDOW_MODE;
2121     }
2122     if (uifirstType_ == UiFirstCcmType::MULTI) {
2123         return UiFirstModeType::MULTI_WINDOW_MODE;
2124     }
2125     if (uifirstType_ == UiFirstCcmType::HYBRID) {
2126         return isFreeMultiWindowEnabled_ ? UiFirstModeType::MULTI_WINDOW_MODE : UiFirstModeType::SINGLE_WINDOW_MODE;
2127     }
2128     return UiFirstModeType::SINGLE_WINDOW_MODE;
2129 }
2130 
ReadUIFirstCcmParam()2131 void RSUifirstManager::ReadUIFirstCcmParam()
2132 {
2133 #ifdef ROSEN_EMULATOR
2134     // close uifirst on emulator
2135     isUiFirstOn_ = false;
2136     isCardUiFirstOn_ = false;
2137 #else
2138     isUiFirstOn_ = UIFirstParam::IsUIFirstEnable();
2139     isCardUiFirstOn_ = UIFirstParam::IsCardUIFirstEnable();
2140 #endif
2141     SetUiFirstType(UIFirstParam::GetUIFirstType());
2142     uifirstWindowsNumThreshold_ = UIFirstParam::GetUIFirstEnableWindowThreshold();
2143     RS_LOGI("ReadUIFirstCcmParam isUiFirstOn_=%{public}d isCardUiFirstOn_=%{public}d"
2144         " uifirstType_=%{public}d uiFirstEnableWindowThreshold_=%{public}d",
2145         isUiFirstOn_, isCardUiFirstOn_, static_cast<int>(uifirstType_), uifirstWindowsNumThreshold_);
2146 }
2147 
SetUiFirstType(int type)2148 void RSUifirstManager::SetUiFirstType(int type)
2149 {
2150     if (type < (int)UiFirstCcmType::SINGLE || type > (int)UiFirstCcmType::HYBRID) {
2151         return;
2152     }
2153     if (type == (int)UiFirstCcmType::SINGLE) {
2154         uifirstType_ = UiFirstCcmType::SINGLE;
2155     } else if (type == (int)UiFirstCcmType::MULTI) {
2156         uifirstType_ = UiFirstCcmType::MULTI;
2157     } else if (type == (int)UiFirstCcmType::HYBRID) {
2158         uifirstType_ = UiFirstCcmType::HYBRID;
2159     }
2160 }
2161 
RefreshUIFirstParam()2162 void RSUifirstManager::RefreshUIFirstParam()
2163 {
2164     RSUifirstManager::Instance().SetPurgeEnable(RSSystemParameters::GetUIFirstPurgeEnabled());
2165     const std::shared_ptr<RSBaseRenderNode> rootNode = RSMainThread::Instance()->GetContext()
2166         .GetGlobalRootRenderNode();
2167     if (!rootNode) {
2168         return;
2169     }
2170     auto firstChildren = rootNode->GetFirstChild();
2171     if (!firstChildren) {
2172         return;
2173     }
2174     auto screenNode = RSBaseRenderNode::ReinterpretCast<RSScreenRenderNode>(firstChildren);
2175     if (!screenNode) {
2176         return;
2177     }
2178     isUiFirstSupportFlag_ = true;
2179 }
2180 
IsSubTreeNeedPrepareForSnapshot(RSSurfaceRenderNode & node)2181 bool RSUifirstManager::IsSubTreeNeedPrepareForSnapshot(RSSurfaceRenderNode& node)
2182 {
2183     return RSUifirstManager::Instance().IsRecentTaskScene() &&
2184         (node.IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId()) ||
2185         node.IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()));
2186 }
2187 
IsSubHighPriorityType(RSSurfaceRenderNode & node) const2188 bool RSUifirstManager::IsSubHighPriorityType(RSSurfaceRenderNode& node) const
2189 {
2190     return node.GetName().find("hipreview") != std::string::npos;
2191 }
2192 
CheckHwcChildrenType(RSSurfaceRenderNode & node,SurfaceHwcNodeType & enabledType)2193 void RSUifirstManager::CheckHwcChildrenType(RSSurfaceRenderNode& node, SurfaceHwcNodeType& enabledType)
2194 {
2195     if (enabledType == SurfaceHwcNodeType::DEFAULT_HWC_ROSENWEB) {
2196         return;
2197     }
2198     if (node.IsAppWindow()) {
2199         auto hwcNodes = node.GetChildHardwareEnabledNodes();
2200         if (hwcNodes.empty()) {
2201             return;
2202         }
2203         if (IsSubHighPriorityType(node)) {
2204             enabledType = SurfaceHwcNodeType::DEFAULT_HWC_VIDEO;
2205             return;
2206         }
2207         if (node.IsRosenWeb()) {
2208             enabledType = SurfaceHwcNodeType::DEFAULT_HWC_ROSENWEB;
2209             return;
2210         }
2211         for (auto hwcNode : hwcNodes) {
2212             auto hwcNodePtr = hwcNode.lock();
2213             if (!hwcNodePtr) {
2214                 continue;
2215             }
2216             if (hwcNodePtr->IsRosenWeb()) {
2217                 enabledType = SurfaceHwcNodeType::DEFAULT_HWC_ROSENWEB;
2218                 return;
2219             }
2220             if (IsSubHighPriorityType(*hwcNodePtr)) {
2221                 enabledType = SurfaceHwcNodeType::DEFAULT_HWC_VIDEO;
2222                 return;
2223             }
2224         }
2225     } else if (node.IsLeashWindow()) {
2226         for (auto& child : *(node.GetChildren())) {
2227             auto surfaceNode = child->ReinterpretCastTo<RSSurfaceRenderNode>();
2228             if (surfaceNode == nullptr) {
2229                 continue;
2230             }
2231             CheckHwcChildrenType(*surfaceNode, enabledType);
2232         }
2233     }
2234 }
2235 
MarkSubHighPriorityType(RSSurfaceRenderNode & node)2236 void RSUifirstManager::MarkSubHighPriorityType(RSSurfaceRenderNode& node)
2237 {
2238     if (uifirstType_ != UiFirstCcmType::MULTI) {
2239         return;
2240     }
2241     SurfaceHwcNodeType preSubHighPriority = SurfaceHwcNodeType::DEFAULT_HWC_TYPE;
2242     CheckHwcChildrenType(node, preSubHighPriority);
2243     RS_OPTIONAL_TRACE_NAME_FMT("SubHighPriorityType::name:[%s] preSub:%d", node.GetName().c_str(), preSubHighPriority);
2244     node.SetPreSubHighPriorityType(preSubHighPriority == SurfaceHwcNodeType::DEFAULT_HWC_VIDEO);
2245 }
2246 
RecordScreenRect(RSSurfaceRenderNode & node,RectI rect)2247 void RSUifirstManager::RecordScreenRect(RSSurfaceRenderNode& node, RectI rect)
2248 {
2249     auto stagingSurfaceParams = static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
2250     if (!stagingSurfaceParams) {
2251         RS_LOGE("RecordScreenRect stagingSurfaceParams is nullptr");
2252         return;
2253     }
2254     stagingSurfaceParams->RecordScreenRect(rect);
2255     node.AddToPendingSyncList();
2256 }
2257 
RecordDirtyRegionMatrix(RSSurfaceRenderNode & node,const Drawing::Matrix & matrix)2258 void RSUifirstManager::RecordDirtyRegionMatrix(RSSurfaceRenderNode& node, const Drawing::Matrix& matrix)
2259 {
2260     auto stagingSurfaceParams = static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
2261     if (!stagingSurfaceParams) {
2262         RS_LOGE("RecordDirtyRegionMatrix stagingSurfaceParams is nullptr");
2263         return;
2264     }
2265     stagingSurfaceParams->RecordDirtyRegionMatrix(matrix);
2266     node.AddToPendingSyncList();
2267 }
2268 
IsFocusedNode(const RSSurfaceRenderNode & node) const2269 bool RSUifirstManager::IsFocusedNode(const RSSurfaceRenderNode& node) const
2270 {
2271     return node.IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()) ||
2272         node.IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId());
2273 }
2274 
IncreaseUifirstWindowCount(const RSSurfaceRenderNode & node)2275 void RSUifirstManager::IncreaseUifirstWindowCount(const RSSurfaceRenderNode& node)
2276 {
2277     if (IsFocusedNode(node) || node.IsAbilityComponent()) {
2278         return;
2279     }
2280     curUifirstWindowNums_++;
2281 }
2282 
DecreaseUifirstWindowCount(const RSSurfaceRenderNode & node)2283 void RSUifirstManager::DecreaseUifirstWindowCount(const RSSurfaceRenderNode& node)
2284 {
2285     if (IsFocusedNode(node) || node.IsAbilityComponent()) {
2286         return;
2287     }
2288     if (curUifirstWindowNums_ > 0) {
2289         curUifirstWindowNums_--;
2290     }
2291 }
2292 
IsExceededWindowsThreshold(const RSSurfaceRenderNode & node) const2293 bool RSUifirstManager::IsExceededWindowsThreshold(const RSSurfaceRenderNode& node) const
2294 {
2295     // no restriction when threshold is less than or equal to 0
2296     if (uifirstWindowsNumThreshold_ <= 0) {
2297         return false;
2298     }
2299 
2300     // do not count focus window
2301     if (IsFocusedNode(node)) {
2302         return false;
2303     }
2304 
2305     // Non-focus window, Z/V sequence control
2306     if (curUifirstWindowNums_ < uifirstWindowsNumThreshold_) {
2307         return false;
2308     }
2309     return true;
2310 }
2311 
AddMarkedClearCacheNode(NodeId id)2312 void RSUifirstManager::AddMarkedClearCacheNode(NodeId id)
2313 {
2314     RS_TRACE_NAME_FMT("AddMarkedClearCacheNode %" PRIu64, id);
2315     RS_LOGI("AddMarkedClearCacheNode %{public}" PRIu64, id);
2316     if (id == INVALID_NODEID) {
2317         return;
2318     }
2319 
2320     markedClearCacheNodes_.insert(id);
2321 }
2322 
ProcessMarkedNodeSubThreadCache()2323 void RSUifirstManager::ProcessMarkedNodeSubThreadCache()
2324 {
2325     RS_OPTIONAL_TRACE_NAME_FMT("ProcessMarkedNodeSubThreadCache size:%d", markedClearCacheNodes_.size());
2326     for (auto& markedNode : markedClearCacheNodes_) {
2327         if (subthreadProcessingNode_.find(markedNode) == subthreadProcessingNode_.end()) {
2328             auto drawable = GetSurfaceDrawableByID(markedNode);
2329             if (!drawable) {
2330                 RS_LOGE("ProcessMarkedNodeSubThreadCache drawable is null. id:%{public}" PRIu64, markedNode);
2331                 continue;
2332             }
2333             if ((pendingPostNodes_.find(markedNode) != pendingPostNodes_.end()) ||
2334                 (pendingPostCardNodes_.find(markedNode) != pendingPostCardNodes_.end())) {
2335                 continue;
2336             }
2337             RS_TRACE_NAME_FMT("ProcessMarkedNodeSubThreadCache id:%" PRIu64, markedNode);
2338             RS_LOGI("ProcessMarkedNodeSubThreadCache id:%{public}" PRIu64, markedNode);
2339             auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
2340             rsSubThreadCache.ClearCacheSurfaceOnly();
2341         }
2342     }
2343     markedClearCacheNodes_.clear();
2344 }
2345 } // namespace Rosen
2346 } // namespace OHOS
2347