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