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