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