• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     conditionStatus_.clear();
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         return dataManager->IsInDeviceStandyWhitelist(bundleName_);
359     }
360     return true;
361 }
362 
IsTimerReady(WorkCondition::Type type)363 bool WorkStatus::IsTimerReady(WorkCondition::Type type)
364 {
365     if (type != WorkCondition::Type::TIMER) {
366         return true;
367     }
368     auto workConditionMap = workInfo_->GetConditionMap();
369     uint32_t intervalTime = workConditionMap->at(WorkCondition::Type::TIMER)->uintVal;
370     time_t lastTime;
371     if (s_uid_last_time_map.find(uid_) == s_uid_last_time_map.end()) {
372         lastTime = 0;
373     } else {
374         lastTime = s_uid_last_time_map[uid_];
375     }
376     double currentdel = difftime(getCurrentTime(), baseTime_) * ONE_SECOND;
377     double oppositedel = difftime(getOppositeTime(), lastTime);
378     double del = currentdel > oppositedel ? currentdel : oppositedel;
379     if (del < intervalTime) {
380         conditionStatus_ += DELIMITER + COND_TYPE_STRING_MAP[type] + "&unready(" +
381             to_string(static_cast<long>(del)) + ":" + to_string(intervalTime) + ")";
382         return false;
383     }
384     return true;
385 }
386 
IsNapReady(WorkCondition::Type type)387 bool WorkStatus::IsNapReady(WorkCondition::Type type)
388 {
389     if (type != WorkCondition::Type::DEEP_IDLE) {
390         return true;
391     }
392     auto conditionSet = workInfo_->GetConditionMap()->at(WorkCondition::Type::DEEP_IDLE);
393     auto conditionCurrent = conditionMap_.at(WorkCondition::Type::DEEP_IDLE);
394     if (conditionSet->boolVal != conditionCurrent->boolVal) {
395         return false;
396     }
397     return true;
398 }
399 
SetMinInterval()400 bool WorkStatus::SetMinInterval()
401 {
402 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
403     int32_t group = 0;
404     if (workInfo_->IsCallBySystemApp()) {
405         WS_HILOGD("system app %{public}s, default group is active.", bundleName_.c_str());
406         return SetMinIntervalByGroup(ACTIVE_GROUP);
407     }
408     bool res = DelayedSingleton<DataManager>::GetInstance()->FindGroup(bundleName_, userId_, group);
409     if (!res) {
410         WS_HILOGI("no cache find, bundleName:%{public}s", bundleName_.c_str());
411         auto errCode = DeviceUsageStats::BundleActiveClient::GetInstance().QueryAppGroup(group, bundleName_, userId_);
412         if (errCode != ERR_OK) {
413             WS_HILOGE("query package group failed. userId = %{public}d, bundleName = %{public}s",
414                 userId_, bundleName_.c_str());
415             group = ACTIVE_GROUP;
416         }
417         DelayedSingleton<DataManager>::GetInstance()->AddGroup(bundleName_, userId_, group);
418     }
419 #else
420     int32_t group = ACTIVE_GROUP;
421 #endif
422     return SetMinIntervalByGroup(group);
423 }
424 
SetMinIntervalByGroup(int32_t group)425 bool WorkStatus::SetMinIntervalByGroup(int32_t group)
426 {
427     groupChanged_ = true;
428 
429 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
430     int32_t newGroup = group;
431     if (DelayedSingleton<WorkSchedulerConfig>::GetInstance()->IsInActiveGroupWhitelist(bundleName_) &&
432         group > DeviceUsageStats::DeviceUsageStatsGroupConst::ACTIVE_GROUP_FIXED) {
433         newGroup = DeviceUsageStats::DeviceUsageStatsGroupConst::ACTIVE_GROUP_FIXED;
434     }
435     auto itMap = DeviceUsageStats::DeviceUsageStatsGroupMap::groupIntervalMap_.find(newGroup);
436     if (itMap != DeviceUsageStats::DeviceUsageStatsGroupMap::groupIntervalMap_.end()) {
437         minInterval_ = DeviceUsageStats::DeviceUsageStatsGroupMap::groupIntervalMap_[newGroup];
438     } else {
439         WS_HILOGE("query package group interval failed. group:%{public}d, bundleName:%{public}s",
440             newGroup, bundleName_.c_str());
441         minInterval_ = -1;
442     }
443 #else
444     minInterval_ = MIN_INTERVAL_DEFAULT;
445 #endif
446     WS_HILOGD("set min interval to %{public}" PRId64 " by group %{public}d", minInterval_, group);
447     return true;
448 }
449 
SetMinIntervalByDump(int64_t interval)450 void WorkStatus::SetMinIntervalByDump(int64_t interval)
451 {
452     WS_HILOGD("set min interval by dump to %{public}" PRId64 "", interval);
453     g_groupDebugMode = interval == 0 ? false : true;
454     minInterval_ = interval == 0 ? minInterval_ : interval;
455 }
456 
GetMinInterval()457 int64_t WorkStatus::GetMinInterval()
458 {
459     return minInterval_;
460 }
461 
UpdateUidLastTimeMap()462 void WorkStatus::UpdateUidLastTimeMap()
463 {
464     std::lock_guard<ffrt::mutex> lock(s_uid_last_time_mutex);
465     time_t lastTime = getOppositeTime();
466     s_uid_last_time_map[uid_] = lastTime;
467 }
468 
ClearUidLastTimeMap(int32_t uid)469 void WorkStatus::ClearUidLastTimeMap(int32_t uid)
470 {
471     std::lock_guard<ffrt::mutex> lock(s_uid_last_time_mutex);
472     s_uid_last_time_map.erase(uid);
473 }
474 
IsRunning()475 bool WorkStatus::IsRunning()
476 {
477     return currentStatus_ == RUNNING;
478 }
479 
IsPaused()480 bool WorkStatus::IsPaused()
481 {
482     return paused_;
483 }
484 
IsReadyStatus()485 bool WorkStatus::IsReadyStatus()
486 {
487     return currentStatus_ == CONDITION_READY;
488 }
489 
IsRemoved()490 bool WorkStatus::IsRemoved()
491 {
492     return currentStatus_ == REMOVED;
493 }
494 
IsLastWorkTimeout()495 bool WorkStatus::IsLastWorkTimeout()
496 {
497     return lastTimeout_;
498 }
499 
IsRepeating()500 bool WorkStatus::IsRepeating()
501 {
502     std::lock_guard<ffrt::mutex> lock(conditionMapMutex_);
503     if (conditionMap_.count(WorkCondition::Type::TIMER) <= 0) {
504         return false;
505     }
506     if (conditionMap_.at(WorkCondition::Type::TIMER)->boolVal) {
507         return true;
508     } else {
509         return conditionMap_.at(WorkCondition::Type::TIMER)->intVal > 0;
510     }
511 }
512 
GetStatus()513 WorkStatus::Status WorkStatus::GetStatus()
514 {
515     return currentStatus_;
516 }
517 
GetPriority()518 int WorkStatus::GetPriority()
519 {
520     if ((OHOS::system::GetIntParameter("const.debuggable", 0) == 1) &&
521         (bundleName_ == "com.huawei.hmos.hiviewx")) {
522         return HIGH_PRIORITY;
523     }
524     return DEFAULT_PRIORITY;
525 }
526 
Dump(string & result)527 void WorkStatus::Dump(string& result)
528 {
529     result.append("{\n");
530     result.append(string("\"workId\":") + workId_ + ",\n");
531     result.append(string("\"bundleName\":") + bundleName_ + ",\n");
532     result.append(string("\"status\":") + to_string(currentStatus_) + ",\n");
533     result.append(string("\"paused\":") + (paused_ ? "true" : "false") + ",\n");
534     result.append(string("\"priority\":") + to_string(priority_) + ",\n");
535     result.append(string("\"conditionMap\":{\n"));
536     std::lock_guard<ffrt::mutex> lock(conditionMapMutex_);
537     if (conditionMap_.count(WorkCondition::Type::NETWORK) > 0) {
538         result.append(string("\"networkType\":") +
539             to_string(conditionMap_.at(WorkCondition::Type::NETWORK)->enumVal) + ",\n");
540     }
541     if (conditionMap_.count(WorkCondition::Type::CHARGER) > 0) {
542         result.append(string("\"isCharging\":") +
543             (conditionMap_.at(WorkCondition::Type::CHARGER)->boolVal ? "true" : "false") + ",\n");
544         result.append(string("\"chargerType\":") +
545             to_string(conditionMap_.at(WorkCondition::Type::CHARGER)->enumVal) + ",\n");
546     }
547     if (conditionMap_.count(WorkCondition::Type::BATTERY_LEVEL) > 0) {
548         result.append(string("\"batteryLevel\":") +
549             to_string(conditionMap_.at(WorkCondition::Type::BATTERY_LEVEL)->intVal) + ",\n");
550     }
551     if (conditionMap_.count(WorkCondition::Type::BATTERY_STATUS) > 0) {
552         result.append(string("\"batteryStatus\":") +
553             to_string(conditionMap_.at(WorkCondition::Type::BATTERY_STATUS)->enumVal) + ",\n");
554     }
555     if (conditionMap_.count(WorkCondition::Type::STORAGE) > 0) {
556         result.append(string("\"storageLevel\":") +
557             to_string(conditionMap_.at(WorkCondition::Type::STORAGE)->enumVal) + ",\n");
558     }
559     if (conditionMap_.count(WorkCondition::Type::TIMER) > 0) {
560         result.append(string("\"baseTime\":") + to_string(baseTime_) + ",\n");
561         if (conditionMap_.at(WorkCondition::Type::TIMER)->boolVal) {
562             result.append(string("\"isRepeat\": true,\n"));
563         } else {
564             result.append(string("\"cycleLeft\":") +
565                 to_string(conditionMap_.at(WorkCondition::Type::TIMER)->intVal) + ",\n");
566         }
567     }
568     if (conditionMap_.count(WorkCondition::Type::DEEP_IDLE) > 0) {
569         result.append(string("\"isDeepIdle\":") +
570             to_string(conditionMap_.at(WorkCondition::Type::DEEP_IDLE)->boolVal) + ",\n");
571     }
572     result.append("},\n\"workInfo\":\n");
573     workInfo_->Dump(result);
574     result.append("}\n");
575     result.append("\n");
576 }
577 
ToString(WorkCondition::Type type)578 void WorkStatus::ToString(WorkCondition::Type type)
579 {
580     auto dataManager = DelayedSingleton<DataManager>::GetInstance();
581     if (dataManager->GetDeviceSleep()) {
582         if (dataManager->IsInDeviceStandyWhitelist(bundleName_)) {
583             conditionStatus_ += DELIMITER + COND_TYPE_STRING_MAP[WorkCondition::Type::STANDBY] + "&exemption";
584         }
585         conditionStatus_ += DELIMITER + COND_TYPE_STRING_MAP[WorkCondition::Type::STANDBY] + "&unExemption";
586     }
587     if (conditionStatus_.empty()) {
588         WS_HILOGE("eventType:%{public}s, conditionStatus is empty", COND_TYPE_STRING_MAP[type].c_str());
589         return;
590     }
591     WS_HILOGI("eventType:%{public}s,workStatus:%{public}s_%{public}s%{public}s", COND_TYPE_STRING_MAP[type].c_str(),
592         bundleName_.c_str(), workId_.c_str(), conditionStatus_.c_str());
593 }
594 } // namespace WorkScheduler
595 } // namespace OHOS