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