blob: 16f460f92c56115c77cafd2dcceaf6082c8b25b0 [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>
Martijn Coenen72110162016-08-19 14:28:25 +020023#include <hwbinder/Parcel.h>
Andreas Huber00a985c2016-09-28 14:24:53 -070024#include <tuple>
Iliyan Malchev692070a2016-09-12 16:30:44 -070025#include <utils/Errors.h>
26#include <utils/RefBase.h>
27#include <utils/StrongPointer.h>
Martijn Coenen72110162016-08-19 14:28:25 +020028
29namespace android {
30namespace hardware {
31
32struct hidl_string {
33 hidl_string();
34 ~hidl_string();
35
36 hidl_string(const hidl_string &);
37 hidl_string &operator=(const hidl_string &);
38
39 const char *c_str() const;
40 size_t size() const;
41 bool empty() const;
42
43 hidl_string &operator=(const char *s);
44 void clear();
45
46 // Reference an external char array. Ownership is _not_ transferred.
47 // Caller is responsible for ensuring that underlying memory is valid
48 // for the lifetime of this hidl_string.
49 void setToExternal(const char *data, size_t size);
50
51 status_t readEmbeddedFromParcel(
52 const Parcel &parcel, size_t parentHandle, size_t parentOffset);
53
54 status_t writeEmbeddedToParcel(
55 Parcel *parcel, size_t parentHandle, size_t parentOffset) const;
56
Andreas Huberebfeb362016-08-25 13:39:05 -070057 // offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
58 static const size_t kOffsetOfBuffer;
59
Martijn Coenen72110162016-08-19 14:28:25 +020060private:
61 char *mBuffer;
62 size_t mSize; // NOT including the terminating '\0'.
63 bool mOwnsBuffer;
64
65 hidl_string &setTo(const char *data, size_t size);
66};
67
Andreas Huber20dce082016-09-22 19:39:13 -070068////////////////////////////////////////////////////////////////////////////////
69
Martijn Coenen72110162016-08-19 14:28:25 +020070template<typename T>
71struct hidl_vec {
72 hidl_vec()
73 : mBuffer(NULL),
74 mSize(0),
75 mOwnsBuffer(true) {
76 }
77
78 hidl_vec(const hidl_vec<T> &other)
79 : mBuffer(NULL),
80 mSize(0),
81 mOwnsBuffer(true) {
82 *this = other;
83 }
84
Alexey Polyudov0ebdbe82016-10-18 09:31:46 -070085 hidl_vec(hidl_vec<T> &&other) {
86 *this = static_cast<hidl_vec &&>(other);
87 }
88
Martijn Coenen72110162016-08-19 14:28:25 +020089 ~hidl_vec() {
90 if (mOwnsBuffer) {
91 delete[] mBuffer;
92 }
93 mBuffer = NULL;
94 }
95
96 // Reference an existing array _WITHOUT_ taking ownership. It is the
97 // caller's responsibility to ensure that the underlying memory stays
98 // valid for the lifetime of this hidl_vec.
99 void setToExternal(T *data, size_t size) {
100 if (mOwnsBuffer) {
101 delete [] mBuffer;
102 }
103 mBuffer = data;
104 mSize = size;
105 mOwnsBuffer = false;
106 }
107
Alexey Polyudov6f0c9a12016-10-18 09:37:35 -0700108 T *data() {
109 return mBuffer;
110 }
111
112 const T *data() const {
113 return mBuffer;
114 }
115
Alexey Polyudov0ebdbe82016-10-18 09:31:46 -0700116 hidl_vec &operator=(hidl_vec &&other) {
117 mBuffer = other.mBuffer;
118 mSize = other.mSize;
119 mOwnsBuffer = other.mOwnsBuffer;
120 other.mOwnsBuffer = false;
121 return *this;
122 }
123
Martijn Coenen72110162016-08-19 14:28:25 +0200124 hidl_vec &operator=(const hidl_vec &other) {
125 if (this != &other) {
126 if (mOwnsBuffer) {
127 delete[] mBuffer;
128 }
129 mBuffer = NULL;
130 mSize = other.mSize;
131 mOwnsBuffer = true;
132 if (mSize > 0) {
133 mBuffer = new T[mSize];
134 for (size_t i = 0; i < mSize; ++i) {
135 mBuffer[i] = other.mBuffer[i];
136 }
137 }
138 }
139
140 return *this;
141 }
142
143 size_t size() const {
144 return mSize;
145 }
146
147 T &operator[](size_t index) {
148 return mBuffer[index];
149 }
150
151 const T &operator[](size_t index) const {
152 return mBuffer[index];
153 }
154
155 void resize(size_t size) {
156 T *newBuffer = new T[size];
157
158 for (size_t i = 0; i < std::min(size, mSize); ++i) {
159 newBuffer[i] = mBuffer[i];
160 }
161
162 if (mOwnsBuffer) {
163 delete[] mBuffer;
164 }
165 mBuffer = newBuffer;
166
167 mSize = size;
168 mOwnsBuffer = true;
169 }
170
171 status_t readEmbeddedFromParcel(
172 const Parcel &parcel,
173 size_t parentHandle,
174 size_t parentOffset,
175 size_t *handle);
176
177 status_t writeEmbeddedToParcel(
178 Parcel *parcel,
179 size_t parentHandle,
180 size_t parentOffset,
181 size_t *handle) const;
182
Yifan Hongb1d8d4c2016-08-23 17:39:06 -0700183 status_t findInParcel(const Parcel &parcel, size_t *handle) const {
184 return parcel.quickFindBuffer(mBuffer, handle);
185 }
186
187
Martijn Coenen72110162016-08-19 14:28:25 +0200188private:
189 T *mBuffer;
190 size_t mSize;
191 bool mOwnsBuffer;
192};
193
Andreas Huber20dce082016-09-22 19:39:13 -0700194////////////////////////////////////////////////////////////////////////////////
195
196namespace details {
197
198 template<size_t SIZE1, size_t... SIZES>
199 struct product {
200 static constexpr size_t value = SIZE1 * product<SIZES...>::value;
201 };
202
203 template<size_t SIZE1>
204 struct product<SIZE1> {
205 static constexpr size_t value = SIZE1;
206 };
207
208 template<typename T, size_t SIZE1, size_t... SIZES>
209 struct accessor {
210 explicit accessor(T *base)
211 : mBase(base) {
212 }
213
214 accessor<T, SIZES...> operator[](size_t index) {
215 return accessor<T, SIZES...>(
216 &mBase[index * product<SIZES...>::value]);
217 }
218
219 private:
220 T *mBase;
221 };
222
223 template<typename T, size_t SIZE1>
224 struct accessor<T, SIZE1> {
225 explicit accessor(T *base)
226 : mBase(base) {
227 }
228
229 T &operator[](size_t index) {
230 return mBase[index];
231 }
232
233 private:
234 T *mBase;
235 };
236
237 template<typename T, size_t SIZE1, size_t... SIZES>
238 struct const_accessor {
239 explicit const_accessor(const T *base)
240 : mBase(base) {
241 }
242
243 const_accessor<T, SIZES...> operator[](size_t index) {
244 return const_accessor<T, SIZES...>(
245 &mBase[index * product<SIZES...>::value]);
246 }
247
248 private:
249 const T *mBase;
250 };
251
252 template<typename T, size_t SIZE1>
253 struct const_accessor<T, SIZE1> {
254 explicit const_accessor(const T *base)
255 : mBase(base) {
256 }
257
258 const T &operator[](size_t index) const {
259 return mBase[index];
260 }
261
262 private:
263 const T *mBase;
264 };
265
266} // namespace details
267
268////////////////////////////////////////////////////////////////////////////////
269
270template<typename T, size_t SIZE1, size_t... SIZES>
271struct hidl_array {
272 hidl_array() = default;
273
274 T *data() { return mBuffer; }
275 const T *data() const { return mBuffer; }
276
277 details::accessor<T, SIZES...> operator[](size_t index) {
278 return details::accessor<T, SIZES...>(
279 &mBuffer[index * details::product<SIZES...>::value]);
280 }
281
282 details::const_accessor<T, SIZES...> operator[](size_t index) const {
283 return details::const_accessor<T, SIZES...>(
284 &mBuffer[index * details::product<SIZES...>::value]);
285 }
286
Andreas Huber00a985c2016-09-28 14:24:53 -0700287 using size_tuple_type = std::tuple<decltype(SIZE1), decltype(SIZES)...>;
288
289 static constexpr size_tuple_type size() {
290 return std::make_tuple(SIZE1, SIZES...);
291 }
292
Andreas Huber20dce082016-09-22 19:39:13 -0700293private:
294 T mBuffer[details::product<SIZE1, SIZES...>::value];
295};
296
297template<typename T, size_t SIZE1>
298struct hidl_array<T, SIZE1> {
299 hidl_array() = default;
300
301 T *data() { return mBuffer; }
302 const T *data() const { return mBuffer; }
303
304 T &operator[](size_t index) {
305 return mBuffer[index];
306 }
307
308 const T &operator[](size_t index) const {
309 return mBuffer[index];
310 }
311
Andreas Huber00a985c2016-09-28 14:24:53 -0700312 static constexpr size_t size() { return SIZE1; }
313
Andreas Huber20dce082016-09-22 19:39:13 -0700314private:
315 T mBuffer[SIZE1];
316};
317
318////////////////////////////////////////////////////////////////////////////////
319
Martijn Coenen72110162016-08-19 14:28:25 +0200320template<typename T>
321status_t hidl_vec<T>::readEmbeddedFromParcel(
322 const Parcel &parcel,
323 size_t parentHandle,
324 size_t parentOffset,
325 size_t *handle) {
326 const void *ptr = parcel.readEmbeddedBuffer(
327 handle,
328 parentHandle,
329 parentOffset + offsetof(hidl_vec<T>, mBuffer));
330
331 return ptr != NULL ? OK : UNKNOWN_ERROR;
332}
333
334template<typename T>
335status_t hidl_vec<T>::writeEmbeddedToParcel(
336 Parcel *parcel,
337 size_t parentHandle,
338 size_t parentOffset,
339 size_t *handle) const {
340 return parcel->writeEmbeddedBuffer(
341 mBuffer,
342 sizeof(T) * mSize,
343 handle,
344 parentHandle,
345 parentOffset + offsetof(hidl_vec<T>, mBuffer));
346}
347
Yifan Hongb1d8d4c2016-08-23 17:39:06 -0700348///////////////////////////// pointers for HIDL
349
350template <typename T>
351static status_t readEmbeddedReferenceFromParcel(
352 T const* * /* bufptr */,
353 const Parcel & parcel,
354 size_t parentHandle,
355 size_t parentOffset,
356 size_t *handle,
357 bool *shouldResolveRefInBuffer
358 ) {
359 // *bufptr is ignored because, if I am embedded in some
360 // other buffer, the kernel should have fixed me up already.
361 bool isPreviouslyWritten;
362 status_t result = parcel.readEmbeddedReference(
363 nullptr, // ignored, not written to bufptr.
364 handle,
365 parentHandle,
366 parentOffset,
367 &isPreviouslyWritten);
368 // tell caller to run T::readEmbeddedToParcel and
369 // T::readEmbeddedReferenceToParcel if necessary.
370 // It is not called here because we don't know if these two are valid methods.
371 *shouldResolveRefInBuffer = !isPreviouslyWritten;
372 return result;
373}
374
375template <typename T>
376static status_t writeEmbeddedReferenceToParcel(
377 T const* buf,
378 Parcel *parcel, size_t parentHandle, size_t parentOffset,
379 size_t *handle,
380 bool *shouldResolveRefInBuffer
381 ) {
382
383 if(buf == nullptr) {
384 *shouldResolveRefInBuffer = false;
385 return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset);
386 }
387
388 // find whether the buffer exists
389 size_t childHandle, childOffset;
390 status_t result;
391 bool found;
392
393 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
394
395 // tell caller to run T::writeEmbeddedToParcel and
396 // T::writeEmbeddedReferenceToParcel if necessary.
397 // It is not called here because we don't know if these two are valid methods.
398 *shouldResolveRefInBuffer = !found;
399
400 if(result != OK) {
401 return result; // bad pointers and length given
402 }
403 if(!found) { // did not find it.
404 return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle,
405 parentHandle, parentOffset);
406 }
407 // found the buffer. easy case.
408 return parcel->writeEmbeddedReference(
409 handle,
410 childHandle,
411 childOffset,
412 parentHandle,
413 parentOffset);
414}
415
416template <typename T>
417static status_t readReferenceFromParcel(
418 T const* *bufptr,
419 const Parcel & parcel,
420 size_t *handle,
421 bool *shouldResolveRefInBuffer
422 ) {
423 bool isPreviouslyWritten;
424 status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr),
425 handle, &isPreviouslyWritten);
426 // tell caller to run T::readEmbeddedToParcel and
427 // T::readEmbeddedReferenceToParcel if necessary.
428 // It is not called here because we don't know if these two are valid methods.
429 *shouldResolveRefInBuffer = !isPreviouslyWritten;
430 return result;
431}
432
433template <typename T>
434static status_t writeReferenceToParcel(
435 T const *buf,
436 Parcel * parcel,
437 size_t *handle,
438 bool *shouldResolveRefInBuffer
439 ) {
440
441 if(buf == nullptr) {
442 *shouldResolveRefInBuffer = false;
443 return parcel->writeNullReference(handle);
444 }
445
446 // find whether the buffer exists
447 size_t childHandle, childOffset;
448 status_t result;
449 bool found;
450
451 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
452
453 // tell caller to run T::writeEmbeddedToParcel and
454 // T::writeEmbeddedReferenceToParcel if necessary.
455 // It is not called here because we don't know if these two are valid methods.
456 *shouldResolveRefInBuffer = !found;
457
458 if(result != OK) {
459 return result; // bad pointers and length given
460 }
461 if(!found) { // did not find it.
462 return parcel->writeBuffer(buf, sizeof(T), handle);
463 }
464 // found the buffer. easy case.
465 return parcel->writeReference(handle,
466 childHandle, childOffset);
467}
468
Martijn Coenen72110162016-08-19 14:28:25 +0200469// ----------------------------------------------------------------------
470// Version functions
471struct hidl_version {
472public:
Chia-I Wu666b76b2016-10-06 14:15:59 +0800473 constexpr hidl_version(uint16_t major, uint16_t minor) : mMajor(major), mMinor(minor) {}
Martijn Coenen72110162016-08-19 14:28:25 +0200474
475 bool operator==(const hidl_version& other) {
476 return (mMajor == other.get_major() && mMinor == other.get_minor());
477 }
Martijn Coenenc28f1152016-08-22 14:06:56 +0200478
Martijn Coenen097a7672016-09-08 16:56:41 +0200479 constexpr uint16_t get_major() const { return mMajor; }
480 constexpr uint16_t get_minor() const { return mMinor; }
Martijn Coenen72110162016-08-19 14:28:25 +0200481
482 android::status_t writeToParcel(android::hardware::Parcel& parcel) const {
Chia-I Wu666b76b2016-10-06 14:15:59 +0800483 return parcel.writeUint32(static_cast<uint32_t>(mMajor) << 16 | mMinor);
Martijn Coenen72110162016-08-19 14:28:25 +0200484 }
485
486 static hidl_version* readFromParcel(const android::hardware::Parcel& parcel) {
487 uint32_t version;
488 android::status_t status = parcel.readUint32(&version);
489 if (status != OK) {
490 return nullptr;
491 } else {
492 return new hidl_version(version >> 16, version & 0xFFFF);
493 }
494 }
495
496private:
497 uint16_t mMajor;
498 uint16_t mMinor;
499};
500
501inline android::hardware::hidl_version make_hidl_version(uint16_t major, uint16_t minor) {
502 return hidl_version(major,minor);
503}
504
Steven Morelandbdf26662016-09-02 11:03:15 -0700505#if defined(__LP64__)
506#define HAL_LIBRARY_PATH_SYSTEM "/system/lib64/hw/"
507#define HAL_LIBRARY_PATH_VENDOR "/vendor/lib64/hw/"
508#define HAL_LIBRARY_PATH_ODM "/odm/lib64/hw/"
509#else
510#define HAL_LIBRARY_PATH_SYSTEM "/system/lib/hw/"
511#define HAL_LIBRARY_PATH_VENDOR "/vendor/lib/hw/"
512#define HAL_LIBRARY_PATH_ODM "/odm/lib/hw/"
513#endif
514
Martijn Coenenc28f1152016-08-22 14:06:56 +0200515#define DECLARE_REGISTER_AND_GET_SERVICE(INTERFACE) \
516 static ::android::sp<I##INTERFACE> getService( \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700517 const std::string &serviceName, bool getStub=false); \
Steven Morelandbdf26662016-09-02 11:03:15 -0700518 status_t registerAsService( \
Martijn Coenen097a7672016-09-08 16:56:41 +0200519 const std::string &serviceName); \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200520
Steven Morelandbdf26662016-09-02 11:03:15 -0700521#define IMPLEMENT_REGISTER_AND_GET_SERVICE(INTERFACE, LIB) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200522 ::android::sp<I##INTERFACE> I##INTERFACE::getService( \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700523 const std::string &serviceName, bool getStub) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200524 { \
525 sp<I##INTERFACE> iface; \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700526 const struct timespec DELAY {1,0}; \
527 unsigned retries = 3; \
528 if (!getStub) { \
529 do { \
530 const sp<IServiceManager> sm = defaultServiceManager(); \
531 if (sm != nullptr) { \
532 sp<IBinder> binderIface = \
533 sm->checkService(String16(serviceName.c_str()), \
534 I##INTERFACE::version); \
535 iface = IHw##INTERFACE::asInterface(binderIface); \
536 } \
537 if (iface != nullptr) { \
538 return iface; \
539 } \
540 TEMP_FAILURE_RETRY(nanosleep(&DELAY, nullptr)); \
541 } while (retries--); \
Steven Morelandbdf26662016-09-02 11:03:15 -0700542 } \
543 int dlMode = RTLD_LAZY; \
544 void *handle = dlopen(HAL_LIBRARY_PATH_ODM LIB, dlMode); \
545 if (handle == nullptr) { \
546 handle = dlopen(HAL_LIBRARY_PATH_VENDOR LIB, dlMode); \
547 } \
548 if (handle == nullptr) { \
549 handle = dlopen(HAL_LIBRARY_PATH_SYSTEM LIB, dlMode); \
550 } \
551 if (handle == nullptr) { \
552 return iface; \
553 } \
554 I##INTERFACE* (*generator)(const char* name); \
555 *(void **)(&generator) = dlsym(handle, "HIDL_FETCH_I"#INTERFACE); \
556 if (generator) { \
Martijn Coenenf7a651d2016-09-08 13:38:12 +0200557 iface = (*generator)(serviceName.c_str()); \
Steven Moreland7391bc32016-09-14 10:31:48 -0700558 if (iface != nullptr) { \
559 iface = new Bs##INTERFACE(iface); \
560 } \
Steven Morelandbdf26662016-09-02 11:03:15 -0700561 } \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200562 return iface; \
563 } \
Steven Morelandbdf26662016-09-02 11:03:15 -0700564 status_t I##INTERFACE::registerAsService( \
Martijn Coenen097a7672016-09-08 16:56:41 +0200565 const std::string &serviceName) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200566 { \
567 sp<Bn##INTERFACE> binderIface = new Bn##INTERFACE(this); \
568 const sp<IServiceManager> sm = defaultServiceManager(); \
Martijn Coenen097a7672016-09-08 16:56:41 +0200569 return sm->addService(String16(serviceName.c_str()), binderIface, \
570 I##INTERFACE::version); \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200571 }
572
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700573// ----------------------------------------------------------------------
574// Hidl instrumentation utilities.
575
576// Event that triggers the instrumentation. e.g. enter of an API call on
577// the server/client side, exit of an API call on the server/client side etc.
578enum InstrumentationEvent {
579 SERVER_API_ENTRY = 0,
580 SERVER_API_EXIT,
581 CLIENT_API_ENTRY,
582 CLIENT_API_EXIT,
583 SYNC_CALLBACK_ENTRY,
584 SYNC_CALLBACK_EXIT,
585 ASYNC_CALLBACK_ENTRY,
586 ASYNC_CALLBACK_EXIT,
587};
588
589// Signature of the instrumentation callback function.
590using InstrumentationCallback = std::function<void(
591 const InstrumentationEvent event,
592 const char *package,
593 const char *version,
594 const char *interface,
595 const char *method,
596 std::vector<void *> *args)>;
597
598// Function that lookup and dynamically loads the hidl instrumentation libraries
599// and registers the instrumentation callback functions.
600//
601// The instrumentation libraries should be stored under any of the following
602// directories: HAL_LIBRARY_PATH_SYSTEM, HAL_LIBRARY_PATH_VENDOR and
603// HAL_LIBRARY_PATH_ODM. The name of instrumentation libraries should follow
604// pattern: ^profilerPrefix(.*).profiler.so$
605//
606// Each instrumentation library is expected to implement the instrumentation
607// function called HIDL_INSTRUMENTATION_FUNCTION.
608//
609// A no-op for user build.
610void registerInstrumentationCallbacks(
611 const std::string &profilerPrefix,
612 std::vector<InstrumentationCallback> *instrumentationCallbacks);
613
614// Utility function to determine whether a give file is a instrumentation
615// library (i.e. the file name follow the expected pattern).
616bool isInstrumentationLib(
617 const std::string &profilerPrefix,
618 const dirent *file);
619
Martijn Coenen72110162016-08-19 14:28:25 +0200620} // namespace hardware
621} // namespace android
622
Martijn Coenenc28f1152016-08-22 14:06:56 +0200623
Martijn Coenen72110162016-08-19 14:28:25 +0200624#endif // ANDROID_HIDL_SUPPORT_H
625