• 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 #include <cinttypes>
27 #include <variant>
28 
29 /**
30  * Hybrid Interfaces
31  * =================
32  *
33  * A hybrid interface is a binder interface that
34  * 1. is implemented both traditionally and as a wrapper around a hidl
35  *    interface, and allows querying whether the underlying instance comes from
36  *    a hidl interface or not; and
37  * 2. allows efficient calls to a hidl interface (if the underlying instance
38  *    comes from a hidl interface) by automatically creating the wrapper in the
39  *    process that calls it.
40  *
41  * Terminology:
42  * - `HalToken`: The type for a "token" of a hidl interface. This is defined to
43  *   be compatible with `ITokenManager.hal`.
44  * - `HInterface`: The base type for a hidl interface. Currently, it is defined
45  *   as `::android::hidl::base::V1_0::IBase`.
46  * - `HALINTERFACE`: The hidl interface that will be sent through binders.
47  * - `INTERFACE`: The binder interface that will be the wrapper of
48  *   `HALINTERFACE`. `INTERFACE` is supposed to be somewhat similar to
49  *   `HALINTERFACE`.
50  *
51  * To demonstrate how this is done, here is an example. Suppose `INTERFACE` is
52  * `IFoo` and `HALINTERFACE` is `HFoo`. The required steps are:
53  * 1. Use `DECLARE_HYBRID_META_INTERFACE` instead of `DECLARE_META_INTERFACE` in
54  *    the declaration of `IFoo`. `DECLARE_HYBRID_META_INTERFACE` takes an
55  *    additional argument that is the hidl interface to be converted into a
56  *    binder interface. Example:
57  *        Change from `DECLARE_META_INTERFACE(Foo)`
58  *                 to `DECLARE_HYBRID_META_INTERFACE(Foo, HFoo)`
59  * 2. Create a converter class that derives from
60  *    `H2BConverter<HFoo, BnFoo>`. Let us call this `H2BFoo`.
61  * 3. Add the following constructor in `H2BFoo` that call the corresponding
62  *    constructors in `H2BConverter`:
63  *        `H2BFoo(const sp<HalInterface>& base) : CBase(base) {}`
64  *    Note: `CBase = H2BConverter<HFoo, BnFoo>` and `HalInterface = HFoo` are
65  *    member typedefs of `H2BConverter<HFoo, BnFoo>`, so the above line can be
66  *    copied verbatim into `H2BFoo`.
67  * 4. Implement `IFoo` in `H2BFoo` on top of `HFoo`. `H2BConverter` provides a
68  *    protected `mBase` of type `sp<HFoo>` that can be used to access the `HFoo`
69  *    instance. (There is also a public function named `getBase()` that returns
70  *    `mBase`.)
71  * 5. Create a hardware proxy class that derives from
72  *    `HpInterface<BpFoo, H2BFoo>`. Name this class `HpFoo`. (This name cannot
73  *    deviate. See step 8 below.)
74  * 6. Add the following constructor to `HpFoo`:
75  *        `HpFoo(const sp<IBinder>& base): PBase(base) {}`
76  *    Note: `PBase` a member typedef of `HpInterface<BpFoo, H2BFoo>` that is
77  *    equal to `HpInterface<BpFoo, H2BFoo>` itself, so the above line can be
78  *    copied verbatim into `HpFoo`.
79  * 7. Delegate all functions in `HpFoo` that come from `IFoo` (except those that
80  *    are defined by the macro `DECLARE_HYBRID_META_INTERFACE`) to the protected
81  *    member `mBase`. `mBase` is defined in `HpInterface<BpFoo, H2BFoo>` (hence
82  *    in `HpFoo`) with type `IFoo`. There is also a public function named
83  *    `getBase()` that returns `mBase`.
84  * 8. Replace the existing `IMPLEMENT_META_INTERFACE` for `IFoo` by
85  *    `IMPLEMENT_HYBRID_META_INTERFACE`. This macro assumes that the subclass of
86  *    `HpInterface` for `IFoo` is named `HpFoo`.
87  *
88  * After the hybrid interface has been put in place properly, it can be used to
89  * do the following tasks:
90  * 1. Create an `IFoo` instance from an `HFoo` by passing `sp<HFoo>` to
91  *    the constructor of `H2BFoo`.
92  * 2. Retrieve an `HFoo` from an `HpFoo` instance by calling
93  *    `HpFoo::getHalInterface<HFoo>()`. This function may return `nullptr` if
94  *    the `HpFoo` object is not backed by `HFoo`. The template parameter is
95  *    required because `HpFoo` in fact may be backed by multiple H2B converter
96  *    classes.
97  *
98  * Multiple H2B Converters
99  * =======================
100  *
101  * Because the system may support multiple versions of hidl interfaces for the
102  * same object, one binder interface may correspond to multiple H2B converters.
103  * The hybrid interface is designed to handle this as
104  * well---`DECLARE_HYBRID_META_INTERFACE` and `HpInterface` can take a variable
105  * number of arguments.
106  *
107  * As a concrete example, suppose `IFoo` is a binder interface that corresponds
108  * to two hidl interfaces `HFoo1` and `HFoo2`. That means `HpFoo`, the hybrid
109  * interface presenting `IFoo`, may be backed by `HFoo1` or `HFoo2`. This is
110  * achievable by
111  *
112  *   - Replacing `DECLARE_META_INTERFACE(Foo)` by
113  *     `DECLARE_HYBRID_META_INTERFACE(Foo, HFoo1, HFoo2)` in the declaration of
114  *     `IFoo`.
115  *   - Creating `H2BFoo1` as a subclass of `H2BConverter<HFoo1, BnFoo>`;
116  *   - Creating `H2BFoo2` as a subclass of `H2BConverter<HFoo2, BnFoo>`; and
117  *   - Creating `HpFoo` as a subclass of `HpInterface<BpFoo, H2BFoo1, H2BFoo2>`.
118  *
119  * It is important that `HFoo1` and `HFoo2` are different hidl interfaces. [The
120  * actual requirement is that for each pair `<HFoo, IFoo>`, there can be only
121  * one subclass of `H2BConverter<HFoo, BnFoo>`.]
122  *
123  * As mentioned in the previous section, `HpFoo::getHalInterface` requires a
124  * template argument because it must be able to return different hidl
125  * interface types based on which hidl interface is being used. The user of
126  * `HpFoo` can query the type of the underlying hidl interface by calling
127  * `HpFoo::getHalIndex()`. The return value is a 1-based index into the list of
128  * all the supported hidl interfaces. In the example with 2 hidl interfaces
129  * `HFoo1` and `HFoo2`, index 1 corresponds to `HFoo1` and index 2 corresponds
130  * to `HFoo2`. A typical code block that accesses the underlying hidl interface
131  * of would look like this:
132  *
133  * void someFunction(const sp<IFoo> &foo) {
134  *
135  *     switch (foo->getHalIndex()) {
136  *     case 1: {
137  *             sp<HFoo1> hFoo1 = foo->getHalInterface<HFoo1>();
138  *             ...
139  *             break;
140  *         }
141  *     case 2: {
142  *             sp<HFoo2> hFoo2 = foo->getHalInterface<HFoo2>();
143  *             ...
144  *             break;
145  *         }
146  *     default: // Not backed by a hidl interface.
147  *              // Alternatively, "case 0:" can be used.
148  *     }
149  *
150  * }
151  *
152  * Error State
153  * ===========
154  *
155  * A corrupted transaction may cause an `HpInterface` to be in an error state.
156  * This could cause `getHalInterface<ExpectedHalInterface>()` to return
157  * `nullptr` even though `getHalIndex()` returns a non-zero index and
158  * `ExpectedHalInterface` is the corresponding hidl interface. It is therefore
159  * recommended that a null check be performed on the return value of
160  * `getHalInterface` before using it.
161  *
162  * DECLARE_HYBRID_META_INTERFACE_WITH_CODE
163  * =======================================
164  *
165  * `H2BConverter` and `HpInterface` use `transact()` to send over tokens with
166  * the transaction code (the first argument of `transact()`) equal to `_GHT`,
167  * which is defined as a global constant named
168  * `DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE`.
169  *
170  * In the rare occasion that this value clashes with other values already used
171  * by the `Bp` class and modifying the `Bp` class is difficult, the
172  * "GET_HAL_TOKEN" transaction code can be changed to a different value simply
173  * by replacing `DECLARE_HYBRID_META_INTERFACE` with
174  * `DECLARE_HYBRID_META_INTERFACE_WITH_CODE` in the declaration of the base
175  * interface and supplying the new transaction code in the first argument of
176  * this macro.
177  *
178  */
179 
180 namespace android {
181 
182 typedef ::android::hardware::hidl_vec<uint8_t> HalToken;
183 typedef ::android::hidl::base::V1_0::IBase HInterface;
184 
185 constexpr uint32_t DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE =
186         B_PACK_CHARS('_', 'G', 'H', 'T');
187 
188 sp<HInterface> retrieveHalInterface(const HalToken& token);
189 bool createHalToken(const sp<HInterface>& interface, HalToken* token);
190 bool deleteHalToken(const HalToken& token);
191 
192 template <typename HINTERFACE,
193           typename BNINTERFACE>
194 class H2BConverter : public BNINTERFACE {
195 public:
196     typedef H2BConverter<HINTERFACE, BNINTERFACE> CBase; // Converter Base
197     typedef typename BNINTERFACE::BaseInterface BaseInterface;
198     typedef HINTERFACE HalInterface;
199     typedef typename BaseInterface::HalVariant HalVariant;
200     using BaseInterface::sGetHalTokenTransactionCode;
201 
H2BConverter(const sp<HalInterface> & base)202     H2BConverter(const sp<HalInterface>& base) : mBase{base} {}
203     virtual status_t onTransact(uint32_t code,
204             const Parcel& data, Parcel* reply, uint32_t flags = 0);
205     virtual status_t linkToDeath(
206             const sp<IBinder::DeathRecipient>& recipient,
207             void* cookie = nullptr,
208             uint32_t flags = 0);
209     virtual status_t unlinkToDeath(
210             const wp<IBinder::DeathRecipient>& recipient,
211             void* cookie = nullptr,
212             uint32_t flags = 0,
213             wp<IBinder::DeathRecipient>* outRecipient = nullptr);
getHalVariant()214     virtual HalVariant getHalVariant() const override { return { mBase }; }
getBase()215     HalInterface* getBase() { return mBase.get(); }
216 
217 protected:
218     sp<HalInterface> mBase;
219 
220 private:
221     struct Obituary : public hardware::hidl_death_recipient {
222         wp<IBinder::DeathRecipient> recipient;
223         void* cookie;
224         uint32_t flags;
225         wp<IBinder> who;
ObituaryObituary226         Obituary(
227                 const wp<IBinder::DeathRecipient>& r,
228                 void* c, uint32_t f,
229                 const wp<IBinder>& w) :
230             recipient(r), cookie(c), flags(f), who(w) {
231         }
ObituaryObituary232         Obituary(const Obituary& o) :
233             recipient(o.recipient),
234             cookie(o.cookie),
235             flags(o.flags),
236             who(o.who) {
237         }
238         Obituary& operator=(const Obituary& o) {
239             recipient = o.recipient;
240             cookie = o.cookie;
241             flags = o.flags;
242             who = o.who;
243             return *this;
244         }
serviceDiedObituary245         void serviceDied(uint64_t, const wp<HInterface>&) override {
246             sp<IBinder::DeathRecipient> dr = recipient.promote();
247             if (dr != nullptr) {
248                 dr->binderDied(who);
249             }
250         }
251     };
252     std::mutex mObituariesLock;
253     std::vector<sp<Obituary> > mObituaries;
254 
255     template <size_t Index = std::variant_size_v<HalVariant> - 1>
_findIndex()256     static constexpr size_t _findIndex() {
257         if constexpr (Index == 0) {
258             return Index;
259         } else if constexpr (
260                 std::is_same_v<
261                     std::variant_alternative_t<Index, HalVariant>,
262                     sp<HalInterface>>) {
263             return Index;
264         } else {
265             return _findIndex<Index - 1>();
266         }
267     }
268 
269     static constexpr size_t sHalIndex = _findIndex<>();
270     static_assert(sHalIndex != 0,
271                   "H2BConverter from an unrecognized HAL interface.");
272 };
273 
274 template <typename BPINTERFACE, typename CONVERTER, typename... CONVERTERS>
275 class HpInterface : public CONVERTER::BaseInterface {
276 public:
277     typedef HpInterface<BPINTERFACE, CONVERTER, CONVERTERS...> PBase; // Proxy Base
278     typedef typename CONVERTER::BaseInterface BaseInterface;
279     typedef typename BaseInterface::HalVariant HalVariant;
280     using BaseInterface::sGetHalTokenTransactionCode;
281 
282     explicit HpInterface(const sp<IBinder>& impl);
getBase()283     BaseInterface* getBase() { return mBase.get(); }
getHalVariant()284     virtual HalVariant getHalVariant() const override { return mHalVariant; }
285 
286 protected:
287     IBinder* mBpBinder;
288     sp<BPINTERFACE> mBp;
289     sp<BaseInterface> mBase;
290     HalVariant mHalVariant;
291     bool mHasConverter{false};
onAsBinder()292     IBinder* onAsBinder() override { return mBpBinder; }
293 
294 private:
295     typedef std::variant<std::monostate,
296             CONVERTER, CONVERTERS...> _ConverterVar;
297     typedef std::variant<std::monostate,
298             typename CONVERTER::HalInterface,
299             typename CONVERTERS::HalInterface...> _ConverterHalVar;
300     typedef std::variant<std::monostate,
301             sp<typename CONVERTER::HalInterface>,
302             sp<typename CONVERTERS::HalInterface>...> _ConverterHalPointerVar;
303 
304     static_assert(std::is_same_v<_ConverterHalPointerVar, HalVariant>,
305                   "Converter classes do not match HAL interfaces.");
306 
307     template <size_t Index = std::variant_size_v<HalVariant> - 1>
_castFromHalBaseAndConvert(size_t halIndex,const sp<HInterface> & halBase)308     bool _castFromHalBaseAndConvert(size_t halIndex,
309                                     const sp<HInterface>& halBase) {
310         if constexpr (Index == 0) {
311             return false;
312         } else {
313             if (halIndex != Index) {
314                 return _castFromHalBaseAndConvert<Index - 1>(halIndex, halBase);
315             }
316             typedef std::variant_alternative_t<Index, _ConverterHalVar>
317                     HalInterface;
318             sp<HalInterface> halInterface = HalInterface::castFrom(halBase);
319             mHalVariant.template emplace<Index>(halInterface);
320             if (!halInterface) {
321                 return false;
322             }
323             if (mHasConverter) {
324                 typedef std::variant_alternative_t<Index, _ConverterVar>
325                         Converter;
326                 sp<Converter> converter = sp<Converter>::make(halInterface);
327                 if (converter) {
328                     mBase = converter;
329                 } else {
330                     ALOGW("HpInterface: Failed to create an H2B converter -- "
331                           "index = %zu.", Index);
332                 }
333             }
334             return true;
335         }
336     }
337 
castFromHalBaseAndConvert(size_t halIndex,const sp<HInterface> & halBase)338     bool castFromHalBaseAndConvert(size_t halIndex,
339                                    const sp<HInterface>& halBase) {
340         if (!_castFromHalBaseAndConvert<>(halIndex, halBase)) {
341             return false;
342         }
343         return true;
344     }
345 
346 };
347 
348 // ----------------------------------------------------------------------
349 
350 #define DECLARE_HYBRID_META_INTERFACE(INTERFACE, ...)                                          \
351     DECLARE_HYBRID_META_INTERFACE_WITH_CODE(::android::DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE, \
352                                             INTERFACE, __VA_ARGS__)
353 
354 #define DECLARE_HYBRID_META_INTERFACE_WITH_CODE(GTKCODE, INTERFACE, ...)                          \
355   private:                                                                                        \
356     typedef ::std::variant<::std::monostate, __VA_ARGS__> _HalVariant;                            \
357     template <typename... Types>                                                                  \
358     using _SpVariant = ::std::variant<::std::monostate, ::android::sp<Types>...>;                 \
359                                                                                                   \
360   public:                                                                                         \
361     typedef _SpVariant<__VA_ARGS__> HalVariant;                                                   \
362     virtual HalVariant getHalVariant() const;                                                     \
363     size_t getHalIndex() const;                                                                   \
364     template <size_t Index>                                                                       \
365     using HalInterface = ::std::variant_alternative_t<Index, _HalVariant>;                        \
366     template <typename HAL>                                                                       \
367     sp<HAL> getHalInterface() const {                                                             \
368         HalVariant halVariant = getHalVariant();                                                  \
369         const sp<HAL>* hal = std::get_if<sp<HAL>>(&halVariant);                                   \
370         return hal ? *hal : nullptr;                                                              \
371     }                                                                                             \
372                                                                                                   \
373     static const ::android::String16 descriptor;                                                  \
374     static ::android::sp<I##INTERFACE> asInterface(const ::android::sp<::android::IBinder>& obj); \
375     virtual const ::android::String16& getInterfaceDescriptor() const;                            \
376     I##INTERFACE();                                                                               \
377     virtual ~I##INTERFACE();                                                                      \
378     static constexpr uint32_t sGetHalTokenTransactionCode = GTKCODE;
379 
380 #define IMPLEMENT_HYBRID_META_INTERFACE(INTERFACE, NAME)                                       \
381     I##INTERFACE::HalVariant I##INTERFACE::getHalVariant() const {                             \
382         return HalVariant{std::in_place_index<0>};                                             \
383     }                                                                                          \
384     size_t I##INTERFACE::getHalIndex() const {                                                 \
385         return getHalVariant().index();                                                        \
386     }                                                                                          \
387     constexpr uint32_t I##INTERFACE::sGetHalTokenTransactionCode;                              \
388     static const ::android::StaticString16 I##INTERFACE##_desc_str16(u##NAME);                 \
389     const ::android::String16 I##INTERFACE::descriptor(I##INTERFACE##_desc_str16);             \
390     const ::android::String16& I##INTERFACE::getInterfaceDescriptor() const {                  \
391         return I##INTERFACE::descriptor;                                                       \
392     }                                                                                          \
393     ::android::sp<I##INTERFACE> I##INTERFACE::asInterface(                                     \
394             const ::android::sp<::android::IBinder>& obj) {                                    \
395         ::android::sp<I##INTERFACE> intr;                                                      \
396         if (obj != nullptr) {                                                                  \
397             intr = sp<I##INTERFACE>::cast(obj->queryLocalInterface(I##INTERFACE::descriptor)); \
398             if (intr == nullptr) {                                                             \
399                 intr = sp<Hp##INTERFACE>::make(obj);                                           \
400             }                                                                                  \
401         }                                                                                      \
402         return intr;                                                                           \
403     }                                                                                          \
404     I##INTERFACE::I##INTERFACE() {}                                                            \
405     I##INTERFACE::~I##INTERFACE() {}
406 
407 // ----------------------------------------------------------------------
408 
409 template <typename HINTERFACE,
410           typename BNINTERFACE>
411 status_t H2BConverter<HINTERFACE, BNINTERFACE>::
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)412         onTransact(
413         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
414     if (code == sGetHalTokenTransactionCode) {
415         if (!data.enforceInterface(BaseInterface::getInterfaceDescriptor())) {
416             return BAD_TYPE;
417         }
418 
419         HalToken token;
420         bool result;
421         result = createHalToken(mBase, &token);
422         // Write whether a HAL token is present.
423         reply->writeBool(result);
424         if (!result) {
425             ALOGE("H2BConverter: Failed to create HAL token.");
426             return NO_ERROR;
427         }
428 
429         // Write the HAL token.
430         reply->writeByteArray(token.size(), token.data());
431 
432         // Write the HAL index.
433         reply->writeUint32(static_cast<uint32_t>(sHalIndex));
434 
435         // Write a flag indicating that a converter needs to be created.
436         reply->writeBool(true);
437 
438         return NO_ERROR;
439     }
440     return BNINTERFACE::onTransact(code, data, reply, flags);
441 }
442 
443 template <typename HINTERFACE,
444           typename BNINTERFACE>
linkToDeath(const sp<IBinder::DeathRecipient> & recipient,void * cookie,uint32_t flags)445 status_t H2BConverter<HINTERFACE, BNINTERFACE>::linkToDeath(
446         const sp<IBinder::DeathRecipient>& recipient,
447         void* cookie, uint32_t flags) {
448     LOG_ALWAYS_FATAL_IF(
449             recipient == nullptr,
450             "linkToDeath(): recipient must not be null.");
451     {
452         std::lock_guard<std::mutex> lock(mObituariesLock);
453         mObituaries.push_back(
454                 sp<Obituary>::make(recipient, cookie, flags, wp<IBinder>::fromExisting(this)));
455         if (!mBase->linkToDeath(mObituaries.back(), 0)) {
456            return DEAD_OBJECT;
457         }
458     }
459     return NO_ERROR;
460 }
461 
462 template <typename HINTERFACE,
463           typename BNINTERFACE>
unlinkToDeath(const wp<IBinder::DeathRecipient> & recipient,void * cookie,uint32_t flags,wp<IBinder::DeathRecipient> * outRecipient)464 status_t H2BConverter<HINTERFACE, BNINTERFACE>::unlinkToDeath(
465         const wp<IBinder::DeathRecipient>& recipient,
466         void* cookie, uint32_t flags,
467         wp<IBinder::DeathRecipient>* outRecipient) {
468     std::lock_guard<std::mutex> lock(mObituariesLock);
469     for (auto i = mObituaries.begin(); i != mObituaries.end(); ++i) {
470         if ((flags = (*i)->flags) && (
471                 (recipient == (*i)->recipient) ||
472                 ((recipient == nullptr) && (cookie == (*i)->cookie)))) {
473             if (outRecipient != nullptr) {
474                 *outRecipient = (*i)->recipient;
475             }
476             bool success = mBase->unlinkToDeath(*i);
477             mObituaries.erase(i);
478             return success ? NO_ERROR : DEAD_OBJECT;
479         }
480     }
481     return NAME_NOT_FOUND;
482 }
483 
484 template <typename BPINTERFACE, typename CONVERTER, typename... CONVERTERS>
HpInterface(const sp<IBinder> & impl)485 HpInterface<BPINTERFACE, CONVERTER, CONVERTERS...>::HpInterface(const sp<IBinder>& impl)
486     : mBpBinder{impl.get()}, mBp{sp<BPINTERFACE>::make(impl)} {
487     mBase = mBp;
488     if (!mBpBinder->remoteBinder()) {
489         return;
490     }
491     Parcel data, reply;
492     data.writeInterfaceToken(BaseInterface::getInterfaceDescriptor());
493     if (mBpBinder->transact(sGetHalTokenTransactionCode,
494                             data, &reply) == NO_ERROR) {
495         // Read whether a HAL token is present.
496         bool tokenCreated;
497         if (reply.readBool(&tokenCreated) != OK) {
498             ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
499                   "(tokenCreated).");
500         }
501 
502         if (!tokenCreated) {
503             ALOGW("HpInterface: No HAL token was created.");
504             return;
505         }
506 
507         // Read the HAL token.
508         std::vector<uint8_t> tokenVector;
509         if (reply.readByteVector(&tokenVector) != OK) {
510             ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
511                   "(halToken).");
512             return;
513         }
514 
515         // Retrieve the HAL interface from the token.
516         HalToken token{tokenVector};
517         sp<HInterface> halBase = retrieveHalInterface(token);
518         deleteHalToken(token);
519 
520         if (!halBase) {
521             ALOGW("HpInterface: Failed to retrieve HAL interface.");
522             return;
523         }
524 
525         uint32_t halIndex;
526         // Read the hal index.
527         if (reply.readUint32(&halIndex) != OK) {
528             ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
529                   "(halIndex).");
530             return;
531         }
532 
533         // Read the converter flag.
534         if (reply.readBool(&mHasConverter) != OK) {
535             ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
536                   "(hasConverter).");
537             return;
538         }
539 
540         // Call castFrom from the right HAL interface and create a converter if
541         // needed.
542         if (!castFromHalBaseAndConvert(static_cast<size_t>(halIndex),
543                                        halBase)) {
544             ALOGW("HpInterface: Failed to cast to the correct HAL interface -- "
545                   "HAL index = %" PRIu32 ".", halIndex);
546         }
547     }
548 }
549 
550 // ----------------------------------------------------------------------
551 
552 }  // namespace android
553 
554 #endif // ANDROID_HYBRIDINTERFACE_H
555