1 /*
2 * Copyright (c) 2022-2024 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 "time_service_client.h"
19 #include "work_datashare_helper.h"
20 #include "work_sched_errors.h"
21 #include "work_sched_utils.h"
22 #include "work_scheduler_service.h"
23 #include "work_sched_hilog.h"
24 #include "work_sched_errors.h"
25 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
26 #include "bundle_active_client.h"
27 #include "bundle_active_group_map.h"
28 #endif
29 #include "parameters.h"
30 #include "work_sched_data_manager.h"
31 #include "work_sched_config.h"
32 #include <unordered_map>
33
34 using namespace std;
35
36 namespace OHOS {
37 namespace WorkScheduler {
38 static const double ONE_SECOND = 1000.0;
39 static bool g_groupDebugMode = false;
40 static const int64_t MIN_INTERVAL_DEFAULT = 2 * 60 * 60 * 1000;
41 std::map<int32_t, time_t> WorkStatus::s_uid_last_time_map;
42 const int32_t DEFAULT_PRIORITY = 10000;
43 const int32_t HIGH_PRIORITY = 0;
44 const int32_t ACTIVE_GROUP = 10;
45 const string SWITCH_ON = "1";
46 const string DELIMITER = ",";
47 ffrt::mutex WorkStatus::s_uid_last_time_mutex;
48
49 std::unordered_map<WorkCondition::Type, std::string> COND_TYPE_STRING_MAP = {
50 {WorkCondition::Type::NETWORK, "NETWORK"},
51 {WorkCondition::Type::CHARGER, "CHARGER"},
52 {WorkCondition::Type::BATTERY_STATUS, "BATTERY_STATUS"},
53 {WorkCondition::Type::BATTERY_LEVEL, "BATTERY_LEVEL"},
54 {WorkCondition::Type::STORAGE, "STORAGE"},
55 {WorkCondition::Type::TIMER, "TIMER"},
56 {WorkCondition::Type::GROUP, "GROUP"},
57 {WorkCondition::Type::DEEP_IDLE, "DEEP_IDLE"},
58 {WorkCondition::Type::STANDBY, "STANDBY"}
59 };
60
getCurrentTime()61 time_t getCurrentTime()
62 {
63 time_t result;
64 time(&result);
65 return result;
66 }
67
getOppositeTime()68 time_t getOppositeTime()
69 {
70 time_t result;
71 sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
72 result = static_cast<time_t>(timer->GetBootTimeMs());
73 return result;
74 }
75
WorkStatus(WorkInfo & workInfo,int32_t uid)76 WorkStatus::WorkStatus(WorkInfo &workInfo, int32_t uid)
77 {
78 this->workInfo_ = make_shared<WorkInfo>(workInfo);
79 this->workId_ = MakeWorkId(workInfo.GetWorkId(), uid);
80 this->bundleName_ = workInfo.GetBundleName();
81 this->abilityName_ = workInfo.GetAbilityName();
82 this->baseTime_ = workInfo.GetBaseTime();
83 this->uid_ = uid;
84 this->userId_ = WorkSchedUtils::GetUserIdByUid(uid);
85 if (workInfo.GetConditionMap()->count(WorkCondition::Type::TIMER) > 0) {
86 auto workTimerCondition = workInfo.GetConditionMap()->at(WorkCondition::Type::TIMER);
87 shared_ptr<Condition> timeCondition = make_shared<Condition>();
88 timeCondition->uintVal = workTimerCondition->uintVal;
89 timeCondition->boolVal = workTimerCondition->boolVal;
90 if (!workTimerCondition->boolVal) {
91 timeCondition->intVal = workTimerCondition->intVal;
92 }
93 std::lock_guard<ffrt::mutex> lock(conditionMapMutex_);
94 conditionMap_.emplace(WorkCondition::Type::TIMER, timeCondition);
95 }
96 this->persisted_ = workInfo.IsPersisted();
97 this->priority_ = GetPriority();
98 this->currentStatus_ = WAIT_CONDITION;
99 this->minInterval_ = MIN_INTERVAL_DEFAULT;
100 this->groupChanged_ = false;
101 }
102
~WorkStatus()103 WorkStatus::~WorkStatus() {}
104
OnConditionChanged(WorkCondition::Type & type,shared_ptr<Condition> value)105 int32_t WorkStatus::OnConditionChanged(WorkCondition::Type &type, shared_ptr<Condition> value)
106 {
107 WS_HILOGD("Work status condition changed.");
108 if (workInfo_->GetConditionMap()->count(type) > 0
109 && type != WorkCondition::Type::TIMER
110 && type != WorkCondition::Type::GROUP) {
111 std::lock_guard<ffrt::mutex> lock(conditionMapMutex_);
112 if (conditionMap_.count(type) > 0) {
113 conditionMap_.at(type) = value;
114 } else {
115 conditionMap_.emplace(type, value);
116 }
117 }
118 groupChanged_ = false;
119 if (type == WorkCondition::Type::GROUP && value && value->boolVal) {
120 WS_HILOGD("Group changed, bundleName: %{public}s.", value->strVal.c_str());
121 groupChanged_ = true;
122 if (value->intVal == userId_ && value->strVal == bundleName_) {
123 SetMinIntervalByGroup(value->enumVal);
124 } else {
125 return E_GROUP_CHANGE_NOT_MATCH_HAP;
126 }
127 }
128 if (!IsStandbyExemption()) {
129 return E_GROUP_CHANGE_NOT_MATCH_HAP;
130 }
131 if (IsReady()) {
132 MarkStatus(Status::CONDITION_READY);
133 }
134 return ERR_OK;
135 }
136
MakeWorkId(int32_t workId,int32_t uid)137 string WorkStatus::MakeWorkId(int32_t workId, int32_t uid)
138 {
139 return string("u") + to_string(uid) + "_" + to_string(workId);
140 }
141
MarkTimeout()142 void WorkStatus::MarkTimeout()
143 {
144 lastTimeout_ = true;
145 }
146
MarkStatus(Status status)147 void WorkStatus::MarkStatus(Status status)
148 {
149 currentStatus_ = status;
150 }
151
MarkRound()152 void WorkStatus::MarkRound() {}
153
UpdateTimerIfNeed()154 void WorkStatus::UpdateTimerIfNeed()
155 {
156 std::lock_guard<ffrt::mutex> lock(conditionMapMutex_);
157 if (conditionMap_.count(WorkCondition::Type::TIMER) > 0) {
158 baseTime_ = getCurrentTime();
159 if (conditionMap_.at(WorkCondition::Type::TIMER)->boolVal) {
160 workInfo_->RequestBaseTime(baseTime_);
161 DelayedSingleton<WorkSchedulerService>::GetInstance()->RefreshPersistedWorks();
162 return;
163 }
164 int32_t cycleLeft = conditionMap_.at(WorkCondition::Type::TIMER)->intVal;
165 conditionMap_.at(WorkCondition::Type::TIMER)->intVal = cycleLeft - 1;
166 workInfo_->RequestBaseTimeAndCycle(baseTime_, cycleLeft - 1);
167 DelayedSingleton<WorkSchedulerService>::GetInstance()->RefreshPersistedWorks();
168 }
169 }
170
NeedRemove()171 bool WorkStatus::NeedRemove()
172 {
173 std::lock_guard<ffrt::mutex> lock(conditionMapMutex_);
174 if (conditionMap_.count(WorkCondition::Type::TIMER) <= 0) {
175 return true;
176 }
177 if (conditionMap_.at(WorkCondition::Type::TIMER)->boolVal) {
178 return false;
179 }
180 if (conditionMap_.at(WorkCondition::Type::TIMER)->intVal <= 0) {
181 return true;
182 }
183 return false;
184 }
185
IsSameUser()186 bool WorkStatus::IsSameUser()
187 {
188 if (userId_ > 0 && !WorkSchedUtils::IsIdActive(userId_)) {
189 return false;
190 }
191 return true;
192 }
193
IsUriKeySwitchOn()194 bool WorkStatus::IsUriKeySwitchOn()
195 {
196 if (!workInfo_->IsPreinstalled()) {
197 return true;
198 }
199 if (workInfo_->GetUriKey().empty()) {
200 WS_HILOGE("key is empty %{public}s", workId_.c_str());
201 return false;
202 }
203 string key = workInfo_->GetUriKey();
204 string value;
205 (void)WorkDatashareHelper::GetInstance().GetStringValue(key, value);
206 if (value == SWITCH_ON) {
207 return true;
208 }
209 WS_HILOGE("workid %{public}s key %{public}s, value is 0", workId_.c_str(), key.c_str());
210 return false;
211 }
212
IsReady()213 bool WorkStatus::IsReady()
214 {
215 conditionStatus_.clear();
216 if (!IsSameUser()) {
217 conditionStatus_ += DELIMITER + "notSameUser";
218 return false;
219 }
220 if (IsRunning()) {
221 conditionStatus_ += DELIMITER + "running";
222 return false;
223 }
224 if (!IsConditionReady()) {
225 return false;
226 }
227 if (!IsUriKeySwitchOn()) {
228 conditionStatus_ += DELIMITER + "uriKeyOFF";
229 return false;
230 }
231 if (DelayedSingleton<WorkSchedulerService>::GetInstance()->CheckEffiResApplyInfo(uid_)) {
232 conditionStatus_ += DELIMITER + "effiResWhitelist";
233 return true;
234 }
235 if (!g_groupDebugMode && ((!groupChanged_ && !SetMinInterval()) || minInterval_ == -1)) {
236 WS_HILOGE("Work can't ready due to false group, forbidden group or unused group, bundleName:%{public}s, "
237 "minInterval:%{public}" PRId64 ", workId:%{public}s", bundleName_.c_str(), minInterval_, workId_.c_str());
238 return false;
239 }
240 if (s_uid_last_time_map.find(uid_) == s_uid_last_time_map.end()) {
241 conditionStatus_ += DELIMITER + "firstTrigger";
242 return true;
243 }
244 double del = difftime(getOppositeTime(), s_uid_last_time_map[uid_]);
245 if (del < minInterval_) {
246 conditionStatus_ += DELIMITER + COND_TYPE_STRING_MAP[WorkCondition::Type::GROUP] + "&unready(" +
247 to_string(static_cast<long>(del)) + ":" + to_string(minInterval_) + ")";
248 needRetrigger_ = true;
249 timeRetrigger_ = int(minInterval_ - del + ONE_SECOND);
250 return false;
251 }
252 WS_HILOGI("All condition ready, bundleName:%{public}s, abilityName:%{public}s, workId:%{public}s, "
253 "groupChanged:%{public}d, minInterval:%{public}" PRId64 ", del = %{public}f",
254 bundleName_.c_str(), abilityName_.c_str(), workId_.c_str(), groupChanged_, minInterval_, del);
255 return true;
256 }
257
IsConditionReady()258 bool WorkStatus::IsConditionReady()
259 {
260 auto workConditionMap = workInfo_->GetConditionMap();
261 std::lock_guard<ffrt::mutex> lock(s_uid_last_time_mutex);
262 bool isReady = true;
263 for (auto it : *workConditionMap) {
264 if (conditionMap_.count(it.first) <= 0) {
265 conditionStatus_ += DELIMITER + COND_TYPE_STRING_MAP[it.first] + "&unready";
266 isReady = false;
267 break;
268 }
269 if (!IsBatteryAndNetworkReady(it.first) || !IsStorageReady(it.first) ||
270 !IsChargerReady(it.first) || !IsNapReady(it.first)) {
271 conditionStatus_ += DELIMITER + COND_TYPE_STRING_MAP[it.first] + "&unready";
272 isReady = false;
273 break;
274 }
275 if (!IsTimerReady(it.first)) {
276 isReady = false;
277 break;
278 }
279 conditionStatus_ += DELIMITER + COND_TYPE_STRING_MAP[it.first] + "&ready";
280 }
281 return isReady;
282 }
283
IsBatteryAndNetworkReady(WorkCondition::Type type)284 bool WorkStatus::IsBatteryAndNetworkReady(WorkCondition::Type type)
285 {
286 auto workConditionMap = workInfo_->GetConditionMap();
287 switch (type) {
288 case WorkCondition::Type::NETWORK: {
289 if (conditionMap_.at(type)->enumVal == WorkCondition::Network::NETWORK_UNKNOWN) {
290 return false;
291 }
292 if (workConditionMap->at(type)->enumVal != WorkCondition::Network::NETWORK_TYPE_ANY &&
293 workConditionMap->at(type)->enumVal != conditionMap_.at(type)->enumVal) {
294 return false;
295 }
296 break;
297 }
298 case WorkCondition::Type::BATTERY_STATUS: {
299 int32_t batteryReq = workConditionMap->at(type)->enumVal;
300 if (batteryReq != WorkCondition::BatteryStatus::BATTERY_STATUS_LOW_OR_OKAY &&
301 batteryReq != conditionMap_.at(type)->enumVal) {
302 return false;
303 }
304 break;
305 }
306 case WorkCondition::Type::BATTERY_LEVEL: {
307 if (workConditionMap->at(type)->intVal > conditionMap_.at(type)->intVal) {
308 return false;
309 }
310 break;
311 }
312 default:
313 break;
314 }
315 return true;
316 }
317
IsChargerReady(WorkCondition::Type type)318 bool WorkStatus::IsChargerReady(WorkCondition::Type type)
319 {
320 if (type != WorkCondition::Type::CHARGER) {
321 return true;
322 }
323 auto conditionSet = workInfo_->GetConditionMap()->at(WorkCondition::Type::CHARGER);
324 auto conditionCurrent = conditionMap_.at(WorkCondition::Type::CHARGER);
325 if (conditionSet->boolVal != conditionCurrent->boolVal) {
326 return false;
327 }
328 if (conditionSet->boolVal) {
329 if (conditionCurrent->enumVal != conditionSet->enumVal && conditionSet->enumVal !=
330 static_cast<int32_t>(WorkCondition::Charger::CHARGING_PLUGGED_ANY)) {
331 return false;
332 }
333 } else {
334 if (conditionCurrent->enumVal != static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNPLUGGED)) {
335 return false;
336 }
337 }
338 return true;
339 }
340
IsStorageReady(WorkCondition::Type type)341 bool WorkStatus::IsStorageReady(WorkCondition::Type type)
342 {
343 if (type != WorkCondition::Type::STORAGE) {
344 return true;
345 }
346 auto workConditionMap = workInfo_->GetConditionMap();
347 if (workConditionMap->at(type)->enumVal != WorkCondition::Storage::STORAGE_LEVEL_LOW_OR_OKAY &&
348 workConditionMap->at(type)->enumVal != conditionMap_.at(type)->enumVal) {
349 return false;
350 }
351 return true;
352 }
353
IsStandbyExemption()354 bool WorkStatus::IsStandbyExemption()
355 {
356 auto dataManager = DelayedSingleton<DataManager>::GetInstance();
357 if (dataManager->GetDeviceSleep()) {
358 if (dataManager->IsInDeviceStandyWhitelist(bundleName_)) {
359 conditionStatus_ += "|" + COND_TYPE_STRING_MAP[WorkCondition::Type::STANDBY] + "&exemption";
360 return true;
361 }
362 conditionStatus_ += "|" + COND_TYPE_STRING_MAP[WorkCondition::Type::STANDBY] + "&unExemption";
363 return false;
364 }
365 return true;
366 }
367
IsTimerReady(WorkCondition::Type type)368 bool WorkStatus::IsTimerReady(WorkCondition::Type type)
369 {
370 if (type != WorkCondition::Type::TIMER) {
371 return true;
372 }
373 auto workConditionMap = workInfo_->GetConditionMap();
374 uint32_t intervalTime = workConditionMap->at(WorkCondition::Type::TIMER)->uintVal;
375 time_t lastTime;
376 if (s_uid_last_time_map.find(uid_) == s_uid_last_time_map.end()) {
377 lastTime = 0;
378 } else {
379 lastTime = s_uid_last_time_map[uid_];
380 }
381 double currentdel = difftime(getCurrentTime(), baseTime_) * ONE_SECOND;
382 double oppositedel = difftime(getOppositeTime(), lastTime);
383 double del = currentdel > oppositedel ? currentdel : oppositedel;
384 if (del < intervalTime) {
385 conditionStatus_ += DELIMITER + COND_TYPE_STRING_MAP[type] + "&unready(" +
386 to_string(static_cast<long>(del)) + ":" + to_string(intervalTime) + ")";
387 return false;
388 }
389 return true;
390 }
391
IsNapReady(WorkCondition::Type type)392 bool WorkStatus::IsNapReady(WorkCondition::Type type)
393 {
394 if (type != WorkCondition::Type::DEEP_IDLE) {
395 return true;
396 }
397 auto conditionSet = workInfo_->GetConditionMap()->at(WorkCondition::Type::DEEP_IDLE);
398 auto conditionCurrent = conditionMap_.at(WorkCondition::Type::DEEP_IDLE);
399 if (conditionSet->boolVal != conditionCurrent->boolVal) {
400 return false;
401 }
402 return true;
403 }
404
SetMinInterval()405 bool WorkStatus::SetMinInterval()
406 {
407 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
408 int32_t group = 0;
409 if (workInfo_->IsCallBySystemApp()) {
410 WS_HILOGD("system app %{public}s, default group is active.", bundleName_.c_str());
411 return SetMinIntervalByGroup(ACTIVE_GROUP);
412 }
413 bool res = DelayedSingleton<DataManager>::GetInstance()->FindGroup(bundleName_, userId_, group);
414 if (!res) {
415 WS_HILOGI("no cache find, bundleName:%{public}s", bundleName_.c_str());
416 auto errCode = DeviceUsageStats::BundleActiveClient::GetInstance().QueryAppGroup(group, bundleName_, userId_);
417 if (errCode != ERR_OK) {
418 WS_HILOGE("query package group failed. userId = %{public}d, bundleName = %{public}s",
419 userId_, bundleName_.c_str());
420 group = ACTIVE_GROUP;
421 }
422 DelayedSingleton<DataManager>::GetInstance()->AddGroup(bundleName_, userId_, group);
423 }
424 #else
425 int32_t group = ACTIVE_GROUP;
426 #endif
427 return SetMinIntervalByGroup(group);
428 }
429
SetMinIntervalByGroup(int32_t group)430 bool WorkStatus::SetMinIntervalByGroup(int32_t group)
431 {
432 groupChanged_ = true;
433
434 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
435 int32_t newGroup = group;
436 if (DelayedSingleton<WorkSchedulerConfig>::GetInstance()->IsInActiveGroupWhitelist(bundleName_) &&
437 group > DeviceUsageStats::DeviceUsageStatsGroupConst::ACTIVE_GROUP_FIXED) {
438 newGroup = DeviceUsageStats::DeviceUsageStatsGroupConst::ACTIVE_GROUP_FIXED;
439 }
440 auto itMap = DeviceUsageStats::DeviceUsageStatsGroupMap::groupIntervalMap_.find(newGroup);
441 if (itMap != DeviceUsageStats::DeviceUsageStatsGroupMap::groupIntervalMap_.end()) {
442 minInterval_ = DeviceUsageStats::DeviceUsageStatsGroupMap::groupIntervalMap_[newGroup];
443 } else {
444 WS_HILOGE("query package group interval failed. group:%{public}d, bundleName:%{public}s",
445 newGroup, bundleName_.c_str());
446 minInterval_ = -1;
447 }
448 #else
449 minInterval_ = MIN_INTERVAL_DEFAULT;
450 #endif
451 WS_HILOGD("set min interval to %{public}" PRId64 " by group %{public}d", minInterval_, group);
452 return true;
453 }
454
SetMinIntervalByDump(int64_t interval)455 void WorkStatus::SetMinIntervalByDump(int64_t interval)
456 {
457 WS_HILOGD("set min interval by dump to %{public}" PRId64 "", interval);
458 g_groupDebugMode = interval == 0 ? false : true;
459 minInterval_ = interval == 0 ? minInterval_ : interval;
460 }
461
GetMinInterval()462 int64_t WorkStatus::GetMinInterval()
463 {
464 return minInterval_;
465 }
466
UpdateUidLastTimeMap()467 void WorkStatus::UpdateUidLastTimeMap()
468 {
469 std::lock_guard<ffrt::mutex> lock(s_uid_last_time_mutex);
470 time_t lastTime = getOppositeTime();
471 s_uid_last_time_map[uid_] = lastTime;
472 }
473
ClearUidLastTimeMap(int32_t uid)474 void WorkStatus::ClearUidLastTimeMap(int32_t uid)
475 {
476 std::lock_guard<ffrt::mutex> lock(s_uid_last_time_mutex);
477 s_uid_last_time_map.erase(uid);
478 }
479
IsRunning()480 bool WorkStatus::IsRunning()
481 {
482 return currentStatus_ == RUNNING;
483 }
484
IsPaused()485 bool WorkStatus::IsPaused()
486 {
487 return paused_;
488 }
489
IsReadyStatus()490 bool WorkStatus::IsReadyStatus()
491 {
492 return currentStatus_ == CONDITION_READY;
493 }
494
IsRemoved()495 bool WorkStatus::IsRemoved()
496 {
497 return currentStatus_ == REMOVED;
498 }
499
IsLastWorkTimeout()500 bool WorkStatus::IsLastWorkTimeout()
501 {
502 return lastTimeout_;
503 }
504
IsRepeating()505 bool WorkStatus::IsRepeating()
506 {
507 std::lock_guard<ffrt::mutex> lock(conditionMapMutex_);
508 if (conditionMap_.count(WorkCondition::Type::TIMER) <= 0) {
509 return false;
510 }
511 if (conditionMap_.at(WorkCondition::Type::TIMER)->boolVal) {
512 return true;
513 } else {
514 return conditionMap_.at(WorkCondition::Type::TIMER)->intVal > 0;
515 }
516 }
517
GetStatus()518 WorkStatus::Status WorkStatus::GetStatus()
519 {
520 return currentStatus_;
521 }
522
GetPriority()523 int WorkStatus::GetPriority()
524 {
525 if ((OHOS::system::GetIntParameter("const.debuggable", 0) == 1) &&
526 (bundleName_ == "com.huawei.hmos.hiviewx")) {
527 return HIGH_PRIORITY;
528 }
529 return DEFAULT_PRIORITY;
530 }
531
Dump(string & result)532 void WorkStatus::Dump(string& result)
533 {
534 result.append("{\n");
535 result.append(string("\"workId\":") + workId_ + ",\n");
536 result.append(string("\"bundleName\":") + bundleName_ + ",\n");
537 result.append(string("\"status\":") + to_string(currentStatus_) + ",\n");
538 result.append(string("\"paused\":") + (paused_ ? "true" : "false") + ",\n");
539 result.append(string("\"priority\":") + to_string(priority_) + ",\n");
540 result.append(string("\"conditionMap\":{\n"));
541 std::lock_guard<ffrt::mutex> lock(conditionMapMutex_);
542 if (conditionMap_.count(WorkCondition::Type::NETWORK) > 0) {
543 result.append(string("\"networkType\":") +
544 to_string(conditionMap_.at(WorkCondition::Type::NETWORK)->enumVal) + ",\n");
545 }
546 if (conditionMap_.count(WorkCondition::Type::CHARGER) > 0) {
547 result.append(string("\"isCharging\":") +
548 (conditionMap_.at(WorkCondition::Type::CHARGER)->boolVal ? "true" : "false") + ",\n");
549 result.append(string("\"chargerType\":") +
550 to_string(conditionMap_.at(WorkCondition::Type::CHARGER)->enumVal) + ",\n");
551 }
552 if (conditionMap_.count(WorkCondition::Type::BATTERY_LEVEL) > 0) {
553 result.append(string("\"batteryLevel\":") +
554 to_string(conditionMap_.at(WorkCondition::Type::BATTERY_LEVEL)->intVal) + ",\n");
555 }
556 if (conditionMap_.count(WorkCondition::Type::BATTERY_STATUS) > 0) {
557 result.append(string("\"batteryStatus\":") +
558 to_string(conditionMap_.at(WorkCondition::Type::BATTERY_STATUS)->enumVal) + ",\n");
559 }
560 if (conditionMap_.count(WorkCondition::Type::STORAGE) > 0) {
561 result.append(string("\"storageLevel\":") +
562 to_string(conditionMap_.at(WorkCondition::Type::STORAGE)->enumVal) + ",\n");
563 }
564 if (conditionMap_.count(WorkCondition::Type::TIMER) > 0) {
565 result.append(string("\"baseTime\":") + to_string(baseTime_) + ",\n");
566 if (conditionMap_.at(WorkCondition::Type::TIMER)->boolVal) {
567 result.append(string("\"isRepeat\": true,\n"));
568 } else {
569 result.append(string("\"cycleLeft\":") +
570 to_string(conditionMap_.at(WorkCondition::Type::TIMER)->intVal) + ",\n");
571 }
572 }
573 if (conditionMap_.count(WorkCondition::Type::DEEP_IDLE) > 0) {
574 result.append(string("\"isDeepIdle\":") +
575 to_string(conditionMap_.at(WorkCondition::Type::DEEP_IDLE)->boolVal) + ",\n");
576 }
577 result.append("},\n\"workInfo\":\n");
578 workInfo_->Dump(result);
579 result.append("}\n");
580 result.append("\n");
581 }
582
ToString(WorkCondition::Type type)583 void WorkStatus::ToString(WorkCondition::Type type)
584 {
585 if (conditionStatus_.empty()) {
586 return;
587 }
588 IsStandbyExemption();
589 WS_HILOGI("eventType:%{public}s,workStatus:%{public}s_%{public}s%{public}s", COND_TYPE_STRING_MAP[type].c_str(),
590 bundleName_.c_str(), workId_.c_str(), conditionStatus_.c_str());
591 }
592 } // namespace WorkScheduler
593 } // namespace OHOS