• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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