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