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