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