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 after 15s-------------------------");
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 if (!account) {
563 HILOGE("account is null, skip update.");
564 return;
565 }
566
567 std::shared_ptr<BundlePriorityInfo> bundle = account->FindBundleById(uid);
568 if (!bundle) {
569 HILOGE("bundle is null, skip update.");
570 return;
571 }
572
573 ProcessPriorityInfo &proc = bundle->FindProcByPid(pid);
574 UpdatePriorityByProcStatus(bundle, proc);
575 OomScoreAdjUtils::WriteOomScoreAdjToKernel(bundle);
576 HILOGD("end update after 15s----------------------------");
577 }
578
HandleCreateProcess(ReqProc & target,int accountId,bool isRender)579 bool ReclaimPriorityManager::HandleCreateProcess(ReqProc &target, int accountId, bool isRender)
580 {
581 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
582 if (isRender) {
583 OomScoreAdjUtils::WriteOomScoreAdjToKernel(target.pid, RECLAIM_PRIORITY_FOREGROUND);
584 return true;
585 }
586 if (account == nullptr) {
587 DECLARE_SHARED_POINTER(AccountBundleInfo, tmpAccount);
588 MAKE_POINTER(tmpAccount, shared, AccountBundleInfo, "cannot new account!!", return false, accountId);
589 account = tmpAccount;
590 AddOsAccountInfo(account);
591 }
592 std::shared_ptr<BundlePriorityInfo> bundle;
593 AppAction action;
594 if (account->HasBundle(target.uid)) {
595 // insert new ProcessInfo and update new priority
596 bundle = account->FindBundleById(target.uid);
597 action = AppAction::CREATE_PROCESS_ONLY;
598 } else {
599 // need to new BundleInfo ,add to list and map
600 MAKE_POINTER(bundle, shared, BundlePriorityInfo, "cannot new account!!", return false,
601 target.bundleName, target.uid, RECLAIM_PRIORITY_BACKGROUND);
602 AddBundleInfoToSet(bundle);
603 action = AppAction::CREATE_PROCESS_AND_APP;
604 }
605 int priority = RECLAIM_PRIORITY_FOREGROUND;
606 bool isImportantProc = IsImportantProc(target.processName, priority);
607 ProcessPriorityInfo proc(target.pid, target.uid, priority, isImportantProc);
608 //初始化时将isFreground设置为false
609 proc.isFreground = false;
610 if (IsKillableSystemApp(bundle) && proc.priority_ > RECLAIM_PRIORITY_KILLABLE_SYSTEM) {
611 proc.priority_ = RECLAIM_PRIORITY_KILLABLE_SYSTEM;
612 }
613 bundle->AddProc(proc);
614 UpdateBundlePriority(bundle);
615 account->AddBundleToOsAccount(bundle);
616 //set timer for process check
617 if (handler_ != nullptr) {
618 pid_t pid = target.pid;
619 int uid = target.uid;
620 HILOGI("set timer for process check\n");
621 handler_->PostTask([this, pid, uid] { this->CheckCreateProcPriorityDelay(pid, uid);},
622 TIMER_DELAY_MS, AppExecFwk::EventQueue::Priority::IMMEDIATE);
623 }
624 bool ret = ApplyReclaimPriority(bundle, target.pid, action);
625 HILOGI("create: bundleName=%{public}s, prio=%{public}d", target.bundleName.c_str(), bundle->priority_);
626 return ret;
627 }
628
HandleTerminateProcess(ProcessPriorityInfo proc,std::shared_ptr<BundlePriorityInfo> bundle,std::shared_ptr<AccountBundleInfo> account)629 bool ReclaimPriorityManager::HandleTerminateProcess(ProcessPriorityInfo proc,
630 std::shared_ptr<BundlePriorityInfo> bundle, std::shared_ptr<AccountBundleInfo> account)
631 {
632 HILOGI("terminated: bundleName=%{public}s, pid=%{public}d", bundle->name_.c_str(), proc.pid_);
633
634 // clear proc and bundle if needed, delete the object
635 int removedProcessPrio = proc.priority_;
636 bundle->RemoveProcByPid(proc.pid_);
637 bool ret = true;
638
639 if (bundle->GetProcsCount() == 0) {
640 ret = ApplyReclaimPriority(bundle, proc.pid_, AppAction::APP_DIED);
641 account->RemoveBundleById(bundle->uid_);
642 DeleteBundleInfoFromSet(bundle);
643 } else {
644 if (removedProcessPrio <= bundle->priority_) {
645 UpdateBundlePriority(bundle);
646 }
647 }
648 if (account->GetBundlesCount() == 0) {
649 RemoveOsAccountById(account->id_);
650 }
651 return ret;
652 }
653
SetTimerForDiedProcessCheck(int64_t delayTime)654 void ReclaimPriorityManager::SetTimerForDiedProcessCheck(int64_t delayTime)
655 {
656 handler_->PostTask([this] { this->HandleDiedProcessCheck(); }, delayTime, AppExecFwk::EventQueue::Priority::LOW);
657 }
658
FilterDiedProcess()659 void ReclaimPriorityManager::FilterDiedProcess()
660 {
661 std::vector<unsigned int> alivePids;
662 if (!KernelInterface::GetInstance().GetAllProcPids(alivePids)) {
663 return;
664 }
665
666 std::lock_guard<std::mutex> lock(totalBundlePrioSetLock_);
667 for (auto itrBundle = totalBundlePrioSet_.begin(); itrBundle != totalBundlePrioSet_.end();) {
668 std::shared_ptr<BundlePriorityInfo> bundle = *itrBundle;
669 if (bundle == nullptr) {
670 continue;
671 }
672 for (auto itrProcess = bundle->procs_.begin(); itrProcess != bundle->procs_.end();) {
673 auto itProc = std::find(alivePids.begin(), alivePids.end(), itrProcess->second.pid_);
674 if (itProc == alivePids.end()) {
675 itrProcess = bundle->procs_.erase(itrProcess);
676 continue;
677 } else {
678 HandleDiedExtensionBindToMe(itrProcess, alivePids);
679 HandleDiedExtensionBindFromMe(itrProcess, alivePids);
680 }
681 ++itrProcess;
682 }
683 if (bundle->GetProcsCount() == 0) {
684 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(bundle->accountId_);
685 if (account != nullptr) {
686 account->RemoveBundleById(bundle->uid_);
687 itrBundle = totalBundlePrioSet_.erase(itrBundle);
688 continue;
689 }
690 }
691 ++itrBundle;
692 }
693 }
694
HandleDiedExtensionBindToMe(std::map<pid_t,ProcessPriorityInfo>::iterator processPriorityInfoMap,const std::vector<unsigned int> & alivePids)695 void ReclaimPriorityManager::HandleDiedExtensionBindToMe(
696 std::map<pid_t, ProcessPriorityInfo>::iterator processPriorityInfoMap, const std::vector<unsigned int> &alivePids)
697 {
698 std::vector<int32_t> diedProcsForConnectors;
699 for (auto &pair : processPriorityInfoMap->second.procsBindToMe_) {
700 auto connector = pair.first;
701 if (std::find(alivePids.begin(), alivePids.end(), connector) == alivePids.end()) {
702 diedProcsForConnectors.push_back(connector);
703 }
704 }
705 for (int32_t diedPid : diedProcsForConnectors) {
706 processPriorityInfoMap->second.ProcUnBindToMe(diedPid);
707 }
708 }
709
HandleDiedExtensionBindFromMe(std::map<pid_t,ProcessPriorityInfo>::iterator processPriorityInfoMap,const std::vector<unsigned int> & alivePids)710 void ReclaimPriorityManager::HandleDiedExtensionBindFromMe(
711 std::map<pid_t, ProcessPriorityInfo>::iterator processPriorityInfoMap, const std::vector<unsigned int> &alivePids)
712 {
713 std::vector<int32_t> diedProcsForConnectors;
714 for (auto &pair : processPriorityInfoMap->second.procsBindFromMe_) {
715 auto connector = pair.first;
716 if (std::find(alivePids.begin(), alivePids.end(), connector) == alivePids.end()) {
717 diedProcsForConnectors.push_back(connector);
718 }
719 }
720 for (int32_t diedPid : diedProcsForConnectors) {
721 processPriorityInfoMap->second.ProcUnBindFromMe(diedPid);
722 }
723 }
724
HandleDiedProcessCheck()725 void ReclaimPriorityManager::HandleDiedProcessCheck()
726 {
727 FilterDiedProcess();
728 if (totalBundlePrioSet_.size() > MAX_TOTALBUNDLESET_SIZE) {
729 SetTimerForDiedProcessCheck(TIMER_DIED_PROC_FAST_CHECK_MS);
730 } else {
731 SetTimerForDiedProcessCheck(TIMER_DIED_PROC_SLOW_CHECK_MS);
732 }
733 }
734
HandleApplicationSuspend(std::shared_ptr<BundlePriorityInfo> bundle)735 bool ReclaimPriorityManager::HandleApplicationSuspend(std::shared_ptr<BundlePriorityInfo> bundle)
736 {
737 if (bundle == nullptr) {
738 return false;
739 }
740 HILOGI("application suspend: bundleName=%{public}s", bundle->name_.c_str());
741 for (auto i = bundle->procs_.begin(); i != bundle->procs_.end(); ++i) {
742 i->second.priority_ = RECLAIM_PRIORITY_SUSPEND;
743 }
744 UpdateBundlePriority(bundle);
745 bool ret = ApplyReclaimPriority(bundle, IGNORE_PID, AppAction::OTHERS);
746 return ret;
747 }
748
UpdateExtensionStatusForTarget(UpdateRequest & request,int64_t eventTime)749 bool ReclaimPriorityManager::UpdateExtensionStatusForTarget(UpdateRequest &request, int64_t eventTime)
750 {
751 ReqProc caller = request.caller;
752 ReqProc target = request.target;
753 int accountId = GetOsAccountIdByUid(target.uid);
754 if (!IsProcExist(target.pid, target.uid, accountId)) {
755 HILOGE("process not exist and not to create it!!");
756 return false;
757 }
758 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
759 std::shared_ptr<BundlePriorityInfo> bundle = account->FindBundleById(target.uid);
760 ProcessPriorityInfo &proc = bundle->FindProcByPid(target.pid);
761
762 if (proc.priority_ <= RECLAIM_PRIORITY_KILLABLE_SYSTEM || bundle->priority_ <= RECLAIM_PRIORITY_KILLABLE_SYSTEM ||
763 IsKillableSystemApp(bundle)) {
764 HILOGD("%{public}s is system app, skip!", target.bundleName.c_str());
765 return true;
766 }
767
768 if (request.reason == AppStateUpdateReason::BIND_EXTENSION) {
769 proc.isFreground = false; // current process is a extension, it never be a fg app.
770 proc.isExtension_ = true;
771 proc.ProcBindToMe(caller.pid, caller.uid);
772 } else if (request.reason == AppStateUpdateReason::UNBIND_EXTENSION) {
773 proc.isFreground = false; // current process is a extension, it never be a fg app.
774 proc.isExtension_ = true;
775 proc.ProcUnBindToMe(caller.pid);
776 }
777 AppAction action = AppAction::OTHERS;
778 HandleUpdateProcess(request.reason, bundle, proc, action, eventTime);
779 return ApplyReclaimPriority(bundle, target.pid, action);
780 }
781
UpdateExtensionStatusForCaller(UpdateRequest & request)782 bool ReclaimPriorityManager::UpdateExtensionStatusForCaller(UpdateRequest &request)
783 {
784 ReqProc caller = request.caller;
785 ReqProc target = request.target;
786 int callerAccountId = GetOsAccountIdByUid(caller.uid);
787 if (!IsProcExist(caller.pid, caller.uid, callerAccountId)) {
788 HILOGE("caller process not exist and not to create it!!");
789 return false;
790 }
791 std::shared_ptr<AccountBundleInfo> callerAccount = FindOsAccountById(callerAccountId);
792 std::shared_ptr<BundlePriorityInfo> callerBundle = callerAccount->FindBundleById(caller.uid);
793 ProcessPriorityInfo &callerProc = callerBundle->FindProcByPid(caller.pid);
794
795 if (request.reason == AppStateUpdateReason::BIND_EXTENSION) {
796 callerProc.ProcBindFromMe(target.pid, target.uid);
797 } else if (request.reason == AppStateUpdateReason::UNBIND_EXTENSION) {
798 callerProc.ProcUnBindFromMe(target.pid);
799 }
800 return true;
801 }
802
GetConnectedExtensionProc(const ProcessPriorityInfo & proc,ProcInfoVec & procVec)803 void ReclaimPriorityManager::GetConnectedExtensionProc(const ProcessPriorityInfo &proc, ProcInfoVec &procVec)
804 {
805 std::set<int32_t> isExtensionProcVisitedSet;
806 std::queue<ProcessPriorityInfo> extensionProcQue;
807 extensionProcQue.push(proc);
808
809 while (!extensionProcQue.empty()) {
810 ProcessPriorityInfo extensionProc(extensionProcQue.front());
811 extensionProcQue.pop();
812 if (isExtensionProcVisitedSet.count(extensionProc.pid_)) {
813 continue;
814 }
815 if (extensionProc.isExtension_) {
816 procVec.push_back(extensionProc);
817 isExtensionProcVisitedSet.insert(extensionProc.pid_);
818 }
819
820 for (const auto &pair : extensionProc.procsBindFromMe_) {
821 if (isExtensionProcVisitedSet.count(pair.first)) {
822 continue;
823 }
824 int accountId = GetOsAccountIdByUid(pair.second);
825 if (!IsProcExist(pair.first, pair.second, accountId)) {
826 continue;
827 }
828 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
829 std::shared_ptr<BundlePriorityInfo> bundle = account->FindBundleById(pair.second);
830 ProcessPriorityInfo &procBindFromMe = bundle->FindProcByPid(pair.first);
831 extensionProcQue.push(procBindFromMe);
832 }
833 }
834 }
835
CalculateExtensionProcPrio(ProcInfoVec & procVec,ProcInfoSet & procSet)836 void ReclaimPriorityManager::CalculateExtensionProcPrio(ProcInfoVec &procVec, ProcInfoSet &procSet)
837 {
838 for (auto &extensionProc : procVec) {
839 int32_t minExtensionPriority = RECLAIM_PRIORITY_BACKGROUND;
840 for (const auto &connectorProcPair : extensionProc.procsBindToMe_) {
841 int accountId = GetOsAccountIdByUid(connectorProcPair.second);
842 if (!IsProcExist(connectorProcPair.first, connectorProcPair.second, accountId)) {
843 minExtensionPriority = 0;
844 continue;
845 }
846
847 std::shared_ptr<AccountBundleInfo> connectorAccount = FindOsAccountById(accountId);
848 std::shared_ptr<BundlePriorityInfo> bundle = connectorAccount->FindBundleById(connectorProcPair.second);
849 ProcessPriorityInfo &procBindToMe = bundle->FindProcByPid(connectorProcPair.first);
850 minExtensionPriority =
851 minExtensionPriority < procBindToMe.priority_ ? minExtensionPriority : procBindToMe.priority_;
852 }
853
854 extensionProc.priority_ = minExtensionPriority;
855 procSet.insert(extensionProc);
856 }
857 }
858
SetConnectExtensionProcPrio(const ProcInfoSet & procSet)859 void ReclaimPriorityManager::SetConnectExtensionProcPrio(const ProcInfoSet &procSet)
860 {
861 int32_t deltaPriority = 100;
862 for (const auto &extensionProcess : procSet) {
863 int32_t minExtensionPriority = RECLAIM_PRIORITY_BACKGROUND;
864 for (const auto &connectorProcPair : extensionProcess.procsBindToMe_) {
865 int accountId = GetOsAccountIdByUid(connectorProcPair.second);
866 if (!IsProcExist(connectorProcPair.first, connectorProcPair.second, accountId)) {
867 minExtensionPriority = 0;
868 continue;
869 }
870 std::shared_ptr<AccountBundleInfo> connectorAccount = FindOsAccountById(accountId);
871 std::shared_ptr<BundlePriorityInfo> bundle = connectorAccount->FindBundleById(connectorProcPair.second);
872 ProcessPriorityInfo &procBindToMe = bundle->FindProcByPid(connectorProcPair.first);
873 int32_t procBindToMePrio = procBindToMe.priority_ < 0 ? 0 : procBindToMe.priority_;
874 minExtensionPriority =
875 minExtensionPriority < procBindToMePrio ? minExtensionPriority : procBindToMePrio;
876 }
877
878 int extensionAccountId = GetOsAccountIdByUid(extensionProcess.uid_);
879 if (!IsProcExist(extensionProcess.pid_, extensionProcess.uid_, extensionAccountId)) {
880 continue;
881 }
882
883 std::shared_ptr<AccountBundleInfo> extensionAccount = FindOsAccountById(extensionAccountId);
884 std::shared_ptr<BundlePriorityInfo> extensionBundle = extensionAccount->FindBundleById(extensionProcess.uid_);
885 ProcessPriorityInfo &procExtensionUpdate = extensionBundle->FindProcByPid(extensionProcess.pid_);
886 int priorityAsApp = GetPriorityByProcStatus(procExtensionUpdate);
887 int priorityAsExtension = minExtensionPriority + deltaPriority;
888 int minPriority = priorityAsApp < priorityAsExtension ? priorityAsApp : priorityAsExtension;
889 procExtensionUpdate.SetPriority(minPriority);
890 if (procExtensionUpdate.isImportant_) {
891 SetImportantProcPriority(procExtensionUpdate);
892 }
893 UpdateBundlePriority(extensionBundle);
894 OomScoreAdjUtils::WriteOomScoreAdjToKernel(procExtensionUpdate.pid_, procExtensionUpdate.priority_);
895 }
896 }
897
GetPriorityByProcStatus(const ProcessPriorityInfo & proc)898 int ReclaimPriorityManager::GetPriorityByProcStatus(const ProcessPriorityInfo &proc)
899 {
900 int priority = RECLAIM_PRIORITY_UNKNOWN;
901
902 if (!proc.isFreground && proc.hasUI_) {
903 priority = RECLAIM_PRIORITY_BACKGROUND;
904 }
905 if (proc.isFreground) {
906 priority = RECLAIM_PRIORITY_FOREGROUND;
907 } else if (proc.isVisible_) {
908 priority = RECLAIM_PRIORITY_VISIBLE;
909 } else if (proc.isSuspendDelay) {
910 priority = RECLAIM_PRIORITY_BG_SUSPEND_DELAY;
911 } else if (proc.isBackgroundRunning || proc.isEventStart) {
912 priority = RECLAIM_PRIORITY_BG_PERCEIVED;
913 } else if (proc.isDistDeviceConnected) {
914 priority = RECLAIM_PRIORITY_BG_DIST_DEVICE;
915 }
916
917 if (proc.isImportant_) {
918 if (proc.priority_ >= proc.priorityIfImportant_) {
919 priority = proc.priorityIfImportant_;
920 }
921 }
922
923 return priority;
924 }
925
HandleExtensionProcess(UpdateRequest & request,int64_t eventTime)926 bool ReclaimPriorityManager::HandleExtensionProcess(UpdateRequest &request, int64_t eventTime)
927 {
928 UpdateExtensionStatusForCaller(request);
929 return UpdateExtensionStatusForTarget(request, eventTime);
930 }
931
932
UpdateReclaimPriorityInner(UpdateRequest request,int64_t eventTime)933 bool ReclaimPriorityManager::UpdateReclaimPriorityInner(UpdateRequest request, int64_t eventTime)
934 {
935 // This function can only be called by UpdateReclaimPriority, otherwise it may deadlock.
936 std::lock_guard<std::mutex> setLock(totalBundlePrioSetLock_);
937 ReqProc target = request.target;
938 int accountId = GetOsAccountIdByUid(target.uid);
939 HILOGD("accountId=%{public}d", accountId);
940
941 if (request.reason == AppStateUpdateReason::BIND_EXTENSION ||
942 request.reason == AppStateUpdateReason::UNBIND_EXTENSION) {
943 return HandleExtensionProcess(request, eventTime);
944 }
945
946 if (request.reason == AppStateUpdateReason::CREATE_PROCESS) {
947 return HandleCreateProcess(target, accountId);
948 }
949
950 if (request.reason == AppStateUpdateReason::RENDER_CREATE_PROCESS) {
951 return HandleCreateProcess(target, accountId, true);
952 }
953
954 if (request.reason == AppStateUpdateReason::ABILITY_START) {
955 return HandleAbilityStart(request, eventTime);
956 }
957
958 if (!IsProcExist(target.pid, target.uid, accountId)) {
959 HILOGE("process not exist and not to create it!!");
960 return false;
961 }
962 std::shared_ptr<AccountBundleInfo> account = FindOsAccountById(accountId);
963 std::shared_ptr<BundlePriorityInfo> bundle = account->FindBundleById(target.uid);
964 if (bundle->priority_ <= RECLAIM_PRIORITY_KILLABLE_SYSTEM) {
965 HILOGI("%{public}s is system app, skip!", target.bundleName.c_str());
966 return true;
967 }
968
969 if (request.reason == AppStateUpdateReason::APPLICATION_SUSPEND) {
970 return HandleApplicationSuspend(bundle);
971 }
972
973 ProcessPriorityInfo &proc = bundle->FindProcByPid(target.pid);
974 AppAction action = AppAction::OTHERS;
975 if (request.reason == AppStateUpdateReason::PROCESS_TERMINATED) {
976 return HandleTerminateProcess(proc, bundle, account);
977 } else {
978 HandleUpdateProcess(request.reason, bundle, proc, action, eventTime);
979 }
980 return ApplyReclaimPriority(bundle, target.pid, action);
981 }
982
IsImportantProc(const std::string procName,int & dstPriority)983 bool ReclaimPriorityManager::IsImportantProc(const std::string procName, int &dstPriority)
984 {
985 std::map<std::string, int> importantProcs = config_.GetImportantBgApps();
986 if (importantProcs.count(procName)) {
987 dstPriority = importantProcs.at(procName);
988 HILOGD("is an important proc, procName=%{public}s, importPriority=%{public}d", procName.c_str(), dstPriority);
989 return true;
990 }
991 return false;
992 }
993
SetImportantProcPriority(ProcessPriorityInfo & proc)994 void ReclaimPriorityManager::SetImportantProcPriority(ProcessPriorityInfo &proc)
995 {
996 if (proc.priority_ > proc.priorityIfImportant_) {
997 proc.priority_ = proc.priorityIfImportant_;
998 }
999 }
1000
UpdatePriorityByProcForExtension(ProcessPriorityInfo & proc)1001 void ReclaimPriorityManager::UpdatePriorityByProcForExtension(ProcessPriorityInfo &proc)
1002 {
1003 ProcInfoVec allConnectedExtensionProcVec;
1004 GetConnectedExtensionProc(proc, allConnectedExtensionProcVec);
1005 if (allConnectedExtensionProcVec.size() == 0) {
1006 return;
1007 }
1008 ProcInfoSet allConnectedExtensionProcSet;
1009 CalculateExtensionProcPrio(allConnectedExtensionProcVec, allConnectedExtensionProcSet);
1010
1011 SetConnectExtensionProcPrio(allConnectedExtensionProcSet);
1012 }
1013
UpdatePriorityByProcConnector(ProcessPriorityInfo & proc)1014 void ReclaimPriorityManager::UpdatePriorityByProcConnector(ProcessPriorityInfo &proc)
1015 {
1016 if (proc.procsBindFromMe_.size() == 0) {
1017 return;
1018 }
1019 proc.SetPriority(RECLAIM_PRIORITY_BACKGROUND);
1020 int minPriority = RECLAIM_PRIORITY_UNKNOWN;
1021 for (auto &pair : proc.procsBindFromMe_) {
1022 int32_t connectorUid = pair.second;
1023 int connectorAccountId = GetOsAccountIdByUid(connectorUid);
1024 std::shared_ptr<AccountBundleInfo> connectorAccount = FindOsAccountById(connectorAccountId);
1025 if (connectorAccount == nullptr || !connectorAccount->HasBundle(connectorUid)) {
1026 minPriority = 0; // native
1027 continue;
1028 }
1029 std::shared_ptr<BundlePriorityInfo> connectorBundle = connectorAccount->FindBundleById(connectorUid);
1030 if (connectorBundle == nullptr) {
1031 return;
1032 }
1033 for (auto procEntry : connectorBundle->procs_) {
1034 ProcessPriorityInfo &connectorProc = procEntry.second;
1035 minPriority = connectorProc.priority_ < minPriority ? connectorProc.priority_ : minPriority;
1036 }
1037 }
1038 proc.SetPriority(minPriority + 100); // raise the priority of the lowest-priority process by 100
1039 }
1040
UpdatePriorityByProcStatus(std::shared_ptr<BundlePriorityInfo> bundle,ProcessPriorityInfo & proc)1041 void ReclaimPriorityManager::UpdatePriorityByProcStatus(std::shared_ptr<BundlePriorityInfo> bundle,
1042 ProcessPriorityInfo &proc)
1043 {
1044 if (bundle->priority_ < RECLAIM_PRIORITY_FOREGROUND) { // is a system process
1045 return;
1046 }
1047 if (proc.isRender_) { // priority of render follow its host and it is updated by action of its host
1048 return;
1049 }
1050 if (proc.isFreground) { // is a freground process
1051 if (proc.priority_ > RECLAIM_PRIORITY_FOREGROUND) {
1052 proc.SetPriority(RECLAIM_PRIORITY_FOREGROUND);
1053 }
1054 } else if (!proc.isExtension_) { // is a background process
1055 proc.SetPriority(RECLAIM_PRIORITY_BACKGROUND);
1056 }
1057 if (proc.isVisible_) {
1058 if (proc.priority_ > RECLAIM_PRIORITY_VISIBLE) {
1059 proc.SetPriority(RECLAIM_PRIORITY_VISIBLE);
1060 }
1061 }
1062 if (proc.isSuspendDelay) { // is a background process with transient task
1063 if (proc.priority_ > RECLAIM_PRIORITY_BG_SUSPEND_DELAY) {
1064 proc.SetPriority(RECLAIM_PRIORITY_BG_SUSPEND_DELAY);
1065 }
1066 } else if (proc.isBackgroundRunning || proc.isEventStart) {
1067 // is a background perceived process
1068 if (proc.priority_ > RECLAIM_PRIORITY_BG_PERCEIVED) {
1069 proc.SetPriority(RECLAIM_PRIORITY_BG_PERCEIVED);
1070 }
1071 } else if (proc.isDistDeviceConnected) { // is a background process connected by distribute device
1072 if (proc.priority_ > RECLAIM_PRIORITY_BG_DIST_DEVICE) {
1073 proc.SetPriority(RECLAIM_PRIORITY_BG_DIST_DEVICE);
1074 }
1075 } else {
1076 // is a plain background process
1077 }
1078
1079 if (proc.isImportant_) {
1080 SetImportantProcPriority(proc);
1081 }
1082 UpdateBundlePriority(bundle);
1083 UpdatePriorityByProcForExtension(proc);
1084 }
1085
HandleForeground(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1086 void ReclaimPriorityManager::HandleForeground(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1087 {
1088 proc.isFreground = true;
1089 proc.hasUI_ = true;
1090 action = AppAction::APP_FOREGROUND;
1091 FinishAbilityStartIfNeed(proc, AppStateUpdateReason::FOREGROUND, eventTime);
1092 }
1093
HandleBackground(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1094 void ReclaimPriorityManager::HandleBackground(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1095 {
1096 proc.isFreground = false;
1097 proc.hasUI_ = true;
1098 action = AppAction::APP_BACKGROUND;
1099 FinishAbilityStartIfNeed(proc, AppStateUpdateReason::BACKGROUND, eventTime);
1100 }
1101
HandleSuspendDelayStart(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1102 void ReclaimPriorityManager::HandleSuspendDelayStart(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1103 {
1104 proc.isSuspendDelay = true;
1105 }
1106
HandleSuspendDelayEnd(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1107 void ReclaimPriorityManager::HandleSuspendDelayEnd(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1108 {
1109 proc.isSuspendDelay = false;
1110 }
1111
HandleBackgroundRunningStart(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1112 void ReclaimPriorityManager::HandleBackgroundRunningStart(ProcessPriorityInfo &proc, AppAction &action,
1113 int64_t eventTime)
1114 {
1115 proc.isBackgroundRunning = true;
1116 }
1117
HandleBackgroundRunningEnd(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1118 void ReclaimPriorityManager::HandleBackgroundRunningEnd(ProcessPriorityInfo &proc, AppAction &action,
1119 int64_t eventTime)
1120 {
1121 proc.isBackgroundRunning = false;
1122 }
1123
HandleEventStart(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1124 void ReclaimPriorityManager::HandleEventStart(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1125 {
1126 proc.isEventStart = true;
1127 }
1128
HandleEventEnd(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1129 void ReclaimPriorityManager::HandleEventEnd(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1130 {
1131 proc.isEventStart = false;
1132 }
1133
HandleDistDeviceConnected(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1134 void ReclaimPriorityManager::HandleDistDeviceConnected(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1135 {
1136 proc.isDistDeviceConnected = true;
1137 }
1138
HandleDistDeviceDisconnected(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1139 void ReclaimPriorityManager::HandleDistDeviceDisconnected(ProcessPriorityInfo &proc, AppAction &action,
1140 int64_t eventTime)
1141 {
1142 proc.isDistDeviceConnected = false;
1143 }
1144
HandleBindExtension(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1145 void ReclaimPriorityManager::HandleBindExtension(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1146 {
1147 if (proc.ExtensionConnectorsCount() > 0) {
1148 proc.extensionBindStatus = EXTENSION_STATUS_FG_BIND;
1149 }
1150 }
1151
HandleUnbindExtension(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1152 void ReclaimPriorityManager::HandleUnbindExtension(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1153 {
1154 if (proc.ExtensionConnectorsCount() == 0) {
1155 proc.extensionBindStatus = EXTENSION_STATUS_NO_BIND;
1156 }
1157 }
1158
HandleVisible(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1159 void ReclaimPriorityManager::HandleVisible(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1160 {
1161 proc.isVisible_ = true;
1162 }
1163
HandleUnvisible(ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1164 void ReclaimPriorityManager::HandleUnvisible(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1165 {
1166 proc.isVisible_ = false;
1167 }
1168
InitChangeProcMapping()1169 void ReclaimPriorityManager::InitChangeProcMapping()
1170 {
1171 changeProcMapping_[AppStateUpdateReason::FOREGROUND] = &ReclaimPriorityManager::HandleForeground;
1172 changeProcMapping_[AppStateUpdateReason::BACKGROUND] = &ReclaimPriorityManager::HandleBackground;
1173 changeProcMapping_[AppStateUpdateReason::SUSPEND_DELAY_START] = &ReclaimPriorityManager::HandleSuspendDelayStart;
1174 changeProcMapping_[AppStateUpdateReason::SUSPEND_DELAY_END] = &ReclaimPriorityManager::HandleSuspendDelayEnd;
1175 changeProcMapping_[AppStateUpdateReason::BACKGROUND_RUNNING_START] =
1176 &ReclaimPriorityManager::HandleBackgroundRunningStart;
1177 changeProcMapping_[AppStateUpdateReason::BACKGROUND_RUNNING_END] =
1178 &ReclaimPriorityManager::HandleBackgroundRunningEnd;
1179 changeProcMapping_[AppStateUpdateReason::EVENT_START] = &ReclaimPriorityManager::HandleEventStart;
1180 changeProcMapping_[AppStateUpdateReason::EVENT_END] = &ReclaimPriorityManager::HandleEventEnd;
1181 changeProcMapping_[AppStateUpdateReason::DIST_DEVICE_CONNECTED] =
1182 &ReclaimPriorityManager::HandleDistDeviceConnected;
1183 changeProcMapping_[AppStateUpdateReason::DIST_DEVICE_DISCONNECTED] =
1184 &ReclaimPriorityManager::HandleDistDeviceDisconnected;
1185 changeProcMapping_[AppStateUpdateReason::BIND_EXTENSION] = &ReclaimPriorityManager::HandleBindExtension;
1186 changeProcMapping_[AppStateUpdateReason::UNBIND_EXTENSION] = &ReclaimPriorityManager::HandleUnbindExtension;
1187 changeProcMapping_[AppStateUpdateReason::VISIBLE] = &ReclaimPriorityManager::HandleVisible;
1188 changeProcMapping_[AppStateUpdateReason::UN_VISIBLE] = &ReclaimPriorityManager::HandleUnvisible;
1189 }
1190
1191
HandleUpdateProcess(AppStateUpdateReason reason,std::shared_ptr<BundlePriorityInfo> bundle,ProcessPriorityInfo & proc,AppAction & action,int64_t eventTime)1192 void ReclaimPriorityManager::HandleUpdateProcess(AppStateUpdateReason reason,
1193 std::shared_ptr<BundlePriorityInfo> bundle, ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime)
1194 {
1195 HILOGD("called, bundle[uid_=%{public}d,name=%{public}s,priority=%{public}d], proc[pid_=%{public}d, uid=%{public}d,"
1196 "isFreground=%{public}d, isBackgroundRunning=%{public}d, isSuspendDelay=%{public}d, isEventStart=%{public}d,"
1197 "isDistDeviceConnected=%{public}d, extensionBindStatus=%{public}d, priority=%{public}d], case:%{public}s",
1198 bundle->uid_, bundle->name_.c_str(), bundle->priority_, proc.pid_, proc.uid_, proc.isFreground,
1199 proc.isBackgroundRunning, proc.isSuspendDelay, proc.isEventStart, proc.isDistDeviceConnected,
1200 proc.extensionBindStatus, proc.priority_, AppStateUpdateResonToString(reason).c_str());
1201 auto it = changeProcMapping_.find(reason);
1202 if (it != changeProcMapping_.end()) {
1203 auto changeProcPtr = it->second;
1204 (this->*changeProcPtr)(proc, action, eventTime);
1205 }
1206
1207 if (NeedSkipEventBeforeAbilityStart(proc, reason, eventTime)) {
1208 HILOGI("this event<pid=%{public}d,uid=%{public}d,reason=%{public}s> should execute befor startAbility event,\
1209 skip update priority.", proc.pid_, proc.uid_, AppStateUpdateResonToString(reason).c_str());
1210 return;
1211 }
1212 UpdatePriorityByProcStatus(bundle, proc);
1213 }
1214
ApplyReclaimPriority(std::shared_ptr<BundlePriorityInfo> bundle,pid_t pid,AppAction action)1215 bool ReclaimPriorityManager::ApplyReclaimPriority(std::shared_ptr<BundlePriorityInfo> bundle,
1216 pid_t pid, AppAction action)
1217 {
1218 HILOGD("called");
1219 if (bundle == nullptr) {
1220 HILOGD("bundle is nullptr");
1221 return false;
1222 }
1223 #ifdef USE_HYPERHOLD_MEMORY
1224 DECLARE_SHARED_POINTER(ReclaimParam, para);
1225 MAKE_POINTER(para, shared, ReclaimParam, "make ReclaimParam failed", return false,
1226 pid, bundle->uid_, bundle->name_, bundle->accountId_, bundle->priority_, action);
1227 ReclaimStrategyManager::GetInstance().NotifyAppStateChanged(para);
1228 #endif
1229 return OomScoreAdjUtils::WriteOomScoreAdjToKernel(bundle);
1230 }
1231
OsAccountChanged(int accountId,AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)1232 bool ReclaimPriorityManager::OsAccountChanged(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)
1233 {
1234 if (!initialized_) {
1235 HILOGE("has not been initialized_, skiped!");
1236 return false;
1237 }
1238 if (accountId < 0) {
1239 HILOGE("invalid account id!");
1240 return false;
1241 }
1242 return handler_->PostImmediateTask([this, accountId, switchMod] {
1243 this->OsAccountChangedInner(accountId, switchMod);
1244 });
1245 }
1246
OsAccountChangedInner(int accountId,AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)1247 bool ReclaimPriorityManager::OsAccountChangedInner(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)
1248 {
1249 return UpdateAllPrioForOsAccountChanged(accountId, switchMod);
1250 }
1251
UpdateAllPrioForOsAccountChanged(int accountId,AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)1252 bool ReclaimPriorityManager::UpdateAllPrioForOsAccountChanged(int accountId,
1253 AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod)
1254 {
1255 if (!initialized_) {
1256 HILOGE("has not been initialized_, skiped!");
1257 return false;
1258 }
1259 HILOGI("UpdateReclaimPriority for all apps because of os account changed ");
1260 bool ret = MultiAccountManager::GetInstance().HandleOsAccountsChanged(accountId, switchMod, osAccountsInfoMap_);
1261 return ret;
1262 }
1263
Reset()1264 void ReclaimPriorityManager::Reset()
1265 {
1266 // add locks
1267 std::lock_guard<std::mutex> setLock(totalBundlePrioSetLock_);
1268
1269 HILOGI("clear totalBundlePrioSet(size: %{public}zu) and osAccountslnfoMap(size: %{public}zu) ",
1270 totalBundlePrioSet_.size(), osAccountsInfoMap_.size());
1271 totalBundlePrioSet_.clear();
1272 osAccountsInfoMap_.clear();
1273 }
1274
CheckCurrentEventHappenedBeforeAbilityStart(const ProcessPriorityInfo & proc,AppStateUpdateReason reason,int64_t eventTime)1275 bool ReclaimPriorityManager::CheckCurrentEventHappenedBeforeAbilityStart(const ProcessPriorityInfo &proc,
1276 AppStateUpdateReason reason, int64_t eventTime)
1277 {
1278 if (eventTime == INVALID_TIME) {
1279 return false;
1280 }
1281 if (eventTime < proc.GetStartingAbilityTime()) {
1282 return true;
1283 }
1284 return false;
1285 }
1286
RemoveTimerForAbilityStartCompletedCheck(const ProcessPriorityInfo & proc)1287 void ReclaimPriorityManager::RemoveTimerForAbilityStartCompletedCheck(const ProcessPriorityInfo &proc)
1288 {
1289 if (handler_ == nullptr) {
1290 return;
1291 }
1292 handler_->RemoveTask(std::to_string(proc.pid_) +
1293 AppStateUpdateResonToString(AppStateUpdateReason::ABILITY_START));
1294 }
1295
1296 // set priority of proc to RECLAIM_PRIORITY_FOREGROUND when proc is starting ability
AbilityStartingBegin(ProcessPriorityInfo & proc,std::shared_ptr<BundlePriorityInfo> bundle,int64_t eventTime)1297 void ReclaimPriorityManager::AbilityStartingBegin(ProcessPriorityInfo &proc, std::shared_ptr<BundlePriorityInfo> bundle,
1298 int64_t eventTime)
1299 {
1300 if (bundle == nullptr) {
1301 return;
1302 }
1303 // set priority to RECLAIM_PRIORITY_FOREGROUND
1304 proc.SetPriority(RECLAIM_PRIORITY_FOREGROUND);
1305 proc.SetStartingAbilityTime(eventTime);
1306 proc.SetIsAbilityStarting(true);
1307
1308 UpdateBundlePriority(bundle);
1309 ApplyReclaimPriority(bundle, proc.pid_, AppAction::OTHERS);
1310 }
1311
AbilityStartingEnd(ProcessPriorityInfo & proc,std::shared_ptr<BundlePriorityInfo> bundle,bool isUpdatePriority)1312 void ReclaimPriorityManager::AbilityStartingEnd(ProcessPriorityInfo &proc, std::shared_ptr<BundlePriorityInfo> bundle,
1313 bool isUpdatePriority)
1314 {
1315 proc.SetIsAbilityStarting(false);
1316
1317 // update priority based on process's status if need
1318 if (isUpdatePriority && bundle != nullptr) {
1319 int32_t beforePriority = proc.priority_;
1320 UpdatePriorityByProcStatus(bundle, proc);
1321 ApplyReclaimPriority(bundle, proc.pid_, AppAction::OTHERS);
1322 HILOGI("check process<pid=%{public}d,uid=%{public}d>, beforePrio=%{public}d, set currentPrio:%{public}d!",
1323 proc.pid_, proc.uid_, beforePriority, proc.priority_);
1324 }
1325 }
1326
FinishAbilityStartIfNeed(ProcessPriorityInfo & proc,AppStateUpdateReason reason,int64_t eventTime)1327 void ReclaimPriorityManager::FinishAbilityStartIfNeed(ProcessPriorityInfo &proc, AppStateUpdateReason reason,
1328 int64_t eventTime)
1329 {
1330 if (CheckAbilityStartNeedFinishInAdvance(proc, reason, eventTime)) {
1331 RemoveTimerForAbilityStartCompletedCheck(proc);
1332 AbilityStartingEnd(proc);
1333 }
1334 }
1335
CheckAbilityStartNeedFinishInAdvance(const ProcessPriorityInfo & proc,AppStateUpdateReason reason,int64_t eventTime)1336 bool ReclaimPriorityManager::CheckAbilityStartNeedFinishInAdvance(const ProcessPriorityInfo &proc,
1337 AppStateUpdateReason reason, int64_t eventTime)
1338 {
1339 return proc.IsAbilityStarting() && !CheckCurrentEventHappenedBeforeAbilityStart(proc, reason, eventTime);
1340 }
1341
NeedSkipEventBeforeAbilityStart(const ProcessPriorityInfo & proc,AppStateUpdateReason reason,int64_t eventTime)1342 bool ReclaimPriorityManager::NeedSkipEventBeforeAbilityStart(const ProcessPriorityInfo &proc,
1343 AppStateUpdateReason reason, int64_t eventTime)
1344 {
1345 return proc.IsAbilityStarting() && CheckCurrentEventHappenedBeforeAbilityStart(proc, reason, eventTime);
1346 }
1347 } // namespace Memory
1348 } // namespace OHOS