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