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