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