• 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 #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