• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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