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