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 "work_queue_manager.h"
16 #include "work_scheduler_service.h"
17 #include "work_sched_hilog.h"
18
19 using namespace std;
20
21 namespace OHOS {
22 namespace WorkScheduler {
23 const uint32_t TIME_CYCLE = 20 * 60 * 1000; // 20min
24 static int32_t g_timeRetrigger = INT32_MAX;
25
WorkQueueManager(const wptr<WorkSchedulerService> & wss)26 WorkQueueManager::WorkQueueManager(const wptr<WorkSchedulerService>& wss) : wss_(wss)
27 {
28 timeCycle_ = TIME_CYCLE;
29 }
30
Init()31 bool WorkQueueManager::Init()
32 {
33 return true;
34 }
35
AddListener(WorkCondition::Type type,shared_ptr<IConditionListener> listener)36 bool WorkQueueManager::AddListener(WorkCondition::Type type, shared_ptr<IConditionListener> listener)
37 {
38 std::lock_guard<std::mutex> lock(mutex_);
39 if (listenerMap_.count(type) > 0) {
40 return false;
41 }
42 listenerMap_.emplace(type, listener);
43 return true;
44 }
45
AddWork(shared_ptr<WorkStatus> workStatus)46 bool WorkQueueManager::AddWork(shared_ptr<WorkStatus> workStatus)
47 {
48 if (!workStatus || !workStatus->workInfo_ || !workStatus->workInfo_->GetConditionMap()) {
49 return false;
50 }
51 WS_HILOGD("workStatus ID: %{public}s", workStatus->workId_.c_str());
52 std::lock_guard<std::mutex> lock(mutex_);
53 auto map = workStatus->workInfo_->GetConditionMap();
54 for (auto it : *map) {
55 if (queueMap_.count(it.first) == 0) {
56 queueMap_.emplace(it.first, make_shared<WorkQueue>());
57 if (listenerMap_.count(it.first) != 0) {
58 listenerMap_.at(it.first)->Start();
59 }
60 }
61 queueMap_.at(it.first)->Push(workStatus);
62 }
63 return true;
64 }
65
RemoveWork(shared_ptr<WorkStatus> workStatus)66 bool WorkQueueManager::RemoveWork(shared_ptr<WorkStatus> workStatus)
67 {
68 std::lock_guard<std::mutex> lock(mutex_);
69 WS_HILOGD("workStatus ID: %{public}s", workStatus->workId_.c_str());
70 auto map = workStatus->workInfo_->GetConditionMap();
71 for (auto it : *map) {
72 if (queueMap_.count(it.first) > 0) {
73 queueMap_.at(it.first)->Remove(workStatus);
74 }
75 if (queueMap_.count(it.first) == 0) {
76 listenerMap_.at(it.first)->Stop();
77 }
78 }
79 return true;
80 }
81
CancelWork(shared_ptr<WorkStatus> workStatus)82 bool WorkQueueManager::CancelWork(shared_ptr<WorkStatus> workStatus)
83 {
84 std::lock_guard<std::mutex> lock(mutex_);
85 WS_HILOGD("workStatus ID: %{public}s", workStatus->workId_.c_str());
86 for (auto it : queueMap_) {
87 it.second->CancelWork(workStatus);
88 if (queueMap_.count(it.first) == 0) {
89 listenerMap_.at(it.first)->Stop();
90 }
91 }
92 return true;
93 }
94
GetReayQueue(WorkCondition::Type conditionType,shared_ptr<DetectorValue> conditionVal)95 vector<shared_ptr<WorkStatus>> WorkQueueManager::GetReayQueue(WorkCondition::Type conditionType,
96 shared_ptr<DetectorValue> conditionVal)
97 {
98 vector<shared_ptr<WorkStatus>> result;
99 std::lock_guard<std::mutex> lock(mutex_);
100 if (conditionType != WorkCondition::Type::GROUP && queueMap_.count(conditionType) > 0) {
101 shared_ptr<WorkQueue> workQueue = queueMap_.at(conditionType);
102 result = workQueue->OnConditionChanged(conditionType, conditionVal);
103 }
104 if (conditionType == WorkCondition::Type::GROUP) {
105 for (auto it : queueMap_) {
106 shared_ptr<WorkQueue> workQueue = it.second;
107 result = workQueue->OnConditionChanged(conditionType, conditionVal);
108 }
109 }
110 auto it = result.begin();
111 while (it != result.end()) {
112 if ((*it)->needRetrigger_) {
113 if (conditionType != WorkCondition::Type::TIMER
114 && conditionType != WorkCondition::Type::GROUP) {
115 WS_HILOGD("Need retrigger, start group listener.");
116 SetTimeRetrigger((*it)->timeRetrigger_);
117 listenerMap_.at(WorkCondition::Type::GROUP)->Start();
118 }
119 (*it)->needRetrigger_ = false;
120 (*it)->timeRetrigger_ = INT32_MAX;
121 it = result.erase(it);
122 } else {
123 ++it;
124 }
125 }
126 return result;
127 }
128
OnConditionChanged(WorkCondition::Type conditionType,shared_ptr<DetectorValue> conditionVal)129 void WorkQueueManager::OnConditionChanged(WorkCondition::Type conditionType,
130 shared_ptr<DetectorValue> conditionVal)
131 {
132 vector<shared_ptr<WorkStatus>> readyWorkVector = GetReayQueue(conditionType, conditionVal);
133 if (readyWorkVector.size() == 0) {
134 return;
135 }
136 for (auto it : readyWorkVector) {
137 it->MarkStatus(WorkStatus::Status::CONDITION_READY);
138 }
139 auto ws = wss_.promote();
140 ws->OnConditionReady(make_shared<vector<shared_ptr<WorkStatus>>>(readyWorkVector));
141 }
142
StopAndClearWorks(list<shared_ptr<WorkStatus>> workList)143 bool WorkQueueManager::StopAndClearWorks(list<shared_ptr<WorkStatus>> workList)
144 {
145 for (auto &it : workList) {
146 CancelWork(it);
147 }
148 return true;
149 }
150
Dump(string & result)151 void WorkQueueManager::Dump(string& result)
152 {
153 std::lock_guard<std::mutex> lock(mutex_);
154 string conditionType[] = {"network", "charger", "battery_status", "battery_level",
155 "storage", "timer", "unknown"};
156 uint32_t size = sizeof(conditionType);
157 for (auto it : queueMap_) {
158 if (it.first < size) {
159 result.append(conditionType[it.first]);
160 } else {
161 result.append(conditionType[size - 1]);
162 }
163 result.append(" : ");
164 result.append("[");
165 string workIdStr;
166 it.second->GetWorkIdStr(workIdStr);
167 result.append(workIdStr);
168 result.append("]\n");
169 }
170 }
171
SetTimeCycle(uint32_t time)172 void WorkQueueManager::SetTimeCycle(uint32_t time)
173 {
174 timeCycle_ = time;
175 }
176
GetTimeCycle()177 uint32_t WorkQueueManager::GetTimeCycle()
178 {
179 return timeCycle_;
180 }
181
SetTimeRetrigger(int32_t time)182 void WorkQueueManager::SetTimeRetrigger(int32_t time)
183 {
184 g_timeRetrigger = time;
185 }
186
GetTimeRetrigger()187 int32_t WorkQueueManager::GetTimeRetrigger()
188 {
189 return g_timeRetrigger;
190 }
191
SetMinIntervalByDump(int64_t interval)192 void WorkQueueManager::SetMinIntervalByDump(int64_t interval)
193 {
194 for (auto it : queueMap_) {
195 it.second->SetMinIntervalByDump(interval);
196 }
197 }
198 } // namespace WorkScheduler
199 } // namespace OHOS