• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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