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 #ifndef OHOS_MEMORY_MEMMGR_RECALIM_PRIORITY_MANAGER_H
17 #define OHOS_MEMORY_MEMMGR_RECALIM_PRIORITY_MANAGER_H
18 
19 #include "single_instance.h"
20 #include "event_handler.h"
21 #include "reclaim_priority_constants.h"
22 #include "process_priority_info.h"
23 #include "bundle_priority_info.h"
24 #include "account_bundle_info.h"
25 #include "os_account_manager.h"
26 #include "reclaim_param.h"
27 #include "memmgr_config_manager.h"
28 
29 #include <map>
30 #include <mutex>
31 #include <queue>
32 #include <string>
33 #include <set>
34 
35 namespace OHOS {
36 namespace Memory {
37 struct ReclaimHandleRequest {
38     int32_t callerPid;
39     int32_t callerUid;
40     pid_t pid;
41     int uid;
42     std::string callerBundleName;
43     std::string bundleName;
44     AppStateUpdateReason reason;
45 };
46 
47 struct ReqProc {
48     int pid;
49     int uid;
50     std::string processName;
51     std::string bundleName;
52 };
53 
54 struct UpdateRequest {
55     ReqProc caller;
56     ReqProc target;
57     AppStateUpdateReason reason;
58 };
59 
SingleRequest(const ReqProc & target,AppStateUpdateReason reason)60 inline UpdateRequest SingleRequest(const ReqProc &target, AppStateUpdateReason reason)
61 {
62     UpdateRequest request;
63     request.target = target;
64     request.reason = reason;
65     return request;
66 }
67 
CallerRequest(const ReqProc & caller,const ReqProc & target,AppStateUpdateReason reason)68 inline UpdateRequest CallerRequest(const ReqProc &caller, const ReqProc &target, AppStateUpdateReason reason)
69 {
70     UpdateRequest request;
71     request.caller = caller;
72     request.target = target;
73     request.reason = reason;
74     return request;
75 }
76 
77 class ReclaimPriorityManager {
78     DECLARE_SINGLE_INSTANCE_BASE(ReclaimPriorityManager);
79 
80 public:
81     struct BundleInfoPtrCmp {
operatorBundleInfoPtrCmp82         bool operator() (const std::shared_ptr<BundlePriorityInfo> p1, const std::shared_ptr<BundlePriorityInfo> p2)
83         {
84             if (p1->uid_ == p2->uid_) {
85                 // remove duplicate BundlePriorityInfo according to uid_
86                 return false;
87             } else {
88                 if (p1->priority_ != p2->priority_) {
89                     // in ascending order
90                     return p1->priority_ < p2->priority_;
91                 } else {
92                     // when in same priority_, sort by uid_
93                     // it will be sorted by last used time
94                     return p1->uid_ < p2->uid_;
95                 }
96             }
97         }
98     };
99 
100     struct BundleInfoCmp {
operatorBundleInfoCmp101         bool operator() (const BundlePriorityInfo &p1, const BundlePriorityInfo &p2)
102         {
103             if (p1.uid_ == p2.uid_) {
104                 // remove duplicate BundlePriorityInfo according to uid_
105                 return false;
106             } else {
107                 if (p1.priority_ != p2.priority_) {
108                     // in descending order
109                     return p1.priority_ > p2.priority_;
110                 } else {
111                     // when in same priority_, sort by uid_
112                     // it will be sorted by last used time
113                     return p1.uid_ < p2.uid_;
114                 }
115             }
116         }
117     };
118 
119     struct ProcInfoCmpByPriority {
operatorProcInfoCmpByPriority120         bool operator() (const ProcessPriorityInfo &p1, const ProcessPriorityInfo &p2)
121         {
122             if (p1.pid_ == p2.pid_) {
123                 return false;
124             } else {
125                 if (p1.priority_ != p2.priority_) {
126                     return p1.priority_ < p2.priority_;
127                 }
128 
129                 return p1.pid_ < p2.pid_;
130             }
131         }
132     };
133 
134     using BundlePrioSet = std::set<std::shared_ptr<BundlePriorityInfo>, BundleInfoPtrCmp>;
135     using BunldeCopySet = std::set<BundlePriorityInfo, BundleInfoCmp>;
136     // map <bundleUid, std::shared_ptr<BundlePriorityInfo>>
137     using BundlePrioMap = std::map<int, std::shared_ptr<BundlePriorityInfo>>;
138     using OsAccountsMap = std::map<int, std::shared_ptr<AccountBundleInfo>>;
139     using ProcInfoVec = std::vector<ProcessPriorityInfo>;
140     using ProcInfoSet = std::set<ProcessPriorityInfo, ProcInfoCmpByPriority>;
141     bool Init();
142     bool UpdateReclaimPriority(UpdateRequest request);
143     bool UpdateRecalimPrioritySyncWithLock(const UpdateRequest &request);
144     bool OsAccountChanged(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod);
145 
Initailized()146     inline bool Initailized()
147     {
148         return initialized_;
149     };
150 
151     // for lmkd and memory reclaim
152     void GetBundlePrioSet(BunldeCopySet &bundleSet);
153 
154     void GetOneKillableBundle(int minPrio, BunldeCopySet &bundleSet);
155 
156     void SetBundleState(int accountId, int uid, BundleState state);
157 
158     // for hidumper, usage: hdc shell hidumper -s 1909
159     void Dump(int fd);
160 
161     void Reset();
162 private:
163     bool initialized_ = false;
164 
165     // map <accountId, accountInfo>
166     OsAccountsMap osAccountsInfoMap_;
167     // total system prioritySet
168     // when new a BundlePriorityInfo, it will be added into this set
169     // when delete a BundlePriorityInfo, it will be removed from this set
170     // when change the priority of BundlePriorityInfo, it will be removed and added from this set to re-sort it
171     BundlePrioSet totalBundlePrioSet_;
172     std::mutex totalBundlePrioSetLock_;
173 
174     std::shared_ptr<AppExecFwk::EventHandler> handler_;
175     std::map<int32_t, std::string> updateReasonStrMapping_;
176     std::string UNKOWN_REASON = "UNKOWN_REASON";
177     ReclaimPriorityConfig config_;
178     std::set<std::string> allKillableSystemApps_;
179     using ChangeProcFunc = void (ReclaimPriorityManager::*)(ProcessPriorityInfo &proc, AppAction &action,
180         int64_t eventTime);
181     std::map<AppStateUpdateReason, ChangeProcFunc> changeProcMapping_;
182 
183     ReclaimPriorityManager();
184     void InitUpdateReasonStrMapping();
185     void InitChangeProcMapping();
186     bool GetEventHandler();
187     void UpdateForegroundApps();
188     bool IsFrontApp(const std::string& pkgName, int32_t uid, int32_t pid);
189     void GetAllKillableSystemApps();
190     void GetKillableSystemAppsFromAms(std::set<std::string> &killableApps);
191     void HandlePreStartedProcs();
192     bool UpdateReclaimPriorityInner(UpdateRequest request, int64_t eventTime = INVALID_TIME);
193     bool HandleExtensionProcess(UpdateRequest &request, int64_t eventTime);
194     bool OsAccountChangedInner(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod);
195     bool UpdateAllPrioForOsAccountChanged(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod);
196     bool ApplyReclaimPriority(std::shared_ptr<BundlePriorityInfo> bundle, pid_t pid, AppAction action);
197     bool IsProcExist(pid_t pid, int bundleUid, int accountId);
198     bool IsOsAccountExist(int accountId);
199     bool HandleCreateProcess(ReqProc &request, int accountId, bool isRender = false);
200     bool HandleTerminateProcess(ProcessPriorityInfo proc, std::shared_ptr<BundlePriorityInfo> bundle,
201             std::shared_ptr<AccountBundleInfo> account);
202     void HandleUpdateProcess(AppStateUpdateReason reason, std::shared_ptr<BundlePriorityInfo> bundle,
203             ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
204     void UpdatePriorityByProcStatus(std::shared_ptr<BundlePriorityInfo> bundle, ProcessPriorityInfo &proc);
205     bool HandleApplicationSuspend(std::shared_ptr<BundlePriorityInfo> bundle);
206     std::shared_ptr<AccountBundleInfo> FindOsAccountById(int accountId);
207     void RemoveOsAccountById(int accountId);
208     void AddOsAccountInfo(std::shared_ptr<AccountBundleInfo> account);
209     bool IsKillableSystemApp(std::shared_ptr<BundlePriorityInfo> bundle);
210     void NotifyKillableSystemAppsAdded(std::set<std::string> &newKillableApps);
211     void SetImportantProcPriority(ProcessPriorityInfo &proc);
212     bool IsImportantProc(const std::string procName, int &dstPriority);
213     bool UpdateExtensionStatusForCaller(UpdateRequest &request);
214     bool UpdateExtensionStatusForTarget(UpdateRequest &request, int64_t eventTime);
215     void UpdatePriorityByProcForExtension(ProcessPriorityInfo &proc);
216     void UpdatePriorityByProcConnector(ProcessPriorityInfo &proc);
217     void SetTimerForDiedProcessCheck(int64_t delayTime);
218     void FilterDiedProcess();
219     void HandleDiedProcessCheck();
220     void HandleDiedExtensionBindToMe(std::map<pid_t, ProcessPriorityInfo>::iterator processPriorityInfoMap,
221         const std::vector<unsigned int> &alivePids);
222     void HandleDiedExtensionBindFromMe(std::map<pid_t, ProcessPriorityInfo>::iterator processPriorityInfoMap,
223         const std::vector<unsigned int> &alivePids);
224     void GetConnectedExtensionProc(const ProcessPriorityInfo &proc, ProcInfoVec &procVec);
225     void CalculateExtensionProcPrio(ProcInfoVec &proc, ProcInfoSet &procSet);
226     void SetConnectExtensionProcPrio(const ProcInfoSet &procSet);
227 
228     // two methods below used to manage totalBundlePrioSet_ by BundlePriorityInfo
229     void AddBundleInfoToSet(std::shared_ptr<BundlePriorityInfo> bundle);
230     void UpdateBundlePriority(std::shared_ptr<BundlePriorityInfo> bundle);
231     void DeleteBundleInfoFromSet(std::shared_ptr<BundlePriorityInfo> bundle);
232 
233     std::string& AppStateUpdateResonToString(AppStateUpdateReason reason);
234 
235     void HandleForeground(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
236     void HandleBackground(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
237     void HandleSuspendDelayStart(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
238     void HandleSuspendDelayEnd(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
239     void HandleBackgroundRunningStart(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
240     void HandleBackgroundRunningEnd(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
241     void HandleEventStart(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
242     void HandleEventEnd(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
243     void HandleDistDeviceConnected(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
244     void HandleDistDeviceDisconnected(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
245     void HandleBindExtension(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
246     void HandleUnbindExtension(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
247     void HandleVisible(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
248     void HandleUnvisible(ProcessPriorityInfo &proc, AppAction &action, int64_t eventTime);
249 
250     // these methods below used to check ability start completely
251     bool HandleAbilityStart(const UpdateRequest &request, int64_t eventTime);
252     bool CheckSatifyAbilityStartCondition(const ProcessPriorityInfo &proc);
253     void CheckAbilityStartCompleted(pid_t pid, int32_t bundleUid, int32_t accountId);
254     void SetTimerForAbilityStartCompletedCheck(pid_t pid, int32_t bundleUid, int32_t accountId);
255     void RemoveTimerForAbilityStartCompletedCheck(const ProcessPriorityInfo &proc);
256     void FinishAbilityStartIfNeed(ProcessPriorityInfo &proc, AppStateUpdateReason reason, int64_t eventTime);
257     bool CheckAbilityStartNeedFinishInAdvance(const ProcessPriorityInfo &proc, AppStateUpdateReason reason,
258         int64_t eventTime);
259     bool CheckCurrentEventHappenedBeforeAbilityStart(const ProcessPriorityInfo &proc, AppStateUpdateReason reason,
260         int64_t eventTime);
261     bool NeedSkipEventBeforeAbilityStart(const ProcessPriorityInfo &proc, AppStateUpdateReason reason,
262         int64_t eventTime);
263     void AbilityStartingBegin(ProcessPriorityInfo &proc, std::shared_ptr<BundlePriorityInfo> bundle,
264         int64_t eventTime);
265     void AbilityStartingEnd(ProcessPriorityInfo &proc, std::shared_ptr<BundlePriorityInfo> bundle = nullptr,
266         bool isUpdatePriority = false);
267     void CheckCreateProcPriorityDelay(pid_t pid, int uid);
268 };
269 } // namespace Memory
270 } // namespace OHOS
271 #endif // OHOS_MEMORY_MEMMGR_RECALIM_PRIORITY_MANAGER_H
272