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