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