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 #include <set>
16 #include "work_queue.h"
17
18 #include "work_condition.h"
19 #include "work_sched_hilog.h"
20 #include "work_sched_errors.h"
21 #include "work_scheduler_service.h"
22
23 using namespace std;
24
25 namespace OHOS {
26 namespace WorkScheduler {
OnConditionChanged(WorkCondition::Type type,shared_ptr<DetectorValue> conditionVal)27 vector<shared_ptr<WorkStatus>> WorkQueue::OnConditionChanged(WorkCondition::Type type,
28 shared_ptr<DetectorValue> conditionVal)
29 {
30 shared_ptr<Condition> value = ParseCondition(type, conditionVal);
31 vector<shared_ptr<WorkStatus>> result;
32 std::set<int32_t> uidList;
33 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
34 workList_.sort(WorkComp());
35 for (auto it : workList_) {
36 if (it->OnConditionChanged(type, value) == E_GROUP_CHANGE_NOT_MATCH_HAP) {
37 continue;
38 }
39 if (uidList.count(it->uid_) > 0 && it->GetMinInterval() != 0 &&
40 !DelayedSingleton<WorkSchedulerService>::GetInstance()->CheckEffiResApplyInfo(it->uid_)) {
41 WS_HILOGI("One uid can start only one work, uid:%{public}d, bundleName:%{public}s",
42 it->uid_, it->bundleName_.c_str());
43 continue;
44 }
45 bool isReady = it->workInfo_->IsSA() ? it->IsSAReady() : it->IsReady();
46 if (isReady) {
47 result.emplace_back(it);
48 uidList.insert(it->uid_);
49 } else {
50 if (it->IsReadyStatus()) {
51 it->MarkStatus(WorkStatus::Status::WAIT_CONDITION);
52 }
53 }
54 if (it->needRetrigger_) {
55 result.emplace_back(it);
56 }
57 }
58 return result;
59 }
60
ParseCondition(WorkCondition::Type type,shared_ptr<DetectorValue> conditionVal)61 shared_ptr<Condition> WorkQueue::ParseCondition(WorkCondition::Type type,
62 shared_ptr<DetectorValue> conditionVal)
63 {
64 shared_ptr<Condition> value = make_shared<Condition>();
65 switch (type) {
66 case WorkCondition::Type::NETWORK:
67 // fall-through
68 case WorkCondition::Type::BATTERY_STATUS:
69 // fall-through
70 case WorkCondition::Type::STORAGE: {
71 value->enumVal = conditionVal->intVal;
72 break;
73 }
74 case WorkCondition::Type::CHARGER: {
75 value->enumVal = conditionVal->intVal;
76 value->boolVal = conditionVal->boolVal;
77 break;
78 }
79 case WorkCondition::Type::BATTERY_LEVEL: {
80 value->intVal = conditionVal->intVal;
81 break;
82 }
83 case WorkCondition::Type::TIMER: {
84 break;
85 }
86 case WorkCondition::Type::GROUP: {
87 value->enumVal = conditionVal->intVal;
88 value->intVal = conditionVal->timeVal;
89 value->boolVal = conditionVal->boolVal;
90 value->strVal = conditionVal->strVal;
91 break;
92 }
93 case WorkCondition::Type::DEEP_IDLE:
94 case WorkCondition::Type::STANDBY: {
95 value->boolVal = conditionVal->boolVal;
96 break;
97 }
98 default: {}
99 }
100 return value;
101 }
102
Push(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)103 void WorkQueue::Push(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)
104 {
105 for (auto it : *workStatusVector) {
106 Push(it);
107 }
108 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
109 workList_.sort(WorkComp());
110 }
111
Push(shared_ptr<WorkStatus> workStatus)112 void WorkQueue::Push(shared_ptr<WorkStatus> workStatus)
113 {
114 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
115 if (this->Contains(make_shared<string>(workStatus->workId_))) {
116 for (auto it : workList_) {
117 if (it->workId_.compare(workStatus->workId_) == 0) {
118 return;
119 }
120 }
121 return;
122 }
123 workList_.push_back(workStatus);
124 }
125
Remove(shared_ptr<WorkStatus> workStatus)126 bool WorkQueue::Remove(shared_ptr<WorkStatus> workStatus)
127 {
128 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
129 auto iter = std::find(workList_.cbegin(), workList_.cend(), workStatus);
130 if (iter != workList_.end()) {
131 workList_.remove(*iter);
132 }
133 return true;
134 }
135
GetSize()136 uint32_t WorkQueue::GetSize()
137 {
138 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
139 return workList_.size();
140 }
141
Contains(std::shared_ptr<std::string> workId)142 bool WorkQueue::Contains(std::shared_ptr<std::string> workId)
143 {
144 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
145 auto iter = std::find_if(workList_.cbegin(), workList_.cend(), [&workId]
146 (const shared_ptr<WorkStatus> &workStatus) { return workId->compare(workStatus->workId_) == 0; });
147 if (iter != workList_.end()) {
148 return true;
149 }
150 return false;
151 }
152
Find(string workId)153 shared_ptr<WorkStatus> WorkQueue::Find(string workId)
154 {
155 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
156 auto iter = std::find_if(workList_.cbegin(), workList_.cend(),
157 [&workId](const shared_ptr<WorkStatus> &workStatus) { return workStatus->workId_ == workId; });
158 if (iter != workList_.end()) {
159 return *iter;
160 }
161 return nullptr;
162 }
163
FindSA(int32_t saId)164 shared_ptr<WorkStatus> WorkQueue::FindSA(int32_t saId)
165 {
166 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
167 auto iter = std::find_if(workList_.cbegin(), workList_.cend(),
168 [&saId](const shared_ptr<WorkStatus> &workStatus) {
169 return workStatus->workInfo_->IsSA() && workStatus->workInfo_->GetSaId() == saId;
170 });
171 if (iter != workList_.end()) {
172 return *iter;
173 }
174 return nullptr;
175 }
176
Find(const int32_t userId,const std::string & bundleName)177 bool WorkQueue::Find(const int32_t userId, const std::string &bundleName)
178 {
179 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
180 auto iter = std::find_if(workList_.cbegin(), workList_.cend(),
181 [userId, &bundleName](const shared_ptr<WorkStatus> &workStatus) {
182 return workStatus->userId_ == userId && workStatus->bundleName_ == bundleName;
183 });
184 return iter != workList_.end();
185 }
186
GetWorkToRunByPriority()187 shared_ptr<WorkStatus> WorkQueue::GetWorkToRunByPriority()
188 {
189 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
190 workList_.sort(WorkComp());
191 auto work = workList_.begin();
192 shared_ptr<WorkStatus> workStatus = nullptr;
193 while (work != workList_.end()) {
194 if ((*work)->GetStatus() == WorkStatus::CONDITION_READY) {
195 workStatus = *work;
196 workStatus->priority_++;
197 break;
198 }
199 work++;
200 }
201 return workStatus;
202 }
203
CancelWork(shared_ptr<WorkStatus> workStatus)204 bool WorkQueue::CancelWork(shared_ptr<WorkStatus> workStatus)
205 {
206 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
207 workList_.remove(workStatus);
208 return true;
209 }
210
GetWorkList()211 list<shared_ptr<WorkStatus>> WorkQueue::GetWorkList()
212 {
213 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
214 return workList_;
215 }
216
RemoveUnReady()217 void WorkQueue::RemoveUnReady()
218 {
219 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
220 workList_.remove_if([](shared_ptr<WorkStatus> value) {
221 return (value->GetStatus() != WorkStatus::Status::CONDITION_READY);
222 });
223 }
224
GetRunningCount()225 int32_t WorkQueue::GetRunningCount()
226 {
227 int32_t count = 0;
228 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
229 for (shared_ptr<WorkStatus> work : workList_) {
230 if (work->IsRunning()) {
231 count++;
232 }
233 }
234 return count;
235 }
236
GetRunningWorks()237 std::vector<WorkInfo> WorkQueue::GetRunningWorks()
238 {
239 std::vector<WorkInfo> workInfo;
240 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
241 for (shared_ptr<WorkStatus> work : workList_) {
242 if (work->IsRunning()) {
243 auto info = WorkInfo();
244 info.SetElement(work->bundleName_, work->abilityName_);
245 info.RefreshUid(work->uid_);
246 workInfo.emplace_back(info);
247 }
248 }
249 return workInfo;
250 }
251
GetDeepIdleWorks()252 std::list<std::shared_ptr<WorkStatus>> WorkQueue::GetDeepIdleWorks()
253 {
254 std::list<std::shared_ptr<WorkStatus>> works;
255 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
256 for (shared_ptr<WorkStatus> work : workList_) {
257 if (work->IsRunning() && work->workInfo_->GetDeepIdle() == WorkCondition::DeepIdle::DEEP_IDLE_IN &&
258 !work->workInfo_->IsSA()) {
259 works.emplace_back(work);
260 }
261 }
262 return works;
263 }
264
GetWorkIdStr(string & result)265 void WorkQueue::GetWorkIdStr(string& result)
266 {
267 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
268 for (auto it : workList_) {
269 result.append(it->workId_ + ", ");
270 }
271 }
272
Dump(string & result)273 void WorkQueue::Dump(string& result)
274 {
275 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
276 for (auto it : workList_) {
277 it->Dump(result);
278 }
279 }
280
ClearAll()281 void WorkQueue::ClearAll()
282 {
283 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
284 workList_.clear();
285 }
286
operator ()(const shared_ptr<WorkStatus> w1,const shared_ptr<WorkStatus> w2)287 bool WorkComp::operator () (const shared_ptr<WorkStatus> w1, const shared_ptr<WorkStatus> w2)
288 {
289 return w1->priority_ < w2->priority_;
290 }
291
SetMinIntervalByDump(int64_t interval)292 void WorkQueue::SetMinIntervalByDump(int64_t interval)
293 {
294 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
295 for (auto it : workList_) {
296 it->SetMinIntervalByDump(interval);
297 }
298 }
299 } // namespace WorkScheduler
300 } // namespace OHOS