• 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 #ifndef RS_UIFIRST_MANAGER_H
17 #define RS_UIFIRST_MANAGER_H
18 
19 #include <chrono>
20 #include <condition_variable>
21 #include <map>
22 #include <set>
23 #include <vector>
24 
25 #include "drawable/rs_surface_render_node_drawable.h"
26 #include "pipeline/rs_processor.h"
27 #include "pipeline/main_thread/rs_main_thread.h"
28 #include "pipeline/rs_surface_render_node.h"
29 #include "transaction/rs_render_service_client.h"
30 
31 namespace OHOS::Rosen {
32 class RSUifirstManager {
33 public:
34     // planning: move to display node
35     static RSUifirstManager& Instance();
36 
37     typedef enum {
38         STATE_NEED_SKIP,
39         STATE_NOT_SKIP,
40         STATE_NEED_CHECK,
41     } SkipSyncState;
42 
43     struct EventInfo {
44         int64_t startTime = 0;
45         int64_t stopTime = 0;
46         int64_t uniqueId = 0;
47         int32_t appPid = -1;
48         std::string sceneId;
49         std::set<NodeId> disableNodes;
50     };
51 
52     void AddProcessDoneNode(NodeId id);
53     void AddProcessSkippedNode(NodeId id);
54     void AddPendingPostNode(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node,
55         MultiThreadCacheType cacheType);
56     void AddPendingResetNode(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node);
57     void AddPendingNodeBehindWindow(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node,
58     MultiThreadCacheType currentFrameCacheType);
59 
60     bool NeedNextDrawForSkippedNode();
61 
62     CacheProcessStatus GetNodeStatus(NodeId id);
63     // judge if surfacenode satisfies async subthread rendering condtions for Uifirst
64     void UpdateUifirstNodes(RSSurfaceRenderNode& node, bool ancestorNodeHasAnimation);
65     void UpdateUIFirstNodeUseDma(RSSurfaceRenderNode& node, const std::vector<RectI>& rects);
66     void PostUifistSubTasks();
67     void ProcessSubDoneNode();
68     // check whether the node should skip onsync process,
69     // if node is drawing in subthread, onsync may cause wrong result.
70     bool CollectSkipSyncNode(const std::shared_ptr<RSRenderNode> &node);
71     void ForceClearSubthreadRes();
72     void ProcessForceUpdateNode();
73     // check if uifirst is force-enabled or force-disabled
74     bool ForceUpdateUifirstNodes(RSSurfaceRenderNode& node);
75 
76     // process animation events, such as LAUNCHER_SCROLL
77     void OnProcessEventResponse(DataBaseRs& info);
78     void OnProcessEventComplete(DataBaseRs& info);
79     void PrepareCurrentFrameEvent();
80 
81     // animate procss
82     void OnProcessAnimateScene(SystemAnimatedScenes systemAnimatedScene);
83 
84     // check if node is child of main screen or negative screen
85     bool NodeIsInCardWhiteList(RSRenderNode& node);
GetCurrentFrameSkipFirstWait()86     bool GetCurrentFrameSkipFirstWait() const
87     {
88         return currentFrameCanSkipFirstWait_.load();
89     }
90     bool CheckIfAppWindowHasAnimation(RSSurfaceRenderNode& node);
91     void DisableUifirstNode(RSSurfaceRenderNode& node);
92     static void ProcessTreeStateChange(RSSurfaceRenderNode& node);
93 
GetUiFirstSwitch()94     bool GetUiFirstSwitch() const
95     {
96         return isUiFirstOn_ && isUiFirstSupportFlag_;
97     }
98 
GetUiFirstType()99     UiFirstCcmType GetUiFirstType() const
100     {
101         return uifirstType_;
102     }
103 
104     void SetUiFirstType(int type);
105 
SetPurgeEnable(bool purgeEnable)106     void SetPurgeEnable(bool purgeEnable)
107     {
108         purgeEnable_ = purgeEnable;
109     }
110 
SetCardUiFirstSwitch(bool cardUiFirstSwitch)111     void SetCardUiFirstSwitch(bool cardUiFirstSwitch)
112     {
113         isCardUiFirstOn_ = cardUiFirstSwitch;
114     }
115 
SetNodeNeedForceUpdateFlag(bool flag)116     void SetNodeNeedForceUpdateFlag(bool flag)
117     {
118         hasForceUpdateNode_ = flag;
119     }
120 
HasForceUpdateNode()121     bool HasForceUpdateNode()
122     {
123         return hasForceUpdateNode_;
124     }
125 
126     void MergeOldDirty(NodeId id);
127     void MergeOldDirtyToDirtyManager(std::shared_ptr<RSSurfaceRenderNode>& node);
128 
PreStatusProcess(bool rotationChanged)129     void PreStatusProcess(bool rotationChanged)
130     {
131         rotationChanged_ = rotationChanged;
132         curUifirstWindowNums_ = 0;
133     }
134 
IsRecentTaskScene()135     bool IsRecentTaskScene() const
136     {
137         return isRecentTaskScene_.load();
138     }
139 
IsMissionCenterScene()140     bool IsMissionCenterScene() const
141     {
142         return isMissionCenterScene_.load();
143     }
144 
IsSplitScreenScene()145     bool IsSplitScreenScene() const
146     {
147         return isSplitScreenScene_.load();
148     }
149 
IsSnapshotRotationScene()150     bool IsSnapshotRotationScene() const
151     {
152         return isSnapshotRotationScene_;
153     }
154 
155     void AddCapturedNodes(NodeId id);
156 
AddCardNodes(NodeId id,MultiThreadCacheType currentFrameCacheType)157     void AddCardNodes(NodeId id, MultiThreadCacheType currentFrameCacheType)
158     {
159         if (currentFrameCacheType != MultiThreadCacheType::ARKTS_CARD) {
160             return;
161         }
162         collectedCardNodes_.insert(id);
163     }
164 
RemoveCardNodes(NodeId id)165     void RemoveCardNodes(NodeId id)
166     {
167         if (!collectedCardNodes_.count(id)) {
168             return;
169         }
170         collectedCardNodes_.erase(id);
171     }
172 
GetPendingPostNodes()173     std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>> GetPendingPostNodes()
174     {
175         return pendingPostNodes_;
176     }
177 
178     void PostReleaseCacheSurfaceSubTasks();
179     void PostReleaseCacheSurfaceSubTask(NodeId id);
180     void TryReleaseTextureForIdleThread();
181 
182     // only use in mainThread & RT onsync
UifirstCurStateClear()183     inline void UifirstCurStateClear()
184     {
185         uifirstCacheState_.clear();
186     }
187 
SetFreeMultiWindowStatus(bool enable)188     void SetFreeMultiWindowStatus(bool enable)
189     {
190         isFreeMultiWindowEnabled_ = enable;
191     }
192     UiFirstModeType GetUiFirstMode();
193     void ReadUIFirstCcmParam();
194     void RefreshUIFirstParam();
195 
196     bool IsSubTreeNeedPrepareForSnapshot(RSSurfaceRenderNode& node);
197     bool IsSubHighPriorityType(RSSurfaceRenderNode& node) const;
198     void CheckHwcChildrenType(RSSurfaceRenderNode& node, SurfaceHwcNodeType& enabledType);
199     void MarkSubHighPriorityType(RSSurfaceRenderNode& node);
200     void MarkPostNodesPriority();
201     void RecordScreenRect(RSSurfaceRenderNode& node, RectI rect);
202     void RecordDirtyRegionMatrix(RSSurfaceRenderNode& node, const Drawing::Matrix& matrix);
203     // get cache state of uifirst root node
204     CacheProcessStatus GetCacheSurfaceProcessedStatus(const RSSurfaceRenderParams& surfaceParams);
205     bool SubThreadControlFrameRate(NodeId id,
206     std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable>& drawable,
207     std::shared_ptr<RSSurfaceRenderNode>& node);
208     void AddMarkedClearCacheNode(NodeId id);
209     void ProcessMarkedNodeSubThreadCache();
IsUiFirstWorking()210     bool IsUiFirstWorking() const
211     {
212         return !subthreadProcessingNode_.empty();
213     }
214 private:
215     struct NodeDataBehindWindow {
216         uint64_t curTime = 0;
217         bool isFirst = true;
218     };
219     RSUifirstManager() = default;
220     ~RSUifirstManager() = default;
221     RSUifirstManager(const RSUifirstManager&);
222     RSUifirstManager(const RSUifirstManager&&);
223     RSUifirstManager& operator=(const RSUifirstManager&);
224     RSUifirstManager& operator=(const RSUifirstManager&&);
225 
226     void PostSubTask(NodeId id);
227     void UpdateCompletedSurface(NodeId id);
228 
229     std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> GetSurfaceDrawableByID(NodeId id);
230     bool SetUifirstNodeEnableParam(RSSurfaceRenderNode& node, MultiThreadCacheType type);
231     void RenderGroupUpdate(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable);
232     bool IsInLeashWindowTree(RSSurfaceRenderNode& node, NodeId instanceRootId);
233 
234     void ProcessResetNode();
235     void ProcessSkippedNode();
236     void ProcessDoneNode();
237     void ProcessDoneNodeInner();
238     void UpdateSkipSyncNode();
239     void RestoreSkipSyncNode();
240     void ClearSubthreadRes();
241     // reset node status and clear cache when exit uifirst
242     void ResetUifirstNode(std::shared_ptr<RSSurfaceRenderNode>& nodePtr);
243     // clear main thread cache
244     void ResetWindowCache(std::shared_ptr<RSSurfaceRenderNode>& nodePtr);
245     bool CheckVisibleDirtyRegionIsEmpty(const std::shared_ptr<RSSurfaceRenderNode>& node);
246     bool CurSurfaceHasVisibleDirtyRegion(const std::shared_ptr<RSSurfaceRenderNode>& node);
247     bool IsBehindWindowOcclusion(const std::shared_ptr<RSSurfaceRenderNode>& node);
248     bool NeedPurgeByBehindWindow(NodeId id, bool hasTexture,
249     const std::shared_ptr<RSSurfaceRenderNode>& node);
250     // filter out the nodes by behind window
251     void HandlePurgeBehindWindow(std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>::iterator& it,
252         std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>& pendingNode);
253     // filter out the nodes which need to draw in subthread
254     void DoPurgePendingPostNodes(std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>& pendingNode);
255     // use in behindwindow condition to calculate the node purge time interval
256     uint64_t GetTimeDiffBehindWindow(uint64_t currentTime, NodeId id);
257     uint64_t GetMainThreadVsyncTime();
258     void PurgePendingPostNodes();
259     void SetNodePriorty(std::list<NodeId>& result,
260         std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>& pendingNode);
261     void SortSubThreadNodesPriority();
262     // check if ArkTsCard enable uifirst
263     static bool IsArkTsCardCache(RSSurfaceRenderNode& node, bool animation);
264     // check if leash window enable uifirst
265     static bool IsLeashWindowCache(RSSurfaceRenderNode& node, bool animation);
266     void SyncHDRDisplayParam(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable,
267         const GraphicColorGamut& colorGamut);
268     // check if non-focus window enable uifirst
269     static bool IsNonFocusWindowCache(RSSurfaceRenderNode& node, bool animation);
270 
271     // update node's uifirst state
272     void UifirstStateChange(RSSurfaceRenderNode& node, MultiThreadCacheType currentFrameCacheType);
273     NodeId LeashWindowContainMainWindowAndStarting(RSSurfaceRenderNode& node);
274     void NotifyUIStartingWindow(NodeId id, bool wait);
275     bool HasStartingWindow(RSSurfaceRenderNode& node);
276 
277     void UpdateChildrenDirtyRect(RSSurfaceRenderNode& node);
278     bool EventsCanSkipFirstWait(std::vector<EventInfo>& events);
279     bool IsCardSkipFirstWaitScene(std::string& scene, int32_t appPid);
280     void EventDisableLeashWindowCache(NodeId id, EventInfo& info);
281     void ConvertPendingNodeToDrawable();
282     void CheckCurrentFrameHasCardNodeReCreate(const RSSurfaceRenderNode& node);
283     void ResetCurrentFrameDeletedCardNodes();
284     bool IsPreFirstLevelNodeDoingAndTryClear(std::shared_ptr<RSRenderNode> node);
285     SkipSyncState CollectSkipSyncNodeWithDrawableState(const std::shared_ptr<RSRenderNode> &node);
286     CacheProcessStatus& GetUifirstCachedState(NodeId id);
287     bool IsVMSurfaceName(std::string surfaceName);
288 
289     bool IsToSubByAppAnimation() const;
290     bool QuerySubAssignable(RSSurfaceRenderNode& node, bool isRotation);
291     bool GetSubNodeIsTransparent(RSSurfaceRenderNode& node, std::string& dfxMsg);
292     bool CheckHasTransAndFilter(RSSurfaceRenderNode& node);
293     bool HasBgNodeBelowRootNode(RSSurfaceRenderNode& appNode) const;
294 
295     // stating
296     void ProcessFirstFrameCache(RSSurfaceRenderNode& node, MultiThreadCacheType cacheType);
297 
298     bool IsFocusedNode(const RSSurfaceRenderNode& node) const;
299     void IncreaseUifirstWindowCount(const RSSurfaceRenderNode& node);
300     void DecreaseUifirstWindowCount(const RSSurfaceRenderNode& node);
301     bool IsExceededWindowsThreshold(const RSSurfaceRenderNode& node) const;
302 
303     bool rotationChanged_ = false;
304     bool isUiFirstOn_ = false;
305     bool isUiFirstSupportFlag_ = false;
306     bool purgeEnable_ = false;
307     bool isCardUiFirstOn_ = false;
308     UiFirstCcmType uifirstType_ = UiFirstCcmType::SINGLE;
309     bool isFreeMultiWindowEnabled_ = false;
310     std::atomic<bool> currentFrameCanSkipFirstWait_ = false;
311     // for recents scene
312     std::atomic<bool> isRecentTaskScene_ = false;
313     std::atomic<bool> isMissionCenterScene_ = false;
314     std::atomic<bool> isSplitScreenScene_ = false;
315     std::atomic<bool> isSnapshotRotationScene_ = false;
316     std::atomic<bool> isCurrentFrameHasCardNodeReCreate_ = false;
317     static constexpr int CLEAR_RES_THRESHOLD = 3; // 3 frames  to clear resource
318     static constexpr int BEHIND_WINDOW_TIME_THRESHOLD = 3;
319     // Minimum frame drop time in behind window condition
320     static constexpr int BEHIND_WINDOW_RELEASE_TIME = 33;
321     // the max Delivery time in behind window condition
322     static constexpr int PURGE_BEHIND_WINDOW_TIME = BEHIND_WINDOW_RELEASE_TIME - BEHIND_WINDOW_TIME_THRESHOLD;
323     int32_t scbPid_ = 0;
324     std::atomic<int> noUifirstNodeFrameCount_ = 0;
325     NodeId entryViewNodeId_ = INVALID_NODEID; // desktop surfaceNode ID
326     NodeId negativeScreenNodeId_ = INVALID_NODEID; // negativeScreen surfaceNode ID
327     RSMainThread* mainThread_ = nullptr;
328     // only use in mainThread & RT onsync
329     std::vector<NodeId> pendingForceUpdateNode_;
330     std::vector<std::shared_ptr<RSRenderNode>> markForceUpdateByUifirst_;
331 
332     std::map<NodeId, CacheProcessStatus> uifirstCacheState_;
333 
334     // priority
335     bool isFocusNodeFound_ = false;
336     pid_t focusNodeThreadIndex_ = UINT32_MAX;
337 
338     // only use in RT
339     std::unordered_map<NodeId, std::shared_ptr<DrawableV2::RSRenderNodeDrawableAdapter>> subthreadProcessingNode_;
340     std::set<NodeId> processingNodeSkipSync_;
341     std::set<NodeId> processingNodePartialSync_;
342     std::set<NodeId> processingCardNodeSkipSync_;
343     // (instanceId, vector<needsync_node>)
344     std::unordered_map<NodeId, std::vector<std::shared_ptr<RSRenderNode>>> pendingSyncForSkipBefore_;
345 
346     // use in RT & subThread
347     std::mutex childernDrawableMutex_;
348     std::vector<NodeId> subthreadProcessDoneNode_;
349     std::mutex skippedNodeMutex_;
350     std::unordered_set<NodeId> subthreadProcessSkippedNode_;
351 
352     // pending post node: collect in main, use&clear in RT
353     std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>> pendingPostNodes_;
354     std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>> pendingPostCardNodes_;
355     std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>> pendingResetNodes_;
356     // record the release time of each pendingnode to control the release frequency
357     std::unordered_map<NodeId, NodeDataBehindWindow> pendingNodeBehindWindow_;
358     std::list<NodeId> sortedSubThreadNodeIds_;
359     std::vector<std::shared_ptr<RSSurfaceRenderNode>> pendingResetWindowCachedNodes_;
360 
361     std::set<NodeId> collectedCardNodes_;
362     bool hasForceUpdateNode_ = false;
363     // event list
364     std::mutex globalFrameEventMutex_;
365     std::vector<EventInfo> globalFrameEvent_; // <time, data>
366     std::vector<EventInfo> currentFrameEvent_;
367     // scene in scb
368     const std::vector<std::string> cardCanSkipFirstWaitScene_ = {
369         { "INTO_HOME_ANI" }, // unlock to desktop
370         { "FINGERPRINT_UNLOCK_ANI" }, // finger unlock to desktop
371         { "SCREEN_OFF_FINGERPRINT_UNLOCK_ANI" }, // aod finger unlock
372         { "PASSWORD_UNLOCK_ANI" }, // password unlock to desktop
373         { "FACIAL_FLING_UNLOCK_ANI" }, // facial unlock to desktop
374         { "FACIAL_UNLOCK_ANI" }, // facial unlock to desktop
375         { "APP_SWIPER_SCROLL" }, // desktop swipe
376         { "APP_SWIPER_FLING" }, // desktop swipe
377         { "LAUNCHER_SCROLL" }, // desktop swipe
378         { "SCROLL_2_AA" }, // desktop to negativeScreen
379     };
380     const std::vector<std::string> toSubByAppAnimation_ = {
381         { "WINDOW_TITLE_BAR_MINIMIZED" },
382         { "LAUNCHER_APP_LAUNCH_FROM_DOCK" },
383     };
384 
385     const std::vector<std::string> vmAppNameSet_ = {
386         { "ohvm" },
387         { "win_emulator" },
388         { "hongyunvd" },
389         { "ecoengine" },
390     };
391     std::vector<NodeId> capturedNodes_;
392     std::vector<NodeId> currentFrameDeletedCardNodes_;
393 
394     // maximum uifirst window count
395     int uifirstWindowsNumThreshold_ = 0;
396     // current uifirst window count
397     int curUifirstWindowNums_ = 0;
398     // uifirst mem opt.
399     std::set<NodeId> markedClearCacheNodes_;
400 };
401 
402 // If a subnode is delivered directly
403 // record the firstLevelNodeId in the delivered subnode as the real one.
404 class RSB_EXPORT RSUiFirstProcessStateCheckerHelper {
405 public:
RSUiFirstProcessStateCheckerHelper(NodeId curFirsLevelNodeId,NodeId curUifirstRootNodeId,NodeId curNodeId)406     RSUiFirstProcessStateCheckerHelper(NodeId curFirsLevelNodeId, NodeId curUifirstRootNodeId, NodeId curNodeId)
407     {
408         isCurUifirstRootNodeId_ = curNodeId == curUifirstRootNodeId;
409         isCurFirsLevelNodeId_ = curNodeId == curFirsLevelNodeId;
410         if (isCurUifirstRootNodeId_) {
411             curUifirstRootNodeId_ = curUifirstRootNodeId;
412         }
413         if (isCurFirsLevelNodeId_) {
414             curFirstLevelNodeId_ = curFirsLevelNodeId;
415         }
416     }
417 
RSUiFirstProcessStateCheckerHelper(NodeId curFirsLevelNodeId,NodeId curUifirstRootNodeId)418     RSUiFirstProcessStateCheckerHelper(NodeId curFirsLevelNodeId, NodeId curUifirstRootNodeId)
419     {
420         isCurUifirstRootNodeId_ = true;
421         isCurFirsLevelNodeId_ = true;
422         curUifirstRootNodeId_ = curUifirstRootNodeId;
423         curFirstLevelNodeId_ = curFirsLevelNodeId;
424     }
425 
~RSUiFirstProcessStateCheckerHelper()426     ~RSUiFirstProcessStateCheckerHelper()
427     {
428         if (isCurUifirstRootNodeId_) {
429             curUifirstRootNodeId_ = INVALID_NODEID;
430         }
431         if (isCurFirsLevelNodeId_) {
432             curFirstLevelNodeId_ = INVALID_NODEID;
433         }
434     }
435     // return false when timeout
NotifyAll(std::function<void ()> condChange)436     static inline void NotifyAll(std::function<void()> condChange)
437     {
438         if (LIKELY(condChange)) {
439             std::unique_lock<std::mutex> lock(notifyMutex_);
440             condChange();
441         }
442         notifyCv_.notify_all();
443     }
444     static bool CheckMatchAndWaitNotify(const RSRenderParams& params, bool checkMatch = true);
445 private:
446     static bool IsCurFirstLevelMatch(const RSRenderParams& params);
447     static bool CheckAndWaitPreFirstLevelDrawableNotify(const RSRenderParams& params);
448 
449     static inline std::mutex notifyMutex_;
450     static inline std::condition_variable notifyCv_;
451 
452     static inline thread_local NodeId curUifirstRootNodeId_ = INVALID_NODEID;
453     static inline thread_local NodeId curFirstLevelNodeId_ = INVALID_NODEID;
454 
455     bool isCurUifirstRootNodeId_ = false;
456     bool isCurFirsLevelNodeId_ = false;
457 };
458 }
459 #endif // RS_UIFIRST_MANAGER_H
460