1 /*
2 * Copyright (C) 2024-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 "task_manager.h"
17
18 #include <string>
19
20 #include "actions/action.h"
21 #include "actions/action_wait.h"
22 #include "global.h"
23 #include "tasks/task.h"
24 #include "tasks/task_inner.h"
25
26 namespace OHOS {
27 namespace MiscServices {
28 // LCOV_EXCL_START
29 static const std::string THREAD_NAME = "OS_imf_task_manager";
30
TaskManager()31 TaskManager::TaskManager()
32 {
33 auto runner = AppExecFwk::EventRunner::Create(THREAD_NAME);
34 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
35 }
36
GetInstance()37 TaskManager &TaskManager::GetInstance()
38 {
39 static TaskManager instance;
40 return instance;
41 }
42
PostTask(task_ptr_t task,uint32_t delayMs)43 uint64_t TaskManager::PostTask(task_ptr_t task, uint32_t delayMs)
44 {
45 if (!task) {
46 IMSA_HILOGE("task is NULL!");
47 return 0;
48 }
49
50 auto func = [this, task]() { OnNewTask(task); };
51 eventHandler_->PostTask(func, __FUNCTION__, delayMs);
52 return task->GetSeqId();
53 }
54
ProcessAsync()55 void TaskManager::ProcessAsync()
56 {
57 auto func = [=] {
58 Process();
59 };
60 eventHandler_->PostTask(func, __FUNCTION__);
61 }
62
Complete(uint64_t seqId)63 void TaskManager::Complete(uint64_t seqId)
64 {
65 PostTask(std::make_shared<TaskResume>(seqId));
66 }
67
Pend(action_ptr_t action)68 int32_t TaskManager::Pend(action_ptr_t action)
69 {
70 if (action == nullptr) {
71 IMSA_HILOGE("curTask_ is NULL or not runing, pend failed!");
72 return ErrorCode::ERROR_NULL_POINTER;
73 }
74 if (curTask_ == nullptr || !curTask_->IsRunning()) {
75 IMSA_HILOGE("curTask_ is NULL or not runing, pend failed!");
76 return ErrorCode::ERROR_TASK_MANAGER_PEND_FAILED;
77 }
78 return curTask_->Pend(std::move(action));
79 }
80
Pend(std::function<void ()> func)81 int32_t TaskManager::Pend(std::function<void()> func)
82 {
83 return Pend(std::make_unique<Action>(func));
84 }
85
WaitExec(uint64_t seqId,uint32_t timeoutMs,std::function<void ()> func)86 int32_t TaskManager::WaitExec(uint64_t seqId, uint32_t timeoutMs, std::function<void()> func)
87 {
88 auto wait = std::make_unique<ActionWait>(seqId, timeoutMs);
89 int32_t ret = Pend(std::move(wait));
90 if (ret != ErrorCode::NO_ERROR) {
91 IMSA_HILOGE("Pend ActionWait failed, ret=%{public}d", ret);
92 return ret;
93 }
94
95 auto exec = std::make_unique<Action>(func);
96 ret = Pend(std::move(exec));
97 if (ret != ErrorCode::NO_ERROR) {
98 IMSA_HILOGE("Pend Action failed, ret=%{public}d", ret);
99 return ret;
100 }
101 return ErrorCode::NO_ERROR;
102 }
103
SetInited(bool flag)104 void TaskManager::SetInited(bool flag)
105 {
106 inited_ = flag;
107 }
108
OnNewTask(task_ptr_t task)109 void TaskManager::OnNewTask(task_ptr_t task)
110 {
111 if (task == nullptr) {
112 IMSA_HILOGE("task is NULL!");
113 return;
114 }
115 auto srcType = task->GetSourceType();
116 switch (srcType) {
117 case SOURCE_TYPE_AMS:
118 amsTasks_.push_back(task);
119 break;
120 case SOURCE_TYPE_IMA:
121 imaTasks_.push_back(task);
122 break;
123 case SOURCE_TYPE_IMSA:
124 imsaTasks_.push_back(task);
125 break;
126 case SOURCE_TYPE_INNER:
127 innerTasks_.push_back(task);
128 break;
129 default:
130 IMSA_HILOGE("task type %{public}d unknown!", srcType);
131 return;
132 }
133 Process();
134 }
135
Process()136 void TaskManager::Process()
137 {
138 ProcessNextInnerTask();
139 ProcessNextAmsTask();
140 ProcessNextImaTask();
141 ProcessNextImsaTask();
142 }
143
ProcessNextInnerTask()144 void TaskManager::ProcessNextInnerTask()
145 {
146 while (curTask_) {
147 // curTask_ is not NULL, it must be paused
148 // Loop through innerTasks_, try resume
149 if (innerTasks_.empty()) {
150 IMSA_HILOGD("InnerTasks_ empty, return");
151 return;
152 }
153
154 auto task = innerTasks_.front();
155 innerTasks_.pop_front();
156 auto state = curTask_->OnTask(task);
157 if (state == RUNNING_STATE_COMPLETED) {
158 // current task completed
159 curTask_.reset();
160 innerTasks_.clear();
161 return;
162 }
163 if (state == RUNNING_STATE_PAUSED) {
164 // current task still paused, try next inner task
165 continue;
166 }
167
168 // unreachable
169 IMSA_HILOGE("Unexpected OnTask result %{public}d", state);
170 curTask_.reset();
171 innerTasks_.clear();
172 }
173 }
174
ProcessNextAmsTask()175 void TaskManager::ProcessNextAmsTask()
176 {
177 if (amsTasks_.empty()) {
178 return;
179 }
180
181 // AMS task has higher priority. If curTask_ is valid and not from AMS, drop it
182 if (curTask_) {
183 if (curTask_->GetSourceType() == SOURCE_TYPE_AMS) {
184 return;
185 }
186 curTask_.reset();
187 }
188
189 while (!curTask_) {
190 if (amsTasks_.empty()) {
191 return;
192 }
193 curTask_ = amsTasks_.front();
194 amsTasks_.pop_front();
195 ExecuteCurrentTask();
196 }
197 }
198
ProcessNextImaTask()199 void TaskManager::ProcessNextImaTask()
200 {
201 if (imaTasks_.empty()) {
202 return;
203 }
204
205 if (curTask_) {
206 // curTask_ must be paused here
207 while (!imaTasks_.empty()) {
208 auto task = imaTasks_.front();
209 imaTasks_.pop_front();
210 auto state = curTask_->OnTask(task);
211 if (state == RUNNING_STATE_COMPLETED) {
212 curTask_.reset();
213 break;
214 }
215 }
216 }
217
218 while (!curTask_) {
219 if (imaTasks_.empty()) {
220 return;
221 }
222 curTask_ = imaTasks_.front();
223 imaTasks_.pop_front();
224 ExecuteCurrentTask();
225 }
226 }
227
ProcessNextImsaTask()228 void TaskManager::ProcessNextImsaTask()
229 {
230 if (!inited_) {
231 return;
232 }
233
234 if (curTask_ || imsaTasks_.empty()) {
235 return;
236 }
237
238 while (!curTask_) {
239 if (imsaTasks_.empty()) {
240 return;
241 }
242 curTask_ = imsaTasks_.front();
243 imsaTasks_.pop_front();
244 ExecuteCurrentTask();
245 }
246 }
247
ExecuteCurrentTask()248 void TaskManager::ExecuteCurrentTask()
249 {
250 if (curTask_ == nullptr) {
251 return;
252 }
253 auto state = curTask_->Execute();
254 if (state == RUNNING_STATE_COMPLETED) {
255 IMSA_HILOGD("curTask_ completed");
256 curTask_.reset();
257 ProcessAsync();
258 return;
259 }
260 if (state == RUNNING_STATE_PAUSED) {
261 IMSA_HILOGI("curTask_ paused");
262 return;
263 }
264 IMSA_HILOGE("Unexpected Execute result %{public}u", state);
265 curTask_.reset();
266 }
267
Reset()268 void TaskManager::Reset()
269 {
270 inited_ = false;
271 curTask_ = nullptr;
272 innerTasks_.clear();
273 imaTasks_.clear();
274 imsaTasks_.clear();
275 amsTasks_.clear();
276 }
277 // LCOV_EXCL_STOP
278 } // namespace MiscServices
279 } // namespace OHOS
280