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