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 #include "core/pipeline_ng/ui_task_scheduler.h" 17 18 #include "base/log/frame_report.h" 19 #include "base/memory/referenced.h" 20 #include "base/thread/background_task_executor.h" 21 #include "base/thread/cancelable_callback.h" 22 #include "base/utils/utils.h" 23 #include "core/common/thread_checker.h" 24 #include "core/components_ng/base/frame_node.h" 25 26 namespace OHOS::Ace::NG { 27 28 UITaskScheduler::~UITaskScheduler() = default; 29 AddDirtyLayoutNode(const RefPtr<FrameNode> & dirty)30void UITaskScheduler::AddDirtyLayoutNode(const RefPtr<FrameNode>& dirty) 31 { 32 CHECK_RUN_ON(UI); 33 CHECK_NULL_VOID(dirty); 34 dirtyLayoutNodes_[dirty->GetPageId()].emplace(dirty); 35 } 36 AddDirtyRenderNode(const RefPtr<FrameNode> & dirty)37void UITaskScheduler::AddDirtyRenderNode(const RefPtr<FrameNode>& dirty) 38 { 39 CHECK_RUN_ON(UI); 40 CHECK_NULL_VOID(dirty); 41 auto result = dirtyRenderNodes_[dirty->GetPageId()].emplace(dirty); 42 if (!result.second) { 43 LOGW("fail to emplace %{public}s render node", dirty->GetTag().c_str()); 44 } 45 } 46 FlushLayoutTask(bool forceUseMainThread)47void UITaskScheduler::FlushLayoutTask(bool forceUseMainThread) 48 { 49 CHECK_RUN_ON(UI); 50 ACE_FUNCTION_TRACE(); 51 if (FrameReport::GetInstance().GetEnable()) { 52 FrameReport::GetInstance().BeginFlushRender(); 53 } 54 auto dirtyLayoutNodes = std::move(dirtyLayoutNodes_); 55 // Priority task creation 56 for (auto&& pageNodes : dirtyLayoutNodes) { 57 for (auto&& node : pageNodes.second) { 58 if (!node) { 59 continue; 60 } 61 if (node->IsInDestroying()) { 62 continue; 63 } 64 auto task = node->CreateLayoutTask(forceUseMainThread); 65 if (task) { 66 if (forceUseMainThread || (task->GetTaskThreadType() == MAIN_TASK)) { 67 (*task)(); 68 } else { 69 LOGW("need to use multithread feature"); 70 } 71 } 72 } 73 } 74 } 75 FlushRenderTask(bool forceUseMainThread)76void UITaskScheduler::FlushRenderTask(bool forceUseMainThread) 77 { 78 CHECK_RUN_ON(UI); 79 ACE_FUNCTION_TRACE(); 80 if (FrameReport::GetInstance().GetEnable()) { 81 FrameReport::GetInstance().BeginFlushRender(); 82 } 83 auto dirtyRenderNodes = std::move(dirtyRenderNodes_); 84 // Priority task creation 85 for (auto&& pageNodes : dirtyRenderNodes) { 86 for (auto&& node : pageNodes.second) { 87 if (!node) { 88 continue; 89 } 90 if (node->IsInDestroying()) { 91 continue; 92 } 93 auto task = node->CreateRenderTask(forceUseMainThread); 94 if (task) { 95 if (forceUseMainThread || (task->GetTaskThreadType() == MAIN_TASK)) { 96 (*task)(); 97 } else { 98 LOGW("need to use multithread feature"); 99 } 100 } 101 } 102 } 103 } 104 FlushTask()105void UITaskScheduler::FlushTask() 106 { 107 CHECK_RUN_ON(UI); 108 ACE_SCOPED_TRACE("UITaskScheduler::FlushTask"); 109 FlushLayoutTask(); 110 if (!afterLayoutTasks_.empty()) { 111 FlushAfterLayoutTask(); 112 } 113 FlushRenderTask(); 114 } 115 AddPredictTask(PredictTask && task)116void UITaskScheduler::AddPredictTask(PredictTask&& task) 117 { 118 predictTask_.push_back(std::move(task)); 119 } 120 FlushPredictTask(int64_t deadline)121void UITaskScheduler::FlushPredictTask(int64_t deadline) 122 { 123 decltype(predictTask_) tasks(std::move(predictTask_)); 124 for (const auto& task : tasks) { 125 if (task) { 126 task(deadline); 127 } 128 } 129 } 130 CleanUp()131void UITaskScheduler::CleanUp() 132 { 133 dirtyLayoutNodes_.clear(); 134 dirtyRenderNodes_.clear(); 135 } 136 isEmpty()137bool UITaskScheduler::isEmpty() 138 { 139 if (dirtyLayoutNodes_.empty() && dirtyRenderNodes_.empty()) { 140 return true; 141 } 142 return false; 143 } 144 AddAfterLayoutTask(std::function<void ()> && task)145void UITaskScheduler::AddAfterLayoutTask(std::function<void()>&& task) 146 { 147 afterLayoutTasks_.emplace_back(std::move(task)); 148 } 149 FlushAfterLayoutTask()150void UITaskScheduler::FlushAfterLayoutTask() 151 { 152 decltype(afterLayoutTasks_) tasks(std::move(afterLayoutTasks_)); 153 for (const auto& task : tasks) { 154 if (task) { 155 task(); 156 } 157 } 158 } 159 160 } // namespace OHOS::Ace::NG 161