• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
20 #include <algorithm>
21 #include <array>
22 #include <iterator>
23 #include <cutils/native_handle.h>
24 #include <hidl/HidlInternal.h>
25 #include <hidl/Status.h>
26 #include <map>
27 #include <sstream>
28 #include <stddef.h>
29 #include <tuple>
30 #include <type_traits>
31 #include <utils/Errors.h>
32 #include <utils/RefBase.h>
33 #include <utils/StrongPointer.h>
34 #include <vector>
35 
36 namespace android {
37 
38 // this file is included by all hidl interface, so we must forward declare the
39 // IMemory and IBase types.
40 namespace hidl {
41 namespace memory {
42 namespace V1_0 {
43 
44 struct IMemory;
45 
46 }  // namespace V1_0
47 }  // namespace memory
48 }  // namespace hidl
49 
50 namespace hidl {
51 namespace base {
52 namespace V1_0 {
53 
54 struct IBase;
55 
56 }  // namespace V1_0
57 }  // namespace base
58 }  // namespace hidl
59 
60 namespace hardware {
61 
62 namespace details {
63 // Return true on userdebug / eng builds and false on user builds.
64 bool debuggable();
65 } //  namespace details
66 
67 // hidl_death_recipient is a callback interfaced that can be used with
68 // linkToDeath() / unlinkToDeath()
69 struct hidl_death_recipient : public virtual RefBase {
70     virtual void serviceDied(uint64_t cookie,
71             const ::android::wp<::android::hidl::base::V1_0::IBase>& who) = 0;
72 };
73 
74 // hidl_handle wraps a pointer to a native_handle_t in a hidl_pointer,
75 // so that it can safely be transferred between 32-bit and 64-bit processes.
76 // The ownership semantics for this are:
77 // 1) The conversion constructor and assignment operator taking a const native_handle_t*
78 //    do not take ownership of the handle; this is because these operations are usually
79 //    just done for IPC, and cloning by default is a waste of resources. If you want
80 //    a hidl_handle to take ownership, call setTo(handle, true /*shouldOwn*/);
81 // 2) The copy constructor/assignment operator taking a hidl_handle *DO* take ownership;
82 //    that is because it's not intuitive that this class encapsulates a native_handle_t
83 //    which needs cloning to be valid; in particular, this allows constructs like this:
84 //    hidl_handle copy;
85 //    foo->someHidlCall([&](auto incoming_handle) {
86 //            copy = incoming_handle;
87 //    });
88 //    // copy and its enclosed file descriptors will remain valid here.
89 // 3) The move constructor does what you would expect; it only owns the handle if the
90 //    original did.
91 struct hidl_handle {
92     hidl_handle();
93     ~hidl_handle();
94 
95     hidl_handle(const native_handle_t *handle);
96 
97     // copy constructor.
98     hidl_handle(const hidl_handle &other);
99 
100     // move constructor.
101     hidl_handle(hidl_handle &&other) noexcept;
102 
103     // assignment operators
104     hidl_handle &operator=(const hidl_handle &other);
105 
106     hidl_handle &operator=(const native_handle_t *native_handle);
107 
108     hidl_handle &operator=(hidl_handle &&other) noexcept;
109 
110     void setTo(native_handle_t* handle, bool shouldOwn = false);
111 
112     const native_handle_t* operator->() const;
113 
114     // implicit conversion to const native_handle_t*
115     operator const native_handle_t *() const;
116 
117     // explicit conversion
118     const native_handle_t *getNativeHandle() const;
119 
120     // offsetof(hidl_handle, mHandle) exposed since mHandle is private.
121     static const size_t kOffsetOfNativeHandle;
122 
123 private:
124     void freeHandle();
125 
126     details::hidl_pointer<const native_handle_t> mHandle __attribute__ ((aligned(8)));
127     bool mOwnsHandle __attribute ((aligned(8)));
128 };
129 
130 struct hidl_string {
131     hidl_string();
132     ~hidl_string();
133 
134     // copy constructor.
135     hidl_string(const hidl_string &);
136     // copy from a C-style string. nullptr will create an empty string
137     hidl_string(const char *);
138     // copy the first length characters from a C-style string.
139     hidl_string(const char *, size_t length);
140     // copy from an std::string.
141     hidl_string(const std::string &);
142 
143     // move constructor.
144     hidl_string(hidl_string &&) noexcept;
145 
146     const char *c_str() const;
147     size_t size() const;
148     bool empty() const;
149 
150     // copy assignment operator.
151     hidl_string &operator=(const hidl_string &);
152     // copy from a C-style string.
153     hidl_string &operator=(const char *s);
154     // copy from an std::string.
155     hidl_string &operator=(const std::string &);
156     // move assignment operator.
157     hidl_string &operator=(hidl_string &&other) noexcept;
158     // cast to std::string.
159     operator std::string() const;
160 
161     void clear();
162 
163     // Reference an external char array. Ownership is _not_ transferred.
164     // Caller is responsible for ensuring that underlying memory is valid
165     // for the lifetime of this hidl_string.
166     //
167     // size == strlen(data)
168     void setToExternal(const char *data, size_t size);
169 
170     // offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
171     static const size_t kOffsetOfBuffer;
172 
173 private:
174     details::hidl_pointer<const char> mBuffer;
175     uint32_t mSize;  // NOT including the terminating '\0'.
176     bool mOwnsBuffer; // if true then mBuffer is a mutable char *
177 
178     // copy from data with size. Assume that my memory is freed
179     // (through clear(), for example)
180     void copyFrom(const char *data, size_t size);
181     // move from another hidl_string
182     void moveFrom(hidl_string &&);
183 };
184 
185 // Use NOLINT to suppress missing parentheses warnings around OP.
186 #define HIDL_STRING_OPERATOR(OP)                                              \
187     inline bool operator OP(const hidl_string& hs1, const hidl_string& hs2) { \
188         return strcmp(hs1.c_str(), hs2.c_str()) OP 0; /* NOLINT */            \
189     }                                                                         \
190     inline bool operator OP(const hidl_string& hs, const char* s) {           \
191         return strcmp(hs.c_str(), s) OP 0; /* NOLINT */                       \
192     }                                                                         \
193     inline bool operator OP(const char* s, const hidl_string& hs) {           \
194         return strcmp(s, hs.c_str()) OP 0; /* NOLINT */                       \
195     }
196 
197 HIDL_STRING_OPERATOR(==)
198 HIDL_STRING_OPERATOR(!=)
199 HIDL_STRING_OPERATOR(<)
200 HIDL_STRING_OPERATOR(<=)
201 HIDL_STRING_OPERATOR(>)
202 HIDL_STRING_OPERATOR(>=)
203 
204 #undef HIDL_STRING_OPERATOR
205 
206 // Send our content to the output stream
207 std::ostream& operator<<(std::ostream& os, const hidl_string& str);
208 
209 
210 // hidl_memory is a structure that can be used to transfer
211 // pieces of shared memory between processes. The assumption
212 // of this object is that the memory remains accessible as
213 // long as the file descriptors in the enclosed mHandle
214 // - as well as all of its cross-process dups() - remain opened.
215 struct hidl_memory {
216 
hidl_memoryhidl_memory217     hidl_memory() : mHandle(nullptr), mSize(0), mName("") {
218     }
219 
220     /**
221      * Creates a hidl_memory object whose handle has the same lifetime
222      * as the handle moved into it.
223      */
hidl_memoryhidl_memory224     hidl_memory(const hidl_string& name, hidl_handle&& handle, size_t size)
225         : mHandle(std::move(handle)), mSize(size), mName(name) {}
226 
227     /**
228      * Creates a hidl_memory object, but doesn't take ownership of
229      * the passed in native_handle_t; callers are responsible for
230      * making sure the handle remains valid while this object is
231      * used.
232      */
hidl_memoryhidl_memory233     hidl_memory(const hidl_string &name, const native_handle_t *handle, size_t size)
234       :  mHandle(handle),
235          mSize(size),
236          mName(name)
237     {}
238 
239     // copy constructor
hidl_memoryhidl_memory240     hidl_memory(const hidl_memory& other) {
241         *this = other;
242     }
243 
244     // copy assignment
245     hidl_memory &operator=(const hidl_memory &other) {
246         if (this != &other) {
247             mHandle = other.mHandle;
248             mSize = other.mSize;
249             mName = other.mName;
250         }
251 
252         return *this;
253     }
254 
255     // move constructor
hidl_memoryhidl_memory256     hidl_memory(hidl_memory&& other) noexcept {
257         *this = std::move(other);
258     }
259 
260     // move assignment
261     hidl_memory &operator=(hidl_memory &&other) noexcept {
262         if (this != &other) {
263             mHandle = std::move(other.mHandle);
264             mSize = other.mSize;
265             mName = std::move(other.mName);
266             other.mSize = 0;
267         }
268 
269         return *this;
270     }
271 
272 
~hidl_memoryhidl_memory273     ~hidl_memory() {
274     }
275 
handlehidl_memory276     const native_handle_t* handle() const {
277         return mHandle;
278     }
279 
namehidl_memory280     const hidl_string &name() const {
281         return mName;
282     }
283 
sizehidl_memory284     uint64_t size() const {
285         return mSize;
286     }
287 
288     // @return true if it's valid
validhidl_memory289     inline bool valid() const { return handle() != nullptr; }
290 
291     // offsetof(hidl_memory, mHandle) exposed since mHandle is private.
292     static const size_t kOffsetOfHandle;
293     // offsetof(hidl_memory, mName) exposed since mHandle is private.
294     static const size_t kOffsetOfName;
295 
296 private:
297     hidl_handle mHandle __attribute__ ((aligned(8)));
298     uint64_t mSize __attribute__ ((aligned(8)));
299     hidl_string mName __attribute__ ((aligned(8)));
300 };
301 
302 // HidlMemory is a wrapper class to support sp<> for hidl_memory. It also
303 // provides factory methods to create an instance from hidl_memory or
304 // from a opened file descriptor. The number of factory methods can be increase
305 // to support other type of hidl_memory without break the ABI.
306 class HidlMemory : public virtual hidl_memory, public virtual ::android::RefBase {
307 public:
308     static sp<HidlMemory> getInstance(const hidl_memory& mem);
309 
310     static sp<HidlMemory> getInstance(hidl_memory&& mem);
311 
312     static sp<HidlMemory> getInstance(const hidl_string& name, hidl_handle&& handle, uint64_t size);
313     // @param fd, shall be opened and points to the resource.
314     // @note this method takes the ownership of the fd and will close it in
315     //     destructor
316     // @return nullptr in failure with the fd closed
317     static sp<HidlMemory> getInstance(const hidl_string& name, int fd, uint64_t size);
318 
319     virtual ~HidlMemory();
320 
321 protected:
322     HidlMemory();
323     HidlMemory(const hidl_string& name, hidl_handle&& handle, size_t size);
324 };
325 ////////////////////////////////////////////////////////////////////////////////
326 
327 template<typename T>
328 struct hidl_vec {
hidl_vechidl_vec329     hidl_vec() {
330         static_assert(hidl_vec<T>::kOffsetOfBuffer == 0, "wrong offset");
331 
332         memset(this, 0, sizeof(*this));
333         // mSize is 0
334         // mBuffer is nullptr
335 
336         // this is for consistency with the original implementation
337         mOwnsBuffer = true;
338     }
339 
340     // Note, does not initialize primitive types.
hidl_vechidl_vec341     hidl_vec(size_t size) : hidl_vec() { resize(size); }
342 
hidl_vechidl_vec343     hidl_vec(const hidl_vec<T> &other) : hidl_vec() {
344         *this = other;
345     }
346 
hidl_vechidl_vec347     hidl_vec(hidl_vec<T> &&other) noexcept : hidl_vec() {
348         *this = std::move(other);
349     }
350 
hidl_vechidl_vec351     hidl_vec(const std::initializer_list<T> list) : hidl_vec() { *this = list; }
352 
hidl_vechidl_vec353     hidl_vec(const std::vector<T> &other) : hidl_vec() {
354         *this = other;
355     }
356 
357     template <typename InputIterator,
358               typename = typename std::enable_if<std::is_convertible<
359                   typename std::iterator_traits<InputIterator>::iterator_category,
360                   std::input_iterator_tag>::value>::type>
hidl_vechidl_vec361     hidl_vec(InputIterator first, InputIterator last) : hidl_vec() {
362         auto size = std::distance(first, last);
363         if (size > static_cast<int64_t>(UINT32_MAX)) {
364             details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
365         }
366         if (size < 0) {
367             details::logAlwaysFatal("size can't be negative.");
368         }
369         mSize = static_cast<uint32_t>(size);
370         mBuffer = new T[mSize]();
371         mOwnsBuffer = true;
372 
373         size_t idx = 0;
374         for (; first != last; ++first) {
375             mBuffer[idx++] = static_cast<T>(*first);
376         }
377     }
378 
~hidl_vechidl_vec379     ~hidl_vec() {
380         if (mOwnsBuffer) {
381             delete[] mBuffer;
382         }
383         mBuffer = nullptr;
384     }
385 
386     // Reference an existing array, optionally taking ownership. It is the
387     // caller's responsibility to ensure that the underlying memory stays
388     // valid for the lifetime of this hidl_vec.
389     void setToExternal(T *data, size_t size, bool shouldOwn = false) {
390         if (mOwnsBuffer) {
391             delete [] mBuffer;
392         }
393         mBuffer = data;
394         if (size > UINT32_MAX) {
395             details::logAlwaysFatal("external vector size exceeds 2^32 elements.");
396         }
397         mSize = static_cast<uint32_t>(size);
398         mOwnsBuffer = shouldOwn;
399     }
400 
datahidl_vec401     T *data() {
402         return mBuffer;
403     }
404 
datahidl_vec405     const T *data() const {
406         return mBuffer;
407     }
408 
releaseDatahidl_vec409     T *releaseData() {
410         if (!mOwnsBuffer && mSize > 0) {
411             resize(mSize);
412         }
413         mOwnsBuffer = false;
414         return mBuffer;
415     }
416 
417     hidl_vec &operator=(hidl_vec &&other) noexcept {
418         if (mOwnsBuffer) {
419             delete[] mBuffer;
420         }
421         mBuffer = other.mBuffer;
422         mSize = other.mSize;
423         mOwnsBuffer = other.mOwnsBuffer;
424         other.mOwnsBuffer = false;
425         return *this;
426     }
427 
428     hidl_vec &operator=(const hidl_vec &other) {
429         if (this != &other) {
430             if (mOwnsBuffer) {
431                 delete[] mBuffer;
432             }
433             copyFrom(other, other.mSize);
434         }
435 
436         return *this;
437     }
438 
439     // copy from an std::vector.
440     hidl_vec &operator=(const std::vector<T> &other) {
441         if (mOwnsBuffer) {
442             delete[] mBuffer;
443         }
444         copyFrom(other, other.size());
445         return *this;
446     }
447 
448     hidl_vec& operator=(const std::initializer_list<T> list) {
449         if (list.size() > UINT32_MAX) {
450             details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
451         }
452         if (mOwnsBuffer) {
453             delete[] mBuffer;
454         }
455         mSize = static_cast<uint32_t>(list.size());
456         mBuffer = new T[mSize]();
457         mOwnsBuffer = true;
458 
459         size_t idx = 0;
460         for (auto it = list.begin(); it != list.end(); ++it) {
461             mBuffer[idx++] = *it;
462         }
463         return *this;
464     }
465 
466     // cast to an std::vector.
467     operator std::vector<T>() const {
468         std::vector<T> v(mSize);
469         for (size_t i = 0; i < mSize; ++i) {
470             v[i] = mBuffer[i];
471         }
472         return v;
473     }
474 
475     // equality check, assuming that T::operator== is defined.
476     bool operator==(const hidl_vec &other) const {
477         if (mSize != other.size()) {
478             return false;
479         }
480         for (size_t i = 0; i < mSize; ++i) {
481             if (!(mBuffer[i] == other.mBuffer[i])) {
482                 return false;
483             }
484         }
485         return true;
486     }
487 
488     // inequality check, assuming that T::operator== is defined.
489     inline bool operator!=(const hidl_vec &other) const {
490         return !((*this) == other);
491     }
492 
sizehidl_vec493     size_t size() const {
494         return mSize;
495     }
496 
497     T &operator[](size_t index) {
498         return mBuffer[index];
499     }
500 
501     const T &operator[](size_t index) const {
502         return mBuffer[index];
503     }
504 
505     // Does not initialize primitive types if new size > old size.
resizehidl_vec506     void resize(size_t size) {
507         if (size > UINT32_MAX) {
508             details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
509         }
510         T* newBuffer = new T[size]();
511 
512         for (size_t i = 0; i < std::min(static_cast<uint32_t>(size), mSize); ++i) {
513             newBuffer[i] = mBuffer[i];
514         }
515 
516         if (mOwnsBuffer) {
517             delete[] mBuffer;
518         }
519         mBuffer = newBuffer;
520 
521         mSize = static_cast<uint32_t>(size);
522         mOwnsBuffer = true;
523     }
524 
525     // offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
526     static const size_t kOffsetOfBuffer;
527 
528 private:
529     // Define std interator interface for walking the array contents
530     template<bool is_const>
531     class iter : public std::iterator<
532             std::random_access_iterator_tag, /* Category */
533             T,
534             ptrdiff_t, /* Distance */
535             typename std::conditional<is_const, const T *, T *>::type /* Pointer */,
536             typename std::conditional<is_const, const T &, T &>::type /* Reference */>
537     {
538         using traits = std::iterator_traits<iter>;
539         using ptr_type = typename traits::pointer;
540         using ref_type = typename traits::reference;
541         using diff_type = typename traits::difference_type;
542     public:
iterhidl_vec543         iter(ptr_type ptr) : mPtr(ptr) { }
544         inline iter &operator++()    { mPtr++; return *this; }
545         inline iter  operator++(int) { iter i = *this; mPtr++; return i; }
546         inline iter &operator--()    { mPtr--; return *this; }
547         inline iter  operator--(int) { iter i = *this; mPtr--; return i; }
548         inline friend iter operator+(diff_type n, const iter &it) { return it.mPtr + n; }
549         inline iter  operator+(diff_type n) const { return mPtr + n; }
550         inline iter  operator-(diff_type n) const { return mPtr - n; }
551         inline diff_type operator-(const iter &other) const { return mPtr - other.mPtr; }
552         inline iter &operator+=(diff_type n) { mPtr += n; return *this; }
553         inline iter &operator-=(diff_type n) { mPtr -= n; return *this; }
554         inline ref_type operator*() const  { return *mPtr; }
555         inline ptr_type operator->() const { return mPtr; }
556         inline bool operator==(const iter &rhs) const { return mPtr == rhs.mPtr; }
557         inline bool operator!=(const iter &rhs) const { return mPtr != rhs.mPtr; }
558         inline bool operator< (const iter &rhs) const { return mPtr <  rhs.mPtr; }
559         inline bool operator> (const iter &rhs) const { return mPtr >  rhs.mPtr; }
560         inline bool operator<=(const iter &rhs) const { return mPtr <= rhs.mPtr; }
561         inline bool operator>=(const iter &rhs) const { return mPtr >= rhs.mPtr; }
562         inline ref_type operator[](size_t n) const { return mPtr[n]; }
563     private:
564         ptr_type mPtr;
565     };
566 public:
567     using iterator       = iter<false /* is_const */>;
568     using const_iterator = iter<true  /* is_const */>;
569 
beginhidl_vec570     iterator begin() { return data(); }
endhidl_vec571     iterator end() { return data()+mSize; }
beginhidl_vec572     const_iterator begin() const { return data(); }
endhidl_vec573     const_iterator end() const { return data()+mSize; }
574 
575 private:
576     details::hidl_pointer<T> mBuffer;
577     uint32_t mSize;
578     bool mOwnsBuffer;
579 
580     // copy from an array-like object, assuming my resources are freed.
581     template <typename Array>
copyFromhidl_vec582     void copyFrom(const Array &data, size_t size) {
583         mSize = static_cast<uint32_t>(size);
584         mOwnsBuffer = true;
585         if (mSize > 0) {
586             mBuffer = new T[size]();
587             for (size_t i = 0; i < size; ++i) {
588                 mBuffer[i] = data[i];
589             }
590         } else {
591             mBuffer = nullptr;
592         }
593     }
594 };
595 
596 template <typename T>
597 const size_t hidl_vec<T>::kOffsetOfBuffer = offsetof(hidl_vec<T>, mBuffer);
598 
599 ////////////////////////////////////////////////////////////////////////////////
600 
601 namespace details {
602 
603     template<size_t SIZE1, size_t... SIZES>
604     struct product {
605         static constexpr size_t value = SIZE1 * product<SIZES...>::value;
606     };
607 
608     template<size_t SIZE1>
609     struct product<SIZE1> {
610         static constexpr size_t value = SIZE1;
611     };
612 
613     template<typename T, size_t SIZE1, size_t... SIZES>
614     struct std_array {
615         using type = std::array<typename std_array<T, SIZES...>::type, SIZE1>;
616     };
617 
618     template<typename T, size_t SIZE1>
619     struct std_array<T, SIZE1> {
620         using type = std::array<T, SIZE1>;
621     };
622 
623     template<typename T, size_t SIZE1, size_t... SIZES>
624     struct accessor {
625 
626         using std_array_type = typename std_array<T, SIZE1, SIZES...>::type;
627 
628         explicit accessor(T *base)
629             : mBase(base) {
630         }
631 
632         accessor<T, SIZES...> operator[](size_t index) {
633             return accessor<T, SIZES...>(
634                     &mBase[index * product<SIZES...>::value]);
635         }
636 
637         accessor &operator=(const std_array_type &other) {
638             for (size_t i = 0; i < SIZE1; ++i) {
639                 (*this)[i] = other[i];
640             }
641             return *this;
642         }
643 
644     private:
645         T *mBase;
646     };
647 
648     template<typename T, size_t SIZE1>
649     struct accessor<T, SIZE1> {
650 
651         using std_array_type = typename std_array<T, SIZE1>::type;
652 
653         explicit accessor(T *base)
654             : mBase(base) {
655         }
656 
657         T &operator[](size_t index) {
658             return mBase[index];
659         }
660 
661         accessor &operator=(const std_array_type &other) {
662             for (size_t i = 0; i < SIZE1; ++i) {
663                 (*this)[i] = other[i];
664             }
665             return *this;
666         }
667 
668     private:
669         T *mBase;
670     };
671 
672     template<typename T, size_t SIZE1, size_t... SIZES>
673     struct const_accessor {
674 
675         using std_array_type = typename std_array<T, SIZE1, SIZES...>::type;
676 
677         explicit const_accessor(const T *base)
678             : mBase(base) {
679         }
680 
681         const_accessor<T, SIZES...> operator[](size_t index) const {
682             return const_accessor<T, SIZES...>(
683                     &mBase[index * product<SIZES...>::value]);
684         }
685 
686         operator std_array_type() {
687             std_array_type array;
688             for (size_t i = 0; i < SIZE1; ++i) {
689                 array[i] = (*this)[i];
690             }
691             return array;
692         }
693 
694     private:
695         const T *mBase;
696     };
697 
698     template<typename T, size_t SIZE1>
699     struct const_accessor<T, SIZE1> {
700 
701         using std_array_type = typename std_array<T, SIZE1>::type;
702 
703         explicit const_accessor(const T *base)
704             : mBase(base) {
705         }
706 
707         const T &operator[](size_t index) const {
708             return mBase[index];
709         }
710 
711         operator std_array_type() {
712             std_array_type array;
713             for (size_t i = 0; i < SIZE1; ++i) {
714                 array[i] = (*this)[i];
715             }
716             return array;
717         }
718 
719     private:
720         const T *mBase;
721     };
722 
723 }  // namespace details
724 
725 ////////////////////////////////////////////////////////////////////////////////
726 
727 // A multidimensional array of T's. Assumes that T::operator=(const T &) is defined.
728 template<typename T, size_t SIZE1, size_t... SIZES>
729 struct hidl_array {
730 
731     using std_array_type = typename details::std_array<T, SIZE1, SIZES...>::type;
732 
733     hidl_array() = default;
734 
735     // Copies the data from source, using T::operator=(const T &).
736     hidl_array(const T *source) {
737         for (size_t i = 0; i < elementCount(); ++i) {
738             mBuffer[i] = source[i];
739         }
740     }
741 
742     // Copies the data from the given std::array, using T::operator=(const T &).
743     hidl_array(const std_array_type &array) {
744         details::accessor<T, SIZE1, SIZES...> modifier(mBuffer);
745         modifier = array;
746     }
747 
748     T *data() { return mBuffer; }
749     const T *data() const { return mBuffer; }
750 
751     details::accessor<T, SIZES...> operator[](size_t index) {
752         return details::accessor<T, SIZES...>(
753                 &mBuffer[index * details::product<SIZES...>::value]);
754     }
755 
756     details::const_accessor<T, SIZES...> operator[](size_t index) const {
757         return details::const_accessor<T, SIZES...>(
758                 &mBuffer[index * details::product<SIZES...>::value]);
759     }
760 
761     // equality check, assuming that T::operator== is defined.
762     bool operator==(const hidl_array &other) const {
763         for (size_t i = 0; i < elementCount(); ++i) {
764             if (!(mBuffer[i] == other.mBuffer[i])) {
765                 return false;
766             }
767         }
768         return true;
769     }
770 
771     inline bool operator!=(const hidl_array &other) const {
772         return !((*this) == other);
773     }
774 
775     using size_tuple_type = std::tuple<decltype(SIZE1), decltype(SIZES)...>;
776 
777     static constexpr size_tuple_type size() {
778         return std::make_tuple(SIZE1, SIZES...);
779     }
780 
781     static constexpr size_t elementCount() {
782         return details::product<SIZE1, SIZES...>::value;
783     }
784 
785     operator std_array_type() const {
786         return details::const_accessor<T, SIZE1, SIZES...>(mBuffer);
787     }
788 
789 private:
790     T mBuffer[elementCount()];
791 };
792 
793 // An array of T's. Assumes that T::operator=(const T &) is defined.
794 template<typename T, size_t SIZE1>
795 struct hidl_array<T, SIZE1> {
796 
797     using std_array_type = typename details::std_array<T, SIZE1>::type;
798 
799     hidl_array() = default;
800 
801     // Copies the data from source, using T::operator=(const T &).
802     hidl_array(const T *source) {
803         for (size_t i = 0; i < elementCount(); ++i) {
804             mBuffer[i] = source[i];
805         }
806     }
807 
808     // Copies the data from the given std::array, using T::operator=(const T &).
809     hidl_array(const std_array_type &array) : hidl_array(array.data()) {}
810 
811     T *data() { return mBuffer; }
812     const T *data() const { return mBuffer; }
813 
814     T &operator[](size_t index) {
815         return mBuffer[index];
816     }
817 
818     const T &operator[](size_t index) const {
819         return mBuffer[index];
820     }
821 
822     // equality check, assuming that T::operator== is defined.
823     bool operator==(const hidl_array &other) const {
824         for (size_t i = 0; i < elementCount(); ++i) {
825             if (!(mBuffer[i] == other.mBuffer[i])) {
826                 return false;
827             }
828         }
829         return true;
830     }
831 
832     inline bool operator!=(const hidl_array &other) const {
833         return !((*this) == other);
834     }
835 
836     static constexpr size_t size() { return SIZE1; }
837     static constexpr size_t elementCount() { return SIZE1; }
838 
839     // Copies the data to an std::array, using T::operator=(T).
840     operator std_array_type() const {
841         std_array_type array;
842         for (size_t i = 0; i < SIZE1; ++i) {
843             array[i] = mBuffer[i];
844         }
845         return array;
846     }
847 
848 private:
849     T mBuffer[SIZE1];
850 };
851 
852 // ----------------------------------------------------------------------
853 // Version functions
854 struct hidl_version {
855 public:
856     constexpr hidl_version(uint16_t major, uint16_t minor) : mMajor(major), mMinor(minor) {
857         static_assert(sizeof(*this) == 4, "wrong size");
858     }
859 
860     bool operator==(const hidl_version& other) const {
861         return (mMajor == other.get_major() && mMinor == other.get_minor());
862     }
863 
864     bool operator!=(const hidl_version& other) const {
865         return !(*this == other);
866     }
867 
868     bool operator<(const hidl_version& other) const {
869         return (mMajor < other.get_major() ||
870                 (mMajor == other.get_major() && mMinor < other.get_minor()));
871     }
872 
873     bool operator>(const hidl_version& other) const {
874         return other < *this;
875     }
876 
877     bool operator<=(const hidl_version& other) const {
878         return !(*this > other);
879     }
880 
881     bool operator>=(const hidl_version& other) const {
882         return !(*this < other);
883     }
884 
885     constexpr uint16_t get_major() const { return mMajor; }
886     constexpr uint16_t get_minor() const { return mMinor; }
887 
888 private:
889     uint16_t mMajor;
890     uint16_t mMinor;
891 };
892 
893 inline android::hardware::hidl_version make_hidl_version(uint16_t major, uint16_t minor) {
894     return hidl_version(major,minor);
895 }
896 
897 ///////////////////// toString functions
898 
899 std::string toString(const void *t);
900 
901 // toString alias for numeric types
902 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
903 inline std::string toString(T t) {
904     return std::to_string(t);
905 }
906 
907 namespace details {
908 
909 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
910 inline std::string toHexString(T t, bool prefix = true) {
911     std::ostringstream os;
912     if (prefix) { os << std::showbase; }
913     os << std::hex << t;
914     return os.str();
915 }
916 
917 template<>
918 inline std::string toHexString(uint8_t t, bool prefix) {
919     return toHexString(static_cast<int32_t>(t), prefix);
920 }
921 
922 template<>
923 inline std::string toHexString(int8_t t, bool prefix) {
924     return toHexString(static_cast<int32_t>(t), prefix);
925 }
926 
927 template<typename Array>
928 std::string arrayToString(const Array &a, size_t size);
929 
930 template<size_t SIZE1>
931 std::string arraySizeToString() {
932     return std::string{"["} + toString(SIZE1) + "]";
933 }
934 
935 template<size_t SIZE1, size_t SIZE2, size_t... SIZES>
936 std::string arraySizeToString() {
937     return std::string{"["} + toString(SIZE1) + "]" + arraySizeToString<SIZE2, SIZES...>();
938 }
939 
940 template<typename T, size_t SIZE1>
941 std::string toString(details::const_accessor<T, SIZE1> a) {
942     return arrayToString(a, SIZE1);
943 }
944 
945 template<typename Array>
946 std::string arrayToString(const Array &a, size_t size) {
947     using android::hardware::toString;
948     std::string os;
949     os += "{";
950     for (size_t i = 0; i < size; ++i) {
951         if (i > 0) {
952             os += ", ";
953         }
954         os += toString(a[i]);
955     }
956     os += "}";
957     return os;
958 }
959 
960 template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
961 std::string toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...> a) {
962     return arrayToString(a, SIZE1);
963 }
964 
965 }  //namespace details
966 
967 inline std::string toString(const void *t) {
968     return details::toHexString(reinterpret_cast<uintptr_t>(t));
969 }
970 
971 // debug string dump. There will be quotes around the string!
972 inline std::string toString(const hidl_string &hs) {
973     return std::string{"\""} + hs.c_str() + "\"";
974 }
975 
976 // debug string dump
977 inline std::string toString(const hidl_handle &hs) {
978     return toString(hs.getNativeHandle());
979 }
980 
981 inline std::string toString(const hidl_memory &mem) {
982     return std::string{"memory {.name = "} + toString(mem.name()) + ", .size = "
983               + toString(mem.size())
984               + ", .handle = " + toString(mem.handle()) + "}";
985 }
986 
987 inline std::string toString(const sp<hidl_death_recipient> &dr) {
988     return std::string{"death_recipient@"} + toString(dr.get());
989 }
990 
991 // debug string dump, assuming that toString(T) is defined.
992 template<typename T>
993 std::string toString(const hidl_vec<T> &a) {
994     std::string os;
995     os += "[" + toString(a.size()) + "]";
996     os += details::arrayToString(a, a.size());
997     return os;
998 }
999 
1000 template<typename T, size_t SIZE1>
1001 std::string toString(const hidl_array<T, SIZE1> &a) {
1002     return details::arraySizeToString<SIZE1>()
1003             + details::toString(details::const_accessor<T, SIZE1>(a.data()));
1004 }
1005 
1006 template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
1007 std::string toString(const hidl_array<T, SIZE1, SIZE2, SIZES...> &a) {
1008     return details::arraySizeToString<SIZE1, SIZE2, SIZES...>()
1009             + details::toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...>(a.data()));
1010 }
1011 
1012 namespace details {
1013 // Never instantiated. Used as a placeholder for template variables.
1014 template <typename T>
1015 struct hidl_invalid_type;
1016 
1017 // HIDL generates specializations of this for enums. See hidl_enum_range.
1018 template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
1019 constexpr hidl_invalid_type<T> hidl_enum_values;
1020 }  // namespace details
1021 
1022 /**
1023  * Every HIDL generated enum supports this function.
1024  * E.x.: for(const auto v : hidl_enum_range<Enum>) { ... }
1025  */
1026 template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
1027 struct hidl_enum_range {
1028     constexpr auto begin() const { return std::begin(details::hidl_enum_values<T>); }
1029     constexpr auto cbegin() const { return begin(); }
1030     constexpr auto rbegin() const { return std::rbegin(details::hidl_enum_values<T>); }
1031     constexpr auto crbegin() const { return rbegin(); }
1032     constexpr auto end() const { return std::end(details::hidl_enum_values<T>); }
1033     constexpr auto cend() const { return end(); }
1034     constexpr auto rend() const { return std::rend(details::hidl_enum_values<T>); }
1035     constexpr auto crend() const { return rend(); }
1036 };
1037 
1038 template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
1039 struct hidl_enum_iterator {
1040     static_assert(!std::is_enum<T>::value,
1041                   "b/78573628: hidl_enum_iterator was renamed to hidl_enum_range because it is not "
1042                   "actually an iterator. Please use that type instead.");
1043 };
1044 
1045 /**
1046  * Bitfields in HIDL are the underlying type of the enumeration.
1047  */
1048 template <typename Enum>
1049 using hidl_bitfield = typename std::underlying_type<Enum>::type;
1050 
1051 }  // namespace hardware
1052 }  // namespace android
1053 
1054 
1055 #endif  // ANDROID_HIDL_SUPPORT_H
1056