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