1 /* 2 * Copyright (c) 2022 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 FOUNDATION_ACE_FRAMEWORKS_CORE_COMMON_PIPELINE_NG_UI_TASK_SCHEDULER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMMON_PIPELINE_NG_UI_TASK_SCHEDULER_H 18 19 #include <cstdint> 20 #include <functional> 21 #include <list> 22 #include <map> 23 #include <queue> 24 #include <set> 25 26 #include "base/log/frame_info.h" 27 #include "base/memory/referenced.h" 28 #include "base/utils/macros.h" 29 #include "core/common/ace_application_info.h" 30 31 namespace OHOS::Ace::NG { 32 33 class CustomNode; 34 class FrameNode; 35 36 using TaskThread = uint32_t; 37 constexpr TaskThread PLATFORM_TASK = 0; 38 constexpr TaskThread MAIN_TASK = 1; 39 constexpr TaskThread BACKGROUND_TASK = 1 << 1; 40 constexpr TaskThread UNDEFINED_TASK = 1 << 2; 41 42 using IgnoreLayoutSafeAreaBundle = std::pair<std::vector<RefPtr<FrameNode>>, RefPtr<FrameNode>>; 43 44 class UITask { 45 public: UITask(std::function<void ()> && task)46 explicit UITask(std::function<void()>&& task) : task_(std::move(task)) {} 47 UITask(std::function<void ()> && task,TaskThread taskThread)48 UITask(std::function<void()>&& task, TaskThread taskThread) : task_(std::move(task)), taskThread_(taskThread) {} 49 50 ~UITask() = default; 51 SetTaskThreadType(TaskThread taskThread)52 void SetTaskThreadType(TaskThread taskThread) 53 { 54 taskThread_ = taskThread; 55 } 56 GetTaskThreadType()57 TaskThread GetTaskThreadType() const 58 { 59 return taskThread_; 60 } 61 operator()62 void operator()() const 63 { 64 if (task_) { 65 task_(); 66 } 67 } 68 69 private: 70 std::function<void()> task_; 71 TaskThread taskThread_ = MAIN_TASK; 72 }; 73 74 class ACE_EXPORT UITaskScheduler final { 75 public: 76 using PredictTask = std::function<void(int64_t, bool)>; 77 UITaskScheduler(); 78 ~UITaskScheduler(); 79 80 // Called on Main Thread. 81 void AddDirtyLayoutNode(const RefPtr<FrameNode>& dirty); 82 void AddIgnoreLayoutSafeAreaBundle(IgnoreLayoutSafeAreaBundle&& bundle); 83 void AddLayoutNode(const RefPtr<FrameNode>& layoutNode); 84 void AddDirtyRenderNode(const RefPtr<FrameNode>& dirty); 85 void AddPredictTask(PredictTask&& task); 86 void AddAfterLayoutTask(std::function<void()>&& task, bool isFlushInImplicitAnimationTask = false); 87 void AddAfterRenderTask(std::function<void()>&& task); 88 void AddPersistAfterLayoutTask(std::function<void()>&& task); 89 void AddAfterModifierTask(std::function<void()>&& task); 90 91 void FlushLayoutTask(bool forceUseMainThread = false); 92 void FlushRenderTask(bool forceUseMainThread = false); 93 void FlushTask(); 94 void FlushTaskWithCheck(bool triggeredByImplicitAnimation = false); 95 void FlushPredictTask(int64_t deadline, bool canUseLongPredictTask = false); 96 void FlushAfterLayoutTask(); 97 void FlushAfterLayoutCallbackInImplicitAnimationTask(); 98 void FlushAfterRenderTask(); 99 void FlushPersistAfterLayoutTask(); 100 void FlushAfterModifierTask(); 101 void ExpandSafeArea(); 102 103 void FlushDelayJsActive(); 104 UpdateCurrentPageId(uint32_t id)105 void UpdateCurrentPageId(uint32_t id) 106 { 107 currentPageId_ = id; 108 } 109 110 void CleanUp(); 111 112 bool isEmpty(); 113 114 bool IsPredictTaskEmpty(); 115 StartRecordFrameInfo(FrameInfo * info)116 void StartRecordFrameInfo(FrameInfo* info) 117 { 118 frameInfo_ = info; 119 } 120 FinishRecordFrameInfo()121 void FinishRecordFrameInfo() 122 { 123 frameInfo_ = nullptr; 124 } 125 GetFrameId()126 static uint64_t GetFrameId() 127 { 128 return frameId_; 129 } 130 IsLayouting()131 bool IsLayouting() const 132 { 133 return isLayouting_; 134 } 135 136 void AddSingleNodeToFlush(const RefPtr<FrameNode>& dirtyNode); 137 138 bool RequestFrameOnLayoutCountExceeds(); 139 140 void SetJSViewActive(bool active, WeakPtr<CustomNode> custom); 141 IsDirtyLayoutNodesEmpty()142 bool IsDirtyLayoutNodesEmpty() 143 { 144 return dirtyLayoutNodes_.empty(); 145 } 146 AddSyncGeometryNodeTask(std::function<void ()> && task)147 void AddSyncGeometryNodeTask(std::function<void()>&& task) 148 { 149 syncGeometryNodeTasks_.emplace_back(task); 150 } 151 152 void AddSafeAreaPaddingProcessTask(FrameNode* node); 153 void RemoveSafeAreaPaddingProcessTask(FrameNode* node); 154 void FlushSafeAreaPaddingProcess(); 155 SetIsLayouting(bool layouting)156 void SetIsLayouting(bool layouting) 157 { 158 isLayouting_ = layouting; 159 } 160 161 void FlushSyncGeometryNodeTasks(); 162 void FlushPostponedLayoutTask(bool forceUseMainThread); 163 164 private: 165 bool NeedAdditionalLayout(); 166 void FlushAllSingleNodeTasks(); 167 void SetLayoutNodeRect(); 168 169 template<typename T> 170 struct NodeCompare { operatorNodeCompare171 bool operator()(const T& nodeLeft, const T& nodeRight) const 172 { 173 if (!nodeLeft || !nodeRight) { 174 return false; 175 } 176 if (nodeLeft->GetLayoutPriority() != nodeRight->GetLayoutPriority()) { 177 return nodeLeft->GetLayoutPriority() > nodeRight->GetLayoutPriority(); 178 } 179 if (nodeLeft->GetPageId() != nodeRight->GetPageId()) { 180 return nodeLeft->GetPageId() < nodeRight->GetPageId(); 181 } 182 if (nodeLeft->GetDepth() != nodeRight->GetDepth()) { 183 return nodeLeft->GetDepth() < nodeRight->GetDepth(); 184 } 185 return nodeLeft < nodeRight; 186 } 187 }; 188 189 using PageDirtySet = std::set<RefPtr<FrameNode>, NodeCompare<RefPtr<FrameNode>>>; 190 using LayoutNodesSet = std::set<RefPtr<FrameNode>, NodeCompare<RefPtr<FrameNode>>>; 191 using RootDirtyMap = std::map<uint32_t, PageDirtySet>; 192 193 std::vector<IgnoreLayoutSafeAreaBundle> ignoreLayoutSafeAreaBundles_; 194 std::list<RefPtr<FrameNode>> dirtyLayoutNodes_; 195 std::list<RefPtr<FrameNode>> layoutNodes_; 196 RootDirtyMap dirtyRenderNodes_; 197 std::list<PredictTask> predictTask_; 198 std::list<std::function<void()>> afterLayoutTasks_; 199 std::list<std::function<void()>> afterLayoutCallbacksInImplicitAnimationTask_; 200 std::list<std::function<void()>> afterRenderTasks_; 201 std::list<std::function<void()>> persistAfterLayoutTasks_; 202 std::list<std::function<void()>> syncGeometryNodeTasks_; 203 std::list<std::function<void()>> afterModifierTasks_; 204 std::set<FrameNode*, NodeCompare<FrameNode*>> safeAreaPaddingProcessTasks_; 205 std::set<RefPtr<FrameNode>> singleDirtyNodesToFlush_; 206 std::queue<bool> layoutWithImplicitAnimation_; 207 208 uint32_t currentPageId_ = 0; 209 bool is64BitSystem_ = false; 210 bool isLayouting_ = false; 211 int32_t multiLayoutCount_ = 0; 212 213 FrameInfo* frameInfo_ = nullptr; 214 215 static uint64_t frameId_; 216 217 ACE_DISALLOW_COPY_AND_MOVE(UITaskScheduler); 218 }; 219 220 } // namespace OHOS::Ace::NG 221 222 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMMON_PIPELINE_NG_UI_TASK_SCHEDULER_H 223