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
16 #include "work_status.h"
17
18 #include "battery_srv_client.h"
19 #include "work_sched_common.h"
20 #include "work_sched_utils.h"
21
22 using namespace std;
23 using namespace OHOS::PowerMgr;
24
25 namespace OHOS {
26 namespace WorkScheduler {
27 static const int ONE_SECOND = 1000;
28
getCurrentTime()29 time_t getCurrentTime()
30 {
31 time_t result;
32 time(&result);
33 return result;
34 }
35
WorkStatus(WorkInfo & workInfo,int32_t uid)36 WorkStatus::WorkStatus(WorkInfo &workInfo, int32_t uid)
37 {
38 this->workInfo_ = make_shared<WorkInfo>(workInfo);
39 this->workId_ = MakeWorkId(workInfo.GetWorkId(), uid);
40 this->bundleName_ = workInfo.GetBundleName();
41 this->abilityName_ = workInfo.GetAbilityName();
42 this->baseTime_ = getCurrentTime();
43 this->uid_ = uid;
44 this->userId_ = WorkSchedUtils::GetUserIdByUid(uid);
45 if (workInfo.GetConditionMap()->count(WorkCondition::Type::TIMER) > 0) {
46 auto workTimerCondition = workInfo.GetConditionMap()->at(WorkCondition::Type::TIMER);
47 shared_ptr<Condition> timeCondition = make_shared<Condition>();
48 timeCondition->uintVal = workTimerCondition->uintVal;
49 if (!workTimerCondition->boolVal) {
50 timeCondition->intVal = workTimerCondition->intVal;
51 }
52 conditionMap_.emplace(WorkCondition::Type::TIMER, timeCondition);
53 }
54 this->persisted_ = workInfo.IsPersisted();
55 this->priority_ = DEFAULT_PRIORITY;
56 this->currentStatus_ = WAIT_CONDITION;
57 }
58
~WorkStatus()59 WorkStatus::~WorkStatus() {}
60
OnConditionChanged(WorkCondition::Type & type,shared_ptr<Condition> value)61 void WorkStatus::OnConditionChanged(WorkCondition::Type &type, shared_ptr<Condition> value)
62 {
63 if (workInfo_->GetConditionMap()->count(type) > 0
64 && type != WorkCondition::Type::TIMER) {
65 if (conditionMap_.count(type) > 0) {
66 conditionMap_.at(type) = value;
67 } else {
68 conditionMap_.emplace(type, value);
69 }
70 }
71 if (IsReady()) {
72 MarkStatus(Status::CONDITION_READY);
73 }
74 }
75
MakeWorkId(int32_t workId,int32_t uid)76 string WorkStatus::MakeWorkId(int32_t workId, int32_t uid)
77 {
78 return string("u") + to_string(uid) + "_" + to_string(workId);
79 }
80
MarkTimeout()81 void WorkStatus::MarkTimeout()
82 {
83 lastTimeout_ = true;
84 }
85
MarkStatus(Status status)86 void WorkStatus::MarkStatus(Status status)
87 {
88 currentStatus_ = status;
89 }
90
MarkRound()91 void WorkStatus::MarkRound() {}
92
UpdateTimerIfNeed()93 void WorkStatus::UpdateTimerIfNeed()
94 {
95 if (conditionMap_.count(WorkCondition::Type::TIMER) > 0) {
96 baseTime_ = getCurrentTime();
97 if (conditionMap_.at(WorkCondition::Type::TIMER)->boolVal) {
98 return;
99 }
100 int cycleLeft = conditionMap_.at(WorkCondition::Type::TIMER)->intVal;
101 conditionMap_.at(WorkCondition::Type::TIMER)->intVal = cycleLeft - 1;
102 }
103 }
104
NeedRemove()105 bool WorkStatus::NeedRemove()
106 {
107 if (conditionMap_.count(WorkCondition::Type::TIMER) <= 0) {
108 return true;
109 }
110 if (conditionMap_.at(WorkCondition::Type::TIMER)->boolVal) {
111 return false;
112 }
113 if (conditionMap_.at(WorkCondition::Type::TIMER)->intVal <= 0) {
114 return true;
115 }
116 return false;
117 }
118
IsSameUser()119 bool WorkStatus::IsSameUser()
120 {
121 if (!WorkSchedUtils::IsIdActive(userId_)) {
122 return false;
123 }
124 return true;
125 }
126
IsReady()127 bool WorkStatus::IsReady()
128 {
129 if (!IsSameUser()) {
130 WS_HILOGD("Not same user. WorkId:%{public}s", workId_.c_str());
131 return false;
132 }
133 if (IsRunning()) {
134 WS_HILOGD("Work is running");
135 return false;
136 }
137 auto workConditionMap = workInfo_->GetConditionMap();
138 for (auto it : *workConditionMap) {
139 if (conditionMap_.count(it.first) <= 0) {
140 return false;
141 }
142 switch (it.first) {
143 case WorkCondition::Type::NETWORK: {
144 if (conditionMap_.at(it.first)->enumVal == WorkCondition::Network::NETWORK_UNKNOWN) {
145 return false;
146 }
147 if (workConditionMap->at(it.first)->enumVal != WorkCondition::Network::NETWORK_TYPE_ANY &&
148 workConditionMap->at(it.first)->enumVal != conditionMap_.at(it.first)->enumVal) {
149 return false;
150 }
151 break;
152 }
153 case WorkCondition::Type::BATTERY_STATUS: {
154 int batteryReq = workConditionMap->at(it.first)->enumVal;
155 if (batteryReq != WorkCondition::BatteryStatus::BATTERY_STATUS_LOW_OR_OKAY &&
156 batteryReq != conditionMap_.at(it.first)->enumVal) {
157 return false;
158 }
159 break;
160 }
161 case WorkCondition::Type::STORAGE: {
162 if (workConditionMap->at(it.first)->enumVal != WorkCondition::Storage::STORAGE_LEVEL_LOW_OR_OKAY &&
163 workConditionMap->at(it.first)->enumVal != conditionMap_.at(it.first)->enumVal) {
164 return false;
165 }
166 break;
167 }
168 case WorkCondition::Type::CHARGER: {
169 auto conditionSet = workConditionMap->at(it.first);
170 auto conditionCurrent = conditionMap_.at(it.first);
171 if (conditionSet->boolVal) {
172 if (conditionCurrent->enumVal != conditionSet->enumVal &&
173 conditionSet->enumVal !=
174 static_cast<int32_t>(WorkCondition::Charger::CHARGING_PLUGGED_ANY)) {
175 return false;
176 }
177 } else {
178 if (conditionCurrent->enumVal !=
179 static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNPLUGGED)) {
180 return false;
181 }
182 }
183 break;
184 }
185 case WorkCondition::Type::BATTERY_LEVEL: {
186 if (workConditionMap->at(it.first)->intVal > conditionMap_.at(it.first)->intVal) {
187 return false;
188 }
189 break;
190 }
191 case WorkCondition::Type::TIMER: {
192 uint32_t intervalTime = workConditionMap->at(WorkCondition::Type::TIMER)->uintVal;
193 double del = difftime(getCurrentTime(), baseTime_) * ONE_SECOND;
194 WS_HILOGD("del time:%{public}f, intervalTime:%{public}d", del, intervalTime);
195 if (del < intervalTime) {
196 return false;
197 }
198 break;
199 }
200 default:
201 break;
202 }
203 }
204 return true;
205 }
206
IsRunning()207 bool WorkStatus::IsRunning()
208 {
209 return currentStatus_ == RUNNING;
210 }
211
IsReadyStatus()212 bool WorkStatus::IsReadyStatus()
213 {
214 return currentStatus_ == CONDITION_READY;
215 }
216
IsRemoved()217 bool WorkStatus::IsRemoved()
218 {
219 return currentStatus_ == REMOVED;
220 }
221
IsLastWorkTimeout()222 bool WorkStatus::IsLastWorkTimeout()
223 {
224 return lastTimeout_;
225 }
226
IsRepeating()227 bool WorkStatus::IsRepeating()
228 {
229 if (conditionMap_.count(WorkCondition::Type::TIMER) <= 0) {
230 return false;
231 }
232 if (conditionMap_.at(WorkCondition::Type::TIMER)->boolVal) {
233 return true;
234 } else {
235 return conditionMap_.at(WorkCondition::Type::TIMER)->intVal > 0;
236 }
237 }
238
GetStatus()239 WorkStatus::Status WorkStatus::GetStatus()
240 {
241 return currentStatus_;
242 }
243
Dump(string & result)244 void WorkStatus::Dump(string& result)
245 {
246 result.append("{\n");
247 result.append(string("\"workId\":") + workId_ + ",\n");
248 result.append(string("\"bundleName\":") + bundleName_ + ",\n");
249 result.append(string("\"status\":") + to_string(currentStatus_) + ",\n");
250 result.append(string("\"conditionMap\":{\n"));
251 if (conditionMap_.count(WorkCondition::Type::NETWORK) > 0) {
252 result.append(string("\"networkType\":") +
253 to_string(conditionMap_.at(WorkCondition::Type::NETWORK)->enumVal) + ",\n");
254 }
255 if (conditionMap_.count(WorkCondition::Type::CHARGER) > 0) {
256 result.append(string("\"isCharging\":") +
257 (conditionMap_.at(WorkCondition::Type::CHARGER)->boolVal ? "true" : "false") + ",\n");
258 result.append(string("\"chargerType\":") +
259 to_string(conditionMap_.at(WorkCondition::Type::CHARGER)->enumVal) + ",\n");
260 }
261 if (conditionMap_.count(WorkCondition::Type::BATTERY_LEVEL) > 0) {
262 result.append(string("\"batteryLevel\":") +
263 to_string(conditionMap_.at(WorkCondition::Type::BATTERY_LEVEL)->intVal) + ",\n");
264 }
265 if (conditionMap_.count(WorkCondition::Type::BATTERY_STATUS) > 0) {
266 result.append(string("\"batteryStatus\":") +
267 to_string(conditionMap_.at(WorkCondition::Type::BATTERY_STATUS)->enumVal) + ",\n");
268 }
269 if (conditionMap_.count(WorkCondition::Type::STORAGE) > 0) {
270 result.append(string("\"storageLevel\":") +
271 to_string(conditionMap_.at(WorkCondition::Type::STORAGE)->enumVal) + ",\n");
272 }
273 if (conditionMap_.count(WorkCondition::Type::TIMER) > 0) {
274 result.append(string("\"baseTime\":") + to_string(baseTime_) + ",\n");
275 if (conditionMap_.at(WorkCondition::Type::TIMER)->boolVal) {
276 result.append(string("\"isRepeat\": true,\n"));
277 } else {
278 result.append(string("\"cycleLeft\":") +
279 to_string(conditionMap_.at(WorkCondition::Type::TIMER)->intVal) + ",\n");
280 }
281 }
282 result.append("},\n\"workInfo\":\n");
283 workInfo_->Dump(result);
284 result.append("}\n");
285 result.append("\n");
286 WS_HILOGD("%s", result.c_str());
287 }
288 } // namespace WorkScheduler
289 } // namespace OHOS