blob: 8c2cd61418cb9e0bea4d70b3309705de68d04884 [file] [log] [blame]
Yifan Hong7f97f442016-11-14 18:31:05 -08001/*
2 * Copyright (C) 2016 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_HIDL_BINDER_SUPPORT_H
18#define ANDROID_HIDL_BINDER_SUPPORT_H
19
20#include <hidl/HidlSupport.h>
Martijn Coenen12f04d92016-12-07 17:29:41 +010021#include <hidl/HidlTransportUtils.h>
Yifan Hong7f97f442016-11-14 18:31:05 -080022#include <hidl/MQDescriptor.h>
Yifan Hongb2c9c752016-12-07 15:15:41 -080023#include <hidl/Static.h>
Yifan Hong7f97f442016-11-14 18:31:05 -080024#include <hwbinder/IBinder.h>
25#include <hwbinder/Parcel.h>
Martijn Coenen12f04d92016-12-07 17:29:41 +010026#include <android/hidl/base/1.0/BnBase.h>
Yifan Hong7f97f442016-11-14 18:31:05 -080027// Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor,
28// etc. to interact with Parcel.
29
30namespace android {
31namespace hardware {
32
Martijn Coenen30791002016-12-01 15:40:46 +010033// ---------------------- hidl_memory
34
35status_t readEmbeddedFromParcel(hidl_memory *memory,
36 const Parcel &parcel, size_t parentHandle, size_t parentOffset);
37
38status_t writeEmbeddedToParcel(const hidl_memory &memory,
39 Parcel *parcel, size_t parentHandle, size_t parentOffset);
40
Yifan Hong7f97f442016-11-14 18:31:05 -080041// ---------------------- hidl_string
42
43status_t readEmbeddedFromParcel(hidl_string *string,
44 const Parcel &parcel, size_t parentHandle, size_t parentOffset);
45
46status_t writeEmbeddedToParcel(const hidl_string &string,
47 Parcel *parcel, size_t parentHandle, size_t parentOffset);
48
49// ---------------------- hidl_version
50
51status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel);
52
53// Caller is responsible for freeing the returned object.
54hidl_version* readFromParcel(const android::hardware::Parcel& parcel);
55
56// ---------------------- Status
57
58// Bear in mind that if the client or service is a Java endpoint, this
59// is not the logic which will provide/interpret the data here.
60status_t readFromParcel(Status *status, const Parcel& parcel);
61status_t writeToParcel(const Status &status, Parcel* parcel);
62
63// ---------------------- hidl_vec
64
65template<typename T>
66status_t readEmbeddedFromParcel(
67 hidl_vec<T> * /*vec*/,
68 const Parcel &parcel,
69 size_t parentHandle,
70 size_t parentOffset,
71 size_t *handle) {
72 const void *ptr = parcel.readEmbeddedBuffer(
73 handle,
74 parentHandle,
75 parentOffset + hidl_vec<T>::kOffsetOfBuffer);
76
77 return ptr != NULL ? OK : UNKNOWN_ERROR;
78}
79
80template<typename T>
81status_t writeEmbeddedToParcel(
82 const hidl_vec<T> &vec,
83 Parcel *parcel,
84 size_t parentHandle,
85 size_t parentOffset,
86 size_t *handle) {
87 return parcel->writeEmbeddedBuffer(
88 vec.data(),
89 sizeof(T) * vec.size(),
90 handle,
91 parentHandle,
92 parentOffset + hidl_vec<T>::kOffsetOfBuffer);
93}
94
95template<typename T>
96status_t findInParcel(const hidl_vec<T> &vec, const Parcel &parcel, size_t *handle) {
97 return parcel.quickFindBuffer(vec.data(), handle);
98}
99
100// ---------------------- MQDescriptor
101
102template<MQFlavor flavor>
103::android::status_t readEmbeddedFromParcel(
104 MQDescriptor<flavor> *obj,
105 const ::android::hardware::Parcel &parcel,
106 size_t parentHandle,
107 size_t parentOffset) {
108 ::android::status_t _hidl_err = ::android::OK;
109
110 size_t _hidl_grantors_child;
111
112 _hidl_err = ::android::hardware::readEmbeddedFromParcel(
113 &obj->grantors(),
114 parcel,
115 parentHandle,
116 parentOffset + MQDescriptor<flavor>::kOffsetOfGrantors,
117 &_hidl_grantors_child);
118
119 if (_hidl_err != ::android::OK) { return _hidl_err; }
120
121 const native_handle_t *_hidl_mq_handle_ptr = parcel.readEmbeddedNativeHandle(
122 parentHandle,
123 parentOffset + MQDescriptor<flavor>::kOffsetOfHandle);
124
125 if (_hidl_mq_handle_ptr == nullptr) {
126 _hidl_err = ::android::UNKNOWN_ERROR;
127 return _hidl_err;
128 }
129
130 return _hidl_err;
131}
132
133template<MQFlavor flavor>
134::android::status_t writeEmbeddedToParcel(
135 const MQDescriptor<flavor> &obj,
136 ::android::hardware::Parcel *parcel,
137 size_t parentHandle,
138 size_t parentOffset) {
139 ::android::status_t _hidl_err = ::android::OK;
140
141 size_t _hidl_grantors_child;
142
143 _hidl_err = ::android::hardware::writeEmbeddedToParcel(
144 obj.grantors(),
145 parcel,
146 parentHandle,
147 parentOffset + MQDescriptor<flavor>::kOffsetOfGrantors,
148 &_hidl_grantors_child);
149
150 if (_hidl_err != ::android::OK) { return _hidl_err; }
151
152 _hidl_err = parcel->writeEmbeddedNativeHandle(
153 obj.handle(),
154 parentHandle,
155 parentOffset + MQDescriptor<flavor>::kOffsetOfHandle);
156
157 if (_hidl_err != ::android::OK) { return _hidl_err; }
158
159 return _hidl_err;
160}
161
162// ---------------------- pointers for HIDL
163
164template <typename T>
165static status_t readEmbeddedReferenceFromParcel(
166 T const* * /* bufptr */,
167 const Parcel & parcel,
168 size_t parentHandle,
169 size_t parentOffset,
170 size_t *handle,
171 bool *shouldResolveRefInBuffer
172 ) {
173 // *bufptr is ignored because, if I am embedded in some
174 // other buffer, the kernel should have fixed me up already.
175 bool isPreviouslyWritten;
176 status_t result = parcel.readEmbeddedReference(
177 nullptr, // ignored, not written to bufptr.
178 handle,
179 parentHandle,
180 parentOffset,
181 &isPreviouslyWritten);
182 // tell caller to run T::readEmbeddedToParcel and
183 // T::readEmbeddedReferenceToParcel if necessary.
184 // It is not called here because we don't know if these two are valid methods.
185 *shouldResolveRefInBuffer = !isPreviouslyWritten;
186 return result;
187}
188
189template <typename T>
190static status_t writeEmbeddedReferenceToParcel(
191 T const* buf,
192 Parcel *parcel, size_t parentHandle, size_t parentOffset,
193 size_t *handle,
194 bool *shouldResolveRefInBuffer
195 ) {
196
197 if(buf == nullptr) {
198 *shouldResolveRefInBuffer = false;
199 return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset);
200 }
201
202 // find whether the buffer exists
203 size_t childHandle, childOffset;
204 status_t result;
205 bool found;
206
207 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
208
209 // tell caller to run T::writeEmbeddedToParcel and
210 // T::writeEmbeddedReferenceToParcel if necessary.
211 // It is not called here because we don't know if these two are valid methods.
212 *shouldResolveRefInBuffer = !found;
213
214 if(result != OK) {
215 return result; // bad pointers and length given
216 }
217 if(!found) { // did not find it.
218 return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle,
219 parentHandle, parentOffset);
220 }
221 // found the buffer. easy case.
222 return parcel->writeEmbeddedReference(
223 handle,
224 childHandle,
225 childOffset,
226 parentHandle,
227 parentOffset);
228}
229
230template <typename T>
231static status_t readReferenceFromParcel(
232 T const* *bufptr,
233 const Parcel & parcel,
234 size_t *handle,
235 bool *shouldResolveRefInBuffer
236 ) {
237 bool isPreviouslyWritten;
238 status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr),
239 handle, &isPreviouslyWritten);
240 // tell caller to run T::readEmbeddedToParcel and
241 // T::readEmbeddedReferenceToParcel if necessary.
242 // It is not called here because we don't know if these two are valid methods.
243 *shouldResolveRefInBuffer = !isPreviouslyWritten;
244 return result;
245}
246
247template <typename T>
248static status_t writeReferenceToParcel(
249 T const *buf,
250 Parcel * parcel,
251 size_t *handle,
252 bool *shouldResolveRefInBuffer
253 ) {
254
255 if(buf == nullptr) {
256 *shouldResolveRefInBuffer = false;
257 return parcel->writeNullReference(handle);
258 }
259
260 // find whether the buffer exists
261 size_t childHandle, childOffset;
262 status_t result;
263 bool found;
264
265 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
266
267 // tell caller to run T::writeEmbeddedToParcel and
268 // T::writeEmbeddedReferenceToParcel if necessary.
269 // It is not called here because we don't know if these two are valid methods.
270 *shouldResolveRefInBuffer = !found;
271
272 if(result != OK) {
273 return result; // bad pointers and length given
274 }
275 if(!found) { // did not find it.
276 return parcel->writeBuffer(buf, sizeof(T), handle);
277 }
278 // found the buffer. easy case.
279 return parcel->writeReference(handle,
280 childHandle, childOffset);
281}
282
283// ---------------------- support for casting interfaces
284
Yifan Hong7f97f442016-11-14 18:31:05 -0800285// Construct a smallest possible binder from the given interface.
286// If it is remote, then its remote() will be retrieved.
287// Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
288// and iface is of class IChild. BnChild will be used to wrapped the given iface.
289// Return nullptr if iface is null or any failure.
Martijn Coenen12f04d92016-12-07 17:29:41 +0100290template <typename IType, typename ProxyType>
Yifan Hong7f97f442016-11-14 18:31:05 -0800291sp<IBinder> toBinder(sp<IType> iface) {
292 IType *ifacePtr = iface.get();
293 if (ifacePtr == nullptr) {
294 return nullptr;
295 }
296 if (ifacePtr->isRemote()) {
Martijn Coenen12f04d92016-12-07 17:29:41 +0100297 return ::android::hardware::IInterface::asBinder(static_cast<ProxyType *>(ifacePtr));
Yifan Hong7f97f442016-11-14 18:31:05 -0800298 } else {
299 std::string myDescriptor{};
300 ifacePtr->interfaceChain([&](const hidl_vec<hidl_string> &types) {
301 if (types.size() > 0) {
302 myDescriptor = types[0].c_str();
303 }
304 });
305 if (myDescriptor.empty()) {
Yifan Hongb2c9c752016-12-07 15:15:41 -0800306 // interfaceChain fails
Yifan Hong7f97f442016-11-14 18:31:05 -0800307 return nullptr;
308 }
309 auto iter = gBnConstructorMap.find(myDescriptor);
310 if (iter == gBnConstructorMap.end()) {
311 return nullptr;
312 }
313 return sp<IBinder>((iter->second)(reinterpret_cast<void *>(ifacePtr)));
314 }
315}
316
Martijn Coenen12f04d92016-12-07 17:29:41 +0100317template <typename IType, typename ProxyType, typename StubType>
318sp<IType> fromBinder(const sp<IBinder>& binderIface) {
319 using ::android::hidl::base::V1_0::IBase;
320 using ::android::hidl::base::V1_0::BnBase;
321
322 if (binderIface.get() == nullptr) {
323 return nullptr;
324 }
325 if (binderIface->localBinder() == nullptr) {
326 return new ProxyType(binderIface);
327 }
328 sp<IBase> base = static_cast<BnBase*>(binderIface.get())->getImpl();
329 if (canCastInterface(base.get(), IType::descriptor)) {
330 StubType* stub = static_cast<StubType*>(binderIface.get());
331 return stub->getImpl();
332 } else {
333 return nullptr;
334 }
335}
336
Yifan Hong7f97f442016-11-14 18:31:05 -0800337#define IMPLEMENT_SERVICE_MANAGER_INTERACTIONS(INTERFACE, PACKAGE) \
338 ::android::sp<I##INTERFACE> I##INTERFACE::getService( \
339 const std::string &serviceName, bool getStub) \
340 { \
341 using ::android::sp; \
342 using ::android::hardware::defaultServiceManager; \
Yifan Hong7f97f442016-11-14 18:31:05 -0800343 using ::android::hidl::manager::V1_0::IServiceManager; \
344 sp<I##INTERFACE> iface; \
345 const sp<IServiceManager> sm = defaultServiceManager(); \
346 if (sm != nullptr && !getStub) { \
Yifan Hong2cd440c2016-11-23 11:30:36 -0800347 sp<::android::hidl::base::V1_0::IBase> base; \
Yifan Hong7f97f442016-11-14 18:31:05 -0800348 ::android::hardware::Return<void> ret = \
349 sm->get(PACKAGE "::I" #INTERFACE, serviceName.c_str(), \
Yifan Hong2cd440c2016-11-23 11:30:36 -0800350 [&base](sp<::android::hidl::base::V1_0::IBase> found) { \
351 base = found; \
Yifan Hong7f97f442016-11-14 18:31:05 -0800352 }); \
353 if (ret.getStatus().isOk()) { \
Yifan Hong2cd440c2016-11-23 11:30:36 -0800354 iface = I##INTERFACE::castFrom(base); \
Yifan Hong7f97f442016-11-14 18:31:05 -0800355 if (iface != nullptr) { \
356 return iface; \
357 } \
358 } \
359 } \
360 int dlMode = RTLD_LAZY; \
361 void *handle = dlopen(HAL_LIBRARY_PATH_ODM PACKAGE "-impl.so", dlMode); \
362 if (handle == nullptr) { \
363 handle = dlopen(HAL_LIBRARY_PATH_VENDOR PACKAGE "-impl.so", dlMode); \
364 } \
365 if (handle == nullptr) { \
366 handle = dlopen(HAL_LIBRARY_PATH_SYSTEM PACKAGE "-impl.so", dlMode); \
367 } \
368 if (handle == nullptr) { \
369 return iface; \
370 } \
371 I##INTERFACE* (*generator)(const char* name); \
372 *(void **)(&generator) = dlsym(handle, "HIDL_FETCH_I"#INTERFACE); \
373 if (generator) { \
374 iface = (*generator)(serviceName.c_str()); \
375 if (iface != nullptr) { \
376 iface = new Bs##INTERFACE(iface); \
377 } \
378 } \
379 return iface; \
380 } \
381 ::android::status_t I##INTERFACE::registerAsService( \
382 const std::string &serviceName) \
383 { \
384 using ::android::sp; \
385 using ::android::hardware::defaultServiceManager; \
386 using ::android::hidl::manager::V1_0::IServiceManager; \
Yifan Hong7f97f442016-11-14 18:31:05 -0800387 const sp<IServiceManager> sm = defaultServiceManager(); \
388 bool success = false; \
389 ::android::hardware::Return<void> ret = \
390 this->interfaceChain( \
Martijn Coenen12f04d92016-12-07 17:29:41 +0100391 [&success, &sm, &serviceName, this](const auto &chain) { \
Steven Moreland337c3ae2016-11-22 13:37:32 -0800392 ::android::hardware::Return<bool> addRet = \
Martijn Coenen12f04d92016-12-07 17:29:41 +0100393 sm->add(chain, serviceName.c_str(), this); \
Steven Moreland1cfaee72016-12-01 08:34:19 -0800394 success = addRet.isOk() && addRet; \
Yifan Hong7f97f442016-11-14 18:31:05 -0800395 }); \
396 success = success && ret.getStatus().isOk(); \
397 return success ? ::android::OK : ::android::UNKNOWN_ERROR; \
398 } \
399 bool I##INTERFACE::registerForNotifications( \
400 const std::string &serviceName, \
401 const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> \
402 &notification) \
403 { \
404 using ::android::sp; \
405 using ::android::hardware::defaultServiceManager; \
406 using ::android::hidl::manager::V1_0::IServiceManager; \
407 const sp<IServiceManager> sm = defaultServiceManager(); \
408 if (sm == nullptr) { \
409 return false; \
410 } \
Steven Moreland337c3ae2016-11-22 13:37:32 -0800411 ::android::hardware::Return<bool> success = \
412 sm->registerForNotifications(PACKAGE "::I" #INTERFACE, \
413 serviceName, \
414 notification); \
Steven Moreland1cfaee72016-12-01 08:34:19 -0800415 return success.isOk() && success; \
Yifan Hong7f97f442016-11-14 18:31:05 -0800416 }
417
418
419} // namespace hardware
420} // namespace android
421
422
423#endif // ANDROID_HIDL_BINDER_SUPPORT_H