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