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