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 "decision_maker.h"
17
18 #include <climits>
19
20 #include "bg_transient_task_mgr.h"
21 #include "bgtask_common.h"
22 #include "transient_task_log.h"
23 #include "time_provider.h"
24 #include "iservice_registry.h"
25 #include "system_ability_definition.h"
26 #include "hisysevent.h"
27 #include "data_storage_helper.h"
28 #include "bgtask_config.h"
29
30 using namespace std;
31
32 namespace OHOS {
33 namespace BackgroundTaskMgr {
34 namespace {
35 const std::string SUSPEND_MANAGER_CONFIG_FILE = "/etc/efficiency_manager/suspend_manager_config.json";
36 }
DecisionMaker(const shared_ptr<TimerManager> & timerManager,const shared_ptr<DeviceInfoManager> & device)37 DecisionMaker::DecisionMaker(const shared_ptr<TimerManager>& timerManager, const shared_ptr<DeviceInfoManager>& device)
38 {
39 lock_guard<mutex> lock(lock_);
40 timerManager_ = timerManager;
41 deviceInfoManager_ = device;
42
43 if (!GetAppMgrProxy()) {
44 BGTASK_LOGE("GetAppMgrProxy failed");
45 return;
46 }
47 }
48
~DecisionMaker()49 DecisionMaker::~DecisionMaker()
50 {
51 lock_guard<mutex> lock(lock_);
52 if (appMgrProxy_ && observer_) {
53 appMgrProxy_->UnregisterApplicationStateObserver(iface_cast<AppExecFwk::IApplicationStateObserver>(observer_));
54 }
55 appMgrProxy_ = nullptr;
56 observer_ = nullptr;
57 recipient_ = nullptr;
58 }
59
GetAppMgrProxy()60 bool DecisionMaker::GetAppMgrProxy()
61 {
62 if (appMgrProxy_ != nullptr) {
63 return true;
64 }
65
66 sptr<ISystemAbilityManager> systemAbilityManager =
67 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
68 if (systemAbilityManager == nullptr) {
69 BGTASK_LOGE("GetSystemAbilityManager failed.");
70 return false;
71 }
72
73 sptr<IRemoteObject> remoteObject =
74 systemAbilityManager->GetSystemAbility(APP_MGR_SERVICE_ID);
75 if (remoteObject == nullptr) {
76 BGTASK_LOGE("GetSystemAbility failed.");
77 return false;
78 }
79
80 appMgrProxy_ = iface_cast<AppExecFwk::IAppMgr>(remoteObject);
81 if ((appMgrProxy_ == nullptr) || (appMgrProxy_->AsObject() == nullptr)) {
82 BGTASK_LOGE("iface_cast remoteObject failed.");
83 return false;
84 }
85 observer_ = new (std::nothrow) ApplicationStateObserver(*this);
86 if (observer_ == nullptr) {
87 return false;
88 }
89 appMgrProxy_->RegisterApplicationStateObserver(iface_cast<AppExecFwk::IApplicationStateObserver>(observer_));
90
91 recipient_ = new (std::nothrow) AppMgrDeathRecipient(*this);
92 if (recipient_ == nullptr) {
93 return false;
94 }
95 appMgrProxy_->AsObject()->AddDeathRecipient(recipient_);
96 return true;
97 }
98
ResetAppMgrProxy()99 void DecisionMaker::ResetAppMgrProxy()
100 {
101 if ((appMgrProxy_ != nullptr) && (appMgrProxy_->AsObject() != nullptr)) {
102 appMgrProxy_->AsObject()->RemoveDeathRecipient(recipient_);
103 }
104 appMgrProxy_ = nullptr;
105 }
106
OnRemoteDied(const wptr<IRemoteObject> & remote)107 void DecisionMaker::AppMgrDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
108 {
109 lock_guard<mutex> lock(decisionMaker_.lock_);
110 decisionMaker_.ResetAppMgrProxy();
111 decisionMaker_.GetAppMgrProxy();
112 }
113
OnForegroundApplicationChanged(const AppExecFwk::AppStateData & appStateData)114 void DecisionMaker::ApplicationStateObserver::OnForegroundApplicationChanged(
115 const AppExecFwk::AppStateData &appStateData)
116 {
117 lock_guard<mutex> lock(decisionMaker_.lock_);
118
119 auto key = std::make_shared<KeyInfo>(appStateData.bundleName, appStateData.uid);
120 if (appStateData.state == static_cast<int32_t>(AppExecFwk::ApplicationState::APP_STATE_FOREGROUND) ||
121 appStateData.state == static_cast<int32_t>(AppExecFwk::ApplicationState::APP_STATE_FOCUS)) {
122 auto it = decisionMaker_.pkgDelaySuspendInfoMap_.find(key);
123 if (it != decisionMaker_.pkgDelaySuspendInfoMap_.end()) {
124 auto pkgInfo = it->second;
125 pkgInfo->StopAccountingAll();
126 }
127 auto itBg = decisionMaker_.pkgBgDurationMap_.find(key);
128 if (itBg != decisionMaker_.pkgBgDurationMap_.end()) {
129 decisionMaker_.pkgBgDurationMap_.erase(itBg);
130 }
131 } else if (appStateData.state == static_cast<int32_t>(AppExecFwk::ApplicationState::APP_STATE_BACKGROUND)) {
132 decisionMaker_.pkgBgDurationMap_[key] = TimeProvider::GetCurrentTime();
133 auto it = decisionMaker_.pkgDelaySuspendInfoMap_.find(key);
134 if (it == decisionMaker_.pkgDelaySuspendInfoMap_.end()) {
135 return;
136 }
137 auto pkgInfo = it->second;
138 if (decisionMaker_.CanStartAccountingLocked(pkgInfo)) {
139 pkgInfo->StartAccounting();
140 }
141 }
142 }
143
GetAllowRequestTime()144 int DecisionMaker::GetAllowRequestTime()
145 {
146 static int time = 0;
147
148 if (time != 0) {
149 return time;
150 }
151 if (!DelayedSingleton<DataStorageHelper>::GetInstance()->ParseFastSuspendDozeTime(
152 SUSPEND_MANAGER_CONFIG_FILE, time)) {
153 time = ALLOW_REQUEST_TIME_BG;
154 }
155 BGTASK_LOGI("time = %{public}d", time);
156 return time;
157 }
158
CheckQuotaTime(const std::shared_ptr<PkgDelaySuspendInfo> & pkgInfo,const std::string & name,int32_t uid,const std::shared_ptr<KeyInfo> & key,bool & needSetTime)159 ErrCode DecisionMaker::CheckQuotaTime(const std::shared_ptr<PkgDelaySuspendInfo>& pkgInfo, const std::string &name,
160 int32_t uid, const std::shared_ptr<KeyInfo>& key, bool &needSetTime)
161 {
162 ErrCode ret = pkgInfo->IsAllowRequest();
163 if (ret == ERR_BGTASK_TIME_INSUFFICIENT) {
164 bool isExemptedApp = DelayedSingleton<BgtaskConfig>::GetInstance()->
165 IsTransientTaskExemptedQuatoApp(name);
166 BGTASK_LOGI("pkgname %{public}s has no quota time, isExemptedApp %{public}d", name.c_str(), isExemptedApp);
167 if (isExemptedApp) {
168 needSetTime = true;
169 return ERR_OK;
170 } else {
171 return ERR_BGTASK_TIME_INSUFFICIENT;
172 }
173 }
174 if (ret != ERR_OK) {
175 BGTASK_LOGE("Request not allow by its info");
176 return ret;
177 }
178 return ERR_OK;
179 }
180
Decide(const std::shared_ptr<KeyInfo> & key,const std::shared_ptr<DelaySuspendInfoEx> & delayInfo)181 ErrCode DecisionMaker::Decide(const std::shared_ptr<KeyInfo>& key, const std::shared_ptr<DelaySuspendInfoEx>& delayInfo)
182 {
183 lock_guard<mutex> lock(lock_);
184 if (key == nullptr || delayInfo == nullptr) {
185 BGTASK_LOGE("Invalid key or delayInfo");
186 return ERR_BGTASK_NO_MEMORY;
187 }
188
189 ResetDayQuotaLocked();
190 auto findBgDurationIt = pkgBgDurationMap_.find(key);
191 if (findBgDurationIt != pkgBgDurationMap_.end()) {
192 if (TimeProvider::GetCurrentTime() - findBgDurationIt->second > GetAllowRequestTime()) {
193 BGTASK_LOGI("Request not allow after entering background for a valid duration, %{public}s",
194 key->ToString().c_str());
195 return ERR_BGTASK_NOT_IN_PRESET_TIME;
196 }
197 }
198 const string &name = key->GetPkg();
199 int32_t uid = key->GetUid();
200 auto findInfoIt = pkgDelaySuspendInfoMap_.find(key);
201 if (findInfoIt == pkgDelaySuspendInfoMap_.end()) {
202 pkgDelaySuspendInfoMap_[key] = make_shared<PkgDelaySuspendInfo>(name, uid, timerManager_);
203 }
204 auto pkgInfo = pkgDelaySuspendInfoMap_[key];
205 bool needSetTime = false;
206 ErrCode ret = CheckQuotaTime(pkgInfo, name, uid, key, needSetTime);
207 if (ret != ERR_OK) {
208 return ret;
209 }
210 delayInfo->SetRequestId(NewDelaySuspendRequestId());
211 pkgInfo->AddRequest(delayInfo, GetDelayTime(), needSetTime);
212 auto appInfo = make_shared<TransientTaskAppInfo>(name, uid, key->GetPid());
213 DelayedSingleton<BgTransientTaskMgr>::GetInstance()
214 ->HandleTransientTaskSuscriberTask(appInfo, TransientTaskEventType::TASK_START);
215 if (pkgInfo->GetRequestSize() == 1) {
216 suspendController_.RequestSuspendDelay(key);
217 auto info = make_shared<TransientTaskAppInfo>(name, uid);
218 DelayedSingleton<BgTransientTaskMgr>::GetInstance()
219 ->HandleTransientTaskSuscriberTask(info, TransientTaskEventType::APP_TASK_START);
220 }
221 if (CanStartAccountingLocked(pkgInfo)) {
222 pkgInfo->StartAccounting(delayInfo->GetRequestId());
223 }
224 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::BACKGROUND_TASK, "TRANSIENT_TASK_APPLY",
225 HiviewDFX::HiSysEvent::EventType::STATISTIC, "APP_UID", key->GetUid(), "APP_PID", key->GetPid(),
226 "APP_NAME", key->GetPkg(), "TASKID", delayInfo->GetRequestId(), "VALUE", delayInfo->GetActualDelayTime());
227 return ERR_OK;
228 }
229
PauseTransientTaskTimeForInner(int32_t uid,const std::string & name)230 ErrCode DecisionMaker::PauseTransientTaskTimeForInner(int32_t uid, const std::string &name)
231 {
232 lock_guard<mutex> lock(lock_);
233 auto key = std::make_shared<KeyInfo>(name, uid);
234 auto itBg = pkgBgDurationMap_.find(key);
235 if (itBg == pkgBgDurationMap_.end()) {
236 BGTASK_LOGE("pkgname: %{public}s, uid: %{public}d is foreground applicaion.", name.c_str(), uid);
237 return ERR_BGTASK_FOREGROUND;
238 }
239 auto it = pkgDelaySuspendInfoMap_.find(key);
240 if (it == pkgDelaySuspendInfoMap_.end()) {
241 BGTASK_LOGE("pkgname: %{public}s, uid: %{public}d not request transient task.", name.c_str(), uid);
242 return ERR_BGTASK_NOREQUEST_TASK;
243 }
244 auto pkgInfo = it->second;
245 pkgInfo->StopAccountingAll();
246 return ERR_OK;
247 }
248
StartTransientTaskTimeForInner(int32_t uid,const std::string & name)249 ErrCode DecisionMaker::StartTransientTaskTimeForInner(int32_t uid, const std::string &name)
250 {
251 lock_guard<mutex> lock(lock_);
252 auto key = std::make_shared<KeyInfo>(name, uid);
253 auto itBg = pkgBgDurationMap_.find(key);
254 if (itBg == pkgBgDurationMap_.end()) {
255 BGTASK_LOGE("pkgname: %{public}s, uid: %{public}d is foreground applicaion.", name.c_str(), uid);
256 return ERR_BGTASK_FOREGROUND;
257 }
258 auto it = pkgDelaySuspendInfoMap_.find(key);
259 if (it == pkgDelaySuspendInfoMap_.end()) {
260 BGTASK_LOGE("pkgname: %{public}s, uid: %{public}d not request transient task.", name.c_str(), uid);
261 return ERR_BGTASK_NOREQUEST_TASK;
262 }
263 auto pkgInfo = it->second;
264 if (CanStartAccountingLocked(pkgInfo)) {
265 pkgInfo->StartAccounting();
266 } else {
267 BGTASK_LOGE("pkgname: %{public}s, uid: %{public}d can't can startAccountingLocked.", name.c_str(), uid);
268 return ERR_BGTASK_FOREGROUND;
269 }
270 return ERR_OK;
271 }
272
RemoveRequest(const std::shared_ptr<KeyInfo> & key,const int32_t requestId)273 void DecisionMaker::RemoveRequest(const std::shared_ptr<KeyInfo>& key, const int32_t requestId)
274 {
275 lock_guard<mutex> lock(lock_);
276 if (key == nullptr) {
277 BGTASK_LOGE("Invalid key");
278 return;
279 }
280
281 auto findInfoIt = pkgDelaySuspendInfoMap_.find(key);
282 if (findInfoIt != pkgDelaySuspendInfoMap_.end()) {
283 auto pkgInfo = findInfoIt->second;
284 pkgInfo->RemoveRequest(requestId);
285 auto appInfo = make_shared<TransientTaskAppInfo>(key->GetPkg(), key->GetUid(), key->GetPid());
286 DelayedSingleton<BgTransientTaskMgr>::GetInstance()
287 ->HandleTransientTaskSuscriberTask(appInfo, TransientTaskEventType::TASK_END);
288 if (pkgInfo->IsRequestEmpty()) {
289 suspendController_.CancelSuspendDelay(key);
290 auto info = make_shared<TransientTaskAppInfo>(key->GetPkg(), key->GetUid());
291 DelayedSingleton<BgTransientTaskMgr>::GetInstance()
292 ->HandleTransientTaskSuscriberTask(info, TransientTaskEventType::APP_TASK_END);
293 }
294 BGTASK_LOGD("Remove requestId: %{public}d", requestId);
295 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::BACKGROUND_TASK, "TRANSIENT_TASK_CANCEL",
296 HiviewDFX::HiSysEvent::EventType::STATISTIC, "APP_UID", key->GetUid(), "APP_PID", key->GetPid(),
297 "APP_NAME", key->GetPkg(), "TASKID", requestId);
298 }
299 }
300
GetRemainingDelayTime(const std::shared_ptr<KeyInfo> & key,const int32_t requestId)301 int32_t DecisionMaker::GetRemainingDelayTime(const std::shared_ptr<KeyInfo>& key, const int32_t requestId)
302 {
303 lock_guard<mutex> lock(lock_);
304 if (key == nullptr) {
305 BGTASK_LOGE("GetRemainingDelayTime, key is null.");
306 return -1;
307 }
308
309 auto it = pkgDelaySuspendInfoMap_.find(key);
310 if (it != pkgDelaySuspendInfoMap_.end()) {
311 auto pkgInfo = it->second;
312 return pkgInfo->GetRemainDelayTime(requestId);
313 }
314 return -1;
315 }
316
GetRequestIdListByKey(const std::shared_ptr<KeyInfo> & key)317 vector<int32_t> DecisionMaker::GetRequestIdListByKey(const std::shared_ptr<KeyInfo>& key)
318 {
319 lock_guard<mutex> lock(lock_);
320 vector<int32_t> requestIdList;
321 if (key == nullptr) {
322 BGTASK_LOGE("GetRequestListByKey, key is null.");
323 return requestIdList;
324 }
325 auto it = pkgDelaySuspendInfoMap_.find(key);
326 if (it != pkgDelaySuspendInfoMap_.end()) {
327 auto pkgInfo = it->second;
328 for (const auto &task : pkgInfo->GetRequestList()) {
329 requestIdList.emplace_back(task->GetRequestId());
330 }
331 } else {
332 BGTASK_LOGD("pkgname: %{public}s, uid: %{public}d not request transient task.",
333 key->GetPkg().c_str(), key->GetUid());
334 }
335 return requestIdList;
336 }
337
GetQuota(const std::shared_ptr<KeyInfo> & key)338 int32_t DecisionMaker::GetQuota(const std::shared_ptr<KeyInfo>& key)
339 {
340 lock_guard<mutex> lock(lock_);
341 if (key == nullptr) {
342 BGTASK_LOGE("GetQuota, key is null.");
343 return -1;
344 }
345
346 auto it = pkgDelaySuspendInfoMap_.find(key);
347 if (it != pkgDelaySuspendInfoMap_.end()) {
348 auto pkgInfo = it->second;
349 pkgInfo->UpdateQuota();
350 return pkgInfo->GetQuota();
351 }
352 return INIT_QUOTA;
353 }
354
IsFrontApp(const string & pkgName,int32_t uid)355 bool DecisionMaker::IsFrontApp(const string& pkgName, int32_t uid)
356 {
357 lock_guard<mutex> lock(lock_);
358 if (!GetAppMgrProxy()) {
359 BGTASK_LOGE("GetAppMgrProxy failed");
360 return false;
361 }
362 vector<AppExecFwk::AppStateData> fgAppList;
363 appMgrProxy_->GetForegroundApplications(fgAppList);
364 for (auto fgApp : fgAppList) {
365 if (fgApp.bundleName == pkgName && fgApp.uid == uid) {
366 return true;
367 }
368 }
369 return false;
370 }
371
CanStartAccountingLocked(const std::shared_ptr<PkgDelaySuspendInfo> & pkgInfo)372 bool DecisionMaker::CanStartAccountingLocked(const std::shared_ptr<PkgDelaySuspendInfo>& pkgInfo)
373 {
374 if (!deviceInfoManager_->IsScreenOn()) {
375 return true;
376 }
377
378 if (!GetAppMgrProxy()) {
379 BGTASK_LOGE("GetAppMgrProxy failed");
380 return false;
381 }
382 vector<AppExecFwk::AppStateData> fgAppList;
383 appMgrProxy_->GetForegroundApplications(fgAppList);
384 for (auto fgApp : fgAppList) {
385 if (fgApp.bundleName == pkgInfo->GetPkg() && fgApp.uid == pkgInfo->GetUid()) {
386 return false;
387 }
388 }
389 return true;
390 }
391
GetDelayTime()392 int32_t DecisionMaker::GetDelayTime()
393 {
394 return deviceInfoManager_->IsLowPowerMode() ? DELAY_TIME_LOW_POWER : DELAY_TIME_NORMAL;
395 }
396
NewDelaySuspendRequestId()397 int32_t DecisionMaker::NewDelaySuspendRequestId()
398 {
399 if (requestId_ == INT_MAX) {
400 requestId_ = initRequestId_;
401 }
402 return requestId_++;
403 }
404
ResetDayQuotaLocked()405 void DecisionMaker::ResetDayQuotaLocked()
406 {
407 int64_t currentTime = TimeProvider::GetCurrentTime();
408 if (!IsAfterOneDay(lastRequestTime_, currentTime)) {
409 return;
410 }
411 for (auto iter = pkgDelaySuspendInfoMap_.begin(); iter != pkgDelaySuspendInfoMap_.end();) {
412 auto pkgInfo = iter->second;
413 if (pkgInfo->IsRequestEmpty()) {
414 iter = pkgDelaySuspendInfoMap_.erase(iter);
415 } else {
416 pkgInfo->UpdateQuota(true);
417 iter++;
418 }
419 }
420 lastRequestTime_ = currentTime;
421 }
422
IsAfterOneDay(int64_t lastRequestTime,int64_t currentTime)423 bool DecisionMaker::IsAfterOneDay(int64_t lastRequestTime, int64_t currentTime)
424 {
425 if (currentTime - lastRequestTime > QUOTA_UPDATE) {
426 return true;
427 }
428 return false;
429 }
430
OnInputEvent(const EventInfo & eventInfo)431 void DecisionMaker::OnInputEvent(const EventInfo& eventInfo)
432 {
433 if (!eventInfo.GetEventId()) {
434 return;
435 }
436
437 switch (eventInfo.GetEventId()) {
438 case EVENT_SCREEN_ON:
439 HandleScreenOn();
440 break;
441 case EVENT_SCREEN_OFF:
442 HandleScreenOff();
443 break;
444 default:
445 break;
446 }
447 }
448
HandleScreenOn()449 void DecisionMaker::HandleScreenOn()
450 {
451 lock_guard<mutex> lock(lock_);
452 if (!GetAppMgrProxy()) {
453 BGTASK_LOGE("GetAppMgrProxy failed");
454 return;
455 }
456 vector<AppExecFwk::AppStateData> fgAppList;
457 appMgrProxy_->GetForegroundApplications(fgAppList);
458 for (auto fgApp : fgAppList) {
459 auto key = std::make_shared<KeyInfo>(fgApp.bundleName, fgApp.uid);
460 auto it = pkgDelaySuspendInfoMap_.find(key);
461 if (it != pkgDelaySuspendInfoMap_.end()) {
462 auto pkgInfo = it->second;
463 pkgInfo->StopAccountingAll();
464 }
465 }
466 }
467
HandleScreenOff()468 void DecisionMaker::HandleScreenOff()
469 {
470 lock_guard<mutex> lock(lock_);
471 std::set<int32_t> &transientPauseUid = DelayedSingleton<BgTransientTaskMgr>::GetInstance()
472 ->GetTransientPauseUid();
473 for (const auto &p : pkgDelaySuspendInfoMap_) {
474 auto pkgInfo = p.second;
475 auto findUid = [&pkgInfo](const auto &target) {
476 return pkgInfo->GetUid() == target;
477 };
478 auto findUidIter = find_if(transientPauseUid.begin(), transientPauseUid.end(), findUid);
479 if (findUidIter != transientPauseUid.end()) {
480 BGTASK_LOGD("transient task freeze, not can start.");
481 continue;
482 }
483 if (CanStartAccountingLocked(pkgInfo)) {
484 pkgInfo->StartAccounting();
485 }
486 }
487 }
488 } // namespace BackgroundTaskMgr
489 } // namespace OHOS