1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #include "MemtrackProxy.h"
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker #include <android-base/logging.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <android/binder_manager.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
22*38e8c45fSAndroid Build Coastguard Worker
23*38e8c45fSAndroid Build Coastguard Worker using ::android::hardware::hidl_vec;
24*38e8c45fSAndroid Build Coastguard Worker using ::android::hardware::Return;
25*38e8c45fSAndroid Build Coastguard Worker
26*38e8c45fSAndroid Build Coastguard Worker namespace aidl {
27*38e8c45fSAndroid Build Coastguard Worker namespace android {
28*38e8c45fSAndroid Build Coastguard Worker namespace hardware {
29*38e8c45fSAndroid Build Coastguard Worker namespace memtrack {
30*38e8c45fSAndroid Build Coastguard Worker
31*38e8c45fSAndroid Build Coastguard Worker // Check Memtrack Flags
32*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SMAPS_ACCOUNTED) ==
33*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SMAPS_ACCOUNTED));
34*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SMAPS_UNACCOUNTED) ==
35*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SMAPS_UNACCOUNTED));
36*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SHARED) ==
37*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SHARED));
38*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SHARED_PSS) ==
39*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SHARED_PSS));
40*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::PRIVATE) ==
41*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_PRIVATE));
42*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SYSTEM) ==
43*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SYSTEM));
44*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::DEDICATED) ==
45*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_DEDICATED));
46*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::NONSECURE) ==
47*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_NONSECURE));
48*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SECURE) ==
49*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SECURE));
50*38e8c45fSAndroid Build Coastguard Worker
51*38e8c45fSAndroid Build Coastguard Worker // Check Memtrack Types
52*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::OTHER) ==
53*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackType::OTHER));
54*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::GL) ==
55*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackType::GL));
56*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::GRAPHICS) ==
57*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackType::GRAPHICS));
58*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::MULTIMEDIA) ==
59*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackType::MULTIMEDIA));
60*38e8c45fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::CAMERA) ==
61*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(V1_aidl::MemtrackType::CAMERA));
62*38e8c45fSAndroid Build Coastguard Worker
translate(const V1_0_hidl::MemtrackRecord & in,V1_aidl::MemtrackRecord * out)63*38e8c45fSAndroid Build Coastguard Worker __attribute__((warn_unused_result)) bool translate(const V1_0_hidl::MemtrackRecord& in,
64*38e8c45fSAndroid Build Coastguard Worker V1_aidl::MemtrackRecord* out) {
65*38e8c45fSAndroid Build Coastguard Worker // Convert uint64_t to int64_t (long in AIDL). AIDL doesn't support unsigned types.
66*38e8c45fSAndroid Build Coastguard Worker if (in.sizeInBytes > std::numeric_limits<int64_t>::max() || in.sizeInBytes < 0) {
67*38e8c45fSAndroid Build Coastguard Worker return false;
68*38e8c45fSAndroid Build Coastguard Worker }
69*38e8c45fSAndroid Build Coastguard Worker out->sizeInBytes = static_cast<int64_t>(in.sizeInBytes);
70*38e8c45fSAndroid Build Coastguard Worker
71*38e8c45fSAndroid Build Coastguard Worker // It's ok to just assign directly, since this is a bitmap.
72*38e8c45fSAndroid Build Coastguard Worker out->flags = in.flags;
73*38e8c45fSAndroid Build Coastguard Worker return true;
74*38e8c45fSAndroid Build Coastguard Worker }
75*38e8c45fSAndroid Build Coastguard Worker
MemtrackHidlInstance()76*38e8c45fSAndroid Build Coastguard Worker sp<V1_0_hidl::IMemtrack> MemtrackProxy::MemtrackHidlInstance() {
77*38e8c45fSAndroid Build Coastguard Worker return V1_0_hidl::IMemtrack::getService();
78*38e8c45fSAndroid Build Coastguard Worker }
79*38e8c45fSAndroid Build Coastguard Worker
MemtrackAidlInstance()80*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<V1_aidl::IMemtrack> MemtrackProxy::MemtrackAidlInstance() {
81*38e8c45fSAndroid Build Coastguard Worker const auto instance = std::string() + V1_aidl::IMemtrack::descriptor + "/default";
82*38e8c45fSAndroid Build Coastguard Worker bool declared = AServiceManager_isDeclared(instance.c_str());
83*38e8c45fSAndroid Build Coastguard Worker if (!declared) {
84*38e8c45fSAndroid Build Coastguard Worker return nullptr;
85*38e8c45fSAndroid Build Coastguard Worker }
86*38e8c45fSAndroid Build Coastguard Worker ndk::SpAIBinder memtrack_binder =
87*38e8c45fSAndroid Build Coastguard Worker ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str()));
88*38e8c45fSAndroid Build Coastguard Worker return V1_aidl::IMemtrack::fromBinder(memtrack_binder);
89*38e8c45fSAndroid Build Coastguard Worker }
90*38e8c45fSAndroid Build Coastguard Worker
CheckUid(uid_t calling_uid)91*38e8c45fSAndroid Build Coastguard Worker bool MemtrackProxy::CheckUid(uid_t calling_uid) {
92*38e8c45fSAndroid Build Coastguard Worker // Allow AID_SHELL for adb shell dumpsys meminfo
93*38e8c45fSAndroid Build Coastguard Worker return calling_uid == AID_SYSTEM || calling_uid == AID_ROOT || calling_uid == AID_SHELL;
94*38e8c45fSAndroid Build Coastguard Worker }
95*38e8c45fSAndroid Build Coastguard Worker
CheckPid(pid_t calling_pid,pid_t request_pid)96*38e8c45fSAndroid Build Coastguard Worker bool MemtrackProxy::CheckPid(pid_t calling_pid, pid_t request_pid) {
97*38e8c45fSAndroid Build Coastguard Worker return calling_pid == request_pid;
98*38e8c45fSAndroid Build Coastguard Worker }
99*38e8c45fSAndroid Build Coastguard Worker
MemtrackProxy()100*38e8c45fSAndroid Build Coastguard Worker MemtrackProxy::MemtrackProxy() {
101*38e8c45fSAndroid Build Coastguard Worker memtrack_aidl_instance_ = MemtrackProxy::MemtrackAidlInstance();
102*38e8c45fSAndroid Build Coastguard Worker
103*38e8c45fSAndroid Build Coastguard Worker // Only check for a HIDL implementation if we failed to get the AIDL service
104*38e8c45fSAndroid Build Coastguard Worker if (!memtrack_aidl_instance_) {
105*38e8c45fSAndroid Build Coastguard Worker memtrack_hidl_instance_ = MemtrackProxy::MemtrackHidlInstance();
106*38e8c45fSAndroid Build Coastguard Worker }
107*38e8c45fSAndroid Build Coastguard Worker }
108*38e8c45fSAndroid Build Coastguard Worker
getMemory(int pid,MemtrackType type,std::vector<MemtrackRecord> * _aidl_return)109*38e8c45fSAndroid Build Coastguard Worker ndk::ScopedAStatus MemtrackProxy::getMemory(int pid, MemtrackType type,
110*38e8c45fSAndroid Build Coastguard Worker std::vector<MemtrackRecord>* _aidl_return) {
111*38e8c45fSAndroid Build Coastguard Worker if (pid < 0) {
112*38e8c45fSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
113*38e8c45fSAndroid Build Coastguard Worker }
114*38e8c45fSAndroid Build Coastguard Worker
115*38e8c45fSAndroid Build Coastguard Worker if (!MemtrackProxy::CheckPid(AIBinder_getCallingPid(), pid) &&
116*38e8c45fSAndroid Build Coastguard Worker !MemtrackProxy::CheckUid(AIBinder_getCallingUid())) {
117*38e8c45fSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
118*38e8c45fSAndroid Build Coastguard Worker EX_SECURITY,
119*38e8c45fSAndroid Build Coastguard Worker "Only AID_ROOT, AID_SYSTEM and AID_SHELL can request getMemory() for PIDs other "
120*38e8c45fSAndroid Build Coastguard Worker "than the calling PID");
121*38e8c45fSAndroid Build Coastguard Worker }
122*38e8c45fSAndroid Build Coastguard Worker
123*38e8c45fSAndroid Build Coastguard Worker if (type != MemtrackType::OTHER && type != MemtrackType::GL && type != MemtrackType::GRAPHICS &&
124*38e8c45fSAndroid Build Coastguard Worker type != MemtrackType::MULTIMEDIA && type != MemtrackType::CAMERA) {
125*38e8c45fSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
126*38e8c45fSAndroid Build Coastguard Worker }
127*38e8c45fSAndroid Build Coastguard Worker
128*38e8c45fSAndroid Build Coastguard Worker _aidl_return->clear();
129*38e8c45fSAndroid Build Coastguard Worker
130*38e8c45fSAndroid Build Coastguard Worker if (memtrack_aidl_instance_) {
131*38e8c45fSAndroid Build Coastguard Worker return memtrack_aidl_instance_->getMemory(pid, type, _aidl_return);
132*38e8c45fSAndroid Build Coastguard Worker } else if (memtrack_hidl_instance_) {
133*38e8c45fSAndroid Build Coastguard Worker ndk::ScopedAStatus aidl_status;
134*38e8c45fSAndroid Build Coastguard Worker
135*38e8c45fSAndroid Build Coastguard Worker Return<void> ret = memtrack_hidl_instance_->getMemory(
136*38e8c45fSAndroid Build Coastguard Worker pid, static_cast<V1_0_hidl::MemtrackType>(type),
137*38e8c45fSAndroid Build Coastguard Worker [&_aidl_return, &aidl_status](V1_0_hidl::MemtrackStatus status,
138*38e8c45fSAndroid Build Coastguard Worker hidl_vec<V1_0_hidl::MemtrackRecord> records) {
139*38e8c45fSAndroid Build Coastguard Worker switch (status) {
140*38e8c45fSAndroid Build Coastguard Worker case V1_0_hidl::MemtrackStatus::SUCCESS:
141*38e8c45fSAndroid Build Coastguard Worker aidl_status = ndk::ScopedAStatus::ok();
142*38e8c45fSAndroid Build Coastguard Worker break;
143*38e8c45fSAndroid Build Coastguard Worker case V1_0_hidl::MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED:
144*38e8c45fSAndroid Build Coastguard Worker [[fallthrough]];
145*38e8c45fSAndroid Build Coastguard Worker case V1_0_hidl::MemtrackStatus::TYPE_NOT_SUPPORTED:
146*38e8c45fSAndroid Build Coastguard Worker [[fallthrough]];
147*38e8c45fSAndroid Build Coastguard Worker default:
148*38e8c45fSAndroid Build Coastguard Worker aidl_status =
149*38e8c45fSAndroid Build Coastguard Worker ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
150*38e8c45fSAndroid Build Coastguard Worker return;
151*38e8c45fSAndroid Build Coastguard Worker }
152*38e8c45fSAndroid Build Coastguard Worker
153*38e8c45fSAndroid Build Coastguard Worker _aidl_return->resize(records.size());
154*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < records.size(); i++) {
155*38e8c45fSAndroid Build Coastguard Worker if (!translate(records[i], &(*_aidl_return)[i])) {
156*38e8c45fSAndroid Build Coastguard Worker aidl_status = ndk::ScopedAStatus::fromExceptionCodeWithMessage(
157*38e8c45fSAndroid Build Coastguard Worker EX_SERVICE_SPECIFIC,
158*38e8c45fSAndroid Build Coastguard Worker "Failed to convert HIDL MemtrackRecord to AIDL");
159*38e8c45fSAndroid Build Coastguard Worker return;
160*38e8c45fSAndroid Build Coastguard Worker }
161*38e8c45fSAndroid Build Coastguard Worker }
162*38e8c45fSAndroid Build Coastguard Worker });
163*38e8c45fSAndroid Build Coastguard Worker
164*38e8c45fSAndroid Build Coastguard Worker // Check HIDL return
165*38e8c45fSAndroid Build Coastguard Worker if (!ret.isOk()) {
166*38e8c45fSAndroid Build Coastguard Worker const char* err_msg = "HIDL Memtrack::getMemory() failed";
167*38e8c45fSAndroid Build Coastguard Worker aidl_status =
168*38e8c45fSAndroid Build Coastguard Worker ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC, err_msg);
169*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << err_msg << ": " << ret.description();
170*38e8c45fSAndroid Build Coastguard Worker }
171*38e8c45fSAndroid Build Coastguard Worker
172*38e8c45fSAndroid Build Coastguard Worker return aidl_status;
173*38e8c45fSAndroid Build Coastguard Worker }
174*38e8c45fSAndroid Build Coastguard Worker
175*38e8c45fSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
176*38e8c45fSAndroid Build Coastguard Worker "Memtrack HAL service not available");
177*38e8c45fSAndroid Build Coastguard Worker }
178*38e8c45fSAndroid Build Coastguard Worker
getGpuDeviceInfo(std::vector<DeviceInfo> * _aidl_return)179*38e8c45fSAndroid Build Coastguard Worker ndk::ScopedAStatus MemtrackProxy::getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) {
180*38e8c45fSAndroid Build Coastguard Worker if (!MemtrackProxy::CheckUid(AIBinder_getCallingUid())) {
181*38e8c45fSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_SECURITY,
182*38e8c45fSAndroid Build Coastguard Worker "Only AID_ROOT, AID_SYSTEM and AID_SHELL can request getGpuDeviceInfo()");
183*38e8c45fSAndroid Build Coastguard Worker }
184*38e8c45fSAndroid Build Coastguard Worker
185*38e8c45fSAndroid Build Coastguard Worker _aidl_return->clear();
186*38e8c45fSAndroid Build Coastguard Worker
187*38e8c45fSAndroid Build Coastguard Worker if (memtrack_aidl_instance_ ||
188*38e8c45fSAndroid Build Coastguard Worker (memtrack_aidl_instance_ = MemtrackProxy::MemtrackAidlInstance())) {
189*38e8c45fSAndroid Build Coastguard Worker return memtrack_aidl_instance_->getGpuDeviceInfo(_aidl_return);
190*38e8c45fSAndroid Build Coastguard Worker }
191*38e8c45fSAndroid Build Coastguard Worker
192*38e8c45fSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
193*38e8c45fSAndroid Build Coastguard Worker "Memtrack HAL service not available");
194*38e8c45fSAndroid Build Coastguard Worker }
195*38e8c45fSAndroid Build Coastguard Worker
196*38e8c45fSAndroid Build Coastguard Worker } // namespace memtrack
197*38e8c45fSAndroid Build Coastguard Worker } // namespace hardware
198*38e8c45fSAndroid Build Coastguard Worker } // namespace android
199*38e8c45fSAndroid Build Coastguard Worker } // namespace aidl
200