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