1 /*
2 * Copyright (c) 2022-2023 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 "reclaim_priority_manager.h"
17
18 #include "app_mgr_interface.h"
19 #include "bundle_mgr_proxy.h"
20 #include "iservice_registry.h"
21 #include "kernel_interface.h"
22 #include "memmgr_log.h"
23 #include "memmgr_ptr_util.h"
24 #include "multi_account_manager.h"
25 #include "oom_score_adj_utils.h"
26 #include "reclaim_priority_constants.h"
27 #include "reclaim_strategy_manager.h"
28 #include "render_process_info.h"
29 #include "singleton.h"
30 #include "system_ability_definition.h"
31
32 namespace OHOS {
33 namespace Memory {
34 namespace {
35 const std::string TAG = "ReclaimPriorityManager";
36 constexpr int TIMER_DIED_PROC_FAST_CHECK_MS = 10000;
37 constexpr int TIMER_DIED_PROC_SLOW_CHECK_MS = 3 * 60 * 1000; // 3min
38 constexpr int MAX_TOTALBUNDLESET_SIZE = 2000;
39
40 constexpr int TIMER_ABILITY_START_CHECK_MS = 10 * 1000; // 10s
41 }
42 IMPLEMENT_SINGLE_INSTANCE(ReclaimPriorityManager);
43
ReclaimPriorityManager()44 ReclaimPriorityManager::ReclaimPriorityManager()
45 {
46 InitUpdateReasonStrMapping();
47 InitChangeProcMapping();
48 }
49
InitUpdateReasonStrMapping()50 void ReclaimPriorityManager::InitUpdateReasonStrMapping()
51 {
52 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::CREATE_PROCESS)] = "CREATE_PROCESS";
53 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::PROCESS_READY)] = "PROCESS_READY";
54 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::FOREGROUND)] = "FOREGROUND";
55 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::BACKGROUND)] = "BACKGROUND";
56 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::SUSPEND_DELAY_START)] = "SUSPEND_DELAY_START";
57 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::SUSPEND_DELAY_END)] = "SUSPEND_DELAY_END";
58 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::BACKGROUND_RUNNING_START)] =
59 "BACKGROUND_RUNNING_START";
60 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::BACKGROUND_RUNNING_END)] =
61 "BACKGROUND_RUNNING_END";
62 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::EVENT_START)] = "EVENT_START";
63 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::EVENT_END)] = "EVENT_END";
64 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::APPLICATION_SUSPEND)] = "APPLICATION_SUSPEND";
65 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::PROCESS_TERMINATED)] = "PROCESS_TERMINATED";
66 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::OS_ACCOUNT_CHANGED)] = "OS_ACCOUNT_CHANGED";
67 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::DIST_DEVICE_CONNECTED)] =
68 "DIST_DEVICE_CONNECTED";
69 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::DIST_DEVICE_DISCONNECTED)] =
70 "DIST_DEVICE_DISCONNECTED";
71 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::BIND_EXTENSION)] = "BIND_EXTENSION";
72 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::UNBIND_EXTENSION)] = "UNBIND_EXTENSION";
73 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::RENDER_CREATE_PROCESS)] =
74 "RENDER_CREATE_PROCESS";
75 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::VISIBLE)] = "VISIBLE";
76 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::UN_VISIBLE)] = "UN_VISIBLE";
77 updateReasonStrMapping_[static_cast<int32_t>(AppStateUpdateReason::ABILITY_START)] = "ABILITY_START";
78 }
79
AppStateUpdateResonToString(AppStateUpdateReason reason)80 std::string& ReclaimPriorityManager::AppStateUpdateResonToString(AppStateUpdateReason reason)
81 {
82 auto ptr = updateReasonStrMapping_.find(static_cast<int32_t>(reason));
83 if (ptr != updateReasonStrMapping_.end()) {
84 return ptr->second;
85 } else {
86 return UNKOWN_REASON;
87 }
88 }
89
Init()90 bool ReclaimPriorityManager::Init()
91 {
92 config_ = MemmgrConfigManager::GetInstance().GetReclaimPriorityConfig();
93 initialized_ = GetEventHandler();
94 GetAllKillableSystemApps();
95 if (initialized_) {
96 HILOGI("init successed");
97 } else {
98 HILOGE("init failed");
99 }
100 SetTimerForDiedProcessCheck(TIMER_DIED_PROC_SLOW_CHECK_MS);
101 return initialized_;
102 }
103
GetEventHandler()104 bool ReclaimPriorityManager::GetEventHandler()
105 {
106 if (!handler_) {
107 MAKE_POINTER(handler_, shared, AppExecFwk::EventHandler, "failed to create event handler", return false,
108 AppExecFwk::EventRunner::Create());
109 }
110 return true;
111 }
112
Dump(int fd)113 void ReclaimPriorityManager::Dump(int fd)
114 {
115 // add lock
116 std::lock_guard<std::mutex> setLock(totalBundlePrioSetLock_);
117
118 dprintf(fd, "priority list of all managed apps\n");
119 dprintf(fd, " uid name priority\n");
120 for (auto bundlePtr : totalBundlePrioSet_) {
121 if (bundlePtr == nullptr) {
122 dprintf(fd, "bundlePtr is nullptr.\n");
123 continue;
124 }
125 dprintf(fd, "%8d %42s %5d %3d\n", bundlePtr->uid_, bundlePtr->name_.c_str(), bundlePtr->priority_,
126 bundlePtr->GetProcsCount());
127 }
128 dprintf(fd, "-----------------------------------------------------------------\n\n");
129
130 dprintf(fd, "priority list of all managed processes, status:(fg,visible,bgtask,trantask,evt,dist,extb,ext,"
131 "render,startAbility)\n");
132 dprintf(fd, " pid uid bundle priority status\
133 connnectorpids connnectoruids processuids\n");
134 for (auto bundlePtr : totalBundlePrioSet_) {
135 dprintf(fd, "|-----------------------------------------\n");
136 if (bundlePtr == nullptr) {
137 dprintf(fd, "bundlePtr is nullptr.\n");
138 continue;
139 }
140 for (auto procEntry : bundlePtr->procs_) {
141 ProcessPriorityInfo &proc = procEntry.second;
142 dprintf(fd, "|%8d %8d %42s %5d %d%d%d%d%d%d%d%d%d%d %30s\n",
143 proc.pid_, bundlePtr->uid_, bundlePtr->name_.c_str(),
144 proc.priority_, proc.isFreground, proc.isVisible_, proc.isBackgroundRunning,
145 proc.isSuspendDelay, proc.isEventStart, proc.isDistDeviceConnected,
146 proc.extensionBindStatus, proc.isExtension_, proc.isRender_,
147 proc.IsAbilityStarting(), proc.ProcsBindToMe().c_str());
148 }
149 }
150 dprintf(fd, "-----------------------------------------------------------------\n");
151 }
152
GetAppMgrProxy()153 sptr<AppExecFwk::IAppMgr> GetAppMgrProxy()
154 {
155 auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
156 auto appObject = systemAbilityManager->GetSystemAbility(APP_MGR_SERVICE_ID);
157 return iface_cast<AppExecFwk::IAppMgr>(appObject);
158 }
159
IsFrontApp(const std::string & pkgName,int32_t uid,int32_t pid)160 bool ReclaimPriorityManager::IsFrontApp(const std::string& pkgName, int32_t uid, int32_t pid)
161 {
162 sptr<AppExecFwk::IAppMgr> appMgrProxy_ = GetAppMgrProxy();
163 if (!appMgrProxy_) {
164 HILOGE("GetAppMgrProxy failed");
165 return false;
166 }
167 std::vector<AppExecFwk::AppStateData> fgAppList;
168 if (appMgrProxy_->GetForegroundApplications(fgAppList) != 0) {
169 HILOGE("GetForegroundApplications failed");
170 return false;
171 }
172 for (auto fgApp : fgAppList) {
173 if (fgApp.bundleName == pkgName && fgApp.uid == uid) {
174 return true;
175 }
176 }
177 return false;
178 }
179
GetAllKillableSystemApps()180 void ReclaimPriorityManager::GetAllKillableSystemApps()
181 {
182 HILOGI("called");
183 // get killable system apps from xml
184 allKillableSystemApps_.merge(config_.GetkillalbeSystemApps());
185 // get killable system apps from fwk (finally from bms)
186 std::set<std::string> killableSystemAppsFromAms_;
187 GetKillableSystemAppsFromAms(killableSystemAppsFromAms_);
188 allKillableSystemApps_.merge(killableSystemAppsFromAms_);
189 }
190
GetKillableSystemAppsFromAms(std::set<std::string> & killableApps)191 void ReclaimPriorityManager::GetKillableSystemAppsFromAms(std::set<std::string> &killableApps)
192 {
193 // get killable system apps from fwk (finally from bms)
194 }
195
196 // if user install new killable system apps, fwk should tell me by calling this interface.
197 // if user uninstall some killable system apps, we can do nothing since killable info will be updated on next rebooting.
NotifyKillableSystemAppsAdded(std::set<std::string> & newKillableApps)198 void ReclaimPriorityManager::NotifyKillableSystemAppsAdded(std::set<std::string> &newKillableApps)
199 {
200 allKillableSystemApps_.merge(newKillableApps);
201 }
202
203 // handle process started before our service
HandlePreStartedProcs()204 void ReclaimPriorityManager::HandlePreStartedProcs()
205 {
206 std::vector<unsigned int> preStartedPids;
207 KernelInterface::GetInstance().GetAllProcPids(preStartedPids);
208 for (unsigned int pid : preStartedPids) {
209 unsigned int uid = 0;
210 if (!KernelInterface::GetInstance().GetUidByPid(pid, uid)) {
211 HILOGE("process[pid=%{public}d] started before me, but GetUidByPid failed.", pid);
212 continue;
213 }
214 struct ProcInfo procInfo;
215 std::string name;
216 if (!KernelInterface::GetInstance().GetProcNameByPid(pid, name)) {
217 HILOGE("process[pid=%{public}d, uid=%{public}d] started before me, but GetProcNameByPid failed.", pid, uid);
218 continue;
219 }
220 if (allKillableSystemApps_.find(name) != allKillableSystemApps_.end()) {
221 OomScoreAdjUtils::WriteOomScoreAdjToKernel(pid, RECLAIM_PRIORITY_KILLABLE_SYSTEM);
222 HILOGI("process[pid=%{public}d, uid=%{public}d, name=%{public}s] started before me, killable = %{public}d",
223 pid, uid, name.c_str(), true);
224 }
225 }
226 }
227
GetBundlePrioSet(BunldeCopySet & bundleSet)228 void ReclaimPriorityManager::GetBundlePrioSet(BunldeCopySet &bundleSet)
229 {
230 // add lock
231 std::lock_guard<std::mutex> setLock(totalBundlePrioSetLock_);
232
233 HILOGD("iter %{public}zu bundles begin", totalBundlePrioSet_.size());
234 int count = 0;
235 for (auto itrBundle = totalBundlePrioSet_.rbegin(); itrBundle != totalBundlePrioSet_.rend(); ++itrBundle, ++count) {
236 std::shared_ptr<BundlePriorityInfo> bundle = *itrBundle;
237 if (bundle == nullptr) {
238 HILOGD("bundle %{public}d/%{public}zu is nullptr", count, totalBundlePrioSet_.size());
239 continue;
240 }
241
242 HILOGD("bundle %{public}d/%{public}zu, uid=%{publics}d", count, totalBundlePrioSet_.size(), bundle->uid_);
243 BundlePriorityInfo tmpBundleInfo(bundle->name_, bundle->uid_, bundle->priority_,
244 bundle->accountId_, bundle->state_);
245
246 for (auto itrProcess = bundle->procs_.begin(); itrProcess != bundle->procs_.end(); itrProcess++) {
247 ProcessPriorityInfo processInfo = itrProcess->second;
248 ProcessPriorityInfo tmpProcess(processInfo);
249
250 tmpBundleInfo.procs_.insert(std::make_pair(tmpProcess.pid_, tmpProcess));
251 }
252
253 HILOGD("insert bundle [%{public}d][%{public}s] to set, priority=%{public}d",
254 tmpBundleInfo.uid_, tmpBundleInfo.name_.c_str(), tmpBundleInfo.priority_);
255 bundleSet.insert(tmpBundleInfo);
256 }
257 HILOGD("iter bundles end");
258 }
259
GetOneKillableBundle(int minPrio,BunldeCopySet & bundleSet)260 void ReclaimPriorityManager::GetOneKillableBundle(int minPrio, BunldeCopySet &bundleSet)
261 {
262 HILOGD("called, minPrio=%{public}d", minPrio);
263 // add lock
264 std::lock_guard<std::mutex> setLock(totalBundlePrioSetLock_);
265
266 HILOGD("iter %{public}zu bundles begin", totalBundlePrioSet_.size());
267 int count = 0;
268 for (auto itrBundle = totalBundlePrioSet_.rbegin(); itrBundle != totalBundlePrioSet_.rend(); ++itrBundle) {
269 std::shared_ptr<BundlePriorityInfo> bundle = *itrBundle;
270 if (bundle == nullptr) {
271 HILOGD("bundle %{public}d/%{public}zu is nullptr", count, totalBundlePrioSet_.size());
272 continue;
273 }
274 if (bundle->priority_ < minPrio) {
275 HILOGD("there is no bundle with priority bigger than %{public}d, break!", minPrio);
276 break;
277 }
278 if (bundle->GetState() == BundleState::STATE_WAITING_FOR_KILL) {
279 HILOGD("bundle<%{public}d, %{public}s}> is waiting to kill, skiped!", bundle->uid_, bundle->name_.c_str());
280 continue;
281 }
282
283 try {
284 auto ret = bundleSet.insert(*bundle);
285 if (ret.second) {
286 HILOGI("insert bundle<%{public}d, %{public}s}> to set, priority=%{public}d", bundle->uid_,
287 bundle->name_.c_str(), bundle->priority_);
288 ++count;
289 break;
290 }
291 } catch (...) {
292 HILOGE("new BundlePriorityInfo failed, need kill quickly!");
293 for (auto procEntry : bundle->procs_) {
294 HILOGE("quick killing bundle<%{public}d, %{public}s}>, pid=%{public}d", bundle->uid_,
295 bundle->name_.c_str(), procEntry.second.pid_);
296 KernelInterface::GetInstance().KillOneProcessByPid(procEntry.second.pid_);
297 }
298 }
299 }
300 HILOGD("iter bundles end");
301 }
302
SetBundleState(int accountId,int uid,BundleState state)303 void ReclaimPriorityManager::SetBundleState(int accountId, int uid, BundleState state)
304 {
305 std::lock_guard<std::mutex> setLock(totalBundlePrioSetLock_);
306 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
307 if (account != nullptr) {
308 auto pairPtr = account->bundleIdInfoMapping_.find(uid);
309 if (pairPtr != account->bundleIdInfoMapping_.end()) {
310 if (pairPtr->second != nullptr) {
311 auto bundlePtr = pairPtr->second;
312 bundlePtr->SetState(state);
313 }
314 }
315 }
316 }
317
IsOsAccountExist(int accountId)318 bool ReclaimPriorityManager::IsOsAccountExist(int accountId)
319 {
320 if (osAccountsInfoMap_.find(accountId) == osAccountsInfoMap_.end()) {
321 HILOGE("accountId not exist");
322 return false;
323 }
324 return true;
325 }
326
AddBundleInfoToSet(std::shared_ptr<BundlePriorityInfo> bundle)327 void ReclaimPriorityManager::AddBundleInfoToSet(std::shared_ptr<BundlePriorityInfo> bundle)
328 {
329 auto ret = totalBundlePrioSet_.insert(bundle);
330 if (ret.second) {
331 HILOGD("success to insert bundle to set, uid=%{public}d, totalBundlePrioSet_.size=%{public}zu",
332 bundle->uid_, totalBundlePrioSet_.size());
333 }
334 }
335
DeleteBundleInfoFromSet(std::shared_ptr<BundlePriorityInfo> bundle)336 void ReclaimPriorityManager::DeleteBundleInfoFromSet(std::shared_ptr<BundlePriorityInfo> bundle)
337 {
338 int delCount = totalBundlePrioSet_.erase(bundle);
339 HILOGD("delete %{public}d bundles from set, uid=%{public}d, totalBundlePrioSet_.size=%{public}zu",
340 delCount, bundle->uid_, totalBundlePrioSet_.size());
341 }
342
FindOsAccountById(int accountId)343 std::shared_ptr<AccountBundleInfo> ReclaimPriorityManager::FindOsAccountById(int accountId)
344 {
345 auto iter = osAccountsInfoMap_.find(accountId);
346 if (iter != osAccountsInfoMap_.end()) {
347 return iter->second;
348 }
349 HILOGI("not found the account info");
350 return nullptr;
351 }
352
RemoveOsAccountById(int accountId)353 void ReclaimPriorityManager::RemoveOsAccountById(int accountId)
354 {
355 // erase the accountId data
356 osAccountsInfoMap_.erase(accountId);
357 }
358
AddOsAccountInfo(std::shared_ptr<AccountBundleInfo> account)359 void ReclaimPriorityManager::AddOsAccountInfo(std::shared_ptr<AccountBundleInfo> account)
360 {
361 osAccountsInfoMap_.insert(std::make_pair(account->id_, account));
362 }
363
IsProcExist(pid_t pid,int bundleUid,int accountId)364 bool ReclaimPriorityManager::IsProcExist(pid_t pid, int bundleUid, int accountId)
365 {
366 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
367 if (account == nullptr || !account->HasBundle(bundleUid)) {
368 HILOGE("account or bundle name not exist");
369 return false;
370 }
371 std::shared_ptr<BundlePriorityInfo> bundle = account->FindBundleById(bundleUid);
372 if (bundle == nullptr) {
373 return false;
374 }
375 if (pid == IGNORE_PID) {
376 return true;
377 }
378 if (!bundle->HasProc(pid)) {
379 HILOGE("pid not exist");
380 return false;
381 }
382 return true;
383 }
384
UpdateReclaimPriority(UpdateRequest request)385 bool ReclaimPriorityManager::UpdateReclaimPriority(UpdateRequest request)
386 {
387 if (!initialized_) {
388 HILOGE("has not been initialized_, skiped!");
389 return false;
390 }
391 int64_t eventTime = KernelInterface::GetInstance().GetSystemTimeMs();
392 std::function<void()> updateReclaimPriorityInnerFunc =
393 [this, request, eventTime] { this->UpdateReclaimPriorityInner(request, eventTime); };
394 if (request.reason == AppStateUpdateReason::ABILITY_START) {
395 return handler_->PostTask(updateReclaimPriorityInnerFunc, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
396 } else {
397 return handler_->PostTask(updateReclaimPriorityInnerFunc, 0, AppExecFwk::EventQueue::Priority::HIGH);
398 }
399 }
400
UpdateRecalimPrioritySyncWithLock(const UpdateRequest & request)401 bool ReclaimPriorityManager::UpdateRecalimPrioritySyncWithLock(const UpdateRequest &request)
402 {
403 if (!initialized_) {
404 HILOGE("has not been initialized_, skiped!");
405 return false;
406 }
407 // add lock
408 std::lock_guard<std::mutex> lock(totalBundlePrioSetLock_);
409
410 if (request.reason == AppStateUpdateReason::ABILITY_START) {
411 int64_t eventTime = KernelInterface::GetInstance().GetSystemTimeMs();
412 return HandleAbilityStart(request, eventTime);
413 }
414 return true;
415 }
416
CheckSatifyAbilityStartCondition(const ProcessPriorityInfo & proc)417 bool ReclaimPriorityManager::CheckSatifyAbilityStartCondition(const ProcessPriorityInfo &proc)
418 {
419 // priority of process is less important than RECLAIM_PRIORITY_FOREGROUND
420 if (proc.priority_ > RECLAIM_PRIORITY_FOREGROUND) {
421 return true;
422 }
423 if (proc.priority_ < RECLAIM_PRIORITY_FOREGROUND) {
424 return false;
425 }
426 // process is starting ability
427 if (proc.IsAbilityStarting()) {
428 return true;
429 }
430 return false;
431 }
432
433 // add lock before use this function
HandleAbilityStart(const UpdateRequest & request,int64_t eventTime)434 bool ReclaimPriorityManager::HandleAbilityStart(const UpdateRequest &request, int64_t eventTime)
435 {
436 ReqProc target = request.target;
437 int accountId = GetOsAccountIdByUid(target.uid);
438 if (!IsProcExist(target.pid, target.uid, accountId)) {
439 HILOGE("process not exist and not to create it!!");
440 return false;
441 }
442 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
443 std::shared_ptr<BundlePriorityInfo> bundle = account->FindBundleById(target.uid);
444 ProcessPriorityInfo &proc = bundle->FindProcByPid(target.pid);
445
446 if (CheckSatifyAbilityStartCondition(proc)) {
447 AbilityStartingBegin(proc, bundle, eventTime);
448
449 // remove previous timer if proc is not first starting ability
450 RemoveTimerForAbilityStartCompletedCheck(proc);
451 HILOGD("SetTimerForAbilityStartCompletedCheck, add timer!");
452 SetTimerForAbilityStartCompletedCheck(proc.pid_, proc.uid_, accountId);
453 }
454
455 return true;
456 }
457
SetTimerForAbilityStartCompletedCheck(pid_t pid,int32_t bundleUid,int32_t accountId)458 void ReclaimPriorityManager::SetTimerForAbilityStartCompletedCheck(pid_t pid, int32_t bundleUid, int32_t accountId)
459 {
460 std::string taskName = std::to_string(pid) + AppStateUpdateResonToString(AppStateUpdateReason::ABILITY_START);
461 handler_->PostTask(
462 [this, pid, bundleUid, accountId] { this->CheckAbilityStartCompleted(pid, bundleUid, accountId); },
463 taskName, TIMER_ABILITY_START_CHECK_MS, AppExecFwk::EventQueue::Priority::LOW);
464 HILOGI("set process<pid=%{public}d,uid=%{public}d> ability start check timer after %{public}d ms",
465 pid, bundleUid, TIMER_ABILITY_START_CHECK_MS);
466 }
467
CheckAbilityStartCompleted(pid_t pid,int32_t bundleUid,int32_t accountId)468 void ReclaimPriorityManager::CheckAbilityStartCompleted(pid_t pid, int32_t bundleUid, int32_t accountId)
469 {
470 // add lock
471 std::lock_guard<std::mutex> lock(totalBundlePrioSetLock_);
472
473 if (!IsProcExist(pid, bundleUid, accountId)) {
474 return;
475 }
476 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
477 std::shared_ptr<BundlePriorityInfo> bundle = account->FindBundleById(bundleUid);
478 ProcessPriorityInfo &proc = bundle->FindProcByPid(pid);
479
480 if (!proc.IsAbilityStarting()) {
481 HILOGD("check process<pid=%{public}d,uid=%{public}d,prio=%{public}d> : is not starting ability,"
482 " not handle!", proc.pid_, proc.uid_, proc.priority_);
483 return;
484 }
485
486 AbilityStartingEnd(proc, bundle, true);
487 }
488
GetBundleMgr()489 sptr<AppExecFwk::IBundleMgr> GetBundleMgr()
490 {
491 sptr<ISystemAbilityManager> saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
492 if (saMgr == nullptr) {
493 HILOGE("failed to get system ability manager!");
494 return nullptr;
495 }
496 sptr<IRemoteObject> remoteObject_ = saMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
497 if (remoteObject_ == nullptr) {
498 HILOGE("bms not found!");
499 return nullptr;
500 }
501 sptr<AppExecFwk::IBundleMgr> bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(remoteObject_);
502 if (bundleMgr == nullptr) {
503 HILOGE("bms interface cast failed!");
504 }
505 return bundleMgr;
506 }
507
IsKillableSystemApp(std::shared_ptr<BundlePriorityInfo> bundle)508 bool ReclaimPriorityManager::IsKillableSystemApp(std::shared_ptr<BundlePriorityInfo> bundle)
509 {
510 if (allKillableSystemApps_.find(bundle->name_) != allKillableSystemApps_.end()) {
511 HILOGD("find bundle (%{public}s) in killable system app list", bundle->name_.c_str());
512 return true;
513 }
514
515 sptr<AppExecFwk::IBundleMgr> bmsPtr = GetBundleMgr();
516 if (bmsPtr == nullptr) {
517 HILOGE("failed to get BundleMgr!");
518 return false;
519 }
520
521 AppExecFwk::ApplicationInfo info;
522 bool result = bmsPtr->GetApplicationInfo(bundle->name_.c_str(),
523 AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, GetOsAccountIdByUid(bundle->uid_), info);
524 if (result) {
525 HILOGD("appInfo<%{public}s,%{public}d><keepAlive=%{public}d, isSystemApp=%{public}d, isLauncherApp=%{public}d>",
526 bundle->name_.c_str(), bundle->uid_, info.keepAlive, info.isSystemApp, info.isLauncherApp);
527 if (info.keepAlive) {
528 auto ret = allKillableSystemApps_.insert(bundle->name_);
529 if (ret.second) {
530 HILOGD("add a new killable system app (%{public}s)", bundle->name_.c_str());
531 }
532 }
533 return info.keepAlive;
534 } else {
535 HILOGE("bundleMgr GetApplicationInfo failed!");
536 }
537 return false;
538 }
539
UpdateBundlePriority(std::shared_ptr<BundlePriorityInfo> bundle)540 void ReclaimPriorityManager::UpdateBundlePriority(std::shared_ptr<BundlePriorityInfo> bundle)
541 {
542 HILOGD("begin-------------------------");
543 DeleteBundleInfoFromSet(bundle);
544 bundle->UpdatePriority();
545 AddBundleInfoToSet(bundle);
546 HILOGD("end----------------------------");
547 }
548
HandleCreateProcess(ReqProc & target,int accountId,bool isRender)549 bool ReclaimPriorityManager::HandleCreateProcess(ReqProc &target, int accountId, bool isRender)
550 {
551 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
552 if (isRender) {
553 OomScoreAdjUtils::WriteOomScoreAdjToKernel(target.pid, RECLAIM_PRIORITY_FOREGROUND);
554 return true;
555 }
556 if (account == nullptr) {
557 DECLARE_SHARED_POINTER(AccountBundleInfo, tmpAccount);
558 MAKE_POINTER(tmpAccount, shared, AccountBundleInfo, "cannot new account!!", return false, accountId);
559 account = tmpAccount;
560 AddOsAccountInfo(account);
561 }
562 std::shared_ptr<BundlePriorityInfo> bundle;
563 AppAction action;
564 if (account->HasBundle(target.uid)) {
565 // insert new ProcessInfo and update new priority
566 bundle = account->FindBundleById(target.uid);
567 action = AppAction::CREATE_PROCESS_ONLY;
568 } else {
569 // need to new BundleInfo ,add to list and map
570 MAKE_POINTER(bundle, shared, BundlePriorityInfo, "cannot new account!!", return false,
571 target.bundleName, target.uid, RECLAIM_PRIORITY_BACKGROUND);
572 AddBundleInfoToSet(bundle);
573 action = AppAction::CREATE_PROCESS_AND_APP;
574 }
575
576 int priority = RECLAIM_PRIORITY_BACKGROUND;
577 bool isImportantProc = IsImportantProc(target.processName, priority);
578 ProcessPriorityInfo proc(target.pid, target.uid, priority, isImportantProc);
579 if (IsKillableSystemApp(bundle) && proc.priority_ > RECLAIM_PRIORITY_KILLABLE_SYSTEM) {
580 proc.priority_ = RECLAIM_PRIORITY_KILLABLE_SYSTEM;
581 }
582 bundle->AddProc(proc);
583 UpdateBundlePriority(bundle);
584 account->AddBundleToOsAccount(bundle);
585 bool ret = ApplyReclaimPriority(bundle, target.pid, action);
586 HILOGI("create: bundleName=%{public}s, prio=%{public}d", target.bundleName.c_str(), bundle->priority_);
587 return ret;
588 }
589
HandleTerminateProcess(ProcessPriorityInfo proc,std::shared_ptr<BundlePriorityInfo> bundle,std::shared_ptr<AccountBundleInfo> account)590 bool ReclaimPriorityManager::HandleTerminateProcess(ProcessPriorityInfo proc,
591 std::shared_ptr<BundlePriorityInfo> bundle, std::shared_ptr<AccountBundleInfo> account)
592 {
593 HILOGI("terminated: bundleName=%{public}s, pid=%{public}d", bundle->name_.c_str(), proc.pid_);
594
595 // clear proc and bundle if needed, delete the object
596 int removedProcessPrio = proc.priority_;
597 bundle->RemoveProcByPid(proc.pid_);
598 bool ret = true;
599
600 if (bundle->GetProcsCount() == 0) {
601 ret = ApplyReclaimPriority(bundle, proc.pid_, AppAction::APP_DIED);
602 account->RemoveBundleById(bundle->uid_);
603 DeleteBundleInfoFromSet(bundle);
604 } else {
605 if (removedProcessPrio <= bundle->priority_) {
606 UpdateBundlePriority(bundle);
607 }
608 }
609 if (account->GetBundlesCount() == 0) {
610 RemoveOsAccountById(account->id_);
611 }
612 return ret;
613 }
614
SetTimerForDiedProcessCheck(int64_t delayTime)615 void ReclaimPriorityManager::SetTimerForDiedProcessCheck(int64_t delayTime)
616 {
617 handler_->PostTask([this] { this->HandleDiedProcessCheck(); }, delayTime, AppExecFwk::EventQueue::Priority::LOW);
618 }
619
FilterDiedProcess()620 void ReclaimPriorityManager::FilterDiedProcess()
621 {
622 std::vector<unsigned int> alivePids;
623 if (!KernelInterface::GetInstance().GetAllProcPids(alivePids)) {
624 return;
625 }
626
627 std::lock_guard<std::mutex> lock(totalBundlePrioSetLock_);
628 for (auto itrBundle = totalBundlePrioSet_.begin(); itrBundle != totalBundlePrioSet_.end();) {
629 std::shared_ptr<BundlePriorityInfo> bundle = *itrBundle;
630 if (bundle == nullptr) {
631 continue;
632 }
633 for (auto itrProcess = bundle->procs_.begin(); itrProcess != bundle->procs_.end();) {
634 auto itProc = std::find(alivePids.begin(), alivePids.end(), itrProcess->second.pid_);
635 if (itProc == alivePids.end()) {
636 itrProcess = bundle->procs_.erase(itrProcess);
637 continue;
638 } else {
639 HandleDiedExtensionBindToMe(itrProcess, alivePids);
640 HandleDiedExtensionBindFromMe(itrProcess, alivePids);
641 }
642 ++itrProcess;
643 }
644 if (bundle->GetProcsCount() == 0) {
645 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(bundle->accountId_);
646 if (account != nullptr) {
647 account->RemoveBundleById(bundle->uid_);
648 itrBundle = totalBundlePrioSet_.erase(itrBundle);
649 continue;
650 }
651 }
652 ++itrBundle;
653 }
654 }
655
HandleDiedExtensionBindToMe(std::map<pid_t,ProcessPriorityInfo>::iterator processPriorityInfoMap,const std::vector<unsigned int> & alivePids)656 void ReclaimPriorityManager::HandleDiedExtensionBindToMe(
657 std::map<pid_t, ProcessPriorityInfo>::iterator processPriorityInfoMap, const std::vector<unsigned int> &alivePids)
658 {
659 std::vector<int32_t> diedProcsForConnectors;
660 for (auto &pair : processPriorityInfoMap->second.procsBindToMe_) {
661 auto connector = pair.first;
662 if (std::find(alivePids.begin(), alivePids.end(), connector) == alivePids.end()) {
663 diedProcsForConnectors.push_back(connector);
664 }
665 }
666 for (int32_t diedPid : diedProcsForConnectors) {
667 processPriorityInfoMap->second.ProcUnBindToMe(diedPid);
668 }
669 }
670
HandleDiedExtensionBindFromMe(std::map<pid_t,ProcessPriorityInfo>::iterator processPriorityInfoMap,const std::vector<unsigned int> & alivePids)671 void ReclaimPriorityManager::HandleDiedExtensionBindFromMe(
672 std::map<pid_t, ProcessPriorityInfo>::iterator processPriorityInfoMap, const std::vector<unsigned int> &alivePids)
673 {
674 std::vector<int32_t> diedProcsForConnectors;
675 for (auto &pair : processPriorityInfoMap->second.procsBindFromMe_) {
676 auto connector = pair.first;
677 if (std::find(alivePids.begin(), alivePids.end(), connector) == alivePids.end()) {
678 diedProcsForConnectors.push_back(connector);
679 }
680 }
681 for (int32_t diedPid : diedProcsForConnectors) {
682 processPriorityInfoMap->second.ProcUnBindFromMe(diedPid);
683 }
684 }
685
HandleDiedProcessCheck()686 void ReclaimPriorityManager::HandleDiedProcessCheck()
687 {
688 FilterDiedProcess();
689 if (totalBundlePrioSet_.size() > MAX_TOTALBUNDLESET_SIZE) {
690 SetTimerForDiedProcessCheck(TIMER_DIED_PROC_FAST_CHECK_MS);
691 } else {
692 SetTimerForDiedProcessCheck(TIMER_DIED_PROC_SLOW_CHECK_MS);
693 }
694 }
695
HandleApplicationSuspend(std::shared_ptr<BundlePriorityInfo> bundle)696 bool ReclaimPriorityManager::HandleApplicationSuspend(std::shared_ptr<BundlePriorityInfo> bundle)
697 {
698 if (bundle == nullptr) {
699 return false;
700 }
701 HILOGI("application suspend: bundleName=%{public}s", bundle->name_.c_str());
702 for (auto i = bundle->procs_.begin(); i != bundle->procs_.end(); ++i) {
703 i->second.priority_ = RECLAIM_PRIORITY_SUSPEND;
704 }
705 UpdateBundlePriority(bundle);
706 bool ret = ApplyReclaimPriority(bundle, IGNORE_PID, AppAction::OTHERS);
707 return ret;
708 }
709
UpdateExtensionStatusForTarget(UpdateRequest & request,int64_t eventTime)710 bool ReclaimPriorityManager::UpdateExtensionStatusForTarget(UpdateRequest &request, int64_t eventTime)
711 {
712 ReqProc caller = request.caller;
713 ReqProc target = request.target;
714 int accountId = GetOsAccountIdByUid(target.uid);
715 if (!IsProcExist(target.pid, target.uid, accountId)) {
716 HILOGE("process not exist and not to create it!!");
717 return false;
718 }
719 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
720 std::shared_ptr<BundlePriorityInfo> bundle = account->FindBundleById(target.uid);
721 ProcessPriorityInfo &proc = bundle->FindProcByPid(target.pid);
722
723 if (proc.priority_ <= RECLAIM_PRIORITY_KILLABLE_SYSTEM || bundle->priority_ <= RECLAIM_PRIORITY_KILLABLE_SYSTEM ||
724 IsKillableSystemApp(bundle)) {
725 HILOGD("%{public}s is system app, skip!", target.bundleName.c_str());
726 return true;
727 }
728
729 if (request.reason == AppStateUpdateReason::BIND_EXTENSION) {
730 proc.isFreground = false; // current process is a extension, it never be a fg app.
731 proc.isExtension_ = true;
732 proc.ProcBindToMe(caller.pid, caller.uid);
733 } else if (request.reason == AppStateUpdateReason::UNBIND_EXTENSION) {
734 proc.isFreground = false; // current process is a extension, it never be a fg app.
735 proc.isExtension_ = true;
736 proc.ProcUnBindToMe(caller.pid);
737 }
738 AppAction action = AppAction::OTHERS;
739 HandleUpdateProcess(request.reason, bundle, proc, action, eventTime);
740 return ApplyReclaimPriority(bundle, target.pid, action);
741 }
742
UpdateExtensionStatusForCaller(UpdateRequest & request)743 bool ReclaimPriorityManager::UpdateExtensionStatusForCaller(UpdateRequest &request)
744 {
745 ReqProc caller = request.caller;
746 ReqProc target = request.target;
747 int callerAccountId = GetOsAccountIdByUid(caller.uid);
748 if (!IsProcExist(caller.pid, caller.uid, callerAccountId)) {
749 HILOGE("caller process not exist and not to create it!!");
750 return false;
751 }
752 std::shared_ptr<AccountBundleInfo> callerAccount = FindOsAccountById(callerAccountId);
753 std::shared_ptr<BundlePriorityInfo> callerBundle = callerAccount->FindBundleById(caller.uid);
754 ProcessPriorityInfo &callerProc = callerBundle->FindProcByPid(caller.pid);
755
756 if (request.reason == AppStateUpdateReason::BIND_EXTENSION) {
757 callerProc.ProcBindFromMe(target.pid, target.uid);
758 } else if (request.reason == AppStateUpdateReason::UNBIND_EXTENSION) {
759 callerProc.ProcUnBindFromMe(target.pid);
760 }
761 return true;
762 }
763
GetConnectedExtensionProc(const ProcessPriorityInfo & proc,ProcInfoVec & procVec)764 void ReclaimPriorityManager::GetConnectedExtensionProc(const ProcessPriorityInfo &proc, ProcInfoVec &procVec)
765 {
766 std::set<int32_t> isExtensionProcVisitedSet;
767 std::queue<ProcessPriorityInfo> extensionProcQue;
768 extensionProcQue.push(proc);
769
770 while (!extensionProcQue.empty()) {
771 ProcessPriorityInfo extensionProc(extensionProcQue.front());
772 extensionProcQue.pop();
773 if (isExtensionProcVisitedSet.count(extensionProc.pid_)) {
774 continue;
775 }
776 if (extensionProc.isExtension_) {
777 procVec.push_back(extensionProc);
778 isExtensionProcVisitedSet.insert(extensionProc.pid_);
779 }
780
781 for (const auto &pair : extensionProc.procsBindFromMe_) {
782 if (isExtensionProcVisitedSet.count(pair.first)) {
783 continue;
784 }
785 int accountId = GetOsAccountIdByUid(pair.second);
786 if (!IsProcExist(pair.first, pair.second, accountId)) {
787 continue;
788 }
789 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
790 std::shared_ptr<BundlePriorityInfo> bundle = account->FindBundleById(pair.second);
791 ProcessPriorityInfo &procBindFromMe = bundle->FindProcByPid(pair.first);
792 extensionProcQue.push(procBindFromMe);
793 }
794 }
795 }
796
CalculateExtensionProcPrio(ProcInfoVec & procVec,ProcInfoSet & procSet)797 void ReclaimPriorityManager::CalculateExtensionProcPrio(ProcInfoVec &procVec, ProcInfoSet &procSet)
798 {
799 for (auto &extensionProc : procVec) {
800 int32_t minExtensionPriority = RECLAIM_PRIORITY_BACKGROUND;
801 for (const auto &connectorProcPair : extensionProc.procsBindToMe_) {
802 int accountId = GetOsAccountIdByUid(connectorProcPair.second);
803 if (!IsProcExist(connectorProcPair.first, connectorProcPair.second, accountId)) {
804 minExtensionPriority = 0;
805 continue;
806 }
807
808 std::shared_ptr<AccountBundleInfo> connectorAccount = FindOsAccountById(accountId);
809 std::shared_ptr<BundlePriorityInfo> bundle = connectorAccount->FindBundleById(connectorProcPair.second);
810 ProcessPriorityInfo &procBindToMe = bundle->FindProcByPid(connectorProcPair.first);
811 minExtensionPriority =
812 minExtensionPriority < procBindToMe.priority_ ? minExtensionPriority : procBindToMe.priority_;
813 }
814
815 extensionProc.priority_ = minExtensionPriority;
816 procSet.insert(extensionProc);
817 }
818 }
819
SetConnectExtensionProcPrio(const ProcInfoSet & procSet)820 void ReclaimPriorityManager::SetConnectExtensionProcPrio(const ProcInfoSet &procSet)
821 {
822 int32_t deltaPriority = 100;
823 for (const auto &extensionProcess : procSet) {
824 int32_t minExtensionPriority = RECLAIM_PRIORITY_BACKGROUND;
825 for (const auto &connectorProcPair : extensionProcess.procsBindToMe_) {
826 int accountId = GetOsAccountIdByUid(connectorProcPair.second);
827 if (!IsProcExist(connectorProcPair.first, connectorProcPair.second, accountId)) {
828 minExtensionPriority = 0;
829 continue;
830 }
831 std::shared_ptr<AccountBundleInfo> connectorAccount = FindOsAccountById(accountId);
832 std::shared_ptr<BundlePriorityInfo> bundle = connectorAccount->FindBundleById(connectorProcPair.second);
833 ProcessPriorityInfo &procBindToMe = bundle->FindProcByPid(connectorProcPair.first);
834 int32_t procBindToMePrio = procBindToMe.priority_ < 0 ? 0 : procBindToMe.priority_;
835 minExtensionPriority =
836 minExtensionPriority < procBindToMePrio ? minExtensionPriority : procBindToMePrio;
837 }
838
839 int extensionAccountId = GetOsAccountIdByUid(extensionProcess.uid_);
840 if (!IsProcExist(extensionProcess.pid_, extensionProcess.uid_, extensionAccountId)) {
841 continue;
842 }
843
844 std::shared_ptr<AccountBundleInfo> extensionAccount = FindOsAccountById(extensionAccountId);
845 std::shared_ptr<BundlePriorityInfo> extensionBundle = extensionAccount->FindBundleById(extensionProcess.uid_);
846 ProcessPriorityInfo &procExtensionUpdate = extensionBundle->FindProcByPid(extensionProcess.pid_);
847 procExtensionUpdate.SetPriority(minExtensionPriority + deltaPriority);
848 if (procExtensionUpdate.isImportant_) {
849 SetImportantProcPriority(procExtensionUpdate);
850 }
851 UpdateBundlePriority(extensionBundle);
852 OomScoreAdjUtils::WriteOomScoreAdjToKernel(procExtensionUpdate.pid_, procExtensionUpdate.priority_);
853 }
854 }
855
HandleExtensionProcess(UpdateRequest & request,int64_t eventTime)856 bool ReclaimPriorityManager::HandleExtensionProcess(UpdateRequest &request, int64_t eventTime)
857 {
858 UpdateExtensionStatusForCaller(request);
859 return UpdateExtensionStatusForTarget(request, eventTime);
860 }
861
862
UpdateReclaimPriorityInner(UpdateRequest request,int64_t eventTime)863 bool ReclaimPriorityManager::UpdateReclaimPriorityInner(UpdateRequest request, int64_t eventTime)
864 {
865 // This function can only be called by UpdateReclaimPriority, otherwise it may deadlock.
866 std::lock_guard<std::mutex> setLock(totalBundlePrioSetLock_);
867 ReqProc target = request.target;
868 int accountId = GetOsAccountIdByUid(target.uid);
869 HILOGD("accountId=%{public}d", accountId);
870
871 if (request.reason == AppStateUpdateReason::BIND_EXTENSION ||
872 request.reason == AppStateUpdateReason::UNBIND_EXTENSION) {
873 return HandleExtensionProcess(request, eventTime);
874 }
875
876 if (request.reason == AppStateUpdateReason::CREATE_PROCESS) {
877 return HandleCreateProcess(target, accountId);
878 }
879
880 if (request.reason == AppStateUpdateReason::RENDER_CREATE_PROCESS) {
881 return HandleCreateProcess(target, accountId, true);
882 }
883
884 if (request.reason == AppStateUpdateReason::ABILITY_START) {
885 return HandleAbilityStart(request, eventTime);
886 }
887
888 if (!IsProcExist(target.pid, target.uid, accountId)) {
889 HILOGE("process not exist and not to create it!!");
890 return false;
891 }
892 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
893 std::shared_ptr<BundlePriorityInfo> bundle = account->FindBundleById(target.uid);
894 if (bundle->priority_ <= RECLAIM_PRIORITY_KILLABLE_SYSTEM) {
895 HILOGI("%{public}s is system app, skip!", target.bundleName.c_str());
896 return true;
897 }
898
899 if (request.reason == AppStateUpdateReason::APPLICATION_SUSPEND) {
900 return HandleApplicationSuspend(bundle);
901 }
902
903 ProcessPriorityInfo &proc = bundle->FindProcByPid(target.pid);
904 AppAction action = AppAction::OTHERS;
905 if (request.reason == AppStateUpdateReason::PROCESS_TERMINATED) {
906 return HandleTerminateProcess(proc, bundle, account);
907 } else {
908 HandleUpdateProcess(request.reason, bundle, proc, action, eventTime);
909 }
910 return ApplyReclaimPriority(bundle, target.pid, action);
911 }
912
IsImportantProc(const std::string procName,int & dstPriority)913 bool ReclaimPriorityManager::IsImportantProc(const std::string procName, int &dstPriority)
914 {
915 std::map<std::string, int> importantProcs = config_.GetImportantBgApps();
916 if (importantProcs.count(procName)) {
917 dstPriority = importantProcs.at(procName);
918 HILOGD("is an important proc, procName=%{public}s, importPriority=%{public}d", procName.c_str(), dstPriority);
919 return true;
920 }
921 return false;
922 }
923
SetImportantProcPriority(ProcessPriorityInfo & proc)924 void ReclaimPriorityManager::SetImportantProcPriority(ProcessPriorityInfo &proc)
925 {
926 if (proc.priority_ > proc.priorityIfImportant_) {
927 proc.priority_ = proc.priorityIfImportant_;
928 }
929 }
930
UpdatePriorityByProcForExtension(ProcessPriorityInfo & proc)931 void ReclaimPriorityManager::UpdatePriorityByProcForExtension(ProcessPriorityInfo &proc)
932 {
933 ProcInfoVec allConnectedExtensionProcVec;
934 GetConnectedExtensionProc(proc, allConnectedExtensionProcVec);
935 if (allConnectedExtensionProcVec.size() == 0) {
936 return;
937 }
938 ProcInfoSet allConnectedExtensionProcSet;
939 CalculateExtensionProcPrio(allConnectedExtensionProcVec, allConnectedExtensionProcSet);
940
941 SetConnectExtensionProcPrio(allConnectedExtensionProcSet);
942 }
943
UpdatePriorityByProcConnector(ProcessPriorityInfo & proc)944 void ReclaimPriorityManager::UpdatePriorityByProcConnector(ProcessPriorityInfo &proc)
945 {
946 if (proc.procsBindFromMe_.size() == 0) {
947 return;
948 }
949 proc.SetPriority(RECLAIM_PRIORITY_BACKGROUND);
950 int minPriority = RECLAIM_PRIORITY_UNKNOWN;
951 for (auto &pair : proc.procsBindFromMe_) {
952 int32_t connectorUid = pair.second;
953 int connectorAccountId = GetOsAccountIdByUid(connectorUid);
954 std::shared_ptr<AccountBundleInfo> connectorAccount = FindOsAccountById(connectorAccountId);
955 if (connectorAccount == nullptr || !connectorAccount->HasBundle(connectorUid)) {
956 minPriority = 0; // native
957 continue;
958 }
959 std::shared_ptr<BundlePriorityInfo> connectorBundle = connectorAccount->FindBundleById(connectorUid);
960 if (connectorBundle == nullptr) {
961 return;
962 }
963 for (auto procEntry : connectorBundle->procs_) {
964 ProcessPriorityInfo &connectorProc = procEntry.second;
965 minPriority = connectorProc.priority_ < minPriority ? connectorProc.priority_ : minPriority;
966 }
967 }
968 proc.SetPriority(minPriority + 100); // raise the priority of the lowest-priority process by 100
969 }
970
UpdatePriorityByProcStatus(std::shared_ptr<BundlePriorityInfo> bundle,ProcessPriorityInfo & proc)971 void ReclaimPriorityManager::UpdatePriorityByProcStatus(std::shared_ptr<BundlePriorityInfo> bundle,
972 ProcessPriorityInfo &proc)
973 {
974 if (bundle->priority_ < RECLAIM_PRIORITY_FOREGROUND) { // is a system process
975 return;
976 }
977 if (proc.isRender_) { // priority of render follow its host and it is updated by action of its host
978 return;
979 }
980 if (proc.isFreground) { // is a freground process
981 if (proc.priority_ > RECLAIM_PRIORITY_FOREGROUND) {
982 proc.SetPriority(RECLAIM_PRIORITY_FOREGROUND);
983 }
984 } else if (!proc.isExtension_) { // is a background process
985 proc.SetPriority(RECLAIM_PRIORITY_BACKGROUND);
986 }
987 if (proc.isVisible_) {
988 if (proc.priority_ > RECLAIM_PRIORITY_VISIBLE) {
989 proc.SetPriority(RECLAIM_PRIORITY_VISIBLE);
990 }
991 }
992 if (proc.isSuspendDelay) { // is a background process with transient task
993 if (proc.priority_ > RECLAIM_PRIORITY_BG_SUSPEND_DELAY) {
994 proc.SetPriority(RECLAIM_PRIORITY_BG_SUSPEND_DELAY);
995 }
996 } else if (proc.isBackgroundRunning || proc.isEventStart) {
997 // is a background perceived process
998 if (proc.priority_ > RECLAIM_PRIORITY_BG_PERCEIVED) {
999 proc.SetPriority(RECLAIM_PRIORITY_BG_PERCEIVED);
1000 }
1001 } else if (proc.isDistDeviceConnected) { // is a background process connected by distribute device
1002 if (proc.priority_ > RECLAIM_PRIORITY_BG_DIST_DEVICE) {
1003 proc.SetPriority(RECLAIM_PRIORITY_BG_DIST_DEVICE);
1004 }
1005 } else {
1006 // is a plain background process
1007 }
1008
1009 if (proc.isImportant_) {
1010 SetImportantProcPriority(proc);
1011 }
1012 UpdateBundlePriority(bundle);
1013 UpdatePriorityByProcForExtension(proc);
1014 }
1015
HandleForeground(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1016 void ReclaimPriorityManager::HandleForeground(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1017 {
1018 proc.isFreground = true;
1019 action = AppAction::APP_FOREGROUND;
1020 FinishAbilityStartIfNeed(proc, AppStateUpdateReason::FOREGROUND, eventTime);
1021 }
1022
HandleBackground(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1023 void ReclaimPriorityManager::HandleBackground(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1024 {
1025 proc.isFreground = false;
1026 action = AppAction::APP_BACKGROUND;
1027 FinishAbilityStartIfNeed(proc, AppStateUpdateReason::BACKGROUND, eventTime);
1028 }
1029
HandleSuspendDelayStart(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1030 void ReclaimPriorityManager::HandleSuspendDelayStart(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1031 {
1032 proc.isSuspendDelay = true;
1033 }
1034
HandleSuspendDelayEnd(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1035 void ReclaimPriorityManager::HandleSuspendDelayEnd(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1036 {
1037 proc.isSuspendDelay = false;
1038 }
1039
HandleBackgroundRunningStart(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1040 void ReclaimPriorityManager::HandleBackgroundRunningStart(ProcessPriorityInfo &proc, AppAction &action,
1041 int64_t eventTime)
1042 {
1043 proc.isBackgroundRunning = true;
1044 }
1045
HandleBackgroundRunningEnd(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1046 void ReclaimPriorityManager::HandleBackgroundRunningEnd(ProcessPriorityInfo &proc, AppAction &action,
1047 int64_t eventTime)
1048 {
1049 proc.isBackgroundRunning = false;
1050 }
1051
HandleEventStart(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1052 void ReclaimPriorityManager::HandleEventStart(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1053 {
1054 proc.isEventStart = true;
1055 }
1056
HandleEventEnd(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1057 void ReclaimPriorityManager::HandleEventEnd(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1058 {
1059 proc.isEventStart = false;
1060 }
1061
HandleDistDeviceConnected(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1062 void ReclaimPriorityManager::HandleDistDeviceConnected(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1063 {
1064 proc.isDistDeviceConnected = true;
1065 }
1066
HandleDistDeviceDisconnected(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1067 void ReclaimPriorityManager::HandleDistDeviceDisconnected(ProcessPriorityInfo &proc, AppAction &action,
1068 int64_t eventTime)
1069 {
1070 proc.isDistDeviceConnected = false;
1071 }
1072
HandleBindExtension(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1073 void ReclaimPriorityManager::HandleBindExtension(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1074 {
1075 if (proc.ExtensionConnectorsCount() > 0) {
1076 proc.extensionBindStatus = EXTENSION_STATUS_FG_BIND;
1077 }
1078 }
1079
HandleUnbindExtension(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1080 void ReclaimPriorityManager::HandleUnbindExtension(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1081 {
1082 if (proc.ExtensionConnectorsCount() == 0) {
1083 proc.extensionBindStatus = EXTENSION_STATUS_NO_BIND;
1084 }
1085 }
1086
HandleVisible(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1087 void ReclaimPriorityManager::HandleVisible(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1088 {
1089 proc.isVisible_ = true;
1090 }
1091
HandleUnvisible(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1092 void ReclaimPriorityManager::HandleUnvisible(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1093 {
1094 proc.isVisible_ = false;
1095 }
1096
InitChangeProcMapping()1097 void ReclaimPriorityManager::InitChangeProcMapping()
1098 {
1099 changeProcMapping_[AppStateUpdateReason::FOREGROUND] = &ReclaimPriorityManager::HandleForeground;
1100 changeProcMapping_[AppStateUpdateReason::BACKGROUND] = &ReclaimPriorityManager::HandleBackground;
1101 changeProcMapping_[AppStateUpdateReason::SUSPEND_DELAY_START] = &ReclaimPriorityManager::HandleSuspendDelayStart;
1102 changeProcMapping_[AppStateUpdateReason::SUSPEND_DELAY_END] = &ReclaimPriorityManager::HandleSuspendDelayEnd;
1103 changeProcMapping_[AppStateUpdateReason::BACKGROUND_RUNNING_START] =
1104 &ReclaimPriorityManager::HandleBackgroundRunningStart;
1105 changeProcMapping_[AppStateUpdateReason::BACKGROUND_RUNNING_END] =
1106 &ReclaimPriorityManager::HandleBackgroundRunningEnd;
1107 changeProcMapping_[AppStateUpdateReason::EVENT_START] = &ReclaimPriorityManager::HandleEventStart;
1108 changeProcMapping_[AppStateUpdateReason::EVENT_END] = &ReclaimPriorityManager::HandleEventEnd;
1109 changeProcMapping_[AppStateUpdateReason::DIST_DEVICE_CONNECTED] =
1110 &ReclaimPriorityManager::HandleDistDeviceConnected;
1111 changeProcMapping_[AppStateUpdateReason::DIST_DEVICE_DISCONNECTED] =
1112 &ReclaimPriorityManager::HandleDistDeviceDisconnected;
1113 changeProcMapping_[AppStateUpdateReason::BIND_EXTENSION] = &ReclaimPriorityManager::HandleBindExtension;
1114 changeProcMapping_[AppStateUpdateReason::UNBIND_EXTENSION] = &ReclaimPriorityManager::HandleUnbindExtension;
1115 changeProcMapping_[AppStateUpdateReason::VISIBLE] = &ReclaimPriorityManager::HandleVisible;
1116 changeProcMapping_[AppStateUpdateReason::UN_VISIBLE] = &ReclaimPriorityManager::HandleUnvisible;
1117 }
1118
1119
HandleUpdateProcess(AppStateUpdateReason reason,std::shared_ptr<BundlePriorityInfo> bundle,ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1120 void ReclaimPriorityManager::HandleUpdateProcess(AppStateUpdateReason reason,
1121 std::shared_ptr<BundlePriorityInfo> bundle, ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1122 {
1123 HILOGD("called, bundle[uid_=%{public}d,name=%{public}s,priority=%{public}d], proc[pid_=%{public}d, uid=%{public}d,"
1124 "isFreground=%{public}d, isBackgroundRunning=%{public}d, isSuspendDelay=%{public}d, isEventStart=%{public}d,"
1125 "isDistDeviceConnected=%{public}d, extensionBindStatus=%{public}d, priority=%{public}d], case:%{public}s",
1126 bundle->uid_, bundle->name_.c_str(), bundle->priority_, proc.pid_, proc.uid_, proc.isFreground,
1127 proc.isBackgroundRunning, proc.isSuspendDelay, proc.isEventStart, proc.isDistDeviceConnected,
1128 proc.extensionBindStatus, proc.priority_, AppStateUpdateResonToString(reason).c_str());
1129 auto it = changeProcMapping_.find(reason);
1130 if (it != changeProcMapping_.end()) {
1131 auto changeProcPtr = it->second;
1132 (this->*changeProcPtr)(proc, action, eventTime);
1133 }
1134
1135 if (NeedSkipEventBeforeAbilityStart(proc, reason, eventTime)) {
1136 HILOGI("this event<pid=%{public}d,uid=%{public}d,reason=%{public}s> should execute befor startAbility event,\
1137 skip update priority.", proc.pid_, proc.uid_, AppStateUpdateResonToString(reason).c_str());
1138 return;
1139 }
1140 UpdatePriorityByProcStatus(bundle, proc);
1141 }
1142
ApplyReclaimPriority(std::shared_ptr<BundlePriorityInfo> bundle,pid_t pid,AppAction action)1143 bool ReclaimPriorityManager::ApplyReclaimPriority(std::shared_ptr<BundlePriorityInfo> bundle,
1144 pid_t pid, AppAction action)
1145 {
1146 HILOGD("called");
1147 if (bundle == nullptr) {
1148 HILOGD("bundle is nullptr");
1149 return false;
1150 }
1151 #ifdef USE_HYPERHOLD_MEMORY
1152 DECLARE_SHARED_POINTER(ReclaimParam, para);
1153 MAKE_POINTER(para, shared, ReclaimParam, "make ReclaimParam failed", return false,
1154 pid, bundle->uid_, bundle->name_, bundle->accountId_, bundle->priority_, action);
1155 ReclaimStrategyManager::GetInstance().NotifyAppStateChanged(para);
1156 #endif
1157 return OomScoreAdjUtils::WriteOomScoreAdjToKernel(bundle);
1158 }
1159
OsAccountChanged(int accountId,AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)1160 bool ReclaimPriorityManager::OsAccountChanged(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)
1161 {
1162 if (!initialized_) {
1163 HILOGE("has not been initialized_, skiped!");
1164 return false;
1165 }
1166 if (accountId < 0) {
1167 HILOGE("invalid account id!");
1168 return false;
1169 }
1170 return handler_->PostImmediateTask([this, accountId, switchMod] {
1171 this->OsAccountChangedInner(accountId, switchMod);
1172 });
1173 }
1174
OsAccountChangedInner(int accountId,AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)1175 bool ReclaimPriorityManager::OsAccountChangedInner(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)
1176 {
1177 return UpdateAllPrioForOsAccountChanged(accountId, switchMod);
1178 }
1179
UpdateAllPrioForOsAccountChanged(int accountId,AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)1180 bool ReclaimPriorityManager::UpdateAllPrioForOsAccountChanged(int accountId,
1181 AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)
1182 {
1183 if (!initialized_) {
1184 HILOGE("has not been initialized_, skiped!");
1185 return false;
1186 }
1187 HILOGI("UpdateReclaimPriority for all apps because of os account changed ");
1188 bool ret = MultiAccountManager::GetInstance().HandleOsAccountsChanged(accountId, switchMod, osAccountsInfoMap_);
1189 return ret;
1190 }
1191
Reset()1192 void ReclaimPriorityManager::Reset()
1193 {
1194 // add locks
1195 std::lock_guard<std::mutex> setLock(totalBundlePrioSetLock_);
1196
1197 HILOGI("clear totalBundlePrioSet(size: %{public}zu) and osAccountslnfoMap(size: %{public}zu) ",
1198 totalBundlePrioSet_.size(), osAccountsInfoMap_.size());
1199 totalBundlePrioSet_.clear();
1200 osAccountsInfoMap_.clear();
1201 }
1202
CheckCurrentEventHappenedBeforeAbilityStart(const ProcessPriorityInfo & proc,AppStateUpdateReason reason,int64_t eventTime)1203 bool ReclaimPriorityManager::CheckCurrentEventHappenedBeforeAbilityStart(const ProcessPriorityInfo &proc,
1204 AppStateUpdateReason reason, int64_t eventTime)
1205 {
1206 if (eventTime == INVALID_TIME) {
1207 return false;
1208 }
1209 if (eventTime < proc.GetStartingAbilityTime()) {
1210 return true;
1211 }
1212 return false;
1213 }
1214
RemoveTimerForAbilityStartCompletedCheck(const ProcessPriorityInfo & proc)1215 void ReclaimPriorityManager::RemoveTimerForAbilityStartCompletedCheck(const ProcessPriorityInfo &proc)
1216 {
1217 if (handler_ == nullptr) {
1218 return;
1219 }
1220 handler_->RemoveTask(std::to_string(proc.pid_) +
1221 AppStateUpdateResonToString(AppStateUpdateReason::ABILITY_START));
1222 }
1223
1224 // set priority of proc to RECLAIM_PRIORITY_FOREGROUND when proc is starting ability
AbilityStartingBegin(ProcessPriorityInfo & proc,std::shared_ptr<BundlePriorityInfo> bundle,int64_t eventTime)1225 void ReclaimPriorityManager::AbilityStartingBegin(ProcessPriorityInfo &proc, std::shared_ptr<BundlePriorityInfo> bundle,
1226 int64_t eventTime)
1227 {
1228 if (bundle == nullptr) {
1229 return;
1230 }
1231 // set priority to RECLAIM_PRIORITY_FOREGROUND
1232 proc.SetPriority(RECLAIM_PRIORITY_FOREGROUND);
1233 proc.SetStartingAbilityTime(eventTime);
1234 proc.SetIsAbilityStarting(true);
1235
1236 UpdateBundlePriority(bundle);
1237 ApplyReclaimPriority(bundle, proc.pid_, AppAction::OTHERS);
1238 }
1239
AbilityStartingEnd(ProcessPriorityInfo & proc,std::shared_ptr<BundlePriorityInfo> bundle,bool isUpdatePriority)1240 void ReclaimPriorityManager::AbilityStartingEnd(ProcessPriorityInfo &proc, std::shared_ptr<BundlePriorityInfo> bundle,
1241 bool isUpdatePriority)
1242 {
1243 proc.SetIsAbilityStarting(false);
1244
1245 // update priority based on process's status if need
1246 if (isUpdatePriority && bundle != nullptr) {
1247 int32_t beforePriority = proc.priority_;
1248 UpdatePriorityByProcStatus(bundle, proc);
1249 ApplyReclaimPriority(bundle, proc.pid_, AppAction::OTHERS);
1250 HILOGI("check process<pid=%{public}d,uid=%{public}d>, beforePrio=%{public}d, set currentPrio:%{public}d!",
1251 proc.pid_, proc.uid_, beforePriority, proc.priority_);
1252 }
1253 }
1254
FinishAbilityStartIfNeed(ProcessPriorityInfo & proc,AppStateUpdateReason reason,int64_t eventTime)1255 void ReclaimPriorityManager::FinishAbilityStartIfNeed(ProcessPriorityInfo &proc, AppStateUpdateReason reason,
1256 int64_t eventTime)
1257 {
1258 if (CheckAbilityStartNeedFinishInAdvance(proc, reason, eventTime)) {
1259 RemoveTimerForAbilityStartCompletedCheck(proc);
1260 AbilityStartingEnd(proc);
1261 }
1262 }
1263
CheckAbilityStartNeedFinishInAdvance(const ProcessPriorityInfo & proc,AppStateUpdateReason reason,int64_t eventTime)1264 bool ReclaimPriorityManager::CheckAbilityStartNeedFinishInAdvance(const ProcessPriorityInfo &proc,
1265 AppStateUpdateReason reason, int64_t eventTime)
1266 {
1267 return proc.IsAbilityStarting() && !CheckCurrentEventHappenedBeforeAbilityStart(proc, reason, eventTime);
1268 }
1269
NeedSkipEventBeforeAbilityStart(const ProcessPriorityInfo & proc,AppStateUpdateReason reason,int64_t eventTime)1270 bool ReclaimPriorityManager::NeedSkipEventBeforeAbilityStart(const ProcessPriorityInfo &proc,
1271 AppStateUpdateReason reason, int64_t eventTime)
1272 {
1273 return proc.IsAbilityStarting() && CheckCurrentEventHappenedBeforeAbilityStart(proc, reason, eventTime);
1274 }
1275 } // namespace Memory
1276 } // namespace OHOS