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