1 /*
2 * Copyright (c) 2022 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 "mem_mgr_service.h"
17
18 #include <parameters.h>
19 #include <unistd.h>
20
21 #include "accesstoken_kit.h"
22 #include "ipc_skeleton.h"
23 #include "low_memory_killer.h"
24 #include "mem_mgr_event_center.h"
25 #include "memmgr_config_manager.h"
26 #include "memmgr_log.h"
27 #include "multi_account_manager.h"
28 #include "nandlife_controller.h"
29 #include "reclaim_priority_manager.h"
30 #include "reclaim_strategy_manager.h"
31 #include "system_ability_definition.h"
32 #include "window_visibility_observer.h"
33 #ifdef USE_PURGEABLE_MEMORY
34 #include "kernel_interface.h"
35 #include "purgeable_mem_manager.h"
36 #endif
37 #include "dump_command_dispatcher.h"
38
39 namespace OHOS {
40 namespace Memory {
41 namespace {
42 const std::string TAG = "MemMgrService";
43 const int32_t ENG_MODE = OHOS::system::GetIntParameter("const.debuggable", 0);
44 const int32_t ERR_MEMMGR_PERMISSION_DENIED = -1;
45 }
46
47 IMPLEMENT_SINGLE_INSTANCE(MemMgrService);
48 const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(&MemMgrService::GetInstance());
49
MemMgrService()50 MemMgrService::MemMgrService() : SystemAbility(MEMORY_MANAGER_SA_ID, true)
51 {
52 }
53
Init()54 bool MemMgrService::Init()
55 {
56 MemmgrConfigManager::GetInstance().Init();
57
58 // init reclaim priority manager
59 if (!ReclaimPriorityManager::GetInstance().Init()) {
60 HILOGE("ReclaimPriorityManager init failed");
61 return false;
62 }
63
64 // init multiple account manager
65 MultiAccountManager::GetInstance().Init();
66
67 #ifdef USE_HYPERHOLD_MEMORY
68 // init reclaim strategy manager
69 if (!ReclaimStrategyManager::GetInstance().Init()) {
70 HILOGE("ReclaimStrategyManager init failed");
71 return false;
72 }
73 #endif
74
75 // init event center, then managers above can work by event trigger
76 if (!MemMgrEventCenter::GetInstance().Init()) {
77 HILOGE("MemMgrEventCenter init failed");
78 return false;
79 }
80
81 #ifdef USE_HYPERHOLD_MEMORY
82 // init nandlife controller
83 NandLifeController::GetInstance().Init();
84 #endif
85
86 HILOGI("init successed");
87 return true;
88 }
89
OnStart()90 void MemMgrService::OnStart()
91 {
92 HILOGI("called");
93 if (!Init()) {
94 HILOGE("init failed");
95 return;
96 }
97 if (!Publish(this)) {
98 HILOGE("publish SA failed");
99 return;
100 }
101 HILOGI("publish SA successed");
102
103 AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID);
104 AddSystemAbilityListener(COMMON_EVENT_SERVICE_ABILITY_ID);
105 AddSystemAbilityListener(BACKGROUND_TASK_MANAGER_SERVICE_ID);
106 AddSystemAbilityListener(SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN);
107 AddSystemAbilityListener(SUBSYS_APPLICATIONS_SYS_ABILITY_ID_BEGIN);
108 AddSystemAbilityListener(APP_MGR_SERVICE_ID);
109 AddSystemAbilityListener(ABILITY_MGR_SERVICE_ID);
110 }
111
OnStop()112 void MemMgrService::OnStop()
113 {
114 HILOGI("called");
115 }
116
117 // implements of innerkits list below
118
GetBundlePriorityList(BundlePriorityList & bundlePrioList)119 int32_t MemMgrService::GetBundlePriorityList(BundlePriorityList &bundlePrioList)
120 {
121 HILOGI("called");
122 ReclaimPriorityManager::BunldeCopySet bundleSet;
123 ReclaimPriorityManager::GetInstance().GetBundlePrioSet(bundleSet);
124 for (auto bundlePriorityInfo : bundleSet) {
125 Memory::BundlePriority bi = Memory::BundlePriority(bundlePriorityInfo.uid_,
126 bundlePriorityInfo.name_, bundlePriorityInfo.priority_, bundlePriorityInfo.accountId_);
127 bundlePrioList.AddBundleInfo(bi);
128 }
129 bundlePrioList.SetCount(bundlePrioList.Size());
130 return 0;
131 }
132
NotifyDistDevStatus(int32_t pid,int32_t uid,const std::string & name,bool connected)133 int32_t MemMgrService::NotifyDistDevStatus(int32_t pid, int32_t uid, const std::string &name, bool connected)
134 {
135 HILOGI("called, pid=%{public}d, uid=%{public}d, name=%{public}s, connected=%{public}d", pid, uid, name.c_str(),
136 connected);
137 ReclaimHandleRequest request;
138 request.pid = pid;
139 request.uid = uid;
140 request.bundleName = name;
141 request.reason =
142 connected ? AppStateUpdateReason::DIST_DEVICE_CONNECTED : AppStateUpdateReason::DIST_DEVICE_DISCONNECTED;
143 ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(
144 SingleRequest({pid, uid, "", name},
145 connected ? AppStateUpdateReason::DIST_DEVICE_CONNECTED : AppStateUpdateReason::DIST_DEVICE_DISCONNECTED));
146 return 0;
147 }
148
GetKillLevelOfLmkd(int32_t & killLevel)149 int32_t MemMgrService::GetKillLevelOfLmkd(int32_t &killLevel)
150 {
151 HILOGI("called");
152 killLevel = LowMemoryKiller::GetInstance().GetKillLevel();
153 return 0;
154 }
155
156 #ifdef USE_PURGEABLE_MEMORY
RegisterActiveApps(int32_t pid,int32_t uid)157 int32_t MemMgrService::RegisterActiveApps(int32_t pid, int32_t uid)
158 {
159 HILOGI("called, pid=%{public}d, uid=%{public}d", pid, uid);
160 PurgeableMemManager::GetInstance().RegisterActiveApps(pid, uid);
161 return 0;
162 }
163
DeregisterActiveApps(int32_t pid,int32_t uid)164 int32_t MemMgrService::DeregisterActiveApps(int32_t pid, int32_t uid)
165 {
166 HILOGI("called, pid=%{public}d, uid=%{public}d", pid, uid);
167 PurgeableMemManager::GetInstance().DeregisterActiveApps(pid, uid);
168 return 0;
169 }
170
SubscribeAppState(const sptr<IAppStateSubscriber> & subscriber)171 int32_t MemMgrService::SubscribeAppState(const sptr<IAppStateSubscriber> &subscriber)
172 {
173 HILOGI("called");
174 PurgeableMemManager::GetInstance().AddSubscriber(subscriber);
175 return 0;
176 }
177
UnsubscribeAppState(const sptr<IAppStateSubscriber> & subscriber)178 int32_t MemMgrService::UnsubscribeAppState(const sptr<IAppStateSubscriber> &subscriber)
179 {
180 HILOGI("called");
181 PurgeableMemManager::GetInstance().RemoveSubscriber(subscriber);
182 return 0;
183 }
184
GetAvailableMemory(int32_t & memSize)185 int32_t MemMgrService::GetAvailableMemory(int32_t &memSize)
186 {
187 HILOGI("called");
188 memSize = KernelInterface::GetInstance().GetCurrentBuffer();
189 if (memSize < 0 || memSize >= MAX_BUFFER_KB) {
190 return -1;
191 }
192 return 0;
193 }
194
GetTotalMemory(int32_t & memSize)195 int32_t MemMgrService::GetTotalMemory(int32_t &memSize)
196 {
197 HILOGI("called");
198 memSize = KernelInterface::GetInstance().GetTotalBuffer();
199 if (memSize < 0 || memSize >= MAX_BUFFER_KB) {
200 return -1;
201 }
202 return 0;
203 }
204 #endif // USE_PURGEABLE_MEMORY
205
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)206 void MemMgrService::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
207 {
208 HILOGI("systemAbilityId: %{public}d add", systemAbilityId);
209 MemMgrEventCenter::GetInstance().RetryRegisterEventObserver(systemAbilityId);
210 }
211
OnWindowVisibilityChanged(const std::vector<sptr<MemMgrWindowInfo>> & MemMgrWindowInfo)212 int32_t MemMgrService::OnWindowVisibilityChanged(const std::vector<sptr<MemMgrWindowInfo>> &MemMgrWindowInfo)
213 {
214 HILOGI("called");
215 int32_t callingUid = IPCSkeleton::GetCallingUid();
216 if (callingUid != windowManagerUid_) {
217 HILOGE("OnWindowVisibilityChanged refused for%{public}d", callingUid);
218 return -1;
219 }
220 HILOGI("OnWindowVisibilityChanged called %{public}d", callingUid);
221 WindowVisibilityObserver::GetInstance().UpdateWindowVisibilityPriority(MemMgrWindowInfo);
222 return 0;
223 }
224
GetReclaimPriorityByPid(int32_t pid,int32_t & priority)225 int32_t MemMgrService::GetReclaimPriorityByPid(int32_t pid, int32_t &priority)
226 {
227 HILOGI("called");
228 std::string path = KernelInterface::GetInstance().JoinPath("/proc/", std::to_string(pid), "/oom_score_adj");
229 std::string contentStr;
230 if (KernelInterface::GetInstance().ReadFromFile(path, contentStr) || contentStr.size() == 0) {
231 HILOGE("read %{public}s failed, content=[%{public}s]", path.c_str(), contentStr.c_str());
232 return -1;
233 }
234 HILOGD("read %{public}s succ, content=[%{public}s]", path.c_str(), contentStr.c_str());
235
236 try {
237 priority = std::stoi(contentStr);
238 } catch (std::out_of_range&) {
239 HILOGW("stoi() failed: out_of_range");
240 return -1;
241 } catch (std::invalid_argument&) {
242 HILOGW("stoi() failed: invalid_argument");
243 return -1;
244 }
245 return 0;
246 }
247
248
NotifyProcessStateChangedSync(const MemMgrProcessStateInfo & processStateInfo)249 int32_t MemMgrService::NotifyProcessStateChangedSync(const MemMgrProcessStateInfo &processStateInfo)
250 {
251 HILOGD("called");
252 if (processStateInfo.reason_ == ProcPriorityUpdateReason::START_ABILITY) {
253 HILOGD("callerpid=%{public}d,calleruid=%{public}d,pid=%{public}d,uid=%{public}d,reason=%{public}u",
254 processStateInfo.callerPid_, processStateInfo.callerUid_, processStateInfo.pid_, processStateInfo.uid_,
255 static_cast<uint32_t>(processStateInfo.reason_));
256 UpdateRequest request = CallerRequest({processStateInfo.callerPid_, processStateInfo.callerUid_, "", ""},
257 {processStateInfo.pid_, processStateInfo.uid_, "", ""}, AppStateUpdateReason::ABILITY_START);
258 if (!ReclaimPriorityManager::GetInstance().UpdateRecalimPrioritySyncWithLock(request)) {
259 HILOGE("NotifyProcessStateChangedSync <pid=%{public}d,uid=%{public}d,reason=%{public}u> failed",
260 processStateInfo.pid_, processStateInfo.uid_, static_cast<uint32_t>(processStateInfo.reason_));
261 return static_cast<int32_t>(MemMgrErrorCode::MEMMGR_SERVICE_ERR);
262 }
263 }
264 return 0;
265 }
266
NotifyProcessStateChangedAsync(const MemMgrProcessStateInfo & processStateInfo)267 int32_t MemMgrService::NotifyProcessStateChangedAsync(const MemMgrProcessStateInfo &processStateInfo)
268 {
269 HILOGD("called");
270 if (processStateInfo.reason_ == ProcPriorityUpdateReason::START_ABILITY) {
271 HILOGD("callerpid=%{public}d,calleruid=%{public}d,pid=%{public}d,uid=%{public}d,reason=%{public}u",
272 processStateInfo.callerPid_, processStateInfo.callerUid_, processStateInfo.pid_, processStateInfo.uid_,
273 static_cast<uint32_t>(processStateInfo.reason_));
274 UpdateRequest request = CallerRequest({processStateInfo.callerPid_, processStateInfo.callerUid_, "", ""},
275 {processStateInfo.pid_, processStateInfo.uid_, "", ""}, AppStateUpdateReason::ABILITY_START);
276 if (!ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(request)) {
277 HILOGE("NotifyProcessStateChangedAsync <pid=%{public}d,uid=%{public}d,reason=%{public}u> failed",
278 processStateInfo.pid_, processStateInfo.uid_, static_cast<uint32_t>(processStateInfo.reason_));
279 return static_cast<int32_t>(MemMgrErrorCode::MEMMGR_SERVICE_ERR);
280 }
281 }
282 return 0;
283 }
284
NotifyProcessStatus(int32_t pid,int32_t type,int32_t status,int32_t saId)285 int32_t MemMgrService::NotifyProcessStatus(int32_t pid, int32_t type, int32_t status, int32_t saId)
286 {
287 HILOGI("pid=%{public}d,type=%{public}d,status=%{public}d,saId=%{public}d",
288 pid, type, status, saId);
289 return 0;
290 }
291
SetCritical(int32_t pid,bool critical,int32_t saId)292 int32_t MemMgrService::SetCritical(int32_t pid, bool critical, int32_t saId)
293 {
294 HILOGI("pid=%{public}d,critical=%{public}d,saId=%{public}d", pid, critical, saId);
295 return 0;
296 }
297
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)298 void MemMgrService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
299 {
300 HILOGI("systemAbilityId: %{public}d add", systemAbilityId);
301 MemMgrEventCenter::GetInstance().RemoveEventObserver(systemAbilityId);
302 }
303
ParseParams(const std::vector<std::string> & params,std::map<std::string,std::vector<std::string>> & keyValuesMapping)304 void ParseParams(const std::vector<std::string> ¶ms,
305 std::map<std::string, std::vector<std::string>> &keyValuesMapping)
306 {
307 std::string tmpKey;
308 std::vector<std::string> tmpValue;
309 for (auto i = 0; i < params.size(); i++) {
310 if (params[i].empty())
311 continue;
312 if (params[i][0] == '-') {
313 if (!tmpKey.empty()) {
314 keyValuesMapping[tmpKey] = tmpValue;
315 tmpValue.clear();
316 }
317 tmpKey = params[i];
318 } else {
319 tmpValue.emplace_back(params[i]);
320 }
321 }
322 if (!tmpKey.empty()) {
323 keyValuesMapping[tmpKey] = tmpValue;
324 }
325
326 HILOGD("keyValuesMapping.size()=%{public}zu\n", keyValuesMapping.size());
327 for (auto &it : keyValuesMapping) {
328 HILOGD("key=%{public}s", it.first.c_str());
329 for (auto i = 0; i < it.second.size(); i++) {
330 HILOGD("value[%{public}d]=%{public}s", i, it.second[i].c_str());
331 }
332 }
333 }
334
AllowDump()335 bool MemMgrService::AllowDump()
336 {
337 if (ENG_MODE == 0) {
338 HILOGE("Not eng mode");
339 return false;
340 }
341 Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetFirstTokenID();
342 int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "ohos.permission.DUMP");
343 if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
344 HILOGE("CheckPermission failed");
345 return false;
346 }
347 return true;
348 }
349
Dump(int fd,const std::vector<std::u16string> & args)350 int MemMgrService::Dump(int fd, const std::vector<std::u16string> &args)
351 {
352 if (!AllowDump()) {
353 return ERR_MEMMGR_PERMISSION_DENIED;
354 }
355 HILOGI("called");
356 std::vector<std::string> params;
357 for (auto &arg : args) {
358 params.emplace_back(Str16ToStr8(arg));
359 }
360 std::map<std::string, std::vector<std::string>> keyValuesMapping;
361 ParseParams(params, keyValuesMapping);
362 DispatchDumpCommand(fd, keyValuesMapping);
363 return 0;
364 }
365 } // namespace Memory
366 } // namespace OHOS
367