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