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