• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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