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