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