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