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