• 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<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