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