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