1/*
2 * Copyright (C) 2017 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_HYBRIDINTERFACE_H
18#define ANDROID_HYBRIDINTERFACE_H
19
20#include <vector>
21#include <mutex>
22
23#include <binder/Parcel.h>
24#include <hidl/HidlSupport.h>
25
26/**
27 * Hybrid Interfaces
28 * =================
29 *
30 * A hybrid interface is a binder interface that
31 * 1. is implemented both traditionally and as a wrapper around a hidl
32 *    interface, and allows querying whether the underlying instance comes from
33 *    a hidl interface or not; and
34 * 2. allows efficient calls to a hidl interface (if the underlying instance
35 *    comes from a hidl interface) by automatically creating the wrapper in the
36 *    process that calls it.
37 *
38 * Terminology:
39 * - `HalToken`: The type for a "token" of a hidl interface. This is defined to
40 *   be compatible with `ITokenManager.hal`.
41 * - `HInterface`: The base type for a hidl interface. Currently, it is defined
42 *   as `::android::hidl::base::V1_0::IBase`.
43 * - `HALINTERFACE`: The hidl interface that will be sent through binders.
44 * - `INTERFACE`: The binder interface that will be the wrapper of
45 *   `HALINTERFACE`. `INTERFACE` is supposed to be somewhat similar to
46 *   `HALINTERFACE`.
47 *
48 * To demonstrate how this is done, here is an example. Suppose `INTERFACE` is
49 * `IFoo` and `HALINTERFACE` is `HFoo`. The required steps are:
50 * 1. Use DECLARE_HYBRID_META_INTERFACE instead of DECLARE_META_INTERFACE in the
51 *    definition of `IFoo`. The usage is
52 *        DECLARE_HYBRID_META_INTERFACE(IFoo, HFoo)
53 *    inside the body of `IFoo`.
54 * 2. Create a converter class that derives from
55 *    `H2BConverter<HFoo, IFoo, BnFoo>`. Let us call this `H2BFoo`.
56 * 3. Add the following constructor in `H2BFoo` that call the corresponding
57 *    constructors in `H2BConverter`:
58 *        H2BFoo(const sp<HalInterface>& base) : CBase(base) {}
59 *    Note: `CBase = H2BConverter<HFoo, IFoo, BnFoo>` and `HalInterface = HFoo`
60 *    are member typedefs of `H2BConverter<HFoo, IFoo, BnFoo>`, so the above
61 *    line can be copied into `H2BFoo`.
62 * 4. Implement `IFoo` in `H2BFoo` on top of `HFoo`. `H2BConverter` provides a
63 *    protected `mBase` of type `sp<HFoo>` that can be used to access the `HFoo`
64 *    instance. (There is also a public function named `getHalInterface()` that
65 *    returns `mBase`.)
66 * 5. Create a hardware proxy class that derives from
67 *    `HpInterface<BpFoo, H2BFoo>`. Name this class `HpFoo`. (This name cannot
68 *    deviate. See step 8 below.)
69 * 6. Add the following constructor to `HpFoo`:
70 *        HpFoo(const sp<IBinder>& base): PBase(base) {}
71 *    Note: `PBase` a member typedef of `HpInterface<BpFoo, H2BFoo>` that is
72 *    equal to `HpInterface<BpFoo, H2BFoo>` itself, so the above line can be
73 *    copied verbatim into `HpFoo`.
74 * 7. Delegate all functions in `HpFoo` that come from `IFoo` except
75 *    `getHalInterface` to the protected member `mBase`,
76 *    which is defined in `HpInterface<BpFoo, H2BFoo>` (hence in `HpFoo`) with
77 *    type `IFoo`. (There is also a public function named `getBaseInterface()`
78 *    that returns `mBase`.)
79 * 8. Replace the existing `IMPLEMENT_META_INTERFACE` for INTERFACE by
80 *    `IMPLEMENT_HYBRID_META_INTERFACE`. Note that this macro relies on the
81 *    exact naming of `HpFoo`, where `Foo` comes from the interface name `IFoo`.
82 *    An example usage is
83 *        IMPLEMENT_HYBRID_META_INTERFACE(IFoo, HFoo, "example.interface.foo");
84 *
85 * `GETTOKEN` Template Argument
86 * ============================
87 *
88 * Following the instructions above, `H2BConverter` and `HpInterface` would use
89 * `transact()` to send over tokens, with `code` (the first argument of
90 * `transact()`) equal to `DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE`. If this
91 * value clashes with other values already in use in the `Bp` class, it can be
92 * changed by supplying the last optional template argument to `H2BConverter`
93 * and `HpInterface`.
94 *
95 */
96
97namespace android {
98
99typedef ::android::hardware::hidl_vec<uint8_t> HalToken;
100typedef ::android::hidl::base::V1_0::IBase HInterface;
101
102constexpr uint32_t DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE =
103        B_PACK_CHARS('_', 'G', 'H', 'T');
104
105sp<HInterface> retrieveHalInterface(const HalToken& token);
106bool createHalToken(const sp<HInterface>& interface, HalToken* token);
107bool deleteHalToken(const HalToken& token);
108
109template <
110        typename HINTERFACE,
111        typename INTERFACE,
112        typename BNINTERFACE,
113        uint32_t GETTOKEN = DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE>
114class H2BConverter : public BNINTERFACE {
115public:
116    typedef H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN> CBase; // Converter Base
117    typedef INTERFACE BaseInterface;
118    typedef HINTERFACE HalInterface;
119    static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN;
120
121    H2BConverter(const sp<HalInterface>& base) : mBase(base) {}
122    virtual status_t onTransact(uint32_t code,
123            const Parcel& data, Parcel* reply, uint32_t flags = 0);
124    virtual sp<HalInterface> getHalInterface() { return mBase; }
125    HalInterface* getBaseInterface() { return mBase.get(); }
126    virtual status_t linkToDeath(
127            const sp<IBinder::DeathRecipient>& recipient,
128            void* cookie = NULL,
129            uint32_t flags = 0);
130    virtual status_t unlinkToDeath(
131            const wp<IBinder::DeathRecipient>& recipient,
132            void* cookie = NULL,
133            uint32_t flags = 0,
134            wp<IBinder::DeathRecipient>* outRecipient = NULL);
135
136protected:
137    sp<HalInterface> mBase;
138    struct Obituary : public hardware::hidl_death_recipient {
139        wp<IBinder::DeathRecipient> recipient;
140        void* cookie;
141        uint32_t flags;
142        wp<IBinder> who;
143        Obituary(
144                const wp<IBinder::DeathRecipient>& r,
145                void* c, uint32_t f,
146                const wp<IBinder>& w) :
147            recipient(r), cookie(c), flags(f), who(w) {
148        }
149        Obituary(const Obituary& o) :
150            recipient(o.recipient),
151            cookie(o.cookie),
152            flags(o.flags),
153            who(o.who) {
154        }
155        Obituary& operator=(const Obituary& o) {
156            recipient = o.recipient;
157            cookie = o.cookie;
158            flags = o.flags;
159            who = o.who;
160            return *this;
161        }
162        void serviceDied(uint64_t, const wp<HInterface>&) override {
163            sp<IBinder::DeathRecipient> dr = recipient.promote();
164            if (dr != nullptr) {
165                dr->binderDied(who);
166            }
167        }
168    };
169    std::mutex mObituariesLock;
170    std::vector<sp<Obituary> > mObituaries;
171};
172
173template <
174        typename BPINTERFACE,
175        typename CONVERTER,
176        uint32_t GETTOKEN = DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE>
177class HpInterface : public CONVERTER::BaseInterface {
178public:
179    typedef HpInterface<BPINTERFACE, CONVERTER, GETTOKEN> PBase; // Proxy Base
180    typedef typename CONVERTER::BaseInterface BaseInterface;
181    typedef typename CONVERTER::HalInterface HalInterface;
182    static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN;
183
184    explicit HpInterface(const sp<IBinder>& impl);
185    virtual sp<HalInterface> getHalInterface() { return mHal; }
186    BaseInterface* getBaseInterface() { return mBase.get(); }
187
188protected:
189    IBinder* mImpl;
190    sp<BPINTERFACE> mBp;
191    sp<BaseInterface> mBase;
192    sp<HalInterface> mHal;
193    IBinder* onAsBinder() override { return mImpl; }
194};
195
196// ----------------------------------------------------------------------
197
198#define DECLARE_HYBRID_META_INTERFACE(INTERFACE, HAL)                   \
199    static const ::android::String16 descriptor;                        \
200    static ::android::sp<I##INTERFACE> asInterface(                     \
201            const ::android::sp<::android::IBinder>& obj);              \
202    virtual const ::android::String16& getInterfaceDescriptor() const;  \
203    I##INTERFACE();                                                     \
204    virtual ~I##INTERFACE();                                            \
205    virtual sp<HAL> getHalInterface();                                  \
206
207
208#define IMPLEMENT_HYBRID_META_INTERFACE(INTERFACE, HAL, NAME)           \
209    const ::android::String16 I##INTERFACE::descriptor(NAME);           \
210    const ::android::String16&                                          \
211            I##INTERFACE::getInterfaceDescriptor() const {              \
212        return I##INTERFACE::descriptor;                                \
213    }                                                                   \
214    ::android::sp<I##INTERFACE> I##INTERFACE::asInterface(              \
215            const ::android::sp<::android::IBinder>& obj)               \
216    {                                                                   \
217        ::android::sp<I##INTERFACE> intr;                               \
218        if (obj != NULL) {                                              \
219            intr = static_cast<I##INTERFACE*>(                          \
220                obj->queryLocalInterface(                               \
221                        I##INTERFACE::descriptor).get());               \
222            if (intr == NULL) {                                         \
223                intr = new Hp##INTERFACE(obj);                          \
224            }                                                           \
225        }                                                               \
226        return intr;                                                    \
227    }                                                                   \
228    I##INTERFACE::I##INTERFACE() { }                                    \
229    I##INTERFACE::~I##INTERFACE() { }                                   \
230    sp<HAL> I##INTERFACE::getHalInterface() { return nullptr; }         \
231
232// ----------------------------------------------------------------------
233
234template <
235        typename HINTERFACE,
236        typename INTERFACE,
237        typename BNINTERFACE,
238        uint32_t GETTOKEN>
239status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
240        onTransact(
241        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
242    if (code == GET_HAL_TOKEN) {
243        HalToken token;
244        bool result;
245        result = createHalToken(mBase, &token);
246        if (!result) {
247            ALOGE("H2BConverter: Failed to create HAL token.");
248        }
249        reply->writeBool(result);
250        reply->writeByteArray(token.size(), token.data());
251        return NO_ERROR;
252    }
253    return BNINTERFACE::onTransact(code, data, reply, flags);
254}
255
256template <
257        typename HINTERFACE,
258        typename INTERFACE,
259        typename BNINTERFACE,
260        uint32_t GETTOKEN>
261status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
262        linkToDeath(
263        const sp<IBinder::DeathRecipient>& recipient,
264        void* cookie, uint32_t flags) {
265    LOG_ALWAYS_FATAL_IF(recipient == NULL,
266            "linkToDeath(): recipient must be non-NULL");
267    {
268        std::lock_guard<std::mutex> lock(mObituariesLock);
269        mObituaries.push_back(new Obituary(recipient, cookie, flags, this));
270        if (!mBase->linkToDeath(mObituaries.back(), 0)) {
271           return DEAD_OBJECT;
272        }
273    }
274    return NO_ERROR;
275}
276
277template <
278        typename HINTERFACE,
279        typename INTERFACE,
280        typename BNINTERFACE,
281        uint32_t GETTOKEN>
282status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
283        unlinkToDeath(
284        const wp<IBinder::DeathRecipient>& recipient,
285        void* cookie, uint32_t flags,
286        wp<IBinder::DeathRecipient>* outRecipient) {
287    std::lock_guard<std::mutex> lock(mObituariesLock);
288    for (auto i = mObituaries.begin(); i != mObituaries.end(); ++i) {
289        if ((flags = (*i)->flags) && (
290                (recipient == (*i)->recipient) ||
291                ((recipient == nullptr) && (cookie == (*i)->cookie)))) {
292            if (outRecipient != nullptr) {
293                *outRecipient = (*i)->recipient;
294            }
295            bool success = mBase->unlinkToDeath(*i);
296            mObituaries.erase(i);
297            return success ? NO_ERROR : DEAD_OBJECT;
298        }
299    }
300    return NAME_NOT_FOUND;
301}
302
303template <typename BPINTERFACE, typename CONVERTER, uint32_t GETTOKEN>
304HpInterface<BPINTERFACE, CONVERTER, GETTOKEN>::HpInterface(
305        const sp<IBinder>& impl) :
306    mImpl(impl.get()),
307    mBp(new BPINTERFACE(impl)) {
308    mBase = mBp;
309    if (mImpl->remoteBinder() == nullptr) {
310        return;
311    }
312    Parcel data, reply;
313    data.writeInterfaceToken(BaseInterface::getInterfaceDescriptor());
314    if (mImpl->transact(GET_HAL_TOKEN, data, &reply) == NO_ERROR) {
315        bool tokenCreated = reply.readBool();
316
317        std::vector<uint8_t> tokenVector;
318        reply.readByteVector(&tokenVector);
319        HalToken token = HalToken(tokenVector);
320
321        if (tokenCreated) {
322            sp<HInterface> hBase = retrieveHalInterface(token);
323            if (hBase != nullptr) {
324                mHal = HalInterface::castFrom(hBase);
325                if (mHal != nullptr) {
326                    mBase = new CONVERTER(mHal);
327                } else {
328                    ALOGE("HpInterface: Wrong interface type.");
329                }
330            } else {
331                ALOGE("HpInterface: Invalid HAL token.");
332            }
333            deleteHalToken(token);
334        }
335    }
336}
337
338// ----------------------------------------------------------------------
339
340}; // namespace android
341
342#endif // ANDROID_HYBRIDINTERFACE_H
343