• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_policy_manager.h"
17 
18 #include <string>
19 #include <hisysevent.h>
20 #include <if_system_ability_manager.h>
21 #include <ipc_skeleton.h>
22 #include <iservice_registry.h>
23 #include <system_ability_definition.h>
24 #include "parameters.h"
25 #include "policy/app_data_clear_listener.h"
26 #include "work_scheduler_service.h"
27 #include "work_event_handler.h"
28 #include "work_sched_hilog.h"
29 #include "work_sched_errors.h"
30 #include "watchdog.h"
31 
32 using namespace std;
33 using namespace OHOS::AppExecFwk;
34 using namespace OHOS::HiviewDFX;
35 
36 namespace OHOS {
37 namespace WorkScheduler {
38 namespace {
39 const int32_t MAX_RUNNING_COUNT = 3;
40 const uint32_t MAX_WORK_COUNT_PER_UID = 10;
41 const int32_t DELAY_TIME_LONG = 30000;
42 const int32_t DELAY_TIME_SHORT = 5000;
43 const uint32_t MAX_WATCHDOG_ID = 1000;
44 const uint32_t INIT_WATCHDOG_ID = 1;
45 const int32_t INIT_DUMP_SET_MEMORY = -1;
46 const int32_t WATCHDOG_TIME = 2 * 60 * 1000;
47 const int32_t MEDIUM_WATCHDOG_TIME = 10 * 60 * 1000;
48 const int32_t LONG_WATCHDOG_TIME = 20 * 60 * 1000;
49 static int32_t g_lastWatchdogTime = WATCHDOG_TIME;
50 }
51 
WorkPolicyManager(const std::shared_ptr<WorkSchedulerService> & wss)52 WorkPolicyManager::WorkPolicyManager(const std::shared_ptr<WorkSchedulerService>& wss) : wss_(wss)
53 {
54     conditionReadyQueue_ = std::make_shared<WorkQueue>();
55     watchdogId_ = INIT_WATCHDOG_ID;
56     dumpSetMemory_ = INIT_DUMP_SET_MEMORY;
57     watchdogTime_ = WATCHDOG_TIME;
58 }
59 
Init(const std::shared_ptr<AppExecFwk::EventRunner> & runner)60 bool WorkPolicyManager::Init(const std::shared_ptr<AppExecFwk::EventRunner>& runner)
61 {
62     WS_HILOGD("Work policy manager init.");
63     if (wss_.expired()) {
64         WS_HILOGE("wss_ expired");
65         return false;
66     }
67     workConnManager_ = make_shared<WorkConnManager>();
68     handler_ = wss_.lock()->GetHandler();
69     if (handler_ == nullptr) {
70         WS_HILOGE("failed due to handler_ is nullptr");
71         return false;
72     }
73     watchdog_ = std::make_shared<Watchdog>(wss_.lock()->GetWorkPolicyManager(), runner);
74     return true;
75 }
76 
AddPolicyFilter(shared_ptr<IPolicyFilter> filter)77 void WorkPolicyManager::AddPolicyFilter(shared_ptr<IPolicyFilter> filter)
78 {
79     policyFilters_.emplace_back(filter);
80 }
81 
AddAppDataClearListener(std::shared_ptr<AppDataClearListener> listener)82 void WorkPolicyManager::AddAppDataClearListener(std::shared_ptr<AppDataClearListener> listener)
83 {
84     appDataClearListener_ = listener;
85     appDataClearListener_->Start();
86 }
87 
AddWork(shared_ptr<WorkStatus> workStatus,int32_t uid)88 int32_t WorkPolicyManager::AddWork(shared_ptr<WorkStatus> workStatus, int32_t uid)
89 {
90     WS_HILOGD("Add work");
91     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
92     if (uidQueueMap_.count(uid) > 0) {
93         if (uidQueueMap_.at(uid)->Contains(make_shared<string>(workStatus->workId_))) {
94             WS_HILOGE("Workid has been added, should remove first.");
95             return E_ADD_REPEAT_WORK_ERR;
96         } else if (uidQueueMap_.at(uid)->GetSize() >= MAX_WORK_COUNT_PER_UID) {
97             WS_HILOGE("each uid only can be added %{public}u works", MAX_WORK_COUNT_PER_UID);
98             return E_WORK_EXCEED_UPPER_LIMIT;
99         }
100         uidQueueMap_.at(uid)->Push(workStatus);
101     } else {
102         WS_HILOGD("uidQueue(%{public}d) not exists, create", uid);
103         uidQueueMap_.emplace(uid, make_shared<WorkQueue>());
104         uidQueueMap_.at(uid)->Push(workStatus);
105     }
106 
107     // Notify work add event to battery statistics
108     int32_t pid = IPCSkeleton::GetCallingPid();
109     string conditions = "";
110     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::NETWORK) > 0) {
111         conditions.append("NETWORK-");
112     }
113 
114     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::CHARGER) > 0) {
115         conditions.append("CHARGER-");
116     }
117 
118     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::BATTERY_STATUS) > 0) {
119         conditions.append("BATTERY_STATUS-");
120     }
121 
122     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::BATTERY_LEVEL) > 0) {
123         conditions.append("BATTERY_LEVEL-");
124     }
125 
126     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::STORAGE) > 0) {
127         conditions.append("STORAGE-");
128     }
129 
130     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::TIMER) > 0) {
131         conditions.append("TIMER-");
132     }
133     conditions.pop_back();
134 
135     string type = "Repeat";
136     if (!workStatus->workInfo_->IsRepeat()) {
137         type = "Not Repeat";
138     }
139 
140     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::WORK_SCHEDULER,
141         "WORK_ADD", HiSysEvent::EventType::STATISTIC, "UID", uid,
142         "PID", pid, "NAME", workStatus->bundleName_, "WORKID", workStatus->workId_, "TRIGGER", conditions, "TYPE",
143         type, "INTERVAL", workStatus->workInfo_->GetTimeInterval());
144 
145     WS_HILOGI("push workStatus ID: %{public}s to uidQueue(%{public}d)", workStatus->workId_.c_str(), uid);
146     return ERR_OK;
147 }
148 
RemoveWork(shared_ptr<WorkStatus> workStatus,int32_t uid)149 bool WorkPolicyManager::RemoveWork(shared_ptr<WorkStatus> workStatus, int32_t uid)
150 {
151     WS_HILOGD("Remove work.");
152     bool ret = false;
153     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
154     if (uidQueueMap_.count(uid) > 0) {
155         WS_HILOGD("Remove workStatus ID: %{public}s form uidQueue(%{public}d)", workStatus->workId_.c_str(), uid);
156         ret = uidQueueMap_.at(uid)->Remove(workStatus);
157         if (uidQueueMap_.count(uid) <= 0) {
158             uidQueueMap_.erase(uid);
159         }
160     }
161     return ret;
162 }
163 
FindWorkStatus(WorkInfo & workInfo,int32_t uid)164 shared_ptr<WorkStatus> WorkPolicyManager::FindWorkStatus(WorkInfo& workInfo, int32_t uid)
165 {
166     WS_HILOGD("Find work status start.");
167     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
168     if (uidQueueMap_.count(uid) > 0) {
169         return uidQueueMap_.at(uid)->Find(WorkStatus::MakeWorkId(workInfo.GetWorkId(), uid));
170     }
171     return nullptr;
172 }
173 
RemoveFromUidQueue(std::shared_ptr<WorkStatus> workStatus,int32_t uid)174 void WorkPolicyManager::RemoveFromUidQueue(std::shared_ptr<WorkStatus> workStatus, int32_t uid)
175 {
176     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
177     if (uidQueueMap_.count(uid) > 0) {
178         uidQueueMap_.at(uid)->CancelWork(workStatus);
179         if (uidQueueMap_.at(uid)->GetSize() <= 0) {
180             uidQueueMap_.erase(uid);
181         }
182     }
183 }
184 
RemoveFromReadyQueue(std::shared_ptr<WorkStatus> workStatus)185 void WorkPolicyManager::RemoveFromReadyQueue(std::shared_ptr<WorkStatus> workStatus)
186 {
187     conditionReadyQueue_->RemoveUnReady();
188 }
189 
StopWork(std::shared_ptr<WorkStatus> workStatus,int32_t uid,const bool needCancel,bool isTimeOut)190 bool WorkPolicyManager::StopWork(std::shared_ptr<WorkStatus> workStatus, int32_t uid,
191     const bool needCancel, bool isTimeOut)
192 {
193     WS_HILOGD("enter");
194     bool hasCanceled = false;
195     if (workStatus->IsRunning()) {
196         workStatus->lastTimeout_ = isTimeOut;
197         workConnManager_->StopWork(workStatus);
198         if (!workStatus->IsRepeating()) {
199             workStatus->MarkStatus(WorkStatus::Status::REMOVED);
200             RemoveFromUidQueue(workStatus, uid);
201             RemoveFromReadyQueue(workStatus);
202             hasCanceled = true;
203         } else {
204             workStatus->MarkStatus(WorkStatus::Status::WAIT_CONDITION);
205         }
206     }
207 
208     if (!hasCanceled && needCancel) {
209         RemoveFromUidQueue(workStatus, uid);
210         RemoveFromReadyQueue(workStatus);
211         hasCanceled = true;
212     }
213 
214     CheckWorkToRun();
215     return hasCanceled;
216 }
217 
StopAndClearWorks(int32_t uid)218 bool WorkPolicyManager::StopAndClearWorks(int32_t uid)
219 {
220     WS_HILOGD("enter");
221     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
222     if (uidQueueMap_.count(uid) > 0) {
223         auto queue = uidQueueMap_.at(uid);
224         for (auto it : queue->GetWorkList()) {
225             workConnManager_->StopWork(it);
226             it->MarkStatus(WorkStatus::Status::REMOVED);
227             RemoveFromReadyQueue(it);
228         }
229         queue->ClearAll();
230         uidQueueMap_.erase(uid);
231     }
232     CheckWorkToRun();
233     return true;
234 }
235 
IsLastWorkTimeout(int32_t workId,int32_t uid,bool & result)236 int32_t WorkPolicyManager::IsLastWorkTimeout(int32_t workId, int32_t uid, bool &result)
237 {
238     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
239     string workIdStr = WorkStatus::MakeWorkId(workId, uid);
240     if (uidQueueMap_.count(uid) > 0) {
241         shared_ptr<WorkStatus> workStatus = uidQueueMap_.at(uid)->Find(workIdStr);
242         if (workStatus != nullptr) {
243             return workStatus->IsLastWorkTimeout();
244         }
245     }
246     return E_WORK_NOT_EXIST_FAILED;
247 }
248 
OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)249 void WorkPolicyManager::OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)
250 {
251     WS_HILOGD("enter");
252     if (workStatusVector == nullptr) {
253         return;
254     }
255     AddToReadyQueue(workStatusVector);
256     CheckWorkToRun();
257 }
258 
AddToReadyQueue(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)259 void WorkPolicyManager::AddToReadyQueue(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)
260 {
261     conditionReadyQueue_->Push(workStatusVector);
262 }
263 
GetMaxRunningCount()264 int32_t WorkPolicyManager::GetMaxRunningCount()
265 {
266     int32_t currentMaxRunning = MAX_RUNNING_COUNT;
267     for (auto policyFilter : policyFilters_) {
268         int32_t policyMaxRunning = policyFilter->GetPolicyMaxRunning();
269         if (policyMaxRunning < currentMaxRunning) {
270             currentMaxRunning = policyMaxRunning;
271         }
272     }
273     return currentMaxRunning;
274 }
275 
GetRunningCount()276 int32_t WorkPolicyManager::GetRunningCount()
277 {
278     WS_HILOGD("enter");
279     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
280     int32_t count = 0;
281     auto it = uidQueueMap_.begin();
282     while (it != uidQueueMap_.end()) {
283         count += it->second->GetRunningCount();
284         it++;
285     }
286     return count;
287 }
288 
OnPolicyChanged(PolicyType policyType,shared_ptr<DetectorValue> detectorVal)289 void WorkPolicyManager::OnPolicyChanged(PolicyType policyType, shared_ptr<DetectorValue> detectorVal)
290 {
291     WS_HILOGD("enter");
292     if (wss_.expired()) {
293         WS_HILOGE("wss_ expired");
294         return;
295     }
296     switch (policyType) {
297         case PolicyType::APP_REMOVED: {
298             int32_t uid = detectorVal->intVal;
299             WorkStatus::ClearUidLastTimeMap(uid);
300             [[fallthrough]];
301         }
302         case PolicyType::APP_DATA_CLEAR: {
303             wss_.lock()->StopAndClearWorksByUid(detectorVal->intVal);
304             break;
305         }
306         default: {}
307     }
308     CheckWorkToRun();
309 }
310 
IsSpecialScene(std::shared_ptr<WorkStatus> topWork)311 bool WorkPolicyManager::IsSpecialScene(std::shared_ptr<WorkStatus> topWork)
312 {
313     return (OHOS::system::GetIntParameter("const.debuggable", 0) == 1) &&
314         (topWork->bundleName_ == "com.huawei.hmos.hiviewx");
315 }
316 
CheckWorkToRun()317 void WorkPolicyManager::CheckWorkToRun()
318 {
319     WS_HILOGD("Check work to run.");
320     RemoveAllUnReady();
321     if (handler_ == nullptr) {
322         WS_HILOGE("handler lock() returns nullptr");
323         return;
324     }
325     handler_->RemoveEvent(WorkEventHandler::RETRIGGER_MSG);
326     shared_ptr<WorkStatus> topWork = GetWorkToRun();
327     if (topWork == nullptr) {
328         WS_HILOGD("no condition ready work not running, return.");
329         return;
330     }
331     if (GetRunningCount() < GetMaxRunningCount() || IsSpecialScene(topWork)) {
332         WS_HILOGD("running count < max running count");
333         RealStartWork(topWork);
334         SendRetrigger(DELAY_TIME_SHORT);
335     } else {
336         WS_HILOGD("trigger delay: %{public}d", DELAY_TIME_LONG);
337         SendRetrigger(DELAY_TIME_LONG);
338     }
339     WS_HILOGD("out");
340 }
341 
RemoveAllUnReady()342 void WorkPolicyManager::RemoveAllUnReady()
343 {
344     conditionReadyQueue_->RemoveUnReady();
345 }
346 
GetWorkToRun()347 std::shared_ptr<WorkStatus> WorkPolicyManager::GetWorkToRun()
348 {
349     shared_ptr<WorkStatus> topWork = conditionReadyQueue_->GetWorkToRunByPriority();
350     return topWork;
351 }
352 
RealStartWork(std::shared_ptr<WorkStatus> topWork)353 void WorkPolicyManager::RealStartWork(std::shared_ptr<WorkStatus> topWork)
354 {
355     WS_HILOGD("RealStartWork topWork ID: %{public}s", topWork->workId_.c_str());
356     if (wss_.expired()) {
357         WS_HILOGE("wss_ expired");
358         return;
359     }
360     UpdateWatchdogTime(wss_.lock(), topWork);
361     topWork->MarkStatus(WorkStatus::Status::RUNNING);
362     wss_.lock()->UpdateWorkBeforeRealStart(topWork);
363     RemoveFromReadyQueue(topWork);
364     bool ret = workConnManager_->StartWork(topWork);
365     if (ret) {
366         AddWatchdogForWork(topWork);
367         topWork->UpdateUidLastTimeMap();
368     } else {
369         if (!topWork->IsRepeating()) {
370             topWork->MarkStatus(WorkStatus::Status::REMOVED);
371             RemoveFromUidQueue(topWork, topWork->uid_);
372         } else {
373             topWork->MarkStatus(WorkStatus::Status::WAIT_CONDITION);
374         }
375     }
376 }
377 
UpdateWatchdogTime(const std::shared_ptr<WorkSchedulerService> & wmsptr,std::shared_ptr<WorkStatus> & topWork)378 void WorkPolicyManager::UpdateWatchdogTime(const std::shared_ptr<WorkSchedulerService> &wmsptr,
379     std::shared_ptr<WorkStatus> &topWork)
380 {
381     if (!wmsptr->CheckEffiResApplyInfo(topWork->uid_)) {
382         SetWatchdogTime(g_lastWatchdogTime);
383         return;
384     }
385     int32_t chargerStatus = 0;
386     auto iter = topWork->conditionMap_.find(WorkCondition::Type::CHARGER);
387     if (iter != topWork->conditionMap_.end() && iter->second) {
388         chargerStatus = topWork->conditionMap_.at(WorkCondition::Type::CHARGER)->enumVal;
389     } else {
390         WS_HILOGD("charger is in CHARGING_UNKNOWN status");
391         chargerStatus = static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNKNOWN);
392     }
393     if (chargerStatus == static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNPLUGGED)
394         || chargerStatus == static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNKNOWN)) {
395         WS_HILOGD("charger is in CHARGING_UNKNOWN or CHARGING_UNPLUGGED status");
396         SetWatchdogTime(MEDIUM_WATCHDOG_TIME);
397     } else {
398         WS_HILOGD("charger is in CHARGING status");
399         SetWatchdogTime(LONG_WATCHDOG_TIME);
400     }
401 }
402 
AddWatchdogForWork(std::shared_ptr<WorkStatus> workStatus)403 void WorkPolicyManager::AddWatchdogForWork(std::shared_ptr<WorkStatus> workStatus)
404 {
405     uint32_t watchId = NewWatchdogId();
406     WS_HILOGI("AddWatchdog, watchId:%{public}u, bundleName:%{public}s, workId:%{public}s, watchdogTime:%{public}d",
407         watchId, workStatus->bundleName_.c_str(), workStatus->workId_.c_str(), watchdogTime_);
408     watchdog_->AddWatchdog(watchId, watchdogTime_);
409     std::lock_guard<std::mutex> lock(watchdogIdMapMutex_);
410     watchdogIdMap_.emplace(watchId, workStatus);
411 }
412 
SendRetrigger(int32_t delaytime)413 void WorkPolicyManager::SendRetrigger(int32_t delaytime)
414 {
415     WS_HILOGD("enter");
416     if (handler_ == nullptr) {
417         return;
418     }
419     WS_HILOGD("delay = %{public}d", delaytime);
420     handler_->SendEvent(InnerEvent::Get(WorkEventHandler::RETRIGGER_MSG, 0), delaytime);
421 }
422 
WatchdogTimeOut(uint32_t watchdogId)423 void WorkPolicyManager::WatchdogTimeOut(uint32_t watchdogId)
424 {
425     if (wss_.expired()) {
426         WS_HILOGE("wss_ expired");
427         return;
428     }
429     std::shared_ptr<WorkStatus> workStatus = GetWorkFromWatchdog(watchdogId);
430     WS_HILOGI("WatchdogTimeOut, watchId:%{public}u, bundleName:%{public}s, workId:%{public}s",
431         watchdogId, workStatus->bundleName_.c_str(), workStatus->workId_.c_str());
432     wss_.lock()->WatchdogTimeOut(workStatus);
433 }
434 
GetWorkFromWatchdog(uint32_t id)435 std::shared_ptr<WorkStatus> WorkPolicyManager::GetWorkFromWatchdog(uint32_t id)
436 {
437     std::lock_guard<std::mutex> lock(watchdogIdMapMutex_);
438     return watchdogIdMap_.at(id);
439 }
440 
ObtainAllWorks(int32_t & uid)441 list<shared_ptr<WorkInfo>> WorkPolicyManager::ObtainAllWorks(int32_t &uid)
442 {
443     WS_HILOGD("Wenter");
444     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
445     list<shared_ptr<WorkInfo>> allWorks;
446     if (uidQueueMap_.count(uid) > 0) {
447         auto queue = uidQueueMap_.at(uid);
448         auto allWorkStatus = queue->GetWorkList();
449         std::transform(allWorkStatus.begin(), allWorkStatus.end(), std::back_inserter(allWorks),
450             [](std::shared_ptr<WorkStatus> it) { return it->workInfo_; });
451     }
452     return allWorks;
453 }
454 
GetWorkStatus(int32_t & uid,int32_t & workId)455 shared_ptr<WorkInfo> WorkPolicyManager::GetWorkStatus(int32_t &uid, int32_t &workId)
456 {
457     WS_HILOGD("enter");
458     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
459     if (uidQueueMap_.count(uid) > 0) {
460         auto queue = uidQueueMap_.at(uid);
461         auto workStatus = queue->Find(string("u") + to_string(uid) + "_" + to_string(workId));
462         if (workStatus != nullptr) {
463             return workStatus->workInfo_;
464         }
465     }
466     return nullptr;
467 }
468 
GetAllWorkStatus(int32_t & uid)469 list<std::shared_ptr<WorkStatus>> WorkPolicyManager::GetAllWorkStatus(int32_t &uid)
470 {
471     WS_HILOGD("enter");
472     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
473     list<shared_ptr<WorkStatus>> allWorks;
474     if (uidQueueMap_.count(uid) > 0) {
475         allWorks = uidQueueMap_.at(uid)->GetWorkList();
476     }
477     return allWorks;
478 }
479 
GetAllRunningWorks()480 std::list<std::shared_ptr<WorkInfo>> WorkPolicyManager::GetAllRunningWorks()
481 {
482     WS_HILOGD("enter");
483     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
484     list<shared_ptr<WorkInfo>> allWorks;
485     auto it = uidQueueMap_.begin();
486     while (it != uidQueueMap_.end()) {
487         std::list<std::shared_ptr<WorkInfo>> workList = it->second->GetRunningWorks();
488         allWorks.insert(allWorks.end(), workList.begin(), workList.end());
489         it++;
490     }
491     return allWorks;
492 }
493 
DumpConditionReadyQueue(string & result)494 void WorkPolicyManager::DumpConditionReadyQueue(string& result)
495 {
496     conditionReadyQueue_->Dump(result);
497 }
498 
DumpUidQueueMap(string & result)499 void WorkPolicyManager::DumpUidQueueMap(string& result)
500 {
501     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
502     for (auto it : uidQueueMap_) {
503         result.append("uid: " + std::to_string(it.first) + ":\n");
504         it.second->Dump(result);
505     }
506 }
507 
Dump(string & result)508 void WorkPolicyManager::Dump(string& result)
509 {
510     WS_HILOGI("enter");
511     result.append("1. workPolicyManager conditionReadyQueue:\n");
512     DumpConditionReadyQueue(result);
513     result.append("\n");
514 
515     result.append("2. workPolicyManager uidQueueMap:\n");
516     DumpUidQueueMap(result);
517 
518     result.append("3. GetMaxRunningCount:");
519     result.append(to_string(GetMaxRunningCount()) + "\n");
520 }
521 
NewWatchdogId()522 uint32_t WorkPolicyManager::NewWatchdogId()
523 {
524     if (watchdogId_ == MAX_WATCHDOG_ID) {
525         watchdogId_ = INIT_WATCHDOG_ID;
526     }
527     return watchdogId_++;
528 }
529 
GetDumpSetMemory()530 int32_t WorkPolicyManager::GetDumpSetMemory()
531 {
532     return dumpSetMemory_;
533 }
534 
SetMemoryByDump(int32_t memory)535 void WorkPolicyManager::SetMemoryByDump(int32_t memory)
536 {
537     dumpSetMemory_ = memory;
538 }
539 
SetWatchdogTimeByDump(int32_t time)540 void WorkPolicyManager::SetWatchdogTimeByDump(int32_t time)
541 {
542     WS_HILOGD("Set watchdog time by dump to %{public}d", time);
543     watchdogTime_ = time == 0 ? WATCHDOG_TIME : time;
544     g_lastWatchdogTime = watchdogTime_;
545 }
546 
SetWatchdogTime(int32_t time)547 void WorkPolicyManager::SetWatchdogTime(int32_t time)
548 {
549     watchdogTime_ = time;
550 }
551 
GetWatchdogTime()552 int32_t WorkPolicyManager::WorkPolicyManager::GetWatchdogTime()
553 {
554     return watchdogTime_;
555 }
556 
DumpCheckIdeWorkToRun(const std::string & bundleName,const std::string & abilityName)557 void WorkPolicyManager::DumpCheckIdeWorkToRun(const std::string &bundleName, const std::string &abilityName)
558 {
559     std::lock_guard<std::recursive_mutex> lock(ideDebugListMutex_);
560     ideDebugList = GetAllIdeWorkStatus(bundleName, abilityName);
561     if (ideDebugList.empty()) {
562         WS_HILOGE("ideDebugList is empty, please add one work");
563         return;
564     }
565     SendIdeWorkRetriggerEvent(0);
566 }
567 
TriggerIdeWork()568 void WorkPolicyManager::TriggerIdeWork()
569 {
570     std::lock_guard<std::recursive_mutex> lock(ideDebugListMutex_);
571     if (ideDebugList.empty()) {
572         WS_HILOGI("ideDebugList has been empty, all the works have been done");
573         return;
574     }
575 
576     auto topWork = ideDebugList.front();
577     ideDebugList.pop_front();
578     if (topWork->IsRunning()) {
579         SendIdeWorkRetriggerEvent(g_lastWatchdogTime + DELAY_TIME_SHORT);
580         return;
581     }
582     topWork->MarkStatus(WorkStatus::Status::RUNNING);
583     bool ret = workConnManager_->StartWork(topWork);
584     if (ret) {
585         WS_HILOGI("TriggerIdeWork ok");
586         int time = watchdogTime_;
587         watchdogTime_ = g_lastWatchdogTime;
588         AddWatchdogForWork(topWork);
589         watchdogTime_ = time;
590     } else {
591         WS_HILOGE("TriggerIdeWork error");
592         ideDebugList.clear();
593         return;
594     }
595     SendIdeWorkRetriggerEvent(g_lastWatchdogTime + DELAY_TIME_SHORT);
596 }
597 
SendIdeWorkRetriggerEvent(int32_t delaytime)598 void WorkPolicyManager::SendIdeWorkRetriggerEvent(int32_t delaytime)
599 {
600     if (handler_ == nullptr) {
601         WS_HILOGE("handle is nullptr");
602         return;
603     }
604     handler_->SendEvent(InnerEvent::Get(WorkEventHandler::IDE_RETRIGGER_MSG, 0), delaytime);
605 }
606 
GetAllIdeWorkStatus(const std::string & bundleName,const std::string & abilityName)607 std::list<std::shared_ptr<WorkStatus>> WorkPolicyManager::GetAllIdeWorkStatus(const std::string &bundleName,
608     const std::string &abilityName)
609 {
610     std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
611     std::list<shared_ptr<WorkStatus>> allWorks;
612     auto it = uidQueueMap_.begin();
613     while (it != uidQueueMap_.end()) {
614         if (it->second->GetWorkList().empty()) {
615             it++;
616             continue;
617         }
618         auto work = it->second->GetWorkList().front();
619         if (work->workInfo_->GetBundleName() != bundleName || work->workInfo_->GetAbilityName() != abilityName) {
620             it++;
621             continue;
622         }
623         allWorks = uidQueueMap_.at(work->uid_)->GetWorkList();
624         return allWorks;
625     }
626     return allWorks;
627 }
628 } // namespace WorkScheduler
629 } // namespace OHOS
630