• 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 "work_sched_utils.h"
31 #include "watchdog.h"
32 #include "work_sched_data_manager.h"
33 #include <cinttypes>
34 
35 using namespace std;
36 using namespace OHOS::AppExecFwk;
37 using namespace OHOS::HiviewDFX;
38 
39 namespace OHOS {
40 namespace WorkScheduler {
41 namespace {
42 const int32_t MAX_RUNNING_COUNT = 3;
43 const int32_t STANDBY_MAX_RUNNING_COUNT = 2 * MAX_RUNNING_COUNT;
44 const uint32_t MAX_WORK_COUNT_PER_UID = 10;
45 const int32_t DELAY_TIME_LONG = 30000;
46 const int32_t DELAY_TIME_SHORT = 5000;
47 const uint32_t MAX_WATCHDOG_ID = 1000;
48 const uint32_t INIT_WATCHDOG_ID = 1;
49 const int32_t INIT_DUMP_SET_MEMORY = -1;
50 const int32_t WATCHDOG_TIME = 2 * 60 * 1000;
51 const int32_t MEDIUM_WATCHDOG_TIME = 10 * 60 * 1000;
52 const int32_t LONG_WATCHDOG_TIME = 20 * 60 * 1000;
53 const int32_t INIT_DUMP_SET_CPU = 0;
54 const int32_t INVALID_VALUE = -1;
55 const int32_t DUMP_SET_MAX_COUNT_LIMIT = 100;
56 static int32_t g_lastWatchdogTime = WATCHDOG_TIME;
57 }
58 
WorkPolicyManager(const std::shared_ptr<WorkSchedulerService> & wss)59 WorkPolicyManager::WorkPolicyManager(const std::shared_ptr<WorkSchedulerService>& wss) : wss_(wss)
60 {
61     conditionReadyQueue_ = std::make_shared<WorkQueue>();
62     watchdogId_ = INIT_WATCHDOG_ID;
63     dumpSetMemory_ = INIT_DUMP_SET_MEMORY;
64     watchdogTime_ = WATCHDOG_TIME;
65     dumpSetCpu_ = INIT_DUMP_SET_CPU;
66     dumpSetMaxRunningCount_ = INVALID_VALUE;
67 }
68 
Init(const std::shared_ptr<AppExecFwk::EventRunner> & runner)69 bool WorkPolicyManager::Init(const std::shared_ptr<AppExecFwk::EventRunner>& runner)
70 {
71     WS_HILOGD("Work policy manager init.");
72     if (wss_.expired()) {
73         WS_HILOGE("wss_ expired");
74         return false;
75     }
76     workConnManager_ = make_shared<WorkConnManager>();
77     handler_ = wss_.lock()->GetHandler();
78     if (handler_ == nullptr) {
79         WS_HILOGE("failed due to handler_ is nullptr");
80         return false;
81     }
82     watchdog_ = std::make_shared<Watchdog>(wss_.lock()->GetWorkPolicyManager(), runner);
83     return true;
84 }
85 
AddPolicyFilter(shared_ptr<IPolicyFilter> filter)86 void WorkPolicyManager::AddPolicyFilter(shared_ptr<IPolicyFilter> filter)
87 {
88     policyFilters_.emplace_back(filter);
89 }
90 
AddAppDataClearListener(std::shared_ptr<AppDataClearListener> listener)91 void WorkPolicyManager::AddAppDataClearListener(std::shared_ptr<AppDataClearListener> listener)
92 {
93     appDataClearListener_ = listener;
94     appDataClearListener_->Start();
95 }
96 
97 
GetConditionString(const shared_ptr<WorkStatus> workStatus)98 std::string WorkPolicyManager::GetConditionString(const shared_ptr<WorkStatus> workStatus)
99 {
100     string conditions = "";
101     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::NETWORK) > 0) {
102         conditions.append("NETWORK-");
103     }
104 
105     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::CHARGER) > 0) {
106         conditions.append("CHARGER-");
107     }
108 
109     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::BATTERY_STATUS) > 0) {
110         conditions.append("BATTERY_STATUS-");
111     }
112 
113     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::BATTERY_LEVEL) > 0) {
114         conditions.append("BATTERY_LEVEL-");
115     }
116 
117     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::STORAGE) > 0) {
118         conditions.append("STORAGE-");
119     }
120 
121     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::TIMER) > 0) {
122         conditions.append("TIMER-");
123     }
124 
125     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::DEEP_IDLE) > 0) {
126         conditions.append("DEEP_IDLE-");
127     }
128     conditions.pop_back();
129     return conditions;
130 }
131 
AddWork(shared_ptr<WorkStatus> workStatus,int32_t uid)132 int32_t WorkPolicyManager::AddWork(shared_ptr<WorkStatus> workStatus, int32_t uid)
133 {
134     WS_HILOGD("Add work");
135     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
136     if (uidQueueMap_.count(uid) > 0) {
137         if (uidQueueMap_.at(uid)->Contains(make_shared<string>(workStatus->workId_))) {
138             WS_HILOGD("Workid has been added, should remove first.");
139             return E_ADD_REPEAT_WORK_ERR;
140         } else if (uidQueueMap_.at(uid)->GetSize() >= MAX_WORK_COUNT_PER_UID) {
141             WS_HILOGE("each uid only can be added %{public}u works", MAX_WORK_COUNT_PER_UID);
142             return E_WORK_EXCEED_UPPER_LIMIT;
143         }
144         uidQueueMap_.at(uid)->Push(workStatus);
145     } else {
146         WS_HILOGD("uidQueue(%{public}d) not exists, create", uid);
147         uidQueueMap_.emplace(uid, make_shared<WorkQueue>());
148         uidQueueMap_.at(uid)->Push(workStatus);
149     }
150 
151     // Notify work add event to battery statistics
152     int32_t pid = IPCSkeleton::GetCallingPid();
153     string type = "Repeat";
154     if (!workStatus->workInfo_->IsRepeat()) {
155         type = "Not Repeat";
156     }
157 
158     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::WORK_SCHEDULER,
159         "WORK_ADD", HiSysEvent::EventType::STATISTIC, "UID", uid, "PID", pid,
160         "NAME", workStatus->bundleName_, "WORKID", workStatus->workId_, "TRIGGER", GetConditionString(workStatus),
161         "TYPE", type, "INTERVAL", workStatus->workInfo_->GetTimeInterval());
162 
163     WS_HILOGI("push workStatus ID: %{public}s to uidQueue(%{public}d)", workStatus->workId_.c_str(), uid);
164     return ERR_OK;
165 }
166 
RemoveWork(shared_ptr<WorkStatus> workStatus,int32_t uid)167 bool WorkPolicyManager::RemoveWork(shared_ptr<WorkStatus> workStatus, int32_t uid)
168 {
169     WS_HILOGD("Remove work.");
170     bool ret = false;
171     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
172     if (uidQueueMap_.count(uid) > 0) {
173         WS_HILOGD("Remove workStatus ID: %{public}s form uidQueue(%{public}d)", workStatus->workId_.c_str(), uid);
174         ret = uidQueueMap_.at(uid)->Remove(workStatus);
175         if (uidQueueMap_.count(uid) <= 0) {
176             uidQueueMap_.erase(uid);
177         }
178     }
179     return ret;
180 }
181 
FindWorkStatus(WorkInfo & workInfo,int32_t uid)182 shared_ptr<WorkStatus> WorkPolicyManager::FindWorkStatus(WorkInfo& workInfo, int32_t uid)
183 {
184     WS_HILOGD("Find work status start.");
185     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
186     if (uidQueueMap_.count(uid) > 0) {
187         return uidQueueMap_.at(uid)->Find(WorkStatus::MakeWorkId(workInfo.GetWorkId(), uid));
188     }
189     return nullptr;
190 }
191 
FindSA(int32_t saId,int32_t uid)192 shared_ptr<WorkStatus> WorkPolicyManager::FindSA(int32_t saId, int32_t uid)
193 {
194     WS_HILOGD("Find SA, saId:%{public}d, uid:%{public}d", saId, uid);
195     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
196     if (uidQueueMap_.count(uid) > 0) {
197         return uidQueueMap_.at(uid)->FindSA(saId);
198     }
199     return nullptr;
200 }
201 
RemoveFromUidQueue(std::shared_ptr<WorkStatus> workStatus,int32_t uid)202 void WorkPolicyManager::RemoveFromUidQueue(std::shared_ptr<WorkStatus> workStatus, int32_t uid)
203 {
204     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
205     if (uidQueueMap_.count(uid) > 0) {
206         uidQueueMap_.at(uid)->CancelWork(workStatus);
207         if (uidQueueMap_.at(uid)->GetSize() <= 0) {
208             uidQueueMap_.erase(uid);
209         }
210     }
211 }
212 
RemoveFromReadyQueue(std::shared_ptr<WorkStatus> workStatus)213 void WorkPolicyManager::RemoveFromReadyQueue(std::shared_ptr<WorkStatus> workStatus)
214 {
215     conditionReadyQueue_->RemoveUnReady();
216 }
217 
StopWork(std::shared_ptr<WorkStatus> workStatus,int32_t uid,const bool needCancel,bool isTimeOut)218 bool WorkPolicyManager::StopWork(std::shared_ptr<WorkStatus> workStatus, int32_t uid,
219     const bool needCancel, bool isTimeOut)
220 {
221     WS_HILOGD("enter");
222     bool hasCanceled = false;
223     if (workStatus->IsRunning()) {
224         workStatus->lastTimeout_ = isTimeOut;
225         workConnManager_->StopWork(workStatus, isTimeOut);
226         if (!workStatus->IsRepeating()) {
227             workStatus->MarkStatus(WorkStatus::Status::REMOVED);
228             RemoveFromUidQueue(workStatus, uid);
229             RemoveFromReadyQueue(workStatus);
230             hasCanceled = true;
231         } else {
232             workStatus->workStartTime_ = 0;
233             workStatus->workWatchDogTime_ = 0;
234             workStatus->duration_ = 0;
235             workStatus->MarkStatus(WorkStatus::Status::WAIT_CONDITION);
236         }
237     }
238 
239     if (!hasCanceled && needCancel) {
240         RemoveFromUidQueue(workStatus, uid);
241         RemoveFromReadyQueue(workStatus);
242         hasCanceled = true;
243     }
244     if (isTimeOut && (workStatus->GetStatus() == WorkStatus::Status::REMOVED)) {
245         WS_HILOGI("disconect %{public}s when timeout", workStatus->workId_.c_str());
246         workStatus->lastTimeout_ = isTimeOut;
247         workConnManager_->StopWork(workStatus, isTimeOut);
248     }
249     CheckWorkToRun();
250     return hasCanceled;
251 }
252 
StopAndClearWorks(int32_t uid)253 bool WorkPolicyManager::StopAndClearWorks(int32_t uid)
254 {
255     WS_HILOGD("enter");
256     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
257     auto iter = uidQueueMap_.find(uid);
258     if (iter != uidQueueMap_.end()) {
259         auto queue = iter->second;
260         if (!queue) {
261             WS_HILOGE("StopAndClearWorks failed, queue is nullptr");
262             return false;
263         }
264         for (auto it : queue->GetWorkList()) {
265             workConnManager_->StopWork(it, false);
266             it->MarkStatus(WorkStatus::Status::REMOVED);
267             RemoveFromReadyQueue(it);
268         }
269         queue->ClearAll();
270         uidQueueMap_.erase(uid);
271     }
272     CheckWorkToRun();
273     return true;
274 }
275 
IsLastWorkTimeout(int32_t workId,int32_t uid,bool & result)276 int32_t WorkPolicyManager::IsLastWorkTimeout(int32_t workId, int32_t uid, bool &result)
277 {
278     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
279     string workIdStr = WorkStatus::MakeWorkId(workId, uid);
280     if (uidQueueMap_.count(uid) > 0) {
281         auto queue = uidQueueMap_.at(uid);
282         if (!queue) {
283             WS_HILOGE("IsLastWorkTimeout failed, queue is nullptr");
284             return E_WORK_NOT_EXIST_FAILED;
285         }
286         shared_ptr<WorkStatus> workStatus = queue->Find(workIdStr);
287         if (workStatus != nullptr) {
288             return workStatus->IsLastWorkTimeout();
289         }
290     }
291     return E_WORK_NOT_EXIST_FAILED;
292 }
293 
OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)294 void WorkPolicyManager::OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)
295 {
296     WS_HILOGD("enter");
297     if (workStatusVector == nullptr) {
298         return;
299     }
300     AddToReadyQueue(workStatusVector);
301     CheckWorkToRun();
302 }
303 
AddToReadyQueue(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)304 void WorkPolicyManager::AddToReadyQueue(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)
305 {
306     conditionReadyQueue_->Push(workStatusVector);
307 }
308 
GetMaxRunningCount(std::string & policyName)309 int32_t WorkPolicyManager::GetMaxRunningCount(std::string& policyName)
310 {
311     int32_t currentMaxRunning = GetDumpSetMaxRunningCount();
312     if (currentMaxRunning > 0 && currentMaxRunning <= DUMP_SET_MAX_COUNT_LIMIT) {
313         return currentMaxRunning;
314     }
315     currentMaxRunning = MAX_RUNNING_COUNT;
316     for (auto policyFilter : policyFilters_) {
317         int32_t policyMaxRunning = policyFilter->GetPolicyMaxRunning();
318         if (policyMaxRunning < currentMaxRunning) {
319             currentMaxRunning = policyMaxRunning;
320             policyName = policyFilter->GetPolicyName();
321         }
322     }
323     return currentMaxRunning;
324 }
325 
GetRunningCount()326 int32_t WorkPolicyManager::GetRunningCount()
327 {
328     WS_HILOGD("enter");
329     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
330     int32_t count = 0;
331     auto it = uidQueueMap_.begin();
332     while (it != uidQueueMap_.end()) {
333         count += it->second->GetRunningCount();
334         it++;
335     }
336     return count;
337 }
338 
OnPolicyChanged(PolicyType policyType,shared_ptr<DetectorValue> detectorVal)339 void WorkPolicyManager::OnPolicyChanged(PolicyType policyType, shared_ptr<DetectorValue> detectorVal)
340 {
341     WS_HILOGD("enter");
342     if (wss_.expired()) {
343         WS_HILOGE("wss_ expired");
344         return;
345     }
346     auto service = wss_.lock();
347     if (!service) {
348         WS_HILOGE("service is null");
349         return;
350     }
351     switch (policyType) {
352         case PolicyType::USER_SWITCHED: {
353             service->InitPreinstalledWork();
354             break;
355         }
356         case PolicyType::APP_ADDED: {
357             if (!service->IsPreinstalledBundle(detectorVal->strVal)) {
358                 return;
359             }
360             service->InitPreinstalledWork();
361             break;
362         }
363         case PolicyType::APP_REMOVED: {
364             int32_t uid = detectorVal->intVal;
365             WorkStatus::ClearUidLastTimeMap(uid);
366             service->StopAndClearWorksByUid(detectorVal->intVal);
367             int32_t userId = WorkSchedUtils::GetUserIdByUid(uid);
368             DelayedSingleton<DataManager>::GetInstance()->ClearGroup(detectorVal->strVal, userId);
369             break;
370         }
371         default: {}
372     }
373     CheckWorkToRun();
374 }
375 
IsSpecialScene(std::shared_ptr<WorkStatus> topWork,int32_t runningCount)376 bool WorkPolicyManager::IsSpecialScene(std::shared_ptr<WorkStatus> topWork, int32_t runningCount)
377 {
378     if (OHOS::system::GetIntParameter("const.debuggable", 0) == 1 &&
379         wss_.lock()->IsExemptionBundle(topWork->bundleName_)) {
380         return true;
381     }
382     if (DelayedSingleton<DataManager>::GetInstance()->IsInDeviceStandyRestrictlist(topWork->bundleName_)) {
383         return false;
384     }
385     if (DelayedSingleton<DataManager>::GetInstance()->GetDeviceSleep() &&
386         runningCount < STANDBY_MAX_RUNNING_COUNT &&
387         DelayedSingleton<DataManager>::GetInstance()->IsInDeviceStandyWhitelist(topWork->bundleName_)) {
388         WS_HILOGI("device is in standy mode, and work %{public}s is in whitelist, allow to run",
389             topWork->bundleName_.c_str());
390         return true;
391     }
392     return false;
393 }
394 
CheckWorkToRun()395 void WorkPolicyManager::CheckWorkToRun()
396 {
397     WS_HILOGD("Check work to run.");
398     if (wss_.lock() == nullptr) {
399         WS_HILOGE("wss_ expired");
400         return;
401     }
402     RemoveAllUnReady();
403     if (handler_ == nullptr) {
404         WS_HILOGE("handler lock() returns nullptr");
405         return;
406     }
407     handler_->RemoveEvent(WorkEventHandler::RETRIGGER_MSG);
408     shared_ptr<WorkStatus> topWork = GetWorkToRun();
409     if (topWork == nullptr) {
410         WS_HILOGD("no condition ready work not running, return.");
411         return;
412     }
413     std::string policyName;
414     int32_t runningCount = GetRunningCount();
415     int32_t allowRunningCount = GetMaxRunningCount(policyName);
416     if (runningCount < allowRunningCount || IsSpecialScene(topWork, runningCount)) {
417         WS_HILOGD("running count < max running count");
418         if (topWork->workInfo_->IsSA()) {
419             RealStartSA(topWork);
420         } else {
421             RealStartWork(topWork);
422         }
423         SendRetrigger(DELAY_TIME_SHORT);
424     } else {
425         WS_HILOGD("trigger delay: %{public}d", DELAY_TIME_LONG);
426         if (runningCount == MAX_RUNNING_COUNT) {
427             policyName = "OVER_LIMIT";
428         }
429 
430         if (!policyName.empty()) {
431             topWork->delayReason_= policyName;
432             WS_HILOGI("trigger delay, reason: %{public}s, bundleName: %{public}s, runningCount:%{public}d,"
433                 " allowRunningCount:%{public}d",
434                 policyName.c_str(), topWork->bundleName_.c_str(), runningCount, allowRunningCount);
435         }
436         SendRetrigger(DELAY_TIME_LONG);
437     }
438     WS_HILOGD("out");
439 }
440 
RemoveAllUnReady()441 void WorkPolicyManager::RemoveAllUnReady()
442 {
443     conditionReadyQueue_->RemoveUnReady();
444 }
445 
GetWorkToRun()446 std::shared_ptr<WorkStatus> WorkPolicyManager::GetWorkToRun()
447 {
448     shared_ptr<WorkStatus> topWork = conditionReadyQueue_->GetWorkToRunByPriority();
449     return topWork;
450 }
451 
RealStartSA(std::shared_ptr<WorkStatus> topWork)452 void WorkPolicyManager::RealStartSA(std::shared_ptr<WorkStatus> topWork)
453 {
454     WS_HILOGI("RealStartSA %{public}d workId:%{public}s", topWork->workInfo_->GetSaId(), topWork->workId_.c_str());
455     if (wss_.expired()) {
456         WS_HILOGE("wss_ expired");
457         return;
458     }
459     wss_.lock()->UpdateWorkBeforeRealStart(topWork);
460     RemoveFromReadyQueue(topWork);
461     bool ret = wss_.lock()->LoadSa(topWork, "");
462     if (ret) {
463         WS_HILOGI("startSA %{public}d workId:%{public}s success",
464             topWork->workInfo_->GetSaId(), topWork->workId_.c_str());
465         topWork->UpdateUidLastTimeMap();
466         if (!topWork->IsRepeating()) {
467             topWork->MarkStatus(WorkStatus::Status::REMOVED);
468             RemoveFromUidQueue(topWork, topWork->uid_);
469         } else {
470             topWork->MarkStatus(WorkStatus::Status::WAIT_CONDITION);
471         }
472         return;
473     }
474     WS_HILOGE("startSA %{public}d workId:%{public}s failed",
475         topWork->workInfo_->GetSaId(), topWork->workId_.c_str());
476 }
477 
RealStartWork(std::shared_ptr<WorkStatus> topWork)478 void WorkPolicyManager::RealStartWork(std::shared_ptr<WorkStatus> topWork)
479 {
480     WS_HILOGD("RealStartWork topWork ID: %{public}s", topWork->workId_.c_str());
481     if (wss_.expired()) {
482         WS_HILOGE("wss_ expired");
483         return;
484     }
485     UpdateWatchdogTime(wss_.lock(), topWork);
486     topWork->MarkStatus(WorkStatus::Status::RUNNING);
487     wss_.lock()->UpdateWorkBeforeRealStart(topWork);
488     RemoveFromReadyQueue(topWork);
489     bool ret = workConnManager_->StartWork(topWork);
490     if (ret) {
491         AddWatchdogForWork(topWork);
492         topWork->UpdateUidLastTimeMap();
493     } else {
494         if (!topWork->IsRepeating()) {
495             topWork->MarkStatus(WorkStatus::Status::REMOVED);
496             RemoveFromUidQueue(topWork, topWork->uid_);
497         } else {
498             topWork->MarkStatus(WorkStatus::Status::WAIT_CONDITION);
499         }
500     }
501 }
502 
UpdateWatchdogTime(const std::shared_ptr<WorkSchedulerService> & wmsptr,std::shared_ptr<WorkStatus> & topWork)503 void WorkPolicyManager::UpdateWatchdogTime(const std::shared_ptr<WorkSchedulerService> &wmsptr,
504     std::shared_ptr<WorkStatus> &topWork)
505 {
506     if (topWork->workInfo_->GetDeepIdle() == WorkCondition::DeepIdle::DEEP_IDLE_IN
507         && topWork->workInfo_->GetChargerType() != WorkCondition::Charger::CHARGING_UNKNOWN
508         && topWork->workInfo_->GetChargerType() != WorkCondition::Charger::CHARGING_UNPLUGGED) {
509         WS_HILOGD("deep idle and charger condition, update watchdog time:%{public}d", LONG_WATCHDOG_TIME);
510         SetWatchdogTime(LONG_WATCHDOG_TIME);
511         return;
512     }
513 
514     if (!wmsptr->CheckEffiResApplyInfo(topWork->uid_)) {
515         SetWatchdogTime(g_lastWatchdogTime);
516         return;
517     }
518     int32_t chargerStatus = 0;
519     auto iter = topWork->conditionMap_.find(WorkCondition::Type::CHARGER);
520     if (iter != topWork->conditionMap_.end() && iter->second) {
521         chargerStatus = topWork->conditionMap_.at(WorkCondition::Type::CHARGER)->enumVal;
522     } else {
523         WS_HILOGD("charger is in CHARGING_UNKNOWN status");
524         chargerStatus = static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNKNOWN);
525     }
526     if (chargerStatus == static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNPLUGGED)
527         || chargerStatus == static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNKNOWN)) {
528         WS_HILOGD("charger is in CHARGING_UNKNOWN or CHARGING_UNPLUGGED status");
529         SetWatchdogTime(MEDIUM_WATCHDOG_TIME);
530     } else {
531         WS_HILOGD("charger is in CHARGING status");
532         SetWatchdogTime(LONG_WATCHDOG_TIME);
533     }
534 }
535 
AddWatchdogForWork(std::shared_ptr<WorkStatus> workStatus)536 void WorkPolicyManager::AddWatchdogForWork(std::shared_ptr<WorkStatus> workStatus)
537 {
538     uint32_t watchId = NewWatchdogId();
539     WS_HILOGI("AddWatchdog, watchId:%{public}u, bundleName:%{public}s, workId:%{public}s, watchdogTime:%{public}d",
540         watchId, workStatus->bundleName_.c_str(), workStatus->workId_.c_str(), watchdogTime_);
541     watchdog_->AddWatchdog(watchId, watchdogTime_);
542     workStatus->workStartTime_ = WorkSchedUtils::GetCurrentTimeMs();
543     workStatus->workWatchDogTime_ = static_cast<uint64_t>(watchdogTime_);
544     std::lock_guard<ffrt::mutex> lock(watchdogIdMapMutex_);
545     watchdogIdMap_.emplace(watchId, workStatus);
546 }
547 
SendRetrigger(int32_t delaytime)548 void WorkPolicyManager::SendRetrigger(int32_t delaytime)
549 {
550     WS_HILOGD("enter");
551     if (handler_ == nullptr) {
552         return;
553     }
554     WS_HILOGD("delay = %{public}d", delaytime);
555     handler_->SendEvent(InnerEvent::Get(WorkEventHandler::RETRIGGER_MSG, 0), delaytime);
556 }
557 
WatchdogTimeOut(uint32_t watchdogId)558 void WorkPolicyManager::WatchdogTimeOut(uint32_t watchdogId)
559 {
560     if (wss_.expired()) {
561         WS_HILOGE("wss_ expired");
562         return;
563     }
564     std::shared_ptr<WorkStatus> workStatus = GetWorkFromWatchdog(watchdogId);
565     if (workStatus == nullptr) {
566         WS_HILOGE("watchdog:%{public}u time out error, workStatus is nullptr", watchdogId);
567         return;
568     }
569     WS_HILOGI("WatchdogTimeOut, watchId:%{public}u, bundleName:%{public}s, workId:%{public}s",
570         watchdogId, workStatus->bundleName_.c_str(), workStatus->workId_.c_str());
571     wss_.lock()->WatchdogTimeOut(workStatus);
572     std::lock_guard<ffrt::mutex> lock(watchdogIdMapMutex_);
573     watchdogIdMap_.erase(watchdogId);
574 }
575 
GetWorkFromWatchdog(uint32_t id)576 std::shared_ptr<WorkStatus> WorkPolicyManager::GetWorkFromWatchdog(uint32_t id)
577 {
578     std::lock_guard<ffrt::mutex> lock(watchdogIdMapMutex_);
579     return watchdogIdMap_.count(id) > 0 ? watchdogIdMap_.at(id) : nullptr;
580 }
581 
ObtainAllWorks(int32_t & uid)582 vector<WorkInfo> WorkPolicyManager::ObtainAllWorks(int32_t &uid)
583 {
584     WS_HILOGD("Wenter");
585     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
586     vector<WorkInfo> allWorks;
587     if (uidQueueMap_.count(uid) > 0) {
588         auto queue = uidQueueMap_.at(uid);
589         if (!queue) {
590             WS_HILOGE("ObtainAllWorks failed, queue is nullptr");
591             return allWorks;
592         }
593         auto allWorkStatus = queue->GetWorkList();
594         std::transform(allWorkStatus.begin(), allWorkStatus.end(), std::back_inserter(allWorks),
595             [](std::shared_ptr<WorkStatus> it) { return *(it->workInfo_); });
596     }
597     return allWorks;
598 }
599 
GetWorkStatus(int32_t & uid,int32_t & workId)600 shared_ptr<WorkInfo> WorkPolicyManager::GetWorkStatus(int32_t &uid, int32_t &workId)
601 {
602     WS_HILOGD("enter");
603     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
604     if (uidQueueMap_.count(uid) > 0) {
605         auto queue = uidQueueMap_.at(uid);
606         if (!queue) {
607             WS_HILOGE("GetWorkStatus failed, queue is nullptr");
608             return nullptr;
609         }
610         auto workStatus = queue->Find(string("u") + to_string(uid) + "_" + to_string(workId));
611         if (workStatus != nullptr) {
612             return workStatus->workInfo_;
613         }
614     }
615     return nullptr;
616 }
617 
GetAllWorkStatus(int32_t & uid)618 list<std::shared_ptr<WorkStatus>> WorkPolicyManager::GetAllWorkStatus(int32_t &uid)
619 {
620     WS_HILOGD("enter");
621     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
622     list<shared_ptr<WorkStatus>> allWorks;
623     if (uidQueueMap_.count(uid) > 0) {
624         allWorks = uidQueueMap_.at(uid)->GetWorkList();
625     }
626     return allWorks;
627 }
628 
GetAllRunningWorks()629 std::vector<WorkInfo> WorkPolicyManager::GetAllRunningWorks()
630 {
631     WS_HILOGD("enter");
632     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
633     vector<WorkInfo> allWorks;
634     auto it = uidQueueMap_.begin();
635     while (it != uidQueueMap_.end()) {
636         std::vector<WorkInfo> workList = it->second->GetRunningWorks();
637         allWorks.insert(allWorks.end(), workList.begin(), workList.end());
638         it++;
639     }
640     return allWorks;
641 }
642 
DumpConditionReadyQueue(string & result)643 void WorkPolicyManager::DumpConditionReadyQueue(string& result)
644 {
645     conditionReadyQueue_->Dump(result);
646 }
647 
DumpUidQueueMap(string & result)648 void WorkPolicyManager::DumpUidQueueMap(string& result)
649 {
650     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
651     for (auto it : uidQueueMap_) {
652         result.append("uid: " + std::to_string(it.first) + ":\n");
653         it.second->Dump(result);
654     }
655 }
656 
Dump(string & result)657 void WorkPolicyManager::Dump(string& result)
658 {
659     WS_HILOGI("enter");
660     result.append("1. workPolicyManager conditionReadyQueue:\n");
661     DumpConditionReadyQueue(result);
662     result.append("\n");
663 
664     result.append("2. workPolicyManager uidQueueMap:\n");
665     DumpUidQueueMap(result);
666 
667     std::string policyName;
668     result.append("3. GetMaxRunningCount:");
669     result.append(to_string(GetMaxRunningCount(policyName))
670         + (policyName.empty() ? "" : " reason: " + policyName) + "\n");
671 }
672 
NewWatchdogId()673 uint32_t WorkPolicyManager::NewWatchdogId()
674 {
675     if (watchdogId_ == MAX_WATCHDOG_ID) {
676         watchdogId_ = INIT_WATCHDOG_ID;
677     }
678     return watchdogId_++;
679 }
680 
GetDumpSetMemory()681 int32_t WorkPolicyManager::GetDumpSetMemory()
682 {
683     return dumpSetMemory_;
684 }
685 
SetMemoryByDump(int32_t memory)686 void WorkPolicyManager::SetMemoryByDump(int32_t memory)
687 {
688     dumpSetMemory_ = memory;
689 }
690 
GetDumpSetCpuUsage()691 int32_t WorkPolicyManager::GetDumpSetCpuUsage()
692 {
693     return dumpSetCpu_;
694 }
695 
SetCpuUsageByDump(int32_t cpu)696 void WorkPolicyManager::SetCpuUsageByDump(int32_t cpu)
697 {
698     dumpSetCpu_ = cpu;
699 }
700 
GetDumpSetMaxRunningCount()701 int32_t WorkPolicyManager::GetDumpSetMaxRunningCount()
702 {
703     return dumpSetMaxRunningCount_;
704 }
705 
SetMaxRunningCountByDump(int32_t count)706 void WorkPolicyManager::SetMaxRunningCountByDump(int32_t count)
707 {
708     dumpSetMaxRunningCount_ = count;
709 }
710 
SetWatchdogTimeByDump(int32_t time)711 void WorkPolicyManager::SetWatchdogTimeByDump(int32_t time)
712 {
713     WS_HILOGD("Set watchdog time by dump to %{public}d", time);
714     watchdogTime_ = time == 0 ? WATCHDOG_TIME : time;
715     g_lastWatchdogTime = watchdogTime_;
716 }
717 
SetWatchdogTime(int32_t time)718 void WorkPolicyManager::SetWatchdogTime(int32_t time)
719 {
720     watchdogTime_ = time;
721 }
722 
GetWatchdogTime()723 int32_t WorkPolicyManager::WorkPolicyManager::GetWatchdogTime()
724 {
725     return watchdogTime_;
726 }
727 
DumpCheckIdeWorkToRun(const std::string & bundleName,const std::string & abilityName)728 void WorkPolicyManager::DumpCheckIdeWorkToRun(const std::string &bundleName, const std::string &abilityName)
729 {
730     std::lock_guard<ffrt::recursive_mutex> lock(ideDebugListMutex_);
731     ideDebugList = GetAllIdeWorkStatus(bundleName, abilityName);
732     if (ideDebugList.empty()) {
733         WS_HILOGE("ideDebugList is empty, please add one work");
734         return;
735     }
736     SendIdeWorkRetriggerEvent(0);
737 }
738 
TriggerIdeWork()739 void WorkPolicyManager::TriggerIdeWork()
740 {
741     std::lock_guard<ffrt::recursive_mutex> lock(ideDebugListMutex_);
742     if (ideDebugList.empty()) {
743         WS_HILOGI("ideDebugList has been empty, all the works have been done");
744         return;
745     }
746 
747     auto topWork = ideDebugList.front();
748     ideDebugList.pop_front();
749     if (topWork->IsRunning()) {
750         SendIdeWorkRetriggerEvent(g_lastWatchdogTime + DELAY_TIME_SHORT);
751         return;
752     }
753     topWork->MarkStatus(WorkStatus::Status::RUNNING);
754     bool ret = workConnManager_->StartWork(topWork);
755     if (ret) {
756         WS_HILOGI("TriggerIdeWork ok");
757         int time = watchdogTime_;
758         watchdogTime_ = g_lastWatchdogTime;
759         AddWatchdogForWork(topWork);
760         watchdogTime_ = time;
761     } else {
762         WS_HILOGE("TriggerIdeWork error");
763         ideDebugList.clear();
764         return;
765     }
766     SendIdeWorkRetriggerEvent(g_lastWatchdogTime + DELAY_TIME_SHORT);
767 }
768 
SendIdeWorkRetriggerEvent(int32_t delaytime)769 void WorkPolicyManager::SendIdeWorkRetriggerEvent(int32_t delaytime)
770 {
771     if (handler_ == nullptr) {
772         WS_HILOGE("handle is nullptr");
773         return;
774     }
775     handler_->SendEvent(InnerEvent::Get(WorkEventHandler::IDE_RETRIGGER_MSG, 0), delaytime);
776 }
777 
GetAllIdeWorkStatus(const std::string & bundleName,const std::string & abilityName)778 std::list<std::shared_ptr<WorkStatus>> WorkPolicyManager::GetAllIdeWorkStatus(const std::string &bundleName,
779     const std::string &abilityName)
780 {
781     int32_t currentAccountId = WorkSchedUtils::GetCurrentAccountId();
782     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
783     std::list<shared_ptr<WorkStatus>> allWorks;
784     auto it = uidQueueMap_.begin();
785     while (it != uidQueueMap_.end()) {
786         if (it->second->GetWorkList().empty()) {
787             it++;
788             continue;
789         }
790         bool isExist = false;
791         for (auto work : it->second->GetWorkList()) {
792             if (work->workInfo_->GetBundleName() == bundleName &&
793                 work->workInfo_->GetAbilityName() == abilityName &&
794                 (work->userId_ == 0 || work->userId_ == currentAccountId)) {
795                 allWorks.push_back(work);
796                 isExist = true;
797             }
798         }
799         if (isExist) {
800             return allWorks;
801         }
802         it++;
803     }
804     return allWorks;
805 }
806 
PauseRunningWorks(int32_t uid)807 int32_t WorkPolicyManager::PauseRunningWorks(int32_t uid)
808 {
809     WS_HILOGI("Pause Running Work Scheduler Work, uid:%{public}d", uid);
810     bool hasWorkWithUid = false;
811     std::lock_guard<ffrt::mutex> lock(watchdogIdMapMutex_);
812     for (auto it = watchdogIdMap_.begin(); it != watchdogIdMap_.end(); it++) {
813         auto workStatus = it->second;
814         if (workStatus->uid_ == uid && workStatus->IsRunning()) {
815             hasWorkWithUid = true;
816             if (workStatus->IsPaused()) {
817                 WS_HILOGE("Work has paused, bundleName:%{public}s, workId:%{public}s",
818                     workStatus->bundleName_.c_str(), workStatus->workId_.c_str());
819                 continue;
820             }
821             uint64_t oldWatchdogTime = workStatus->workWatchDogTime_;
822             uint64_t runningTime = WorkSchedUtils::GetCurrentTimeMs() - workStatus->workStartTime_;
823             uint64_t newWatchdogTime = oldWatchdogTime - runningTime;
824             if (newWatchdogTime > LONG_WATCHDOG_TIME) {
825                 WS_HILOGE("bundleName:%{public}s, workId:%{public}s, invalid watchdogtime: %{public}" PRIu64
826                     ",oldWatchdogTime:%{public}" PRIu64 ", runningTime:%{public}" PRIu64,
827                     workStatus->bundleName_.c_str(), workStatus->workId_.c_str(), newWatchdogTime, oldWatchdogTime,
828                     runningTime);
829                 newWatchdogTime = 0;
830             }
831             workStatus->duration_ += runningTime;
832             WS_HILOGI("PauseRunningWorks, watchId:%{public}u, bundleName:%{public}s, workId:%{public}s,"
833                 " oldWatchdogTime:%{public}" PRIu64 ", newWatchdogTime:%{public}" PRIu64 ", duration:%{public}" PRIu64,
834                 it->first, workStatus->bundleName_.c_str(), workStatus->workId_.c_str(),
835                 oldWatchdogTime, newWatchdogTime, workStatus->duration_);
836             workStatus->paused_ = true;
837             workStatus->workWatchDogTime_ = newWatchdogTime;
838             watchdog_->RemoveWatchdog(it->first);
839         }
840     }
841 
842     if (!hasWorkWithUid) {
843         WS_HILOGE("PauseRunningWorks fail, the uid:%{public}d has no matching work", uid);
844         return E_UID_NO_MATCHING_WORK_ERR;
845     }
846     return ERR_OK;
847 }
848 
ResumePausedWorks(int32_t uid)849 int32_t WorkPolicyManager::ResumePausedWorks(int32_t uid)
850 {
851     WS_HILOGI("Resume Paused Work Scheduler Work, uid:%{public}d", uid);
852     bool hasWorkWithUid = false;
853     std::lock_guard<ffrt::mutex> lock(watchdogIdMapMutex_);
854     for (auto it = watchdogIdMap_.begin(); it != watchdogIdMap_.end(); it++) {
855         auto workStatus = it->second;
856         if (workStatus->uid_ == uid && workStatus->IsRunning()) {
857             hasWorkWithUid = true;
858             if (!workStatus->IsPaused()) {
859                 WS_HILOGE("Work has resumed, bundleName:%{public}s, workId:%{public}s",
860                     workStatus->bundleName_.c_str(), workStatus->workId_.c_str());
861                 continue;
862             }
863             int32_t watchdogTime = static_cast<int32_t>(workStatus->workWatchDogTime_);
864             WS_HILOGI("ResumePausedWorks, watchId:%{public}u, bundleName:%{public}s, workId:%{public}s"
865                 " watchdogTime:%{public}d",
866                 it->first, workStatus->bundleName_.c_str(), workStatus->workId_.c_str(), watchdogTime);
867             workStatus->paused_ = false;
868             watchdog_->AddWatchdog(it->first, watchdogTime);
869             workStatus->workStartTime_ = WorkSchedUtils::GetCurrentTimeMs();
870         }
871     }
872 
873     if (!hasWorkWithUid) {
874         WS_HILOGE("ResumePausedWorks fail, the uid:%{public}d has no matching work", uid);
875         return E_UID_NO_MATCHING_WORK_ERR;
876     }
877     return ERR_OK;
878 }
879 
RemoveWatchDog(std::shared_ptr<WorkStatus> workStatus)880 void WorkPolicyManager::RemoveWatchDog(std::shared_ptr<WorkStatus> workStatus)
881 {
882     if (!workStatus || workStatus->workId_.empty()) {
883         WS_HILOGE("remove watchdog error, workStatus or workId is null");
884         return;
885     }
886 
887     std::lock_guard<ffrt::mutex> lock(watchdogIdMapMutex_);
888     uint32_t watchdogId = UINT32_MAX;
889     for (auto it = watchdogIdMap_.begin(); it != watchdogIdMap_.end(); it++) {
890         if (workStatus->workId_ == it->second->workId_) {
891             watchdog_->RemoveWatchdog(it->first);
892             watchdogId = it->first;
893             break;
894         }
895     }
896     if (watchdogId != UINT32_MAX) {
897         watchdogIdMap_.erase(watchdogId);
898     }
899 }
900 
GetDeepIdleWorks()901 std::list<std::shared_ptr<WorkStatus>> WorkPolicyManager::GetDeepIdleWorks()
902 {
903     std::list<shared_ptr<WorkStatus>> deepIdleWorkds;
904     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
905     auto it = uidQueueMap_.begin();
906     while (it != uidQueueMap_.end()) {
907         std::list<std::shared_ptr<WorkStatus>> workList = it->second->GetDeepIdleWorks();
908         if (workList.size() != 0) {
909             deepIdleWorkds.insert(deepIdleWorkds.end(), workList.begin(), workList.end());
910         }
911         it++;
912     }
913     return deepIdleWorkds;
914 }
915 
FindWork(int32_t uid)916 bool WorkPolicyManager::FindWork(int32_t uid)
917 {
918     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
919     auto iter = uidQueueMap_.find(uid);
920     return iter != uidQueueMap_.end() && iter->second->GetSize() > 0;
921 }
922 
FindWork(const int32_t userId,const std::string & bundleName)923 bool WorkPolicyManager::FindWork(const int32_t userId, const std::string &bundleName)
924 {
925     std::lock_guard<ffrt::recursive_mutex> lock(uidMapMutex_);
926     for (auto list : uidQueueMap_) {
927         if (list.second && list.second->Find(userId, bundleName)) {
928             return true;
929         }
930     }
931     return false;
932 }
933 } // namespace WorkScheduler
934 } // namespace OHOS