• 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 
28 using namespace std;
29 
30 namespace OHOS {
31 namespace BackgroundTaskMgr {
DecisionMaker(const shared_ptr<TimerManager> & timerManager,const shared_ptr<DeviceInfoManager> & device)32 DecisionMaker::DecisionMaker(const shared_ptr<TimerManager>& timerManager, const shared_ptr<DeviceInfoManager>& device)
33 {
34     timerManager_ = timerManager;
35     deviceInfoManager_ = device;
36 
37     if (!GetAppMgrProxy()) {
38         BGTASK_LOGE("GetAppMgrProxy failed");
39         return;
40     }
41 }
42 
~DecisionMaker()43 DecisionMaker::~DecisionMaker()
44 {
45     if (!GetAppMgrProxy()) {
46         BGTASK_LOGE("GetAppMgrProxy failed");
47         return;
48     }
49     appMgrProxy_->UnregisterApplicationStateObserver(iface_cast<AppExecFwk::IApplicationStateObserver>(observer_));
50 }
51 
GetAppMgrProxy()52 bool DecisionMaker::GetAppMgrProxy()
53 {
54     if (appMgrProxy_ != nullptr) {
55         return true;
56     }
57 
58     sptr<ISystemAbilityManager> systemAbilityManager =
59         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
60     if (systemAbilityManager == nullptr) {
61         BGTASK_LOGE("GetSystemAbilityManager failed.");
62         return false;
63     }
64 
65     sptr<IRemoteObject> remoteObject =
66         systemAbilityManager->GetSystemAbility(APP_MGR_SERVICE_ID);
67     if (remoteObject == nullptr) {
68         BGTASK_LOGE("GetSystemAbility failed.");
69         return false;
70     }
71 
72     appMgrProxy_ = iface_cast<AppExecFwk::IAppMgr>(remoteObject);
73     if ((appMgrProxy_ == nullptr) || (appMgrProxy_->AsObject() == nullptr)) {
74         BGTASK_LOGE("iface_cast remoteObject failed.");
75         return false;
76     }
77     observer_ = new (std::nothrow) ApplicationStateObserver(*this);
78     if (observer_ == nullptr) {
79         return false;
80     }
81     appMgrProxy_->RegisterApplicationStateObserver(iface_cast<AppExecFwk::IApplicationStateObserver>(observer_));
82 
83     recipient_ = new (std::nothrow) AppMgrDeathRecipient(*this);
84     if (recipient_ == nullptr) {
85         return false;
86     }
87     appMgrProxy_->AsObject()->AddDeathRecipient(recipient_);
88     return true;
89 }
90 
ResetAppMgrProxy()91 void DecisionMaker::ResetAppMgrProxy()
92 {
93     if ((appMgrProxy_ != nullptr) && (appMgrProxy_->AsObject() != nullptr)) {
94         appMgrProxy_->AsObject()->RemoveDeathRecipient(recipient_);
95     }
96     appMgrProxy_ = nullptr;
97 }
98 
OnRemoteDied(const wptr<IRemoteObject> & remote)99 void DecisionMaker::AppMgrDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
100 {
101     decisionMaker_.ResetAppMgrProxy();
102     decisionMaker_.GetAppMgrProxy();
103 }
104 
OnForegroundApplicationChanged(const AppExecFwk::AppStateData & appStateData)105 void DecisionMaker::ApplicationStateObserver::OnForegroundApplicationChanged(
106     const AppExecFwk::AppStateData &appStateData)
107 {
108     lock_guard<mutex> lock(decisionMaker_.lock_);
109 
110     auto key = std::make_shared<KeyInfo>(appStateData.bundleName, appStateData.uid);
111     if (appStateData.state == static_cast<int32_t>(AppExecFwk::ApplicationState::APP_STATE_FOREGROUND) ||
112         appStateData.state == static_cast<int32_t>(AppExecFwk::ApplicationState::APP_STATE_FOCUS)) {
113         auto it = decisionMaker_.pkgDelaySuspendInfoMap_.find(key);
114         if (it != decisionMaker_.pkgDelaySuspendInfoMap_.end()) {
115             auto pkgInfo = it->second;
116             pkgInfo->StopAccountingAll();
117         }
118         auto itBg = decisionMaker_.pkgBgDurationMap_.find(key);
119         if (itBg != decisionMaker_.pkgBgDurationMap_.end()) {
120             decisionMaker_.pkgBgDurationMap_.erase(itBg);
121         }
122     } else if (appStateData.state == static_cast<int32_t>(AppExecFwk::ApplicationState::APP_STATE_BACKGROUND)) {
123         decisionMaker_.pkgBgDurationMap_[key] = TimeProvider::GetCurrentTime();
124         auto it = decisionMaker_.pkgDelaySuspendInfoMap_.find(key);
125         if (it == decisionMaker_.pkgDelaySuspendInfoMap_.end()) {
126             return;
127         }
128         auto pkgInfo = it->second;
129         if (decisionMaker_.CanStartAccountingLocked(pkgInfo)) {
130             pkgInfo->StartAccounting();
131         }
132     }
133 }
134 
Decide(const std::shared_ptr<KeyInfo> & key,const std::shared_ptr<DelaySuspendInfoEx> & delayInfo)135 ErrCode DecisionMaker::Decide(const std::shared_ptr<KeyInfo>& key, const std::shared_ptr<DelaySuspendInfoEx>& delayInfo)
136 {
137     lock_guard<mutex> lock(lock_);
138     if (key == nullptr) {
139         BGTASK_LOGE("Invalid key");
140         return ERR_BGTASK_NO_MEMORY;
141     }
142 
143     ResetDayQuotaLocked();
144     auto findBgDurationIt = pkgBgDurationMap_.find(key);
145     if (findBgDurationIt != pkgBgDurationMap_.end()) {
146         if (TimeProvider::GetCurrentTime() - findBgDurationIt->second > ALLOW_REQUEST_TIME_BG) {
147             BGTASK_LOGI("Request not allow after entering background for a valid duration, %{public}s",
148                 key->ToString().c_str());
149             return ERR_BGTASK_NOT_IN_PRESET_TIME;
150         }
151     }
152 
153     const string &name = key->GetPkg();
154     int32_t uid = key->GetUid();
155     auto findInfoIt = pkgDelaySuspendInfoMap_.find(key);
156     if (findInfoIt == pkgDelaySuspendInfoMap_.end()) {
157         pkgDelaySuspendInfoMap_[key] = make_shared<PkgDelaySuspendInfo>(name, uid, timerManager_);
158     }
159 
160     auto pkgInfo = pkgDelaySuspendInfoMap_[key];
161     ErrCode ret = pkgInfo->IsAllowRequest();
162     if (ret != ERR_OK) {
163         BGTASK_LOGI("Request not allow by its info");
164         return ret;
165     }
166 
167     if (delayInfo == nullptr) {
168         BGTASK_LOGE("Invalid delayInfo");
169         return ERR_BGTASK_NO_MEMORY;
170     }
171     delayInfo->SetRequestId(NewDelaySuspendRequestId());
172     pkgInfo->AddRequest(delayInfo, GetDelayTime());
173     auto appInfo = make_shared<TransientTaskAppInfo>(name, uid, key->GetPid());
174     DelayedSingleton<BgTransientTaskMgr>::GetInstance()
175         ->HandleTransientTaskSuscriberTask(appInfo, TransientTaskEventType::TASK_START);
176     if (pkgInfo->GetRequestSize() == 1) {
177         suspendController_.RequestSuspendDelay(key);
178         auto info = make_shared<TransientTaskAppInfo>(name, uid);
179         DelayedSingleton<BgTransientTaskMgr>::GetInstance()
180         ->HandleTransientTaskSuscriberTask(info, TransientTaskEventType::APP_TASK_START);
181     }
182     if (CanStartAccountingLocked(pkgInfo)) {
183         pkgInfo->StartAccounting(delayInfo->GetRequestId());
184     }
185     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::BACKGROUND_TASK, "TRANSIENT_TASK_APPLY",
186         HiviewDFX::HiSysEvent::EventType::STATISTIC, "APP_UID", key->GetUid(), "APP_PID", key->GetPid(),
187         "APP_NAME", key->GetPkg(), "TASKID", delayInfo->GetRequestId(), "VALUE", delayInfo->GetActualDelayTime());
188     return ERR_OK;
189 }
190 
RemoveRequest(const std::shared_ptr<KeyInfo> & key,const int32_t requestId)191 void DecisionMaker::RemoveRequest(const std::shared_ptr<KeyInfo>& key, const int32_t requestId)
192 {
193     lock_guard<mutex> lock(lock_);
194     if (key == nullptr) {
195         BGTASK_LOGE("Invalid key");
196         return;
197     }
198 
199     auto findInfoIt = pkgDelaySuspendInfoMap_.find(key);
200     if (findInfoIt != pkgDelaySuspendInfoMap_.end()) {
201         auto pkgInfo = findInfoIt->second;
202         pkgInfo->RemoveRequest(requestId);
203         auto appInfo = make_shared<TransientTaskAppInfo>(key->GetPkg(), key->GetUid(), key->GetPid());
204         DelayedSingleton<BgTransientTaskMgr>::GetInstance()
205             ->HandleTransientTaskSuscriberTask(appInfo, TransientTaskEventType::TASK_END);
206         if (pkgInfo->IsRequestEmpty()) {
207             suspendController_.CancelSuspendDelay(key);
208             auto info = make_shared<TransientTaskAppInfo>(key->GetPkg(), key->GetUid());
209             DelayedSingleton<BgTransientTaskMgr>::GetInstance()
210                 ->HandleTransientTaskSuscriberTask(info, TransientTaskEventType::APP_TASK_END);
211         }
212         BGTASK_LOGD("Remove requestId: %{public}d", requestId);
213         HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::BACKGROUND_TASK, "TRANSIENT_TASK_CANCEL",
214             HiviewDFX::HiSysEvent::EventType::STATISTIC, "APP_UID", key->GetUid(), "APP_PID", key->GetPid(),
215             "APP_NAME", key->GetPkg(), "TASKID", requestId);
216     }
217 }
218 
GetRemainingDelayTime(const std::shared_ptr<KeyInfo> & key,const int32_t requestId)219 int32_t DecisionMaker::GetRemainingDelayTime(const std::shared_ptr<KeyInfo>& key, const int32_t requestId)
220 {
221     lock_guard<mutex> lock(lock_);
222     if (key == nullptr) {
223         BGTASK_LOGE("GetRemainingDelayTime, key is null.");
224         return -1;
225     }
226 
227     auto it = pkgDelaySuspendInfoMap_.find(key);
228     if (it != pkgDelaySuspendInfoMap_.end()) {
229         auto pkgInfo = it->second;
230         return pkgInfo->GetRemainDelayTime(requestId);
231     }
232     return -1;
233 }
234 
GetQuota(const std::shared_ptr<KeyInfo> & key)235 int32_t DecisionMaker::GetQuota(const std::shared_ptr<KeyInfo>& key)
236 {
237     lock_guard<mutex> lock(lock_);
238     if (key == nullptr) {
239         BGTASK_LOGE("GetQuota, key is null.");
240         return -1;
241     }
242 
243     auto it = pkgDelaySuspendInfoMap_.find(key);
244     if (it != pkgDelaySuspendInfoMap_.end()) {
245         auto pkgInfo = it->second;
246         pkgInfo->UpdateQuota();
247         return pkgInfo->GetQuota();
248     }
249     return INIT_QUOTA;
250 }
251 
IsFrontApp(const string & pkgName,int32_t uid)252 bool DecisionMaker::IsFrontApp(const string& pkgName, int32_t uid)
253 {
254     if (!GetAppMgrProxy()) {
255         BGTASK_LOGE("GetAppMgrProxy failed");
256         return false;
257     }
258     vector<AppExecFwk::AppStateData> fgAppList;
259     appMgrProxy_->GetForegroundApplications(fgAppList);
260     for (auto fgApp : fgAppList) {
261         if (fgApp.bundleName == pkgName && fgApp.uid == uid) {
262             return true;
263         }
264     }
265     return false;
266 }
267 
CanStartAccountingLocked(const std::shared_ptr<PkgDelaySuspendInfo> & pkgInfo)268 bool DecisionMaker::CanStartAccountingLocked(const std::shared_ptr<PkgDelaySuspendInfo>& pkgInfo)
269 {
270     if (!deviceInfoManager_->IsScreenOn()) {
271         return true;
272     }
273 
274     if (!GetAppMgrProxy()) {
275         BGTASK_LOGE("GetAppMgrProxy failed");
276         return false;
277     }
278     vector<AppExecFwk::AppStateData> fgAppList;
279     appMgrProxy_->GetForegroundApplications(fgAppList);
280     for (auto fgApp : fgAppList) {
281         if (fgApp.bundleName == pkgInfo->GetPkg() && fgApp.uid == pkgInfo->GetUid()) {
282             return false;
283         }
284     }
285     return true;
286 }
287 
GetDelayTime()288 int32_t DecisionMaker::GetDelayTime()
289 {
290     return deviceInfoManager_->IsLowPowerMode() ? DELAY_TIME_LOW_POWER : DELAY_TIME_NORMAL;
291 }
292 
NewDelaySuspendRequestId()293 int32_t DecisionMaker::NewDelaySuspendRequestId()
294 {
295     if (requestId_ == INT_MAX) {
296         requestId_ = initRequestId_;
297     }
298     return requestId_++;
299 }
300 
ResetDayQuotaLocked()301 void DecisionMaker::ResetDayQuotaLocked()
302 {
303     int64_t currentTime = TimeProvider::GetCurrentTime();
304     if (!IsAfterOneDay(lastRequestTime_, currentTime)) {
305         return;
306     }
307     for (auto iter = pkgDelaySuspendInfoMap_.begin(); iter != pkgDelaySuspendInfoMap_.end();) {
308         auto pkgInfo = iter->second;
309         if (pkgInfo->IsRequestEmpty()) {
310             iter = pkgDelaySuspendInfoMap_.erase(iter);
311         } else {
312             pkgInfo->UpdateQuota(true);
313             iter++;
314         }
315     }
316     lastRequestTime_ = currentTime;
317 }
318 
IsAfterOneDay(int64_t lastRequestTime,int64_t currentTime)319 bool DecisionMaker::IsAfterOneDay(int64_t lastRequestTime, int64_t currentTime)
320 {
321     if (currentTime - lastRequestTime > QUOTA_UPDATE) {
322         return true;
323     }
324     return false;
325 }
326 
OnInputEvent(const EventInfo & eventInfo)327 void DecisionMaker::OnInputEvent(const EventInfo& eventInfo)
328 {
329     if (!eventInfo.GetEventId()) {
330         return;
331     }
332 
333     switch (eventInfo.GetEventId()) {
334         case EVENT_SCREEN_ON:
335             HandleScreenOn();
336             break;
337         case EVENT_SCREEN_OFF:
338             HandleScreenOff();
339             break;
340         default:
341             break;
342     }
343 }
344 
HandleScreenOn()345 void DecisionMaker::HandleScreenOn()
346 {
347     lock_guard<mutex> lock(lock_);
348     if (!GetAppMgrProxy()) {
349         BGTASK_LOGE("GetAppMgrProxy failed");
350         return;
351     }
352     vector<AppExecFwk::AppStateData> fgAppList;
353     appMgrProxy_->GetForegroundApplications(fgAppList);
354     for (auto fgApp : fgAppList) {
355         auto key = std::make_shared<KeyInfo>(fgApp.bundleName, fgApp.uid);
356         auto it = pkgDelaySuspendInfoMap_.find(key);
357         if (it != pkgDelaySuspendInfoMap_.end()) {
358             auto pkgInfo = it->second;
359             pkgInfo->StopAccountingAll();
360         }
361     }
362 }
363 
HandleScreenOff()364 void DecisionMaker::HandleScreenOff()
365 {
366     lock_guard<mutex> lock(lock_);
367     for (const auto &p : pkgDelaySuspendInfoMap_) {
368         auto pkgInfo = p.second;
369         if (CanStartAccountingLocked(pkgInfo)) {
370             pkgInfo->StartAccounting();
371         }
372     }
373 }
374 }  // namespace BackgroundTaskMgr
375 }  // namespace OHOS