HidlBinderSupport.h revision 7e6404dd880b1f25c932f264c0ba2e00e79c536e
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/BnBase.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 *ptr = parcel.readEmbeddedBuffer(
99            handle,
100            parentHandle,
101            parentOffset + hidl_vec<T>::kOffsetOfBuffer);
102
103    return ptr != NULL ? OK : UNKNOWN_ERROR;
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 = parcel.readEmbeddedNativeHandle(
148            parentHandle,
149            parentOffset + MQDescriptor<T, flavor>::kOffsetOfHandle);
150
151    if (_hidl_mq_handle_ptr == nullptr) {
152        _hidl_err = ::android::UNKNOWN_ERROR;
153        return _hidl_err;
154    }
155
156    return _hidl_err;
157}
158
159template<typename T, MQFlavor flavor>
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
190template <typename T>
191static 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
215template <typename T>
216static 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
256template <typename T>
257static 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
273template <typename T>
274static 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// Construct a smallest possible binder from the given interface.
312// If it is remote, then its remote() will be retrieved.
313// Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
314// and iface is of class IChild. BnChild will be used to wrapped the given iface.
315// Return nullptr if iface is null or any failure.
316template <typename IType, typename ProxyType>
317sp<IBinder> toBinder(sp<IType> iface) {
318    IType *ifacePtr = iface.get();
319    if (ifacePtr == nullptr) {
320        return nullptr;
321    }
322    if (ifacePtr->isRemote()) {
323        return ::android::hardware::IInterface::asBinder(static_cast<ProxyType *>(ifacePtr));
324    } else {
325        std::string myDescriptor = getDescriptor(ifacePtr);
326        if (myDescriptor.empty()) {
327            // interfaceChain fails
328            return nullptr;
329        }
330        auto iter = gBnConstructorMap.find(myDescriptor);
331        if (iter == gBnConstructorMap.end()) {
332            return nullptr;
333        }
334        return sp<IBinder>((iter->second)(reinterpret_cast<void *>(ifacePtr)));
335    }
336}
337
338template <typename IType, typename ProxyType, typename StubType>
339sp<IType> fromBinder(const sp<IBinder>& binderIface) {
340    using ::android::hidl::base::V1_0::IBase;
341    using ::android::hidl::base::V1_0::BnBase;
342
343    if (binderIface.get() == nullptr) {
344        return nullptr;
345    }
346    if (binderIface->localBinder() == nullptr) {
347        return new ProxyType(binderIface);
348    }
349    sp<IBase> base = static_cast<BnBase*>(binderIface.get())->getImpl();
350    if (canCastInterface(base.get(), IType::descriptor)) {
351        StubType* stub = static_cast<StubType*>(binderIface.get());
352        return stub->getImpl();
353    } else {
354        return nullptr;
355    }
356}
357
358inline void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
359    ProcessState::self()->setThreadPoolConfiguration(maxThreads, callerWillJoin /*callerJoinsPool*/);
360}
361
362inline void joinBinderRpcThreadpool() {
363    IPCThreadState::self()->joinThreadPool();
364}
365
366}  // namespace hardware
367}  // namespace android
368
369
370#endif  // ANDROID_HIDL_BINDER_SUPPORT_H
371