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 "watchdog.h"
31
32 using namespace std;
33 using namespace OHOS::AppExecFwk;
34 using namespace OHOS::HiviewDFX;
35
36 namespace OHOS {
37 namespace WorkScheduler {
38 namespace {
39 const int32_t MAX_RUNNING_COUNT = 3;
40 const uint32_t MAX_WORK_COUNT_PER_UID = 10;
41 const int32_t DELAY_TIME_LONG = 30000;
42 const int32_t DELAY_TIME_SHORT = 5000;
43 const uint32_t MAX_WATCHDOG_ID = 1000;
44 const uint32_t INIT_WATCHDOG_ID = 1;
45 const int32_t INIT_DUMP_SET_MEMORY = -1;
46 const int32_t WATCHDOG_TIME = 2 * 60 * 1000;
47 const int32_t MEDIUM_WATCHDOG_TIME = 10 * 60 * 1000;
48 const int32_t LONG_WATCHDOG_TIME = 20 * 60 * 1000;
49 static int32_t g_lastWatchdogTime = WATCHDOG_TIME;
50 }
51
WorkPolicyManager(const std::shared_ptr<WorkSchedulerService> & wss)52 WorkPolicyManager::WorkPolicyManager(const std::shared_ptr<WorkSchedulerService>& wss) : wss_(wss)
53 {
54 conditionReadyQueue_ = std::make_shared<WorkQueue>();
55 watchdogId_ = INIT_WATCHDOG_ID;
56 dumpSetMemory_ = INIT_DUMP_SET_MEMORY;
57 watchdogTime_ = WATCHDOG_TIME;
58 }
59
Init(const std::shared_ptr<AppExecFwk::EventRunner> & runner)60 bool WorkPolicyManager::Init(const std::shared_ptr<AppExecFwk::EventRunner>& runner)
61 {
62 WS_HILOGD("Work policy manager init.");
63 if (wss_.expired()) {
64 WS_HILOGE("wss_ expired");
65 return false;
66 }
67 workConnManager_ = make_shared<WorkConnManager>();
68 handler_ = wss_.lock()->GetHandler();
69 if (handler_ == nullptr) {
70 WS_HILOGE("failed due to handler_ is nullptr");
71 return false;
72 }
73 watchdog_ = std::make_shared<Watchdog>(wss_.lock()->GetWorkPolicyManager(), runner);
74 return true;
75 }
76
AddPolicyFilter(shared_ptr<IPolicyFilter> filter)77 void WorkPolicyManager::AddPolicyFilter(shared_ptr<IPolicyFilter> filter)
78 {
79 policyFilters_.emplace_back(filter);
80 }
81
AddAppDataClearListener(std::shared_ptr<AppDataClearListener> listener)82 void WorkPolicyManager::AddAppDataClearListener(std::shared_ptr<AppDataClearListener> listener)
83 {
84 appDataClearListener_ = listener;
85 appDataClearListener_->Start();
86 }
87
AddWork(shared_ptr<WorkStatus> workStatus,int32_t uid)88 int32_t WorkPolicyManager::AddWork(shared_ptr<WorkStatus> workStatus, int32_t uid)
89 {
90 WS_HILOGD("Add work");
91 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
92 if (uidQueueMap_.count(uid) > 0) {
93 if (uidQueueMap_.at(uid)->Contains(make_shared<string>(workStatus->workId_))) {
94 WS_HILOGE("Workid has been added, should remove first.");
95 return E_ADD_REPEAT_WORK_ERR;
96 } else if (uidQueueMap_.at(uid)->GetSize() >= MAX_WORK_COUNT_PER_UID) {
97 WS_HILOGE("each uid only can be added %{public}u works", MAX_WORK_COUNT_PER_UID);
98 return E_WORK_EXCEED_UPPER_LIMIT;
99 }
100 uidQueueMap_.at(uid)->Push(workStatus);
101 } else {
102 WS_HILOGD("uidQueue(%{public}d) not exists, create", uid);
103 uidQueueMap_.emplace(uid, make_shared<WorkQueue>());
104 uidQueueMap_.at(uid)->Push(workStatus);
105 }
106
107 // Notify work add event to battery statistics
108 int32_t pid = IPCSkeleton::GetCallingPid();
109 string conditions = "";
110 if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::NETWORK) > 0) {
111 conditions.append("NETWORK-");
112 }
113
114 if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::CHARGER) > 0) {
115 conditions.append("CHARGER-");
116 }
117
118 if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::BATTERY_STATUS) > 0) {
119 conditions.append("BATTERY_STATUS-");
120 }
121
122 if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::BATTERY_LEVEL) > 0) {
123 conditions.append("BATTERY_LEVEL-");
124 }
125
126 if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::STORAGE) > 0) {
127 conditions.append("STORAGE-");
128 }
129
130 if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::TIMER) > 0) {
131 conditions.append("TIMER-");
132 }
133 conditions.pop_back();
134
135 string type = "Repeat";
136 if (!workStatus->workInfo_->IsRepeat()) {
137 type = "Not Repeat";
138 }
139
140 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::WORK_SCHEDULER,
141 "WORK_ADD", HiSysEvent::EventType::STATISTIC, "UID", uid,
142 "PID", pid, "NAME", workStatus->bundleName_, "WORKID", workStatus->workId_, "TRIGGER", conditions, "TYPE",
143 type, "INTERVAL", workStatus->workInfo_->GetTimeInterval());
144
145 WS_HILOGI("push workStatus ID: %{public}s to uidQueue(%{public}d)", workStatus->workId_.c_str(), uid);
146 return ERR_OK;
147 }
148
RemoveWork(shared_ptr<WorkStatus> workStatus,int32_t uid)149 bool WorkPolicyManager::RemoveWork(shared_ptr<WorkStatus> workStatus, int32_t uid)
150 {
151 WS_HILOGD("Remove work.");
152 bool ret = false;
153 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
154 if (uidQueueMap_.count(uid) > 0) {
155 WS_HILOGD("Remove workStatus ID: %{public}s form uidQueue(%{public}d)", workStatus->workId_.c_str(), uid);
156 ret = uidQueueMap_.at(uid)->Remove(workStatus);
157 if (uidQueueMap_.count(uid) <= 0) {
158 uidQueueMap_.erase(uid);
159 }
160 }
161 return ret;
162 }
163
FindWorkStatus(WorkInfo & workInfo,int32_t uid)164 shared_ptr<WorkStatus> WorkPolicyManager::FindWorkStatus(WorkInfo& workInfo, int32_t uid)
165 {
166 WS_HILOGD("Find work status start.");
167 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
168 if (uidQueueMap_.count(uid) > 0) {
169 return uidQueueMap_.at(uid)->Find(WorkStatus::MakeWorkId(workInfo.GetWorkId(), uid));
170 }
171 return nullptr;
172 }
173
RemoveFromUidQueue(std::shared_ptr<WorkStatus> workStatus,int32_t uid)174 void WorkPolicyManager::RemoveFromUidQueue(std::shared_ptr<WorkStatus> workStatus, int32_t uid)
175 {
176 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
177 if (uidQueueMap_.count(uid) > 0) {
178 uidQueueMap_.at(uid)->CancelWork(workStatus);
179 if (uidQueueMap_.at(uid)->GetSize() <= 0) {
180 uidQueueMap_.erase(uid);
181 }
182 }
183 }
184
RemoveFromReadyQueue(std::shared_ptr<WorkStatus> workStatus)185 void WorkPolicyManager::RemoveFromReadyQueue(std::shared_ptr<WorkStatus> workStatus)
186 {
187 conditionReadyQueue_->RemoveUnReady();
188 }
189
StopWork(std::shared_ptr<WorkStatus> workStatus,int32_t uid,const bool needCancel,bool isTimeOut)190 bool WorkPolicyManager::StopWork(std::shared_ptr<WorkStatus> workStatus, int32_t uid,
191 const bool needCancel, bool isTimeOut)
192 {
193 WS_HILOGD("enter");
194 bool hasCanceled = false;
195 if (workStatus->IsRunning()) {
196 workStatus->lastTimeout_ = isTimeOut;
197 workConnManager_->StopWork(workStatus);
198 if (!workStatus->IsRepeating()) {
199 workStatus->MarkStatus(WorkStatus::Status::REMOVED);
200 RemoveFromUidQueue(workStatus, uid);
201 RemoveFromReadyQueue(workStatus);
202 hasCanceled = true;
203 } else {
204 workStatus->MarkStatus(WorkStatus::Status::WAIT_CONDITION);
205 }
206 }
207
208 if (!hasCanceled && needCancel) {
209 RemoveFromUidQueue(workStatus, uid);
210 RemoveFromReadyQueue(workStatus);
211 hasCanceled = true;
212 }
213
214 CheckWorkToRun();
215 return hasCanceled;
216 }
217
StopAndClearWorks(int32_t uid)218 bool WorkPolicyManager::StopAndClearWorks(int32_t uid)
219 {
220 WS_HILOGD("enter");
221 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
222 if (uidQueueMap_.count(uid) > 0) {
223 auto queue = uidQueueMap_.at(uid);
224 for (auto it : queue->GetWorkList()) {
225 workConnManager_->StopWork(it);
226 it->MarkStatus(WorkStatus::Status::REMOVED);
227 RemoveFromReadyQueue(it);
228 }
229 queue->ClearAll();
230 uidQueueMap_.erase(uid);
231 }
232 CheckWorkToRun();
233 return true;
234 }
235
IsLastWorkTimeout(int32_t workId,int32_t uid,bool & result)236 int32_t WorkPolicyManager::IsLastWorkTimeout(int32_t workId, int32_t uid, bool &result)
237 {
238 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
239 string workIdStr = WorkStatus::MakeWorkId(workId, uid);
240 if (uidQueueMap_.count(uid) > 0) {
241 shared_ptr<WorkStatus> workStatus = uidQueueMap_.at(uid)->Find(workIdStr);
242 if (workStatus != nullptr) {
243 return workStatus->IsLastWorkTimeout();
244 }
245 }
246 return E_WORK_NOT_EXIST_FAILED;
247 }
248
OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)249 void WorkPolicyManager::OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)
250 {
251 WS_HILOGD("enter");
252 if (workStatusVector == nullptr) {
253 return;
254 }
255 AddToReadyQueue(workStatusVector);
256 CheckWorkToRun();
257 }
258
AddToReadyQueue(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)259 void WorkPolicyManager::AddToReadyQueue(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)
260 {
261 conditionReadyQueue_->Push(workStatusVector);
262 }
263
GetMaxRunningCount()264 int32_t WorkPolicyManager::GetMaxRunningCount()
265 {
266 int32_t currentMaxRunning = MAX_RUNNING_COUNT;
267 for (auto policyFilter : policyFilters_) {
268 int32_t policyMaxRunning = policyFilter->GetPolicyMaxRunning();
269 if (policyMaxRunning < currentMaxRunning) {
270 currentMaxRunning = policyMaxRunning;
271 }
272 }
273 return currentMaxRunning;
274 }
275
GetRunningCount()276 int32_t WorkPolicyManager::GetRunningCount()
277 {
278 WS_HILOGD("enter");
279 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
280 int32_t count = 0;
281 auto it = uidQueueMap_.begin();
282 while (it != uidQueueMap_.end()) {
283 count += it->second->GetRunningCount();
284 it++;
285 }
286 return count;
287 }
288
OnPolicyChanged(PolicyType policyType,shared_ptr<DetectorValue> detectorVal)289 void WorkPolicyManager::OnPolicyChanged(PolicyType policyType, shared_ptr<DetectorValue> detectorVal)
290 {
291 WS_HILOGD("enter");
292 if (wss_.expired()) {
293 WS_HILOGE("wss_ expired");
294 return;
295 }
296 switch (policyType) {
297 case PolicyType::APP_REMOVED: {
298 int32_t uid = detectorVal->intVal;
299 WorkStatus::ClearUidLastTimeMap(uid);
300 [[fallthrough]];
301 }
302 case PolicyType::APP_DATA_CLEAR: {
303 wss_.lock()->StopAndClearWorksByUid(detectorVal->intVal);
304 break;
305 }
306 default: {}
307 }
308 CheckWorkToRun();
309 }
310
IsSpecialScene(std::shared_ptr<WorkStatus> topWork)311 bool WorkPolicyManager::IsSpecialScene(std::shared_ptr<WorkStatus> topWork)
312 {
313 return (OHOS::system::GetIntParameter("const.debuggable", 0) == 1) &&
314 (topWork->bundleName_ == "com.huawei.hmos.hiviewx");
315 }
316
CheckWorkToRun()317 void WorkPolicyManager::CheckWorkToRun()
318 {
319 WS_HILOGD("Check work to run.");
320 RemoveAllUnReady();
321 if (handler_ == nullptr) {
322 WS_HILOGE("handler lock() returns nullptr");
323 return;
324 }
325 handler_->RemoveEvent(WorkEventHandler::RETRIGGER_MSG);
326 shared_ptr<WorkStatus> topWork = GetWorkToRun();
327 if (topWork == nullptr) {
328 WS_HILOGD("no condition ready work not running, return.");
329 return;
330 }
331 if (GetRunningCount() < GetMaxRunningCount() || IsSpecialScene(topWork)) {
332 WS_HILOGD("running count < max running count");
333 RealStartWork(topWork);
334 SendRetrigger(DELAY_TIME_SHORT);
335 } else {
336 WS_HILOGD("trigger delay: %{public}d", DELAY_TIME_LONG);
337 SendRetrigger(DELAY_TIME_LONG);
338 }
339 WS_HILOGD("out");
340 }
341
RemoveAllUnReady()342 void WorkPolicyManager::RemoveAllUnReady()
343 {
344 conditionReadyQueue_->RemoveUnReady();
345 }
346
GetWorkToRun()347 std::shared_ptr<WorkStatus> WorkPolicyManager::GetWorkToRun()
348 {
349 shared_ptr<WorkStatus> topWork = conditionReadyQueue_->GetWorkToRunByPriority();
350 return topWork;
351 }
352
RealStartWork(std::shared_ptr<WorkStatus> topWork)353 void WorkPolicyManager::RealStartWork(std::shared_ptr<WorkStatus> topWork)
354 {
355 WS_HILOGD("RealStartWork topWork ID: %{public}s", topWork->workId_.c_str());
356 if (wss_.expired()) {
357 WS_HILOGE("wss_ expired");
358 return;
359 }
360 UpdateWatchdogTime(wss_.lock(), topWork);
361 topWork->MarkStatus(WorkStatus::Status::RUNNING);
362 wss_.lock()->UpdateWorkBeforeRealStart(topWork);
363 RemoveFromReadyQueue(topWork);
364 bool ret = workConnManager_->StartWork(topWork);
365 if (ret) {
366 AddWatchdogForWork(topWork);
367 topWork->UpdateUidLastTimeMap();
368 } else {
369 if (!topWork->IsRepeating()) {
370 topWork->MarkStatus(WorkStatus::Status::REMOVED);
371 RemoveFromUidQueue(topWork, topWork->uid_);
372 } else {
373 topWork->MarkStatus(WorkStatus::Status::WAIT_CONDITION);
374 }
375 }
376 }
377
UpdateWatchdogTime(const std::shared_ptr<WorkSchedulerService> & wmsptr,std::shared_ptr<WorkStatus> & topWork)378 void WorkPolicyManager::UpdateWatchdogTime(const std::shared_ptr<WorkSchedulerService> &wmsptr,
379 std::shared_ptr<WorkStatus> &topWork)
380 {
381 if (!wmsptr->CheckEffiResApplyInfo(topWork->uid_)) {
382 SetWatchdogTime(g_lastWatchdogTime);
383 return;
384 }
385 int32_t chargerStatus = 0;
386 auto iter = topWork->conditionMap_.find(WorkCondition::Type::CHARGER);
387 if (iter != topWork->conditionMap_.end() && iter->second) {
388 chargerStatus = topWork->conditionMap_.at(WorkCondition::Type::CHARGER)->enumVal;
389 } else {
390 WS_HILOGD("charger is in CHARGING_UNKNOWN status");
391 chargerStatus = static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNKNOWN);
392 }
393 if (chargerStatus == static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNPLUGGED)
394 || chargerStatus == static_cast<int32_t>(WorkCondition::Charger::CHARGING_UNKNOWN)) {
395 WS_HILOGD("charger is in CHARGING_UNKNOWN or CHARGING_UNPLUGGED status");
396 SetWatchdogTime(MEDIUM_WATCHDOG_TIME);
397 } else {
398 WS_HILOGD("charger is in CHARGING status");
399 SetWatchdogTime(LONG_WATCHDOG_TIME);
400 }
401 }
402
AddWatchdogForWork(std::shared_ptr<WorkStatus> workStatus)403 void WorkPolicyManager::AddWatchdogForWork(std::shared_ptr<WorkStatus> workStatus)
404 {
405 uint32_t watchId = NewWatchdogId();
406 WS_HILOGI("AddWatchdog, watchId:%{public}u, bundleName:%{public}s, workId:%{public}s, watchdogTime:%{public}d",
407 watchId, workStatus->bundleName_.c_str(), workStatus->workId_.c_str(), watchdogTime_);
408 watchdog_->AddWatchdog(watchId, watchdogTime_);
409 std::lock_guard<std::mutex> lock(watchdogIdMapMutex_);
410 watchdogIdMap_.emplace(watchId, workStatus);
411 }
412
SendRetrigger(int32_t delaytime)413 void WorkPolicyManager::SendRetrigger(int32_t delaytime)
414 {
415 WS_HILOGD("enter");
416 if (handler_ == nullptr) {
417 return;
418 }
419 WS_HILOGD("delay = %{public}d", delaytime);
420 handler_->SendEvent(InnerEvent::Get(WorkEventHandler::RETRIGGER_MSG, 0), delaytime);
421 }
422
WatchdogTimeOut(uint32_t watchdogId)423 void WorkPolicyManager::WatchdogTimeOut(uint32_t watchdogId)
424 {
425 if (wss_.expired()) {
426 WS_HILOGE("wss_ expired");
427 return;
428 }
429 std::shared_ptr<WorkStatus> workStatus = GetWorkFromWatchdog(watchdogId);
430 WS_HILOGI("WatchdogTimeOut, watchId:%{public}u, bundleName:%{public}s, workId:%{public}s",
431 watchdogId, workStatus->bundleName_.c_str(), workStatus->workId_.c_str());
432 wss_.lock()->WatchdogTimeOut(workStatus);
433 }
434
GetWorkFromWatchdog(uint32_t id)435 std::shared_ptr<WorkStatus> WorkPolicyManager::GetWorkFromWatchdog(uint32_t id)
436 {
437 std::lock_guard<std::mutex> lock(watchdogIdMapMutex_);
438 return watchdogIdMap_.at(id);
439 }
440
ObtainAllWorks(int32_t & uid)441 list<shared_ptr<WorkInfo>> WorkPolicyManager::ObtainAllWorks(int32_t &uid)
442 {
443 WS_HILOGD("Wenter");
444 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
445 list<shared_ptr<WorkInfo>> allWorks;
446 if (uidQueueMap_.count(uid) > 0) {
447 auto queue = uidQueueMap_.at(uid);
448 auto allWorkStatus = queue->GetWorkList();
449 std::transform(allWorkStatus.begin(), allWorkStatus.end(), std::back_inserter(allWorks),
450 [](std::shared_ptr<WorkStatus> it) { return it->workInfo_; });
451 }
452 return allWorks;
453 }
454
GetWorkStatus(int32_t & uid,int32_t & workId)455 shared_ptr<WorkInfo> WorkPolicyManager::GetWorkStatus(int32_t &uid, int32_t &workId)
456 {
457 WS_HILOGD("enter");
458 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
459 if (uidQueueMap_.count(uid) > 0) {
460 auto queue = uidQueueMap_.at(uid);
461 auto workStatus = queue->Find(string("u") + to_string(uid) + "_" + to_string(workId));
462 if (workStatus != nullptr) {
463 return workStatus->workInfo_;
464 }
465 }
466 return nullptr;
467 }
468
GetAllWorkStatus(int32_t & uid)469 list<std::shared_ptr<WorkStatus>> WorkPolicyManager::GetAllWorkStatus(int32_t &uid)
470 {
471 WS_HILOGD("enter");
472 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
473 list<shared_ptr<WorkStatus>> allWorks;
474 if (uidQueueMap_.count(uid) > 0) {
475 allWorks = uidQueueMap_.at(uid)->GetWorkList();
476 }
477 return allWorks;
478 }
479
GetAllRunningWorks()480 std::list<std::shared_ptr<WorkInfo>> WorkPolicyManager::GetAllRunningWorks()
481 {
482 WS_HILOGD("enter");
483 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
484 list<shared_ptr<WorkInfo>> allWorks;
485 auto it = uidQueueMap_.begin();
486 while (it != uidQueueMap_.end()) {
487 std::list<std::shared_ptr<WorkInfo>> workList = it->second->GetRunningWorks();
488 allWorks.insert(allWorks.end(), workList.begin(), workList.end());
489 it++;
490 }
491 return allWorks;
492 }
493
DumpConditionReadyQueue(string & result)494 void WorkPolicyManager::DumpConditionReadyQueue(string& result)
495 {
496 conditionReadyQueue_->Dump(result);
497 }
498
DumpUidQueueMap(string & result)499 void WorkPolicyManager::DumpUidQueueMap(string& result)
500 {
501 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
502 for (auto it : uidQueueMap_) {
503 result.append("uid: " + std::to_string(it.first) + ":\n");
504 it.second->Dump(result);
505 }
506 }
507
Dump(string & result)508 void WorkPolicyManager::Dump(string& result)
509 {
510 WS_HILOGI("enter");
511 result.append("1. workPolicyManager conditionReadyQueue:\n");
512 DumpConditionReadyQueue(result);
513 result.append("\n");
514
515 result.append("2. workPolicyManager uidQueueMap:\n");
516 DumpUidQueueMap(result);
517
518 result.append("3. GetMaxRunningCount:");
519 result.append(to_string(GetMaxRunningCount()) + "\n");
520 }
521
NewWatchdogId()522 uint32_t WorkPolicyManager::NewWatchdogId()
523 {
524 if (watchdogId_ == MAX_WATCHDOG_ID) {
525 watchdogId_ = INIT_WATCHDOG_ID;
526 }
527 return watchdogId_++;
528 }
529
GetDumpSetMemory()530 int32_t WorkPolicyManager::GetDumpSetMemory()
531 {
532 return dumpSetMemory_;
533 }
534
SetMemoryByDump(int32_t memory)535 void WorkPolicyManager::SetMemoryByDump(int32_t memory)
536 {
537 dumpSetMemory_ = memory;
538 }
539
SetWatchdogTimeByDump(int32_t time)540 void WorkPolicyManager::SetWatchdogTimeByDump(int32_t time)
541 {
542 WS_HILOGD("Set watchdog time by dump to %{public}d", time);
543 watchdogTime_ = time == 0 ? WATCHDOG_TIME : time;
544 g_lastWatchdogTime = watchdogTime_;
545 }
546
SetWatchdogTime(int32_t time)547 void WorkPolicyManager::SetWatchdogTime(int32_t time)
548 {
549 watchdogTime_ = time;
550 }
551
GetWatchdogTime()552 int32_t WorkPolicyManager::WorkPolicyManager::GetWatchdogTime()
553 {
554 return watchdogTime_;
555 }
556
DumpCheckIdeWorkToRun(const std::string & bundleName,const std::string & abilityName)557 void WorkPolicyManager::DumpCheckIdeWorkToRun(const std::string &bundleName, const std::string &abilityName)
558 {
559 std::lock_guard<std::recursive_mutex> lock(ideDebugListMutex_);
560 ideDebugList = GetAllIdeWorkStatus(bundleName, abilityName);
561 if (ideDebugList.empty()) {
562 WS_HILOGE("ideDebugList is empty, please add one work");
563 return;
564 }
565 SendIdeWorkRetriggerEvent(0);
566 }
567
TriggerIdeWork()568 void WorkPolicyManager::TriggerIdeWork()
569 {
570 std::lock_guard<std::recursive_mutex> lock(ideDebugListMutex_);
571 if (ideDebugList.empty()) {
572 WS_HILOGI("ideDebugList has been empty, all the works have been done");
573 return;
574 }
575
576 auto topWork = ideDebugList.front();
577 ideDebugList.pop_front();
578 if (topWork->IsRunning()) {
579 SendIdeWorkRetriggerEvent(g_lastWatchdogTime + DELAY_TIME_SHORT);
580 return;
581 }
582 topWork->MarkStatus(WorkStatus::Status::RUNNING);
583 bool ret = workConnManager_->StartWork(topWork);
584 if (ret) {
585 WS_HILOGI("TriggerIdeWork ok");
586 int time = watchdogTime_;
587 watchdogTime_ = g_lastWatchdogTime;
588 AddWatchdogForWork(topWork);
589 watchdogTime_ = time;
590 } else {
591 WS_HILOGE("TriggerIdeWork error");
592 ideDebugList.clear();
593 return;
594 }
595 SendIdeWorkRetriggerEvent(g_lastWatchdogTime + DELAY_TIME_SHORT);
596 }
597
SendIdeWorkRetriggerEvent(int32_t delaytime)598 void WorkPolicyManager::SendIdeWorkRetriggerEvent(int32_t delaytime)
599 {
600 if (handler_ == nullptr) {
601 WS_HILOGE("handle is nullptr");
602 return;
603 }
604 handler_->SendEvent(InnerEvent::Get(WorkEventHandler::IDE_RETRIGGER_MSG, 0), delaytime);
605 }
606
GetAllIdeWorkStatus(const std::string & bundleName,const std::string & abilityName)607 std::list<std::shared_ptr<WorkStatus>> WorkPolicyManager::GetAllIdeWorkStatus(const std::string &bundleName,
608 const std::string &abilityName)
609 {
610 std::lock_guard<std::recursive_mutex> lock(uidMapMutex_);
611 std::list<shared_ptr<WorkStatus>> allWorks;
612 auto it = uidQueueMap_.begin();
613 while (it != uidQueueMap_.end()) {
614 if (it->second->GetWorkList().empty()) {
615 it++;
616 continue;
617 }
618 auto work = it->second->GetWorkList().front();
619 if (work->workInfo_->GetBundleName() != bundleName || work->workInfo_->GetAbilityName() != abilityName) {
620 it++;
621 continue;
622 }
623 allWorks = uidQueueMap_.at(work->uid_)->GetWorkList();
624 return allWorks;
625 }
626 return allWorks;
627 }
628 } // namespace WorkScheduler
629 } // namespace OHOS
630