• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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