blob: 1c468edb731a8f92b05a901a996d2bcb122b3950 [file] [log] [blame]
Martijn Coenen72110162016-08-19 14:28:25 +02001/*
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_SUPPORT_H
18#define ANDROID_HIDL_SUPPORT_H
19
Iliyan Malchev692070a2016-09-12 16:30:44 -070020#include <algorithm>
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -070021#include <dirent.h>
Steven Morelandbdf26662016-09-02 11:03:15 -070022#include <dlfcn.h>
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -070023#include <cutils/properties.h>
Yifan Hong1e265bb2016-11-08 12:33:44 -080024#include <functional>
Yifan Honga3c31842016-10-21 10:33:14 -070025#include <hidl/Status.h>
Yifan Hong190e4292016-10-21 10:34:25 -070026#include <hwbinder/IBinder.h>
Martijn Coenen72110162016-08-19 14:28:25 +020027#include <hwbinder/Parcel.h>
Yifan Hong1e265bb2016-11-08 12:33:44 -080028#include <map>
Andreas Huber00a985c2016-09-28 14:24:53 -070029#include <tuple>
Iliyan Malchev692070a2016-09-12 16:30:44 -070030#include <utils/Errors.h>
31#include <utils/RefBase.h>
32#include <utils/StrongPointer.h>
Martijn Coenen72110162016-08-19 14:28:25 +020033
34namespace android {
35namespace hardware {
36
37struct hidl_string {
38 hidl_string();
39 ~hidl_string();
40
Yifan Hong602b85a2016-10-24 13:40:01 -070041 // copy constructor.
Martijn Coenen72110162016-08-19 14:28:25 +020042 hidl_string(const hidl_string &);
Yifan Hong602b85a2016-10-24 13:40:01 -070043 // copy from a C-style string.
Steven Morelande03c0872016-10-24 10:43:50 -070044 hidl_string(const char *);
Yifan Hong602b85a2016-10-24 13:40:01 -070045 // copy from an std::string.
46 hidl_string(const std::string &);
47
48 // move constructor.
49 hidl_string(hidl_string &&);
Martijn Coenen72110162016-08-19 14:28:25 +020050
51 const char *c_str() const;
52 size_t size() const;
53 bool empty() const;
54
Yifan Hong602b85a2016-10-24 13:40:01 -070055 // copy assignment operator.
Steven Morelande03c0872016-10-24 10:43:50 -070056 hidl_string &operator=(const hidl_string &);
Yifan Hong602b85a2016-10-24 13:40:01 -070057 // copy from a C-style string.
Martijn Coenen72110162016-08-19 14:28:25 +020058 hidl_string &operator=(const char *s);
Yifan Hong602b85a2016-10-24 13:40:01 -070059 // copy from an std::string.
60 hidl_string &operator=(const std::string &);
61 // move assignment operator.
62 hidl_string &operator=(hidl_string &&other);
63 // cast to std::string.
64 operator std::string() const;
65 // cast to C-style string. Caller is responsible
66 // to maintain this hidl_string alive.
67 operator const char *() const;
Steven Morelande03c0872016-10-24 10:43:50 -070068
Martijn Coenen72110162016-08-19 14:28:25 +020069 void clear();
70
71 // Reference an external char array. Ownership is _not_ transferred.
72 // Caller is responsible for ensuring that underlying memory is valid
73 // for the lifetime of this hidl_string.
74 void setToExternal(const char *data, size_t size);
75
Andreas Huberebfeb362016-08-25 13:39:05 -070076 // offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
77 static const size_t kOffsetOfBuffer;
78
Martijn Coenen72110162016-08-19 14:28:25 +020079private:
Yifan Hong602b85a2016-10-24 13:40:01 -070080 const char *mBuffer;
Martijn Coenen72110162016-08-19 14:28:25 +020081 size_t mSize; // NOT including the terminating '\0'.
Yifan Hong602b85a2016-10-24 13:40:01 -070082 bool mOwnsBuffer; // if true then mBuffer is a mutable char *
Martijn Coenen72110162016-08-19 14:28:25 +020083
Yifan Hong602b85a2016-10-24 13:40:01 -070084 // copy from data with size. Assume that my memory is freed
85 // (through clear(), for example)
86 void copyFrom(const char *data, size_t size);
87 // move from another hidl_string
88 void moveFrom(hidl_string &&);
Martijn Coenen72110162016-08-19 14:28:25 +020089};
90
Yifan Hong089ae132016-11-11 11:32:52 -080091status_t readEmbeddedFromParcel(hidl_string *string,
92 const Parcel &parcel, size_t parentHandle, size_t parentOffset);
93
94status_t writeEmbeddedToParcel(const hidl_string &string,
95 Parcel *parcel, size_t parentHandle, size_t parentOffset);
96
Yifan Hong5708fb42016-10-26 17:50:29 -070097inline bool operator==(const hidl_string &hs, const char *s) {
98 return strcmp(hs.c_str(), s) == 0;
99}
100
101inline bool operator!=(const hidl_string &hs, const char *s) {
102 return !(hs == s);
103}
104
105inline bool operator==(const char *s, const hidl_string &hs) {
106 return strcmp(hs.c_str(), s) == 0;
107}
108
109inline bool operator!=(const char *s, const hidl_string &hs) {
110 return !(s == hs);
111}
112
Andreas Huber20dce082016-09-22 19:39:13 -0700113////////////////////////////////////////////////////////////////////////////////
114
Martijn Coenen72110162016-08-19 14:28:25 +0200115template<typename T>
116struct hidl_vec {
117 hidl_vec()
118 : mBuffer(NULL),
119 mSize(0),
120 mOwnsBuffer(true) {
121 }
122
Yifan Hong602b85a2016-10-24 13:40:01 -0700123 hidl_vec(const hidl_vec<T> &other) : hidl_vec() {
Martijn Coenen72110162016-08-19 14:28:25 +0200124 *this = other;
125 }
126
Janis Danisevskisd3ddf622016-10-24 11:40:50 +0100127 hidl_vec(hidl_vec<T> &&other)
128 : mOwnsBuffer(false) {
129 *this = std::move(other);
Alexey Polyudov0ebdbe82016-10-18 09:31:46 -0700130 }
131
Yifan Hong602b85a2016-10-24 13:40:01 -0700132 hidl_vec(const std::vector<T> &other) : hidl_vec() {
133 *this = other;
134 }
135
Martijn Coenen72110162016-08-19 14:28:25 +0200136 ~hidl_vec() {
137 if (mOwnsBuffer) {
138 delete[] mBuffer;
139 }
140 mBuffer = NULL;
141 }
142
Alexey Polyudove2299012016-10-19 09:52:00 -0700143 // Reference an existing array, optionally taking ownership. It is the
Martijn Coenen72110162016-08-19 14:28:25 +0200144 // caller's responsibility to ensure that the underlying memory stays
145 // valid for the lifetime of this hidl_vec.
Alexey Polyudove2299012016-10-19 09:52:00 -0700146 void setToExternal(T *data, size_t size, bool shouldOwn = false) {
Martijn Coenen72110162016-08-19 14:28:25 +0200147 if (mOwnsBuffer) {
148 delete [] mBuffer;
149 }
150 mBuffer = data;
151 mSize = size;
Alexey Polyudove2299012016-10-19 09:52:00 -0700152 mOwnsBuffer = shouldOwn;
Martijn Coenen72110162016-08-19 14:28:25 +0200153 }
154
Alexey Polyudov6f0c9a12016-10-18 09:37:35 -0700155 T *data() {
156 return mBuffer;
157 }
158
159 const T *data() const {
160 return mBuffer;
161 }
162
Alexey Polyudovc98a99c2016-10-18 09:43:56 -0700163 T *releaseData() {
164 if (!mOwnsBuffer && mSize > 0) {
165 resize(mSize);
166 }
167 mOwnsBuffer = false;
168 return mBuffer;
169 }
170
Alexey Polyudov0ebdbe82016-10-18 09:31:46 -0700171 hidl_vec &operator=(hidl_vec &&other) {
Janis Danisevskisd3ddf622016-10-24 11:40:50 +0100172 if (mOwnsBuffer) {
173 delete[] mBuffer;
174 }
Alexey Polyudov0ebdbe82016-10-18 09:31:46 -0700175 mBuffer = other.mBuffer;
176 mSize = other.mSize;
177 mOwnsBuffer = other.mOwnsBuffer;
178 other.mOwnsBuffer = false;
179 return *this;
180 }
181
Martijn Coenen72110162016-08-19 14:28:25 +0200182 hidl_vec &operator=(const hidl_vec &other) {
183 if (this != &other) {
184 if (mOwnsBuffer) {
185 delete[] mBuffer;
186 }
Yifan Hong602b85a2016-10-24 13:40:01 -0700187 copyFrom(other, other.mSize);
Martijn Coenen72110162016-08-19 14:28:25 +0200188 }
189
190 return *this;
191 }
192
Yifan Hong602b85a2016-10-24 13:40:01 -0700193 // copy from an std::vector.
194 hidl_vec &operator=(const std::vector<T> &other) {
195 if (mOwnsBuffer) {
196 delete[] mBuffer;
197 }
198 copyFrom(other, other.size());
199 return *this;
200 }
201
202 // cast to an std::vector.
203 operator std::vector<T>() const {
204 std::vector<T> v(mSize);
205 for (size_t i = 0; i < mSize; ++i) {
206 v[i] = mBuffer[i];
207 }
208 return v;
209 }
210
Martijn Coenen72110162016-08-19 14:28:25 +0200211 size_t size() const {
212 return mSize;
213 }
214
215 T &operator[](size_t index) {
216 return mBuffer[index];
217 }
218
219 const T &operator[](size_t index) const {
220 return mBuffer[index];
221 }
222
223 void resize(size_t size) {
224 T *newBuffer = new T[size];
225
226 for (size_t i = 0; i < std::min(size, mSize); ++i) {
227 newBuffer[i] = mBuffer[i];
228 }
229
230 if (mOwnsBuffer) {
231 delete[] mBuffer;
232 }
233 mBuffer = newBuffer;
234
235 mSize = size;
236 mOwnsBuffer = true;
237 }
238
Yifan Hongb1d8d4c2016-08-23 17:39:06 -0700239 status_t findInParcel(const Parcel &parcel, size_t *handle) const {
240 return parcel.quickFindBuffer(mBuffer, handle);
241 }
242
Yifan Hong089ae132016-11-11 11:32:52 -0800243 // offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
244 static const size_t kOffsetOfBuffer;
Martijn Coenen72110162016-08-19 14:28:25 +0200245private:
246 T *mBuffer;
247 size_t mSize;
248 bool mOwnsBuffer;
Yifan Hong602b85a2016-10-24 13:40:01 -0700249
250 // copy from an array-like object, assuming my resources are freed.
251 template <typename Array>
252 void copyFrom(const Array &data, size_t size) {
253 mSize = size;
254 mOwnsBuffer = true;
255 if (mSize > 0) {
256 mBuffer = new T[size];
257 for (size_t i = 0; i < size; ++i) {
258 mBuffer[i] = data[i];
259 }
260 } else {
261 mBuffer = NULL;
262 }
263 }
Martijn Coenen72110162016-08-19 14:28:25 +0200264};
265
Yifan Hong089ae132016-11-11 11:32:52 -0800266template <typename T>
267const size_t hidl_vec<T>::kOffsetOfBuffer = offsetof(hidl_vec<T>, mBuffer);
268
269template<typename T>
270status_t readEmbeddedFromParcel(
271 hidl_vec<T> * /*vec*/,
272 const Parcel &parcel,
273 size_t parentHandle,
274 size_t parentOffset,
275 size_t *handle) {
276 const void *ptr = parcel.readEmbeddedBuffer(
277 handle,
278 parentHandle,
279 parentOffset + hidl_vec<T>::kOffsetOfBuffer);
280
281 return ptr != NULL ? OK : UNKNOWN_ERROR;
282}
283
284template<typename T>
285status_t writeEmbeddedToParcel(
286 const hidl_vec<T> &vec,
287 Parcel *parcel,
288 size_t parentHandle,
289 size_t parentOffset,
290 size_t *handle) {
291 return parcel->writeEmbeddedBuffer(
292 vec.data(),
293 sizeof(T) * vec.size(),
294 handle,
295 parentHandle,
296 parentOffset + hidl_vec<T>::kOffsetOfBuffer);
297}
298
Andreas Huber20dce082016-09-22 19:39:13 -0700299////////////////////////////////////////////////////////////////////////////////
300
301namespace details {
302
303 template<size_t SIZE1, size_t... SIZES>
304 struct product {
305 static constexpr size_t value = SIZE1 * product<SIZES...>::value;
306 };
307
308 template<size_t SIZE1>
309 struct product<SIZE1> {
310 static constexpr size_t value = SIZE1;
311 };
312
313 template<typename T, size_t SIZE1, size_t... SIZES>
314 struct accessor {
315 explicit accessor(T *base)
316 : mBase(base) {
317 }
318
319 accessor<T, SIZES...> operator[](size_t index) {
320 return accessor<T, SIZES...>(
321 &mBase[index * product<SIZES...>::value]);
322 }
323
324 private:
325 T *mBase;
326 };
327
328 template<typename T, size_t SIZE1>
329 struct accessor<T, SIZE1> {
330 explicit accessor(T *base)
331 : mBase(base) {
332 }
333
334 T &operator[](size_t index) {
335 return mBase[index];
336 }
337
338 private:
339 T *mBase;
340 };
341
342 template<typename T, size_t SIZE1, size_t... SIZES>
343 struct const_accessor {
344 explicit const_accessor(const T *base)
345 : mBase(base) {
346 }
347
348 const_accessor<T, SIZES...> operator[](size_t index) {
349 return const_accessor<T, SIZES...>(
350 &mBase[index * product<SIZES...>::value]);
351 }
352
353 private:
354 const T *mBase;
355 };
356
357 template<typename T, size_t SIZE1>
358 struct const_accessor<T, SIZE1> {
359 explicit const_accessor(const T *base)
360 : mBase(base) {
361 }
362
363 const T &operator[](size_t index) const {
364 return mBase[index];
365 }
366
367 private:
368 const T *mBase;
369 };
370
371} // namespace details
372
373////////////////////////////////////////////////////////////////////////////////
374
375template<typename T, size_t SIZE1, size_t... SIZES>
376struct hidl_array {
377 hidl_array() = default;
378
379 T *data() { return mBuffer; }
380 const T *data() const { return mBuffer; }
381
382 details::accessor<T, SIZES...> operator[](size_t index) {
383 return details::accessor<T, SIZES...>(
384 &mBuffer[index * details::product<SIZES...>::value]);
385 }
386
387 details::const_accessor<T, SIZES...> operator[](size_t index) const {
388 return details::const_accessor<T, SIZES...>(
389 &mBuffer[index * details::product<SIZES...>::value]);
390 }
391
Andreas Huber00a985c2016-09-28 14:24:53 -0700392 using size_tuple_type = std::tuple<decltype(SIZE1), decltype(SIZES)...>;
393
394 static constexpr size_tuple_type size() {
395 return std::make_tuple(SIZE1, SIZES...);
396 }
397
Andreas Huber20dce082016-09-22 19:39:13 -0700398private:
399 T mBuffer[details::product<SIZE1, SIZES...>::value];
400};
401
402template<typename T, size_t SIZE1>
403struct hidl_array<T, SIZE1> {
404 hidl_array() = default;
405
406 T *data() { return mBuffer; }
407 const T *data() const { return mBuffer; }
408
409 T &operator[](size_t index) {
410 return mBuffer[index];
411 }
412
413 const T &operator[](size_t index) const {
414 return mBuffer[index];
415 }
416
Andreas Huber00a985c2016-09-28 14:24:53 -0700417 static constexpr size_t size() { return SIZE1; }
418
Andreas Huber20dce082016-09-22 19:39:13 -0700419private:
420 T mBuffer[SIZE1];
421};
422
Yifan Hongb1d8d4c2016-08-23 17:39:06 -0700423///////////////////////////// pointers for HIDL
424
425template <typename T>
426static status_t readEmbeddedReferenceFromParcel(
427 T const* * /* bufptr */,
428 const Parcel & parcel,
429 size_t parentHandle,
430 size_t parentOffset,
431 size_t *handle,
432 bool *shouldResolveRefInBuffer
433 ) {
434 // *bufptr is ignored because, if I am embedded in some
435 // other buffer, the kernel should have fixed me up already.
436 bool isPreviouslyWritten;
437 status_t result = parcel.readEmbeddedReference(
438 nullptr, // ignored, not written to bufptr.
439 handle,
440 parentHandle,
441 parentOffset,
442 &isPreviouslyWritten);
443 // tell caller to run T::readEmbeddedToParcel and
444 // T::readEmbeddedReferenceToParcel if necessary.
445 // It is not called here because we don't know if these two are valid methods.
446 *shouldResolveRefInBuffer = !isPreviouslyWritten;
447 return result;
448}
449
450template <typename T>
451static status_t writeEmbeddedReferenceToParcel(
452 T const* buf,
453 Parcel *parcel, size_t parentHandle, size_t parentOffset,
454 size_t *handle,
455 bool *shouldResolveRefInBuffer
456 ) {
457
458 if(buf == nullptr) {
459 *shouldResolveRefInBuffer = false;
460 return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset);
461 }
462
463 // find whether the buffer exists
464 size_t childHandle, childOffset;
465 status_t result;
466 bool found;
467
468 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
469
470 // tell caller to run T::writeEmbeddedToParcel and
471 // T::writeEmbeddedReferenceToParcel if necessary.
472 // It is not called here because we don't know if these two are valid methods.
473 *shouldResolveRefInBuffer = !found;
474
475 if(result != OK) {
476 return result; // bad pointers and length given
477 }
478 if(!found) { // did not find it.
479 return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle,
480 parentHandle, parentOffset);
481 }
482 // found the buffer. easy case.
483 return parcel->writeEmbeddedReference(
484 handle,
485 childHandle,
486 childOffset,
487 parentHandle,
488 parentOffset);
489}
490
491template <typename T>
492static status_t readReferenceFromParcel(
493 T const* *bufptr,
494 const Parcel & parcel,
495 size_t *handle,
496 bool *shouldResolveRefInBuffer
497 ) {
498 bool isPreviouslyWritten;
499 status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr),
500 handle, &isPreviouslyWritten);
501 // tell caller to run T::readEmbeddedToParcel and
502 // T::readEmbeddedReferenceToParcel if necessary.
503 // It is not called here because we don't know if these two are valid methods.
504 *shouldResolveRefInBuffer = !isPreviouslyWritten;
505 return result;
506}
507
508template <typename T>
509static status_t writeReferenceToParcel(
510 T const *buf,
511 Parcel * parcel,
512 size_t *handle,
513 bool *shouldResolveRefInBuffer
514 ) {
515
516 if(buf == nullptr) {
517 *shouldResolveRefInBuffer = false;
518 return parcel->writeNullReference(handle);
519 }
520
521 // find whether the buffer exists
522 size_t childHandle, childOffset;
523 status_t result;
524 bool found;
525
526 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
527
528 // tell caller to run T::writeEmbeddedToParcel and
529 // T::writeEmbeddedReferenceToParcel if necessary.
530 // It is not called here because we don't know if these two are valid methods.
531 *shouldResolveRefInBuffer = !found;
532
533 if(result != OK) {
534 return result; // bad pointers and length given
535 }
536 if(!found) { // did not find it.
537 return parcel->writeBuffer(buf, sizeof(T), handle);
538 }
539 // found the buffer. easy case.
540 return parcel->writeReference(handle,
541 childHandle, childOffset);
542}
543
Martijn Coenen72110162016-08-19 14:28:25 +0200544// ----------------------------------------------------------------------
545// Version functions
546struct hidl_version {
547public:
Chia-I Wu666b76b2016-10-06 14:15:59 +0800548 constexpr hidl_version(uint16_t major, uint16_t minor) : mMajor(major), mMinor(minor) {}
Martijn Coenen72110162016-08-19 14:28:25 +0200549
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700550 bool operator==(const hidl_version& other) const {
Martijn Coenen72110162016-08-19 14:28:25 +0200551 return (mMajor == other.get_major() && mMinor == other.get_minor());
552 }
Martijn Coenenc28f1152016-08-22 14:06:56 +0200553
Martijn Coenen097a7672016-09-08 16:56:41 +0200554 constexpr uint16_t get_major() const { return mMajor; }
555 constexpr uint16_t get_minor() const { return mMinor; }
Martijn Coenen72110162016-08-19 14:28:25 +0200556
557 android::status_t writeToParcel(android::hardware::Parcel& parcel) const {
Chia-I Wu666b76b2016-10-06 14:15:59 +0800558 return parcel.writeUint32(static_cast<uint32_t>(mMajor) << 16 | mMinor);
Martijn Coenen72110162016-08-19 14:28:25 +0200559 }
560
561 static hidl_version* readFromParcel(const android::hardware::Parcel& parcel) {
562 uint32_t version;
563 android::status_t status = parcel.readUint32(&version);
564 if (status != OK) {
565 return nullptr;
566 } else {
567 return new hidl_version(version >> 16, version & 0xFFFF);
568 }
569 }
570
571private:
572 uint16_t mMajor;
573 uint16_t mMinor;
574};
575
576inline android::hardware::hidl_version make_hidl_version(uint16_t major, uint16_t minor) {
577 return hidl_version(major,minor);
578}
579
Yifan Hongc1a60ef2016-11-08 18:53:16 -0800580struct IBase : virtual public RefBase {
Yifan Honga3c31842016-10-21 10:33:14 -0700581 virtual bool isRemote() const = 0;
582 // HIDL reserved methods follow.
583 virtual ::android::hardware::Return<void> interfaceChain(
584 std::function<void(const hidl_vec<hidl_string>&)> _hidl_cb) = 0;
585 // descriptor for HIDL reserved methods.
Steven Moreland5a682322016-11-11 12:32:50 -0800586 static const char* descriptor;
Yifan Honga3c31842016-10-21 10:33:14 -0700587};
588
Yifan Hong1e265bb2016-11-08 12:33:44 -0800589extern std::map<std::string, std::function<sp<IBinder>(void*)>> gBnConstructorMap;
590
591// Construct a smallest possible binder from the given interface.
592// If it is remote, then its remote() will be retrieved.
593// Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
594// and iface is of class IChild. BnChild will be used to wrapped the given iface.
595// Return nullptr if iface is null or any failure.
596template <typename IType, typename IHwType>
597sp<IBinder> toBinder(sp<IType> iface) {
598 IType *ifacePtr = iface.get();
599 if (ifacePtr == nullptr) {
600 return nullptr;
601 }
602 if (ifacePtr->isRemote()) {
603 return ::android::hardware::IInterface::asBinder(static_cast<IHwType *>(ifacePtr));
604 } else {
605 std::string myDescriptor{};
606 ifacePtr->interfaceChain([&](const hidl_vec<hidl_string> &types) {
607 if (types.size() > 0) {
608 myDescriptor = types[0].c_str();
609 }
610 });
611 if (myDescriptor.empty()) {
612 // interfaceChain fails || types.size() == 0
613 return nullptr;
614 }
615 auto iter = gBnConstructorMap.find(myDescriptor);
616 if (iter == gBnConstructorMap.end()) {
617 return nullptr;
618 }
619 return sp<IBinder>((iter->second)(reinterpret_cast<void *>(ifacePtr)));
620 }
621}
622
623// cast the interface IParent to IChild.
624// Return nullptr if parent is null or any failure.
625template<typename IChild, typename IParent, typename BpChild, typename IHwParent>
Yifan Hong190e4292016-10-21 10:34:25 -0700626sp<IChild> castInterface(sp<IParent> parent, const char *childIndicator) {
627 if (parent.get() == nullptr) {
628 // casts always succeed with nullptrs.
629 return nullptr;
630 }
631 bool canCast = false;
632 parent->interfaceChain([&](const hidl_vec<hidl_string> &allowedCastTypes) {
633 for (size_t i = 0; i < allowedCastTypes.size(); i++) {
634 if (allowedCastTypes[i] == childIndicator) {
635 canCast = true;
636 break;
637 }
638 }
639 });
640
641 if (!canCast) {
642 return sp<IChild>(nullptr); // cast failed.
643 }
644 if (parent->isRemote()) {
645 // binderized mode. Got BpChild. grab the remote and wrap it.
Yifan Hong1e265bb2016-11-08 12:33:44 -0800646 return sp<IChild>(new BpChild(toBinder<IParent, IHwParent>(parent)));
Yifan Hong190e4292016-10-21 10:34:25 -0700647 }
648 // Passthrough mode. Got BnChild and BsChild.
649 return sp<IChild>(static_cast<IChild *>(parent.get()));
650}
651
Steven Morelandbdf26662016-09-02 11:03:15 -0700652#if defined(__LP64__)
653#define HAL_LIBRARY_PATH_SYSTEM "/system/lib64/hw/"
654#define HAL_LIBRARY_PATH_VENDOR "/vendor/lib64/hw/"
655#define HAL_LIBRARY_PATH_ODM "/odm/lib64/hw/"
656#else
657#define HAL_LIBRARY_PATH_SYSTEM "/system/lib/hw/"
658#define HAL_LIBRARY_PATH_VENDOR "/vendor/lib/hw/"
659#define HAL_LIBRARY_PATH_ODM "/odm/lib/hw/"
660#endif
661
Steven Moreland40ede2c2016-11-09 13:51:53 -0800662#define DECLARE_SERVICE_MANAGER_INTERACTIONS(INTERFACE) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200663 static ::android::sp<I##INTERFACE> getService( \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700664 const std::string &serviceName, bool getStub=false); \
Steven Moreland40ede2c2016-11-09 13:51:53 -0800665 ::android::status_t registerAsService(const std::string &serviceName); \
666 static bool registerForNotifications( \
667 const std::string &serviceName, \
668 const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> \
669 &notification); \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200670
Steven Moreland40ede2c2016-11-09 13:51:53 -0800671#define IMPLEMENT_SERVICE_MANAGER_INTERACTIONS(INTERFACE, PACKAGE) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200672 ::android::sp<I##INTERFACE> I##INTERFACE::getService( \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700673 const std::string &serviceName, bool getStub) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200674 { \
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700675 using ::android::sp; \
676 using ::android::hardware::defaultServiceManager; \
677 using ::android::hardware::IBinder; \
678 using ::android::hidl::manager::V1_0::IServiceManager; \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200679 sp<I##INTERFACE> iface; \
Martijn Coenen270cb502016-10-25 00:19:56 +0200680 const sp<IServiceManager> sm = defaultServiceManager(); \
681 if (sm != nullptr && !getStub) { \
Steven Morelandb8573e12016-11-07 12:40:05 -0800682 sp<IBinder> binderIface; \
Steven Morelandf0cc0972016-11-02 17:51:46 -0700683 ::android::hardware::Return<void> ret = \
684 sm->get(PACKAGE "::I" #INTERFACE, serviceName.c_str(), \
685 [&binderIface](sp<IBinder> iface) { \
686 binderIface = iface; \
687 }); \
688 if (ret.getStatus().isOk()) { \
689 iface = IHw##INTERFACE::asInterface(binderIface); \
690 if (iface != nullptr) { \
691 return iface; \
692 } \
Steven Morelandb8573e12016-11-07 12:40:05 -0800693 } \
Steven Morelandbdf26662016-09-02 11:03:15 -0700694 } \
695 int dlMode = RTLD_LAZY; \
Steven Morelandf0cc0972016-11-02 17:51:46 -0700696 void *handle = dlopen(HAL_LIBRARY_PATH_ODM PACKAGE "-impl.so", dlMode); \
Steven Morelandbdf26662016-09-02 11:03:15 -0700697 if (handle == nullptr) { \
Steven Morelandf0cc0972016-11-02 17:51:46 -0700698 handle = dlopen(HAL_LIBRARY_PATH_VENDOR PACKAGE "-impl.so", dlMode); \
Steven Morelandbdf26662016-09-02 11:03:15 -0700699 } \
700 if (handle == nullptr) { \
Steven Morelandf0cc0972016-11-02 17:51:46 -0700701 handle = dlopen(HAL_LIBRARY_PATH_SYSTEM PACKAGE "-impl.so", dlMode); \
Steven Morelandbdf26662016-09-02 11:03:15 -0700702 } \
703 if (handle == nullptr) { \
704 return iface; \
705 } \
706 I##INTERFACE* (*generator)(const char* name); \
707 *(void **)(&generator) = dlsym(handle, "HIDL_FETCH_I"#INTERFACE); \
708 if (generator) { \
Martijn Coenenf7a651d2016-09-08 13:38:12 +0200709 iface = (*generator)(serviceName.c_str()); \
Steven Moreland7391bc32016-09-14 10:31:48 -0700710 if (iface != nullptr) { \
711 iface = new Bs##INTERFACE(iface); \
712 } \
Steven Morelandbdf26662016-09-02 11:03:15 -0700713 } \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200714 return iface; \
715 } \
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700716 ::android::status_t I##INTERFACE::registerAsService( \
Martijn Coenen097a7672016-09-08 16:56:41 +0200717 const std::string &serviceName) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200718 { \
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700719 using ::android::sp; \
720 using ::android::hardware::defaultServiceManager; \
721 using ::android::hidl::manager::V1_0::IServiceManager; \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200722 sp<Bn##INTERFACE> binderIface = new Bn##INTERFACE(this); \
723 const sp<IServiceManager> sm = defaultServiceManager(); \
Steven Morelandf0cc0972016-11-02 17:51:46 -0700724 bool success = false; \
725 ::android::hardware::Return<void> ret = \
726 this->interfaceChain( \
727 [&success, &sm, &serviceName, &binderIface](const auto &chain) { \
728 success = sm->add(chain, serviceName.c_str(), binderIface); \
729 }); \
730 success = success && ret.getStatus().isOk(); \
731 return success ? ::android::OK : ::android::UNKNOWN_ERROR; \
Steven Moreland40ede2c2016-11-09 13:51:53 -0800732 } \
733 bool I##INTERFACE::registerForNotifications( \
734 const std::string &serviceName, \
735 const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> \
736 &notification) \
737 { \
738 using ::android::sp; \
739 using ::android::hardware::defaultServiceManager; \
740 using ::android::hidl::manager::V1_0::IServiceManager; \
741 const sp<IServiceManager> sm = defaultServiceManager(); \
742 if (sm == nullptr) { \
743 return false; \
744 } \
745 return sm->registerForNotifications(PACKAGE "::I" #INTERFACE, \
746 serviceName, \
747 notification); \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200748 }
749
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700750// ----------------------------------------------------------------------
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700751// Class that provides Hidl instrumentation utilities.
752struct HidlInstrumentor {
753 // Event that triggers the instrumentation. e.g. enter of an API call on
754 // the server/client side, exit of an API call on the server/client side
755 // etc.
756 enum InstrumentationEvent {
757 SERVER_API_ENTRY = 0,
758 SERVER_API_EXIT,
759 CLIENT_API_ENTRY,
760 CLIENT_API_EXIT,
761 SYNC_CALLBACK_ENTRY,
762 SYNC_CALLBACK_EXIT,
763 ASYNC_CALLBACK_ENTRY,
764 ASYNC_CALLBACK_EXIT,
Steven Morelandcefbd6e2016-11-01 10:14:30 -0700765 PASSTHROUGH_ENTRY,
766 PASSTHROUGH_EXIT,
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700767 };
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700768
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700769 // Signature of the instrumentation callback function.
770 using InstrumentationCallback = std::function<void(
771 const InstrumentationEvent event,
772 const char *package,
773 const char *version,
774 const char *interface,
775 const char *method,
776 std::vector<void *> *args)>;
777
778 explicit HidlInstrumentor(const std::string &prefix);
779 virtual ~HidlInstrumentor();
780
781 protected:
782 // Function that lookup and dynamically loads the hidl instrumentation
783 // libraries and registers the instrumentation callback functions.
784 //
785 // The instrumentation libraries should be stored under any of the following
786 // directories: HAL_LIBRARY_PATH_SYSTEM, HAL_LIBRARY_PATH_VENDOR and
787 // HAL_LIBRARY_PATH_ODM. The name of instrumentation libraries should
788 // follow pattern: ^profilerPrefix(.*).profiler.so$
789 //
790 // Each instrumentation library is expected to implement the instrumentation
791 // function called HIDL_INSTRUMENTATION_FUNCTION.
792 //
793 // A no-op for user build.
794 void registerInstrumentationCallbacks(
795 const std::string &profilerPrefix,
796 std::vector<InstrumentationCallback> *instrumentationCallbacks);
797
798 // Utility function to determine whether a give file is a instrumentation
799 // library (i.e. the file name follow the expected pattern).
800 bool isInstrumentationLib(
801 const std::string &profilerPrefix,
802 const dirent *file);
803 // A list of registered instrumentation callbacks.
804 std::vector<InstrumentationCallback> mInstrumentationCallbacks;
805 // Flag whether to enable instrumentation.
806 bool mEnableInstrumentation;
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700807};
808
Martijn Coenen72110162016-08-19 14:28:25 +0200809} // namespace hardware
810} // namespace android
811
Martijn Coenenc28f1152016-08-22 14:06:56 +0200812
Martijn Coenen72110162016-08-19 14:28:25 +0200813#endif // ANDROID_HIDL_SUPPORT_H
814