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
39namespace OHOS {
40namespace Memory {
41namespace {
42const std::string TAG = "MemMgrService";
43const int32_t ENG_MODE = OHOS::system::GetIntParameter("const.debuggable", 0);
44const int32_t ERR_MEMMGR_PERMISSION_DENIED = -1;
45}
46
47IMPLEMENT_SINGLE_INSTANCE(MemMgrService);
48const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(&MemMgrService::GetInstance());
49
50MemMgrService::MemMgrService() : SystemAbility(MEMORY_MANAGER_SA_ID, true)
51{
52}
53
54bool 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
90void 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
112void MemMgrService::OnStop()
113{
114    HILOGI("called");
115}
116
117// implements of innerkits list below
118
119int32_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
133int32_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
149int32_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
157int32_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
164int32_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
171int32_t MemMgrService::SubscribeAppState(const sptr<IAppStateSubscriber> &subscriber)
172{
173    HILOGI("called");
174    PurgeableMemManager::GetInstance().AddSubscriber(subscriber);
175    return 0;
176}
177
178int32_t MemMgrService::UnsubscribeAppState(const sptr<IAppStateSubscriber> &subscriber)
179{
180    HILOGI("called");
181    PurgeableMemManager::GetInstance().RemoveSubscriber(subscriber);
182    return 0;
183}
184
185int32_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
195int32_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
206void MemMgrService::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
207{
208    HILOGI("systemAbilityId: %{public}d add", systemAbilityId);
209    MemMgrEventCenter::GetInstance().RetryRegisterEventObserver(systemAbilityId);
210}
211
212int32_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
225int32_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
249int32_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
267int32_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
285int32_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
292int32_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
298void MemMgrService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
299{
300    HILOGI("systemAbilityId: %{public}d add", systemAbilityId);
301    MemMgrEventCenter::GetInstance().RemoveEventObserver(systemAbilityId);
302}
303
304void ParseParams(const std::vector<std::string> &params,
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
335bool 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
350int 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