1 /*
2  * Copyright (c) 2024 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 <vector>
17 #include <sstream>
18 #include "hitrace_meter.h"
19 #include "parameters.h"
20 #include "hilog_tag_wrapper.h"
21 #include "app_state_observer_manager.h"
22 #include "app_mgr_service_inner.h"
23 #include "cache_process_manager.h"
24 #include "res_sched_util.h"
25 #include "ui_extension_utils.h"
26 
27 namespace {
28 const std::string MAX_PROC_CACHE_NUM = "persist.sys.abilityms.maxProcessCacheNum";
29 const std::string RESOURCE_WARM_START_PROCESS_ENABLE = "persist.resourceschedule.enable_warm_start_process";
30 const std::string MAX_ALLOWED_CACHE_NUM = "const.resourceschedule.max_cached_process_nums";
31 const std::string PROCESS_CACHE_API_CHECK_CONFIG = "persist.sys.abilityms.processCacheApiCheck";
32 const std::string PROCESS_CACHE_SET_SUPPORT_CHECK_CONFIG = "persist.sys.abilityms.processCacheSetSupportCheck";
33 const std::string SHELL_ASSISTANT_BUNDLENAME = "com.huawei.shell_assistant";
34 constexpr int32_t API12 = 12;
35 constexpr int32_t API_VERSION_MOD = 100;
36 constexpr int32_t DEFAULT_ALLOWED_CACHE_NUM = 64;
37 }
38 
39 namespace OHOS {
40 namespace AppExecFwk {
41 
CacheProcessManager()42 CacheProcessManager::CacheProcessManager()
43 {
44     maxProcCacheNum_ = OHOS::system::GetIntParameter<int>(MAX_PROC_CACHE_NUM, 0);
45     shouldCheckApi = OHOS::system::GetBoolParameter(PROCESS_CACHE_API_CHECK_CONFIG, true);
46     shouldCheckSupport = OHOS::system::GetBoolParameter(PROCESS_CACHE_SET_SUPPORT_CHECK_CONFIG, true);
47     warmStartProcesEnable_ = OHOS::system::GetBoolParameter(RESOURCE_WARM_START_PROCESS_ENABLE, false);
48     allowedCacheNum_ = OHOS::system::GetIntParameter<int>(MAX_ALLOWED_CACHE_NUM, DEFAULT_ALLOWED_CACHE_NUM);
49     if (maxProcCacheNum_ > 0) {
50         allowedCacheNum_ = maxProcCacheNum_;
51     }
52     TAG_LOGW(AAFwkTag::APPMGR,
53         "maxProcCacheNum_ %{public}d, allowedCacheNum_ %{public}d", maxProcCacheNum_, allowedCacheNum_);
54 }
55 
~CacheProcessManager()56 CacheProcessManager::~CacheProcessManager()
57 {
58 }
59 
SetAppMgr(const std::weak_ptr<AppMgrServiceInner> & appMgr)60 void CacheProcessManager::SetAppMgr(const std::weak_ptr<AppMgrServiceInner> &appMgr)
61 {
62     TAG_LOGD(AAFwkTag::APPMGR, "Called");
63     appMgr_ = appMgr;
64 }
65 
RefreshCacheNum()66 void CacheProcessManager::RefreshCacheNum()
67 {
68     maxProcCacheNum_ = OHOS::system::GetIntParameter<int>(MAX_PROC_CACHE_NUM, 0);
69     allowedCacheNum_ = maxProcCacheNum_;
70     TAG_LOGW(AAFwkTag::APPMGR, "maxProcCacheNum %{public}d", maxProcCacheNum_);
71 }
72 
QueryEnableProcessCache()73 bool CacheProcessManager::QueryEnableProcessCache()
74 {
75     return maxProcCacheNum_ > 0 || warmStartProcesEnable_;
76 }
77 
PenddingCacheProcess(const std::shared_ptr<AppRunningRecord> & appRecord)78 bool CacheProcessManager::PenddingCacheProcess(const std::shared_ptr<AppRunningRecord> &appRecord)
79 {
80     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
81     TAG_LOGD(AAFwkTag::APPMGR, "Called");
82     if (!QueryEnableProcessCache()) {
83         return false;
84     }
85     if (appRecord == nullptr) {
86         TAG_LOGE(AAFwkTag::APPMGR, "nullptr precheck failed");
87         return false;
88     }
89     if (IsCachedProcess(appRecord)) {
90         return false;
91     }
92     if (appRecord->IsKeepAliveApp()) {
93         TAG_LOGW(AAFwkTag::APPMGR, "Not cache keepalive process");
94         return false;
95     }
96     {
97         std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
98         cachedAppRecordQueue_.push_back(appRecord);
99         AddToApplicationSet(appRecord);
100         if (warmStartProcesEnable_) {
101             appRecord->SetProcessCaching(true);
102         }
103     }
104     ShrinkAndKillCache();
105     TAG_LOGI(AAFwkTag::APPMGR, "Pending %{public}s success, %{public}s", appRecord->GetName().c_str(),
106         PrintCacheQueue().c_str());
107     return true;
108 }
109 
CheckAndCacheProcess(const std::shared_ptr<AppRunningRecord> & appRecord)110 bool CacheProcessManager::CheckAndCacheProcess(const std::shared_ptr<AppRunningRecord> &appRecord)
111 {
112     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
113     TAG_LOGD(AAFwkTag::APPMGR, "Called");
114     if (!QueryEnableProcessCache()) {
115         return false;
116     }
117     if (appRecord == nullptr) {
118         TAG_LOGE(AAFwkTag::APPMGR, "appRecord nullptr precheck failed");
119         return false;
120     }
121     if (!IsCachedProcess(appRecord)) {
122         return false;
123     }
124     if (!IsAppAbilitiesEmpty(appRecord)) {
125         TAG_LOGD(AAFwkTag::APPMGR, "%{public}s not cache for abilities not empty",
126             appRecord->GetName().c_str());
127         return true;
128     }
129     if (!warmStartProcesEnable_) {
130         appRecord->ScheduleCacheProcess();
131     }
132     appRecord->SetProcessCaching(false);
133     auto notifyCached = [appRecord]() {
134         DelayedSingleton<CacheProcessManager>::GetInstance()->CheckAndNotifyCachedState(appRecord);
135     };
136     std::string taskName = "DELAY_CACHED_STATE_NOTIFY";
137     if (appRecord->GetPriorityObject()) {
138         taskName += std::to_string(appRecord->GetPriorityObject()->GetPid());
139     }
140     auto res = appRecord->CancelTask(taskName);
141     if (res) {
142         TAG_LOGD(AAFwkTag::APPMGR, "Early delay task canceled.");
143     }
144     appRecord->PostTask(taskName, AMSEventHandler::DELAY_NOTIFY_PROCESS_CACHED_STATE, notifyCached);
145     return true;
146 }
147 
CheckAndNotifyCachedState(const std::shared_ptr<AppRunningRecord> & appRecord)148 bool CacheProcessManager::CheckAndNotifyCachedState(const std::shared_ptr<AppRunningRecord> &appRecord)
149 {
150     if (appRecord == nullptr) {
151         TAG_LOGE(AAFwkTag::APPMGR, "appRecord nullptr precheck failed");
152         return false;
153     }
154     auto appMgrSptr = appMgr_.lock();
155     if (appMgrSptr == nullptr) {
156         TAG_LOGE(AAFwkTag::APPMGR, "appMgr is nullptr");
157         return false;
158     }
159     auto &bundleName = appRecord->GetBundleName();
160     auto uid = appRecord->GetUid();
161     std::shared_ptr<AppRunningRecord> notifyRecord = nullptr;
162     {
163         std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
164         if (sameAppSet.find(bundleName) == sameAppSet.end() ||
165             sameAppSet[bundleName].find(uid) == sameAppSet[bundleName].end()) {
166             TAG_LOGD(AAFwkTag::APPMGR, "app set not found.");
167             return false;
168         }
169         if (sameAppSet[bundleName][uid].size() == 0) {
170             return false;
171         }
172         if (!appMgrSptr->IsAppProcessesAllCached(bundleName, uid, sameAppSet[bundleName][uid])) {
173             TAG_LOGI(AAFwkTag::APPMGR, "Not all processes of one app is cached, abort notify");
174             return false;
175         }
176         notifyRecord = *(sameAppSet[bundleName][uid].begin());
177     }
178     appRecord->SetProcessCaching(false);
179     appMgrSptr->OnAppCacheStateChanged(notifyRecord, ApplicationState::APP_STATE_CACHED);
180     TAG_LOGI(AAFwkTag::APPMGR, "app cached state is notified: %{public}s, uid:%{public}d", bundleName.c_str(), uid);
181     return true;
182 }
183 
IsCachedProcess(const std::shared_ptr<AppRunningRecord> & appRecord)184 bool CacheProcessManager::IsCachedProcess(const std::shared_ptr<AppRunningRecord> &appRecord)
185 {
186     if (appRecord == nullptr) {
187         TAG_LOGI(AAFwkTag::APPMGR, "appRecord nullptr precheck failed");
188         return false;
189     }
190     std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
191     for (auto& tmpAppRecord : cachedAppRecordQueue_) {
192         if (tmpAppRecord == appRecord) {
193             return true;
194         }
195     }
196     return false;
197 }
198 
OnProcessKilled(const std::shared_ptr<AppRunningRecord> & appRecord)199 void CacheProcessManager::OnProcessKilled(const std::shared_ptr<AppRunningRecord> &appRecord)
200 {
201     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
202     if (!QueryEnableProcessCache()) {
203         return;
204     }
205     if (appRecord == nullptr) {
206         TAG_LOGE(AAFwkTag::APPMGR, "appRecord nullptr precheck failed");
207         return;
208     }
209     CheckAndNotifyCachedState(appRecord);
210     {
211         std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
212         srvExtRecords.erase(appRecord);
213         srvExtCheckedFlag.erase(appRecord);
214     }
215     if (!IsCachedProcess(appRecord)) {
216         return;
217     }
218     RemoveCacheRecord(appRecord);
219     TAG_LOGI(AAFwkTag::APPMGR, "%{public}s is killed, %{public}s", appRecord->GetName().c_str(),
220         PrintCacheQueue().c_str());
221 }
222 
ReuseCachedProcess(const std::shared_ptr<AppRunningRecord> & appRecord)223 void CacheProcessManager::ReuseCachedProcess(const std::shared_ptr<AppRunningRecord> &appRecord)
224 {
225     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
226     if (!QueryEnableProcessCache()) {
227         return;
228     }
229     if (appRecord == nullptr) {
230         TAG_LOGE(AAFwkTag::APPMGR, "appRecord nullptr precheck failed");
231         return;
232     }
233     if (!IsCachedProcess(appRecord)) {
234         return;
235     }
236     RemoveCacheRecord(appRecord);
237     auto appMgrSptr = appMgr_.lock();
238     if (appMgrSptr == nullptr) {
239         TAG_LOGE(AAFwkTag::APPMGR, "appMgr is nullptr");
240         return;
241     }
242     if (AAFwk::UIExtensionUtils::IsUIExtension(appRecord->GetExtensionType())) {
243         if (appRecord->GetEnableProcessCache()) {
244             appRecord->SetEnableProcessCache(false);
245         }
246     }
247     appMgrSptr->OnAppCacheStateChanged(appRecord, ApplicationState::APP_STATE_READY);
248     TAG_LOGI(AAFwkTag::APPMGR, "app none cached state is notified: %{public}s, uid: %{public}d, %{public}s",
249         appRecord->GetBundleName().c_str(), appRecord->GetUid(), PrintCacheQueue().c_str());
250 }
251 
IsProcessSupportHotStart(const std::shared_ptr<AppRunningRecord> & appRecord)252 bool CacheProcessManager::IsProcessSupportHotStart(const std::shared_ptr<AppRunningRecord> &appRecord)
253 {
254     if (appRecord == nullptr) {
255         return false;
256     }
257     auto appInfo = appRecord->GetApplicationInfo();
258     if (appInfo == nullptr) {
259         TAG_LOGD(AAFwkTag::APPMGR, "appinfo nullptr");
260         return false;
261     }
262     auto actualVer = appInfo->apiTargetVersion % API_VERSION_MOD;
263     if (shouldCheckApi && actualVer < API12) {
264         TAG_LOGD(AAFwkTag::APPMGR, "App %{public}s 's apiTargetVersion has %{public}d, smaller than 12",
265             appRecord->GetName().c_str(), actualVer);
266         return false;
267     }
268     if (IsAppContainsSrvExt(appRecord)) {
269         TAG_LOGD(AAFwkTag::APPMGR, "%{public}s of %{public}s is service, not support cache.",
270             appRecord->GetProcessName().c_str(), appRecord->GetBundleName().c_str());
271         return false;
272     }
273     if (!appRecord->HasUIAbilityLaunched()) {
274         TAG_LOGD(AAFwkTag::APPMGR, "%{public}s of %{public}s has not created uiability before",
275             appRecord->GetProcessName().c_str(), appRecord->GetBundleName().c_str());
276     }
277     return true;
278 }
279 
CheckAndSetProcessCacheEnable(const std::shared_ptr<AppRunningRecord> & appRecord)280 void CacheProcessManager::CheckAndSetProcessCacheEnable(const std::shared_ptr<AppRunningRecord> &appRecord)
281 {
282     if (appRecord == nullptr || !warmStartProcesEnable_) {
283         return;
284     }
285     if (appRecord->GetSupportProcessCacheState() != SupportProcessCacheState::SUPPORT) {
286         return;
287     }
288     if (!appRecord->GetPriorityObject()) {
289         return;
290     }
291     bool forceKillProcess =
292         AAFwk::ResSchedUtil::GetInstance().CheckShouldForceKillProcess(appRecord->GetPriorityObject()->GetPid());
293     if (forceKillProcess) {
294         appRecord->SetProcessCacheBlocked(true);
295         return;
296     }
297 }
298 
IsAppSupportProcessCache(const std::shared_ptr<AppRunningRecord> & appRecord)299 bool CacheProcessManager::IsAppSupportProcessCache(const std::shared_ptr<AppRunningRecord> &appRecord)
300 {
301     if (appRecord == nullptr) {
302         TAG_LOGI(AAFwkTag::APPMGR, "precheck failed");
303         return false;
304     }
305     if (appRecord->IsAttachedToStatusBar()) {
306         TAG_LOGD(AAFwkTag::APPMGR, "%{public}s of %{public}s is attached to statusbar, not support cache",
307             appRecord->GetProcessName().c_str(), appRecord->GetBundleName().c_str());
308         return false;
309     }
310     if (appRecord->IsKeepAliveApp()) {
311         TAG_LOGD(AAFwkTag::APPMGR, "Keepalive app.");
312         return false;
313     }
314     if (appRecord->GetParentAppRecord() != nullptr) {
315         TAG_LOGD(AAFwkTag::APPMGR, "Child App, not support.");
316         return false;
317     }
318     if (maxProcCacheNum_ > 0 && !IsProcessSupportHotStart(appRecord)) {
319         return false;
320     }
321     return IsAppSupportProcessCacheInnerFirst(appRecord);
322 }
323 
IsAppSupportProcessCacheInnerFirst(const std::shared_ptr<AppRunningRecord> & appRecord)324 bool CacheProcessManager::IsAppSupportProcessCacheInnerFirst(const std::shared_ptr<AppRunningRecord> &appRecord)
325 {
326     if (appRecord == nullptr) {
327         TAG_LOGI(AAFwkTag::APPMGR, "appRecord nullptr precheck failed");
328         return false;
329     }
330     if (appRecord->GetBundleName() == SHELL_ASSISTANT_BUNDLENAME) {
331         TAG_LOGD(AAFwkTag::APPMGR, "shell assistant, not support.");
332         return false;
333     }
334     if (appRecord->GetProcessCacheBlocked()) {
335         TAG_LOGD(AAFwkTag::APPMGR, "%{public}s of %{public}s 's process cache temporarily blocked.",
336             appRecord->GetProcessName().c_str(), appRecord->GetBundleName().c_str());
337         return false;
338     }
339     if (warmStartProcesEnable_) {
340         if (!appRecord->HasUIAbilityLaunched() &&
341             !AAFwk::UIExtensionUtils::IsUIExtension(appRecord->GetExtensionType())) {
342             return false;
343         }
344     }
345 
346     auto supportState = appRecord->GetSupportProcessCacheState();
347     switch (supportState) {
348         case SupportProcessCacheState::UNSPECIFIED:
349             TAG_LOGD(AAFwkTag::APPMGR, "App %{public}s has not defined support state.",
350                 appRecord->GetBundleName().c_str());
351             return shouldCheckSupport ? false : true;
352         case SupportProcessCacheState::SUPPORT:
353             return true;
354         case SupportProcessCacheState::NOT_SUPPORT:
355             TAG_LOGD(AAFwkTag::APPMGR, "App %{public}s defines not support.",
356                 appRecord->GetBundleName().c_str());
357             return false;
358         default:
359             TAG_LOGD(AAFwkTag::APPMGR, "Invalid support state.");
360             return false;
361     }
362 }
363 
IsAppShouldCache(const std::shared_ptr<AppRunningRecord> & appRecord)364 bool CacheProcessManager::IsAppShouldCache(const std::shared_ptr<AppRunningRecord> &appRecord)
365 {
366     if (appRecord == nullptr) {
367         return false;
368     }
369     if (!QueryEnableProcessCache()) {
370         return false;
371     }
372     if (IsCachedProcess(appRecord) && !appRecord->GetProcessCacheBlocked()) {
373         return true;
374     }
375     if (!IsAppSupportProcessCache(appRecord)) {
376         return false;
377     }
378     return true;
379 }
380 
IsAppAbilitiesEmpty(const std::shared_ptr<AppRunningRecord> & appRecord)381 bool CacheProcessManager::IsAppAbilitiesEmpty(const std::shared_ptr<AppRunningRecord> &appRecord)
382 {
383     if (appRecord == nullptr) {
384         TAG_LOGI(AAFwkTag::APPMGR, "appRecord nullptr precheck failed");
385         return false;
386     }
387     auto allModuleRecord = appRecord->GetAllModuleRecord();
388     for (auto moduleRecord : allModuleRecord) {
389         if (moduleRecord != nullptr && !moduleRecord->GetAbilities().empty()) {
390             return false;
391         }
392     }
393     TAG_LOGD(AAFwkTag::APPMGR, "abilities all empty: %{public}s",
394         appRecord->GetName().c_str());
395     return true;
396 }
397 
GetCurrentCachedProcNum()398 int CacheProcessManager::GetCurrentCachedProcNum()
399 {
400     std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
401     return static_cast<int>(cachedAppRecordQueue_.size());
402 }
403 
RemoveCacheRecord(const std::shared_ptr<AppRunningRecord> & appRecord)404 void CacheProcessManager::RemoveCacheRecord(const std::shared_ptr<AppRunningRecord> &appRecord)
405 {
406     std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
407     for (auto it = cachedAppRecordQueue_.begin(); it != cachedAppRecordQueue_.end();) {
408         if (appRecord == *it) {
409             RemoveFromApplicationSet(*it);
410             it = cachedAppRecordQueue_.erase(it);
411         } else {
412             it++;
413         }
414     }
415 }
416 
ShrinkAndKillCache()417 void CacheProcessManager::ShrinkAndKillCache()
418 {
419     TAG_LOGD(AAFwkTag::APPMGR, "Called");
420     if (maxProcCacheNum_ <= 0 && !warmStartProcesEnable_) {
421         TAG_LOGI(AAFwkTag::APPMGR, "Cache disabled.");
422         return;
423     }
424     std::vector<std::shared_ptr<AppRunningRecord>> cleanList;
425     {
426         std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
427         while (GetCurrentCachedProcNum() > allowedCacheNum_) {
428             const auto& tmpAppRecord = cachedAppRecordQueue_.front();
429             cachedAppRecordQueue_.pop_front();
430             RemoveFromApplicationSet(tmpAppRecord);
431             if (tmpAppRecord == nullptr) {
432                 continue;
433             }
434             cleanList.push_back(tmpAppRecord);
435             TAG_LOGI(AAFwkTag::APPMGR, "need clean record %{public}s, current =%{public}d",
436                 tmpAppRecord->GetName().c_str(), GetCurrentCachedProcNum());
437         }
438     }
439     for (auto& tmpAppRecord : cleanList) {
440         KillProcessByRecord(tmpAppRecord);
441     }
442 }
443 
KillProcessByRecord(const std::shared_ptr<AppRunningRecord> & appRecord)444 bool CacheProcessManager::KillProcessByRecord(const std::shared_ptr<AppRunningRecord> &appRecord)
445 {
446     if (appRecord == nullptr) {
447         TAG_LOGW(AAFwkTag::APPMGR, "appRecord nullptr precheck failed");
448         return false;
449     }
450     auto appMgrSptr = appMgr_.lock();
451     if (appMgrSptr == nullptr) {
452         TAG_LOGE(AAFwkTag::APPMGR, "appMgr is nullptr");
453         return false;
454     }
455     appRecord->SetProcessCaching(false);
456     // notify before kill
457     appMgrSptr->OnAppCacheStateChanged(appRecord, ApplicationState::APP_STATE_READY);
458     // this uses ScheduleProcessSecurityExit
459     appMgrSptr->KillApplicationByRecord(appRecord);
460     return true;
461 }
462 
PrintCacheQueue()463 std::string CacheProcessManager::PrintCacheQueue()
464 {
465     std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
466     std::stringstream ss;
467     ss << "queue size: " << cachedAppRecordQueue_.size() << ", record in queue: ";
468     for (auto& record : cachedAppRecordQueue_) {
469         if (record == nullptr) {
470             ss << "null, ";
471         } else {
472             ss << record->GetName() << ", ";
473         }
474     }
475     ss << ".";
476     return ss.str();
477 }
478 
AddToApplicationSet(const std::shared_ptr<AppRunningRecord> & appRecord)479 void CacheProcessManager::AddToApplicationSet(const std::shared_ptr<AppRunningRecord> &appRecord)
480 {
481     if (appRecord == nullptr) {
482         return;
483     }
484     auto &bundleName = appRecord->GetBundleName();
485     std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
486     if (sameAppSet.find(bundleName) == sameAppSet.end()) {
487         std::map<int32_t, std::set<std::shared_ptr<AppRunningRecord>>> uidMap;
488         std::set<std::shared_ptr<AppRunningRecord>> recordSet;
489         recordSet.insert(appRecord);
490         uidMap.insert(std::make_pair(appRecord->GetUid(), recordSet));
491         sameAppSet.insert(std::make_pair(bundleName, uidMap));
492     }
493     auto uid = appRecord->GetUid();
494     if (sameAppSet[bundleName].find(uid) == sameAppSet[bundleName].end()) {
495         std::set<std::shared_ptr<AppRunningRecord>> recordSet;
496         recordSet.insert(appRecord);
497         sameAppSet[bundleName].insert(std::make_pair(uid, recordSet));
498         return;
499     }
500     sameAppSet[bundleName][uid].insert(appRecord);
501 }
502 
RemoveFromApplicationSet(const std::shared_ptr<AppRunningRecord> & appRecord)503 void CacheProcessManager::RemoveFromApplicationSet(const std::shared_ptr<AppRunningRecord> &appRecord)
504 {
505     if (appRecord == nullptr) {
506         return;
507     }
508     auto &bundleName = appRecord->GetBundleName();
509     std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
510     if (sameAppSet.find(bundleName) == sameAppSet.end()) {
511         return;
512     }
513     auto uid = appRecord->GetUid();
514     if (sameAppSet[bundleName].find(uid) == sameAppSet[bundleName].end()) {
515         return;
516     }
517     sameAppSet[bundleName][uid].erase(appRecord);
518     if (sameAppSet[bundleName][uid].size() == 0) {
519         sameAppSet[bundleName].erase(uid);
520     }
521     if (sameAppSet[bundleName].size() == 0) {
522         sameAppSet.erase(bundleName);
523     }
524 }
525 
PrepareActivateCache(const std::shared_ptr<AppRunningRecord> & appRecord)526 void CacheProcessManager::PrepareActivateCache(const std::shared_ptr<AppRunningRecord> &appRecord)
527 {
528     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
529     if (!QueryEnableProcessCache()) {
530         return;
531     }
532     if (appRecord == nullptr) {
533         return;
534     }
535     if (!IsCachedProcess(appRecord)) {
536         return;
537     }
538     TAG_LOGD(AAFwkTag::APPMGR, "%{public}s needs activate.", appRecord->GetBundleName().c_str());
539     auto appMgrSptr = appMgr_.lock();
540     if (appMgrSptr == nullptr) {
541         TAG_LOGE(AAFwkTag::APPMGR, "appMgr is nullptr");
542         return;
543     }
544     appMgrSptr->OnAppCacheStateChanged(appRecord, ApplicationState::APP_STATE_READY);
545 }
546 
IsAppContainsSrvExt(const std::shared_ptr<AppRunningRecord> & appRecord)547 bool CacheProcessManager::IsAppContainsSrvExt(const std::shared_ptr<AppRunningRecord> &appRecord)
548 {
549     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
550     std::lock_guard<ffrt::recursive_mutex> queueLock(cacheQueueMtx);
551     if (appRecord == nullptr) {
552         return false;
553     }
554     if (srvExtCheckedFlag.find(appRecord) != srvExtCheckedFlag.end()) {
555         return srvExtRecords.find(appRecord) != srvExtRecords.end() ? true : false;
556     }
557     auto allModuleRecord = appRecord->GetAllModuleRecord();
558     for (auto moduleRecord : allModuleRecord) {
559         if (moduleRecord == nullptr) {
560             continue;
561         }
562         HapModuleInfo hapModuleInfo;
563         moduleRecord->GetHapModuleInfo(hapModuleInfo);
564         for (auto abilityInfo : hapModuleInfo.abilityInfos) {
565             if (abilityInfo.type == AppExecFwk::AbilityType::EXTENSION &&
566                 abilityInfo.extensionAbilityType == AppExecFwk::ExtensionAbilityType::SERVICE) {
567                     srvExtRecords.insert(appRecord);
568                 TAG_LOGD(AAFwkTag::APPMGR, "%{public}s of %{public}s is service, will not cache",
569                     abilityInfo.name.c_str(), appRecord->GetBundleName().c_str());
570             }
571         }
572         for (auto extAbilityInfo : hapModuleInfo.extensionInfos) {
573             if (extAbilityInfo.type == AppExecFwk::ExtensionAbilityType::SERVICE) {
574                 srvExtRecords.insert(appRecord);
575                 TAG_LOGD(AAFwkTag::APPMGR, "%{public}s of %{public}s is service, will not cache",
576                     extAbilityInfo.name.c_str(), appRecord->GetBundleName().c_str());
577             }
578         }
579     }
580     srvExtCheckedFlag.insert(appRecord);
581     return srvExtRecords.find(appRecord) != srvExtRecords.end() ? true : false;
582 }
583 
OnAppProcessCacheBlocked(const std::shared_ptr<AppRunningRecord> & appRecord)584 void CacheProcessManager::OnAppProcessCacheBlocked(const std::shared_ptr<AppRunningRecord> &appRecord)
585 {
586     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
587     if (!QueryEnableProcessCache()) {
588         return;
589     }
590     if (appRecord == nullptr || !IsCachedProcess(appRecord)) {
591         return;
592     }
593     TAG_LOGI(AAFwkTag::APPMGR, "%{public}s is cached and is blocked, which needs exit.",
594         appRecord->GetBundleName().c_str());
595     RemoveCacheRecord(appRecord);
596     KillProcessByRecord(appRecord);
597 }
598 } // namespace OHOS
599 } // namespace AppExecFwk