blob: b1bb6edf6965e19a95f50f279159bb7c1f695d8b [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 Polyudovc98a99c2016-10-18 09:43:56 -0700116 T *releaseData() {
117 if (!mOwnsBuffer && mSize > 0) {
118 resize(mSize);
119 }
120 mOwnsBuffer = false;
121 return mBuffer;
122 }
123
Alexey Polyudov0ebdbe82016-10-18 09:31:46 -0700124 hidl_vec &operator=(hidl_vec &&other) {
125 mBuffer = other.mBuffer;
126 mSize = other.mSize;
127 mOwnsBuffer = other.mOwnsBuffer;
128 other.mOwnsBuffer = false;
129 return *this;
130 }
131
Martijn Coenen72110162016-08-19 14:28:25 +0200132 hidl_vec &operator=(const hidl_vec &other) {
133 if (this != &other) {
134 if (mOwnsBuffer) {
135 delete[] mBuffer;
136 }
137 mBuffer = NULL;
138 mSize = other.mSize;
139 mOwnsBuffer = true;
140 if (mSize > 0) {
141 mBuffer = new T[mSize];
142 for (size_t i = 0; i < mSize; ++i) {
143 mBuffer[i] = other.mBuffer[i];
144 }
145 }
146 }
147
148 return *this;
149 }
150
151 size_t size() const {
152 return mSize;
153 }
154
155 T &operator[](size_t index) {
156 return mBuffer[index];
157 }
158
159 const T &operator[](size_t index) const {
160 return mBuffer[index];
161 }
162
163 void resize(size_t size) {
164 T *newBuffer = new T[size];
165
166 for (size_t i = 0; i < std::min(size, mSize); ++i) {
167 newBuffer[i] = mBuffer[i];
168 }
169
170 if (mOwnsBuffer) {
171 delete[] mBuffer;
172 }
173 mBuffer = newBuffer;
174
175 mSize = size;
176 mOwnsBuffer = true;
177 }
178
179 status_t readEmbeddedFromParcel(
180 const Parcel &parcel,
181 size_t parentHandle,
182 size_t parentOffset,
183 size_t *handle);
184
185 status_t writeEmbeddedToParcel(
186 Parcel *parcel,
187 size_t parentHandle,
188 size_t parentOffset,
189 size_t *handle) const;
190
Yifan Hongb1d8d4c2016-08-23 17:39:06 -0700191 status_t findInParcel(const Parcel &parcel, size_t *handle) const {
192 return parcel.quickFindBuffer(mBuffer, handle);
193 }
194
195
Martijn Coenen72110162016-08-19 14:28:25 +0200196private:
197 T *mBuffer;
198 size_t mSize;
199 bool mOwnsBuffer;
200};
201
Andreas Huber20dce082016-09-22 19:39:13 -0700202////////////////////////////////////////////////////////////////////////////////
203
204namespace details {
205
206 template<size_t SIZE1, size_t... SIZES>
207 struct product {
208 static constexpr size_t value = SIZE1 * product<SIZES...>::value;
209 };
210
211 template<size_t SIZE1>
212 struct product<SIZE1> {
213 static constexpr size_t value = SIZE1;
214 };
215
216 template<typename T, size_t SIZE1, size_t... SIZES>
217 struct accessor {
218 explicit accessor(T *base)
219 : mBase(base) {
220 }
221
222 accessor<T, SIZES...> operator[](size_t index) {
223 return accessor<T, SIZES...>(
224 &mBase[index * product<SIZES...>::value]);
225 }
226
227 private:
228 T *mBase;
229 };
230
231 template<typename T, size_t SIZE1>
232 struct accessor<T, SIZE1> {
233 explicit accessor(T *base)
234 : mBase(base) {
235 }
236
237 T &operator[](size_t index) {
238 return mBase[index];
239 }
240
241 private:
242 T *mBase;
243 };
244
245 template<typename T, size_t SIZE1, size_t... SIZES>
246 struct const_accessor {
247 explicit const_accessor(const T *base)
248 : mBase(base) {
249 }
250
251 const_accessor<T, SIZES...> operator[](size_t index) {
252 return const_accessor<T, SIZES...>(
253 &mBase[index * product<SIZES...>::value]);
254 }
255
256 private:
257 const T *mBase;
258 };
259
260 template<typename T, size_t SIZE1>
261 struct const_accessor<T, SIZE1> {
262 explicit const_accessor(const T *base)
263 : mBase(base) {
264 }
265
266 const T &operator[](size_t index) const {
267 return mBase[index];
268 }
269
270 private:
271 const T *mBase;
272 };
273
274} // namespace details
275
276////////////////////////////////////////////////////////////////////////////////
277
278template<typename T, size_t SIZE1, size_t... SIZES>
279struct hidl_array {
280 hidl_array() = default;
281
282 T *data() { return mBuffer; }
283 const T *data() const { return mBuffer; }
284
285 details::accessor<T, SIZES...> operator[](size_t index) {
286 return details::accessor<T, SIZES...>(
287 &mBuffer[index * details::product<SIZES...>::value]);
288 }
289
290 details::const_accessor<T, SIZES...> operator[](size_t index) const {
291 return details::const_accessor<T, SIZES...>(
292 &mBuffer[index * details::product<SIZES...>::value]);
293 }
294
Andreas Huber00a985c2016-09-28 14:24:53 -0700295 using size_tuple_type = std::tuple<decltype(SIZE1), decltype(SIZES)...>;
296
297 static constexpr size_tuple_type size() {
298 return std::make_tuple(SIZE1, SIZES...);
299 }
300
Andreas Huber20dce082016-09-22 19:39:13 -0700301private:
302 T mBuffer[details::product<SIZE1, SIZES...>::value];
303};
304
305template<typename T, size_t SIZE1>
306struct hidl_array<T, SIZE1> {
307 hidl_array() = default;
308
309 T *data() { return mBuffer; }
310 const T *data() const { return mBuffer; }
311
312 T &operator[](size_t index) {
313 return mBuffer[index];
314 }
315
316 const T &operator[](size_t index) const {
317 return mBuffer[index];
318 }
319
Andreas Huber00a985c2016-09-28 14:24:53 -0700320 static constexpr size_t size() { return SIZE1; }
321
Andreas Huber20dce082016-09-22 19:39:13 -0700322private:
323 T mBuffer[SIZE1];
324};
325
326////////////////////////////////////////////////////////////////////////////////
327
Martijn Coenen72110162016-08-19 14:28:25 +0200328template<typename T>
329status_t hidl_vec<T>::readEmbeddedFromParcel(
330 const Parcel &parcel,
331 size_t parentHandle,
332 size_t parentOffset,
333 size_t *handle) {
334 const void *ptr = parcel.readEmbeddedBuffer(
335 handle,
336 parentHandle,
337 parentOffset + offsetof(hidl_vec<T>, mBuffer));
338
339 return ptr != NULL ? OK : UNKNOWN_ERROR;
340}
341
342template<typename T>
343status_t hidl_vec<T>::writeEmbeddedToParcel(
344 Parcel *parcel,
345 size_t parentHandle,
346 size_t parentOffset,
347 size_t *handle) const {
348 return parcel->writeEmbeddedBuffer(
349 mBuffer,
350 sizeof(T) * mSize,
351 handle,
352 parentHandle,
353 parentOffset + offsetof(hidl_vec<T>, mBuffer));
354}
355
Yifan Hongb1d8d4c2016-08-23 17:39:06 -0700356///////////////////////////// pointers for HIDL
357
358template <typename T>
359static status_t readEmbeddedReferenceFromParcel(
360 T const* * /* bufptr */,
361 const Parcel & parcel,
362 size_t parentHandle,
363 size_t parentOffset,
364 size_t *handle,
365 bool *shouldResolveRefInBuffer
366 ) {
367 // *bufptr is ignored because, if I am embedded in some
368 // other buffer, the kernel should have fixed me up already.
369 bool isPreviouslyWritten;
370 status_t result = parcel.readEmbeddedReference(
371 nullptr, // ignored, not written to bufptr.
372 handle,
373 parentHandle,
374 parentOffset,
375 &isPreviouslyWritten);
376 // tell caller to run T::readEmbeddedToParcel and
377 // T::readEmbeddedReferenceToParcel if necessary.
378 // It is not called here because we don't know if these two are valid methods.
379 *shouldResolveRefInBuffer = !isPreviouslyWritten;
380 return result;
381}
382
383template <typename T>
384static status_t writeEmbeddedReferenceToParcel(
385 T const* buf,
386 Parcel *parcel, size_t parentHandle, size_t parentOffset,
387 size_t *handle,
388 bool *shouldResolveRefInBuffer
389 ) {
390
391 if(buf == nullptr) {
392 *shouldResolveRefInBuffer = false;
393 return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset);
394 }
395
396 // find whether the buffer exists
397 size_t childHandle, childOffset;
398 status_t result;
399 bool found;
400
401 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
402
403 // tell caller to run T::writeEmbeddedToParcel and
404 // T::writeEmbeddedReferenceToParcel if necessary.
405 // It is not called here because we don't know if these two are valid methods.
406 *shouldResolveRefInBuffer = !found;
407
408 if(result != OK) {
409 return result; // bad pointers and length given
410 }
411 if(!found) { // did not find it.
412 return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle,
413 parentHandle, parentOffset);
414 }
415 // found the buffer. easy case.
416 return parcel->writeEmbeddedReference(
417 handle,
418 childHandle,
419 childOffset,
420 parentHandle,
421 parentOffset);
422}
423
424template <typename T>
425static status_t readReferenceFromParcel(
426 T const* *bufptr,
427 const Parcel & parcel,
428 size_t *handle,
429 bool *shouldResolveRefInBuffer
430 ) {
431 bool isPreviouslyWritten;
432 status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr),
433 handle, &isPreviouslyWritten);
434 // tell caller to run T::readEmbeddedToParcel and
435 // T::readEmbeddedReferenceToParcel if necessary.
436 // It is not called here because we don't know if these two are valid methods.
437 *shouldResolveRefInBuffer = !isPreviouslyWritten;
438 return result;
439}
440
441template <typename T>
442static status_t writeReferenceToParcel(
443 T const *buf,
444 Parcel * parcel,
445 size_t *handle,
446 bool *shouldResolveRefInBuffer
447 ) {
448
449 if(buf == nullptr) {
450 *shouldResolveRefInBuffer = false;
451 return parcel->writeNullReference(handle);
452 }
453
454 // find whether the buffer exists
455 size_t childHandle, childOffset;
456 status_t result;
457 bool found;
458
459 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
460
461 // tell caller to run T::writeEmbeddedToParcel and
462 // T::writeEmbeddedReferenceToParcel if necessary.
463 // It is not called here because we don't know if these two are valid methods.
464 *shouldResolveRefInBuffer = !found;
465
466 if(result != OK) {
467 return result; // bad pointers and length given
468 }
469 if(!found) { // did not find it.
470 return parcel->writeBuffer(buf, sizeof(T), handle);
471 }
472 // found the buffer. easy case.
473 return parcel->writeReference(handle,
474 childHandle, childOffset);
475}
476
Martijn Coenen72110162016-08-19 14:28:25 +0200477// ----------------------------------------------------------------------
478// Version functions
479struct hidl_version {
480public:
Chia-I Wu666b76b2016-10-06 14:15:59 +0800481 constexpr hidl_version(uint16_t major, uint16_t minor) : mMajor(major), mMinor(minor) {}
Martijn Coenen72110162016-08-19 14:28:25 +0200482
483 bool operator==(const hidl_version& other) {
484 return (mMajor == other.get_major() && mMinor == other.get_minor());
485 }
Martijn Coenenc28f1152016-08-22 14:06:56 +0200486
Martijn Coenen097a7672016-09-08 16:56:41 +0200487 constexpr uint16_t get_major() const { return mMajor; }
488 constexpr uint16_t get_minor() const { return mMinor; }
Martijn Coenen72110162016-08-19 14:28:25 +0200489
490 android::status_t writeToParcel(android::hardware::Parcel& parcel) const {
Chia-I Wu666b76b2016-10-06 14:15:59 +0800491 return parcel.writeUint32(static_cast<uint32_t>(mMajor) << 16 | mMinor);
Martijn Coenen72110162016-08-19 14:28:25 +0200492 }
493
494 static hidl_version* readFromParcel(const android::hardware::Parcel& parcel) {
495 uint32_t version;
496 android::status_t status = parcel.readUint32(&version);
497 if (status != OK) {
498 return nullptr;
499 } else {
500 return new hidl_version(version >> 16, version & 0xFFFF);
501 }
502 }
503
504private:
505 uint16_t mMajor;
506 uint16_t mMinor;
507};
508
509inline android::hardware::hidl_version make_hidl_version(uint16_t major, uint16_t minor) {
510 return hidl_version(major,minor);
511}
512
Steven Morelandbdf26662016-09-02 11:03:15 -0700513#if defined(__LP64__)
514#define HAL_LIBRARY_PATH_SYSTEM "/system/lib64/hw/"
515#define HAL_LIBRARY_PATH_VENDOR "/vendor/lib64/hw/"
516#define HAL_LIBRARY_PATH_ODM "/odm/lib64/hw/"
517#else
518#define HAL_LIBRARY_PATH_SYSTEM "/system/lib/hw/"
519#define HAL_LIBRARY_PATH_VENDOR "/vendor/lib/hw/"
520#define HAL_LIBRARY_PATH_ODM "/odm/lib/hw/"
521#endif
522
Martijn Coenenc28f1152016-08-22 14:06:56 +0200523#define DECLARE_REGISTER_AND_GET_SERVICE(INTERFACE) \
524 static ::android::sp<I##INTERFACE> getService( \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700525 const std::string &serviceName, bool getStub=false); \
Steven Morelandbdf26662016-09-02 11:03:15 -0700526 status_t registerAsService( \
Martijn Coenen097a7672016-09-08 16:56:41 +0200527 const std::string &serviceName); \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200528
Steven Morelandbdf26662016-09-02 11:03:15 -0700529#define IMPLEMENT_REGISTER_AND_GET_SERVICE(INTERFACE, LIB) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200530 ::android::sp<I##INTERFACE> I##INTERFACE::getService( \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700531 const std::string &serviceName, bool getStub) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200532 { \
533 sp<I##INTERFACE> iface; \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700534 const struct timespec DELAY {1,0}; \
535 unsigned retries = 3; \
536 if (!getStub) { \
537 do { \
538 const sp<IServiceManager> sm = defaultServiceManager(); \
539 if (sm != nullptr) { \
540 sp<IBinder> binderIface = \
541 sm->checkService(String16(serviceName.c_str()), \
542 I##INTERFACE::version); \
543 iface = IHw##INTERFACE::asInterface(binderIface); \
544 } \
545 if (iface != nullptr) { \
546 return iface; \
547 } \
548 TEMP_FAILURE_RETRY(nanosleep(&DELAY, nullptr)); \
549 } while (retries--); \
Steven Morelandbdf26662016-09-02 11:03:15 -0700550 } \
551 int dlMode = RTLD_LAZY; \
552 void *handle = dlopen(HAL_LIBRARY_PATH_ODM LIB, dlMode); \
553 if (handle == nullptr) { \
554 handle = dlopen(HAL_LIBRARY_PATH_VENDOR LIB, dlMode); \
555 } \
556 if (handle == nullptr) { \
557 handle = dlopen(HAL_LIBRARY_PATH_SYSTEM LIB, dlMode); \
558 } \
559 if (handle == nullptr) { \
560 return iface; \
561 } \
562 I##INTERFACE* (*generator)(const char* name); \
563 *(void **)(&generator) = dlsym(handle, "HIDL_FETCH_I"#INTERFACE); \
564 if (generator) { \
Martijn Coenenf7a651d2016-09-08 13:38:12 +0200565 iface = (*generator)(serviceName.c_str()); \
Steven Moreland7391bc32016-09-14 10:31:48 -0700566 if (iface != nullptr) { \
567 iface = new Bs##INTERFACE(iface); \
568 } \
Steven Morelandbdf26662016-09-02 11:03:15 -0700569 } \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200570 return iface; \
571 } \
Steven Morelandbdf26662016-09-02 11:03:15 -0700572 status_t I##INTERFACE::registerAsService( \
Martijn Coenen097a7672016-09-08 16:56:41 +0200573 const std::string &serviceName) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200574 { \
575 sp<Bn##INTERFACE> binderIface = new Bn##INTERFACE(this); \
576 const sp<IServiceManager> sm = defaultServiceManager(); \
Martijn Coenen097a7672016-09-08 16:56:41 +0200577 return sm->addService(String16(serviceName.c_str()), binderIface, \
578 I##INTERFACE::version); \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200579 }
580
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700581// ----------------------------------------------------------------------
582// Hidl instrumentation utilities.
583
584// Event that triggers the instrumentation. e.g. enter of an API call on
585// the server/client side, exit of an API call on the server/client side etc.
586enum InstrumentationEvent {
587 SERVER_API_ENTRY = 0,
588 SERVER_API_EXIT,
589 CLIENT_API_ENTRY,
590 CLIENT_API_EXIT,
591 SYNC_CALLBACK_ENTRY,
592 SYNC_CALLBACK_EXIT,
593 ASYNC_CALLBACK_ENTRY,
594 ASYNC_CALLBACK_EXIT,
595};
596
597// Signature of the instrumentation callback function.
598using InstrumentationCallback = std::function<void(
599 const InstrumentationEvent event,
600 const char *package,
601 const char *version,
602 const char *interface,
603 const char *method,
604 std::vector<void *> *args)>;
605
606// Function that lookup and dynamically loads the hidl instrumentation libraries
607// and registers the instrumentation callback functions.
608//
609// The instrumentation libraries should be stored under any of the following
610// directories: HAL_LIBRARY_PATH_SYSTEM, HAL_LIBRARY_PATH_VENDOR and
611// HAL_LIBRARY_PATH_ODM. The name of instrumentation libraries should follow
612// pattern: ^profilerPrefix(.*).profiler.so$
613//
614// Each instrumentation library is expected to implement the instrumentation
615// function called HIDL_INSTRUMENTATION_FUNCTION.
616//
617// A no-op for user build.
618void registerInstrumentationCallbacks(
619 const std::string &profilerPrefix,
620 std::vector<InstrumentationCallback> *instrumentationCallbacks);
621
622// Utility function to determine whether a give file is a instrumentation
623// library (i.e. the file name follow the expected pattern).
624bool isInstrumentationLib(
625 const std::string &profilerPrefix,
626 const dirent *file);
627
Martijn Coenen72110162016-08-19 14:28:25 +0200628} // namespace hardware
629} // namespace android
630
Martijn Coenenc28f1152016-08-22 14:06:56 +0200631
Martijn Coenen72110162016-08-19 14:28:25 +0200632#endif // ANDROID_HIDL_SUPPORT_H
633