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