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