• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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