1 /*
2 * Copyright (C) 2016 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 #define LOG_TAG "HidlSupport"
18
19 #include <hidl/HidlBinderSupport.h>
20
21 #include <android/hidl/base/1.0/BpHwBase.h>
22 #include <android/hidl/manager/1.0/BpHwServiceManager.h>
23 #include <android/hidl/manager/1.1/BpHwServiceManager.h>
24 #include <android/hidl/manager/1.2/BpHwServiceManager.h>
25 #include <hwbinder/IPCThreadState.h>
26 #include "InternalStatic.h" // TODO(b/69122224): remove this include, for getOrCreateCachedBinder
27
28 // C includes
29 #include <inttypes.h>
30 #include <unistd.h>
31
32 // C++ includes
33 #include <fstream>
34 #include <sstream>
35
36 namespace android {
37 namespace hardware {
38
hidl_binder_death_recipient(const sp<hidl_death_recipient> & recipient,uint64_t cookie,const sp<::android::hidl::base::V1_0::IBase> & base)39 hidl_binder_death_recipient::hidl_binder_death_recipient(const sp<hidl_death_recipient> &recipient,
40 uint64_t cookie, const sp<::android::hidl::base::V1_0::IBase> &base) :
41 mRecipient(recipient), mCookie(cookie), mBase(base) {
42 }
43
binderDied(const wp<IBinder> &)44 void hidl_binder_death_recipient::binderDied(const wp<IBinder>& /*who*/) {
45 sp<hidl_death_recipient> recipient = mRecipient.promote();
46 if (recipient != nullptr && mBase != nullptr) {
47 recipient->serviceDied(mCookie, mBase);
48 }
49 mBase = nullptr;
50 }
51
getRecipient()52 wp<hidl_death_recipient> hidl_binder_death_recipient::getRecipient() {
53 return mRecipient;
54 }
55
56 const size_t hidl_handle::kOffsetOfNativeHandle = offsetof(hidl_handle, mHandle);
57 static_assert(hidl_handle::kOffsetOfNativeHandle == 0, "wrong offset");
58
readEmbeddedFromParcel(const hidl_handle &,const Parcel & parcel,size_t parentHandle,size_t parentOffset)59 status_t readEmbeddedFromParcel(const hidl_handle& /* handle */,
60 const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
61 const native_handle_t *handle;
62 status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
63 parentHandle,
64 parentOffset + hidl_handle::kOffsetOfNativeHandle,
65 &handle);
66
67 return _hidl_err;
68 }
69
writeEmbeddedToParcel(const hidl_handle & handle,Parcel * parcel,size_t parentHandle,size_t parentOffset)70 status_t writeEmbeddedToParcel(const hidl_handle &handle,
71 Parcel *parcel, size_t parentHandle, size_t parentOffset) {
72 status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
73 handle.getNativeHandle(),
74 parentHandle,
75 parentOffset + hidl_handle::kOffsetOfNativeHandle);
76
77 return _hidl_err;
78 }
79
80 const size_t hidl_memory::kOffsetOfHandle = offsetof(hidl_memory, mHandle);
81 const size_t hidl_memory::kOffsetOfName = offsetof(hidl_memory, mName);
82 static_assert(hidl_memory::kOffsetOfHandle == 0, "wrong offset");
83 static_assert(hidl_memory::kOffsetOfName == 24, "wrong offset");
84
readEmbeddedFromParcel(const hidl_memory & memory,const Parcel & parcel,size_t parentHandle,size_t parentOffset)85 status_t readEmbeddedFromParcel(const hidl_memory& memory,
86 const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
87 // TODO(b/111883309): Invoke readEmbeddedFromParcel(hidl_handle, ...).
88 const native_handle_t *handle;
89 ::android::status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
90 parentHandle,
91 parentOffset + hidl_memory::kOffsetOfHandle,
92 &handle);
93
94 if (_hidl_err == ::android::OK) {
95 _hidl_err = readEmbeddedFromParcel(
96 memory.name(),
97 parcel,
98 parentHandle,
99 parentOffset + hidl_memory::kOffsetOfName);
100 }
101
102 // hidl_memory's size is stored in uint64_t, but mapMemory's mmap will map
103 // size in size_t. If size is over SIZE_MAX, mapMemory could succeed
104 // but the mapped memory's actual size will be smaller than the reported size.
105 if (memory.size() > SIZE_MAX) {
106 ALOGE("Cannot use memory with %" PRId64 " bytes because it is too large.", memory.size());
107 android_errorWriteLog(0x534e4554, "79376389");
108 return BAD_VALUE;
109 }
110
111 return _hidl_err;
112 }
113
writeEmbeddedToParcel(const hidl_memory & memory,Parcel * parcel,size_t parentHandle,size_t parentOffset)114 status_t writeEmbeddedToParcel(const hidl_memory &memory,
115 Parcel *parcel, size_t parentHandle, size_t parentOffset) {
116 // TODO(b/111883309): Invoke writeEmbeddedToParcel(hidl_handle, ...).
117 status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
118 memory.handle(),
119 parentHandle,
120 parentOffset + hidl_memory::kOffsetOfHandle);
121
122 if (_hidl_err == ::android::OK) {
123 _hidl_err = writeEmbeddedToParcel(
124 memory.name(),
125 parcel,
126 parentHandle,
127 parentOffset + hidl_memory::kOffsetOfName);
128 }
129
130 return _hidl_err;
131 }
132 const size_t hidl_string::kOffsetOfBuffer = offsetof(hidl_string, mBuffer);
133 static_assert(hidl_string::kOffsetOfBuffer == 0, "wrong offset");
134
readEmbeddedFromParcel(const hidl_string & string,const Parcel & parcel,size_t parentHandle,size_t parentOffset)135 status_t readEmbeddedFromParcel(const hidl_string &string ,
136 const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
137 const void *out;
138
139 status_t status = parcel.readEmbeddedBuffer(
140 string.size() + 1,
141 nullptr /* buffer_handle */,
142 parentHandle,
143 parentOffset + hidl_string::kOffsetOfBuffer,
144 &out);
145
146 if (status != OK) {
147 return status;
148 }
149
150 // Always safe to access out[string.size()] because we read size+1 bytes
151 if (static_cast<const char *>(out)[string.size()] != '\0') {
152 ALOGE("Received unterminated hidl_string buffer.");
153 return BAD_VALUE;
154 }
155
156 return OK;
157 }
158
writeEmbeddedToParcel(const hidl_string & string,Parcel * parcel,size_t parentHandle,size_t parentOffset)159 status_t writeEmbeddedToParcel(const hidl_string &string,
160 Parcel *parcel, size_t parentHandle, size_t parentOffset) {
161 return parcel->writeEmbeddedBuffer(
162 string.c_str(),
163 string.size() + 1,
164 nullptr /* handle */,
165 parentHandle,
166 parentOffset + hidl_string::kOffsetOfBuffer);
167 }
168
readFromParcel(Status * s,const Parcel & parcel)169 status_t readFromParcel(Status *s, const Parcel& parcel) {
170 int32_t exception;
171 status_t status = parcel.readInt32(&exception);
172 if (status != OK) {
173 s->setFromStatusT(status);
174 return status;
175 }
176
177 if (exception == Status::EX_NONE) {
178 *s = Status::ok();
179 return status;
180 }
181
182 // The remote threw an exception. Get the message back.
183 String16 message;
184 status = parcel.readString16(&message);
185 if (status != OK) {
186 s->setFromStatusT(status);
187 return status;
188 }
189
190 s->setException(exception, String8(message));
191
192 return status;
193 }
194
writeToParcel(const Status & s,Parcel * parcel)195 status_t writeToParcel(const Status &s, Parcel* parcel) {
196 // Something really bad has happened, and we're not going to even
197 // try returning rich error data.
198 if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
199 return s.transactionError();
200 }
201
202 status_t status = parcel->writeInt32(s.exceptionCode());
203 if (status != OK) { return status; }
204 if (s.exceptionCode() == Status::EX_NONE) {
205 // We have no more information to write.
206 return status;
207 }
208 status = parcel->writeString16(String16(s.exceptionMessage()));
209 return status;
210 }
211
212 // assume: iface != nullptr, iface isRemote
213 // This function is to sandbox a cast through a BpHw* class into a function, so
214 // that we can remove cfi sanitization from it. Do not add additional
215 // functionality here.
forceGetRefBase(::android::hidl::base::V1_0::IBase * ifacePtr)216 __attribute__((no_sanitize("cfi"))) static inline BpHwRefBase* forceGetRefBase(
217 ::android::hidl::base::V1_0::IBase* ifacePtr) {
218 using ::android::hidl::base::V1_0::BpHwBase;
219
220 // canary only
221 static_assert(sizeof(BpHwBase) == sizeof(hidl::manager::V1_0::BpHwServiceManager));
222 static_assert(sizeof(BpHwBase) == sizeof(hidl::manager::V1_1::BpHwServiceManager));
223 static_assert(sizeof(BpHwBase) == sizeof(hidl::manager::V1_2::BpHwServiceManager));
224
225 // All BpHw* are generated the same. This may be BpHwServiceManager,
226 // BpHwFoo, or any other class. For ABI compatibility, we can't modify the
227 // class hierarchy of these, so we have no way to get BpHwRefBase from a
228 // remote ifacePtr.
229 BpHwBase* bpBase = static_cast<BpHwBase*>(ifacePtr);
230 return static_cast<BpHwRefBase*>(bpBase);
231 }
232
getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase * ifacePtr)233 sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr) {
234 if (ifacePtr == nullptr) {
235 return nullptr;
236 }
237
238 if (ifacePtr->isRemote()) {
239 BpHwRefBase* bpRefBase = forceGetRefBase(ifacePtr);
240 return sp<IBinder>(bpRefBase->remote());
241 }
242
243 std::string descriptor = details::getDescriptor(ifacePtr);
244 if (descriptor.empty()) {
245 // interfaceDescriptor fails
246 return nullptr;
247 }
248
249 // for get + set
250 std::unique_lock<std::mutex> _lock = details::gBnMap->lock();
251
252 wp<BHwBinder> wBnObj = details::gBnMap->getLocked(ifacePtr, nullptr);
253 sp<IBinder> sBnObj = wBnObj.promote();
254
255 if (sBnObj == nullptr) {
256 auto func = details::getBnConstructorMap().get(descriptor, nullptr);
257 if (!func) {
258 // TODO(b/69122224): remove this static variable when prebuilts updated
259 func = details::gBnConstructorMap->get(descriptor, nullptr);
260 }
261 LOG_ALWAYS_FATAL_IF(func == nullptr, "%s gBnConstructorMap returned null for %s", __func__,
262 descriptor.c_str());
263
264 sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
265 LOG_ALWAYS_FATAL_IF(sBnObj == nullptr, "%s Bn constructor function returned null for %s",
266 __func__, descriptor.c_str());
267
268 details::gBnMap->setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get()));
269 }
270
271 return sBnObj;
272 }
273
274 static bool gThreadPoolConfigured = false;
275
configureBinderRpcThreadpool(size_t maxThreads,bool callerWillJoin)276 void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
277 status_t ret = ProcessState::self()->setThreadPoolConfiguration(
278 maxThreads, callerWillJoin /*callerJoinsPool*/);
279 LOG_ALWAYS_FATAL_IF(ret != OK, "Could not setThreadPoolConfiguration: %d", ret);
280
281 gThreadPoolConfigured = true;
282 }
283
joinBinderRpcThreadpool()284 void joinBinderRpcThreadpool() {
285 LOG_ALWAYS_FATAL_IF(!gThreadPoolConfigured,
286 "HIDL joinRpcThreadpool without calling configureRpcThreadPool.");
287 IPCThreadState::self()->joinThreadPool();
288 }
289
setupBinderPolling()290 int setupBinderPolling() {
291 int fd;
292 int err = IPCThreadState::self()->setupPolling(&fd);
293
294 LOG_ALWAYS_FATAL_IF(err != OK, "Failed to setup binder polling: %d (%s)", err, strerror(err));
295
296 return err == OK ? fd : -1;
297 }
298
handleBinderPoll()299 status_t handleBinderPoll() {
300 return IPCThreadState::self()->handlePolledCommands();
301 }
302
addPostCommandTask(const std::function<void (void)> task)303 void addPostCommandTask(const std::function<void(void)> task) {
304 IPCThreadState::self()->addPostCommandTask(task);
305 }
306
307 } // namespace hardware
308 } // namespace android
309