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