HidlSupport.h revision 0c84ab4192f9b0b03b9840b85fc430afa17f55f1
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 <vintf/Transport.h>
35#include <vector>
36
37namespace android {
38
39// this file is included by all hidl interface, so we must forward declare the
40// IMemory and IBase types.
41namespace hidl {
42namespace memory {
43namespace V1_0 {
44    struct IMemory;
45}; // namespace V1_0
46}; // namespace manager
47}; // namespace hidl
48
49namespace hidl {
50namespace base {
51namespace V1_0 {
52    struct IBase;
53}; // namespace V1_0
54}; // namespace base
55}; // namespace hidl
56
57namespace hardware {
58
59// Get transport method from vendor interface manifest.
60// interfaceName has the format "android.hardware.foo@1.0::IFoo"
61// instanceName is "default", "ashmem", etc.
62// If it starts with "android.hidl.", a static map is looked up instead.
63vintf::Transport getTransport(const std::string &interfaceName,
64                              const std::string &instanceName);
65
66namespace details {
67// Return true on userdebug / eng builds and false on user builds.
68bool debuggable();
69} //  namespace details
70
71// hidl_death_recipient is a callback interfaced that can be used with
72// linkToDeath() / unlinkToDeath()
73struct hidl_death_recipient : public virtual RefBase {
74    virtual void serviceDied(uint64_t cookie,
75            const ::android::wp<::android::hidl::base::V1_0::IBase>& who) = 0;
76};
77
78// hidl_handle wraps a pointer to a native_handle_t in a hidl_pointer,
79// so that it can safely be transferred between 32-bit and 64-bit processes.
80// The ownership semantics for this are:
81// 1) The conversion constructor and assignment operator taking a const native_handle_t*
82//    do not take ownership of the handle; this is because these operations are usually
83//    just done for IPC, and cloning by default is a waste of resources. If you want
84//    a hidl_handle to take ownership, call setTo(handle, true /*shouldOwn*/);
85// 2) The copy constructor/assignment operator taking a hidl_handle *DO* take ownership;
86//    that is because it's not intuitive that this class encapsulates a native_handle_t
87//    which needs cloning to be valid; in particular, this allows constructs like this:
88//    hidl_handle copy;
89//    foo->someHidlCall([&](auto incoming_handle) {
90//            copy = incoming_handle;
91//    });
92//    // copy and its enclosed file descriptors will remain valid here.
93// 3) The move constructor does what you would expect; it only owns the handle if the
94//    original did.
95struct hidl_handle {
96    hidl_handle();
97    ~hidl_handle();
98
99    hidl_handle(const native_handle_t *handle);
100
101    // copy constructor.
102    hidl_handle(const hidl_handle &other);
103
104    // move constructor.
105    hidl_handle(hidl_handle &&other);
106
107    // assignment operators
108    hidl_handle &operator=(const hidl_handle &other);
109
110    hidl_handle &operator=(const native_handle_t *native_handle);
111
112    hidl_handle &operator=(hidl_handle &&other);
113
114    void setTo(native_handle_t* handle, bool shouldOwn = false);
115
116    const native_handle_t* operator->() const;
117
118    // implicit conversion to const native_handle_t*
119    operator const native_handle_t *() const;
120
121    // explicit conversion
122    const native_handle_t *getNativeHandle() const;
123private:
124    void freeHandle();
125
126    details::hidl_pointer<const native_handle_t> mHandle __attribute__ ((aligned(8)));
127    bool mOwnsHandle __attribute ((aligned(8)));
128};
129
130struct 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 &&);
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);
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    void setToExternal(const char *data, size_t size);
167
168    // offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
169    static const size_t kOffsetOfBuffer;
170
171private:
172    details::hidl_pointer<const char> mBuffer;
173    uint32_t mSize;  // NOT including the terminating '\0'.
174    bool mOwnsBuffer; // if true then mBuffer is a mutable char *
175
176    // copy from data with size. Assume that my memory is freed
177    // (through clear(), for example)
178    void copyFrom(const char *data, size_t size);
179    // move from another hidl_string
180    void moveFrom(hidl_string &&);
181};
182
183#define HIDL_STRING_OPERATOR(OP)                                               \
184    inline bool operator OP(const hidl_string &hs1, const hidl_string &hs2) {  \
185        return strcmp(hs1.c_str(), hs2.c_str()) OP 0;                          \
186    }                                                                          \
187    inline bool operator OP(const hidl_string &hs, const char *s) {            \
188        return strcmp(hs.c_str(), s) OP 0;                                     \
189    }                                                                          \
190    inline bool operator OP(const char *s, const hidl_string &hs) {            \
191        return strcmp(hs.c_str(), s) OP 0;                                     \
192    }
193
194HIDL_STRING_OPERATOR(==)
195HIDL_STRING_OPERATOR(!=)
196HIDL_STRING_OPERATOR(<)
197HIDL_STRING_OPERATOR(<=)
198HIDL_STRING_OPERATOR(>)
199HIDL_STRING_OPERATOR(>=)
200
201#undef HIDL_STRING_OPERATOR
202
203// Send our content to the output stream
204std::ostream& operator<<(std::ostream& os, const hidl_string& str);
205
206
207// hidl_memory is a structure that can be used to transfer
208// pieces of shared memory between processes. The assumption
209// of this object is that the memory remains accessible as
210// long as the file descriptors in the enclosed mHandle
211// - as well as all of its cross-process dups() - remain opened.
212struct hidl_memory {
213
214    hidl_memory() : mHandle(nullptr), mSize(0), mName("") {
215    }
216
217    /**
218     * Creates a hidl_memory object, but doesn't take ownership of
219     * the passed in native_handle_t; callers are responsible for
220     * making sure the handle remains valid while this object is
221     * used.
222     */
223    hidl_memory(const hidl_string &name, const native_handle_t *handle, size_t size)
224      :  mHandle(handle),
225         mSize(size),
226         mName(name)
227    {}
228
229    // copy constructor
230    hidl_memory(const hidl_memory& other) {
231        *this = other;
232    }
233
234    // copy assignment
235    hidl_memory &operator=(const hidl_memory &other) {
236        if (this != &other) {
237            mHandle = other.mHandle;
238            mSize = other.mSize;
239            mName = other.mName;
240        }
241
242        return *this;
243    }
244
245    // move constructor
246    hidl_memory(hidl_memory&& other) {
247        *this = std::move(other);
248    }
249
250    // move assignment
251    hidl_memory &operator=(hidl_memory &&other) {
252        if (this != &other) {
253            mHandle = std::move(other.mHandle);
254            mSize = other.mSize;
255            mName = std::move(other.mName);
256            other.mSize = 0;
257        }
258
259        return *this;
260    }
261
262
263    ~hidl_memory() {
264    }
265
266    const native_handle_t* handle() const {
267        return mHandle;
268    }
269
270    const hidl_string &name() const {
271        return mName;
272    }
273
274    uint64_t size() const {
275        return mSize;
276    }
277
278    // offsetof(hidl_memory, mHandle) exposed since mHandle is private.
279    static const size_t kOffsetOfHandle;
280    // offsetof(hidl_memory, mName) exposed since mHandle is private.
281    static const size_t kOffsetOfName;
282
283private:
284    hidl_handle mHandle __attribute__ ((aligned(8)));
285    uint64_t mSize __attribute__ ((aligned(8)));
286    hidl_string mName __attribute__ ((aligned(8)));
287};
288
289////////////////////////////////////////////////////////////////////////////////
290
291template<typename T>
292struct hidl_vec {
293    hidl_vec()
294        : mBuffer(NULL),
295          mSize(0),
296          mOwnsBuffer(true) {
297        static_assert(hidl_vec<T>::kOffsetOfBuffer == 0, "wrong offset");
298    }
299
300    hidl_vec(const hidl_vec<T> &other) : hidl_vec() {
301        *this = other;
302    }
303
304    hidl_vec(hidl_vec<T> &&other)
305    : mOwnsBuffer(false) {
306        *this = std::move(other);
307    }
308
309    hidl_vec(const std::initializer_list<T> list)
310            : mOwnsBuffer(true) {
311        if (list.size() > UINT32_MAX) {
312            details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
313        }
314        mSize = static_cast<uint32_t>(list.size());
315        mBuffer = new T[mSize];
316
317        size_t idx = 0;
318        for (auto it = list.begin(); it != list.end(); ++it) {
319            mBuffer[idx++] = *it;
320        }
321    }
322
323    hidl_vec(const std::vector<T> &other) : hidl_vec() {
324        *this = other;
325    }
326
327    ~hidl_vec() {
328        if (mOwnsBuffer) {
329            delete[] mBuffer;
330        }
331        mBuffer = NULL;
332    }
333
334    // Reference an existing array, optionally taking ownership. It is the
335    // caller's responsibility to ensure that the underlying memory stays
336    // valid for the lifetime of this hidl_vec.
337    void setToExternal(T *data, size_t size, bool shouldOwn = false) {
338        if (mOwnsBuffer) {
339            delete [] mBuffer;
340        }
341        mBuffer = data;
342        if (size > UINT32_MAX) {
343            details::logAlwaysFatal("external vector size exceeds 2^32 elements.");
344        }
345        mSize = static_cast<uint32_t>(size);
346        mOwnsBuffer = shouldOwn;
347    }
348
349    T *data() {
350        return mBuffer;
351    }
352
353    const T *data() const {
354        return mBuffer;
355    }
356
357    T *releaseData() {
358        if (!mOwnsBuffer && mSize > 0) {
359            resize(mSize);
360        }
361        mOwnsBuffer = false;
362        return mBuffer;
363    }
364
365    hidl_vec &operator=(hidl_vec &&other) {
366        if (mOwnsBuffer) {
367            delete[] mBuffer;
368        }
369        mBuffer = other.mBuffer;
370        mSize = other.mSize;
371        mOwnsBuffer = other.mOwnsBuffer;
372        other.mOwnsBuffer = false;
373        return *this;
374    }
375
376    hidl_vec &operator=(const hidl_vec &other) {
377        if (this != &other) {
378            if (mOwnsBuffer) {
379                delete[] mBuffer;
380            }
381            copyFrom(other, other.mSize);
382        }
383
384        return *this;
385    }
386
387    // copy from an std::vector.
388    hidl_vec &operator=(const std::vector<T> &other) {
389        if (mOwnsBuffer) {
390            delete[] mBuffer;
391        }
392        copyFrom(other, other.size());
393        return *this;
394    }
395
396    // cast to an std::vector.
397    operator std::vector<T>() const {
398        std::vector<T> v(mSize);
399        for (size_t i = 0; i < mSize; ++i) {
400            v[i] = mBuffer[i];
401        }
402        return v;
403    }
404
405    // equality check, assuming that T::operator== is defined.
406    bool operator==(const hidl_vec &other) const {
407        if (mSize != other.size()) {
408            return false;
409        }
410        for (size_t i = 0; i < mSize; ++i) {
411            if (!(mBuffer[i] == other.mBuffer[i])) {
412                return false;
413            }
414        }
415        return true;
416    }
417
418    // inequality check, assuming that T::operator== is defined.
419    inline bool operator!=(const hidl_vec &other) const {
420        return !((*this) == other);
421    }
422
423    size_t size() const {
424        return mSize;
425    }
426
427    T &operator[](size_t index) {
428        return mBuffer[index];
429    }
430
431    const T &operator[](size_t index) const {
432        return mBuffer[index];
433    }
434
435    void resize(size_t size) {
436        if (size > UINT32_MAX) {
437            details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
438        }
439        T *newBuffer = new T[size];
440
441        for (size_t i = 0; i < std::min(static_cast<uint32_t>(size), mSize); ++i) {
442            newBuffer[i] = mBuffer[i];
443        }
444
445        if (mOwnsBuffer) {
446            delete[] mBuffer;
447        }
448        mBuffer = newBuffer;
449
450        mSize = static_cast<uint32_t>(size);
451        mOwnsBuffer = true;
452    }
453
454    // offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
455    static const size_t kOffsetOfBuffer;
456
457private:
458    // Define std interator interface for walking the array contents
459    template<bool is_const>
460    class iter : public std::iterator<
461            std::random_access_iterator_tag, /* Category */
462            T,
463            ptrdiff_t, /* Distance */
464            typename std::conditional<is_const, const T *, T *>::type /* Pointer */,
465            typename std::conditional<is_const, const T &, T &>::type /* Reference */>
466    {
467        using traits = std::iterator_traits<iter>;
468        using ptr_type = typename traits::pointer;
469        using ref_type = typename traits::reference;
470        using diff_type = typename traits::difference_type;
471    public:
472        iter(ptr_type ptr) : mPtr(ptr) { }
473        inline iter &operator++()    { mPtr++; return *this; }
474        inline iter  operator++(int) { iter i = *this; mPtr++; return i; }
475        inline iter &operator--()    { mPtr--; return *this; }
476        inline iter  operator--(int) { iter i = *this; mPtr--; return i; }
477        inline friend iter operator+(diff_type n, const iter &it) { return it.mPtr + n; }
478        inline iter  operator+(diff_type n) const { return mPtr + n; }
479        inline iter  operator-(diff_type n) const { return mPtr - n; }
480        inline diff_type operator-(const iter &other) const { return mPtr - other.mPtr; }
481        inline iter &operator+=(diff_type n) { mPtr += n; return *this; }
482        inline iter &operator-=(diff_type n) { mPtr -= n; return *this; }
483        inline ref_type operator*() const  { return *mPtr; }
484        inline ptr_type operator->() const { return mPtr; }
485        inline bool operator==(const iter &rhs) const { return mPtr == rhs.mPtr; }
486        inline bool operator!=(const iter &rhs) const { return mPtr != rhs.mPtr; }
487        inline bool operator< (const iter &rhs) const { return mPtr <  rhs.mPtr; }
488        inline bool operator> (const iter &rhs) const { return mPtr >  rhs.mPtr; }
489        inline bool operator<=(const iter &rhs) const { return mPtr <= rhs.mPtr; }
490        inline bool operator>=(const iter &rhs) const { return mPtr >= rhs.mPtr; }
491        inline ref_type operator[](size_t n) const { return mPtr[n]; }
492    private:
493        ptr_type mPtr;
494    };
495public:
496    using iterator       = iter<false /* is_const */>;
497    using const_iterator = iter<true  /* is_const */>;
498
499    iterator begin() { return data(); }
500    iterator end() { return data()+mSize; }
501    const_iterator begin() const { return data(); }
502    const_iterator end() const { return data()+mSize; }
503
504private:
505    details::hidl_pointer<T> mBuffer;
506    uint32_t mSize;
507    bool mOwnsBuffer;
508
509    // copy from an array-like object, assuming my resources are freed.
510    template <typename Array>
511    void copyFrom(const Array &data, size_t size) {
512        mSize = static_cast<uint32_t>(size);
513        mOwnsBuffer = true;
514        if (mSize > 0) {
515            mBuffer = new T[size];
516            for (size_t i = 0; i < size; ++i) {
517                mBuffer[i] = data[i];
518            }
519        } else {
520            mBuffer = NULL;
521        }
522    }
523};
524
525template <typename T>
526const size_t hidl_vec<T>::kOffsetOfBuffer = offsetof(hidl_vec<T>, mBuffer);
527
528////////////////////////////////////////////////////////////////////////////////
529
530namespace details {
531
532    template<size_t SIZE1, size_t... SIZES>
533    struct product {
534        static constexpr size_t value = SIZE1 * product<SIZES...>::value;
535    };
536
537    template<size_t SIZE1>
538    struct product<SIZE1> {
539        static constexpr size_t value = SIZE1;
540    };
541
542    template<typename T, size_t SIZE1, size_t... SIZES>
543    struct std_array {
544        using type = std::array<typename std_array<T, SIZES...>::type, SIZE1>;
545    };
546
547    template<typename T, size_t SIZE1>
548    struct std_array<T, SIZE1> {
549        using type = std::array<T, SIZE1>;
550    };
551
552    template<typename T, size_t SIZE1, size_t... SIZES>
553    struct accessor {
554
555        using std_array_type = typename std_array<T, SIZE1, SIZES...>::type;
556
557        explicit accessor(T *base)
558            : mBase(base) {
559        }
560
561        accessor<T, SIZES...> operator[](size_t index) {
562            return accessor<T, SIZES...>(
563                    &mBase[index * product<SIZES...>::value]);
564        }
565
566        accessor &operator=(const std_array_type &other) {
567            for (size_t i = 0; i < SIZE1; ++i) {
568                (*this)[i] = other[i];
569            }
570            return *this;
571        }
572
573    private:
574        T *mBase;
575    };
576
577    template<typename T, size_t SIZE1>
578    struct accessor<T, SIZE1> {
579
580        using std_array_type = typename std_array<T, SIZE1>::type;
581
582        explicit accessor(T *base)
583            : mBase(base) {
584        }
585
586        T &operator[](size_t index) {
587            return mBase[index];
588        }
589
590        accessor &operator=(const std_array_type &other) {
591            for (size_t i = 0; i < SIZE1; ++i) {
592                (*this)[i] = other[i];
593            }
594            return *this;
595        }
596
597    private:
598        T *mBase;
599    };
600
601    template<typename T, size_t SIZE1, size_t... SIZES>
602    struct const_accessor {
603
604        using std_array_type = typename std_array<T, SIZE1, SIZES...>::type;
605
606        explicit const_accessor(const T *base)
607            : mBase(base) {
608        }
609
610        const_accessor<T, SIZES...> operator[](size_t index) const {
611            return const_accessor<T, SIZES...>(
612                    &mBase[index * product<SIZES...>::value]);
613        }
614
615        operator std_array_type() {
616            std_array_type array;
617            for (size_t i = 0; i < SIZE1; ++i) {
618                array[i] = (*this)[i];
619            }
620            return array;
621        }
622
623    private:
624        const T *mBase;
625    };
626
627    template<typename T, size_t SIZE1>
628    struct const_accessor<T, SIZE1> {
629
630        using std_array_type = typename std_array<T, SIZE1>::type;
631
632        explicit const_accessor(const T *base)
633            : mBase(base) {
634        }
635
636        const T &operator[](size_t index) const {
637            return mBase[index];
638        }
639
640        operator std_array_type() {
641            std_array_type array;
642            for (size_t i = 0; i < SIZE1; ++i) {
643                array[i] = (*this)[i];
644            }
645            return array;
646        }
647
648    private:
649        const T *mBase;
650    };
651
652}  // namespace details
653
654////////////////////////////////////////////////////////////////////////////////
655
656// A multidimensional array of T's. Assumes that T::operator=(const T &) is defined.
657template<typename T, size_t SIZE1, size_t... SIZES>
658struct hidl_array {
659
660    using std_array_type = typename details::std_array<T, SIZE1, SIZES...>::type;
661
662    hidl_array() = default;
663
664    // Copies the data from source, using T::operator=(const T &).
665    hidl_array(const T *source) {
666        for (size_t i = 0; i < elementCount(); ++i) {
667            mBuffer[i] = source[i];
668        }
669    }
670
671    // Copies the data from the given std::array, using T::operator=(const T &).
672    hidl_array(const std_array_type &array) {
673        details::accessor<T, SIZE1, SIZES...> modifier(mBuffer);
674        modifier = array;
675    }
676
677    T *data() { return mBuffer; }
678    const T *data() const { return mBuffer; }
679
680    details::accessor<T, SIZES...> operator[](size_t index) {
681        return details::accessor<T, SIZES...>(
682                &mBuffer[index * details::product<SIZES...>::value]);
683    }
684
685    details::const_accessor<T, SIZES...> operator[](size_t index) const {
686        return details::const_accessor<T, SIZES...>(
687                &mBuffer[index * details::product<SIZES...>::value]);
688    }
689
690    // equality check, assuming that T::operator== is defined.
691    bool operator==(const hidl_array &other) const {
692        for (size_t i = 0; i < elementCount(); ++i) {
693            if (!(mBuffer[i] == other.mBuffer[i])) {
694                return false;
695            }
696        }
697        return true;
698    }
699
700    inline bool operator!=(const hidl_array &other) const {
701        return !((*this) == other);
702    }
703
704    using size_tuple_type = std::tuple<decltype(SIZE1), decltype(SIZES)...>;
705
706    static constexpr size_tuple_type size() {
707        return std::make_tuple(SIZE1, SIZES...);
708    }
709
710    static constexpr size_t elementCount() {
711        return details::product<SIZE1, SIZES...>::value;
712    }
713
714    operator std_array_type() const {
715        return details::const_accessor<T, SIZE1, SIZES...>(mBuffer);
716    }
717
718private:
719    T mBuffer[elementCount()];
720};
721
722// An array of T's. Assumes that T::operator=(const T &) is defined.
723template<typename T, size_t SIZE1>
724struct hidl_array<T, SIZE1> {
725
726    using std_array_type = typename details::std_array<T, SIZE1>::type;
727
728    hidl_array() = default;
729
730    // Copies the data from source, using T::operator=(const T &).
731    hidl_array(const T *source) {
732        for (size_t i = 0; i < elementCount(); ++i) {
733            mBuffer[i] = source[i];
734        }
735    }
736
737    // Copies the data from the given std::array, using T::operator=(const T &).
738    hidl_array(const std_array_type &array) : hidl_array(array.data()) {}
739
740    T *data() { return mBuffer; }
741    const T *data() const { return mBuffer; }
742
743    T &operator[](size_t index) {
744        return mBuffer[index];
745    }
746
747    const T &operator[](size_t index) const {
748        return mBuffer[index];
749    }
750
751    // equality check, assuming that T::operator== is defined.
752    bool operator==(const hidl_array &other) const {
753        for (size_t i = 0; i < elementCount(); ++i) {
754            if (!(mBuffer[i] == other.mBuffer[i])) {
755                return false;
756            }
757        }
758        return true;
759    }
760
761    inline bool operator!=(const hidl_array &other) const {
762        return !((*this) == other);
763    }
764
765    static constexpr size_t size() { return SIZE1; }
766    static constexpr size_t elementCount() { return SIZE1; }
767
768    // Copies the data to an std::array, using T::operator=(T).
769    operator std_array_type() const {
770        std_array_type array;
771        for (size_t i = 0; i < SIZE1; ++i) {
772            array[i] = mBuffer[i];
773        }
774        return array;
775    }
776
777private:
778    T mBuffer[SIZE1];
779};
780
781// ----------------------------------------------------------------------
782// Version functions
783struct hidl_version {
784public:
785    constexpr hidl_version(uint16_t major, uint16_t minor) : mMajor(major), mMinor(minor) {}
786
787    bool operator==(const hidl_version& other) const {
788        return (mMajor == other.get_major() && mMinor == other.get_minor());
789    }
790
791    bool operator<(const hidl_version& other) const {
792        return (mMajor < other.get_major() ||
793                (mMajor == other.get_major() && mMinor < other.get_minor()));
794    }
795
796    bool operator>(const hidl_version& other) const {
797        return other < *this;
798    }
799
800    bool operator<=(const hidl_version& other) const {
801        return !(*this > other);
802    }
803
804    bool operator>=(const hidl_version& other) const {
805        return !(*this < other);
806    }
807
808    constexpr uint16_t get_major() const { return mMajor; }
809    constexpr uint16_t get_minor() const { return mMinor; }
810
811private:
812    uint16_t mMajor;
813    uint16_t mMinor;
814};
815
816inline android::hardware::hidl_version make_hidl_version(uint16_t major, uint16_t minor) {
817    return hidl_version(major,minor);
818}
819
820///////////////////// toString functions
821
822std::string toString(const void *t);
823
824// toString alias for numeric types
825template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
826inline std::string toString(T t) {
827    return std::to_string(t);
828}
829
830namespace details {
831
832template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
833inline std::string toHexString(T t, bool prefix = true) {
834    std::ostringstream os;
835    if (prefix) { os << std::showbase; }
836    os << std::hex << t;
837    return os.str();
838}
839
840template<>
841inline std::string toHexString(uint8_t t, bool prefix) {
842    return toHexString(static_cast<int32_t>(t), prefix);
843}
844
845template<>
846inline std::string toHexString(int8_t t, bool prefix) {
847    return toHexString(static_cast<int32_t>(t), prefix);
848}
849
850template<typename Array>
851std::string arrayToString(const Array &a, size_t size);
852
853template<size_t SIZE1>
854std::string arraySizeToString() {
855    return std::string{"["} + toString(SIZE1) + "]";
856}
857
858template<size_t SIZE1, size_t SIZE2, size_t... SIZES>
859std::string arraySizeToString() {
860    return std::string{"["} + toString(SIZE1) + "]" + arraySizeToString<SIZE2, SIZES...>();
861}
862
863template<typename T, size_t SIZE1>
864std::string toString(details::const_accessor<T, SIZE1> a) {
865    return arrayToString(a, SIZE1);
866}
867
868template<typename Array>
869std::string arrayToString(const Array &a, size_t size) {
870    using android::hardware::toString;
871    std::string os;
872    os += "{";
873    for (size_t i = 0; i < size; ++i) {
874        if (i > 0) {
875            os += ", ";
876        }
877        os += toString(a[i]);
878    }
879    os += "}";
880    return os;
881}
882
883template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
884std::string toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...> a) {
885    return arrayToString(a, SIZE1);
886}
887
888}  //namespace details
889
890inline std::string toString(const void *t) {
891    return details::toHexString(reinterpret_cast<uintptr_t>(t));
892}
893
894// debug string dump. There will be quotes around the string!
895inline std::string toString(const hidl_string &hs) {
896    return std::string{"\""} + hs.c_str() + "\"";
897}
898
899// debug string dump
900inline std::string toString(const hidl_handle &hs) {
901    return toString(hs.getNativeHandle());
902}
903
904inline std::string toString(const hidl_memory &mem) {
905    return std::string{"memory {.name = "} + toString(mem.name()) + ", .size = "
906              + toString(mem.size())
907              + ", .handle = " + toString(mem.handle()) + "}";
908}
909
910inline std::string toString(const sp<hidl_death_recipient> &dr) {
911    return std::string{"death_recipient@"} + toString(dr.get());
912}
913
914// debug string dump, assuming that toString(T) is defined.
915template<typename T>
916std::string toString(const hidl_vec<T> &a) {
917    std::string os;
918    os += "[" + toString(a.size()) + "]";
919    os += details::arrayToString(a, a.size());
920    return os;
921}
922
923template<typename T, size_t SIZE1>
924std::string toString(const hidl_array<T, SIZE1> &a) {
925    return details::arraySizeToString<SIZE1>()
926            + details::toString(details::const_accessor<T, SIZE1>(a.data()));
927}
928
929template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
930std::string toString(const hidl_array<T, SIZE1, SIZE2, SIZES...> &a) {
931    return details::arraySizeToString<SIZE1, SIZE2, SIZES...>()
932            + details::toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...>(a.data()));
933}
934
935}  // namespace hardware
936}  // namespace android
937
938
939#endif  // ANDROID_HIDL_SUPPORT_H
940