1 /*
2 * Copyright (c) 2022-2025 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_transient_task_mgr.h"
17
18 #include <file_ex.h>
19 #include <ipc_skeleton.h>
20 #include <sstream>
21 #include <system_ability.h>
22 #include <system_ability_definition.h>
23
24 #include "accesstoken_kit.h"
25 #include "bundle_mgr_proxy.h"
26 #include "common_event_data.h"
27 #include "common_event_manager.h"
28 #include "common_event_support.h"
29 #include "if_system_ability_manager.h"
30 #include "iservice_registry.h"
31 #include "want.h"
32
33 #include "background_task_mgr_service.h"
34 #include "bgtask_hitrace_chain.h"
35 #include "bgtaskmgr_inner_errors.h"
36 #include "time_provider.h"
37 #include "transient_task_log.h"
38 #include "hitrace_meter.h"
39
40 using namespace std;
41
42 namespace OHOS {
43 namespace BackgroundTaskMgr {
44 namespace {
45 static const std::string ALL_BGTASKMGR_OPTION = "All";
46 static const std::string LOW_BATTARY_OPTION = "BATTARY_LOW";
47 static const std::string OKAY_BATTARY_OPTION = "BATTARY_OKAY";
48 static const std::string CANCEL_DUMP_OPTION = "DUMP_CANCEL";
49 static const std::string PAUSE_DUMP_OPTION = "PAUSE";
50 static const std::string START_DUMP_OPTION = "START";
51 static const int32_t DUMP_PARAM_INDEX_TWO = 2;
52
53 constexpr int32_t BG_INVALID_REMAIN_TIME = -1;
54 constexpr int32_t WATCHDOG_DELAY_TIME = 6 * MSEC_PER_SEC;
55 constexpr int32_t SERVICE_WAIT_TIME = 2000;
56
57 const std::set<std::string> SUSPEND_NATIVE_OPERATE_CALLER = {
58 "resource_schedule_service",
59 "hidumper_service",
60 };
61 }
62
63 #ifdef BGTASK_MGR_UNIT_TEST
64 #define WEAK_FUNC __attribute__((weak))
65 #else
66 #define WEAK_FUNC
67 #endif
68
BgTransientTaskMgr()69 BgTransientTaskMgr::BgTransientTaskMgr() {}
~BgTransientTaskMgr()70 BgTransientTaskMgr::~BgTransientTaskMgr() {}
71
Init(const std::shared_ptr<AppExecFwk::EventRunner> & runner)72 void BgTransientTaskMgr::Init(const std::shared_ptr<AppExecFwk::EventRunner>& runner)
73 {
74 BGTASK_LOGI("BgTransientTaskMgr service init start");
75 if (runner == nullptr) {
76 BGTASK_LOGE("Failed to init due to create runner error");
77 return;
78 }
79 handler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
80 if (!handler_) {
81 BGTASK_LOGE("Failed to init due to create handler error");
82 }
83 callbackDeathRecipient_ = new (std::nothrow)
84 ExpiredCallbackDeathRecipient(DelayedSingleton<BackgroundTaskMgrService>::GetInstance().get());
85 susriberDeathRecipient_ = new (std::nothrow)
86 SubscriberDeathRecipient(DelayedSingleton<BackgroundTaskMgrService>::GetInstance().get());
87
88 InitNecessaryState(runner);
89 }
90
InitNecessaryState(const std::shared_ptr<AppExecFwk::EventRunner> & runner)91 void BgTransientTaskMgr::InitNecessaryState(const std::shared_ptr<AppExecFwk::EventRunner>& runner)
92 {
93 sptr<ISystemAbilityManager> systemAbilityManager
94 = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
95 if (systemAbilityManager == nullptr
96 || systemAbilityManager->CheckSystemAbility(APP_MGR_SERVICE_ID) == nullptr
97 || systemAbilityManager->CheckSystemAbility(COMMON_EVENT_SERVICE_ID) == nullptr
98 || systemAbilityManager->CheckSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID) == nullptr) {
99 isReady_.store(false);
100 BGTASK_LOGI("request system service is not ready yet!");
101 auto InitNecessaryStateFunc = [this, runner] { this->InitNecessaryState(runner); };
102 handler_->PostTask(InitNecessaryStateFunc, SERVICE_WAIT_TIME);
103 return;
104 }
105
106 deviceInfoManeger_ = make_shared<DeviceInfoManager>();
107 timerManager_ = make_shared<TimerManager>(DelayedSingleton<BackgroundTaskMgrService>::GetInstance().get(), runner);
108 decisionMaker_ = make_shared<DecisionMaker>(timerManager_, deviceInfoManeger_);
109 watchdog_ = make_shared<Watchdog>(DelayedSingleton<BackgroundTaskMgrService>::GetInstance().get(),
110 decisionMaker_, runner);
111
112 inputManager_ = make_shared<InputManager>(runner);
113 if (inputManager_ == nullptr) {
114 BGTASK_LOGE("Fail to make inputManager");
115 return;
116 }
117 inputManager_->RegisterEventHub();
118 inputManager_->RegisterEventListener(deviceInfoManeger_);
119 inputManager_->RegisterEventListener(decisionMaker_);
120 isReady_.store(true);
121 DelayedSingleton<BackgroundTaskMgrService>::GetInstance()->SetReady(ServiceReadyState::TRANSIENT_SERVICE_READY);
122 BGTASK_LOGI("SetReady TRANSIENT_SERVICE_READY");
123 }
124
GetBundleNamesForUid(int32_t uid,std::string & bundleName)125 bool BgTransientTaskMgr::GetBundleNamesForUid(int32_t uid, std::string &bundleName)
126 {
127 sptr<ISystemAbilityManager> systemMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
128 if (systemMgr == nullptr) {
129 BGTASK_LOGE("Fail to get system ability mgr");
130 return false;
131 }
132
133 sptr<IRemoteObject> remoteObject = systemMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
134 if (remoteObject == nullptr) {
135 BGTASK_LOGE("Fail to get bundle manager proxy");
136 return false;
137 }
138
139 sptr<OHOS::AppExecFwk::IBundleMgr> bundleMgrProxy = iface_cast<OHOS::AppExecFwk::IBundleMgr>(remoteObject);
140 if (bundleMgrProxy == nullptr) {
141 BGTASK_LOGE("Bundle mgr proxy is nullptr");
142 return false;
143 }
144
145 if (bundleMgrProxy->GetNameForUid(uid, bundleName) != ERR_OK) {
146 BGTASK_LOGE("Get bundle name failed");
147 return false;
148 }
149 return true;
150 }
151
IsCallingInfoLegal(int32_t uid,int32_t pid,std::string & name,const sptr<IExpiredCallback> & callback)152 ErrCode BgTransientTaskMgr::IsCallingInfoLegal(int32_t uid, int32_t pid, std::string &name,
153 const sptr<IExpiredCallback>& callback)
154 {
155 if (!VerifyCallingInfo(uid, pid)) {
156 BGTASK_LOGE("pid or uid is invalid.");
157 return ERR_BGTASK_INVALID_PID_OR_UID;
158 }
159
160 if (!GetBundleNamesForUid(uid, name)) {
161 BGTASK_LOGE("GetBundleNamesForUid fail.");
162 return ERR_BGTASK_INVALID_BUNDLE_NAME;
163 }
164
165 if (callback == nullptr) {
166 BGTASK_LOGE("callback is null.");
167 return ERR_BGTASK_INVALID_CALLBACK;
168 }
169
170 if (callback->AsObject() == nullptr) {
171 BGTASK_LOGE("remote in callback is null.");
172 return ERR_BGTASK_INVALID_CALLBACK;
173 }
174 return ERR_OK;
175 }
176
RequestSuspendDelay(const std::u16string & reason,const sptr<IExpiredCallback> & callback,std::shared_ptr<DelaySuspendInfo> & delayInfo)177 ErrCode BgTransientTaskMgr::RequestSuspendDelay(const std::u16string& reason,
178 const sptr<IExpiredCallback>& callback, std::shared_ptr<DelaySuspendInfo> &delayInfo)
179 {
180 BgTaskHiTraceChain traceChain(__func__);
181 HitraceScoped traceScoped(HITRACE_TAG_OHOS,
182 "BackgroundTaskManager::TransientTask::Service::RequestSuspendDelay");
183
184 if (!isReady_.load()) {
185 BGTASK_LOGW("Transient task manager is not ready.");
186 return ERR_BGTASK_SYS_NOT_READY;
187 }
188 auto uid = IPCSkeleton::GetCallingUid();
189 auto pid = IPCSkeleton::GetCallingPid();
190 std::string name = "";
191 ErrCode ret = IsCallingInfoLegal(uid, pid, name, callback);
192 if (ret != ERR_OK) {
193 BGTASK_LOGI("Request suspend delay failed, calling info is illegal.");
194 return ret;
195 }
196 BGTASK_LOGD("request suspend delay pkg : %{public}s, reason : %{public}s, uid : %{public}d, pid : %{public}d",
197 name.c_str(), Str16ToStr8(reason).c_str(), uid, pid);
198
199 auto infoEx = make_shared<DelaySuspendInfoEx>(pid);
200 delayInfo = infoEx;
201 auto remote = callback->AsObject();
202 lock_guard<mutex> lock(expiredCallbackLock_);
203 auto findCallback = [&callback](const auto& callbackMap) {
204 return callback->AsObject() == callbackMap.second->AsObject();
205 };
206
207 auto callbackIter = find_if(expiredCallbackMap_.begin(), expiredCallbackMap_.end(), findCallback);
208 if (callbackIter != expiredCallbackMap_.end()) {
209 BGTASK_LOGI("%{public}s request suspend failed, callback is already exists.", name.c_str());
210 return ERR_BGTASK_CALLBACK_EXISTS;
211 }
212
213 auto keyInfo = make_shared<KeyInfo>(name, uid, pid);
214 ret = decisionMaker_->Decide(keyInfo, infoEx);
215 if (ret != ERR_OK) {
216 BGTASK_LOGI("%{public}s request suspend failed.", name.c_str());
217 return ret;
218 }
219 BGTASK_LOGI("request suspend success, pkg : %{public}s, uid : %{public}d, requestId: %{public}d,"
220 "delayTime: %{public}d", name.c_str(), uid, infoEx->GetRequestId(), infoEx->GetActualDelayTime());
221 expiredCallbackMap_[infoEx->GetRequestId()] = callback;
222 keyInfoMap_[infoEx->GetRequestId()] = keyInfo;
223 if (callbackDeathRecipient_ != nullptr) {
224 (void)remote->AddDeathRecipient(callbackDeathRecipient_);
225 }
226
227 return ERR_OK;
228 }
229
CheckProcessName()230 bool WEAK_FUNC BgTransientTaskMgr::CheckProcessName()
231 {
232 Security::AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
233 Security::AccessToken::NativeTokenInfo callingTokenInfo;
234 Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(tokenId, callingTokenInfo);
235 if (SUSPEND_NATIVE_OPERATE_CALLER.find(callingTokenInfo.processName) == SUSPEND_NATIVE_OPERATE_CALLER.end()) {
236 return false;
237 }
238 return true;
239 }
240
PauseTransientTaskTimeForInner(int32_t uid)241 ErrCode BgTransientTaskMgr::PauseTransientTaskTimeForInner(int32_t uid)
242 {
243 if (!isReady_.load()) {
244 BGTASK_LOGW("Transient task manager is not ready.");
245 return ERR_BGTASK_SYS_NOT_READY;
246 }
247
248 if (!CheckProcessName()) {
249 return ERR_BGTASK_INVALID_PROCESS_NAME;
250 }
251
252 if (uid < 0) {
253 BGTASK_LOGE("PauseTransientTaskTimeForInner uid is invalid.");
254 return ERR_BGTASK_INVALID_PID_OR_UID;
255 }
256
257 std::string name = "";
258 if (!GetBundleNamesForUid(uid, name)) {
259 BGTASK_LOGE("GetBundleNamesForUid fail, uid : %{public}d.", uid);
260 return ERR_BGTASK_SERVICE_INNER_ERROR;
261 }
262
263 ErrCode ret = decisionMaker_->PauseTransientTaskTimeForInner(uid, name);
264 if (ret != ERR_OK) {
265 BGTASK_LOGE("pkgname: %{public}s, uid: %{public}d PauseTransientTaskTimeForInner fail.",
266 name.c_str(), uid);
267 return ret;
268 }
269 lock_guard<mutex> lock(transientUidLock_);
270 transientPauseUid_.insert(uid);
271 return ERR_OK;
272 }
273
StartTransientTaskTimeForInner(int32_t uid)274 ErrCode BgTransientTaskMgr::StartTransientTaskTimeForInner(int32_t uid)
275 {
276 if (!isReady_.load()) {
277 BGTASK_LOGW("Transient task manager is not ready.");
278 return ERR_BGTASK_SYS_NOT_READY;
279 }
280
281 if (!CheckProcessName()) {
282 return ERR_BGTASK_INVALID_PROCESS_NAME;
283 }
284
285 if (uid < 0) {
286 BGTASK_LOGE("StartTransientTaskTimeForInner uid is invalid.");
287 return ERR_BGTASK_INVALID_PID_OR_UID;
288 }
289
290 std::string name = "";
291 if (!GetBundleNamesForUid(uid, name)) {
292 BGTASK_LOGE("GetBundleNamesForUid fail, uid : %{public}d.", uid);
293 return ERR_BGTASK_SERVICE_INNER_ERROR;
294 }
295
296 ErrCode ret = decisionMaker_->StartTransientTaskTimeForInner(uid, name);
297 if (ret != ERR_OK) {
298 BGTASK_LOGE("pkgname: %{public}s, uid: %{public}d StartTransientTaskTimeForInner fail.",
299 name.c_str(), uid);
300 return ret;
301 }
302 lock_guard<mutex> lock(transientUidLock_);
303 transientPauseUid_.erase(uid);
304 return ERR_OK;
305 }
306
HandleTransientTaskSuscriberTask(const shared_ptr<TransientTaskAppInfo> & appInfo,const TransientTaskEventType type)307 void BgTransientTaskMgr::HandleTransientTaskSuscriberTask(const shared_ptr<TransientTaskAppInfo>& appInfo,
308 const TransientTaskEventType type)
309 {
310 if (handler_ == nullptr) {
311 BGTASK_LOGE("HandleTransientTaskSuscriberTask handler is not init.");
312 return;
313 }
314 handler_->PostTask([=]() {
315 NotifyTransientTaskSuscriber(appInfo, type);
316 });
317 }
318
NotifyTransientTaskSuscriber(const shared_ptr<TransientTaskAppInfo> & appInfo,const TransientTaskEventType type)319 void BgTransientTaskMgr::NotifyTransientTaskSuscriber(const shared_ptr<TransientTaskAppInfo>& appInfo,
320 const TransientTaskEventType type)
321 {
322 if (appInfo == nullptr) {
323 BGTASK_LOGE("NotifyTransientTaskSuscriber failed, appInfo is null.");
324 return;
325 }
326 if (subscriberList_.empty()) {
327 BGTASK_LOGI("Transient Task Subscriber List is empty");
328 return;
329 }
330 const TransientTaskAppInfo& appInfoRef = *appInfo;
331 switch (type) {
332 case TransientTaskEventType::TASK_START:
333 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); iter++) {
334 (*iter)->OnTransientTaskStart(appInfoRef);
335 }
336 break;
337 case TransientTaskEventType::TASK_END:
338 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); iter++) {
339 (*iter)->OnTransientTaskEnd(appInfoRef);
340 }
341 break;
342 case TransientTaskEventType::TASK_ERR:
343 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); iter++) {
344 (*iter)->OnTransientTaskErr(appInfoRef);
345 }
346 break;
347 case TransientTaskEventType::APP_TASK_START:
348 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); iter++) {
349 (*iter)->OnAppTransientTaskStart(appInfoRef);
350 }
351 break;
352 case TransientTaskEventType::APP_TASK_END:
353 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); iter++) {
354 (*iter)->OnAppTransientTaskEnd(appInfoRef);
355 }
356 break;
357 default:
358 break;
359 }
360 }
361
CancelSuspendDelay(int32_t requestId)362 ErrCode BgTransientTaskMgr::CancelSuspendDelay(int32_t requestId)
363 {
364 HitraceScoped traceScoped(HITRACE_TAG_OHOS,
365 "BackgroundTaskManager::TransientTask::Service::CancelSuspendDelay");
366
367 if (!isReady_.load()) {
368 BGTASK_LOGE("Transient task manager is not ready.");
369 return ERR_BGTASK_SYS_NOT_READY;
370 }
371 auto uid = IPCSkeleton::GetCallingUid();
372 auto pid = IPCSkeleton::GetCallingPid();
373 if (!VerifyCallingInfo(uid, pid)) {
374 BGTASK_LOGI("cancel suspend delay failed, pid or uid is invalid.");
375 return ERR_BGTASK_INVALID_PID_OR_UID;
376 }
377
378 std::string name = "";
379 if (!GetBundleNamesForUid(uid, name)) {
380 BGTASK_LOGW("GetBundleNamesForUid fail, uid : %{public}d.", uid);
381 return ERR_BGTASK_SERVICE_INNER_ERROR;
382 }
383 BGTASK_LOGI("cancel suspend delay pkg : %{public}s, uid : %{public}d, requestId : %{public}d",
384 name.c_str(), uid, requestId);
385
386 lock_guard<mutex> lock(expiredCallbackLock_);
387 if (!VerifyRequestIdLocked(name, uid, requestId)) {
388 BGTASK_LOGI(" cancel suspend delay failed, requestId is illegal.");
389 return ERR_BGTASK_INVALID_REQUEST_ID;
390 }
391
392 return CancelSuspendDelayLocked(requestId);
393 }
394
CancelSuspendDelayLocked(int32_t requestId)395 ErrCode BgTransientTaskMgr::CancelSuspendDelayLocked(int32_t requestId)
396 {
397 watchdog_->RemoveWatchdog(requestId);
398 decisionMaker_->RemoveRequest(keyInfoMap_[requestId], requestId);
399 keyInfoMap_.erase(requestId);
400
401 auto iter = expiredCallbackMap_.find(requestId);
402 if (iter == expiredCallbackMap_.end()) {
403 BGTASK_LOGI("CancelSuspendDelayLocked Callback not found.");
404 return ERR_BGTASK_CALLBACK_NOT_EXIST;
405 }
406 auto remote = iter->second->AsObject();
407 if (remote != nullptr) {
408 remote->RemoveDeathRecipient(callbackDeathRecipient_);
409 }
410 expiredCallbackMap_.erase(iter);
411 return ERR_OK;
412 }
413
ForceCancelSuspendDelay(int32_t requestId)414 void BgTransientTaskMgr::ForceCancelSuspendDelay(int32_t requestId)
415 {
416 lock_guard<mutex> lock(expiredCallbackLock_);
417 auto keyInfoIter = keyInfoMap_.find(requestId);
418 if (keyInfoIter == keyInfoMap_.end()) {
419 BGTASK_LOGI("force cancel suspend delay failed callback not found.");
420 return;
421 }
422
423 CancelSuspendDelayLocked(requestId);
424 }
425
GetRemainingDelayTime(int32_t requestId,int32_t & delayTime)426 ErrCode BgTransientTaskMgr::GetRemainingDelayTime(int32_t requestId, int32_t &delayTime)
427 {
428 HitraceScoped traceScoped(HITRACE_TAG_OHOS,
429 "BackgroundTaskManager::TransientTask::Service::GetRemainingDelayTime");
430
431 if (!isReady_.load()) {
432 BGTASK_LOGW("Transient task manager is not ready.");
433 return ERR_BGTASK_SYS_NOT_READY;
434 }
435 auto uid = IPCSkeleton::GetCallingUid();
436 auto pid = IPCSkeleton::GetCallingPid();
437 if (!VerifyCallingInfo(uid, pid)) {
438 BGTASK_LOGI("get remain time failed, uid or pid is invalid");
439 delayTime = BG_INVALID_REMAIN_TIME;
440 return ERR_BGTASK_INVALID_PID_OR_UID;
441 }
442
443 std::string name = "";
444 if (!GetBundleNamesForUid(uid, name)) {
445 BGTASK_LOGE("GetBundleNamesForUid fail.");
446 delayTime = BG_INVALID_REMAIN_TIME;
447 return ERR_BGTASK_SERVICE_INNER_ERROR;
448 }
449 BGTASK_LOGI("get remain time pkg : %{public}s, uid : %{public}d, requestId : %{public}d",
450 name.c_str(), uid, requestId);
451
452 lock_guard<mutex> lock(expiredCallbackLock_);
453 if (!VerifyRequestIdLocked(name, uid, requestId)) {
454 BGTASK_LOGE("get remain time failed, requestId is illegal.");
455 delayTime = BG_INVALID_REMAIN_TIME;
456 return ERR_BGTASK_INVALID_REQUEST_ID;
457 }
458
459 delayTime = decisionMaker_->GetRemainingDelayTime(keyInfoMap_[requestId], requestId);
460 return ERR_OK;
461 }
462
GetAllTransientTasks(int32_t & remainingQuota,std::vector<std::shared_ptr<DelaySuspendInfo>> & list)463 ErrCode BgTransientTaskMgr::GetAllTransientTasks(int32_t &remainingQuota,
464 std::vector<std::shared_ptr<DelaySuspendInfo>> &list)
465 {
466 HitraceScoped traceScoped(HITRACE_TAG_OHOS,
467 "BackgroundTaskManager::TransientTask::Service::GetAllTransientTasks");
468 if (!isReady_.load()) {
469 BGTASK_LOGW("Transient task manager is not ready.");
470 return ERR_BGTASK_TRANSIENT_SYS_NOT_READY;
471 }
472 auto uid = IPCSkeleton::GetCallingUid();
473 auto pid = IPCSkeleton::GetCallingPid();
474 if (!VerifyCallingInfo(uid, pid)) {
475 BGTASK_LOGE("get remain time failed, uid: %{public}d or pid: %{public}d is invalid", uid, pid);
476 return ERR_BGTASK_INVALID_PID_OR_UID;
477 }
478 std::string name = "";
479 if (!GetBundleNamesForUid(uid, name)) {
480 BGTASK_LOGE("GetBundleNamesForUid fail.");
481 return ERR_BGTASK_SERVICE_INNER_ERROR;
482 }
483 auto keyInfo = std::make_shared<KeyInfo>(name, uid, pid);
484 remainingQuota = decisionMaker_->GetQuota(keyInfo);
485 lock_guard<mutex> lock(expiredCallbackLock_);
486 if (keyInfoMap_.empty()) {
487 BGTASK_LOGD("not have transient task, pkg : %{public}s, uid : %{public}d", name.c_str(), uid);
488 return ERR_OK;
489 }
490 for (const auto &record : keyInfoMap_) {
491 if (!record.second) {
492 continue;
493 }
494 if (record.second->GetPkg() != name || record.second->GetUid() != uid) {
495 continue;
496 }
497 auto info = std::make_shared<DelaySuspendInfo>();
498 info->SetRequestId(record.first);
499 info->SetActualDelayTime(decisionMaker_->GetRemainingDelayTime(record.second, record.first));
500 list.push_back(info);
501 }
502 BGTASK_LOGI("get transient task, pkg : %{public}s, uid : %{public}d", name.c_str(), uid);
503 return ERR_OK;
504 }
505
VerifyCallingInfo(int32_t uid,int32_t pid)506 bool BgTransientTaskMgr::VerifyCallingInfo(int32_t uid, int32_t pid)
507 {
508 return (uid >= 0) && (pid >= 0);
509 }
510
VerifyRequestIdLocked(const std::string & name,int32_t uid,int32_t requestId)511 bool BgTransientTaskMgr::VerifyRequestIdLocked(const std::string& name, int32_t uid, int32_t requestId)
512 {
513 auto keyInfoIter = keyInfoMap_.find(requestId);
514 if (keyInfoIter == keyInfoMap_.end()) {
515 return false;
516 }
517 return keyInfoIter->second->IsEqual(name, uid);
518 }
519
HandleExpiredCallbackDeath(const wptr<IRemoteObject> & remote)520 void BgTransientTaskMgr::HandleExpiredCallbackDeath(const wptr<IRemoteObject>& remote)
521 {
522 if (remote == nullptr) {
523 BGTASK_LOGE("expiredCallback death, remote in callback is null.");
524 return;
525 }
526
527 lock_guard<mutex> lock(expiredCallbackLock_);
528 auto findCallback = [&remote](const auto& callbackMap) {
529 return callbackMap.second->AsObject() == remote;
530 };
531
532 auto callbackIter = find_if(expiredCallbackMap_.begin(), expiredCallbackMap_.end(), findCallback);
533 if (callbackIter == expiredCallbackMap_.end()) {
534 BGTASK_LOGI("expiredCallback death, remote in callback not found.");
535 return;
536 }
537
538 watchdog_->RemoveWatchdog(callbackIter->first);
539 auto keyInfoIter = keyInfoMap_.find(callbackIter->first);
540 expiredCallbackMap_.erase(callbackIter);
541 if (keyInfoIter == keyInfoMap_.end()) {
542 BGTASK_LOGI("expiredCallback death, keyInfo not found.");
543 return;
544 }
545
546 BGTASK_LOGI("expiredCallback death, %{public}s, requestId : %{public}d", keyInfoIter->second->ToString().c_str(),
547 keyInfoIter->first);
548 decisionMaker_->RemoveRequest(keyInfoIter->second, keyInfoIter->first);
549 keyInfoMap_.erase(keyInfoIter);
550 }
551
HandleSubscriberDeath(const wptr<IRemoteObject> & remote)552 void BgTransientTaskMgr::HandleSubscriberDeath(const wptr<IRemoteObject>& remote)
553 {
554 if (remote == nullptr) {
555 BGTASK_LOGE("suscriber death, remote in suscriber is null.");
556 return;
557 }
558
559 handler_->PostSyncTask([&]() {
560 auto findSuscriber = [&remote](const auto& subscriberList) {
561 return remote == subscriberList->AsObject();
562 };
563 auto subscriberIter = find_if(subscriberList_.begin(), subscriberList_.end(), findSuscriber);
564 if (subscriberIter == subscriberList_.end()) {
565 BGTASK_LOGI("suscriber death, remote in suscriber not found.");
566 return;
567 }
568
569 subscriberList_.erase(subscriberIter);
570 BGTASK_LOGI("suscriber death, remove it.");
571 });
572 }
573
HandleRequestExpired(const int32_t requestId)574 void BgTransientTaskMgr::HandleRequestExpired(const int32_t requestId)
575 {
576 BGTASK_LOGI("request expired, id : %{public}d", requestId);
577
578 std::lock_guard<std::mutex> lock(expiredCallbackLock_);
579 auto callbackIter = expiredCallbackMap_.find(requestId);
580 if (callbackIter == expiredCallbackMap_.end()) {
581 BGTASK_LOGE("request expired, callback not found.");
582 return;
583 }
584 callbackIter->second->OnExpired();
585
586 auto keyInfoIter = keyInfoMap_.find(requestId);
587 if (keyInfoIter == keyInfoMap_.end()) {
588 BGTASK_LOGE("request expired, keyinfo not found.");
589 return;
590 }
591 watchdog_->AddWatchdog(requestId, keyInfoIter->second, WATCHDOG_DELAY_TIME);
592 }
593
SubscribeBackgroundTask(const sptr<IBackgroundTaskSubscriber> & subscriber)594 ErrCode BgTransientTaskMgr::SubscribeBackgroundTask(const sptr<IBackgroundTaskSubscriber>& subscriber)
595 {
596 if (subscriber == nullptr) {
597 BGTASK_LOGI("subscriber is null.");
598 return ERR_BGTASK_INVALID_PARAM;
599 }
600 auto remote = subscriber->AsObject();
601 if (remote == nullptr) {
602 BGTASK_LOGE("request suspend delay failed, remote in subscriber is null.");
603 return ERR_BGTASK_INVALID_PARAM;
604 }
605
606 handler_->PostSyncTask([=]() {
607 auto findSuscriber = [&remote](const auto& subscriberList) {
608 return remote == subscriberList->AsObject();
609 };
610 auto subscriberIter = find_if(subscriberList_.begin(), subscriberList_.end(), findSuscriber);
611 if (subscriberIter != subscriberList_.end()) {
612 BGTASK_LOGE("request subscriber is already exists.");
613 return;
614 }
615
616 if (susriberDeathRecipient_ != nullptr) {
617 remote->AddDeathRecipient(susriberDeathRecipient_);
618 }
619 subscriberList_.emplace_back(subscriber);
620 BGTASK_LOGI("subscribe transient task success.");
621 });
622 return ERR_OK;
623 }
624
UnsubscribeBackgroundTask(const sptr<IBackgroundTaskSubscriber> & subscriber)625 ErrCode BgTransientTaskMgr::UnsubscribeBackgroundTask(const sptr<IBackgroundTaskSubscriber>& subscriber)
626 {
627 if (subscriber == nullptr) {
628 BGTASK_LOGE("subscriber is null.");
629 return ERR_BGTASK_INVALID_PARAM;
630 }
631 auto remote = subscriber->AsObject();
632 if (remote == nullptr) {
633 BGTASK_LOGE("request suspend delay failed, remote in subscriber is null.");
634 return ERR_BGTASK_INVALID_PARAM;
635 }
636
637 handler_->PostSyncTask([=]() {
638 auto findSuscriber = [&remote](const auto& subscriberList) {
639 return remote == subscriberList->AsObject();
640 };
641 auto subscriberIter = find_if(subscriberList_.begin(), subscriberList_.end(), findSuscriber);
642 if (subscriberIter == subscriberList_.end()) {
643 BGTASK_LOGE("request subscriber is not exists.");
644 return;
645 }
646 remote->RemoveDeathRecipient(susriberDeathRecipient_);
647 subscriberList_.erase(subscriberIter);
648 BGTASK_LOGI("unsubscribe transient task success.");
649 });
650 return ERR_OK;
651 }
652
GetTransientTaskApps(std::vector<std::shared_ptr<TransientTaskAppInfo>> & list)653 ErrCode BgTransientTaskMgr::GetTransientTaskApps(std::vector<std::shared_ptr<TransientTaskAppInfo>> &list)
654 {
655 lock_guard<mutex> lock(expiredCallbackLock_);
656 if (keyInfoMap_.empty()) {
657 return ERR_OK;
658 }
659
660 for (auto record : keyInfoMap_) {
661 auto findInfo = [&record](const auto& info) {
662 return (record.second->GetPkg() == info->GetPackageName()) &&
663 (record.second->GetUid() == info->GetUid());
664 };
665 auto findInfoIter = std::find_if(list.begin(), list.end(), findInfo);
666 if (findInfoIter == list.end()) {
667 auto appInfo = make_shared<TransientTaskAppInfo>(record.second->GetPkg(),
668 record.second->GetUid());
669 list.push_back(appInfo);
670 }
671 }
672 return ERR_OK;
673 }
674
SetBgTaskConfig(const std::string & configData,int32_t sourceType)675 ErrCode BgTransientTaskMgr::SetBgTaskConfig(const std::string &configData, int32_t sourceType)
676 {
677 if (!isReady_.load()) {
678 BGTASK_LOGE("Transient task manager is not ready.");
679 return ERR_BGTASK_SYS_NOT_READY;
680 }
681 if (!CheckProcessName()) {
682 return ERR_BGTASK_INVALID_PROCESS_NAME;
683 }
684 BGTASK_LOGD("SetBgTaskConfig configData: %{public}s, sourceType: %{public}d.", configData.c_str(), sourceType);
685 bool addResult = DelayedSingleton<BgtaskConfig>::GetInstance()->AddExemptedQuatoData(configData, sourceType);
686 if (!addResult) {
687 BGTASK_LOGE("AddExemptedQuatoData fail.");
688 return ERR_PARAM_NUMBER_ERR;
689 }
690 return ERR_OK;
691 }
692
ShellDump(const std::vector<std::string> & dumpOption,std::vector<std::string> & dumpInfo)693 ErrCode BgTransientTaskMgr::ShellDump(const std::vector<std::string> &dumpOption, std::vector<std::string> &dumpInfo)
694 {
695 if (!isReady_.load()) {
696 BGTASK_LOGE("Transient task manager is not ready.");
697 return ERR_BGTASK_SYS_NOT_READY;
698 }
699 bool result = false;
700 if (dumpOption[1] == ALL_BGTASKMGR_OPTION) {
701 result = DumpAllRequestId(dumpInfo);
702 } else if (dumpOption[1] == LOW_BATTARY_OPTION) {
703 deviceInfoManeger_->SetDump(true);
704 SendLowBatteryEvent(dumpInfo);
705 result = true;
706 } else if (dumpOption[1] == OKAY_BATTARY_OPTION) {
707 deviceInfoManeger_->SetDump(true);
708 SendOkayBatteryEvent(dumpInfo);
709 result = true;
710 } else if (dumpOption[1] == CANCEL_DUMP_OPTION) {
711 deviceInfoManeger_->SetDump(false);
712 result = true;
713 } else if (dumpOption[1] == PAUSE_DUMP_OPTION) {
714 DumpTaskTime(dumpOption, true, dumpInfo);
715 result = true;
716 } else if (dumpOption[1] == START_DUMP_OPTION) {
717 DumpTaskTime(dumpOption, false, dumpInfo);
718 result = true;
719 } else {
720 dumpInfo.push_back("Error transient dump command!\n");
721 }
722
723 return result ? ERR_OK : ERR_BGTASK_PERMISSION_DENIED;
724 }
725
SendLowBatteryEvent(std::vector<std::string> & dumpInfo)726 void BgTransientTaskMgr::SendLowBatteryEvent(std::vector<std::string> &dumpInfo)
727 {
728 AAFwk::Want want;
729 want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_BATTERY_LOW);
730 EventFwk::CommonEventData data;
731 data.SetWant(want);
732 EventFwk::CommonEventPublishInfo publishInfo;
733 publishInfo.SetOrdered(true);
734
735 data.SetCode(0);
736 data.SetData("dump");
737 if (EventFwk::CommonEventManager::PublishCommonEvent(data, publishInfo)) {
738 dumpInfo.push_back("Publish COMMON_EVENT_BATTERY_LOW succeed!\n");
739 } else {
740 dumpInfo.push_back("Publish COMMON_EVENT_BATTERY_LOW failed!\n");
741 }
742 }
743
SendOkayBatteryEvent(std::vector<std::string> & dumpInfo)744 void BgTransientTaskMgr::SendOkayBatteryEvent(std::vector<std::string> &dumpInfo)
745 {
746 AAFwk::Want want;
747 want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_BATTERY_OKAY);
748 EventFwk::CommonEventData data;
749 data.SetWant(want);
750 EventFwk::CommonEventPublishInfo publishInfo;
751 publishInfo.SetOrdered(true);
752
753 data.SetCode(0);
754 data.SetData("dump");
755 if (EventFwk::CommonEventManager::PublishCommonEvent(data, publishInfo)) {
756 dumpInfo.push_back("Publish COMMON_EVENT_BATTERY_OKAY succeed!\n");
757 } else {
758 dumpInfo.push_back("Publish COMMON_EVENT_BATTERY_OKAY failed!\n");
759 }
760 }
761
OnAppCacheStateChanged(int32_t uid,int32_t pid,const std::string & bundleName)762 void BgTransientTaskMgr::OnAppCacheStateChanged(int32_t uid, int32_t pid, const std::string &bundleName)
763 {
764 if (!isReady_.load()) {
765 BGTASK_LOGW("manager is not ready");
766 return;
767 }
768 if (!VerifyCallingInfo(uid, pid)) {
769 BGTASK_LOGE("pid or uid is invalid.");
770 return;
771 }
772 auto keyInfo = make_shared<KeyInfo>(bundleName, uid, pid);
773 vector<int32_t> requestIdList = decisionMaker_->GetRequestIdListByKey(keyInfo);
774 if (requestIdList.empty()) {
775 BGTASK_LOGD("pkgname: %{public}s, uid: %{public}d not request transient task.",
776 bundleName.c_str(), uid);
777 return;
778 }
779 lock_guard<mutex> lock(expiredCallbackLock_);
780 for (auto &requestId : requestIdList) {
781 BGTASK_LOGI("OnAppCacheStateChanged cancel task, bundlename: %{public}s, uid: %{public}d, pid: %{public}d,"
782 " requestId: %{public}d.", bundleName.c_str(), uid, pid, requestId);
783 CancelSuspendDelayLocked(requestId);
784 }
785 }
786
DumpTaskTime(const std::vector<std::string> & dumpOption,bool pause,std::vector<std::string> & dumpInfo)787 void BgTransientTaskMgr::DumpTaskTime(const std::vector<std::string> &dumpOption, bool pause,
788 std::vector<std::string> &dumpInfo)
789 {
790 int32_t uid = std::atoi(dumpOption[DUMP_PARAM_INDEX_TWO].c_str());
791 ErrCode ret = ERR_OK;
792 if (pause) {
793 ret = PauseTransientTaskTimeForInner(uid);
794 if (ret != ERR_OK) {
795 dumpInfo.push_back("pause transient tasl fail!\n");
796 } else {
797 dumpInfo.push_back("pause transient tasl success!\n");
798 }
799 } else {
800 ret = StartTransientTaskTimeForInner(uid);
801 if (ret != ERR_OK) {
802 dumpInfo.push_back("start transient tasl fail!\n");
803 } else {
804 dumpInfo.push_back("start transient tasl success!\n");
805 }
806 }
807 }
808
DumpAllRequestId(std::vector<std::string> & dumpInfo)809 bool BgTransientTaskMgr::DumpAllRequestId(std::vector<std::string> &dumpInfo)
810 {
811 lock_guard<mutex> lock(expiredCallbackLock_);
812 if (keyInfoMap_.empty()) {
813 dumpInfo.push_back("No Transient Task!\n");
814 return true;
815 }
816 std::stringstream stream;
817 int32_t index = 1;
818 for (auto record : keyInfoMap_) {
819 stream.clear();
820 stream.str("");
821 stream << "No." << std::to_string(index++) << "\n";
822 stream << "\tRequestId: " << record.first << "\n";
823 stream << "\tAppName: " << record.second->GetPkg() << "\n";
824 stream << "\tAppUid: " << record.second->GetUid() << "\n";
825 stream << "\tAppPid: " << record.second->GetPid() << "\n";
826 stream << "\tActualDelayTime: " << decisionMaker_->GetRemainingDelayTime(record.second, record.first) << "\n";
827 stream << "\tRemainingQuota: " << decisionMaker_->GetQuota(record.second) << "\n";
828 stream << "\n";
829 dumpInfo.push_back(stream.str());
830 }
831
832 return true;
833 }
834
ExpiredCallbackDeathRecipient(const wptr<BackgroundTaskMgrService> & service)835 ExpiredCallbackDeathRecipient::ExpiredCallbackDeathRecipient(const wptr<BackgroundTaskMgrService>& service)
836 : service_(service) {}
837
~ExpiredCallbackDeathRecipient()838 ExpiredCallbackDeathRecipient::~ExpiredCallbackDeathRecipient() {}
839
OnRemoteDied(const wptr<IRemoteObject> & remote)840 void ExpiredCallbackDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
841 {
842 auto service = service_.promote();
843 if (service == nullptr) {
844 BGTASK_LOGE("expired callback died, BackgroundTaskMgrService dead.");
845 return;
846 }
847 service->HandleExpiredCallbackDeath(remote);
848 }
849
SubscriberDeathRecipient(const wptr<BackgroundTaskMgrService> & service)850 SubscriberDeathRecipient::SubscriberDeathRecipient(const wptr<BackgroundTaskMgrService>& service)
851 : service_(service) {}
852
~SubscriberDeathRecipient()853 SubscriberDeathRecipient::~SubscriberDeathRecipient() {}
854
OnRemoteDied(const wptr<IRemoteObject> & remote)855 void SubscriberDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
856 {
857 auto service = service_.promote();
858 if (service == nullptr) {
859 BGTASK_LOGE("suscriber died, BackgroundTaskMgrService dead.");
860 return;
861 }
862 service->HandleSubscriberDeath(remote);
863 }
864
HandleSuspendManagerDie()865 void BgTransientTaskMgr::HandleSuspendManagerDie()
866 {
867 if (!transientPauseUid_.empty()) {
868 for (auto iter = transientPauseUid_.begin(); iter != transientPauseUid_.end(); iter++) {
869 int32_t uid = *iter;
870 std::string name = "";
871 if (!GetBundleNamesForUid(uid, name)) {
872 BGTASK_LOGE("GetBundleNamesForUid fail, uid : %{public}d.", uid);
873 continue;
874 }
875 ErrCode ret = decisionMaker_->StartTransientTaskTimeForInner(uid, name);
876 if (ret != ERR_OK) {
877 BGTASK_LOGE("transient task uid: %{public}d, restart fail.", uid);
878 }
879 }
880 lock_guard<mutex> lock(transientUidLock_);
881 transientPauseUid_.clear();
882 }
883 }
884
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)885 void BgTransientTaskMgr::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
886 {
887 if (!isReady_.load()) {
888 BGTASK_LOGE("Transient task manager is not ready.");
889 return;
890 }
891 switch (systemAbilityId) {
892 case SUSPEND_MANAGER_SYSTEM_ABILITY_ID:
893 {
894 BGTASK_LOGI("remove suspend manager system ability, systemAbilityId: %{public}d", systemAbilityId);
895 auto task = [this]() { this->HandleSuspendManagerDie(); };
896 handler_->PostTask(task);
897 }
898 break;
899 default:
900 break;
901 }
902 }
903
GetTransientPauseUid()904 std::set<int32_t>& BgTransientTaskMgr::GetTransientPauseUid()
905 {
906 return transientPauseUid_;
907 }
908 } // namespace BackgroundTaskMgr
909 } // namespace OHOS