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