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