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 #ifndef ANDROID_HIDL_BINDER_SUPPORT_H
18 #define ANDROID_HIDL_BINDER_SUPPORT_H
19 
20 #include <sys/types.h>
21 
22 #include <android/hidl/base/1.0/BnHwBase.h>
23 #include <android/hidl/base/1.0/IBase.h>
24 #include <hidl/HidlSupport.h>
25 #include <hidl/HidlTransportUtils.h>
26 #include <hidl/MQDescriptor.h>
27 #include <hidl/Static.h>
28 #include <hwbinder/IBinder.h>
29 #include <hwbinder/IPCThreadState.h>
30 #include <hwbinder/Parcel.h>
31 #include <hwbinder/ProcessState.h>
32 // Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor,
33 // etc. to interact with Parcel.
34 
35 namespace android {
36 namespace hardware {
37 
38 // hidl_binder_death_recipient wraps a transport-independent
39 // hidl_death_recipient, and implements the binder-specific
40 // DeathRecipient interface.
41 struct hidl_binder_death_recipient : IBinder::DeathRecipient {
hidl_binder_death_recipienthidl_binder_death_recipient42     hidl_binder_death_recipient(const sp<hidl_death_recipient> &recipient,
43             uint64_t cookie, const sp<::android::hidl::base::V1_0::IBase> &base) :
44         mRecipient(recipient), mCookie(cookie), mBase(base) {
45     }
binderDiedhidl_binder_death_recipient46     virtual void binderDied(const wp<IBinder>& /*who*/) {
47         sp<hidl_death_recipient> recipient = mRecipient.promote();
48         if (recipient != nullptr) {
49             recipient->serviceDied(mCookie, mBase);
50         }
51     }
getRecipienthidl_binder_death_recipient52     wp<hidl_death_recipient> getRecipient() {
53         return mRecipient;
54     }
55 private:
56     wp<hidl_death_recipient> mRecipient;
57     uint64_t mCookie;
58     wp<::android::hidl::base::V1_0::IBase> mBase;
59 };
60 
61 // ---------------------- hidl_memory
62 
63 status_t readEmbeddedFromParcel(const hidl_memory &memory,
64         const Parcel &parcel, size_t parentHandle, size_t parentOffset);
65 
66 status_t writeEmbeddedToParcel(const hidl_memory &memory,
67         Parcel *parcel, size_t parentHandle, size_t parentOffset);
68 
69 // ---------------------- hidl_string
70 
71 status_t readEmbeddedFromParcel(const hidl_string &string,
72         const Parcel &parcel, size_t parentHandle, size_t parentOffset);
73 
74 status_t writeEmbeddedToParcel(const hidl_string &string,
75         Parcel *parcel, size_t parentHandle, size_t parentOffset);
76 
77 // ---------------------- hidl_version
78 
79 status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel);
80 
81 // Caller is responsible for freeing the returned object.
82 hidl_version* readFromParcel(const android::hardware::Parcel& parcel);
83 
84 // ---------------------- Status
85 
86 // Bear in mind that if the client or service is a Java endpoint, this
87 // is not the logic which will provide/interpret the data here.
88 status_t readFromParcel(Status *status, const Parcel& parcel);
89 status_t writeToParcel(const Status &status, Parcel* parcel);
90 
91 // ---------------------- hidl_vec
92 
93 template<typename T>
readEmbeddedFromParcel(const hidl_vec<T> & vec,const Parcel & parcel,size_t parentHandle,size_t parentOffset,size_t * handle)94 status_t readEmbeddedFromParcel(
95         const hidl_vec<T> &vec,
96         const Parcel &parcel,
97         size_t parentHandle,
98         size_t parentOffset,
99         size_t *handle) {
100     const void *out;
101     return parcel.readNullableEmbeddedBuffer(
102             vec.size() * sizeof(T),
103             handle,
104             parentHandle,
105             parentOffset + hidl_vec<T>::kOffsetOfBuffer,
106             &out);
107 }
108 
109 template<typename T>
writeEmbeddedToParcel(const hidl_vec<T> & vec,Parcel * parcel,size_t parentHandle,size_t parentOffset,size_t * handle)110 status_t writeEmbeddedToParcel(
111         const hidl_vec<T> &vec,
112         Parcel *parcel,
113         size_t parentHandle,
114         size_t parentOffset,
115         size_t *handle) {
116     return parcel->writeEmbeddedBuffer(
117             vec.data(),
118             sizeof(T) * vec.size(),
119             handle,
120             parentHandle,
121             parentOffset + hidl_vec<T>::kOffsetOfBuffer);
122 }
123 
124 template<typename T>
findInParcel(const hidl_vec<T> & vec,const Parcel & parcel,size_t * handle)125 status_t findInParcel(const hidl_vec<T> &vec, const Parcel &parcel, size_t *handle) {
126     return parcel.quickFindBuffer(vec.data(), handle);
127 }
128 
129 // ---------------------- MQDescriptor
130 
131 template<typename T, MQFlavor flavor>
readEmbeddedFromParcel(MQDescriptor<T,flavor> & obj,const::android::hardware::Parcel & parcel,size_t parentHandle,size_t parentOffset)132 ::android::status_t readEmbeddedFromParcel(
133         MQDescriptor<T, flavor> &obj,
134         const ::android::hardware::Parcel &parcel,
135         size_t parentHandle,
136         size_t parentOffset) {
137     ::android::status_t _hidl_err = ::android::OK;
138 
139     size_t _hidl_grantors_child;
140 
141     _hidl_err = ::android::hardware::readEmbeddedFromParcel(
142                 obj.grantors(),
143                 parcel,
144                 parentHandle,
145                 parentOffset + MQDescriptor<T, flavor>::kOffsetOfGrantors,
146                 &_hidl_grantors_child);
147 
148     if (_hidl_err != ::android::OK) { return _hidl_err; }
149 
150     const native_handle_t *_hidl_mq_handle_ptr;
151    _hidl_err = parcel.readNullableEmbeddedNativeHandle(
152             parentHandle,
153             parentOffset + MQDescriptor<T, flavor>::kOffsetOfHandle,
154             &_hidl_mq_handle_ptr);
155 
156     if (_hidl_err != ::android::OK) { return _hidl_err; }
157 
158     return _hidl_err;
159 }
160 
161 template<typename T, MQFlavor flavor>
writeEmbeddedToParcel(const MQDescriptor<T,flavor> & obj,::android::hardware::Parcel * parcel,size_t parentHandle,size_t parentOffset)162 ::android::status_t writeEmbeddedToParcel(
163         const MQDescriptor<T, flavor> &obj,
164         ::android::hardware::Parcel *parcel,
165         size_t parentHandle,
166         size_t parentOffset) {
167     ::android::status_t _hidl_err = ::android::OK;
168 
169     size_t _hidl_grantors_child;
170 
171     _hidl_err = ::android::hardware::writeEmbeddedToParcel(
172             obj.grantors(),
173             parcel,
174             parentHandle,
175             parentOffset + MQDescriptor<T, flavor>::kOffsetOfGrantors,
176             &_hidl_grantors_child);
177 
178     if (_hidl_err != ::android::OK) { return _hidl_err; }
179 
180     _hidl_err = parcel->writeEmbeddedNativeHandle(
181             obj.handle(),
182             parentHandle,
183             parentOffset + MQDescriptor<T, flavor>::kOffsetOfHandle);
184 
185     if (_hidl_err != ::android::OK) { return _hidl_err; }
186 
187     return _hidl_err;
188 }
189 
190 // ---------------------- pointers for HIDL
191 
192 template <typename T>
readEmbeddedReferenceFromParcel(T const **,const Parcel & parcel,size_t parentHandle,size_t parentOffset,size_t * handle,bool * shouldResolveRefInBuffer)193 static status_t readEmbeddedReferenceFromParcel(
194         T const* * /* bufptr */,
195         const Parcel & parcel,
196         size_t parentHandle,
197         size_t parentOffset,
198         size_t *handle,
199         bool *shouldResolveRefInBuffer
200     ) {
201     // *bufptr is ignored because, if I am embedded in some
202     // other buffer, the kernel should have fixed me up already.
203     bool isPreviouslyWritten;
204     status_t result = parcel.readEmbeddedReference(
205         nullptr, // ignored, not written to bufptr.
206         handle,
207         parentHandle,
208         parentOffset,
209         &isPreviouslyWritten);
210     // tell caller to run T::readEmbeddedToParcel and
211     // T::readEmbeddedReferenceToParcel if necessary.
212     // It is not called here because we don't know if these two are valid methods.
213     *shouldResolveRefInBuffer = !isPreviouslyWritten;
214     return result;
215 }
216 
217 template <typename T>
writeEmbeddedReferenceToParcel(T const * buf,Parcel * parcel,size_t parentHandle,size_t parentOffset,size_t * handle,bool * shouldResolveRefInBuffer)218 static status_t writeEmbeddedReferenceToParcel(
219         T const* buf,
220         Parcel *parcel, size_t parentHandle, size_t parentOffset,
221         size_t *handle,
222         bool *shouldResolveRefInBuffer
223         ) {
224 
225     if(buf == nullptr) {
226         *shouldResolveRefInBuffer = false;
227         return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset);
228     }
229 
230     // find whether the buffer exists
231     size_t childHandle, childOffset;
232     status_t result;
233     bool found;
234 
235     result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
236 
237     // tell caller to run T::writeEmbeddedToParcel and
238     // T::writeEmbeddedReferenceToParcel if necessary.
239     // It is not called here because we don't know if these two are valid methods.
240     *shouldResolveRefInBuffer = !found;
241 
242     if(result != OK) {
243         return result; // bad pointers and length given
244     }
245     if(!found) { // did not find it.
246         return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle,
247                 parentHandle, parentOffset);
248     }
249     // found the buffer. easy case.
250     return parcel->writeEmbeddedReference(
251             handle,
252             childHandle,
253             childOffset,
254             parentHandle,
255             parentOffset);
256 }
257 
258 template <typename T>
readReferenceFromParcel(T const ** bufptr,const Parcel & parcel,size_t * handle,bool * shouldResolveRefInBuffer)259 static status_t readReferenceFromParcel(
260         T const* *bufptr,
261         const Parcel & parcel,
262         size_t *handle,
263         bool *shouldResolveRefInBuffer
264     ) {
265     bool isPreviouslyWritten;
266     status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr),
267             handle, &isPreviouslyWritten);
268     // tell caller to run T::readEmbeddedToParcel and
269     // T::readEmbeddedReferenceToParcel if necessary.
270     // It is not called here because we don't know if these two are valid methods.
271     *shouldResolveRefInBuffer = !isPreviouslyWritten;
272     return result;
273 }
274 
275 template <typename T>
writeReferenceToParcel(T const * buf,Parcel * parcel,size_t * handle,bool * shouldResolveRefInBuffer)276 static status_t writeReferenceToParcel(
277         T const *buf,
278         Parcel * parcel,
279         size_t *handle,
280         bool *shouldResolveRefInBuffer
281     ) {
282 
283     if(buf == nullptr) {
284         *shouldResolveRefInBuffer = false;
285         return parcel->writeNullReference(handle);
286     }
287 
288     // find whether the buffer exists
289     size_t childHandle, childOffset;
290     status_t result;
291     bool found;
292 
293     result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
294 
295     // tell caller to run T::writeEmbeddedToParcel and
296     // T::writeEmbeddedReferenceToParcel if necessary.
297     // It is not called here because we don't know if these two are valid methods.
298     *shouldResolveRefInBuffer = !found;
299 
300     if(result != OK) {
301         return result; // bad pointers and length given
302     }
303     if(!found) { // did not find it.
304         return parcel->writeBuffer(buf, sizeof(T), handle);
305     }
306     // found the buffer. easy case.
307     return parcel->writeReference(handle,
308         childHandle, childOffset);
309 }
310 
311 // ---------------------- support for casting interfaces
312 
313 // Construct a smallest possible binder from the given interface.
314 // If it is remote, then its remote() will be retrieved.
315 // Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
316 // and iface is of class IChild. BnChild will be used to wrapped the given iface.
317 // Return nullptr if iface is null or any failure.
318 template <typename IType, typename ProxyType>
toBinder(sp<IType> iface)319 sp<IBinder> toBinder(sp<IType> iface) {
320     IType *ifacePtr = iface.get();
321     if (ifacePtr == nullptr) {
322         return nullptr;
323     }
324     if (ifacePtr->isRemote()) {
325         return ::android::hardware::IInterface::asBinder(static_cast<ProxyType *>(ifacePtr));
326     } else {
327         std::string myDescriptor = details::getDescriptor(ifacePtr);
328         if (myDescriptor.empty()) {
329             // interfaceDescriptor fails
330             return nullptr;
331         }
332         auto func = details::gBnConstructorMap.get(myDescriptor, nullptr);
333         if (!func) {
334             return nullptr;
335         }
336         return sp<IBinder>(func(static_cast<void *>(ifacePtr)));
337     }
338 }
339 
340 template <typename IType, typename ProxyType, typename StubType>
fromBinder(const sp<IBinder> & binderIface)341 sp<IType> fromBinder(const sp<IBinder>& binderIface) {
342     using ::android::hidl::base::V1_0::IBase;
343     using ::android::hidl::base::V1_0::BnHwBase;
344 
345     if (binderIface.get() == nullptr) {
346         return nullptr;
347     }
348     if (binderIface->localBinder() == nullptr) {
349         return new ProxyType(binderIface);
350     }
351     sp<IBase> base = static_cast<BnHwBase*>(binderIface.get())->getImpl();
352     if (details::canCastInterface(base.get(), IType::descriptor)) {
353         StubType* stub = static_cast<StubType*>(binderIface.get());
354         return stub->getImpl();
355     } else {
356         return nullptr;
357     }
358 }
359 
360 void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin);
361 void joinBinderRpcThreadpool();
362 
363 }  // namespace hardware
364 }  // namespace android
365 
366 
367 #endif  // ANDROID_HIDL_BINDER_SUPPORT_H
368