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