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