1 /*
2 * Copyright (c) 2024-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 "keep_alive_process_manager.h"
17
18 #include <utility>
19
20 #include "ability_util.h"
21 #include "ffrt.h"
22 #include "ipc_skeleton.h"
23 #include "keep_alive_utils.h"
24 #include "main_element_utils.h"
25 #include "parameters.h"
26 #include "permission_constants.h"
27 #include "process_options.h"
28
29 namespace OHOS {
30 namespace AAFwk {
31 namespace {
32 constexpr char PRODUCT_ENTERPRISE_FEATURE_SETTING_ENABLED[] = "const.product.enterprisefeature.setting.enabled";
33 constexpr char FOUNDATION_PROCESS_NAME[] = "foundation";
34 constexpr int MAX_RETRY_TIMES = 3;
35 constexpr int RETRY_INTERVAL_MICRO_SECONDS = 200000; // 200ms
36 constexpr int CREATE_STATUS_BAR_TIMEOUT_MICRO_SECONDS = 5000000; // 5s
37 } // namespace
38
Cancel()39 void CheckStatusBarTask::Cancel()
40 {
41 std::lock_guard<ffrt::mutex> lock(cancelMutex_);
42 task_ = nullptr;
43 }
44
Run()45 void CheckStatusBarTask::Run()
46 {
47 std::lock_guard<ffrt::mutex> lock(cancelMutex_);
48 if (task_ == nullptr) {
49 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "task is canceled");
50 return;
51 }
52
53 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "run check task");
54 task_();
55 }
56
GetInstance()57 KeepAliveProcessManager &KeepAliveProcessManager::GetInstance()
58 {
59 static KeepAliveProcessManager instance;
60 return instance;
61 }
62
KeepAliveProcessManager()63 KeepAliveProcessManager::KeepAliveProcessManager() {}
64
~KeepAliveProcessManager()65 KeepAliveProcessManager::~KeepAliveProcessManager() {}
66
StartKeepAliveProcessWithMainElement(std::vector<AppExecFwk::BundleInfo> & bundleInfos,int32_t userId)67 void KeepAliveProcessManager::StartKeepAliveProcessWithMainElement(std::vector<AppExecFwk::BundleInfo> &bundleInfos,
68 int32_t userId)
69 {
70 if (!DelayedSingleton<AbilityManagerService>::GetInstance()->IsSceneBoardReady(userId)) {
71 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "SCB not ready, do not start keep-alive apps");
72 return;
73 }
74 for (const auto &bundleInfo : bundleInfos) {
75 StartKeepAliveProcessWithMainElementPerBundle(bundleInfo, userId);
76 }
77 }
78
StartKeepAliveProcessWithMainElementPerBundle(const AppExecFwk::BundleInfo & bundleInfo,int32_t userId)79 void KeepAliveProcessManager::StartKeepAliveProcessWithMainElementPerBundle(const AppExecFwk::BundleInfo &bundleInfo,
80 int32_t userId)
81 {
82 if (!IsKeepAliveBundle(bundleInfo.name, userId)) {
83 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "bundle is not set keep-alive");
84 return;
85 }
86
87 std::string mainElementName;
88 if (!MainElementUtils::CheckMainUIAbility(bundleInfo, mainElementName)) {
89 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "bundle has no main uiability");
90 return;
91 }
92 KeepAliveAbilityInfo info = {
93 .userId = userId,
94 .appCloneIndex = bundleInfo.appIndex,
95 .uid = bundleInfo.uid,
96 .bundleName = bundleInfo.name,
97 .moduleName = bundleInfo.entryModuleName,
98 .abilityName = mainElementName,
99 };
100 auto isMultiInstance =
101 bundleInfo.applicationInfo.multiAppMode.multiAppModeType == AppExecFwk::MultiAppModeType::MULTI_INSTANCE;
102 auto ret = StartKeepAliveMainAbility(info);
103 if (ret == ERR_OK) {
104 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "start ok");
105 AfterStartKeepAliveApp(bundleInfo.name, bundleInfo.applicationInfo.accessTokenId,
106 bundleInfo.uid, userId, isMultiInstance);
107 return;
108 }
109
110 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "StartKeepAliveMainAbility failed:%{public}d, retry", ret);
111 ffrt::submit([bundleName = bundleInfo.name, accessTokenId = bundleInfo.applicationInfo.accessTokenId,
112 uid = bundleInfo.uid, userId, info, ret, isMultiInstance]() mutable {
113 for (int tried = 0; tried < MAX_RETRY_TIMES && ret != ERR_OK; tried++) {
114 usleep(RETRY_INTERVAL_MICRO_SECONDS);
115 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "retry attempt:%{public}d", tried + 1);
116 ret = KeepAliveProcessManager::GetInstance().StartKeepAliveMainAbility(info);
117 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "retry result:%{public}d", ret);
118 }
119 if (ret != ERR_OK) {
120 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "reach max retry, failed:%{public}d, unsetting keep-alive", ret);
121 KeepAliveProcessManager::GetInstance().SetApplicationKeepAlive(bundleName, userId, false, true, true);
122 return;
123 }
124 KeepAliveProcessManager::GetInstance().AfterStartKeepAliveApp(bundleName, accessTokenId, uid, userId,
125 isMultiInstance);
126 });
127 }
128
StartKeepAliveMainAbility(const KeepAliveAbilityInfo & info)129 int32_t KeepAliveProcessManager::StartKeepAliveMainAbility(const KeepAliveAbilityInfo &info)
130 {
131 Want want;
132 want.SetElementName(info.bundleName, info.abilityName);
133 want.SetParam(Want::PARAM_APP_CLONE_INDEX_KEY, info.appCloneIndex);
134 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "call, bundleName: %{public}s, moduleName: %{public}s, mainElement: %{public}s"
135 " appCloneIndex: %{public}d", info.bundleName.c_str(), info.moduleName.c_str(), info.abilityName.c_str(),
136 info.appCloneIndex);
137 StartOptions options;
138 if (DelayedSingleton<AbilityManagerService>::GetInstance()->IsSupportStatusBar(info.uid)) {
139 options.processOptions = std::make_shared<ProcessOptions>();
140 options.processOptions->isRestartKeepAlive = true;
141 options.processOptions->startupVisibility = StartupVisibility::STARTUP_HIDE;
142 }
143 auto ret = IN_PROCESS_CALL(DelayedSingleton<AbilityManagerService>::GetInstance()->StartAbility(want,
144 options, nullptr, info.userId, DEFAULT_INVAL_VALUE));
145 MainElementUtils::UpdateMainElement(info.bundleName, info.moduleName, info.abilityName, true, info.userId);
146 return ret;
147 }
148
AfterStartKeepAliveApp(const std::string & bundleName,uint32_t accessTokenId,int32_t uid,int32_t userId,bool isMultiInstance)149 void KeepAliveProcessManager::AfterStartKeepAliveApp(const std::string &bundleName,
150 uint32_t accessTokenId, int32_t uid, int32_t userId, bool isMultiInstance)
151 {
152 // not support statusbar and don't need check after 5s
153 if (!DelayedSingleton<AbilityManagerService>::GetInstance()->IsSupportStatusBar(uid)) {
154 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "not support statusBar, don't need check when keep alive");
155 return;
156 }
157
158 auto task = [bundleName, accessTokenId, uid, userId, isMultiInstance]() {
159 bool isStatusBarCreated =
160 DelayedSingleton<AbilityManagerService>::GetInstance()->IsInStatusBar(accessTokenId, uid, isMultiInstance);
161 (void)KeepAliveProcessManager::GetInstance().RemoveCheckStatusBarTask(uid, false);
162 if (isStatusBarCreated) {
163 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "status bar is created");
164 return;
165 }
166 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "timeout, status bar not created, unsetting keep-alive");
167 KeepAliveProcessManager::GetInstance().SetApplicationKeepAlive(bundleName, userId, false, true, true);
168 (void)DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->KillApplication(bundleName);
169 };
170
171 std::lock_guard<ffrt::mutex> lock(checkStatusBarTasksMutex_);
172 auto iter = std::find_if(checkStatusBarTasks_.begin(), checkStatusBarTasks_.end(),
173 [uid](const std::shared_ptr<CheckStatusBarTask> &curTask) {
174 return curTask != nullptr && curTask->GetUid() == uid;
175 });
176 if (iter != checkStatusBarTasks_.end()) {
177 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "exists same task, canceling");
178 if (*iter != nullptr) {
179 (*iter)->Cancel();
180 }
181 checkStatusBarTasks_.erase(iter);
182 }
183 auto checkStatusBarTask = std::make_shared<CheckStatusBarTask>(uid, std::move(task));
184 checkStatusBarTasks_.push_back(checkStatusBarTask);
185 ffrt::task_attr attr;
186 attr.delay(CREATE_STATUS_BAR_TIMEOUT_MICRO_SECONDS);
187 ffrt::submit([checkStatusBarTask]() {
188 if (checkStatusBarTask != nullptr) {
189 checkStatusBarTask->Run();
190 }
191 }, attr);
192 }
193
RemoveCheckStatusBarTask(int32_t uid,bool shouldCancel)194 void KeepAliveProcessManager::RemoveCheckStatusBarTask(int32_t uid, bool shouldCancel)
195 {
196 std::lock_guard<ffrt::mutex> lock(checkStatusBarTasksMutex_);
197 auto iter = std::find_if(checkStatusBarTasks_.begin(), checkStatusBarTasks_.end(),
198 [uid](const std::shared_ptr<CheckStatusBarTask> &curTask) {
199 return curTask != nullptr && curTask->GetUid() == uid;
200 });
201 if (iter == checkStatusBarTasks_.end()) {
202 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "not exist");
203 return;
204 }
205 if (*iter != nullptr && shouldCancel) {
206 (*iter)->Cancel();
207 }
208 checkStatusBarTasks_.erase(iter);
209 }
210
SetApplicationKeepAlive(const std::string & bundleName,int32_t userId,bool updateEnable,bool isByEDM,bool isInner)211 int32_t KeepAliveProcessManager::SetApplicationKeepAlive(const std::string &bundleName,
212 int32_t userId, bool updateEnable, bool isByEDM, bool isInner)
213 {
214 auto result = isByEDM ? CheckPermissionForEDM() : CheckPermission();
215 CHECK_RET_RETURN_RET(result, "permission denied");
216
217 CHECK_TRUE_RETURN_RET(bundleName.empty(), INVALID_PARAMETERS_ERR, "input parameter error");
218
219 auto bms = AbilityUtil::GetBundleManagerHelper();
220 CHECK_POINTER_AND_RETURN(bms, INNER_ERR);
221
222 userId = userId < 0 ? DelayedSingleton<AbilityManagerService>::GetInstance()->GetUserId() : userId;
223 AppExecFwk::BundleInfo bundleInfo;
224 if (!IN_PROCESS_CALL(bms->GetBundleInfo(
225 bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo, userId))) {
226 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "get bundle info failed");
227 return ERR_TARGET_BUNDLE_NOT_EXIST;
228 }
229
230 auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
231 CHECK_POINTER_AND_RETURN(appMgrClient, INNER_ERR);
232
233 bool localEnable = IsKeepAliveBundle(bundleName, userId);
234 if (updateEnable) {
235 std::string mainElementName;
236 CHECK_TRUE_RETURN_RET(!MainElementUtils::CheckMainUIAbility(bundleInfo, mainElementName),
237 ERR_NO_MAIN_ABILITY, "bundle has no main uiability");
238 if (DelayedSingleton<AbilityManagerService>::GetInstance()->IsSupportStatusBar(bundleInfo.uid)) {
239 CHECK_TRUE_RETURN_RET(!MainElementUtils::CheckStatusBarAbility(bundleInfo),
240 ERR_NO_STATUS_BAR_ABILITY, "app has no status bar");
241 bool isRunning = false;
242 result = IN_PROCESS_CALL(appMgrClient->IsAppRunningByBundleNameAndUserId(bundleName, userId, isRunning));
243 CHECK_RET_RETURN_RET(result, "IsAppRunning failed");
244 CHECK_TRUE_RETURN_RET((isRunning && !IsRunningAppInStatusBar(bundleInfo)),
245 ERR_NOT_ATTACHED_TO_STATUS_BAR, "app is not attached to status bar");
246 }
247 }
248
249 KeepAliveInfo info;
250 info.bundleName = bundleName;
251 info.userId = userId;
252 info.appType = bundleInfo.applicationInfo.isSystemApp ? KeepAliveAppType::SYSTEM : KeepAliveAppType::THIRD_PARTY;
253 info.setter = isByEDM ? KeepAliveSetter::SYSTEM : KeepAliveSetter::USER;
254 result = AbilityKeepAliveService::GetInstance().SetApplicationKeepAlive(info, updateEnable);
255 CHECK_RET_RETURN_RET(result, "set keep-alive failed");
256 IN_PROCESS_CALL_WITHOUT_RET(appMgrClient->SetKeepAliveDkv(bundleName, updateEnable, 0));
257 if (!updateEnable && localEnable) {
258 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "unsetting keep-alive");
259 if (!isInner) {
260 RemoveCheckStatusBarTask(bundleInfo.uid, true);
261 }
262 std::vector<AppExecFwk::BundleInfo> bundleInfos{ bundleInfo };
263 KeepAliveUtils::NotifyDisableKeepAliveProcesses(bundleInfos, userId);
264 }
265 return ERR_OK;
266 }
267
IsRunningAppInStatusBar(const AppExecFwk::BundleInfo & bundleInfo)268 bool KeepAliveProcessManager::IsRunningAppInStatusBar(const AppExecFwk::BundleInfo &bundleInfo)
269 {
270 std::string mainElementName;
271 if (!MainElementUtils::CheckMainUIAbility(bundleInfo, mainElementName)) {
272 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "bundle has no main uiability");
273 return false;
274 }
275 auto isMultiInstance =
276 bundleInfo.applicationInfo.multiAppMode.multiAppModeType == AppExecFwk::MultiAppModeType::MULTI_INSTANCE;
277 return DelayedSingleton<AbilityManagerService>::GetInstance()->IsInStatusBar(
278 bundleInfo.applicationInfo.accessTokenId, bundleInfo.uid, isMultiInstance);
279 }
280
OnAppStateChanged(const AppInfo & info)281 void KeepAliveProcessManager::OnAppStateChanged(const AppInfo &info)
282 {
283 if (info.state != AppState::BEGIN) {
284 TAG_LOGD(AAFwkTag::KEEP_ALIVE, "Not a state of concern. state: %{public}d", info.state);
285 return;
286 }
287
288 if (info.pid <= 0) {
289 TAG_LOGD(AAFwkTag::KEEP_ALIVE, "The obtained application pid is incorrect. state: %{public}d", info.pid);
290 return;
291 }
292
293 // user 0
294 int32_t uid = 0;
295 auto appScheduler = DelayedSingleton<AppScheduler>::GetInstance();
296 if (appScheduler == nullptr) {
297 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "app scheduler error");
298 return;
299 }
300 std::string bundleName;
301 appScheduler->GetBundleNameByPid(info.pid, bundleName, uid);
302 if (bundleName.empty()) {
303 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "get bundle name by pid failed");
304 return;
305 }
306
307 auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
308 if (appMgrClient == nullptr) {
309 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "appMgrClient is null");
310 return;
311 }
312
313 bool localEnableForAppservice = IsKeepAliveBundle(bundleName, U1_USER_ID);
314 if (localEnableForAppservice) {
315 IN_PROCESS_CALL_WITHOUT_RET(appMgrClient->SetKeepAliveAppService(bundleName, localEnableForAppservice, uid));
316 }
317 }
318
IsKeepAliveBundle(const std::string & bundleName,int32_t userId)319 bool KeepAliveProcessManager::IsKeepAliveBundle(const std::string &bundleName, int32_t userId)
320 {
321 if (!system::GetBoolParameter(PRODUCT_ENTERPRISE_FEATURE_SETTING_ENABLED, false)) {
322 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "not supported");
323 return false;
324 }
325 return AbilityKeepAliveService::GetInstance().IsKeepAliveApp(bundleName, userId);
326 }
327
GetKeepAliveBundleInfosForUser(std::vector<AppExecFwk::BundleInfo> & bundleInfos,int32_t userId)328 bool KeepAliveProcessManager::GetKeepAliveBundleInfosForUser(std::vector<AppExecFwk::BundleInfo> &bundleInfos,
329 int32_t userId)
330 {
331 if (!system::GetBoolParameter(PRODUCT_ENTERPRISE_FEATURE_SETTING_ENABLED, false)) {
332 TAG_LOGW(AAFwkTag::KEEP_ALIVE, "not supported");
333 return false;
334 }
335 auto bundleMgrHelper = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
336 CHECK_POINTER_AND_RETURN(bundleMgrHelper, false);
337
338 std::vector<KeepAliveInfo> infoList;
339 auto ret = AbilityKeepAliveService::GetInstance().GetKeepAliveApplications(userId, infoList);
340 if (ret != ERR_OK) {
341 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "failed get keep_alive bundle info: %{public}d", ret);
342 return false;
343 }
344 for (const auto &info: infoList) {
345 AppExecFwk::BundleInfo bundleInfo;
346 if (!IN_PROCESS_CALL(bundleMgrHelper->GetBundleInfo(info.bundleName,
347 AppExecFwk::BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, userId))) {
348 TAG_LOGW(AAFwkTag::KEEP_ALIVE, "failed get bundle info: %{public}s", info.bundleName.c_str());
349 continue;
350 }
351 bundleInfos.push_back(bundleInfo);
352 }
353
354 return !bundleInfos.empty();
355 }
356
FilterNeedRestartKeepAliveBundleInfos(std::vector<AppExecFwk::BundleInfo> & bundleInfos)357 void KeepAliveProcessManager::FilterNeedRestartKeepAliveBundleInfos(
358 std::vector<AppExecFwk::BundleInfo> &bundleInfos)
359 {
360 std::lock_guard<ffrt::mutex> lock(needRestartKeepAliveUidSetLock_);
361 for (auto it = bundleInfos.begin(); it != bundleInfos.end();) {
362 auto uidIter = needRestartKeepAliveUidSet_.find(it->uid);
363 if (uidIter == needRestartKeepAliveUidSet_.end()) {
364 TAG_LOGD(AAFwkTag::KEEP_ALIVE, "bundle no need to restart: %{public}s", it->name.c_str());
365 it = bundleInfos.erase(it);
366 continue;
367 }
368 needRestartKeepAliveUidSet_.erase(uidIter);
369 ++it;
370 }
371 }
372
AddNeedRestartKeepAliveUid(int32_t uid)373 void KeepAliveProcessManager::AddNeedRestartKeepAliveUid(int32_t uid)
374 {
375 std::lock_guard<ffrt::mutex> lock(needRestartKeepAliveUidSetLock_);
376 needRestartKeepAliveUidSet_.emplace(uid);
377 }
378
QueryKeepAliveApplications(int32_t appType,int32_t userId,std::vector<KeepAliveInfo> & infoList,bool isByEDM)379 int32_t KeepAliveProcessManager::QueryKeepAliveApplications(int32_t appType, int32_t userId,
380 std::vector<KeepAliveInfo> &infoList, bool isByEDM)
381 {
382 auto result = isByEDM ? CheckPermissionForEDM() : CheckPermission();
383 CHECK_RET_RETURN_RET(result, "permission denied");
384 return AbilityKeepAliveService::GetInstance().QueryKeepAliveApplications(userId, appType, infoList);
385 }
386
SetAppServiceExtensionKeepAlive(const std::string & bundleName,bool updateEnable,bool isByEDM,bool isallowUserToCancel)387 int32_t KeepAliveProcessManager::SetAppServiceExtensionKeepAlive(const std::string &bundleName, bool updateEnable,
388 bool isByEDM, bool isallowUserToCancel)
389 {
390 auto result = isByEDM ? CheckPermissionForEDM() : CheckPermission();
391 CHECK_RET_RETURN_RET(result, "permission denied");
392
393 CHECK_TRUE_RETURN_RET(bundleName.empty(), INVALID_PARAMETERS_ERR, "input parameter error");
394
395 auto bms = AbilityUtil::GetBundleManagerHelper();
396 CHECK_POINTER_AND_RETURN(bms, INNER_ERR);
397 AppExecFwk::BundleInfo bundleInfo;
398 if (!IN_PROCESS_CALL(bms->GetBundleInfo(
399 bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo, U1_USER_ID))) {
400 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "The target bundle is not in u1");
401 return ERR_NO_U1;
402 }
403
404 std::string mainElementName;
405 CHECK_TRUE_RETURN_RET(!MainElementUtils::CheckAppServiceExtension(bundleInfo, mainElementName),
406 ERR_INVALID_MAIN_ELEMENT_TYPE, "Invalid main element type");
407
408 auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
409 CHECK_POINTER_AND_RETURN(appMgrClient, INNER_ERR);
410
411 KeepAliveInfo info;
412 info.bundleName = bundleName;
413 info.userId = U1_USER_ID;
414 info.setterId = IPCSkeleton::GetCallingUid() / BASE_USER_RANGE;
415 info.appType = bundleInfo.applicationInfo.isSystemApp ? KeepAliveAppType::SYSTEM : KeepAliveAppType::THIRD_PARTY;
416 info.setter = isByEDM ? KeepAliveSetter::SYSTEM : KeepAliveSetter::USER;
417 info.policy = isByEDM ? (isallowUserToCancel ? KeepAlivePolicy::ALLOW_CANCEL : KeepAlivePolicy::NOT_ALLOW_CANCEL) :
418 KeepAlivePolicy::UNSPECIFIED;
419 result = AbilityKeepAliveService::GetInstance().SetAppServiceExtensionKeepAlive(info, updateEnable);
420 CHECK_RET_RETURN_RET(result, "set keep-alive failed");
421 IN_PROCESS_CALL_WITHOUT_RET(appMgrClient->SetKeepAliveAppService(bundleName, updateEnable, bundleInfo.uid));
422 return ERR_OK;
423 }
424
QueryKeepAliveAppServiceExtensions(std::vector<KeepAliveInfo> & infoList,bool isByEDM)425 int32_t KeepAliveProcessManager::QueryKeepAliveAppServiceExtensions(std::vector<KeepAliveInfo> &infoList, bool isByEDM)
426 {
427 auto result = isByEDM ? CheckPermissionForEDM() : CheckPermission();
428 CHECK_RET_RETURN_RET(result, "permission denied");
429 return AbilityKeepAliveService::GetInstance().QueryKeepAliveAppServiceExtensions(infoList);
430 }
431
StartKeepAliveAppServiceExtension(std::vector<AppExecFwk::BundleInfo> & bundleInfos)432 void KeepAliveProcessManager::StartKeepAliveAppServiceExtension(std::vector<AppExecFwk::BundleInfo> &bundleInfos)
433 {
434 for (const auto &bundleInfo : bundleInfos) {
435 StartKeepAliveAppServiceExtensionPerBundle(bundleInfo);
436 }
437 }
438
StartKeepAliveAppServiceExtensionPerBundle(const AppExecFwk::BundleInfo & bundleInfo)439 void KeepAliveProcessManager::StartKeepAliveAppServiceExtensionPerBundle(const AppExecFwk::BundleInfo &bundleInfo)
440 {
441 auto userId = U1_USER_ID;
442 if (!IsKeepAliveBundle(bundleInfo.name, userId)) {
443 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "bundle is not set keep-alive");
444 return;
445 }
446
447 std::string mainElementName;
448 if (!MainElementUtils::CheckAppServiceExtension(bundleInfo, mainElementName)) {
449 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "Invalid main element type");
450 return;
451 }
452
453 KeepAliveAbilityInfo info = {
454 .userId = userId,
455 .appCloneIndex = bundleInfo.appIndex,
456 .uid = bundleInfo.uid,
457 .bundleName = bundleInfo.name,
458 .moduleName = bundleInfo.entryModuleName,
459 .abilityName = mainElementName,
460 };
461 auto ret = StartKeepAliveAppServiceExtensionInner(info);
462 if (ret == ERR_OK) {
463 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "start ok");
464 return;
465 }
466
467 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "StartKeepAliveAppServiceExtension failed:%{public}d, retry", ret);
468 ffrt::submit([bundleName = bundleInfo.name, userId, info, ret]() mutable {
469 for (int tried = 0; tried < MAX_RETRY_TIMES && ret != ERR_OK; tried++) {
470 usleep(RETRY_INTERVAL_MICRO_SECONDS);
471 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "retry attempt:%{public}d", tried + 1);
472 ret = KeepAliveProcessManager::GetInstance().StartKeepAliveAppServiceExtensionInner(info);
473 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "retry result:%{public}d", ret);
474 }
475 if (ret != ERR_OK) {
476 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "reach max retry, failed:%{public}d, unsetting keep-alive", ret);
477 return;
478 }
479 });
480 }
481
StartKeepAliveAppServiceExtensionInner(const KeepAliveAbilityInfo & info)482 int32_t KeepAliveProcessManager::StartKeepAliveAppServiceExtensionInner(const KeepAliveAbilityInfo &info)
483 {
484 Want want;
485 want.SetElementName(info.bundleName, info.abilityName);
486 want.SetParam(Want::PARAM_APP_CLONE_INDEX_KEY, info.appCloneIndex);
487 TAG_LOGI(AAFwkTag::KEEP_ALIVE, "call, bundleName: %{public}s, moduleName: %{public}s, mainElement: %{public}s"
488 " appCloneIndex: %{public}d", info.bundleName.c_str(), info.moduleName.c_str(), info.abilityName.c_str(),
489 info.appCloneIndex);
490 auto ret = IN_PROCESS_CALL(DelayedSingleton<AbilityManagerService>::GetInstance()->StartExtensionAbility(want,
491 nullptr, info.userId, AppExecFwk::ExtensionAbilityType::APP_SERVICE));
492 return ret;
493 }
494
ClearKeepAliveAppServiceExtension(int32_t userId)495 int32_t KeepAliveProcessManager::ClearKeepAliveAppServiceExtension(int32_t userId)
496 {
497 KeepAliveInfo info;
498 info.setterId = userId;
499 return AbilityKeepAliveService::GetInstance().ClearKeepAliveAppServiceExtension(info);
500 }
501
CheckPermission()502 int32_t KeepAliveProcessManager::CheckPermission()
503 {
504 if (!system::GetBoolParameter(PRODUCT_ENTERPRISE_FEATURE_SETTING_ENABLED, false)) {
505 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "not supported");
506 return ERR_CAPABILITY_NOT_SUPPORT;
507 }
508
509 if (!PermissionVerification::GetInstance()->JudgeCallerIsAllowedToUseSystemAPI()) {
510 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "not use system-api");
511 return ERR_NOT_SYSTEM_APP;
512 }
513
514 if (!PermissionVerification::GetInstance()->VerifyCallingPermission(
515 PermissionConstants::PERMISSION_MANAGE_APP_KEEP_ALIVE)) {
516 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "verify PERMISSION_MANAGE_APP_KEEP_ALIVE fail");
517 return CHECK_PERMISSION_FAILED;
518 }
519
520 return ERR_OK;
521 }
522
CheckPermissionForEDM()523 int32_t KeepAliveProcessManager::CheckPermissionForEDM()
524 {
525 if (!system::GetBoolParameter(PRODUCT_ENTERPRISE_FEATURE_SETTING_ENABLED, false)) {
526 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "not supported");
527 return ERR_CAPABILITY_NOT_SUPPORT;
528 }
529 if (PermissionVerification::GetInstance()->CheckSpecificSystemAbilityAccessPermission(FOUNDATION_PROCESS_NAME)
530 || (PermissionVerification::GetInstance()->IsSACall()
531 && PermissionVerification::GetInstance()->VerifyCallingPermission(
532 PermissionConstants::PERMISSION_MANAGE_APP_KEEP_ALIVE_INTERNAL))) {
533 return ERR_OK;
534 }
535 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "verify PERMISSION_MANAGE_APP_KEEP_ALIVE_INTERNAL fail");
536 return CHECK_PERMISSION_FAILED;
537 }
538
SaveAppSeriviceRestartAfterUpgrade(const std::string & bundleName,int32_t uid)539 void KeepAliveProcessManager::SaveAppSeriviceRestartAfterUpgrade(const std::string &bundleName, int32_t uid)
540 {
541 if (!IsKeepAliveBundle(bundleName, U1_USER_ID)) {
542 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "bundle is not set keep-alive");
543 return;
544 }
545
546 auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
547 if (!appMgrClient) {
548 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "appMgrClient is null");
549 return;
550 }
551
552 std::vector<AppExecFwk::RunningProcessInfo> infos;
553 auto ret = IN_PROCESS_CALL(appMgrClient->GetProcessRunningInfosByUserId(infos, uid / BASE_USER_RANGE));
554 if (ret != ERR_OK) {
555 TAG_LOGE(AAFwkTag::KEEP_ALIVE, "get ProcessRunningInfos by userId fail");
556 return;
557 }
558
559 std::lock_guard<std::mutex> lock(restartAfterUpgradeMutex_);
560 for (const auto& info : infos) {
561 if (info.uid_ == uid && info.isKeepAliveAppService) {
562 restartAfterUpgradeList_.insert(uid);
563 IN_PROCESS_CALL_WITHOUT_RET(appMgrClient->SetKeepAliveAppService(bundleName, false, uid));
564 }
565 }
566 }
567
568
CheckNeedRestartAfterUpgrade(int32_t uid)569 bool KeepAliveProcessManager::CheckNeedRestartAfterUpgrade(int32_t uid)
570 {
571 std::lock_guard<std::mutex> lock(restartAfterUpgradeMutex_);
572 auto iter = restartAfterUpgradeList_.find(uid);
573 if (iter == restartAfterUpgradeList_.end()) {
574 return false;
575 }
576 restartAfterUpgradeList_.erase(iter);
577 return true;
578 }
579 } // namespace AAFwk
580 } // namespace OHOS
581