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