#ifndef ANDROID_HIDL_SUPPORT_H
#define ANDROID_HIDL_SUPPORT_H
-//#include <algorithm>
-//#include <array>
+#include <string>
#include <iterator>
#include <cutils/native_handle.h>
#include <hidl/HidlInternal.h>
-//#include <hidl/Status.h>
#include <map>
-//#include <sstream>
#include <stddef.h>
#include <tuple>
#include <type_traits>
-//#include <utils/Errors.h>
-//#include <utils/RefBase.h>
-//#include <utils/StrongPointer.h>
+
+#if 0 // REF-ANN
+#include <algorithm>
+#include <array>
+#include <iterator>
+#include <cutils/native_handle.h>
+#include <hidl/HidlInternal.h>
+#include <hidl/Status.h>
+#include <map>
+#include <sstream>
+#include <stddef.h>
+#include <tuple>
+#include <type_traits>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
#include <vector>
-#include <string>
+#endif
namespace android {
namespace hardware {
+#if 0 // REF-ANN
+namespace details {
+// Return true on userdebug / eng builds and false on user builds.
+bool debuggable();
+} // namespace details
+
+// hidl_death_recipient is a callback interfaced that can be used with
+// linkToDeath() / unlinkToDeath()
+struct hidl_death_recipient : public virtual RefBase {
+ virtual void serviceDied(uint64_t cookie,
+ const ::android::wp<::android::hidl::base::V1_0::IBase>& who) = 0;
+};
+
+// hidl_handle wraps a pointer to a native_handle_t in a hidl_pointer,
+// so that it can safely be transferred between 32-bit and 64-bit processes.
+// The ownership semantics for this are:
+// 1) The conversion constructor and assignment operator taking a const native_handle_t*
+// do not take ownership of the handle; this is because these operations are usually
+// just done for IPC, and cloning by default is a waste of resources. If you want
+// a hidl_handle to take ownership, call setTo(handle, true /*shouldOwn*/);
+// 2) The copy constructor/assignment operator taking a hidl_handle *DO* take ownership;
+// that is because it's not intuitive that this class encapsulates a native_handle_t
+// which needs cloning to be valid; in particular, this allows constructs like this:
+// hidl_handle copy;
+// foo->someHidlCall([&](auto incoming_handle) {
+// copy = incoming_handle;
+// });
+// // copy and its enclosed file descriptors will remain valid here.
+// 3) The move constructor does what you would expect; it only owns the handle if the
+// original did.
+struct hidl_handle {
+ hidl_handle();
+ ~hidl_handle();
+
+ hidl_handle(const native_handle_t *handle);
+
+ // copy constructor.
+ hidl_handle(const hidl_handle &other);
+
+ // move constructor.
+ hidl_handle(hidl_handle &&other) noexcept;
+
+ // assignment operators
+ hidl_handle &operator=(const hidl_handle &other);
+
+ hidl_handle &operator=(const native_handle_t *native_handle);
+
+ hidl_handle &operator=(hidl_handle &&other) noexcept;
+
+ void setTo(native_handle_t* handle, bool shouldOwn = false);
+
+ const native_handle_t* operator->() const;
+
+ // implicit conversion to const native_handle_t*
+ operator const native_handle_t *() const;
+
+ // explicit conversion
+ const native_handle_t *getNativeHandle() const;
+private:
+ void freeHandle();
+
+ details::hidl_pointer<const native_handle_t> mHandle __attribute__ ((aligned(8)));
+ bool mOwnsHandle __attribute ((aligned(8)));
+};
+
+struct hidl_string {
+ hidl_string();
+ ~hidl_string();
+
+ // copy constructor.
+ hidl_string(const hidl_string &);
+ // copy from a C-style string. nullptr will create an empty string
+ hidl_string(const char *);
+ // copy the first length characters from a C-style string.
+ hidl_string(const char *, size_t length);
+ // copy from an std::string.
+ hidl_string(const std::string &);
+
+ // move constructor.
+ hidl_string(hidl_string &&) noexcept;
+
+ const char *c_str() const;
+ size_t size() const;
+ bool empty() const;
+
+ // copy assignment operator.
+ hidl_string &operator=(const hidl_string &);
+ // copy from a C-style string.
+ hidl_string &operator=(const char *s);
+ // copy from an std::string.
+ hidl_string &operator=(const std::string &);
+ // move assignment operator.
+ hidl_string &operator=(hidl_string &&other) noexcept;
+ // cast to std::string.
+ operator std::string() const;
+
+ void clear();
+
+ // Reference an external char array. Ownership is _not_ transferred.
+ // Caller is responsible for ensuring that underlying memory is valid
+ // for the lifetime of this hidl_string.
+ void setToExternal(const char *data, size_t size);
+
+ // offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
+ static const size_t kOffsetOfBuffer;
+
+private:
+ details::hidl_pointer<const char> mBuffer;
+ uint32_t mSize; // NOT including the terminating '\0'.
+ bool mOwnsBuffer; // if true then mBuffer is a mutable char *
+
+ // copy from data with size. Assume that my memory is freed
+ // (through clear(), for example)
+ void copyFrom(const char *data, size_t size);
+ // move from another hidl_string
+ void moveFrom(hidl_string &&);
+};
+
+#define HIDL_STRING_OPERATOR(OP) \
+ inline bool operator OP(const hidl_string &hs1, const hidl_string &hs2) { \
+ return strcmp(hs1.c_str(), hs2.c_str()) OP 0; \
+ } \
+ inline bool operator OP(const hidl_string &hs, const char *s) { \
+ return strcmp(hs.c_str(), s) OP 0; \
+ } \
+ inline bool operator OP(const char *s, const hidl_string &hs) { \
+ return strcmp(hs.c_str(), s) OP 0; \
+ }
+
+HIDL_STRING_OPERATOR(==)
+HIDL_STRING_OPERATOR(!=)
+HIDL_STRING_OPERATOR(<)
+HIDL_STRING_OPERATOR(<=)
+HIDL_STRING_OPERATOR(>)
+HIDL_STRING_OPERATOR(>=)
+
+#undef HIDL_STRING_OPERATOR
+
+// Send our content to the output stream
+std::ostream& operator<<(std::ostream& os, const hidl_string& str);
+#endif
+
+
// hidl_memory is a structure that can be used to transfer
// pieces of shared memory between processes. The assumption
// of this object is that the memory remains accessible as
* used.
*/
hidl_memory(const std::string &name, const native_handle_t *handle, size_t size)
+#if 0 // REF-ANN
+ hidl_memory(const hidl_string &name, const native_handle_t *handle, size_t size)
+#endif
: mHandle(handle),
mSize(size),
mName(name)
- {
-// mName = const_cast<std::string>(name);
- }
+ {}
// copy constructor
hidl_memory(const hidl_memory& other) {
}
const std::string &name() const {
+#if 0 // REF-ANN
+ const hidl_string &name() const {
+#endif
return mName;
}
static const size_t kOffsetOfName;
private:
- const native_handle_t *mHandle;
- uint64_t mSize;
- std::string mName; // TODO-NNRT: This was hidl_string.
+ const native_handle_t *mHandle __attribute__ ((aligned(8))); // TODO-NNRT: This was hidl_handle.
+ uint64_t mSize __attribute__ ((aligned(8)));
+ std::string mName __attribute__ ((aligned(8))); // TODO-NNRT: This was hidl_string.
+#if 0 // REF-ANN
+ hidl_handle mHandle __attribute__ ((aligned(8)));
+ uint64_t mSize __attribute__ ((aligned(8)));
+ hidl_string mName __attribute__ ((aligned(8)));
+#endif
};
////////////////////////////////////////////////////////////////////////////////
}
};
+
+#if 0 // REF-ANN
+////////////////////////////////////////////////////////////////////////////////
+
+namespace details {
+
+ template<size_t SIZE1, size_t... SIZES>
+ struct product {
+ static constexpr size_t value = SIZE1 * product<SIZES...>::value;
+ };
+
+ template<size_t SIZE1>
+ struct product<SIZE1> {
+ static constexpr size_t value = SIZE1;
+ };
+
+ template<typename T, size_t SIZE1, size_t... SIZES>
+ struct std_array {
+ using type = std::array<typename std_array<T, SIZES...>::type, SIZE1>;
+ };
+
+ template<typename T, size_t SIZE1>
+ struct std_array<T, SIZE1> {
+ using type = std::array<T, SIZE1>;
+ };
+
+ template<typename T, size_t SIZE1, size_t... SIZES>
+ struct accessor {
+
+ using std_array_type = typename std_array<T, SIZE1, SIZES...>::type;
+
+ explicit accessor(T *base)
+ : mBase(base) {
+ }
+
+ accessor<T, SIZES...> operator[](size_t index) {
+ return accessor<T, SIZES...>(
+ &mBase[index * product<SIZES...>::value]);
+ }
+
+ accessor &operator=(const std_array_type &other) {
+ for (size_t i = 0; i < SIZE1; ++i) {
+ (*this)[i] = other[i];
+ }
+ return *this;
+ }
+
+ private:
+ T *mBase;
+ };
+
+ template<typename T, size_t SIZE1>
+ struct accessor<T, SIZE1> {
+
+ using std_array_type = typename std_array<T, SIZE1>::type;
+
+ explicit accessor(T *base)
+ : mBase(base) {
+ }
+
+ T &operator[](size_t index) {
+ return mBase[index];
+ }
+
+ accessor &operator=(const std_array_type &other) {
+ for (size_t i = 0; i < SIZE1; ++i) {
+ (*this)[i] = other[i];
+ }
+ return *this;
+ }
+
+ private:
+ T *mBase;
+ };
+
+ template<typename T, size_t SIZE1, size_t... SIZES>
+ struct const_accessor {
+
+ using std_array_type = typename std_array<T, SIZE1, SIZES...>::type;
+
+ explicit const_accessor(const T *base)
+ : mBase(base) {
+ }
+
+ const_accessor<T, SIZES...> operator[](size_t index) const {
+ return const_accessor<T, SIZES...>(
+ &mBase[index * product<SIZES...>::value]);
+ }
+
+ operator std_array_type() {
+ std_array_type array;
+ for (size_t i = 0; i < SIZE1; ++i) {
+ array[i] = (*this)[i];
+ }
+ return array;
+ }
+
+ private:
+ const T *mBase;
+ };
+
+ template<typename T, size_t SIZE1>
+ struct const_accessor<T, SIZE1> {
+
+ using std_array_type = typename std_array<T, SIZE1>::type;
+
+ explicit const_accessor(const T *base)
+ : mBase(base) {
+ }
+
+ const T &operator[](size_t index) const {
+ return mBase[index];
+ }
+
+ operator std_array_type() {
+ std_array_type array;
+ for (size_t i = 0; i < SIZE1; ++i) {
+ array[i] = (*this)[i];
+ }
+ return array;
+ }
+
+ private:
+ const T *mBase;
+ };
+
+} // namespace details
+
+////////////////////////////////////////////////////////////////////////////////
+
+// A multidimensional array of T's. Assumes that T::operator=(const T &) is defined.
+template<typename T, size_t SIZE1, size_t... SIZES>
+struct hidl_array {
+
+ using std_array_type = typename details::std_array<T, SIZE1, SIZES...>::type;
+
+ hidl_array() = default;
+
+ // Copies the data from source, using T::operator=(const T &).
+ hidl_array(const T *source) {
+ for (size_t i = 0; i < elementCount(); ++i) {
+ mBuffer[i] = source[i];
+ }
+ }
+
+ // Copies the data from the given std::array, using T::operator=(const T &).
+ hidl_array(const std_array_type &array) {
+ details::accessor<T, SIZE1, SIZES...> modifier(mBuffer);
+ modifier = array;
+ }
+
+ T *data() { return mBuffer; }
+ const T *data() const { return mBuffer; }
+
+ details::accessor<T, SIZES...> operator[](size_t index) {
+ return details::accessor<T, SIZES...>(
+ &mBuffer[index * details::product<SIZES...>::value]);
+ }
+
+ details::const_accessor<T, SIZES...> operator[](size_t index) const {
+ return details::const_accessor<T, SIZES...>(
+ &mBuffer[index * details::product<SIZES...>::value]);
+ }
+
+ // equality check, assuming that T::operator== is defined.
+ bool operator==(const hidl_array &other) const {
+ for (size_t i = 0; i < elementCount(); ++i) {
+ if (!(mBuffer[i] == other.mBuffer[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ inline bool operator!=(const hidl_array &other) const {
+ return !((*this) == other);
+ }
+
+ using size_tuple_type = std::tuple<decltype(SIZE1), decltype(SIZES)...>;
+
+ static constexpr size_tuple_type size() {
+ return std::make_tuple(SIZE1, SIZES...);
+ }
+
+ static constexpr size_t elementCount() {
+ return details::product<SIZE1, SIZES...>::value;
+ }
+
+ operator std_array_type() const {
+ return details::const_accessor<T, SIZE1, SIZES...>(mBuffer);
+ }
+
+private:
+ T mBuffer[elementCount()];
+};
+
+// An array of T's. Assumes that T::operator=(const T &) is defined.
+template<typename T, size_t SIZE1>
+struct hidl_array<T, SIZE1> {
+
+ using std_array_type = typename details::std_array<T, SIZE1>::type;
+
+ hidl_array() = default;
+
+ // Copies the data from source, using T::operator=(const T &).
+ hidl_array(const T *source) {
+ for (size_t i = 0; i < elementCount(); ++i) {
+ mBuffer[i] = source[i];
+ }
+ }
+
+ // Copies the data from the given std::array, using T::operator=(const T &).
+ hidl_array(const std_array_type &array) : hidl_array(array.data()) {}
+
+ T *data() { return mBuffer; }
+ const T *data() const { return mBuffer; }
+
+ T &operator[](size_t index) {
+ return mBuffer[index];
+ }
+
+ const T &operator[](size_t index) const {
+ return mBuffer[index];
+ }
+
+ // equality check, assuming that T::operator== is defined.
+ bool operator==(const hidl_array &other) const {
+ for (size_t i = 0; i < elementCount(); ++i) {
+ if (!(mBuffer[i] == other.mBuffer[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ inline bool operator!=(const hidl_array &other) const {
+ return !((*this) == other);
+ }
+
+ static constexpr size_t size() { return SIZE1; }
+ static constexpr size_t elementCount() { return SIZE1; }
+
+ // Copies the data to an std::array, using T::operator=(T).
+ operator std_array_type() const {
+ std_array_type array;
+ for (size_t i = 0; i < SIZE1; ++i) {
+ array[i] = mBuffer[i];
+ }
+ return array;
+ }
+
+private:
+ T mBuffer[SIZE1];
+};
+
+// ----------------------------------------------------------------------
+// Version functions
+struct hidl_version {
+public:
+ constexpr hidl_version(uint16_t major, uint16_t minor) : mMajor(major), mMinor(minor) {}
+
+ bool operator==(const hidl_version& other) const {
+ return (mMajor == other.get_major() && mMinor == other.get_minor());
+ }
+
+ bool operator<(const hidl_version& other) const {
+ return (mMajor < other.get_major() ||
+ (mMajor == other.get_major() && mMinor < other.get_minor()));
+ }
+
+ bool operator>(const hidl_version& other) const {
+ return other < *this;
+ }
+
+ bool operator<=(const hidl_version& other) const {
+ return !(*this > other);
+ }
+
+ bool operator>=(const hidl_version& other) const {
+ return !(*this < other);
+ }
+
+ constexpr uint16_t get_major() const { return mMajor; }
+ constexpr uint16_t get_minor() const { return mMinor; }
+
+private:
+ uint16_t mMajor;
+ uint16_t mMinor;
+};
+
+inline android::hardware::hidl_version make_hidl_version(uint16_t major, uint16_t minor) {
+ return hidl_version(major,minor);
+}
+
+///////////////////// toString functions
+
+std::string toString(const void *t);
+
+// toString alias for numeric types
+template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
+inline std::string toString(T t) {
+ return std::to_string(t);
+}
+
+namespace details {
+
+template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
+inline std::string toHexString(T t, bool prefix = true) {
+ std::ostringstream os;
+ if (prefix) { os << std::showbase; }
+ os << std::hex << t;
+ return os.str();
+}
+
+template<>
+inline std::string toHexString(uint8_t t, bool prefix) {
+ return toHexString(static_cast<int32_t>(t), prefix);
+}
+
+template<>
+inline std::string toHexString(int8_t t, bool prefix) {
+ return toHexString(static_cast<int32_t>(t), prefix);
+}
+
+template<typename Array>
+std::string arrayToString(const Array &a, size_t size);
+
+template<size_t SIZE1>
+std::string arraySizeToString() {
+ return std::string{"["} + toString(SIZE1) + "]";
+}
+
+template<size_t SIZE1, size_t SIZE2, size_t... SIZES>
+std::string arraySizeToString() {
+ return std::string{"["} + toString(SIZE1) + "]" + arraySizeToString<SIZE2, SIZES...>();
+}
+
+template<typename T, size_t SIZE1>
+std::string toString(details::const_accessor<T, SIZE1> a) {
+ return arrayToString(a, SIZE1);
+}
+
+template<typename Array>
+std::string arrayToString(const Array &a, size_t size) {
+ using android::hardware::toString;
+ std::string os;
+ os += "{";
+ for (size_t i = 0; i < size; ++i) {
+ if (i > 0) {
+ os += ", ";
+ }
+ os += toString(a[i]);
+ }
+ os += "}";
+ return os;
+}
+
+template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
+std::string toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...> a) {
+ return arrayToString(a, SIZE1);
+}
+
+} //namespace details
+
+inline std::string toString(const void *t) {
+ return details::toHexString(reinterpret_cast<uintptr_t>(t));
+}
+
+// debug string dump. There will be quotes around the string!
+inline std::string toString(const hidl_string &hs) {
+ return std::string{"\""} + hs.c_str() + "\"";
+}
+
+// debug string dump
+inline std::string toString(const hidl_handle &hs) {
+ return toString(hs.getNativeHandle());
+}
+
+inline std::string toString(const hidl_memory &mem) {
+ return std::string{"memory {.name = "} + toString(mem.name()) + ", .size = "
+ + toString(mem.size())
+ + ", .handle = " + toString(mem.handle()) + "}";
+}
+
+inline std::string toString(const sp<hidl_death_recipient> &dr) {
+ return std::string{"death_recipient@"} + toString(dr.get());
+}
+
+// debug string dump, assuming that toString(T) is defined.
+template<typename T>
+std::string toString(const hidl_vec<T> &a) {
+ std::string os;
+ os += "[" + toString(a.size()) + "]";
+ os += details::arrayToString(a, a.size());
+ return os;
+}
+
+template<typename T, size_t SIZE1>
+std::string toString(const hidl_array<T, SIZE1> &a) {
+ return details::arraySizeToString<SIZE1>()
+ + details::toString(details::const_accessor<T, SIZE1>(a.data()));
+}
+
+template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
+std::string toString(const hidl_array<T, SIZE1, SIZE2, SIZES...> &a) {
+ return details::arraySizeToString<SIZE1, SIZE2, SIZES...>()
+ + details::toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...>(a.data()));
+}
+#endif
+
} // namespace hardware
} // namespace android