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_continuous_task_mgr.h"
17
18 #include <sstream>
19
20 #include "app_mgr_client.h"
21 #include "bundle_constants.h"
22 #include "bundle_manager_helper.h"
23 #include "common_event_support.h"
24 #include "common_event_manager.h"
25 #include "errors.h"
26 #include "hitrace_meter.h"
27 #include "if_system_ability_manager.h"
28 #include "hisysevent.h"
29 #include "iremote_object.h"
30 #include "iservice_registry.h"
31 #ifdef HAS_OS_ACCOUNT_PART
32 #include "os_account_manager.h"
33 #endif // HAS_OS_ACCOUNT_PART
34 #include "notification_tools.h"
35 #include "parameters.h"
36 #include "running_process_info.h"
37 #include "string_wrapper.h"
38 #include "system_ability_definition.h"
39
40 #include "bgtask_common.h"
41 #include "bgtaskmgr_inner_errors.h"
42 #include "continuous_task_record.h"
43 #include "continuous_task_log.h"
44 #include "system_event_observer.h"
45 #include "data_storage_helper.h"
46 #ifdef SUPPORT_GRAPHICS
47 #include "locale_config.h"
48 #endif // SUPPORT_GRAPHICS
49
50 namespace OHOS {
51 namespace BackgroundTaskMgr {
52 namespace {
53 static const char *g_taskPromptResNames[] = {
54 "ohos_bgmode_prompt_data_transfer",
55 "ohos_bgmode_prompt_audio_playback",
56 "ohos_bgmode_prompt_audio_recording",
57 "ohos_bgmode_prompt_location",
58 "ohos_bgmode_prompt_bluetooth_interaction",
59 "ohos_bgmode_prompt_multidevice_connection",
60 "ohos_bgmode_prompt_wifi_interaction",
61 "ohos_bgmode_prompt_voip",
62 "ohos_bgmode_prompt_task_keeping",
63 "ohos_bgmode_prompt_default_value",
64 };
65
66 static constexpr char SEPARATOR[] = "_";
67 static constexpr char DUMP_PARAM_LIST_ALL[] = "--all";
68 static constexpr char DUMP_PARAM_CANCEL_ALL[] = "--cancel_all";
69 static constexpr char DUMP_PARAM_CANCEL[] = "--cancel";
70 static constexpr char BGMODE_PERMISSION[] = "ohos.permission.KEEP_BACKGROUND_RUNNING";
71 static constexpr char BG_TASK_RES_BUNDLE_NAME[] = "ohos.backgroundtaskmgr.resources";
72 static constexpr uint32_t SYSTEM_APP_BGMODE_WIFI_INTERACTION = 64;
73 static constexpr uint32_t SYSTEM_APP_BGMODE_VOIP = 128;
74 static constexpr uint32_t PC_BGMODE_TASK_KEEPING = 256;
75 static constexpr int32_t DEFAULT_NOTIFICATION_ID = 0;
76 static constexpr int32_t DELAY_TIME = 2000;
77 static constexpr int32_t MAX_DUMP_PARAM_NUMS = 3;
78 static constexpr int32_t UNSET_UID = -1;
79 static constexpr uint32_t INVALID_BGMODE = 0;
80 static constexpr uint32_t BG_MODE_INDEX_HEAD = 1;
81 static constexpr uint32_t BGMODE_NUMS = 10;
82
83 static constexpr uint32_t WEBVIEW_PARAM_UID = 2;
84 static constexpr uint32_t WEBVIEW_PARAM_BGMODE = 3;
85 static constexpr uint32_t WEBVIEW_PARAM_IS_START = 4;
86 static constexpr uint32_t WEBVIEW_PARAM_SIZE = 5;
87
88 #ifndef HAS_OS_ACCOUNT_PART
89 constexpr int32_t DEFAULT_OS_ACCOUNT_ID = 0; // 0 is the default id when there is no os_account part
90 constexpr int32_t UID_TRANSFORM_DIVISOR = 200000;
GetOsAccountIdFromUid(int32_t uid,int32_t & osAccountId)91 static void GetOsAccountIdFromUid(int32_t uid, int32_t &osAccountId)
92 {
93 osAccountId = uid / UID_TRANSFORM_DIVISOR;
94 }
95 #endif // HAS_OS_ACCOUNT_PART
96 }
97
BgContinuousTaskMgr()98 BgContinuousTaskMgr::BgContinuousTaskMgr() {}
99
~BgContinuousTaskMgr()100 BgContinuousTaskMgr::~BgContinuousTaskMgr() {}
101
Init(const std::shared_ptr<AppExecFwk::EventRunner> & runner)102 bool BgContinuousTaskMgr::Init(const std::shared_ptr<AppExecFwk::EventRunner>& runner)
103 {
104 if (runner == nullptr) {
105 BGTASK_LOGE("BgContinuousTaskMgr runner create failed!");
106 return false;
107 }
108 handler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
109 if (handler_ == nullptr) {
110 BGTASK_LOGE("BgContinuousTaskMgr handler create failed!");
111 return false;
112 }
113 std::string identity = IPCSkeleton::ResetCallingIdentity();
114 bgTaskUid_ = IPCSkeleton::GetCallingUid();
115 BGTASK_LOGI("BgContinuousTaskMgr service uid is: %{public}d", bgTaskUid_);
116 IPCSkeleton::SetCallingIdentity(identity);
117 auto registerTask = [this]() { this->InitNecessaryState(); };
118 handler_->PostSyncTask(registerTask);
119 return true;
120 }
121
Clear()122 void BgContinuousTaskMgr::Clear()
123 {
124 #ifdef DISTRIBUTED_NOTIFICATION_ENABLE
125 Notification::NotificationHelper::UnSubscribeNotification(*subscriber_);
126 #endif
127 if (systemEventListener_ != nullptr) {
128 systemEventListener_->Unsubscribe();
129 }
130 if (appStateObserver_ != nullptr) {
131 appStateObserver_->Unsubscribe();
132 }
133 }
134
InitNecessaryState()135 void BgContinuousTaskMgr::InitNecessaryState()
136 {
137 sptr<ISystemAbilityManager> systemAbilityManager
138 = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
139 if (systemAbilityManager == nullptr
140 || systemAbilityManager->CheckSystemAbility(APP_MGR_SERVICE_ID) == nullptr
141 || systemAbilityManager->CheckSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID) == nullptr
142 #ifdef DISTRIBUTED_NOTIFICATION_ENABLE
143 || systemAbilityManager->CheckSystemAbility(ADVANCED_NOTIFICATION_SERVICE_ABILITY_ID) == nullptr
144 #endif
145 || systemAbilityManager->CheckSystemAbility(COMMON_EVENT_SERVICE_ID) == nullptr) {
146 BGTASK_LOGW("request system service is not ready yet!");
147 auto task = [this]() { this->InitNecessaryState(); };
148 handler_->PostTask(task, DELAY_TIME);
149 return;
150 }
151
152 if (!RegisterNotificationSubscriber()) {
153 BGTASK_LOGE("RegisterNotificationSubscriber failed");
154 return;
155 }
156 if (!RegisterAppStateObserver()) {
157 BGTASK_LOGE("RegisterAppStateObserver failed");
158 return;
159 }
160 if (!RegisterSysCommEventListener()) {
161 BGTASK_LOGE("RegisterSysCommEventListener failed");
162 return;
163 }
164 if (!RegisterConfigurationObserver()) {
165 BGTASK_LOGE("RegisterConfigurationObserver failed");
166 return;
167 }
168 deviceType_ = OHOS::system::GetParameter("const.build.characteristics", "");
169 BGTASK_LOGI("current device type is: %{public}s", deviceType_.c_str());
170 InitRequiredResourceInfo();
171 }
172
HandlePersistenceData()173 void BgContinuousTaskMgr::HandlePersistenceData()
174 {
175 BGTASK_LOGI("service restart, restore data");
176 DelayedSingleton<DataStorageHelper>::GetInstance()->RestoreTaskRecord(continuousTaskInfosMap_);
177 auto appMgrClient = std::make_shared<AppExecFwk::AppMgrClient>();
178 std::vector<AppExecFwk::RunningProcessInfo> allAppProcessInfos;
179 if (appMgrClient->ConnectAppMgrService() != ERR_OK) {
180 BGTASK_LOGW("connect to app mgr service failed");
181 return;
182 }
183 appMgrClient->GetAllRunningProcesses(allAppProcessInfos);
184 std::set<std::string> labels;
185 NotificationTools::GetInstance()->GetAllActiveNotificationsLabels(labels);
186 CheckPersistenceData(allAppProcessInfos, labels);
187 DelayedSingleton<DataStorageHelper>::GetInstance()->RefreshTaskRecord(continuousTaskInfosMap_);
188 }
189
CheckProcessUidInfo(const std::vector<AppExecFwk::RunningProcessInfo> & allProcesses,int32_t uid)190 bool BgContinuousTaskMgr::CheckProcessUidInfo(const std::vector<AppExecFwk::RunningProcessInfo> &allProcesses,
191 int32_t uid)
192 {
193 for (const auto &runningProcessInfo : allProcesses) {
194 if (runningProcessInfo.uid_ == uid) {
195 return true;
196 }
197 }
198 return false;
199 }
200
CheckPersistenceData(const std::vector<AppExecFwk::RunningProcessInfo> & allProcesses,const std::set<std::string> & allLabels)201 void BgContinuousTaskMgr::CheckPersistenceData(const std::vector<AppExecFwk::RunningProcessInfo> &allProcesses,
202 const std::set<std::string> &allLabels)
203 {
204 int32_t recordPid;
205 auto iter = continuousTaskInfosMap_.begin();
206 bool pidConditionFlag;
207 bool notificationConditionFlag;
208
209 while (iter != continuousTaskInfosMap_.end()) {
210 recordPid = iter->second->GetPid();
211 const std::string recordLabel = iter->second->GetNotificationLabel();
212 pidConditionFlag = checkPidCondition(allProcesses, recordPid);
213 notificationConditionFlag = checkNotificationCondition(allLabels, recordLabel);
214 if (pidConditionFlag && notificationConditionFlag) {
215 BGTASK_LOGI("target continuous task exist");
216 iter++;
217 continue;
218 }
219
220 if (iter->second->IsFromWebview() && CheckProcessUidInfo(allProcesses, iter->second->GetUid())) {
221 BGTASK_LOGI("Webview continuous task exist.");
222 iter++;
223 continue;
224 }
225
226 if (!pidConditionFlag && notificationConditionFlag) {
227 BGTASK_LOGI("pid: %{public}d not exist, label: %{public}s exist", recordPid, recordLabel.c_str());
228 NotificationTools::GetInstance()->CancelNotification(recordLabel, DEFAULT_NOTIFICATION_ID);
229 iter = continuousTaskInfosMap_.erase(iter);
230 continue;
231 }
232
233 if (pidConditionFlag && !notificationConditionFlag) {
234 BGTASK_LOGI("pid: %{public}d exist, label: %{public}s not exist", recordPid, recordLabel.c_str());
235 iter = continuousTaskInfosMap_.erase(iter);
236 continue;
237 }
238
239 if (!pidConditionFlag && !notificationConditionFlag) {
240 BGTASK_LOGI("pid: %{public}d not exist, label: %{public}s not exist", recordPid, recordLabel.c_str());
241 iter = continuousTaskInfosMap_.erase(iter);
242 continue;
243 }
244 }
245 }
246
checkPidCondition(const std::vector<AppExecFwk::RunningProcessInfo> & allProcesses,int32_t pid)247 bool BgContinuousTaskMgr::checkPidCondition(const std::vector<AppExecFwk::RunningProcessInfo> &allProcesses,
248 int32_t pid)
249 {
250 auto findPid = [pid](const auto &target) {
251 return pid == target.pid_;
252 };
253 auto findPidIter = find_if(allProcesses.begin(), allProcesses.end(), findPid);
254 return findPidIter != allProcesses.end();
255 }
256
checkNotificationCondition(const std::set<std::string> & notificationLabels,const std::string & label)257 bool BgContinuousTaskMgr::checkNotificationCondition(const std::set<std::string> ¬ificationLabels,
258 const std::string &label)
259 {
260 #ifdef DISTRIBUTED_NOTIFICATION_ENABLE
261 auto findLabel = [label](const auto &target) {
262 return label == target;
263 };
264 auto findLabelIter = find_if(notificationLabels.begin(), notificationLabels.end(), findLabel);
265 return findLabelIter != notificationLabels.end();
266 #else
267 return true;
268 #endif
269 }
270
InitRequiredResourceInfo()271 void BgContinuousTaskMgr::InitRequiredResourceInfo()
272 {
273 if (!GetNotificationPrompt()) {
274 BGTASK_LOGW("init required resource info failed. will try again");
275 isSysReady_.store(false);
276 auto task = [this]() { this->InitRequiredResourceInfo(); };
277 handler_->PostTask(task, DELAY_TIME);
278 return;
279 }
280 HandlePersistenceData();
281 isSysReady_.store(true);
282 }
283
RegisterNotificationSubscriber()284 bool BgContinuousTaskMgr::RegisterNotificationSubscriber()
285 {
286 bool res = true;
287 #ifdef DISTRIBUTED_NOTIFICATION_ENABLE
288 subscriber_ = std::make_shared<TaskNotificationSubscriber>();
289 if (Notification::NotificationHelper::SubscribeNotification(*subscriber_) != ERR_OK) {
290 BGTASK_LOGE("SubscribeNotification failed!");
291 res = false;
292 }
293 #endif
294 return res;
295 }
296
RegisterAppStateObserver()297 bool BgContinuousTaskMgr::RegisterAppStateObserver()
298 {
299 bool res = true;
300 appStateObserver_ = DelayedSingleton<AppStateObserver>::GetInstance();
301 if (appStateObserver_ != nullptr) {
302 appStateObserver_->SetEventHandler(handler_);
303 appStateObserver_->SetBgContinuousTaskMgr(shared_from_this());
304 res = appStateObserver_->Subscribe();
305 }
306 return res;
307 }
308
RegisterConfigurationObserver()309 bool BgContinuousTaskMgr::RegisterConfigurationObserver()
310 {
311 auto appMgrClient = std::make_shared<AppExecFwk::AppMgrClient>();
312 if (appMgrClient->ConnectAppMgrService() != ERR_OK) {
313 BGTASK_LOGW("connect to app mgr service failed");
314 return false;
315 }
316 configChangeObserver_ = sptr<AppExecFwk::IConfigurationObserver>(
317 new (std::nothrow) ConfigChangeObserver(handler_, shared_from_this()));
318 if (appMgrClient->RegisterConfigurationObserver(configChangeObserver_) != ERR_OK) {
319 return false;
320 }
321 return true;
322 }
323
GetBundleResMgr(const AppExecFwk::BundleInfo & bundleInfo)324 std::shared_ptr<Global::Resource::ResourceManager> BgContinuousTaskMgr::GetBundleResMgr(
325 const AppExecFwk::BundleInfo &bundleInfo)
326 {
327 std::shared_ptr<Global::Resource::ResourceManager> resourceManager(Global::Resource::CreateResourceManager());
328 if (!resourceManager) {
329 BGTASK_LOGE("create resourceManager failed");
330 return nullptr;
331 }
332 for (auto hapModuleInfo : bundleInfo.hapModuleInfos) {
333 std::string moduleResPath = hapModuleInfo.hapPath.empty() ? hapModuleInfo.resourcePath : hapModuleInfo.hapPath;
334 if (moduleResPath.empty()) {
335 continue;
336 }
337 BGTASK_LOGD("GetBundleResMgr, moduleResPath: %{private}s", moduleResPath.c_str());
338 if (!resourceManager->AddResource(moduleResPath.c_str())) {
339 BGTASK_LOGW("GetBundleResMgr AddResource failed");
340 }
341 }
342 std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
343 #ifdef SUPPORT_GRAPHICS
344 UErrorCode status = U_ZERO_ERROR;
345 icu::Locale locale = icu::Locale::forLanguageTag(Global::I18n::LocaleConfig::GetSystemLanguage(), status);
346 resConfig->SetLocaleInfo(locale);
347 #endif // SUPPORT_GRAPHICS
348 resourceManager->UpdateResConfig(*resConfig);
349 return resourceManager;
350 }
351
GetNotificationPrompt()352 bool BgContinuousTaskMgr::GetNotificationPrompt()
353 {
354 continuousTaskText_.clear();
355 AppExecFwk::BundleInfo bundleInfo;
356 if (!BundleManagerHelper::GetInstance()->GetBundleInfo(BG_TASK_RES_BUNDLE_NAME,
357 AppExecFwk::BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo)) {
358 BGTASK_LOGE("get background task res: %{public}s bundle info failed", BG_TASK_RES_BUNDLE_NAME);
359 return false;
360 }
361 auto resourceManager = GetBundleResMgr(bundleInfo);
362 if (resourceManager == nullptr) {
363 BGTASK_LOGE("Get bgtask resource hap manager failed");
364 return false;
365 }
366 std::string taskText {""};
367 for (std::string name : g_taskPromptResNames) {
368 resourceManager->GetStringByName(name.c_str(), taskText);
369 if (taskText.empty()) {
370 BGTASK_LOGE("get continuous task notification text failed!");
371 return false;
372 }
373 BGTASK_LOGI("get taskText: %{public}s", taskText.c_str());
374 continuousTaskText_.push_back(taskText);
375 }
376 return true;
377 }
378
RegisterSysCommEventListener()379 bool BgContinuousTaskMgr::RegisterSysCommEventListener()
380 {
381 bool res = true;
382 EventFwk::MatchingSkills matchingSkills;
383 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED);
384 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED);
385 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED);
386 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REPLACED);
387 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_REMOVED);
388 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_FULLY_REMOVED);
389 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_DATA_CLEARED);
390 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_ADDED);
391 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_REMOVED);
392 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED);
393 EventFwk::CommonEventSubscribeInfo commonEventSubscribeInfo(matchingSkills);
394 systemEventListener_ = std::make_shared<SystemEventObserver>(commonEventSubscribeInfo);
395 if (systemEventListener_ != nullptr) {
396 systemEventListener_->SetEventHandler(handler_);
397 systemEventListener_->SetBgContinuousTaskMgr(shared_from_this());
398 res = systemEventListener_->Subscribe();
399 }
400 return res;
401 }
402
GetBgTaskUid()403 int32_t BgContinuousTaskMgr::GetBgTaskUid()
404 {
405 return bgTaskUid_;
406 }
407
SetCachedBundleInfo(int32_t uid,int32_t userId,const std::string & bundleName,const std::string & appName)408 bool BgContinuousTaskMgr::SetCachedBundleInfo(int32_t uid, int32_t userId,
409 const std::string &bundleName, const std::string &appName)
410 {
411 AppExecFwk::BundleInfo bundleInfo;
412 if (!BundleManagerHelper::GetInstance()->GetBundleInfo(bundleName,
413 AppExecFwk::BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, userId)) {
414 BGTASK_LOGE("get bundle info: %{public}s failure!", bundleName.c_str());
415 return false;
416 }
417
418 CachedBundleInfo cachedBundleInfo = CachedBundleInfo();
419 cachedBundleInfo.appName_ = appName;
420 if (AddAbilityBgModeInfos(bundleInfo, cachedBundleInfo)) {
421 cachedBundleInfos_.emplace(uid, cachedBundleInfo);
422 return true;
423 }
424 return false;
425 }
426
AddAbilityBgModeInfos(const AppExecFwk::BundleInfo & bundleInfo,CachedBundleInfo & cachedBundleInfo)427 bool BgContinuousTaskMgr::AddAbilityBgModeInfos(const AppExecFwk::BundleInfo &bundleInfo,
428 CachedBundleInfo &cachedBundleInfo)
429 {
430 for (auto abilityInfo : bundleInfo.abilityInfos) {
431 if (abilityInfo.backgroundModes != INVALID_BGMODE) {
432 cachedBundleInfo.abilityBgMode_.emplace(abilityInfo.name, abilityInfo.backgroundModes);
433 BGTASK_LOGI("abilityName: %{public}s, abilityNameHash: %{public}s, Background Mode: %{public}u.",
434 abilityInfo.name.c_str(), std::to_string(std::hash<std::string>()(abilityInfo.name)).c_str(),
435 abilityInfo.backgroundModes);
436 }
437 }
438 if (cachedBundleInfo.abilityBgMode_.empty()) {
439 return false;
440 }
441 return true;
442 }
443
CheckBgmodeType(uint32_t configuredBgMode,uint32_t requestedBgModeId,bool isNewApi,uint64_t fullTokenId)444 ErrCode BgContinuousTaskMgr::CheckBgmodeType(uint32_t configuredBgMode, uint32_t requestedBgModeId,
445 bool isNewApi, uint64_t fullTokenId)
446 {
447 if (!isNewApi) {
448 if (configuredBgMode == INVALID_BGMODE) {
449 BGTASK_LOGE("ability without background mode config");
450 return ERR_BGMODE_NULL_OR_TYPE_ERR;
451 } else {
452 return ERR_OK;
453 }
454 } else {
455 uint32_t recordedBgMode = BG_MODE_INDEX_HEAD << (requestedBgModeId - 1);
456 if ((recordedBgMode == SYSTEM_APP_BGMODE_WIFI_INTERACTION || recordedBgMode == SYSTEM_APP_BGMODE_VOIP)
457 && !BundleManagerHelper::GetInstance()->IsSystemApp(fullTokenId)) {
458 BGTASK_LOGE("voip and wifiInteraction background mode only support for system app");
459 return ERR_BGTASK_NOT_SYSTEM_APP;
460 }
461 if (recordedBgMode == PC_BGMODE_TASK_KEEPING && !SUPPORT_TASK_KEEPING) {
462 BGTASK_LOGE("task keeping is not supported, please set param "
463 "persist.sys.bgtask_support_task_keeping.");
464 return ERR_BGTASK_KEEPING_TASK_VERIFY_ERR;
465 }
466 if (requestedBgModeId == INVALID_BGMODE || (configuredBgMode &
467 (BG_MODE_INDEX_HEAD << (requestedBgModeId - 1))) == 0) {
468 BGTASK_LOGE("requested background mode is not declared in config file!");
469 return ERR_BGTASK_INVALID_BGMODE;
470 }
471 }
472 return ERR_OK;
473 }
474
GetBackgroundModeInfo(int32_t uid,const std::string & abilityName)475 uint32_t BgContinuousTaskMgr::GetBackgroundModeInfo(int32_t uid, const std::string &abilityName)
476 {
477 if (cachedBundleInfos_.find(uid) != cachedBundleInfos_.end()) {
478 auto cachedBundleInfo = cachedBundleInfos_.at(uid);
479 if (cachedBundleInfo.abilityBgMode_.find(abilityName) !=
480 cachedBundleInfo.abilityBgMode_.end()) {
481 return cachedBundleInfo.abilityBgMode_.at(abilityName);
482 }
483 }
484 return INVALID_BGMODE;
485 }
486
CheckTaskParam(const sptr<ContinuousTaskParam> & taskParam)487 bool CheckTaskParam(const sptr<ContinuousTaskParam> &taskParam)
488 {
489 if (!taskParam) {
490 BGTASK_LOGE("continuous task params is null!");
491 return false;
492 }
493
494 if (taskParam->isNewApi_) {
495 if (taskParam->wantAgent_ == nullptr || taskParam->abilityName_.empty()) {
496 BGTASK_LOGE("continuous task params invalid!");
497 return false;
498 }
499 } else {
500 if (taskParam->abilityName_.empty()) {
501 BGTASK_LOGE("continuous task params invalid!");
502 return false;
503 }
504 }
505 return true;
506 }
507
CheckBgmodeTypeForInner(uint32_t requestedBgModeId)508 ErrCode BgContinuousTaskMgr::CheckBgmodeTypeForInner(uint32_t requestedBgModeId)
509 {
510 if (requestedBgModeId == INVALID_BGMODE || requestedBgModeId >= BGMODE_NUMS) {
511 BGTASK_LOGE("requested background mode is not declared in config file!");
512 return ERR_BGTASK_INVALID_BGMODE;
513 }
514 return ERR_OK;
515 }
516
RequestBackgroundRunningForInner(const sptr<ContinuousTaskParamForInner> & taskParam)517 ErrCode BgContinuousTaskMgr::RequestBackgroundRunningForInner(const sptr<ContinuousTaskParamForInner> &taskParam)
518 {
519 if (!isSysReady_.load()) {
520 BGTASK_LOGW("manager is not ready");
521 return ERR_BGTASK_SYS_NOT_READY;
522 }
523
524 if (!taskParam) {
525 BGTASK_LOGE("continuous task param is null!");
526 return ERR_BGTASK_CHECK_TASK_PARAM;
527 }
528 int32_t callingUid = IPCSkeleton::GetCallingUid();
529 if (callingUid != taskParam->uid_) {
530 BGTASK_LOGE("continuous task param uid %{public}d is invalid, real %{public}d", taskParam->uid_, callingUid);
531 return ERR_BGTASK_CHECK_TASK_PARAM;
532 }
533 if (taskParam->isStart_) {
534 return StartBackgroundRunningForInner(taskParam);
535 }
536 return StopBackgroundRunningForInner(taskParam);
537 }
538
StartBackgroundRunningForInner(const sptr<ContinuousTaskParamForInner> & taskParam)539 ErrCode BgContinuousTaskMgr::StartBackgroundRunningForInner(const sptr<ContinuousTaskParamForInner> &taskParam)
540 {
541 ErrCode result = ERR_OK;
542 int32_t uid = taskParam->uid_;
543 pid_t callingPid = IPCSkeleton::GetCallingPid();
544 uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
545 std::string bundleName = BundleManagerHelper::GetInstance()->GetClientBundleName(uid);
546 std::string abilityName = "Webview" + std::to_string(taskParam->bgModeId_);
547 int32_t userId = -1;
548
549 #ifdef HAS_OS_ACCOUNT_PART
550 AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(uid, userId);
551 #else // HAS_OS_ACCOUNT_PART
552 GetOsAccountIdFromUid(uid, userId);
553 #endif // HAS_OS_ACCOUNT_PART
554
555 std::shared_ptr<ContinuousTaskRecord> continuousTaskRecord = std::make_shared<ContinuousTaskRecord>(bundleName,
556 abilityName, uid, callingPid, taskParam->bgModeId_);
557 continuousTaskRecord->isNewApi_ = true;
558 continuousTaskRecord->isFromWebview_ = true;
559 continuousTaskRecord->userId_ = userId;
560 continuousTaskRecord->fullTokenId_ = fullTokenId;
561
562 StartTrace(HITRACE_TAG_OHOS, "BgContinuousTaskMgr::StartBackgroundRunningInner");
563 handler_->PostSyncTask([this, continuousTaskRecord, &result]() mutable {
564 result = this->StartBackgroundRunningInner(continuousTaskRecord);
565 }, AppExecFwk::EventQueue::Priority::HIGH);
566 FinishTrace(HITRACE_TAG_OHOS);
567
568 return result;
569 }
570
StartBackgroundRunning(const sptr<ContinuousTaskParam> & taskParam)571 ErrCode BgContinuousTaskMgr::StartBackgroundRunning(const sptr<ContinuousTaskParam> &taskParam)
572 {
573 if (!isSysReady_.load()) {
574 BGTASK_LOGW("manager is not ready");
575 return ERR_BGTASK_SYS_NOT_READY;
576 }
577
578 if (!CheckTaskParam(taskParam)) {
579 return ERR_BGTASK_CHECK_TASK_PARAM;
580 }
581
582 ErrCode result = ERR_OK;
583
584 int32_t callingUid = IPCSkeleton::GetCallingUid();
585 pid_t callingPid = IPCSkeleton::GetCallingPid();
586 uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
587 std::string bundleName = BundleManagerHelper::GetInstance()->GetClientBundleName(callingUid);
588 int32_t userId = -1;
589 #ifdef HAS_OS_ACCOUNT_PART
590 AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(callingUid, userId);
591 #else // HAS_OS_ACCOUNT_PART
592 GetOsAccountIdFromUid(callingUid, userId);
593 #endif // HAS_OS_ACCOUNT_PART
594
595 if (!BundleManagerHelper::GetInstance()->CheckPermission(BGMODE_PERMISSION)) {
596 BGTASK_LOGE("background mode permission is not passed");
597 return ERR_BGTASK_PERMISSION_DENIED;
598 }
599
600 std::shared_ptr<ContinuousTaskRecord> continuousTaskRecord = std::make_shared<ContinuousTaskRecord>(bundleName,
601 taskParam->abilityName_, callingUid, callingPid, taskParam->bgModeId_);
602 continuousTaskRecord->wantAgent_ = taskParam->wantAgent_;
603 continuousTaskRecord->userId_ = userId;
604 continuousTaskRecord->isNewApi_ = taskParam->isNewApi_;
605 continuousTaskRecord->appName_ = taskParam->appName_;
606 continuousTaskRecord->fullTokenId_ = fullTokenId;
607
608 if (taskParam->wantAgent_ != nullptr && taskParam->wantAgent_->GetPendingWant() != nullptr) {
609 auto target = taskParam->wantAgent_->GetPendingWant()->GetTarget();
610 auto want = taskParam->wantAgent_->GetPendingWant()->GetWant(target);
611 if (want != nullptr) {
612 std::shared_ptr<WantAgentInfo> info = std::make_shared<WantAgentInfo>();
613 info->bundleName_ = want->GetOperation().GetBundleName();
614 info->abilityName_ = want->GetOperation().GetAbilityName();
615 continuousTaskRecord->wantAgentInfo_ = info;
616 }
617 }
618
619 StartTrace(HITRACE_TAG_OHOS, "BgContinuousTaskMgr::StartBackgroundRunningInner");
620 handler_->PostSyncTask([this, continuousTaskRecord, &result]() mutable {
621 result = this->StartBackgroundRunningInner(continuousTaskRecord);
622 }, AppExecFwk::EventQueue::Priority::HIGH);
623 FinishTrace(HITRACE_TAG_OHOS);
624
625 return result;
626 }
627
StartBackgroundRunningInner(std::shared_ptr<ContinuousTaskRecord> & continuousTaskRecord)628 ErrCode BgContinuousTaskMgr::StartBackgroundRunningInner(std::shared_ptr<ContinuousTaskRecord> &continuousTaskRecord)
629 {
630 std::string taskInfoMapKey = std::to_string(continuousTaskRecord->uid_) + SEPARATOR
631 + continuousTaskRecord->abilityName_;
632 if (continuousTaskInfosMap_.find(taskInfoMapKey) != continuousTaskInfosMap_.end()) {
633 BGTASK_LOGW("continuous task is already exist: %{public}s", taskInfoMapKey.c_str());
634 return ERR_BGTASK_OBJECT_EXISTS;
635 }
636
637 if (!continuousTaskRecord->isFromWebview_
638 && cachedBundleInfos_.find(continuousTaskRecord->uid_) == cachedBundleInfos_.end()) {
639 std::string mainAbilityLabel = GetMainAbilityLabel(continuousTaskRecord->bundleName_,
640 continuousTaskRecord->userId_);
641 SetCachedBundleInfo(continuousTaskRecord->uid_, continuousTaskRecord->userId_,
642 continuousTaskRecord->bundleName_, mainAbilityLabel);
643 }
644
645 ErrCode ret;
646 if (continuousTaskRecord->isFromWebview_) {
647 ret = CheckBgmodeTypeForInner(continuousTaskRecord->bgModeId_);
648 } else {
649 uint32_t configuredBgMode = GetBackgroundModeInfo(continuousTaskRecord->uid_,
650 continuousTaskRecord->abilityName_);
651 ret = CheckBgmodeType(configuredBgMode, continuousTaskRecord->bgModeId_, continuousTaskRecord->isNewApi_,
652 continuousTaskRecord->fullTokenId_);
653 }
654 if (ret != ERR_OK) {
655 BGTASK_LOGE("background mode invalid!");
656 return ret;
657 }
658
659 if (!continuousTaskRecord->isFromWebview_) {
660 ret = SendContinuousTaskNotification(continuousTaskRecord);
661 if (ret != ERR_OK) {
662 BGTASK_LOGE("publish error");
663 return ret;
664 }
665 }
666 continuousTaskInfosMap_.emplace(taskInfoMapKey, continuousTaskRecord);
667 OnContinuousTaskChanged(continuousTaskRecord, ContinuousTaskEventTriggerType::TASK_START);
668 return RefreshTaskRecord();
669 }
670
GetBgModeNameIndex(uint32_t bgModeId,bool isNewApi)671 uint32_t GetBgModeNameIndex(uint32_t bgModeId, bool isNewApi)
672 {
673 if (!isNewApi) {
674 return BGMODE_NUMS - 1;
675 } else {
676 return bgModeId - 1;
677 }
678 }
679
SendContinuousTaskNotification(std::shared_ptr<ContinuousTaskRecord> & continuousTaskRecord)680 ErrCode BgContinuousTaskMgr::SendContinuousTaskNotification(
681 std::shared_ptr<ContinuousTaskRecord> &continuousTaskRecord)
682 {
683 std::string notificationText {""};
684 uint32_t index = GetBgModeNameIndex(continuousTaskRecord->GetBgModeId(), continuousTaskRecord->isNewApi_);
685 if (index < BGMODE_NUMS) {
686 notificationText = continuousTaskText_.at(index);
687 }
688 std::string appName {""};
689 if (cachedBundleInfos_.find(continuousTaskRecord->uid_) != cachedBundleInfos_.end()) {
690 appName = cachedBundleInfos_.at(continuousTaskRecord->uid_).appName_;
691 }
692 if (appName.empty() || notificationText.empty()) {
693 BGTASK_LOGE("get notification prompt info failed");
694 return ERR_BGTASK_NOTIFICATION_VERIFY_FAILED;
695 }
696
697 return NotificationTools::GetInstance()->PublishNotification(continuousTaskRecord,
698 appName, notificationText, bgTaskUid_);
699 }
700
StopBackgroundRunningForInner(const sptr<ContinuousTaskParamForInner> & taskParam)701 ErrCode BgContinuousTaskMgr::StopBackgroundRunningForInner(const sptr<ContinuousTaskParamForInner> &taskParam)
702 {
703 ErrCode result = ERR_OK;
704 int32_t uid = taskParam->uid_;
705 std::string abilityName = "Webview" + std::to_string(taskParam->bgModeId_);
706
707 StartTrace(HITRACE_TAG_OHOS, "BgContinuousTaskMgr::StopBackgroundRunningInner");
708 handler_->PostSyncTask([this, uid, abilityName, &result]() {
709 result = this->StopBackgroundRunningInner(uid, abilityName);
710 }, AppExecFwk::EventQueue::Priority::HIGH);
711 FinishTrace(HITRACE_TAG_OHOS);
712
713 return result;
714 }
715
StopBackgroundRunning(const std::string & abilityName)716 ErrCode BgContinuousTaskMgr::StopBackgroundRunning(const std::string &abilityName)
717 {
718 if (!isSysReady_.load()) {
719 BGTASK_LOGW("manager is not ready");
720 return ERR_BGTASK_SYS_NOT_READY;
721 }
722 if (abilityName.empty()) {
723 BGTASK_LOGE("abilityName is empty!");
724 return ERR_BGTASK_INVALID_PARAM;
725 }
726 int32_t callingUid = IPCSkeleton::GetCallingUid();
727
728 ErrCode result = ERR_OK;
729
730 StartTrace(HITRACE_TAG_OHOS, "BgContinuousTaskMgr::StopBackgroundRunningInner");
731 handler_->PostSyncTask([this, callingUid, abilityName, &result]() {
732 result = this->StopBackgroundRunningInner(callingUid, abilityName);
733 }, AppExecFwk::EventQueue::Priority::HIGH);
734 FinishTrace(HITRACE_TAG_OHOS);
735
736 return result;
737 }
738
StopBackgroundRunningInner(int32_t uid,const std::string & abilityName)739 ErrCode BgContinuousTaskMgr::StopBackgroundRunningInner(int32_t uid, const std::string &abilityName)
740 {
741 std::string mapKey = std::to_string(uid) + SEPARATOR + abilityName;
742
743 auto iter = continuousTaskInfosMap_.find(mapKey);
744 if (iter == continuousTaskInfosMap_.end()) {
745 BGTASK_LOGW("%{public}s continuous task not exists", mapKey.c_str());
746 return ERR_BGTASK_OBJECT_NOT_EXIST;
747 }
748
749 ErrCode result = ERR_OK;
750 if (!iter->second->isFromWebview_) {
751 result = NotificationTools::GetInstance()->CancelNotification(
752 iter->second->GetNotificationLabel(), DEFAULT_NOTIFICATION_ID);
753 }
754
755 RemoveContinuousTaskRecord(mapKey);
756 return result;
757 }
758
StopContinuousTask(int32_t uid,int32_t pid,uint32_t taskType)759 void BgContinuousTaskMgr::StopContinuousTask(int32_t uid, int32_t pid, uint32_t taskType)
760 {
761 BGTASK_LOGD("StopContinuousTask begin uid: %{public}d, pid: %{public}d, taskType: %{public}d",
762 uid, pid, taskType);
763 if (!isSysReady_.load()) {
764 BGTASK_LOGW("manager is not ready");
765 return;
766 }
767 auto task = [this, uid, pid, taskType]() { this->HandleStopContinuousTask(uid, pid, taskType); };
768 handler_->PostTask(task);
769 }
770
HandleStopContinuousTask(int32_t uid,int32_t pid,uint32_t taskType)771 void BgContinuousTaskMgr::HandleStopContinuousTask(int32_t uid, int32_t pid, uint32_t taskType)
772 {
773 // uid == -1 means target type continuoust task required condition is not met, so cancel all this kind of tasks;
774 if (uid == UNSET_UID) {
775 RemoveSpecifiedBgTask(taskType);
776 return;
777 }
778 auto iter = continuousTaskInfosMap_.begin();
779 int32_t uidNum = 0;
780 bool uidExist = false;
781 while (iter != continuousTaskInfosMap_.end()) {
782 int32_t recordUid = iter->second->GetUid();
783 uint32_t bgmodeId = iter->second->GetBgModeId();
784 if (recordUid != uid) {
785 iter++;
786 continue;
787 }
788 uidNum++;
789 uidExist = true;
790 if (bgmodeId == taskType) {
791 OnContinuousTaskChanged(iter->second, ContinuousTaskEventTriggerType::TASK_CANCEL);
792 NotificationTools::GetInstance()->CancelNotification(
793 iter->second->GetNotificationLabel(), DEFAULT_NOTIFICATION_ID);
794 iter = continuousTaskInfosMap_.erase(iter);
795 RefreshTaskRecord();
796 uidNum--;
797 } else {
798 iter++;
799 }
800 }
801 if (uidExist && uidNum == 0) {
802 HandleAppContinuousTaskStop(uid);
803 }
804 }
805
RemoveSpecifiedBgTask(uint32_t taskType)806 void BgContinuousTaskMgr::RemoveSpecifiedBgTask(uint32_t taskType)
807 {
808 std::map<int32_t, int32_t> appTaskNum;
809 auto iter = continuousTaskInfosMap_.begin();
810 while (iter != continuousTaskInfosMap_.end()) {
811 int32_t uid = iter->second->GetUid();
812 if (appTaskNum.find(uid) != appTaskNum.end()) {
813 appTaskNum[uid]++;
814 } else {
815 appTaskNum[uid] = 1;
816 }
817 if (iter->second->GetBgModeId() == taskType) {
818 OnContinuousTaskChanged(iter->second, ContinuousTaskEventTriggerType::TASK_CANCEL);
819 NotificationTools::GetInstance()->CancelNotification(
820 iter->second->GetNotificationLabel(), DEFAULT_NOTIFICATION_ID);
821 iter = continuousTaskInfosMap_.erase(iter);
822 RefreshTaskRecord();
823 appTaskNum[uid]--;
824 } else {
825 iter++;
826 }
827 }
828 for (auto var : appTaskNum) {
829 if (var.second == 0) {
830 HandleAppContinuousTaskStop(var.first);
831 }
832 }
833 }
834
AddSubscriber(const sptr<IBackgroundTaskSubscriber> & subscriber)835 ErrCode BgContinuousTaskMgr::AddSubscriber(const sptr<IBackgroundTaskSubscriber> &subscriber)
836 {
837 if (subscriber == nullptr) {
838 BGTASK_LOGE("subscriber is null.");
839 return ERR_BGTASK_INVALID_PARAM;
840 }
841
842 handler_->PostSyncTask([=]() {
843 AddSubscriberInner(subscriber);
844 });
845 return ERR_OK;
846 }
847
AddSubscriberInner(const sptr<IBackgroundTaskSubscriber> & subscriber)848 ErrCode BgContinuousTaskMgr::AddSubscriberInner(const sptr<IBackgroundTaskSubscriber> &subscriber)
849 {
850 auto remoteObj = subscriber->AsObject();
851 auto findSuscriber = [&remoteObj](const auto& target) {
852 return remoteObj == target->AsObject();
853 };
854
855 auto subscriberIter = find_if(bgTaskSubscribers_.begin(), bgTaskSubscribers_.end(), findSuscriber);
856 if (subscriberIter != bgTaskSubscribers_.end()) {
857 BGTASK_LOGW("target subscriber already exist");
858 return ERR_BGTASK_OBJECT_EXISTS;
859 }
860
861 bgTaskSubscribers_.emplace_back(subscriber);
862
863 if (subscriber->AsObject() == nullptr) {
864 BGTASK_LOGW("subscriber is nullptr.");
865 return ERR_BGTASK_INVALID_PARAM;
866 }
867 if (subscriberRecipients_.find(subscriber->AsObject()) != subscriberRecipients_.end()) {
868 BGTASK_LOGW("bgtask subscriber object not exist.");
869 return ERR_BGTASK_OBJECT_EXISTS;
870 }
871 sptr<RemoteDeathRecipient> deathRecipient = new (std::nothrow) RemoteDeathRecipient(
872 [this](const wptr<IRemoteObject> &remote) { this->OnRemoteSubscriberDied(remote); });
873 if (!deathRecipient) {
874 BGTASK_LOGE("create death recipient failed");
875 return ERR_BGTASK_INVALID_PARAM;
876 }
877 subscriber->AsObject()->AddDeathRecipient(deathRecipient);
878 subscriberRecipients_.emplace(subscriber->AsObject(), deathRecipient);
879 subscriber->OnConnected();
880 BGTASK_LOGI("Add continuous task subscriber succeed");
881 return ERR_OK;
882 }
883
RemoveSubscriber(const sptr<IBackgroundTaskSubscriber> & subscriber)884 ErrCode BgContinuousTaskMgr::RemoveSubscriber(const sptr<IBackgroundTaskSubscriber> &subscriber)
885 {
886 if (subscriber == nullptr) {
887 BGTASK_LOGE("subscriber is null.");
888 return ERR_BGTASK_INVALID_PARAM;
889 }
890
891 handler_->PostSyncTask([=]() {
892 RemoveSubscriberInner(subscriber);
893 });
894 return ERR_OK;
895 }
896
RemoveSubscriberInner(const sptr<IBackgroundTaskSubscriber> & subscriber)897 ErrCode BgContinuousTaskMgr::RemoveSubscriberInner(const sptr<IBackgroundTaskSubscriber> &subscriber)
898 {
899 auto remote = subscriber->AsObject();
900 if (remote == nullptr) {
901 BGTASK_LOGE("Subscriber' object is null.");
902 return ERR_BGTASK_INVALID_PARAM;
903 }
904 auto findSubscriber = [&remote](const auto &targetSubscriber) {
905 return remote == targetSubscriber->AsObject();
906 };
907
908 auto subscriberIter = find_if(bgTaskSubscribers_.begin(), bgTaskSubscribers_.end(), findSubscriber);
909 if (subscriberIter == bgTaskSubscribers_.end()) {
910 BGTASK_LOGE("subscriber to remove is not exists.");
911 return ERR_BGTASK_INVALID_PARAM;
912 }
913
914 auto iter = subscriberRecipients_.find(remote);
915 if (iter != subscriberRecipients_.end()) {
916 iter->first->RemoveDeathRecipient(iter->second);
917 subscriberRecipients_.erase(iter);
918 }
919 bgTaskSubscribers_.erase(subscriberIter);
920 BGTASK_LOGI("Remove continuous task subscriber succeed");
921 return ERR_OK;
922 }
923
GetContinuousTaskApps(std::vector<std::shared_ptr<ContinuousTaskCallbackInfo>> & list)924 ErrCode BgContinuousTaskMgr::GetContinuousTaskApps(std::vector<std::shared_ptr<ContinuousTaskCallbackInfo>> &list)
925 {
926 if (!isSysReady_.load()) {
927 BGTASK_LOGW("manager is not ready");
928 return ERR_BGTASK_SYS_NOT_READY;
929 }
930
931 ErrCode result = ERR_OK;
932
933 handler_->PostSyncTask([this, &list, &result]() {
934 result = this->GetContinuousTaskAppsInner(list);
935 }, AppExecFwk::EventQueue::Priority::HIGH);
936
937 return result;
938 }
939
GetContinuousTaskAppsInner(std::vector<std::shared_ptr<ContinuousTaskCallbackInfo>> & list)940 ErrCode BgContinuousTaskMgr::GetContinuousTaskAppsInner(std::vector<std::shared_ptr<ContinuousTaskCallbackInfo>> &list)
941 {
942 if (continuousTaskInfosMap_.empty()) {
943 return ERR_OK;
944 }
945
946 for (auto record : continuousTaskInfosMap_) {
947 auto appInfo = std::make_shared<ContinuousTaskCallbackInfo>(record.second->bgModeId_, record.second->uid_,
948 record.second->pid_, record.second->abilityName_, record.second->isFromWebview_);
949 list.push_back(appInfo);
950 }
951 return ERR_OK;
952 }
953
ShellDump(const std::vector<std::string> & dumpOption,std::vector<std::string> & dumpInfo)954 ErrCode BgContinuousTaskMgr::ShellDump(const std::vector<std::string> &dumpOption, std::vector<std::string> &dumpInfo)
955 {
956 if (!isSysReady_.load()) {
957 BGTASK_LOGW("manager is not ready");
958 return ERR_BGTASK_SYS_NOT_READY;
959 }
960 ErrCode result = ERR_OK;
961 handler_->PostSyncTask([&]() {
962 result = ShellDumpInner(dumpOption, dumpInfo);
963 });
964
965 return result;
966 }
967
ShellDumpInner(const std::vector<std::string> & dumpOption,std::vector<std::string> & dumpInfo)968 ErrCode BgContinuousTaskMgr::ShellDumpInner(const std::vector<std::string> &dumpOption,
969 std::vector<std::string> &dumpInfo)
970 {
971 if (dumpOption[1] == DUMP_PARAM_LIST_ALL) {
972 DumpAllTaskInfo(dumpInfo);
973 } else if (dumpOption[1] == DUMP_PARAM_CANCEL_ALL) {
974 DumpCancelTask(dumpOption, true);
975 } else if (DumpCheckWebviewInfo(dumpOption)) {
976 sptr<ContinuousTaskParamForInner> taskParam = sptr<ContinuousTaskParamForInner>(
977 new ContinuousTaskParamForInner());
978 taskParam->uid_ = std::stoi(dumpOption[WEBVIEW_PARAM_UID]);
979 taskParam->bgModeId_ = static_cast<uint32_t>(std::stoi(dumpOption[WEBVIEW_PARAM_BGMODE]));
980 taskParam->isStart_ = dumpOption[WEBVIEW_PARAM_IS_START] == "Start" ? true : false;
981 RequestBackgroundRunningForInner(taskParam);
982 } else if (dumpOption[1] == DUMP_PARAM_CANCEL) {
983 DumpCancelTask(dumpOption, false);
984 } else {
985 BGTASK_LOGW("invalid dump param");
986 }
987 return ERR_OK;
988 }
989
DumpCheckWebviewInfo(const std::vector<std::string> & dumpOption)990 bool BgContinuousTaskMgr::DumpCheckWebviewInfo(const std::vector<std::string> &dumpOption)
991 {
992 return (dumpOption[1] == "Webview" && dumpOption.size() == WEBVIEW_PARAM_SIZE
993 && !dumpOption[WEBVIEW_PARAM_UID].empty() && !dumpOption[WEBVIEW_PARAM_BGMODE].empty()
994 && dumpOption[WEBVIEW_PARAM_UID].find_first_not_of("0123456789") == std::string::npos
995 && dumpOption[WEBVIEW_PARAM_BGMODE].find_first_not_of("0123456789") == std::string::npos
996 && (dumpOption[WEBVIEW_PARAM_IS_START] == "Start" || dumpOption[WEBVIEW_PARAM_IS_START] == "Stop"));
997 }
998
DumpAllTaskInfo(std::vector<std::string> & dumpInfo)999 void BgContinuousTaskMgr::DumpAllTaskInfo(std::vector<std::string> &dumpInfo)
1000 {
1001 std::stringstream stream;
1002 if (continuousTaskInfosMap_.empty()) {
1003 dumpInfo.emplace_back("No running continuous task\n");
1004 return;
1005 }
1006 std::unordered_map<std::string, std::shared_ptr<ContinuousTaskRecord>>::iterator iter;
1007 uint32_t index = 1;
1008 for (iter = continuousTaskInfosMap_.begin(); iter != continuousTaskInfosMap_.end(); ++iter) {
1009 stream.str("");
1010 stream.clear();
1011 stream << "No." << index;
1012 stream << "\tcontinuousTaskKey: " << iter->first << "\n";
1013 stream << "\tcontinuousTaskValue:" << "\n";
1014 stream << "\t\tbundleName: " << iter->second->GetBundleName() << "\n";
1015 stream << "\t\tabilityName: " << iter->second->GetAbilityName() << "\n";
1016 stream << "\t\tisFromWebview: " << (iter->second->IsFromWebview() ? "true" : "false") << "\n";
1017 stream << "\t\tisFromNewApi: " << (iter->second->IsNewApi() ? "true" : "false") << "\n";
1018 stream << "\t\tbackgroundMode: " << g_continuousTaskModeName[GetBgModeNameIndex(
1019 iter->second->GetBgModeId(), iter->second->IsNewApi())] << "\n";
1020 stream << "\t\tuid: " << iter->second->GetUid() << "\n";
1021 stream << "\t\tuserId: " << iter->second->GetUserId() << "\n";
1022 stream << "\t\tpid: " << iter->second->GetPid() << "\n";
1023 stream << "\t\tnotificationLabel: " << iter->second->GetNotificationLabel() << "\n";
1024 if (iter->second->wantAgentInfo_ != nullptr) {
1025 stream << "\t\twantAgentBundleName: " << iter->second->wantAgentInfo_->bundleName_ << "\n";
1026 stream << "\t\twantAgentAbilityName: " << iter->second->wantAgentInfo_->abilityName_ << "\n";
1027 } else {
1028 stream << "\t\twantAgentBundleName: " << "NULL" << "\n";
1029 stream << "\t\twantAgentAbilityName: " << "NULL" << "\n";
1030 }
1031 stream << "\n";
1032 dumpInfo.emplace_back(stream.str());
1033 index++;
1034 }
1035 }
1036
DumpCancelTask(const std::vector<std::string> & dumpOption,bool cleanAll)1037 void BgContinuousTaskMgr::DumpCancelTask(const std::vector<std::string> &dumpOption, bool cleanAll)
1038 {
1039 if (cleanAll) {
1040 std::set<int32_t> uids;
1041 for (auto item : continuousTaskInfosMap_) {
1042 NotificationTools::GetInstance()->CancelNotification(item.second->GetNotificationLabel(),
1043 DEFAULT_NOTIFICATION_ID);
1044 OnContinuousTaskChanged(item.second, ContinuousTaskEventTriggerType::TASK_CANCEL);
1045 uids.insert(item.second->uid_);
1046 }
1047 continuousTaskInfosMap_.clear();
1048 RefreshTaskRecord();
1049 for (int32_t uid : uids) {
1050 HandleAppContinuousTaskStop(uid);
1051 }
1052 } else {
1053 if (dumpOption.size() < MAX_DUMP_PARAM_NUMS) {
1054 BGTASK_LOGW("invalid dump param");
1055 return;
1056 }
1057 std::string taskKey = dumpOption[2];
1058 auto iter = continuousTaskInfosMap_.find(taskKey);
1059 if (iter == continuousTaskInfosMap_.end()) {
1060 return;
1061 }
1062 NotificationTools::GetInstance()->CancelNotification(iter->second->GetNotificationLabel(),
1063 DEFAULT_NOTIFICATION_ID);
1064 RemoveContinuousTaskRecord(taskKey);
1065 }
1066 }
1067
RemoveContinuousTaskRecord(const std::string & mapKey)1068 bool BgContinuousTaskMgr::RemoveContinuousTaskRecord(const std::string &mapKey)
1069 {
1070 BGTASK_LOGD("task info: %{public}s", mapKey.c_str());
1071 if (continuousTaskInfosMap_.find(mapKey) == continuousTaskInfosMap_.end()) {
1072 BGTASK_LOGW("remove TaskInfo failure, no matched task: %{public}s", mapKey.c_str());
1073 return false;
1074 }
1075 auto record = continuousTaskInfosMap_.at(mapKey);
1076 OnContinuousTaskChanged(record, ContinuousTaskEventTriggerType::TASK_CANCEL);
1077 continuousTaskInfosMap_.erase(mapKey);
1078 HandleAppContinuousTaskStop(record->uid_);
1079 RefreshTaskRecord();
1080 return true;
1081 }
1082
StopContinuousTaskByUser(const std::string & mapKey)1083 bool BgContinuousTaskMgr::StopContinuousTaskByUser(const std::string &mapKey)
1084 {
1085 if (!isSysReady_.load()) {
1086 BGTASK_LOGW("manager is not ready");
1087 return false;
1088 }
1089 bool result = true;
1090 handler_->PostSyncTask([this, mapKey, &result]() {
1091 result = RemoveContinuousTaskRecord(mapKey);
1092 });
1093 return result;
1094 }
1095
OnRemoteSubscriberDied(const wptr<IRemoteObject> & object)1096 void BgContinuousTaskMgr::OnRemoteSubscriberDied(const wptr<IRemoteObject> &object)
1097 {
1098 if (!isSysReady_.load()) {
1099 BGTASK_LOGW("manager is not ready");
1100 return;
1101 }
1102 if (object == nullptr) {
1103 BGTASK_LOGE("remote object is null.");
1104 return;
1105 }
1106
1107 handler_->PostSyncTask([this, &object]() { this->OnRemoteSubscriberDiedInner(object); });
1108 }
1109
OnRemoteSubscriberDiedInner(const wptr<IRemoteObject> & object)1110 void BgContinuousTaskMgr::OnRemoteSubscriberDiedInner(const wptr<IRemoteObject> &object)
1111 {
1112 sptr<IRemoteObject> objectProxy = object.promote();
1113 if (!objectProxy) {
1114 BGTASK_LOGE("get remote object failed");
1115 return;
1116 }
1117 auto iter = bgTaskSubscribers_.begin();
1118 while (iter != bgTaskSubscribers_.end()) {
1119 if ((*iter)->AsObject() == objectProxy) {
1120 iter = bgTaskSubscribers_.erase(iter);
1121 } else {
1122 iter++;
1123 }
1124 }
1125 subscriberRecipients_.erase(objectProxy);
1126 }
1127
OnAbilityStateChanged(int32_t uid,const std::string & abilityName)1128 void BgContinuousTaskMgr::OnAbilityStateChanged(int32_t uid, const std::string &abilityName)
1129 {
1130 if (!isSysReady_.load()) {
1131 BGTASK_LOGW("manager is not ready");
1132 return;
1133 }
1134 auto iter = continuousTaskInfosMap_.begin();
1135 while (iter != continuousTaskInfosMap_.end()) {
1136 if (iter->second->uid_ == uid && (iter->second->abilityName_ == abilityName || iter->second->isFromWebview_)) {
1137 auto record = iter->second;
1138 OnContinuousTaskChanged(record, ContinuousTaskEventTriggerType::TASK_CANCEL);
1139 if (!iter->second->isFromWebview_) {
1140 NotificationTools::GetInstance()->CancelNotification(
1141 record->GetNotificationLabel(), DEFAULT_NOTIFICATION_ID);
1142 }
1143 iter = continuousTaskInfosMap_.erase(iter);
1144 HandleAppContinuousTaskStop(record->uid_);
1145 RefreshTaskRecord();
1146 } else {
1147 iter++;
1148 }
1149 }
1150 }
1151
OnProcessDied(int32_t uid,int32_t pid)1152 void BgContinuousTaskMgr::OnProcessDied(int32_t uid, int32_t pid)
1153 {
1154 if (!isSysReady_.load()) {
1155 BGTASK_LOGW("manager is not ready");
1156 return;
1157 }
1158
1159 auto iter = continuousTaskInfosMap_.begin();
1160 while (iter != continuousTaskInfosMap_.end()) {
1161 if (iter->second->GetPid() == pid) {
1162 auto record = iter->second;
1163 OnContinuousTaskChanged(record, ContinuousTaskEventTriggerType::TASK_CANCEL);
1164 NotificationTools::GetInstance()->CancelNotification(
1165 record->GetNotificationLabel(), DEFAULT_NOTIFICATION_ID);
1166 iter = continuousTaskInfosMap_.erase(iter);
1167 HandleAppContinuousTaskStop(record->uid_);
1168 RefreshTaskRecord();
1169 } else {
1170 iter++;
1171 }
1172 }
1173 }
1174
OnContinuousTaskChanged(const std::shared_ptr<ContinuousTaskRecord> continuousTaskInfo,ContinuousTaskEventTriggerType changeEventType)1175 void BgContinuousTaskMgr::OnContinuousTaskChanged(const std::shared_ptr<ContinuousTaskRecord> continuousTaskInfo,
1176 ContinuousTaskEventTriggerType changeEventType)
1177 {
1178 if (continuousTaskInfo == nullptr) {
1179 BGTASK_LOGW("ContinuousTaskRecord is null");
1180 return;
1181 }
1182
1183 if (bgTaskSubscribers_.empty()) {
1184 BGTASK_LOGI("Background Task Subscriber List is empty");
1185 return;
1186 }
1187
1188 std::shared_ptr<ContinuousTaskCallbackInfo> continuousTaskCallbackInfo
1189 = std::make_shared<ContinuousTaskCallbackInfo>(continuousTaskInfo->GetBgModeId(),
1190 continuousTaskInfo->GetUid(), continuousTaskInfo->GetPid(), continuousTaskInfo->GetAbilityName(),
1191 continuousTaskInfo->IsFromWebview());
1192
1193 switch (changeEventType) {
1194 case ContinuousTaskEventTriggerType::TASK_START:
1195 for (auto iter = bgTaskSubscribers_.begin(); iter != bgTaskSubscribers_.end(); ++iter) {
1196 BGTASK_LOGD("continuous task start callback trigger");
1197 (*iter)->OnContinuousTaskStart(continuousTaskCallbackInfo);
1198 }
1199 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::BACKGROUND_TASK, "CONTINUOUS_TASK_APPLY",
1200 HiviewDFX::HiSysEvent::EventType::STATISTIC, "APP_UID", continuousTaskInfo->GetUid(),
1201 "APP_PID", continuousTaskInfo->GetPid(), "APP_NAME", continuousTaskInfo->GetBundleName(),
1202 "ABILITY", continuousTaskInfo->GetAbilityName(), "BGMODE", continuousTaskInfo->GetBgModeId());
1203 break;
1204 case ContinuousTaskEventTriggerType::TASK_CANCEL:
1205 for (auto iter = bgTaskSubscribers_.begin(); iter != bgTaskSubscribers_.end(); ++iter) {
1206 BGTASK_LOGD("continuous task stop callback trigger");
1207 (*iter)->OnContinuousTaskStop(continuousTaskCallbackInfo);
1208 }
1209 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::BACKGROUND_TASK, "CONTINUOUS_TASK_CANCEL",
1210 HiviewDFX::HiSysEvent::EventType::STATISTIC, "APP_UID", continuousTaskInfo->GetUid(),
1211 "APP_PID", continuousTaskInfo->GetPid(), "APP_NAME", continuousTaskInfo->GetBundleName(),
1212 "ABILITY", continuousTaskInfo->GetAbilityName(), "BGMODE", continuousTaskInfo->GetBgModeId());
1213 break;
1214 }
1215 }
1216
OnBundleInfoChanged(const std::string & action,const std::string & bundleName,int32_t uid)1217 void BgContinuousTaskMgr::OnBundleInfoChanged(const std::string &action, const std::string &bundleName, int32_t uid)
1218 {
1219 if (!isSysReady_.load()) {
1220 BGTASK_LOGW("manager is not ready");
1221 return;
1222 }
1223 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED
1224 || action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED
1225 || action == EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_REMOVED
1226 || action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_FULLY_REMOVED
1227 || action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED
1228 || action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REPLACED) {
1229 cachedBundleInfos_.erase(uid);
1230 } else if (action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_DATA_CLEARED) {
1231 cachedBundleInfos_.erase(uid);
1232 auto iter = continuousTaskInfosMap_.begin();
1233 while (iter != continuousTaskInfosMap_.end()) {
1234 if (iter->second->GetUid() == uid) {
1235 auto record = iter->second;
1236 OnContinuousTaskChanged(record, ContinuousTaskEventTriggerType::TASK_CANCEL);
1237 NotificationTools::GetInstance()->CancelNotification(
1238 record->GetNotificationLabel(), DEFAULT_NOTIFICATION_ID);
1239 iter = continuousTaskInfosMap_.erase(iter);
1240 HandleAppContinuousTaskStop(uid);
1241 RefreshTaskRecord();
1242 } else {
1243 iter++;
1244 }
1245 }
1246 } else {
1247 BGTASK_LOGW("get unregister common event!");
1248 return;
1249 }
1250 }
1251
OnAccountsStateChanged(int32_t id)1252 void BgContinuousTaskMgr::OnAccountsStateChanged(int32_t id)
1253 {
1254 std::vector<int32_t> activatedOsAccountIds;
1255 #ifdef HAS_OS_ACCOUNT_PART
1256 if (AccountSA::OsAccountManager::QueryActiveOsAccountIds(activatedOsAccountIds) != ERR_OK) {
1257 BGTASK_LOGE("query activated account failed");
1258 return;
1259 }
1260 #else // HAS_OS_ACCOUNT_PART
1261 activatedOsAccountIds.push_back(DEFAULT_OS_ACCOUNT_ID);
1262 BGTASK_LOGI("there is no account part, use default id.");
1263 #endif // HAS_OS_ACCOUNT_PART
1264 auto iter = continuousTaskInfosMap_.begin();
1265 while (iter != continuousTaskInfosMap_.end()) {
1266 auto idIter = find(activatedOsAccountIds.begin(), activatedOsAccountIds.end(), iter->second->GetUserId());
1267 if (idIter == activatedOsAccountIds.end()) {
1268 auto record = iter->second;
1269 OnContinuousTaskChanged(record, ContinuousTaskEventTriggerType::TASK_CANCEL);
1270 NotificationTools::GetInstance()->CancelNotification(
1271 record->GetNotificationLabel(), DEFAULT_NOTIFICATION_ID);
1272 iter = continuousTaskInfosMap_.erase(iter);
1273 HandleAppContinuousTaskStop(record->uid_);
1274 RefreshTaskRecord();
1275 } else {
1276 iter++;
1277 }
1278 }
1279 }
1280
HandleAppContinuousTaskStop(int32_t uid)1281 void BgContinuousTaskMgr::HandleAppContinuousTaskStop(int32_t uid)
1282 {
1283 auto findUid = [uid](const auto &target) {
1284 return uid == target.second->GetUid();
1285 };
1286 auto findUidIter = find_if(continuousTaskInfosMap_.begin(), continuousTaskInfosMap_.end(), findUid);
1287 if (findUidIter != continuousTaskInfosMap_.end()) {
1288 return;
1289 }
1290 BGTASK_LOGI("All continuous task has stopped of uid: %{public}d, so notify related subsystem", uid);
1291 for (auto iter = bgTaskSubscribers_.begin(); iter != bgTaskSubscribers_.end(); iter++) {
1292 (*iter)->OnAppContinuousTaskStop(uid);
1293 }
1294 }
1295
RefreshTaskRecord()1296 int32_t BgContinuousTaskMgr::RefreshTaskRecord()
1297 {
1298 int32_t ret = DelayedSingleton<DataStorageHelper>::GetInstance()->RefreshTaskRecord(continuousTaskInfosMap_);
1299 if (ret != ERR_OK) {
1300 BGTASK_LOGE("refresh data failed");
1301 return ret;
1302 }
1303 return ERR_OK;
1304 }
1305
GetMainAbilityLabel(const std::string & bundleName,int32_t userId)1306 std::string BgContinuousTaskMgr::GetMainAbilityLabel(const std::string &bundleName, int32_t userId)
1307 {
1308 AppExecFwk::BundleInfo bundleInfo;
1309 if (!BundleManagerHelper::GetInstance()->GetBundleInfo(bundleName,
1310 AppExecFwk::BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, userId)) {
1311 BGTASK_LOGE("Get %{public}s bundle info failed", bundleName.c_str());
1312 return "";
1313 }
1314 auto resourceManager = GetBundleResMgr(bundleInfo);
1315 if (resourceManager == nullptr) {
1316 BGTASK_LOGE("Get %{public}s resource manager failed", bundleName.c_str());
1317 return "";
1318 }
1319
1320 AAFwk::Want want;
1321 want.SetAction("action.system.home");
1322 want.AddEntity("entity.system.home");
1323 want.SetElementName("", bundleName, "", "");
1324 AppExecFwk::AbilityInfo abilityInfo;
1325 if (!BundleManagerHelper::GetInstance()->QueryAbilityInfo(want,
1326 AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION, userId, abilityInfo)) {
1327 BGTASK_LOGE("Get %{public}s main ability info failed", bundleName.c_str());
1328 return "";
1329 }
1330 std::string mainAbilityLabel {""};
1331 resourceManager->GetStringById(static_cast<uint32_t>(abilityInfo.labelId), mainAbilityLabel);
1332 BGTASK_LOGI("Get main ability label: %{public}s by labelId: %{public}d", mainAbilityLabel.c_str(),
1333 abilityInfo.labelId);
1334 mainAbilityLabel = mainAbilityLabel.empty() ? abilityInfo.label : mainAbilityLabel;
1335 return mainAbilityLabel;
1336 }
1337
OnConfigurationChanged(const AppExecFwk::Configuration & configuration)1338 void BgContinuousTaskMgr::OnConfigurationChanged(const AppExecFwk::Configuration &configuration)
1339 {
1340 BGTASK_LOGI("System language config has changed");
1341 if (!isSysReady_.load()) {
1342 BGTASK_LOGW("manager is not ready");
1343 return;
1344 }
1345 GetNotificationPrompt();
1346 cachedBundleInfos_.clear();
1347 std::map<std::string, std::pair<std::string, std::string>> newPromptInfos;
1348 auto iter = continuousTaskInfosMap_.begin();
1349 while (iter != continuousTaskInfosMap_.end()) {
1350 auto record = iter->second;
1351 std::string mainAbilityLabel = GetMainAbilityLabel(record->bundleName_, record->userId_);
1352
1353 std::string notificationText {""};
1354 uint32_t index = GetBgModeNameIndex(record->bgModeId_, record->isNewApi_);
1355 if (index < BGMODE_NUMS) {
1356 notificationText = continuousTaskText_.at(index);
1357 }
1358 newPromptInfos.emplace(record->notificationLabel_, std::make_pair(mainAbilityLabel, notificationText));
1359 iter++;
1360 }
1361 NotificationTools::GetInstance()->RefreshContinuousNotifications(newPromptInfos, bgTaskUid_);
1362 }
1363 } // namespace BackgroundTaskMgr
1364 } // namespace OHOS
1365