hidl_vec: move elements on resize am: dfbedb8ffb am: 06ef1e772a am: b04213fd4c
am: 66107c84cb

Change-Id: If8662a1f18f4ce6648d8fd7427eb3582d8c69460
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index e7891bb..ea50470 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -517,7 +517,7 @@
         T* newBuffer = new T[size]();
 
         for (size_t i = 0; i < std::min(static_cast<uint32_t>(size), mSize); ++i) {
-            newBuffer[i] = mBuffer[i];
+            newBuffer[i] = std::move(mBuffer[i]);
         }
 
         if (mOwnsBuffer) {
@@ -739,6 +739,8 @@
     using std_array_type = typename details::std_array<T, SIZE1, SIZES...>::type;
 
     hidl_array() = default;
+    hidl_array(const hidl_array&) noexcept = default;
+    hidl_array(hidl_array&&) noexcept = default;
 
     // Copies the data from source, using T::operator=(const T &).
     hidl_array(const T *source) {
@@ -753,6 +755,9 @@
         modifier = array;
     }
 
+    hidl_array& operator=(const hidl_array&) noexcept = default;
+    hidl_array& operator=(hidl_array&&) noexcept = default;
+
     T *data() { return mBuffer; }
     const T *data() const { return mBuffer; }
 
@@ -805,6 +810,8 @@
     using std_array_type = typename details::std_array<T, SIZE1>::type;
 
     hidl_array() = default;
+    hidl_array(const hidl_array&) noexcept = default;
+    hidl_array(hidl_array&&) noexcept = default;
 
     // Copies the data from source, using T::operator=(const T &).
     hidl_array(const T *source) {
@@ -816,6 +823,9 @@
     // Copies the data from the given std::array, using T::operator=(const T &).
     hidl_array(const std_array_type &array) : hidl_array(array.data()) {}
 
+    hidl_array& operator=(const hidl_array&) noexcept = default;
+    hidl_array& operator=(hidl_array&&) noexcept = default;
+
     T *data() { return mBuffer; }
     const T *data() const { return mBuffer; }
 
diff --git a/test_main.cpp b/test_main.cpp
index 9db076c..5defe8c 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -324,6 +324,37 @@
     EXPECT_EQ(sum, 1 + 2 + 3);
 }
 
+struct FailsIfCopied {
+    FailsIfCopied() {}
+
+    // add failure if copied since in general this can be expensive
+    FailsIfCopied(const FailsIfCopied& o) { *this = o; }
+    FailsIfCopied& operator=(const FailsIfCopied&) {
+        ADD_FAILURE() << "FailsIfCopied copied";
+        return *this;
+    }
+
+    // fine to move this type since in general this is cheaper
+    FailsIfCopied(FailsIfCopied&& o) = default;
+    FailsIfCopied& operator=(FailsIfCopied&&) = default;
+};
+
+TEST_F(LibHidlTest, VecResizeNoCopy) {
+    using android::hardware::hidl_vec;
+
+    hidl_vec<FailsIfCopied> noCopies;
+    noCopies.resize(3);  // instantiates three elements
+
+    FailsIfCopied* oldPointer = noCopies.data();
+
+    noCopies.resize(6);  // should move three elements, not copy
+
+    // oldPointer should be invalidated at this point.
+    // hidl_vec doesn't currently try to realloc but if it ever switches
+    // to an implementation that does, this test wouldn't do anything.
+    EXPECT_NE(oldPointer, noCopies.data());
+}
+
 TEST_F(LibHidlTest, ArrayTest) {
     using android::hardware::hidl_array;
     int32_t array[] = {5, 6, 7};