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