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