blob: f9f7f14c70c142845797d616e8514e0fd89afe24 [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
85 ~hidl_vec() {
86 if (mOwnsBuffer) {
87 delete[] mBuffer;
88 }
89 mBuffer = NULL;
90 }
91
92 // Reference an existing array _WITHOUT_ taking ownership. It is the
93 // caller's responsibility to ensure that the underlying memory stays
94 // valid for the lifetime of this hidl_vec.
95 void setToExternal(T *data, size_t size) {
96 if (mOwnsBuffer) {
97 delete [] mBuffer;
98 }
99 mBuffer = data;
100 mSize = size;
101 mOwnsBuffer = false;
102 }
103
104 hidl_vec &operator=(const hidl_vec &other) {
105 if (this != &other) {
106 if (mOwnsBuffer) {
107 delete[] mBuffer;
108 }
109 mBuffer = NULL;
110 mSize = other.mSize;
111 mOwnsBuffer = true;
112 if (mSize > 0) {
113 mBuffer = new T[mSize];
114 for (size_t i = 0; i < mSize; ++i) {
115 mBuffer[i] = other.mBuffer[i];
116 }
117 }
118 }
119
120 return *this;
121 }
122
123 size_t size() const {
124 return mSize;
125 }
126
127 T &operator[](size_t index) {
128 return mBuffer[index];
129 }
130
131 const T &operator[](size_t index) const {
132 return mBuffer[index];
133 }
134
135 void resize(size_t size) {
136 T *newBuffer = new T[size];
137
138 for (size_t i = 0; i < std::min(size, mSize); ++i) {
139 newBuffer[i] = mBuffer[i];
140 }
141
142 if (mOwnsBuffer) {
143 delete[] mBuffer;
144 }
145 mBuffer = newBuffer;
146
147 mSize = size;
148 mOwnsBuffer = true;
149 }
150
151 status_t readEmbeddedFromParcel(
152 const Parcel &parcel,
153 size_t parentHandle,
154 size_t parentOffset,
155 size_t *handle);
156
157 status_t writeEmbeddedToParcel(
158 Parcel *parcel,
159 size_t parentHandle,
160 size_t parentOffset,
161 size_t *handle) const;
162
Yifan Hongb1d8d4c2016-08-23 17:39:06 -0700163 status_t findInParcel(const Parcel &parcel, size_t *handle) const {
164 return parcel.quickFindBuffer(mBuffer, handle);
165 }
166
167
Martijn Coenen72110162016-08-19 14:28:25 +0200168private:
169 T *mBuffer;
170 size_t mSize;
171 bool mOwnsBuffer;
172};
173
Andreas Huber20dce082016-09-22 19:39:13 -0700174////////////////////////////////////////////////////////////////////////////////
175
176namespace details {
177
178 template<size_t SIZE1, size_t... SIZES>
179 struct product {
180 static constexpr size_t value = SIZE1 * product<SIZES...>::value;
181 };
182
183 template<size_t SIZE1>
184 struct product<SIZE1> {
185 static constexpr size_t value = SIZE1;
186 };
187
188 template<typename T, size_t SIZE1, size_t... SIZES>
189 struct accessor {
190 explicit accessor(T *base)
191 : mBase(base) {
192 }
193
194 accessor<T, SIZES...> operator[](size_t index) {
195 return accessor<T, SIZES...>(
196 &mBase[index * product<SIZES...>::value]);
197 }
198
199 private:
200 T *mBase;
201 };
202
203 template<typename T, size_t SIZE1>
204 struct accessor<T, SIZE1> {
205 explicit accessor(T *base)
206 : mBase(base) {
207 }
208
209 T &operator[](size_t index) {
210 return mBase[index];
211 }
212
213 private:
214 T *mBase;
215 };
216
217 template<typename T, size_t SIZE1, size_t... SIZES>
218 struct const_accessor {
219 explicit const_accessor(const T *base)
220 : mBase(base) {
221 }
222
223 const_accessor<T, SIZES...> operator[](size_t index) {
224 return const_accessor<T, SIZES...>(
225 &mBase[index * product<SIZES...>::value]);
226 }
227
228 private:
229 const T *mBase;
230 };
231
232 template<typename T, size_t SIZE1>
233 struct const_accessor<T, SIZE1> {
234 explicit const_accessor(const T *base)
235 : mBase(base) {
236 }
237
238 const T &operator[](size_t index) const {
239 return mBase[index];
240 }
241
242 private:
243 const T *mBase;
244 };
245
246} // namespace details
247
248////////////////////////////////////////////////////////////////////////////////
249
250template<typename T, size_t SIZE1, size_t... SIZES>
251struct hidl_array {
252 hidl_array() = default;
253
254 T *data() { return mBuffer; }
255 const T *data() const { return mBuffer; }
256
257 details::accessor<T, SIZES...> operator[](size_t index) {
258 return details::accessor<T, SIZES...>(
259 &mBuffer[index * details::product<SIZES...>::value]);
260 }
261
262 details::const_accessor<T, SIZES...> operator[](size_t index) const {
263 return details::const_accessor<T, SIZES...>(
264 &mBuffer[index * details::product<SIZES...>::value]);
265 }
266
Andreas Huber00a985c2016-09-28 14:24:53 -0700267 using size_tuple_type = std::tuple<decltype(SIZE1), decltype(SIZES)...>;
268
269 static constexpr size_tuple_type size() {
270 return std::make_tuple(SIZE1, SIZES...);
271 }
272
Andreas Huber20dce082016-09-22 19:39:13 -0700273private:
274 T mBuffer[details::product<SIZE1, SIZES...>::value];
275};
276
277template<typename T, size_t SIZE1>
278struct hidl_array<T, SIZE1> {
279 hidl_array() = default;
280
281 T *data() { return mBuffer; }
282 const T *data() const { return mBuffer; }
283
284 T &operator[](size_t index) {
285 return mBuffer[index];
286 }
287
288 const T &operator[](size_t index) const {
289 return mBuffer[index];
290 }
291
Andreas Huber00a985c2016-09-28 14:24:53 -0700292 static constexpr size_t size() { return SIZE1; }
293
Andreas Huber20dce082016-09-22 19:39:13 -0700294private:
295 T mBuffer[SIZE1];
296};
297
298////////////////////////////////////////////////////////////////////////////////
299
Martijn Coenen72110162016-08-19 14:28:25 +0200300template<typename T>
301status_t hidl_vec<T>::readEmbeddedFromParcel(
302 const Parcel &parcel,
303 size_t parentHandle,
304 size_t parentOffset,
305 size_t *handle) {
306 const void *ptr = parcel.readEmbeddedBuffer(
307 handle,
308 parentHandle,
309 parentOffset + offsetof(hidl_vec<T>, mBuffer));
310
311 return ptr != NULL ? OK : UNKNOWN_ERROR;
312}
313
314template<typename T>
315status_t hidl_vec<T>::writeEmbeddedToParcel(
316 Parcel *parcel,
317 size_t parentHandle,
318 size_t parentOffset,
319 size_t *handle) const {
320 return parcel->writeEmbeddedBuffer(
321 mBuffer,
322 sizeof(T) * mSize,
323 handle,
324 parentHandle,
325 parentOffset + offsetof(hidl_vec<T>, mBuffer));
326}
327
Yifan Hongb1d8d4c2016-08-23 17:39:06 -0700328///////////////////////////// pointers for HIDL
329
330template <typename T>
331static status_t readEmbeddedReferenceFromParcel(
332 T const* * /* bufptr */,
333 const Parcel & parcel,
334 size_t parentHandle,
335 size_t parentOffset,
336 size_t *handle,
337 bool *shouldResolveRefInBuffer
338 ) {
339 // *bufptr is ignored because, if I am embedded in some
340 // other buffer, the kernel should have fixed me up already.
341 bool isPreviouslyWritten;
342 status_t result = parcel.readEmbeddedReference(
343 nullptr, // ignored, not written to bufptr.
344 handle,
345 parentHandle,
346 parentOffset,
347 &isPreviouslyWritten);
348 // tell caller to run T::readEmbeddedToParcel and
349 // T::readEmbeddedReferenceToParcel if necessary.
350 // It is not called here because we don't know if these two are valid methods.
351 *shouldResolveRefInBuffer = !isPreviouslyWritten;
352 return result;
353}
354
355template <typename T>
356static status_t writeEmbeddedReferenceToParcel(
357 T const* buf,
358 Parcel *parcel, size_t parentHandle, size_t parentOffset,
359 size_t *handle,
360 bool *shouldResolveRefInBuffer
361 ) {
362
363 if(buf == nullptr) {
364 *shouldResolveRefInBuffer = false;
365 return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset);
366 }
367
368 // find whether the buffer exists
369 size_t childHandle, childOffset;
370 status_t result;
371 bool found;
372
373 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
374
375 // tell caller to run T::writeEmbeddedToParcel and
376 // T::writeEmbeddedReferenceToParcel if necessary.
377 // It is not called here because we don't know if these two are valid methods.
378 *shouldResolveRefInBuffer = !found;
379
380 if(result != OK) {
381 return result; // bad pointers and length given
382 }
383 if(!found) { // did not find it.
384 return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle,
385 parentHandle, parentOffset);
386 }
387 // found the buffer. easy case.
388 return parcel->writeEmbeddedReference(
389 handle,
390 childHandle,
391 childOffset,
392 parentHandle,
393 parentOffset);
394}
395
396template <typename T>
397static status_t readReferenceFromParcel(
398 T const* *bufptr,
399 const Parcel & parcel,
400 size_t *handle,
401 bool *shouldResolveRefInBuffer
402 ) {
403 bool isPreviouslyWritten;
404 status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr),
405 handle, &isPreviouslyWritten);
406 // tell caller to run T::readEmbeddedToParcel and
407 // T::readEmbeddedReferenceToParcel if necessary.
408 // It is not called here because we don't know if these two are valid methods.
409 *shouldResolveRefInBuffer = !isPreviouslyWritten;
410 return result;
411}
412
413template <typename T>
414static status_t writeReferenceToParcel(
415 T const *buf,
416 Parcel * parcel,
417 size_t *handle,
418 bool *shouldResolveRefInBuffer
419 ) {
420
421 if(buf == nullptr) {
422 *shouldResolveRefInBuffer = false;
423 return parcel->writeNullReference(handle);
424 }
425
426 // find whether the buffer exists
427 size_t childHandle, childOffset;
428 status_t result;
429 bool found;
430
431 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
432
433 // tell caller to run T::writeEmbeddedToParcel and
434 // T::writeEmbeddedReferenceToParcel if necessary.
435 // It is not called here because we don't know if these two are valid methods.
436 *shouldResolveRefInBuffer = !found;
437
438 if(result != OK) {
439 return result; // bad pointers and length given
440 }
441 if(!found) { // did not find it.
442 return parcel->writeBuffer(buf, sizeof(T), handle);
443 }
444 // found the buffer. easy case.
445 return parcel->writeReference(handle,
446 childHandle, childOffset);
447}
448
Martijn Coenen72110162016-08-19 14:28:25 +0200449// ----------------------------------------------------------------------
450// Version functions
451struct hidl_version {
452public:
Chia-I Wu666b76b2016-10-06 14:15:59 +0800453 constexpr hidl_version(uint16_t major, uint16_t minor) : mMajor(major), mMinor(minor) {}
Martijn Coenen72110162016-08-19 14:28:25 +0200454
455 bool operator==(const hidl_version& other) {
456 return (mMajor == other.get_major() && mMinor == other.get_minor());
457 }
Martijn Coenenc28f1152016-08-22 14:06:56 +0200458
Martijn Coenen097a7672016-09-08 16:56:41 +0200459 constexpr uint16_t get_major() const { return mMajor; }
460 constexpr uint16_t get_minor() const { return mMinor; }
Martijn Coenen72110162016-08-19 14:28:25 +0200461
462 android::status_t writeToParcel(android::hardware::Parcel& parcel) const {
Chia-I Wu666b76b2016-10-06 14:15:59 +0800463 return parcel.writeUint32(static_cast<uint32_t>(mMajor) << 16 | mMinor);
Martijn Coenen72110162016-08-19 14:28:25 +0200464 }
465
466 static hidl_version* readFromParcel(const android::hardware::Parcel& parcel) {
467 uint32_t version;
468 android::status_t status = parcel.readUint32(&version);
469 if (status != OK) {
470 return nullptr;
471 } else {
472 return new hidl_version(version >> 16, version & 0xFFFF);
473 }
474 }
475
476private:
477 uint16_t mMajor;
478 uint16_t mMinor;
479};
480
481inline android::hardware::hidl_version make_hidl_version(uint16_t major, uint16_t minor) {
482 return hidl_version(major,minor);
483}
484
Steven Morelandbdf26662016-09-02 11:03:15 -0700485#if defined(__LP64__)
486#define HAL_LIBRARY_PATH_SYSTEM "/system/lib64/hw/"
487#define HAL_LIBRARY_PATH_VENDOR "/vendor/lib64/hw/"
488#define HAL_LIBRARY_PATH_ODM "/odm/lib64/hw/"
489#else
490#define HAL_LIBRARY_PATH_SYSTEM "/system/lib/hw/"
491#define HAL_LIBRARY_PATH_VENDOR "/vendor/lib/hw/"
492#define HAL_LIBRARY_PATH_ODM "/odm/lib/hw/"
493#endif
494
Martijn Coenenc28f1152016-08-22 14:06:56 +0200495#define DECLARE_REGISTER_AND_GET_SERVICE(INTERFACE) \
496 static ::android::sp<I##INTERFACE> getService( \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700497 const std::string &serviceName, bool getStub=false); \
Steven Morelandbdf26662016-09-02 11:03:15 -0700498 status_t registerAsService( \
Martijn Coenen097a7672016-09-08 16:56:41 +0200499 const std::string &serviceName); \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200500
Steven Morelandbdf26662016-09-02 11:03:15 -0700501#define IMPLEMENT_REGISTER_AND_GET_SERVICE(INTERFACE, LIB) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200502 ::android::sp<I##INTERFACE> I##INTERFACE::getService( \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700503 const std::string &serviceName, bool getStub) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200504 { \
505 sp<I##INTERFACE> iface; \
Iliyan Malchevb42ce262016-09-26 00:09:35 -0700506 const struct timespec DELAY {1,0}; \
507 unsigned retries = 3; \
508 if (!getStub) { \
509 do { \
510 const sp<IServiceManager> sm = defaultServiceManager(); \
511 if (sm != nullptr) { \
512 sp<IBinder> binderIface = \
513 sm->checkService(String16(serviceName.c_str()), \
514 I##INTERFACE::version); \
515 iface = IHw##INTERFACE::asInterface(binderIface); \
516 } \
517 if (iface != nullptr) { \
518 return iface; \
519 } \
520 TEMP_FAILURE_RETRY(nanosleep(&DELAY, nullptr)); \
521 } while (retries--); \
Steven Morelandbdf26662016-09-02 11:03:15 -0700522 } \
523 int dlMode = RTLD_LAZY; \
524 void *handle = dlopen(HAL_LIBRARY_PATH_ODM LIB, dlMode); \
525 if (handle == nullptr) { \
526 handle = dlopen(HAL_LIBRARY_PATH_VENDOR LIB, dlMode); \
527 } \
528 if (handle == nullptr) { \
529 handle = dlopen(HAL_LIBRARY_PATH_SYSTEM LIB, dlMode); \
530 } \
531 if (handle == nullptr) { \
532 return iface; \
533 } \
534 I##INTERFACE* (*generator)(const char* name); \
535 *(void **)(&generator) = dlsym(handle, "HIDL_FETCH_I"#INTERFACE); \
536 if (generator) { \
Martijn Coenenf7a651d2016-09-08 13:38:12 +0200537 iface = (*generator)(serviceName.c_str()); \
Steven Moreland7391bc32016-09-14 10:31:48 -0700538 if (iface != nullptr) { \
539 iface = new Bs##INTERFACE(iface); \
540 } \
Steven Morelandbdf26662016-09-02 11:03:15 -0700541 } \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200542 return iface; \
543 } \
Steven Morelandbdf26662016-09-02 11:03:15 -0700544 status_t I##INTERFACE::registerAsService( \
Martijn Coenen097a7672016-09-08 16:56:41 +0200545 const std::string &serviceName) \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200546 { \
547 sp<Bn##INTERFACE> binderIface = new Bn##INTERFACE(this); \
548 const sp<IServiceManager> sm = defaultServiceManager(); \
Martijn Coenen097a7672016-09-08 16:56:41 +0200549 return sm->addService(String16(serviceName.c_str()), binderIface, \
550 I##INTERFACE::version); \
Martijn Coenenc28f1152016-08-22 14:06:56 +0200551 }
552
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700553// ----------------------------------------------------------------------
554// Hidl instrumentation utilities.
555
556// Event that triggers the instrumentation. e.g. enter of an API call on
557// the server/client side, exit of an API call on the server/client side etc.
558enum InstrumentationEvent {
559 SERVER_API_ENTRY = 0,
560 SERVER_API_EXIT,
561 CLIENT_API_ENTRY,
562 CLIENT_API_EXIT,
563 SYNC_CALLBACK_ENTRY,
564 SYNC_CALLBACK_EXIT,
565 ASYNC_CALLBACK_ENTRY,
566 ASYNC_CALLBACK_EXIT,
567};
568
569// Signature of the instrumentation callback function.
570using InstrumentationCallback = std::function<void(
571 const InstrumentationEvent event,
572 const char *package,
573 const char *version,
574 const char *interface,
575 const char *method,
576 std::vector<void *> *args)>;
577
578// Function that lookup and dynamically loads the hidl instrumentation libraries
579// and registers the instrumentation callback functions.
580//
581// The instrumentation libraries should be stored under any of the following
582// directories: HAL_LIBRARY_PATH_SYSTEM, HAL_LIBRARY_PATH_VENDOR and
583// HAL_LIBRARY_PATH_ODM. The name of instrumentation libraries should follow
584// pattern: ^profilerPrefix(.*).profiler.so$
585//
586// Each instrumentation library is expected to implement the instrumentation
587// function called HIDL_INSTRUMENTATION_FUNCTION.
588//
589// A no-op for user build.
590void registerInstrumentationCallbacks(
591 const std::string &profilerPrefix,
592 std::vector<InstrumentationCallback> *instrumentationCallbacks);
593
594// Utility function to determine whether a give file is a instrumentation
595// library (i.e. the file name follow the expected pattern).
596bool isInstrumentationLib(
597 const std::string &profilerPrefix,
598 const dirent *file);
599
Martijn Coenen72110162016-08-19 14:28:25 +0200600} // namespace hardware
601} // namespace android
602
Martijn Coenenc28f1152016-08-22 14:06:56 +0200603
Martijn Coenen72110162016-08-19 14:28:25 +0200604#endif // ANDROID_HIDL_SUPPORT_H
605