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