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