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