• 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 "bg_efficiency_resources_mgr.h"
17 
18 #include <set>
19 #include <algorithm>
20 #include <vector>
21 
22 #include "event_runner.h"
23 #include "system_ability_definition.h"
24 #include "iservice_registry.h"
25 #include "bgtaskmgr_inner_errors.h"
26 
27 #include "resource_type.h"
28 #include "time_provider.h"
29 #include "bundle_manager_helper.h"
30 #include "efficiency_resource_log.h"
31 
32 namespace OHOS {
33 namespace BackgroundTaskMgr {
34 namespace {
35     const std::string BG_EFFICIENCY_RESOURCES_MGR_NAME = "BgEfficiencyResourcesMgr";
36     const std::string DUMP_PARAM_LIST_ALL = "--all";
37     const std::string DUMP_PARAM_RESET_ALL = "--reset_all";
38     const std::string DUMP_PARAM_RESET_APP = "--resetapp";
39     const std::string DUMP_PARAM_RESET_PROC = "--resetproc";
40     const int32_t MAX_DUMP_PARAM_NUMS = 4;
41     const uint32_t APP_MGR_READY = 1;
42     const uint32_t BUNDLE_MGR_READY = 2;
43     const uint32_t ALL_DEPENDS_READY = 3;
44     const std::vector<std::string> ResourceTypeName = {
45         "CPU",
46         "COMMON_EVENT",
47         "TIMER",
48         "WORK_SCHEDULER",
49         "BLUETOOTH",
50         "GPS",
51         "AUDIO",
52     };
53     const uint32_t MAX_RESOURCES_TYPE_NUM = ResourceTypeName.size();
54     const uint32_t MAX_RESOURCE_NUMBER = (1 << ResourceTypeName.size()) - 1;
55 }
BgEfficiencyResourcesMgr()56 BgEfficiencyResourcesMgr::BgEfficiencyResourcesMgr() {}
57 
~BgEfficiencyResourcesMgr()58 BgEfficiencyResourcesMgr::~BgEfficiencyResourcesMgr() {}
59 
Init()60 bool BgEfficiencyResourcesMgr::Init()
61 {
62     subscriberMgr_ = DelayedSingleton<ResourcesSubscriberMgr>::GetInstance();
63     runner_ = AppExecFwk::EventRunner::Create(BG_EFFICIENCY_RESOURCES_MGR_NAME);
64     if (runner_ == nullptr) {
65         BGTASK_LOGE("efficiency resources mgr runner create failed!");
66         return false;
67     }
68     handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
69     if (!handler_) {
70         BGTASK_LOGE("efficiency resources mgr handler create failed!");
71         return false;
72     }
73     HandlePersistenceData();
74     BGTASK_LOGI("efficiency resources mgr finish Init");
75     return true;
76 }
77 
InitNecessaryState()78 void BgEfficiencyResourcesMgr::InitNecessaryState()
79 {
80     RegisterAppStateObserver();
81     BGTASK_LOGI("necessary system service has been accessiable!");
82     BGTASK_LOGD("app resource record size: %{public}d, process  resource record size:  %{public}d!",
83         static_cast<int32_t>(appResourceApplyMap_.size()), static_cast<int32_t>(procResourceApplyMap_.size()));
84     isSysReady_.store(true);
85 }
86 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)87 void BgEfficiencyResourcesMgr::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
88 {
89     BGTASK_LOGI("add system ability, systemAbilityId : %{public}d", systemAbilityId);
90     switch (systemAbilityId) {
91         case APP_MGR_SERVICE_ID:
92             BGTASK_LOGI("app mgr service is ready!");
93             dependsReady_ |= APP_MGR_READY;
94             break;
95         case BUNDLE_MGR_SERVICE_SYS_ABILITY_ID:
96             BGTASK_LOGI("bundle mgr service is ready!");
97             dependsReady_ |= BUNDLE_MGR_READY;
98             break;
99         default:
100             break;
101     }
102     if (dependsReady_ == ALL_DEPENDS_READY) {
103         BGTASK_LOGI("necessary system service has been satisfied!");
104         auto task = [this]() { this->InitNecessaryState(); };
105         handler_->PostSyncTask(task);
106     }
107 }
108 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)109 void BgEfficiencyResourcesMgr::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
110 {
111     BGTASK_LOGI("remove system ability, systemAbilityId : %{public}d", systemAbilityId);
112     switch (systemAbilityId) {
113         case APP_MGR_SERVICE_ID:
114             BGTASK_LOGI("app mgr service is removed!");
115             dependsReady_ &= (~APP_MGR_READY);
116             break;
117         case BUNDLE_MGR_SERVICE_SYS_ABILITY_ID:
118             BGTASK_LOGI("bundle mgr service is removed!");
119             dependsReady_ &= (~BUNDLE_MGR_READY);
120             break;
121         default:
122             break;
123     }
124     if (dependsReady_ != ALL_DEPENDS_READY) {
125         BGTASK_LOGI("necessary system service has been unsatisfied");
126         isSysReady_.store(false);
127     }
128 }
129 
RegisterAppStateObserver()130 void BgEfficiencyResourcesMgr::RegisterAppStateObserver()
131 {
132     appStateObserver_ = DelayedSingleton<AppStateObserver>::GetInstance();
133     if (appStateObserver_) {
134         appStateObserver_->SetBgEfficiencyResourcesMgr(shared_from_this());
135     }
136 }
137 
HandlePersistenceData()138 void BgEfficiencyResourcesMgr::HandlePersistenceData()
139 {
140     BGTASK_LOGD("ResourceRecordStorage service restart, restore data");
141 
142     if (appMgrClient_ == nullptr) {
143         appMgrClient_ = std::make_unique<AppExecFwk::AppMgrClient>();
144         if (!appMgrClient_ || appMgrClient_->ConnectAppMgrService() != ERR_OK) {
145             BGTASK_LOGW("ResourceRecordStorage connect to app mgr service failed");
146             DelayedSingleton<DataStorageHelper>::GetInstance()->RefreshResourceRecord(
147                 appResourceApplyMap_, procResourceApplyMap_);
148             return;
149         }
150     }
151     std::vector<AppExecFwk::RunningProcessInfo> allAppProcessInfos;
152     appMgrClient_->GetAllRunningProcesses(allAppProcessInfos);
153     BGTASK_LOGI("start to recovery delayed task of apps and processes");
154     DelayedSingleton<DataStorageHelper>::GetInstance()->RestoreResourceRecord(
155         appResourceApplyMap_, procResourceApplyMap_);
156     CheckPersistenceData(allAppProcessInfos);
157     RecoverDelayedTask(true, procResourceApplyMap_);
158     RecoverDelayedTask(false, appResourceApplyMap_);
159     DelayedSingleton<DataStorageHelper>::GetInstance()->RefreshResourceRecord(
160         appResourceApplyMap_, procResourceApplyMap_);
161 }
162 
EraseRecordIf(ResourceRecordMap & infoMap,const std::function<bool (ResourceRecordPair)> & fun)163 void BgEfficiencyResourcesMgr::EraseRecordIf(ResourceRecordMap &infoMap,
164     const std::function<bool(ResourceRecordPair)> &fun)
165 {
166     for (auto iter = infoMap.begin(); iter != infoMap.end();) {
167         if (fun(*iter)) {
168             infoMap.erase(iter++);
169         } else {
170             iter++;
171         }
172     }
173 }
174 
CheckPersistenceData(const std::vector<AppExecFwk::RunningProcessInfo> & allProcesses)175 void BgEfficiencyResourcesMgr::CheckPersistenceData(const std::vector<AppExecFwk::RunningProcessInfo> &allProcesses)
176 {
177     BGTASK_LOGI("efficiency resources check existing uid and pid");
178     std::set<int32_t> runningUid;
179     std::set<int32_t> runningPid;
180     std::for_each(allProcesses.begin(), allProcesses.end(), [&runningUid, &runningPid](const auto &iter) {
181         runningUid.emplace(iter.uid_);
182         runningPid.emplace(iter.pid_);
183     });
184     auto removeUid = [&runningUid](const auto &iter) { return runningUid.find(iter.first) == runningUid.end(); };
185     EraseRecordIf(appResourceApplyMap_, removeUid);
186     auto removePid = [&runningPid](const auto &iter)  { return runningPid.find(iter.first) == runningPid.end(); };
187     EraseRecordIf(procResourceApplyMap_, removePid);
188 }
189 
RecoverDelayedTask(bool isProcess,ResourceRecordMap & infoMap)190 void BgEfficiencyResourcesMgr::RecoverDelayedTask(bool isProcess, ResourceRecordMap& infoMap)
191 {
192     BGTASK_LOGD("start to recovery delayed task");
193     const auto &mgr = shared_from_this();
194     for (auto iter = infoMap.begin(); iter != infoMap.end(); iter ++) {
195         auto &resourceList = iter->second->resourceUnitList_;
196         int32_t mapKey = iter->first;
197         for (auto resourceIter = resourceList.begin(); resourceIter != resourceList.end(); resourceIter++) {
198             if (resourceIter->isPersist_) {
199                 continue;
200             }
201             auto task = [mgr, mapKey, isProcess] () {
202                 mgr->ResetTimeOutResource(mapKey, isProcess);
203             };
204             int32_t timeOut = static_cast<int32_t>(resourceIter->endTime_ - TimeProvider::GetCurrentTime());
205             handler_->PostTask(task, std::max(0, timeOut));
206         }
207     }
208 }
209 
RemoveAppRecord(int32_t uid,const std::string & bundleName,bool resetAll)210 ErrCode BgEfficiencyResourcesMgr::RemoveAppRecord(int32_t uid, const std::string &bundleName, bool resetAll)
211 {
212     if (!isSysReady_.load()) {
213         BGTASK_LOGW("Efficiency resources manager is not ready, RemoveAppRecord failed");
214         return ERR_BGTASK_SYS_NOT_READY;
215     }
216     BGTASK_LOGD("app died, uid: %{public}d, bundleName: %{public}s", uid, bundleName.c_str());
217     handler_->PostTask([this, uid, bundleName, resetAll]() {
218         int resourceNumber = resetAll ? MAX_RESOURCE_NUMBER : (MAX_RESOURCE_NUMBER ^ ResourceType::WORK_SCHEDULER);
219         std::shared_ptr<ResourceCallbackInfo> callbackInfo = std::make_shared<ResourceCallbackInfo>(uid,
220             0, resourceNumber, bundleName);
221         this->ResetEfficiencyResourcesInner(callbackInfo, false);
222     });
223     return ERR_OK;
224 }
225 
RemoveProcessRecord(int32_t uid,int32_t pid,const std::string & bundleName)226 ErrCode BgEfficiencyResourcesMgr::RemoveProcessRecord(int32_t uid, int32_t pid, const std::string &bundleName)
227 {
228     if (!isSysReady_.load()) {
229         BGTASK_LOGW("Efficiency resources manager is not ready, remove process record failed");
230         return ERR_BGTASK_SYS_NOT_READY;
231     }
232     BGTASK_LOGD("process died, uid: %{public}d, pid: %{public}d, bundleName: %{public}s",
233         uid, pid, bundleName.c_str());
234     handler_->PostTask([this, uid, pid, bundleName]() {
235         std::shared_ptr<ResourceCallbackInfo> callbackInfo = std::make_shared<ResourceCallbackInfo>(uid,
236             pid, MAX_RESOURCE_NUMBER ^ ResourceType::WORK_SCHEDULER, bundleName);
237         this->ResetEfficiencyResourcesInner(callbackInfo, true);
238         if (!this->CheckAlivedApp(uid)) {
239             this->ResetEfficiencyResourcesInner(callbackInfo, false);
240         }
241     });
242     return ERR_OK;
243 }
244 
CheckAlivedApp(int32_t uid)245 bool BgEfficiencyResourcesMgr::CheckAlivedApp(int32_t uid)
246 {
247     BGTASK_LOGD("start check app alive or not");
248     if (!appMgrClient_ || appMgrClient_->ConnectAppMgrService() != ERR_OK) {
249         BGTASK_LOGE("ResourceRecordStorage connect to app mgr service failed");
250         return true;
251     }
252     std::vector<AppExecFwk::RunningProcessInfo> allAppProcessInfos {};
253     appMgrClient_->GetAllRunningProcesses(allAppProcessInfos);
254     for (const auto &info : allAppProcessInfos) {
255         if (info.uid_ == uid) {
256             return true;
257         }
258     }
259     return false;
260 }
261 
Clear()262 void BgEfficiencyResourcesMgr::Clear()
263 {
264     if (appStateObserver_) {
265         appStateObserver_->Unsubscribe();
266     }
267 }
268 
CheckResourceInfo(const sptr<EfficiencyResourceInfo> & resourceInfo)269 bool CheckResourceInfo(const sptr<EfficiencyResourceInfo> &resourceInfo)
270 {
271     if (!resourceInfo) {
272         BGTASK_LOGE("apply efficiency resource request params is null!");
273         return false;
274     }
275     if (resourceInfo->GetResourceNumber() == 0 || resourceInfo->GetResourceNumber() > MAX_RESOURCE_NUMBER
276         || (resourceInfo->IsApply() && !resourceInfo->IsPersist() && resourceInfo->GetTimeOut() == 0)) {
277         BGTASK_LOGE("efficiency resources params invalid!");
278         return false;
279     }
280     return true;
281 }
282 
ApplyEfficiencyResources(const sptr<EfficiencyResourceInfo> & resourceInfo)283 ErrCode BgEfficiencyResourcesMgr::ApplyEfficiencyResources(
284     const sptr<EfficiencyResourceInfo> &resourceInfo)
285 {
286     BGTASK_LOGD("start bgtaskefficiency");
287     if (!isSysReady_.load()) {
288         BGTASK_LOGW("Efficiency resources manager is not ready");
289         return ERR_BGTASK_SYS_NOT_READY;
290     }
291 
292     if (!CheckResourceInfo(resourceInfo)) {
293         return ERR_BGTASK_RESOURCES_EXCEEDS_MAX;
294     }
295 
296     auto uid = IPCSkeleton::GetCallingUid();
297     auto pid = IPCSkeleton::GetCallingPid();
298     std::string bundleName = "";
299     if (!IsCallingInfoLegal(uid, pid, bundleName)) {
300         BGTASK_LOGI("apply efficiency resources failed, calling info is illegal");
301         return ERR_BGTASK_INVALID_PID_OR_UID;
302     }
303     if (!CheckRunningResourcesApply(uid, bundleName)) {
304         BGTASK_LOGE("apply efficiency resources failed, running resource apply is false");
305         return ERR_BGTASK_PERMISSION_DENIED;
306     }
307     if (!CheckProcApplyWorkScheduler(resourceInfo)) {
308         BGTASK_LOGW("apply work scheduler resources by process is not recommend");
309         return ERR_OK;
310     }
311     std::shared_ptr<ResourceCallbackInfo> callbackInfo = std::make_shared<ResourceCallbackInfo>(uid,
312         pid, resourceInfo->GetResourceNumber(), bundleName);
313     if (resourceInfo->IsApply()) {
314         handler_->PostTask([this, callbackInfo, resourceInfo]() {
315             this->ApplyEfficiencyResourcesInner(callbackInfo, resourceInfo);
316         });
317     } else {
318         handler_->PostTask([this, callbackInfo, resourceInfo]() {
319             this->ResetEfficiencyResourcesInner(callbackInfo, resourceInfo->IsProcess());
320         });
321     }
322     return ERR_OK;
323 }
324 
ApplyEfficiencyResourcesInner(std::shared_ptr<ResourceCallbackInfo> callbackInfo,const sptr<EfficiencyResourceInfo> & resourceInfo)325 void BgEfficiencyResourcesMgr::ApplyEfficiencyResourcesInner(std::shared_ptr<ResourceCallbackInfo>
326     callbackInfo, const sptr<EfficiencyResourceInfo> &resourceInfo)
327 {
328     BGTASK_LOGI("apply efficiency resources, uid:%{public}d, pid %{public}d, resource number: %{public}u,"\
329         "isPersist: %{public}d, timeOut: %{public}u, isProcess: %{public}d", callbackInfo->GetUid(),
330         callbackInfo->GetPid(), resourceInfo->GetResourceNumber(), resourceInfo->IsPersist(),
331         resourceInfo->GetTimeOut(), resourceInfo->IsProcess());
332     int32_t mapKey = resourceInfo->IsProcess() ? callbackInfo->GetPid() : callbackInfo->GetUid();
333     auto &infoMap = resourceInfo->IsProcess() ? procResourceApplyMap_ : appResourceApplyMap_;
334     uint32_t preResourceNumber = 0;
335     auto iter = infoMap.find(mapKey);
336     if (iter == infoMap.end()) {
337         infoMap.emplace(mapKey, std::make_shared<ResourceApplicationRecord>(callbackInfo->GetUid(),
338             callbackInfo->GetPid(), callbackInfo->GetResourceNumber(), callbackInfo->GetBundleName()));
339         iter = infoMap.find(mapKey);
340     } else {
341         preResourceNumber = iter->second->resourceNumber_;
342         iter->second->resourceNumber_ |= callbackInfo->GetResourceNumber();
343     }
344     BGTASK_LOGD("start to update resources end time");
345     UpdateResourcesEndtime(callbackInfo, iter->second, resourceInfo);
346     uint32_t diffResourceNumber = iter->second->resourceNumber_ ^ (preResourceNumber & iter->second->resourceNumber_);
347     if (diffResourceNumber == 0) {
348         BGTASK_LOGD("after update end time, diff between resourcesNumbers is zero");
349         DelayedSingleton<DataStorageHelper>::GetInstance()->RefreshResourceRecord(
350             appResourceApplyMap_, procResourceApplyMap_);
351         return;
352     }
353 
354     callbackInfo->SetResourceNumber(diffResourceNumber);
355     BGTASK_LOGI("after update end time, callbackInfo resource number is %{public}u,"\
356         " uid: %{public}d, bundle name: %{public}s", callbackInfo->GetResourceNumber(),
357         callbackInfo->GetUid(), callbackInfo->GetBundleName().c_str());
358     if (resourceInfo->IsProcess()) {
359         subscriberMgr_->OnResourceChanged(callbackInfo, EfficiencyResourcesEventType::RESOURCE_APPLY);
360     } else {
361         subscriberMgr_->OnResourceChanged(callbackInfo, EfficiencyResourcesEventType::APP_RESOURCE_APPLY);
362     }
363     DelayedSingleton<DataStorageHelper>::GetInstance()->RefreshResourceRecord(
364         appResourceApplyMap_, procResourceApplyMap_);
365 }
366 
UpdateResourcesEndtime(const std::shared_ptr<ResourceCallbackInfo> & callbackInfo,std::shared_ptr<ResourceApplicationRecord> & record,const sptr<EfficiencyResourceInfo> & resourceInfo)367 void BgEfficiencyResourcesMgr::UpdateResourcesEndtime(const std::shared_ptr<ResourceCallbackInfo>
368     &callbackInfo, std::shared_ptr<ResourceApplicationRecord> &record,
369     const sptr<EfficiencyResourceInfo> &resourceInfo)
370 {
371     for (uint32_t resourceIndex = 0; resourceIndex < MAX_RESOURCES_TYPE_NUM; ++resourceIndex) {
372         if ((callbackInfo->GetResourceNumber() & (1 << resourceIndex)) == 0) {
373             continue;
374         }
375         auto task = [resourceIndex](const auto &it) {
376             return it.resourceIndex_ == resourceIndex;
377         };
378         auto resourceUnitIter = std::find_if(record->resourceUnitList_.begin(),
379             record->resourceUnitList_.end(), task);
380         int64_t endtime = TimeProvider::GetCurrentTime() + static_cast<int64_t>(resourceInfo->GetTimeOut());
381         if (resourceUnitIter == record->resourceUnitList_.end()) {
382             if (resourceInfo->IsPersist()) {
383                 endtime = 0;
384             }
385             record->resourceUnitList_.emplace_back(PersistTime {resourceIndex, resourceInfo->IsPersist(),
386                 endtime, resourceInfo->GetReason()});
387         } else {
388             resourceUnitIter->reason_ = resourceInfo->GetReason();
389             resourceUnitIter->isPersist_ = resourceUnitIter->isPersist_ || resourceInfo->IsPersist();
390             if (resourceUnitIter->isPersist_) {
391                 resourceUnitIter->endTime_ = 0;
392             } else {
393                 resourceUnitIter->endTime_ = std::max(resourceUnitIter->endTime_,
394                     endtime);
395             }
396         }
397     }
398     BGTASK_LOGD("update end time of resource");
399     if (resourceInfo->IsPersist()) {
400         return;
401     }
402     const bool isProcess = resourceInfo->IsProcess();
403     int32_t mapKey = isProcess ? callbackInfo->GetPid() : callbackInfo->GetUid();
404     const auto& mgr = shared_from_this();
405     auto task = [mgr, mapKey, isProcess] () {
406         mgr->ResetTimeOutResource(mapKey, isProcess);
407     };
408     handler_->PostTask(task, resourceInfo->GetTimeOut());
409 }
410 
ResetTimeOutResource(int32_t mapKey,bool isProcess)411 void BgEfficiencyResourcesMgr::ResetTimeOutResource(int32_t mapKey, bool isProcess)
412 {
413     BGTASK_LOGD("ResetTimeOutResource reset efficiency rsources, mapkey: %{public}d",
414         mapKey);
415     auto &infoMap = isProcess ? procResourceApplyMap_ : appResourceApplyMap_;
416     auto type = isProcess ? EfficiencyResourcesEventType::RESOURCE_RESET :
417         EfficiencyResourcesEventType::APP_RESOURCE_RESET;
418     auto iter = infoMap.find(mapKey);
419     if (iter == infoMap.end()) {
420         BGTASK_LOGI("efficiency resource does not exist");
421         return;
422     }
423     auto &resourceRecord = iter->second;
424     uint32_t eraseBit = 0;
425     for (auto recordIter = resourceRecord->resourceUnitList_.begin();
426         recordIter != resourceRecord->resourceUnitList_.end(); ++recordIter) {
427         if (recordIter->isPersist_) {
428             continue;
429         }
430         auto endTime = recordIter->endTime_;
431         if (TimeProvider::GetCurrentTime() >= endTime) {
432             eraseBit |= 1 << recordIter->resourceIndex_;
433         }
434     }
435     BGTASK_LOGD("ResetTimeOutResource eraseBit: %{public}u, resourceNumber: %{public}u, result: %{public}u",
436         eraseBit, resourceRecord->resourceNumber_, resourceRecord->resourceNumber_ ^ eraseBit);
437     if (eraseBit == 0) {
438         BGTASK_LOGD("try to reset time out resources, but find nothing to reset");
439         return;
440     }
441     resourceRecord->resourceNumber_ ^= eraseBit;
442     RemoveListRecord(resourceRecord->resourceUnitList_, eraseBit);
443     auto callbackInfo = std::make_shared<ResourceCallbackInfo>(resourceRecord->uid_, resourceRecord->pid_, eraseBit,
444         resourceRecord->bundleName_);
445     BGTASK_LOGI("after reset time out resources, callbackInfo resource number is %{public}u,"\
446         " uid: %{public}d, bundle name: %{public}s", callbackInfo->GetResourceNumber(),
447         callbackInfo->GetUid(), callbackInfo->GetBundleName().c_str());
448     subscriberMgr_->OnResourceChanged(callbackInfo, type);
449     if (resourceRecord->resourceNumber_ == 0) {
450         infoMap.erase(iter);
451     }
452 }
453 
ResetAllEfficiencyResources()454 ErrCode BgEfficiencyResourcesMgr::ResetAllEfficiencyResources()
455 {
456     BGTASK_LOGD("start to reset all efficiency resources");
457     if (!isSysReady_.load()) {
458         BGTASK_LOGW("efficiency resources manager is not ready");
459         return ERR_BGTASK_SYS_NOT_READY;
460     }
461 
462     auto uid = IPCSkeleton::GetCallingUid();
463     auto pid = IPCSkeleton::GetCallingPid();
464     std::string bundleName = "";
465     if (!IsCallingInfoLegal(uid, pid, bundleName)) {
466         BGTASK_LOGE("reset efficiency resources failed, calling info is illegal");
467         return ERR_BGTASK_INVALID_PID_OR_UID;
468     }
469     if (!CheckRunningResourcesApply(uid, bundleName)) {
470         BGTASK_LOGE("reset efficiency resources failed, running resource apply is false");
471         return ERR_BGTASK_PERMISSION_DENIED;
472     }
473 
474     BGTASK_LOGD("reset efficiency resources uid : %{public}d, pid : %{public}d, resource number : %{public}d", uid,
475         pid, MAX_RESOURCE_NUMBER);
476     handler_->PostTask([this, uid, pid, bundleName]() {
477         std::shared_ptr<ResourceCallbackInfo> callbackInfo = std::make_shared<ResourceCallbackInfo>(uid,
478             pid, MAX_RESOURCE_NUMBER, bundleName);
479         this->ResetEfficiencyResourcesInner(callbackInfo, false);
480     });
481     return ERR_OK;
482 }
483 
RemoveRelativeProcessRecord(int32_t uid,uint32_t resourceNumber)484 void BgEfficiencyResourcesMgr::RemoveRelativeProcessRecord(int32_t uid, uint32_t resourceNumber)
485 {
486     for (auto iter = procResourceApplyMap_.begin(); iter != procResourceApplyMap_.end(); iter++) {
487         if (iter->second->uid_ == uid && (resourceNumber & iter->second->resourceNumber_) != 0) {
488             uint32_t eraseBit = (resourceNumber & iter->second->resourceNumber_);
489             std::shared_ptr<ResourceCallbackInfo> callbackInfo = std::make_shared<ResourceCallbackInfo>(uid,
490                 iter->second->pid_, eraseBit, iter->second->bundleName_);
491             handler_->PostTask([this, callbackInfo]() {
492                 this->ResetEfficiencyResourcesInner(callbackInfo, true);
493             });
494         }
495     }
496 }
497 
ResetEfficiencyResourcesInner(const std::shared_ptr<ResourceCallbackInfo> & callbackInfo,bool isProcess)498 void BgEfficiencyResourcesMgr::ResetEfficiencyResourcesInner(
499     const std::shared_ptr<ResourceCallbackInfo> &callbackInfo, bool isProcess)
500 {
501     BGTASK_LOGI("reset efficiency resources inner,  uid:%{public}d, pid %{public}d,"\
502         " resource number: %{public}u, isProcess: %{public}d", callbackInfo->GetUid(),
503         callbackInfo->GetPid(), callbackInfo->GetResourceNumber(), isProcess);
504     if (isProcess) {
505         RemoveTargetResourceRecord(procResourceApplyMap_, callbackInfo->GetPid(),
506             callbackInfo->GetResourceNumber(), EfficiencyResourcesEventType::RESOURCE_RESET);
507     } else {
508         RemoveTargetResourceRecord(appResourceApplyMap_, callbackInfo->GetUid(),
509             callbackInfo->GetResourceNumber(), EfficiencyResourcesEventType::APP_RESOURCE_RESET);
510         RemoveRelativeProcessRecord(callbackInfo->GetUid(), callbackInfo->GetResourceNumber());
511     }
512     DelayedSingleton<DataStorageHelper>::GetInstance()->RefreshResourceRecord(
513         appResourceApplyMap_, procResourceApplyMap_);
514 }
515 
IsCallingInfoLegal(int32_t uid,int32_t pid,std::string & bundleName)516 bool BgEfficiencyResourcesMgr::IsCallingInfoLegal(int32_t uid, int32_t pid, std::string &bundleName)
517 {
518     if (uid < 0 || pid < 0) {
519         BGTASK_LOGE("pid or uid is invalid");
520         return false;
521     }
522     bundleName = BundleManagerHelper::GetInstance()->GetClientBundleName(uid);
523     return true;
524 }
525 
AddSubscriber(const sptr<IBackgroundTaskSubscriber> & subscriber)526 ErrCode BgEfficiencyResourcesMgr::AddSubscriber(const sptr<IBackgroundTaskSubscriber> &subscriber)
527 {
528     BGTASK_LOGI("add subscriber to efficiency resources succeed");
529     return subscriberMgr_->AddSubscriber(subscriber);
530 }
531 
RemoveSubscriber(const sptr<IBackgroundTaskSubscriber> & subscriber)532 ErrCode BgEfficiencyResourcesMgr::RemoveSubscriber(const sptr<IBackgroundTaskSubscriber> &subscriber)
533 {
534     BGTASK_LOGD("remove subscriber to efficiency resources succeed");
535     return subscriberMgr_->RemoveSubscriber(subscriber);
536 }
537 
ShellDump(const std::vector<std::string> & dumpOption,std::vector<std::string> & dumpInfo)538 ErrCode BgEfficiencyResourcesMgr::ShellDump(const std::vector<std::string> &dumpOption,
539     std::vector<std::string> &dumpInfo)
540 {
541     if (!isSysReady_.load()) {
542         BGTASK_LOGE("manager is not ready");
543         return ERR_BGTASK_SYS_NOT_READY;
544     }
545     handler_->PostSyncTask([&]() {
546         this->ShellDumpInner(dumpOption, dumpInfo);
547     });
548     return ERR_OK;
549 }
550 
ShellDumpInner(const std::vector<std::string> & dumpOption,std::vector<std::string> & dumpInfo)551 ErrCode BgEfficiencyResourcesMgr::ShellDumpInner(const std::vector<std::string> &dumpOption,
552     std::vector<std::string> &dumpInfo)
553 {
554     if (dumpOption[1] == DUMP_PARAM_LIST_ALL) {
555         DumpAllApplicationInfo(dumpInfo);
556     } else if (dumpOption[1] == DUMP_PARAM_RESET_ALL) {
557         DumpResetAllResource(dumpInfo);
558     } else if (dumpOption[1] == DUMP_PARAM_RESET_APP) {
559         DumpResetResource(dumpOption, true, false);
560     } else if (dumpOption[1] == DUMP_PARAM_RESET_PROC) {
561         DumpResetResource(dumpOption, false, false);
562     }
563     DelayedSingleton<DataStorageHelper>::GetInstance()->RefreshResourceRecord(
564         appResourceApplyMap_, procResourceApplyMap_);
565     return ERR_OK;
566 }
567 
DumpAllApplicationInfo(std::vector<std::string> & dumpInfo)568 void BgEfficiencyResourcesMgr::DumpAllApplicationInfo(std::vector<std::string> &dumpInfo)
569 {
570     std::stringstream stream;
571     if (appResourceApplyMap_.empty() && procResourceApplyMap_.empty()) {
572         dumpInfo.emplace_back("No running efficiency resources\n");
573         return;
574     }
575     DumpApplicationInfoMap(appResourceApplyMap_, dumpInfo, stream, "app efficiency resource: \n");
576     DumpApplicationInfoMap(procResourceApplyMap_, dumpInfo, stream, "process efficiency resource: \n");
577 }
578 
DumpApplicationInfoMap(std::unordered_map<int32_t,std::shared_ptr<ResourceApplicationRecord>> & infoMap,std::vector<std::string> & dumpInfo,std::stringstream & stream,const char * headInfo)579 void BgEfficiencyResourcesMgr::DumpApplicationInfoMap(std::unordered_map<int32_t,
580     std::shared_ptr<ResourceApplicationRecord>> &infoMap, std::vector<std::string> &dumpInfo,
581     std::stringstream &stream, const char *headInfo)
582 {
583     uint32_t index = 1;
584     stream << headInfo << "\n";
585     for (auto iter = infoMap.begin(); iter != infoMap.end(); iter++) {
586         stream << "No." << index << "\n";
587         stream << "\tefficiencyResourceKey: " << iter->first << "\n";
588         stream << "\tefficiencyResourceValue:" << "\n";
589         stream << "\t\tbundleName: " << iter->second->GetBundleName() << "\n";
590         stream << "\t\tuid: " << iter->second->GetUid() << "\n";
591         stream << "\t\tpid: " << iter->second->GetPid() << "\n";
592         stream << "\t\tresourceNumber: " << iter->second->GetResourceNumber() << "\n";
593         int64_t curTime = TimeProvider::GetCurrentTime();
594         auto &resourceUnitList = iter->second->resourceUnitList_;
595         for (auto unitIter = resourceUnitList.begin();
596             unitIter != resourceUnitList.end(); ++unitIter) {
597             stream << "\t\t\tresource type: " << ResourceTypeName[unitIter->resourceIndex_] << "\n";
598             stream << "\t\t\tisPersist: " << (unitIter->isPersist_ ? "true" : "false") << "\n";
599             if (!unitIter->isPersist_) {
600                 stream << "\t\t\tremainTime: " << unitIter->endTime_ - curTime << "\n";
601             }
602             stream << "\t\t\treason: " << unitIter->reason_ << "\n";
603         }
604         stream << "\n";
605         dumpInfo.emplace_back(stream.str());
606         stream.str("");
607         stream.clear();
608         index++;
609     }
610 }
611 
DumpResetAllResource(const std::vector<std::string> & dumpOption)612 void BgEfficiencyResourcesMgr::DumpResetAllResource(const std::vector<std::string> &dumpOption)
613 {
614     DumpResetResource(dumpOption, true, true);
615     DumpResetResource(dumpOption, false, true);
616 }
617 
DumpResetResource(const std::vector<std::string> & dumpOption,bool cleanApp,bool cleanAll)618 void BgEfficiencyResourcesMgr::DumpResetResource(const std::vector<std::string> &dumpOption,
619     bool cleanApp, bool cleanAll)
620 {
621     auto &infoMap = cleanApp ? appResourceApplyMap_ : procResourceApplyMap_;
622     auto type = cleanApp ? EfficiencyResourcesEventType::APP_RESOURCE_RESET
623         : EfficiencyResourcesEventType::RESOURCE_RESET;
624 
625     if (cleanAll) {
626         for (auto iter = infoMap.begin(); iter != infoMap.end(); ++iter) {
627             std::shared_ptr<ResourceCallbackInfo> callbackInfo = std::make_shared<ResourceCallbackInfo>
628                 (iter->second->GetUid(), iter->second->GetPid(), iter->second->GetResourceNumber(),
629                 iter->second->GetBundleName());
630             subscriberMgr_->OnResourceChanged(callbackInfo, type);
631         }
632         infoMap.clear();
633     } else {
634         if (dumpOption.size() < MAX_DUMP_PARAM_NUMS) {
635             BGTASK_LOGW("invalid dump param");
636             return;
637         }
638         int32_t mapKey = std::atoi(dumpOption[2].c_str());
639         uint32_t cleanResource = static_cast<uint32_t>(std::atoi(dumpOption[3].c_str()));
640         RemoveTargetResourceRecord(infoMap, mapKey, cleanResource, type);
641     }
642 }
643 
RemoveTargetResourceRecord(std::unordered_map<int32_t,std::shared_ptr<ResourceApplicationRecord>> & infoMap,int32_t mapKey,uint32_t cleanResource,EfficiencyResourcesEventType type)644 bool BgEfficiencyResourcesMgr::RemoveTargetResourceRecord(std::unordered_map<int32_t,
645     std::shared_ptr<ResourceApplicationRecord>> &infoMap, int32_t mapKey, uint32_t cleanResource,
646     EfficiencyResourcesEventType type)
647 {
648     BGTASK_LOGD("resource record key: %{public}d, resource record size(): %{public}d",
649         mapKey, static_cast<int32_t>(infoMap.size()));
650     auto iter = infoMap.find(mapKey);
651     if (iter == infoMap.end() || (iter->second->resourceNumber_ & cleanResource) == 0) {
652         BGTASK_LOGW("remove single resource record failure, no matched task: %{public}d", mapKey);
653         return false;
654     }
655     uint32_t eraseBit = (iter->second->resourceNumber_ & cleanResource);
656     iter->second->resourceNumber_ ^= eraseBit;
657     RemoveListRecord(iter->second->resourceUnitList_, eraseBit);
658     auto callbackInfo = std::make_shared<ResourceCallbackInfo>(iter->second->GetUid(),
659         iter->second->GetPid(), eraseBit, iter->second->GetBundleName());
660     BGTASK_LOGI("remove record from info map, uid: %{public}d, bundle name: %{public}s",
661         callbackInfo->GetUid(), callbackInfo->GetBundleName().c_str());
662     subscriberMgr_->OnResourceChanged(callbackInfo, type);
663     if (iter->second->resourceNumber_ == 0) {
664         infoMap.erase(iter);
665     }
666     return true;
667 }
668 
RemoveListRecord(std::list<PersistTime> & resourceUnitList,uint32_t eraseBit)669 void BgEfficiencyResourcesMgr::RemoveListRecord(std::list<PersistTime> &resourceUnitList, uint32_t eraseBit)
670 {
671     BGTASK_LOGD("start remove record from list, eraseBit: %{public}d", eraseBit);
672     if (eraseBit == 0) {
673         return;
674     }
675     for (auto it = resourceUnitList.begin(); it != resourceUnitList.end();) {
676         if (((1 << it->resourceIndex_) & eraseBit) != 0) {
677             it = resourceUnitList.erase(it);
678         } else {
679             ++it;
680         }
681     }
682 }
683 
GetEfficiencyResourcesInfos(std::vector<std::shared_ptr<ResourceCallbackInfo>> & appList,std::vector<std::shared_ptr<ResourceCallbackInfo>> & procList)684 ErrCode BgEfficiencyResourcesMgr::GetEfficiencyResourcesInfos(std::vector<std::shared_ptr<
685     ResourceCallbackInfo>> &appList, std::vector<std::shared_ptr<ResourceCallbackInfo>> &procList)
686 {
687     handler_->PostSyncTask([this, &appList, &procList]() {
688         this->GetEfficiencyResourcesInfosInner(appResourceApplyMap_, appList);
689         this->GetEfficiencyResourcesInfosInner(procResourceApplyMap_, procList);
690         }, AppExecFwk::EventQueue::Priority::HIGH);
691 
692     return ERR_OK;
693 }
694 
GetEfficiencyResourcesInfosInner(const ResourceRecordMap & infoMap,std::vector<std::shared_ptr<ResourceCallbackInfo>> & list)695 void BgEfficiencyResourcesMgr::GetEfficiencyResourcesInfosInner(const ResourceRecordMap &infoMap,
696     std::vector<std::shared_ptr<ResourceCallbackInfo>> &list)
697 {
698     if (infoMap.empty()) {
699         return;
700     }
701     BGTASK_LOGD("get efficiency resources info inner function, resources record size(): %{public}d ",
702         static_cast<int32_t>(infoMap.size()));
703     for (auto &record : infoMap) {
704         auto appInfo = std::make_shared<ResourceCallbackInfo>(record.second->uid_, record.second->pid_,
705             record.second->resourceNumber_, record.second->bundleName_);
706         list.push_back(appInfo);
707     }
708 }
709 
CheckRunningResourcesApply(const int32_t uid,const std::string & bundleName)710 bool BgEfficiencyResourcesMgr::CheckRunningResourcesApply(const int32_t uid, const std::string &bundleName)
711 {
712     AppExecFwk::ApplicationInfo applicationInfo;
713     if (!BundleManagerHelper::GetInstance()->GetApplicationInfo(bundleName,
714         AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, GetUserIdByUid(uid), applicationInfo)) {
715         BGTASK_LOGE("failed to get applicationInfo from AppExecFwk, bundleName is %{public}s", bundleName.c_str());
716         return false;
717     }
718     BGTASK_LOGD("applicationInfo.runningResourcesApply is %{public}d", applicationInfo.runningResourcesApply);
719     return applicationInfo.runningResourcesApply;
720 }
721 
GetUserIdByUid(int32_t uid)722 int32_t BgEfficiencyResourcesMgr::GetUserIdByUid(int32_t uid)
723 {
724     const int32_t BASE_USER_RANGE = 200000;
725     return uid / BASE_USER_RANGE;
726 }
727 
CheckProcApplyWorkScheduler(const sptr<EfficiencyResourceInfo> & resourceInfo)728 bool BgEfficiencyResourcesMgr::CheckProcApplyWorkScheduler(const sptr<EfficiencyResourceInfo> &resourceInfo)
729 {
730     if (resourceInfo->IsProcess() && (resourceInfo->GetResourceNumber() & ResourceType::WORK_SCHEDULER) != 0) {
731         int resourceNumber = resourceInfo->GetResourceNumber() ^ ResourceType::WORK_SCHEDULER;
732         if (resourceNumber != 0) {
733             sptr<EfficiencyResourceInfo> procResourceInfo = new (std::nothrow) EfficiencyResourceInfo(*resourceInfo);
734             procResourceInfo->SetResourceNumber(resourceNumber);
735             ApplyEfficiencyResources(procResourceInfo);
736         }
737         sptr<EfficiencyResourceInfo> appResourceInfo = new (std::nothrow) EfficiencyResourceInfo(*resourceInfo);
738         appResourceInfo->SetResourceNumber(ResourceType::WORK_SCHEDULER);
739         appResourceInfo->SetProcess(false);
740         ApplyEfficiencyResources(appResourceInfo);
741         return false;
742     }
743     return true;
744 }
745 }  // namespace BackgroundTaskMgr
746 }  // namespace OHOS
747