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
GetWorkToRunByPriority()163 shared_ptr<WorkStatus> WorkQueue::GetWorkToRunByPriority()
164 {
165 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
166 workList_.sort(WorkComp());
167 auto work = workList_.begin();
168 shared_ptr<WorkStatus> workStatus = nullptr;
169 while (work != workList_.end()) {
170 if ((*work)->GetStatus() == WorkStatus::CONDITION_READY) {
171 workStatus = *work;
172 workStatus->priority_++;
173 break;
174 }
175 work++;
176 }
177 return workStatus;
178 }
179
CancelWork(shared_ptr<WorkStatus> workStatus)180 bool WorkQueue::CancelWork(shared_ptr<WorkStatus> workStatus)
181 {
182 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
183 workList_.remove(workStatus);
184 return true;
185 }
186
GetWorkList()187 list<shared_ptr<WorkStatus>> WorkQueue::GetWorkList()
188 {
189 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
190 return workList_;
191 }
192
RemoveUnReady()193 void WorkQueue::RemoveUnReady()
194 {
195 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
196 workList_.remove_if([](shared_ptr<WorkStatus> value) {
197 return (value->GetStatus() != WorkStatus::Status::CONDITION_READY);
198 });
199 }
200
GetRunningCount()201 int32_t WorkQueue::GetRunningCount()
202 {
203 int32_t count = 0;
204 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
205 for (shared_ptr<WorkStatus> work : workList_) {
206 if (work->IsRunning()) {
207 count++;
208 }
209 }
210 return count;
211 }
212
GetRunningWorks()213 std::list<std::shared_ptr<WorkInfo>> WorkQueue::GetRunningWorks()
214 {
215 std::list<std::shared_ptr<WorkInfo>> workInfo;
216 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
217 for (shared_ptr<WorkStatus> work : workList_) {
218 if (work->IsRunning()) {
219 auto info = std::make_shared<WorkInfo>();
220 info->SetElement(work->bundleName_, work->abilityName_);
221 info->RefreshUid(work->uid_);
222 workInfo.emplace_back(info);
223 }
224 }
225 return workInfo;
226 }
227
GetDeepIdleWorks()228 std::list<std::shared_ptr<WorkStatus>> WorkQueue::GetDeepIdleWorks()
229 {
230 std::list<std::shared_ptr<WorkStatus>> works;
231 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
232 for (shared_ptr<WorkStatus> work : workList_) {
233 if (work->IsRunning() && work->workInfo_->GetDeepIdle() == WorkCondition::DeepIdle::DEEP_IDLE_IN) {
234 works.emplace_back(work);
235 }
236 }
237 return works;
238 }
239
GetWorkIdStr(string& result)240 void WorkQueue::GetWorkIdStr(string& result)
241 {
242 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
243 for (auto it : workList_) {
244 result.append(it->workId_ + ", ");
245 }
246 }
247
Dump(string& result)248 void WorkQueue::Dump(string& result)
249 {
250 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
251 for (auto it : workList_) {
252 it->Dump(result);
253 }
254 }
255
ClearAll()256 void WorkQueue::ClearAll()
257 {
258 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
259 workList_.clear();
260 }
261
operator ()(const shared_ptr<WorkStatus> w1, const shared_ptr<WorkStatus> w2)262 bool WorkComp::operator () (const shared_ptr<WorkStatus> w1, const shared_ptr<WorkStatus> w2)
263 {
264 return w1->priority_ < w2->priority_;
265 }
266
SetMinIntervalByDump(int64_t interval)267 void WorkQueue::SetMinIntervalByDump(int64_t interval)
268 {
269 std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_);
270 for (auto it : workList_) {
271 it->SetMinIntervalByDump(interval);
272 }
273 }
274 } // namespace WorkScheduler
275 } // namespace OHOS