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 <string>
32 #include <set>
33
34 namespace OHOS {
35 namespace Memory {
36 struct ReclaimHandleRequest {
37 int32_t callerPid;
38 int32_t callerUid;
39 pid_t pid;
40 int uid;
41 std::string callerBundleName;
42 std::string bundleName;
43 AppStateUpdateReason reason;
44 };
45
SingleRequest(int pid,int uid,const std::string & bundleName,AppStateUpdateReason reason)46 inline ReclaimHandleRequest SingleRequest(int pid, int uid, const std::string &bundleName, AppStateUpdateReason reason)
47 {
48 ReclaimHandleRequest request;
49 request.pid = pid;
50 request.uid = uid;
51 request.bundleName = bundleName;
52 request.reason = reason;
53 return request;
54 }
55
56 class ReclaimPriorityManager {
57 DECLARE_SINGLE_INSTANCE_BASE(ReclaimPriorityManager);
58
59 public:
60 struct BundleInfoPtrCmp {
operatorBundleInfoPtrCmp61 bool operator() (const std::shared_ptr<BundlePriorityInfo> p1, const std::shared_ptr<BundlePriorityInfo> p2)
62 {
63 if (p1->uid_ == p2->uid_) {
64 // remove duplicate BundlePriorityInfo according to uid_
65 return false;
66 } else {
67 if (p1->priority_ != p2->priority_) {
68 // in ascending order
69 return p1->priority_ < p2->priority_;
70 } else {
71 // when in same priority_, sort by uid_
72 // it will be sorted by last used time
73 return p1->uid_ < p2->uid_;
74 }
75 }
76 }
77 };
78 struct BundleInfoCmp {
operatorBundleInfoCmp79 bool operator() (const BundlePriorityInfo &p1, const BundlePriorityInfo &p2)
80 {
81 if (p1.uid_ == p2.uid_) {
82 // remove duplicate BundlePriorityInfo according to uid_
83 return false;
84 } else {
85 if (p1.priority_ != p2.priority_) {
86 // in descending order
87 return p1.priority_ > p2.priority_;
88 } else {
89 // when in same priority_, sort by uid_
90 // it will be sorted by last used time
91 return p1.uid_ < p2.uid_;
92 }
93 }
94 }
95 };
96
97 using BundlePrioSet = std::set<std::shared_ptr<BundlePriorityInfo>, BundleInfoPtrCmp>;
98 using BunldeCopySet = std::set<BundlePriorityInfo, BundleInfoCmp>;
99 // map <bundleUid, std::shared_ptr<BundlePriorityInfo>>
100 using BundlePrioMap = std::map<int, std::shared_ptr<BundlePriorityInfo>>;
101 using OsAccountsMap = std::map<int, std::shared_ptr<AccountBundleInfo>>;
102 bool Init();
103 bool UpdateReclaimPriority(const ReclaimHandleRequest &request);
104 bool OsAccountChanged(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod);
105
Initailized()106 inline bool Initailized()
107 {
108 return initialized_;
109 };
110
111 // for lmkd and memory reclaim
112 void GetBundlePrioSet(BunldeCopySet &bundleSet);
113
114 void GetOneKillableBundle(int minPrio, BunldeCopySet &bundleSet);
115
116 void SetBundleState(int accountId, int uid, BundleState state);
117
118 // for hidumper, usage: hdc shell hidumper -s 1909
119 void Dump(int fd);
120
121 void Reset();
122 private:
123 bool initialized_ = false;
124
125 // map <accountId, accountInfo>
126 OsAccountsMap osAccountsInfoMap_;
127 // total system prioritySet
128 // when new a BundlePriorityInfo, it will be added into this set
129 // when delete a BundlePriorityInfo, it will be removed from this set
130 // when change the priority of BundlePriorityInfo, it will be removed and added from this set to re-sort it
131 BundlePrioSet totalBundlePrioSet_;
132 std::mutex totalBundlePrioSetLock_;
133
134 std::shared_ptr<AppExecFwk::EventHandler> handler_;
135 std::map<int32_t, std::string> updateReasonStrMapping_;
136 std::string UNKOWN_REASON = "UNKOWN_REASON";
137 ReclaimPriorityConfig config_;
138 std::set<std::string> allKillableSystemApps_;
139
140 ReclaimPriorityManager();
141 bool GetEventHandler();
142 void UpdateForegroundApps();
143 bool IsFrontApp(const std::string& pkgName, int32_t uid, int32_t pid);
144 void GetAllKillableSystemApps();
145 void GetKillableSystemAppsFromAms(std::set<std::string> &killableApps);
146 void HandlePreStartedProcs();
147 bool UpdateReclaimPriorityInner(const ReclaimHandleRequest &request);
148 void UpdateReclaimPriorityWithLock(const ReclaimHandleRequest &request);
149 bool HandleExtensionProcess(int32_t callerPid, int32_t callerUid, const std::string &callerBundleName,
150 pid_t pid, int bundleUid, const std::string &bundleName, AppStateUpdateReason priorityReason);
151 bool OsAccountChangedInner(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod);
152 bool UpdateAllPrioForOsAccountChanged(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod);
153 bool ApplyReclaimPriority(std::shared_ptr<BundlePriorityInfo> bundle, pid_t pid, AppAction action);
154 bool IsProcExist(pid_t pid, int bundleUid, int accountId);
155 bool IsOsAccountExist(int accountId);
156 bool HandleCreateProcess(int pid, int bundleUid, const std::string &bundleName, int accountId,
157 bool isRender = false);
158 bool HandleTerminateProcess(ProcessPriorityInfo proc, std::shared_ptr<BundlePriorityInfo> bundle,
159 std::shared_ptr<AccountBundleInfo> account);
160 void HandleUpdateProcess(AppStateUpdateReason reason, std::shared_ptr<BundlePriorityInfo> bundle,
161 ProcessPriorityInfo &proc, AppAction &action);
162 void UpdatePriorityByProcStatus(std::shared_ptr<BundlePriorityInfo> bundle, ProcessPriorityInfo &proc);
163 bool HandleApplicationSuspend(std::shared_ptr<BundlePriorityInfo> bundle);
164 std::shared_ptr<AccountBundleInfo> FindOsAccountById(int accountId);
165 void RemoveOsAccountById(int accountId);
166 void AddOsAccountInfo(std::shared_ptr<AccountBundleInfo> account);
167 bool IsKillableSystemApp(std::shared_ptr<BundlePriorityInfo> bundle);
168 void NotifyKillableSystemAppsAdded(std::set<std::string> &newKillableApps);
169 bool IsImportantApp(std::shared_ptr<BundlePriorityInfo> bundle, int &dstPriority);
170 bool UpdateProcessForExtension(int32_t callerPid, int32_t callerUid, const std::string &callerBundleName,
171 pid_t pid, int bundleUid, const std::string &bundleName, AppStateUpdateReason priorityReason);
172 bool UpdateConnectorsForExtension(int32_t callerPid, int32_t callerUid, const std::string &callerBundleName,
173 pid_t pid, int bundleUid, const std::string &bundleName, AppStateUpdateReason priorityReason);
174 void UpdatePriorityByProcForExtension(const ProcessPriorityInfo &proc);
175 void UpdatePriorityByProcConnector(ProcessPriorityInfo &proc);
176 bool HandleUpdateExtensionBundle(int bundleUid);
177
178 // two methods below used to manage totalBundlePrioSet_ by BundlePriorityInfo
179 void AddBundleInfoToSet(std::shared_ptr<BundlePriorityInfo> bundle);
180 void UpdateBundlePriority(std::shared_ptr<BundlePriorityInfo> bundle);
181 void DeleteBundleInfoFromSet(std::shared_ptr<BundlePriorityInfo> bundle);
182
183 std::string& AppStateUpdateResonToString(AppStateUpdateReason reason);
GetOsAccountLocalIdFromUid(int bundleUid)184 static inline int GetOsAccountLocalIdFromUid(int bundleUid)
185 {
186 return GetOsAccountIdByUid(bundleUid);
187 }
188 };
189 } // namespace Memory
190 } // namespace OHOS
191 #endif // OHOS_MEMORY_MEMMGR_RECALIM_PRIORITY_MANAGER_H
192