fix and expand hidl_vec::iterator; add const_iterator.

* Fix flipped post++ and ++pre for hidl_vec::iterator
* make it random accessible.
* add const_iterator.

Test: hidl_test
Change-Id: I8649f8598a13e6054c994d30a4daf383d1dae55c
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index 61a8bea..8bdb5fe 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -28,7 +28,9 @@
 #include <hidl/HidlInternal.h>
 #include <hidl/Status.h>
 #include <map>
+#include <stddef.h>
 #include <tuple>
+#include <type_traits>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/StrongPointer.h>
@@ -395,25 +397,52 @@
     // offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
     static const size_t kOffsetOfBuffer;
 
+private:
     // Define std interator interface for walking the array contents
-    // TODO:  it might be nice to implement a full featured random access iterator...
-    class iterator : public std::iterator<std::bidirectional_iterator_tag, T>
+    template<bool is_const>
+    class iter : public std::iterator<
+            std::random_access_iterator_tag, /* Category */
+            T,
+            ptrdiff_t, /* Distance */
+            typename std::conditional<is_const, const T *, T *>::type /* Pointer */,
+            typename std::conditional<is_const, const T &, T &>::type /* Reference */>
     {
+        using traits = std::iterator_traits<iter>;
+        using ptr_type = typename traits::pointer;
+        using ref_type = typename traits::reference;
+        using diff_type = typename traits::difference_type;
     public:
-        iterator(T* ptr) : mPtr(ptr) { }
-        iterator operator++()    { iterator i = *this; mPtr++; return i; }
-        iterator operator++(int) { mPtr++; return *this; }
-        iterator operator--()    { iterator i = *this; mPtr--; return i; }
-        iterator operator--(int) { mPtr--; return *this; }
-        T& operator*()  { return *mPtr; }
-        T* operator->() { return mPtr; }
-        bool operator==(const iterator& rhs) const { return mPtr == rhs.mPtr; }
-        bool operator!=(const iterator& rhs) const { return mPtr != rhs.mPtr; }
+        iter(ptr_type ptr) : mPtr(ptr) { }
+        inline iter &operator++()    { mPtr++; return *this; }
+        inline iter  operator++(int) { iter i = *this; mPtr++; return i; }
+        inline iter &operator--()    { mPtr--; return *this; }
+        inline iter  operator--(int) { iter i = *this; mPtr--; return i; }
+        inline friend iter operator+(diff_type n, const iter &it) { return it.mPtr + n; }
+        inline iter  operator+(diff_type n) const { return mPtr + n; }
+        inline iter  operator-(diff_type n) const { return mPtr - n; }
+        inline diff_type operator-(const iter &other) const { return mPtr - other.mPtr; }
+        inline iter &operator+=(diff_type n) { mPtr += n; return *this; }
+        inline iter &operator-=(diff_type n) { mPtr -= n; return *this; }
+        inline ref_type operator*() const  { return *mPtr; }
+        inline ptr_type operator->() const { return mPtr; }
+        inline bool operator==(const iter &rhs) const { return mPtr == rhs.mPtr; }
+        inline bool operator!=(const iter &rhs) const { return mPtr != rhs.mPtr; }
+        inline bool operator< (const iter &rhs) const { return mPtr <  rhs.mPtr; }
+        inline bool operator> (const iter &rhs) const { return mPtr >  rhs.mPtr; }
+        inline bool operator<=(const iter &rhs) const { return mPtr <= rhs.mPtr; }
+        inline bool operator>=(const iter &rhs) const { return mPtr >= rhs.mPtr; }
+        inline ref_type operator[](size_t n) const { return mPtr[n]; }
     private:
-        T* mPtr;
+        ptr_type mPtr;
     };
+public:
+    using iterator       = iter<false /* is_const */>;
+    using const_iterator = iter<true  /* is_const */>;
+
     iterator begin() { return data(); }
     iterator end() { return data()+mSize; }
+    const_iterator begin() const { return data(); }
+    const_iterator end() const { return data()+mSize; }
 
 private:
     details::hidl_pointer<T> mBuffer;
diff --git a/test_main.cpp b/test_main.cpp
index 3ee8bc9..0a7ad90 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -110,7 +110,7 @@
     EXPECT_FALSE(hs1 == stringNE);
 }
 
-TEST_F(LibHidlTest, VecTest) {
+TEST_F(LibHidlTest, VecInitTest) {
     using android::hardware::hidl_vec;
     using std::vector;
     int32_t array[] = {5, 6, 7};
@@ -128,19 +128,65 @@
     hidl_vec<int32_t> v3 = {5, 6, 7}; // initializer_list
     EXPECT_EQ(v3.size(), 3ul);
     EXPECT_ARRAYEQ(v3, array, v3.size());
+}
+
+TEST_F(LibHidlTest, VecIterTest) {
+    int32_t array[] = {5, 6, 7};
+    android::hardware::hidl_vec<int32_t> hv1 = std::vector<int32_t>(array, array + 3);
 
     auto iter = hv1.begin();    // iterator begin()
-    EXPECT_EQ(*iter, 5);
-    iter++;                     // post increment
+    EXPECT_EQ(*iter++, 5);
     EXPECT_EQ(*iter, 6);
-    ++iter;                     // pre increment
+    EXPECT_EQ(*++iter, 7);
+    EXPECT_EQ(*iter--, 7);
+    EXPECT_EQ(*iter, 6);
+    EXPECT_EQ(*--iter, 5);
+
+    iter += 2;
     EXPECT_EQ(*iter, 7);
+    iter -= 2;
+    EXPECT_EQ(*iter, 5);
+
+    iter++;
+    EXPECT_EQ(*(iter + 1), 7);
+    EXPECT_EQ(*(1 + iter), 7);
+    EXPECT_EQ(*(iter - 1), 5);
+    EXPECT_EQ(*iter, 6);
+
+    auto five = iter - 1;
+    auto seven = iter + 1;
+    EXPECT_EQ(seven - five, 2);
+    EXPECT_EQ(five - seven, -2);
+
+    EXPECT_LT(five, seven);
+    EXPECT_LE(five, seven);
+    EXPECT_GT(seven, five);
+    EXPECT_GE(seven, five);
+
+    EXPECT_EQ(seven[0], 7);
+    EXPECT_EQ(five[1], 6);
+}
+
+TEST_F(LibHidlTest, VecIterForTest) {
+    using android::hardware::hidl_vec;
+    int32_t array[] = {5, 6, 7};
+    hidl_vec<int32_t> hv1 = std::vector<int32_t>(array, array + 3);
 
     int32_t sum = 0;            // range based for loop interoperability
     for (auto &&i: hv1) {
         sum += i;
     }
     EXPECT_EQ(sum, 5+6+7);
+
+    for (auto iter = hv1.begin(); iter < hv1.end(); ++iter) {
+        *iter += 10;
+    }
+    const hidl_vec<int32_t> &v4 = hv1;
+    sum = 0;
+    for (const auto &i : v4) {
+        sum += i;
+    }
+    EXPECT_EQ(sum, 15+16+17);
 }
 
 TEST_F(LibHidlTest, ArrayTest) {