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