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 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 = nullptr, 129 uint32_t flags = 0); 130 virtual status_t unlinkToDeath( 131 const wp<IBinder::DeathRecipient>& recipient, 132 void* cookie = nullptr, 133 uint32_t flags = 0, 134 wp<IBinder::DeathRecipient>* outRecipient = nullptr); 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; 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 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); 185 virtual sp<HalInterface> getHalInterface() { return mHal; } 186 BaseInterface* getBaseInterface() { return mBase.get(); } 187 188 protected: 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 != nullptr) { \ 219 intr = static_cast<I##INTERFACE*>( \ 220 obj->queryLocalInterface( \ 221 I##INTERFACE::descriptor).get()); \ 222 if (intr == nullptr) { \ 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>:: 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>:: 262 linkToDeath( 263 const sp<IBinder::DeathRecipient>& recipient, 264 void* cookie, uint32_t flags) { 265 LOG_ALWAYS_FATAL_IF(recipient == nullptr, 266 "linkToDeath(): recipient must be non-nullptr"); 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>:: 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> 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