Pawin Vongmasa | fbffe92 | 2017-03-01 02:25:36 -0800 | [diff] [blame^] | 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_HALTOKEN_H |
| 18 | #define ANDROID_HALTOKEN_H |
| 19 | |
| 20 | #include <binder/Parcel.h> |
| 21 | #include <hidl/HidlSupport.h> |
| 22 | |
| 23 | /** |
| 24 | * It is possible to pass a hidl interface via as a binder interface by |
| 25 | * providing an appropriate "wrapper" class. |
| 26 | * |
| 27 | * Terminology: |
| 28 | * - `HalToken`: The type for a "token" of a hidl interface. This is defined to |
| 29 | * be compatible with `ITokenManager.hal`. |
| 30 | * - `HInterface`: The base type for a hidl interface. Currently, it is defined |
| 31 | * as `::android::hidl::base::V1_0::IBase`. |
| 32 | * - `HALINTERFACE`: The hidl interface that will be sent through binders. |
| 33 | * - `INTERFACE`: The binder interface that will be the wrapper of |
| 34 | * `HALINTERFACE`. `INTERFACE` is supposed to be similar to `HALINTERFACE`. |
| 35 | * |
| 36 | * To demonstrate how this is done, here is an example. Suppose `INTERFACE` is |
| 37 | * `IFoo` and `HALINTERFACE` is `HFoo`. The required steps are: |
| 38 | * 1. Use DECLARE_HYBRID_META_INTERFACE instead of DECLARE_META_INTERFACE in the |
| 39 | * definition of `IFoo`. The usage is |
| 40 | * DECLARE_HYBRID_META_INTERFACE(IFoo, HFoo) |
| 41 | * inside the body of `IFoo`. |
| 42 | * 2. Create a converter class that derives from |
| 43 | * `H2BConverter<HFoo, IFoo, BnFoo>`. Let us call this `H2BFoo`. |
| 44 | * 3. Add the following constructors in `H2BFoo` that call the corresponding |
| 45 | * constructors in `H2BConverter`: |
| 46 | * H2BFoo(const sp<HalInterface>& base) : CBase(base) {} |
| 47 | * Note: `CBase = H2BConverter<HFoo, IFoo, BnFoo>` and `HalInterface = HFoo` |
| 48 | * are member typedefs of `CBase`, so the above line can be copied verbatim |
| 49 | * into `H2BFoo`. |
| 50 | * 4. Add conversion functions inside `H2BFoo`. `H2BConverter` provides a |
| 51 | * protected `mBase` of type `sp<HFoo>` that can be used to access the HFoo |
| 52 | * instance. (There is also a public function named `getHalInterface()` that |
| 53 | * returns `mBase`.) |
| 54 | * 5. Create a hardware proxy class that derives from |
| 55 | * `HpInterface<BpFoo, H2BFoo>`. Name this class `HpFoo`. (This name cannot |
| 56 | * deviate. See step 8 below.) |
| 57 | * 6. Add the following constructor to `HpFoo`: |
| 58 | * HpFoo(const sp<IBinder>& base): PBase(base) {} |
| 59 | * Note: `PBase` a member typedef of `HpInterface<BpFoo, H2BFoo>` that is |
| 60 | * equal to `HpInterface<BpFoo, H2BFoo>` itself, so the above line can be |
| 61 | * copied verbatim into `HpFoo`. |
| 62 | * 7. Delegate all functions in `HpFoo` that come from `IFoo` except |
| 63 | * `getHalToken` and `getHalInterface` to the protected member `mBase`, |
| 64 | * which is defined in `HpInterface<BpFoo, H2BFoo>` (hence in `HpFoo`) with |
| 65 | * type `IFoo`. (There is also a public function named `getBaseInterface()` |
| 66 | * that returns `mBase`.) |
| 67 | * 8. Replace the existing `IMPLEMENT_META_INTERFACE` for INTERFACE by |
| 68 | * `IMPLEMENT_HYBRID_META_INTERFACE`. Note that this macro relies on the |
| 69 | * exact naming of `HpFoo`, where `Foo` comes from the interface name `IFoo`. |
| 70 | * An example usage is |
| 71 | * IMPLEMENT_HYBRID_META_INTERFACE(IFoo, HFoo, "example.interface.foo"); |
| 72 | * |
| 73 | * `GETTOKEN` Template Argument |
| 74 | * ============================ |
| 75 | * |
| 76 | * Following the instructions above, `H2BConverter` and `HpInterface` would use |
| 77 | * `transact()` to send over tokens, with `code` (the first argument of |
| 78 | * `transact()`) equal to a 4-byte value of '_GTK'. If this value clashes with |
| 79 | * other values already in use in the `Bp` class, it can be changed by supplying |
| 80 | * the last optional template argument to `H2BConverter` and `HpInterface`. |
| 81 | * |
| 82 | */ |
| 83 | |
| 84 | namespace android { |
| 85 | |
| 86 | typedef uint64_t HalToken; |
| 87 | typedef ::android::hidl::base::V1_0::IBase HInterface; |
| 88 | |
| 89 | sp<HInterface> retrieveHalInterface(const HalToken& token); |
| 90 | bool createHalToken(const sp<HInterface>& interface, HalToken* token); |
| 91 | bool deleteHalToken(const HalToken& token); |
| 92 | |
| 93 | template < |
| 94 | typename HINTERFACE, |
| 95 | typename INTERFACE, |
| 96 | typename BNINTERFACE, |
| 97 | uint32_t GETTOKEN = '_GTK'> |
| 98 | class H2BConverter : public BNINTERFACE { |
| 99 | public: |
| 100 | typedef H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN> CBase; |
| 101 | typedef INTERFACE BaseInterface; |
| 102 | typedef HINTERFACE HalInterface; |
| 103 | static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN; |
| 104 | |
| 105 | H2BConverter(const sp<HalInterface>& base) : mBase(base) {} |
| 106 | virtual status_t onTransact(uint32_t code, |
| 107 | const Parcel& data, Parcel* reply, uint32_t flags = 0); |
| 108 | sp<HalInterface> getHalInterface() override { return mBase; } |
| 109 | HalInterface* getBaseInterface() { return mBase.get(); } |
| 110 | |
| 111 | protected: |
| 112 | sp<HalInterface> mBase; |
| 113 | }; |
| 114 | |
| 115 | template <typename BPINTERFACE, typename CONVERTER, uint32_t GETTOKEN = '_GTK'> |
| 116 | class HpInterface : public BPINTERFACE { |
| 117 | public: |
| 118 | typedef HpInterface<BPINTERFACE, CONVERTER, GETTOKEN> PBase; // Proxy Base |
| 119 | typedef typename CONVERTER::BaseInterface BaseInterface; |
| 120 | typedef typename CONVERTER::HalInterface HalInterface; |
| 121 | static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN; |
| 122 | |
| 123 | explicit HpInterface(const sp<IBinder>& impl); |
| 124 | sp<HalInterface> getHalInterface() override { return mHal; } |
| 125 | BaseInterface* getBaseInterface() { return mBase.get(); } |
| 126 | |
| 127 | protected: |
| 128 | sp<BaseInterface> mBase; |
| 129 | sp<HalInterface> mHal; |
| 130 | }; |
| 131 | |
| 132 | // ---------------------------------------------------------------------- |
| 133 | |
| 134 | #define DECLARE_HYBRID_META_INTERFACE(INTERFACE, HAL) \ |
| 135 | static const ::android::String16 descriptor; \ |
| 136 | static ::android::sp<I##INTERFACE> asInterface( \ |
| 137 | const ::android::sp<::android::IBinder>& obj); \ |
| 138 | virtual const ::android::String16& getInterfaceDescriptor() const; \ |
| 139 | I##INTERFACE(); \ |
| 140 | virtual ~I##INTERFACE(); \ |
| 141 | virtual sp<HAL> getHalInterface(); \ |
| 142 | |
| 143 | |
| 144 | #define IMPLEMENT_HYBRID_META_INTERFACE(INTERFACE, HAL, NAME) \ |
| 145 | const ::android::String16 I##INTERFACE::descriptor(NAME); \ |
| 146 | const ::android::String16& \ |
| 147 | I##INTERFACE::getInterfaceDescriptor() const { \ |
| 148 | return I##INTERFACE::descriptor; \ |
| 149 | } \ |
| 150 | ::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ |
| 151 | const ::android::sp<::android::IBinder>& obj) \ |
| 152 | { \ |
| 153 | ::android::sp<I##INTERFACE> intr; \ |
| 154 | if (obj != NULL) { \ |
| 155 | intr = static_cast<I##INTERFACE*>( \ |
| 156 | obj->queryLocalInterface( \ |
| 157 | I##INTERFACE::descriptor).get()); \ |
| 158 | if (intr == NULL) { \ |
| 159 | intr = new Hp##INTERFACE(obj); \ |
| 160 | } \ |
| 161 | } \ |
| 162 | return intr; \ |
| 163 | } \ |
| 164 | I##INTERFACE::I##INTERFACE() { } \ |
| 165 | I##INTERFACE::~I##INTERFACE() { } \ |
| 166 | sp<HAL> I##INTERFACE::getHalInterface() { return nullptr; } \ |
| 167 | |
| 168 | // ---------------------------------------------------------------------- |
| 169 | |
| 170 | template < |
| 171 | typename HINTERFACE, |
| 172 | typename INTERFACE, |
| 173 | typename BNINTERFACE, |
| 174 | uint32_t GETTOKEN> |
| 175 | status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>:: |
| 176 | onTransact( |
| 177 | uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { |
| 178 | if (code == GET_HAL_TOKEN) { |
| 179 | HalToken token; |
| 180 | bool result; |
| 181 | result = createHalToken(mBase, &token); |
| 182 | if (!result) { |
| 183 | ALOGE("H2BConverter: Failed to create HAL token."); |
| 184 | } |
| 185 | reply->writeBool(result); |
| 186 | reply->writeUint64(token); |
| 187 | return NO_ERROR; |
| 188 | } |
| 189 | return BNINTERFACE::onTransact(code, data, reply, flags); |
| 190 | } |
| 191 | |
| 192 | template <typename BPINTERFACE, typename CONVERTER, uint32_t GETTOKEN> |
| 193 | HpInterface<BPINTERFACE, CONVERTER, GETTOKEN>::HpInterface( |
| 194 | const sp<IBinder>& impl): |
| 195 | BPINTERFACE(impl), |
| 196 | mBase(nullptr) { |
| 197 | |
| 198 | Parcel data, reply; |
| 199 | data.writeInterfaceToken(BaseInterface::getInterfaceDescriptor()); |
| 200 | if (this->remote()->transact(GET_HAL_TOKEN, data, &reply) == NO_ERROR) { |
| 201 | bool tokenCreated = reply.readBool(); |
| 202 | HalToken token = reply.readUint64(); |
| 203 | if (!tokenCreated) { |
| 204 | ALOGE("HpInterface: Sender failed to create HAL token."); |
| 205 | mBase = this; |
| 206 | } else { |
| 207 | sp<HInterface> hInterface = retrieveHalInterface(token); |
| 208 | deleteHalToken(token); |
| 209 | if (hInterface != nullptr) { |
| 210 | mHal = static_cast<HalInterface*>(hInterface.get()); |
| 211 | mBase = new CONVERTER(mHal); |
| 212 | } else { |
| 213 | ALOGE("HpInterface: Cannot retrieve HAL interface from token."); |
| 214 | mBase = this; |
| 215 | } |
| 216 | } |
| 217 | } else { |
| 218 | mBase = this; |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | // ---------------------------------------------------------------------- |
| 223 | |
| 224 | }; // namespace android |
| 225 | |
| 226 | #endif // ANDROID_HALTOKEN_H |