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
35namespace android {
36namespace hardware {
37
38// hidl_binder_death_recipient wraps a transport-independent
39// hidl_death_recipient, and implements the binder-specific
40// DeathRecipient interface.
41struct 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();
46private:
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
54status_t readEmbeddedFromParcel(const hidl_memory &memory,
55        const Parcel &parcel, size_t parentHandle, size_t parentOffset);
56
57status_t writeEmbeddedToParcel(const hidl_memory &memory,
58        Parcel *parcel, size_t parentHandle, size_t parentOffset);
59
60// ---------------------- hidl_string
61
62status_t readEmbeddedFromParcel(const hidl_string &string,
63        const Parcel &parcel, size_t parentHandle, size_t parentOffset);
64
65status_t writeEmbeddedToParcel(const hidl_string &string,
66        Parcel *parcel, size_t parentHandle, size_t parentOffset);
67
68// ---------------------- hidl_version
69
70status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel);
71
72// Caller is responsible for freeing the returned object.
73hidl_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.
79status_t readFromParcel(Status *status, const Parcel& parcel);
80status_t writeToParcel(const Status &status, Parcel* parcel);
81
82// ---------------------- hidl_vec
83
84template<typename T>
85status_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
100template<typename T>
101status_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
115template<typename T>
116status_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
122template<typename T, MQFlavor flavor>
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
152template<typename T, MQFlavor flavor>
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
183template <typename T>
184static 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
208template <typename T>
209static 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
249template <typename T>
250static 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
266template <typename T>
267static 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.
309template <typename IType,
310          typename = std::enable_if_t<std::is_same<details::i_tag, typename IType::_hidl_tag>::value>>
311sp<IBinder> toBinder(sp<IType> iface) {
312    IType *ifacePtr = iface.get();
313    if (ifacePtr == nullptr) {
314        return nullptr;
315    }
316    if (ifacePtr->isRemote()) {
317        return ::android::hardware::IInterface::asBinder(
318            static_cast<BpInterface<IType>*>(ifacePtr));
319    } else {
320        std::string myDescriptor = details::getDescriptor(ifacePtr);
321        if (myDescriptor.empty()) {
322            // interfaceDescriptor fails
323            return nullptr;
324        }
325
326        // for get + set
327        std::unique_lock<std::mutex> _lock = details::gBnMap.lock();
328
329        wp<BHwBinder> wBnObj = details::gBnMap.getLocked(ifacePtr, nullptr);
330        sp<IBinder> sBnObj = wBnObj.promote();
331
332        if (sBnObj == nullptr) {
333            auto func = details::getBnConstructorMap().get(myDescriptor, nullptr);
334            if (!func) {
335                func = details::gBnConstructorMap.get(myDescriptor, nullptr);
336                if (!func) {
337                    return nullptr;
338                }
339            }
340
341            sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
342
343            if (sBnObj != nullptr) {
344                details::gBnMap.setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get()));
345            }
346        }
347
348        return sBnObj;
349    }
350}
351
352template <typename IType, typename ProxyType, typename StubType>
353sp<IType> fromBinder(const sp<IBinder>& binderIface) {
354    using ::android::hidl::base::V1_0::IBase;
355    using ::android::hidl::base::V1_0::BnHwBase;
356
357    if (binderIface.get() == nullptr) {
358        return nullptr;
359    }
360    if (binderIface->localBinder() == nullptr) {
361        return new ProxyType(binderIface);
362    }
363    sp<IBase> base = static_cast<BnHwBase*>(binderIface.get())->getImpl();
364    if (details::canCastInterface(base.get(), IType::descriptor)) {
365        StubType* stub = static_cast<StubType*>(binderIface.get());
366        return stub->getImpl();
367    } else {
368        return nullptr;
369    }
370}
371
372void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin);
373void joinBinderRpcThreadpool();
374int setupBinderPolling();
375status_t handleBinderPoll();
376
377}  // namespace hardware
378}  // namespace android
379
380
381#endif  // ANDROID_HIDL_BINDER_SUPPORT_H
382