• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
97 namespace android {
98 
99 typedef ::android::hardware::hidl_vec<uint8_t> HalToken;
100 typedef ::android::hidl::base::V1_0::IBase HInterface;
101 
102 constexpr uint32_t DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE =
103         B_PACK_CHARS('_', 'G', 'H', 'T');
104 
105 sp<HInterface> retrieveHalInterface(const HalToken& token);
106 bool createHalToken(const sp<HInterface>& interface, HalToken* token);
107 bool deleteHalToken(const HalToken& token);
108 
109 template <
110         typename HINTERFACE,
111         typename INTERFACE,
112         typename BNINTERFACE,
113         uint32_t GETTOKEN = DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE>
114 class H2BConverter : public BNINTERFACE {
115 public:
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 
H2BConverter(const sp<HalInterface> & base)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);
getHalInterface()124     virtual sp<HalInterface> getHalInterface() { return mBase; }
getBaseInterface()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 
136 protected:
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;
ObituaryObituary143         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         }
ObituaryObituary149         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         }
serviceDiedObituary162         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 
173 template <
174         typename BPINTERFACE,
175         typename CONVERTER,
176         uint32_t GETTOKEN = DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE>
177 class HpInterface : public CONVERTER::BaseInterface {
178 public:
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);
getHalInterface()185     virtual sp<HalInterface> getHalInterface() { return mHal; }
getBaseInterface()186     BaseInterface* getBaseInterface() { return mBase.get(); }
187 
188 protected:
189     IBinder* mImpl;
190     sp<BPINTERFACE> mBp;
191     sp<BaseInterface> mBase;
192     sp<HalInterface> mHal;
onAsBinder()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 
234 template <
235         typename HINTERFACE,
236         typename INTERFACE,
237         typename BNINTERFACE,
238         uint32_t GETTOKEN>
239 status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)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 
256 template <
257         typename HINTERFACE,
258         typename INTERFACE,
259         typename BNINTERFACE,
260         uint32_t GETTOKEN>
261 status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
linkToDeath(const sp<IBinder::DeathRecipient> & recipient,void * cookie,uint32_t flags)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 
277 template <
278         typename HINTERFACE,
279         typename INTERFACE,
280         typename BNINTERFACE,
281         uint32_t GETTOKEN>
282 status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
unlinkToDeath(const wp<IBinder::DeathRecipient> & recipient,void * cookie,uint32_t flags,wp<IBinder::DeathRecipient> * outRecipient)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 
303 template <typename BPINTERFACE, typename CONVERTER, uint32_t GETTOKEN>
HpInterface(const sp<IBinder> & impl)304 HpInterface<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