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_stub.h"
17
18#include "accesstoken_kit.h"
19#include "ipc_skeleton.h"
20#include "kernel_interface.h"
21#include "low_memory_killer.h"
22#include "memmgr_log.h"
23#include "memmgr_config_manager.h"
24#include "parcel.h"
25
26namespace OHOS {
27namespace Memory {
28namespace {
29    const std::string TAG = "MemMgrStub";
30    constexpr int MAX_PARCEL_SIZE = 100000;
31    constexpr int CAMERA_SERVICE_UID = 1047;
32    constexpr int FOUNDATION_UID = 5523;
33}
34
35MemMgrStub::MemMgrStub()
36{
37}
38
39MemMgrStub::~MemMgrStub()
40{
41}
42
43int MemMgrStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
44{
45    HILOGI("MemMgrStub::OnReceived, code = %{public}d, flags= %{public}d.", code, option.GetFlags());
46    std::u16string descriptor = MemMgrStub::GetDescriptor();
47    std::u16string remoteDescriptor = data.ReadInterfaceToken();
48    if (descriptor != remoteDescriptor) {
49        HILOGE("local descriptor is not equal to remote");
50        return ERR_INVALID_STATE;
51    }
52
53    return OnRemoteRequestInner(code, data, reply, option);
54}
55
56int32_t MemMgrStub::OnRemoteRequestInner(uint32_t code,
57    MessageParcel &data, MessageParcel &reply, MessageOption &option)
58{
59    switch (code) {
60        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_GET_BUNDLE_PRIORITY_LIST):
61            return HandleGetBunldePriorityList(data, reply);
62        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_NOTIFY_DIST_DEV_STATUS):
63            return HandleNotifyDistDevStatus(data, reply);
64        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_GET_KILL_LEVEL_OF_LMKD):
65            return HandleGetKillLevelOfLmkd(data, reply);
66#ifdef USE_PURGEABLE_MEMORY
67        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_REGISTER_ACTIVE_APPS):
68            return HandleRegisterActiveApps(data, reply);
69        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_DEREGISTER_ACTIVE_APPS):
70            return HandleDeregisterActiveApps(data, reply);
71        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_SUBSCRIBE_APP_STATE):
72            return HandleSubscribeAppState(data, reply);
73        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_UNSUBSCRIBE_APP_STATE):
74            return HandleUnsubscribeAppState(data, reply);
75        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_GET_AVAILABLE_MEMORY):
76            return HandleGetAvailableMemory(data, reply);
77        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_GET_TOTAL_MEMORY):
78            return HandleGetTotalMemory(data, reply);
79#endif
80        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_ON_WINDOW_VISIBILITY_CHANGED):
81            return HandleOnWindowVisibilityChanged(data, reply);
82        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_GET_PRIORITY_BY_PID):
83            return HandleGetReclaimPriorityByPid(data, reply);
84        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_NOTIFY_PROCESS_STATE_CHANGED_SYNC):
85            return HandleNotifyProcessStateChangedSync(data, reply);
86        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_NOTIFY_PROCESS_STATE_CHANGED_ASYNC):
87            return HandleNotifyProcessStateChangedAsync(data, reply);
88        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_NOTIFY_PROCESS_STATUS):
89            return HandleNotifyProcessStatus(data, reply);
90        case static_cast<uint32_t>(MemMgrInterfaceCode::MEM_MGR_SET_CRITICAL):
91            return HandleSetCritical(data, reply);
92        default:
93            return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
94    }
95}
96
97int32_t MemMgrStub::HandleGetBunldePriorityList(MessageParcel &data, MessageParcel &reply)
98{
99    HILOGI("called");
100    std::shared_ptr<BundlePriorityList> list
101        = std::shared_ptr<BundlePriorityList>(data.ReadParcelable<BundlePriorityList>());
102
103    if (!list) {
104        HILOGE("BundlePriorityList ReadParcelable failed");
105        return -1;
106    }
107    int32_t ret = GetBundlePriorityList(*list);
108    reply.WriteParcelable(list.get());
109    return ret;
110}
111
112int32_t MemMgrStub::HandleNotifyDistDevStatus(MessageParcel &data, MessageParcel &reply)
113{
114    HILOGI("called");
115    int32_t pid = 0;
116    int32_t uid = 0;
117    std::string name;
118    bool connected;
119    if (!data.ReadInt32(pid) || !data.ReadInt32(uid) || !data.ReadString(name) || !data.ReadBool(connected)) {
120        HILOGE("read params failed");
121        return IPC_STUB_ERR;
122    }
123    HILOGI("called, pid=%{public}d, uid=%{public}d, name=%{public}s, connected=%{public}d", pid, uid, name.c_str(),
124        connected);
125
126    int32_t ret = NotifyDistDevStatus(pid, uid, name, connected);
127    if (!reply.WriteInt32(ret)) {
128        return IPC_STUB_ERR;
129    }
130    return ret;
131}
132
133int32_t MemMgrStub::HandleGetKillLevelOfLmkd(MessageParcel &data, MessageParcel &reply)
134{
135    HILOGI("called");
136    int32_t killLevel = LowMemoryKiller::GetInstance().GetKillLevel();
137    if (!reply.WriteInt32(killLevel)) {
138        return IPC_STUB_ERR;
139    }
140    return 0;
141}
142
143#ifdef USE_PURGEABLE_MEMORY
144int32_t MemMgrStub::HandleRegisterActiveApps(MessageParcel &data, MessageParcel &reply)
145{
146    HILOGI("called");
147    int32_t pid = 0;
148    int32_t uid = 0;
149    if (!data.ReadInt32(pid) || !data.ReadInt32(uid)) {
150        HILOGE("read params failed");
151        return IPC_STUB_ERR;
152    }
153    HILOGI("called, pid=%{public}d, uid=%{public}d", pid, uid);
154
155    int32_t ret = RegisterActiveApps(pid, uid);
156    if (!reply.WriteInt32(ret)) {
157        return IPC_STUB_ERR;
158    }
159    return ret;
160}
161
162int32_t MemMgrStub::HandleDeregisterActiveApps(MessageParcel &data, MessageParcel &reply)
163{
164    HILOGI("called");
165    int32_t pid = 0;
166    int32_t uid = 0;
167    if (!data.ReadInt32(pid) || !data.ReadInt32(uid)) {
168        HILOGE("read params failed");
169        return IPC_STUB_ERR;
170    }
171    HILOGI("called, pid=%{public}d, uid=%{public}d", pid, uid);
172
173    int32_t ret = DeregisterActiveApps(pid, uid);
174    if (!reply.WriteInt32(ret)) {
175        return IPC_STUB_ERR;
176    }
177    return ret;
178}
179
180int32_t MemMgrStub::HandleSubscribeAppState(MessageParcel &data, MessageParcel &reply)
181{
182    HILOGI("called");
183    sptr<IRemoteObject> subscriber = data.ReadRemoteObject();
184    if (subscriber == nullptr) {
185        HILOGE("read params failed");
186        return IPC_STUB_ERR;
187    }
188    int32_t ret = SubscribeAppState(iface_cast<IAppStateSubscriber>(subscriber));
189    if (!reply.WriteInt32(ret)) {
190        return IPC_STUB_ERR;
191    }
192    return ret;
193}
194
195int32_t MemMgrStub::HandleUnsubscribeAppState(MessageParcel &data, MessageParcel &reply)
196{
197    HILOGI("called");
198    sptr<IRemoteObject> subscriber = data.ReadRemoteObject();
199    if (subscriber == nullptr) {
200        HILOGE("read params failed");
201        return IPC_STUB_ERR;
202    }
203
204    int32_t ret = UnsubscribeAppState(iface_cast<IAppStateSubscriber>(subscriber));
205    if (!reply.WriteInt32(ret)) {
206        return IPC_STUB_ERR;
207    }
208    return ret;
209}
210
211int32_t MemMgrStub::HandleGetAvailableMemory(MessageParcel &data, MessageParcel &reply)
212{
213    HILOGI("called");
214    int32_t memSize = 0;
215    int32_t ret = GetAvailableMemory(memSize);
216    if (!reply.WriteInt32(memSize)) {
217        return IPC_STUB_ERR;
218    }
219    return ret;
220}
221
222int32_t MemMgrStub::HandleGetTotalMemory(MessageParcel &data, MessageParcel &reply)
223{
224    HILOGI("called");
225    int32_t memSize = 0;
226    int32_t ret = GetTotalMemory(memSize);
227    if (!reply.WriteInt32(memSize)) {
228        return IPC_STUB_ERR;
229    }
230    return ret;
231}
232#endif // USE_PURGEABLE_MEMORY
233
234int32_t MemMgrStub::HandleOnWindowVisibilityChanged(MessageParcel &data, MessageParcel &reply)
235{
236    HILOGD("called");
237    std::vector<sptr<MemMgrWindowInfo>> infos;
238    uint32_t len = data.ReadUint32();
239    if (len < 0 || len > MAX_PARCEL_SIZE) {
240        return IPC_STUB_ERR;
241    }
242
243    size_t readAbleSize = data.GetReadableBytes();
244    size_t size = static_cast<size_t>(len);
245    if ((size > readAbleSize) || (size > infos.max_size())) {
246        return IPC_STUB_ERR;
247    }
248    infos.resize(size);
249    if (infos.size() < size) {
250        return IPC_STUB_ERR;
251    }
252    size_t minDesireCapacity = sizeof(int32_t);
253    for (size_t i = 0; i < size; i++) {
254        readAbleSize = data.GetReadableBytes();
255        if (minDesireCapacity > readAbleSize) {
256            return IPC_STUB_ERR;
257        }
258        infos[i] = data.ReadParcelable<MemMgrWindowInfo>();
259    }
260
261    int32_t ret = OnWindowVisibilityChanged(infos);
262    if (!reply.WriteInt32(ret)) {
263        return IPC_STUB_ERR;
264    }
265    return ret;
266}
267
268bool MemMgrStub::IsCameraServiceCalling()
269{
270    int32_t callingUid = IPCSkeleton::GetCallingUid();
271    return callingUid == CAMERA_SERVICE_UID;
272}
273
274int32_t MemMgrStub::HandleGetReclaimPriorityByPid(MessageParcel &data, MessageParcel &reply)
275{
276    HILOGD("called");
277
278    if (!IsCameraServiceCalling()) {
279        HILOGE("calling process has no permission, call failled");
280        return IPC_STUB_ERR;
281    }
282    int32_t pid = data.ReadUint32();
283    int32_t priority = RECLAIM_PRIORITY_UNKNOWN + 1;
284    int32_t ret = GetReclaimPriorityByPid(pid, priority);
285
286    if (!reply.WriteInt32(priority)) {
287        return IPC_STUB_ERR;
288    }
289    return ret;
290}
291
292bool MemMgrStub::CheckCallingToken()
293{
294    Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
295    auto tokenFlag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
296    if (tokenFlag == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE ||
297        tokenFlag == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL) {
298            return true;
299    }
300    return false;
301}
302
303bool IsFoundationCalling()
304{
305    return IPCSkeleton::GetCallingUid() == FOUNDATION_UID;
306}
307
308int32_t MemMgrStub::HandleNotifyProcessStateChangedSync(MessageParcel &data, MessageParcel &reply)
309{
310    HILOGD("called");
311
312    if (!IsFoundationCalling()) {
313        HILOGE("calling process has no permission, call failed");
314        return IPC_STUB_ERR;
315    }
316    std::unique_ptr<MemMgrProcessStateInfo> processStateInfo(data.ReadParcelable<MemMgrProcessStateInfo>());
317    if (processStateInfo == nullptr) {
318        HILOGE("ReadParcelable<MemMgrProcessStateInfo> failed");
319        return IPC_STUB_ERR;
320    }
321
322    int32_t ret = NotifyProcessStateChangedSync(*processStateInfo);
323    if (!reply.WriteInt32(ret)) {
324        HILOGE("reply write failed");
325        return IPC_STUB_ERR;
326    }
327    return ret;
328}
329
330int32_t MemMgrStub::HandleNotifyProcessStateChangedAsync(MessageParcel &data, MessageParcel &reply)
331{
332    HILOGD("called");
333
334    if (!IsFoundationCalling()) {
335        HILOGE("calling process has no permission, call failed");
336        return IPC_STUB_ERR;
337    }
338    std::unique_ptr<MemMgrProcessStateInfo> processStateInfo(data.ReadParcelable<MemMgrProcessStateInfo>());
339    if (processStateInfo == nullptr) {
340        HILOGE("ReadParcelable<MemMgrProcessStateInfo> failed");
341        return IPC_STUB_ERR;
342    }
343
344    int32_t ret = NotifyProcessStateChangedAsync(*processStateInfo);
345    if (!reply.WriteInt32(ret)) {
346        HILOGE("reply write failed");
347        return IPC_STUB_ERR;
348    }
349    return ret;
350}
351int32_t MemMgrStub::HandleNotifyProcessStatus(MessageParcel &data, MessageParcel &reply)
352{
353    HILOGD("called");
354
355    if (!CheckCallingToken()) {
356        HILOGE("calling process has no permission, call failed");
357        return IPC_STUB_ERR;
358    }
359    int32_t pid = 0;
360    int32_t type = 0;
361    int32_t status = 0;
362    int32_t saId = -1;
363    if (!data.ReadInt32(pid) || !data.ReadInt32(type) || !data.ReadInt32(status) || !data.ReadInt32(saId)) {
364        HILOGE("read params failed");
365        return IPC_STUB_ERR;
366    }
367
368    NotifyProcessStatus(pid, type, status, saId);
369
370    return 0;
371}
372
373int32_t MemMgrStub::HandleSetCritical(MessageParcel &data, MessageParcel &reply)
374{
375    HILOGD("called");
376
377    if (!CheckCallingToken()) {
378        HILOGE("calling process has no permission, call failed");
379        return IPC_STUB_ERR;
380    }
381    int32_t pid = 0;
382    bool critical = false;
383    int32_t saId = -1;
384    if (!data.ReadInt32(pid) || !data.ReadBool(critical) || !data.ReadInt32(saId)) {
385        HILOGE("read params failed");
386        return IPC_STUB_ERR;
387    }
388    if (IPCSkeleton::GetCallingPid() != pid) {
389        return 0;
390    }
391
392    SetCritical(pid, critical, saId);
393
394    return 0;
395}
396} // namespace Memory
397} // namespace OHOS
398