Refactor static functions.

Common static functions for manipulating metadata moved
from patial_metadata_interface to metadata_common.h

Common static functions for comparing equivalence with
metadata for tests moved to test_common.h

BUG: 30140438
TEST: Unit tests pass

Change-Id: I4310b4ff05bdd68f7f92f533028989914d0f4c82
diff --git a/modules/camera/3_4/metadata/control.h b/modules/camera/3_4/metadata/control.h
index db19b1d..4b4adcf 100644
--- a/modules/camera/3_4/metadata/control.h
+++ b/modules/camera/3_4/metadata/control.h
@@ -22,6 +22,7 @@
 #include <system/camera_metadata.h>
 
 #include "../common.h"
+#include "metadata_common.h"
 #include "tagged_partial_metadata.h"
 
 namespace v4l2_camera_hal {
diff --git a/modules/camera/3_4/metadata/control_test.cpp b/modules/camera/3_4/metadata/control_test.cpp
index 6e45d02..ef4b6af 100644
--- a/modules/camera/3_4/metadata/control_test.cpp
+++ b/modules/camera/3_4/metadata/control_test.cpp
@@ -22,6 +22,9 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include "metadata_common.h"
+#include "test_common.h"
+
 using testing::AtMost;
 using testing::Return;
 using testing::ReturnRef;
@@ -48,37 +51,6 @@
   virtual void SetUp() {
     control_.reset(new MockControl<uint8_t>(control_tag_));
   }
-  // Check that metadata of a given tag matches expectations.
-  virtual void ExpectMetadataEq(const android::CameraMetadata& metadata,
-                                int32_t tag, const uint8_t* expected,
-                                size_t size) {
-    camera_metadata_ro_entry_t entry = metadata.find(tag);
-    ASSERT_EQ(entry.count, size);
-    for (size_t i = 0; i < size; ++i) {
-      EXPECT_EQ(entry.data.u8[i], expected[i]);
-    }
-  }
-  virtual void ExpectMetadataEq(const android::CameraMetadata& metadata,
-                                int32_t tag, const int32_t* expected,
-                                size_t size) {
-    camera_metadata_ro_entry_t entry = metadata.find(tag);
-    ASSERT_EQ(entry.count, size);
-    for (size_t i = 0; i < size; ++i) {
-      EXPECT_EQ(entry.data.i32[i], expected[i]);
-    }
-  }
-  // Single item.
-  template <typename T>
-  void ExpectMetadataEq(const android::CameraMetadata& metadata, int32_t tag,
-                        T expected) {
-    ExpectMetadataEq(metadata, tag, &expected, 1);
-  }
-  // Vector of items.
-  template <typename T>
-  void ExpectMetadataEq(const android::CameraMetadata& metadata, int32_t tag,
-                        const std::vector<T>& expected) {
-    ExpectMetadataEq(metadata, tag, expected.data(), expected.size());
-  }
 
   std::unique_ptr<MockControl<uint8_t>> control_;
 
@@ -128,7 +100,7 @@
 TEST_F(ControlTest, SupportsRequest) {
   android::CameraMetadata metadata;
   uint8_t test_option = 123;
-  ASSERT_EQ(metadata.update(control_tag_, &test_option, 1), android::OK);
+  ASSERT_EQ(UpdateMetadata(&metadata, control_tag_, test_option), 0);
 
   EXPECT_CALL(*control_, IsSupported(test_option)).WillOnce(Return(true));
   EXPECT_EQ(control_->SupportsRequestValues(metadata), true);
@@ -137,9 +109,7 @@
 TEST_F(ControlTest, ArraySupportsRequest) {
   android::CameraMetadata metadata;
   std::array<uint8_t, 2> test_option = {{12, 34}};
-  ASSERT_EQ(
-      metadata.update(control_tag_, test_option.data(), test_option.size()),
-      android::OK);
+  ASSERT_EQ(UpdateMetadata(&metadata, control_tag_, test_option), 0);
 
   MockControl<std::array<uint8_t, 2>> test_control(control_tag_);
   EXPECT_CALL(test_control, IsSupported(test_option)).WillOnce(Return(true));
@@ -149,7 +119,7 @@
 TEST_F(ControlTest, SupportsRequestFail) {
   android::CameraMetadata metadata;
   uint8_t test_option = 123;
-  ASSERT_EQ(metadata.update(control_tag_, &test_option, 1), android::OK);
+  ASSERT_EQ(UpdateMetadata(&metadata, control_tag_, test_option), 0);
 
   EXPECT_CALL(*control_, IsSupported(test_option)).WillOnce(Return(false));
   EXPECT_EQ(control_->SupportsRequestValues(metadata), false);
@@ -159,8 +129,7 @@
   // Start with a request for multiple values.
   android::CameraMetadata metadata;
   std::vector<uint8_t> test_data = {1, 2, 3};
-  ASSERT_EQ(metadata.update(control_tag_, test_data.data(), test_data.size()),
-            android::OK);
+  ASSERT_EQ(UpdateMetadata(&metadata, control_tag_, test_data), 0);
   EXPECT_EQ(control_->SupportsRequestValues(metadata), false);
 }
 
@@ -168,7 +137,7 @@
   // Start with a request for a single (non-array) value.
   android::CameraMetadata metadata;
   uint8_t test_data = 1;
-  ASSERT_EQ(metadata.update(control_tag_, &test_data, 1), android::OK);
+  ASSERT_EQ(UpdateMetadata(&metadata, control_tag_, test_data), 0);
 
   MockControl<std::array<uint8_t, 2>> test_control(control_tag_);
   EXPECT_EQ(test_control.SupportsRequestValues(metadata), false);
@@ -182,7 +151,7 @@
 TEST_F(ControlTest, SetRequest) {
   android::CameraMetadata metadata(1);
   uint8_t test_option = 123;
-  ASSERT_EQ(metadata.update(control_tag_, &test_option, 1), android::OK);
+  ASSERT_EQ(UpdateMetadata(&metadata, control_tag_, test_option), 0);
 
   EXPECT_CALL(*control_, SetValue(test_option)).WillOnce(Return(0));
   // Make the request.
@@ -192,9 +161,7 @@
 TEST_F(ControlTest, ArraySetRequest) {
   android::CameraMetadata metadata;
   std::array<uint8_t, 2> test_option = {{12, 34}};
-  ASSERT_EQ(
-      metadata.update(control_tag_, test_option.data(), test_option.size()),
-      android::OK);
+  ASSERT_EQ(UpdateMetadata(&metadata, control_tag_, test_option), 0);
 
   MockControl<std::array<uint8_t, 2>> test_control(control_tag_);
   EXPECT_CALL(test_control, SetValue(test_option)).WillOnce(Return(0));
@@ -204,7 +171,7 @@
 TEST_F(ControlTest, SetRequestFail) {
   android::CameraMetadata metadata(1);
   uint8_t test_option = 123;
-  ASSERT_EQ(metadata.update(control_tag_, &test_option, 1), android::OK);
+  ASSERT_EQ(UpdateMetadata(&metadata, control_tag_, test_option), 0);
 
   int err = -99;
   EXPECT_CALL(*control_, SetValue(test_option)).WillOnce(Return(err));
@@ -215,8 +182,7 @@
   // Start with a request for multiple values.
   android::CameraMetadata metadata;
   std::vector<uint8_t> test_data = {1, 2, 3};
-  ASSERT_EQ(metadata.update(control_tag_, test_data.data(), test_data.size()),
-            android::OK);
+  ASSERT_EQ(UpdateMetadata(&metadata, control_tag_, test_data), 0);
   EXPECT_EQ(control_->SetRequestValues(metadata), -EINVAL);
 }
 
@@ -224,7 +190,7 @@
   // Start with a request for a single (non-array) value.
   android::CameraMetadata metadata;
   uint8_t test_data = 1;
-  ASSERT_EQ(metadata.update(control_tag_, &test_data, 1), android::OK);
+  ASSERT_EQ(UpdateMetadata(&metadata, control_tag_, test_data), 0);
 
   MockControl<std::array<uint8_t, 2>> test_control(control_tag_);
   EXPECT_EQ(test_control.SetRequestValues(metadata), -EINVAL);
diff --git a/modules/camera/3_4/metadata/fixed_property_test.cpp b/modules/camera/3_4/metadata/fixed_property_test.cpp
index cf7cf10..07a1bce 100644
--- a/modules/camera/3_4/metadata/fixed_property_test.cpp
+++ b/modules/camera/3_4/metadata/fixed_property_test.cpp
@@ -24,6 +24,8 @@
 #include <gtest/gtest.h>
 
 #include "array_vector.h"
+#include "metadata_common.h"
+#include "test_common.h"
 
 using testing::AtMost;
 using testing::Return;
@@ -67,9 +69,7 @@
   // Should only have added 1 entry.
   EXPECT_EQ(metadata.entryCount(), 1);
   // Should have added the right entry.
-  camera_metadata_entry_t entry = metadata.find(int_tag_);
-  ASSERT_EQ(entry.count, 1);
-  EXPECT_EQ(*entry.data.i32, data);
+  ExpectMetadataEq(metadata, int_tag_, data);
 }
 
 TEST_F(FixedPropertyTest, PopulateStaticVector) {
@@ -85,11 +85,7 @@
   // Should only have added 1 entry.
   EXPECT_EQ(metadata.entryCount(), 1);
   // Should have added the right entry.
-  camera_metadata_entry_t entry = metadata.find(float_tag_);
-  ASSERT_EQ(entry.count, data.size());
-  for (size_t i = 0; i < data.size(); ++i) {
-    EXPECT_EQ(entry.data.f[i], data[i]);
-  }
+  ExpectMetadataEq(metadata, float_tag_, data);
 }
 
 TEST_F(FixedPropertyTest, PopulateStaticArray) {
@@ -105,11 +101,7 @@
   // Should only have added 1 entry.
   EXPECT_EQ(metadata.entryCount(), 1);
   // Should have added the right entry.
-  camera_metadata_entry_t entry = metadata.find(float_tag_);
-  ASSERT_EQ(entry.count, data.size());
-  for (size_t i = 0; i < data.size(); ++i) {
-    EXPECT_EQ(entry.data.f[i], data[i]);
-  }
+  ExpectMetadataEq(metadata, float_tag_, data);
 }
 
 TEST_F(FixedPropertyTest, PopulateStaticArrayVector) {
@@ -127,11 +119,7 @@
   // Should only have added 1 entry.
   EXPECT_EQ(metadata.entryCount(), 1);
   // Should have added the right entry.
-  camera_metadata_entry_t entry = metadata.find(byte_tag_);
-  ASSERT_EQ(entry.count, data.total_num_elements());
-  for (size_t i = 0; i < data.total_num_elements(); ++i) {
-    EXPECT_EQ(entry.data.u8[i], data.data()[i]);
-  }
+  ExpectMetadataEq(metadata, byte_tag_, data);
 }
 
 TEST_F(FixedPropertyTest, PopulateDynamic) {
diff --git a/modules/camera/3_4/metadata/metadata_common.h b/modules/camera/3_4/metadata/metadata_common.h
new file mode 100644
index 0000000..55f8a6f
--- /dev/null
+++ b/modules/camera/3_4/metadata/metadata_common.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_
+#define V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_
+
+#include <array>
+#include <vector>
+
+#include <camera/CameraMetadata.h>
+
+#include "array_vector.h"
+
+namespace v4l2_camera_hal {
+
+// Templated helper functions effectively extending android::CameraMetadata.
+// Will cause a compile-time errors if CameraMetadata doesn't support
+// using the templated type. Templates are provided to extend this support
+// to std::arrays, std::vectors, and ArrayVectors of supported types as
+// appropriate.
+
+// UpdateMetadata(metadata, tag, data):
+//
+// Updates the entry for |tag| in |metadata| (functionally similar to
+// android::CameraMetadata::update).
+//
+// Args:
+//   metadata: the android::CameraMetadata to update.
+//   tag: the tag within |metadata| to update.
+//   data: A reference to the data to update |tag| with.
+//
+// Returns:
+//   0: Success.
+//   -ENODEV: The type of |data| does not match the expected type for |tag|,
+//     or another error occured. Note: no errors are given for updating a
+//     metadata entry with an incorrect amount of data (e.g. filling a tag
+//     that expects to have only one value with multiple values), as this
+//     information is not encoded in the type associated with the tag by
+//     get_camera_metadata_tag_type (from <system/camera_metadata.h>).
+
+// Generic (pointer & size).
+template <typename T>
+static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
+                          const T* data, size_t count) {
+  int res = metadata->update(tag, data, count);
+  if (res) {
+    HAL_LOGE("Failed to update metadata tag %d", tag);
+    return -ENODEV;
+  }
+  return 0;
+}
+
+// Generic (single item reference).
+template <typename T>
+static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
+                          const T& val) {
+  return UpdateMetadata(metadata, tag, &val, 1);
+}
+
+// Specialization for vectors.
+template <typename T>
+static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
+                          const std::vector<T>& val) {
+  return UpdateMetadata(metadata, tag, val.data(), val.size());
+}
+
+// Specialization for arrays.
+template <typename T, size_t N>
+static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
+                          const std::array<T, N>& val) {
+  return UpdateMetadata(metadata, tag, val.data(), N);
+}
+
+// Specialization for ArrayVectors.
+template <typename T, size_t N>
+static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
+                          const ArrayVector<T, N>& val) {
+  return UpdateMetadata(metadata, tag, val.data(), val.total_num_elements());
+}
+
+// Specialization for vectors of arrays.
+template <typename T, size_t N>
+static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
+                          const std::vector<std::array<T, N>>& val) {
+  // Convert to array vector so we know all the elements are contiguous.
+  ArrayVector<T, N> array_vector;
+  for (const auto& array : val) {
+    array_vector.push_back(array);
+  }
+  return UpdateMetadata(metadata, tag, array_vector);
+}
+
+// GetDataPointer(entry, val)
+//
+// A helper for other methods in this file.
+// Gets the data pointer of a given metadata entry into |*val|.
+
+static void GetDataPointer(camera_metadata_ro_entry_t& entry,
+                           const uint8_t** val) {
+  *val = entry.data.u8;
+}
+
+static void GetDataPointer(camera_metadata_ro_entry_t& entry,
+                           const int32_t** val) {
+  *val = entry.data.i32;
+}
+
+static void GetDataPointer(camera_metadata_ro_entry_t& entry,
+                           const float** val) {
+  *val = entry.data.f;
+}
+
+static void GetDataPointer(camera_metadata_ro_entry_t& entry,
+                           const int64_t** val) {
+  *val = entry.data.i64;
+}
+
+static void GetDataPointer(camera_metadata_ro_entry_t& entry,
+                           const double** val) {
+  *val = entry.data.d;
+}
+
+static void GetDataPointer(camera_metadata_ro_entry_t& entry,
+                           const camera_metadata_rational_t** val) {
+  *val = entry.data.r;
+}
+
+// SingleTagValue(metadata, tag, val)
+//
+// Get the value of the |tag| entry in |metadata|.
+// |tag| is expected to refer to an entry with a single item
+// of the templated type (a "single item" is exactly N values
+// if the templated type is an array of size N). An error will be
+// returned if it the wrong number of items are present.
+//
+// Returns:
+//   -ENOENT: The tag couldn't be found or was empty.
+//   -EINVAL: The tag contained more than one item.
+//   -ENODEV: The tag claims to be non-empty, but the data pointer is null.
+//   0: Success. |*val| will contain the value for |tag|.
+
+// Singleton.
+template <typename T>
+static int SingleTagValue(const android::CameraMetadata& metadata, int32_t tag,
+                          T* val) {
+  camera_metadata_ro_entry_t entry = metadata.find(tag);
+  if (entry.count == 0) {
+    HAL_LOGE("Metadata tag %d is empty.", tag);
+    return -ENOENT;
+  } else if (entry.count != 1) {
+    HAL_LOGE(
+        "Error: expected metadata tag %d to contain exactly 1 value "
+        "(had %d).",
+        tag, entry.count);
+    return -EINVAL;
+  }
+  const T* data = nullptr;
+  GetDataPointer(entry, &data);
+  if (data == nullptr) {
+    HAL_LOGE("Metadata tag %d is empty.", tag);
+    return -ENODEV;
+  }
+  *val = *data;
+  return 0;
+}
+
+// Specialization for std::array.
+template <typename T, size_t N>
+static int SingleTagValue(const android::CameraMetadata& metadata, int32_t tag,
+                          std::array<T, N>* val) {
+  camera_metadata_ro_entry_t entry = metadata.find(tag);
+  if (entry.count == 0) {
+    HAL_LOGE("Metadata tag %d is empty.", tag);
+    return -ENOENT;
+  } else if (entry.count != N) {
+    HAL_LOGE(
+        "Error: expected metadata tag %d to contain a single array of "
+        "exactly %d values (had %d).",
+        tag, N, entry.count);
+    return -EINVAL;
+  }
+  const T* data = nullptr;
+  GetDataPointer(entry, &data);
+  if (data == nullptr) {
+    HAL_LOGE("Metadata tag %d is empty.", tag);
+    return -ENODEV;
+  }
+  // Fill in the array.
+  for (size_t i = 0; i < N; ++i) {
+    (*val)[i] = data[i];
+  }
+  return 0;
+}
+
+}  // namespace v4l2_camera_hal
+
+#endif  // V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_
diff --git a/modules/camera/3_4/metadata/optioned_control.h b/modules/camera/3_4/metadata/optioned_control.h
index bf8ec44..10052cc 100644
--- a/modules/camera/3_4/metadata/optioned_control.h
+++ b/modules/camera/3_4/metadata/optioned_control.h
@@ -24,6 +24,7 @@
 
 #include "../common.h"
 #include "control.h"
+#include "metadata_common.h"
 
 namespace v4l2_camera_hal {
 
@@ -68,7 +69,7 @@
   HAL_LOG_ENTER();
 
   // Populate the available options.
-  return Control<T>::UpdateMetadata(metadata, OptionsTag(), options_);
+  return UpdateMetadata(metadata, OptionsTag(), options_);
 }
 
 template <typename T>
diff --git a/modules/camera/3_4/metadata/optioned_control_test.cpp b/modules/camera/3_4/metadata/optioned_control_test.cpp
index 8fcc1cb..1cfccbf 100644
--- a/modules/camera/3_4/metadata/optioned_control_test.cpp
+++ b/modules/camera/3_4/metadata/optioned_control_test.cpp
@@ -20,6 +20,8 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include "test_common.h"
+
 using testing::AtMost;
 using testing::Return;
 using testing::ReturnRef;
@@ -50,37 +52,6 @@
     control_.reset(
         new MockOptionedControl<uint8_t>(control_tag_, options_tag_, options_));
   }
-  // Check that metadata of a given tag matches expectations.
-  virtual void ExpectMetadataEq(const android::CameraMetadata& metadata,
-                                int32_t tag, const uint8_t* expected,
-                                size_t size) {
-    camera_metadata_ro_entry_t entry = metadata.find(tag);
-    ASSERT_EQ(entry.count, size);
-    for (size_t i = 0; i < size; ++i) {
-      EXPECT_EQ(entry.data.u8[i], expected[i]);
-    }
-  }
-  virtual void ExpectMetadataEq(const android::CameraMetadata& metadata,
-                                int32_t tag, const int32_t* expected,
-                                size_t size) {
-    camera_metadata_ro_entry_t entry = metadata.find(tag);
-    ASSERT_EQ(entry.count, size);
-    for (size_t i = 0; i < size; ++i) {
-      EXPECT_EQ(entry.data.i32[i], expected[i]);
-    }
-  }
-  // Single item.
-  template <typename T>
-  void ExpectMetadataEq(const android::CameraMetadata& metadata, int32_t tag,
-                        T expected) {
-    ExpectMetadataEq(metadata, tag, &expected, 1);
-  }
-  // Vector of items.
-  template <typename T>
-  void ExpectMetadataEq(const android::CameraMetadata& metadata, int32_t tag,
-                        const std::vector<T>& expected) {
-    ExpectMetadataEq(metadata, tag, expected.data(), expected.size());
-  }
 
   std::unique_ptr<OptionedControl<uint8_t>> control_;
 
diff --git a/modules/camera/3_4/metadata/partial_metadata_interface.h b/modules/camera/3_4/metadata/partial_metadata_interface.h
index 09bfebc..d1a434f 100644
--- a/modules/camera/3_4/metadata/partial_metadata_interface.h
+++ b/modules/camera/3_4/metadata/partial_metadata_interface.h
@@ -56,159 +56,6 @@
   // tags indicate no change. If |metadata| is empty no controls should
   // be changed.
   virtual int SetRequestValues(const android::CameraMetadata& metadata) = 0;
-
- protected:
-  // Templated helper function to update a single entry of some metadata.
-  // Will cause a compile-time error if CameraMetadata doesn't support
-  // updating the given type. An error will be returned if the data type
-  // does not match the expected type for the tag. No errors are given
-  // for updating a metadata entry with the incorrect amount of data,
-  // as this information is not encoded in the type associated with the tag
-  // by get_camera_metadata_tag_type (from <system/camera_metadata.h>).
-  // Generic (pointer & size).
-  template <typename T>
-  static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
-                            const T* data, size_t count) {
-    int res = metadata->update(tag, data, count);
-    if (res) {
-      HAL_LOGE("Failed to update metadata tag %d", tag);
-      return -ENODEV;
-    }
-    return 0;
-  }
-
-  // Generic (single item reference).
-  template <typename T>
-  static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
-                            const T& val) {
-    return UpdateMetadata(metadata, tag, &val, 1);
-  }
-
-  // Specialization for vectors.
-  template <typename T>
-  static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
-                            const std::vector<T>& val) {
-    return UpdateMetadata(metadata, tag, val.data(), val.size());
-  }
-
-  // Specialization for arrays.
-  template <typename T, size_t N>
-  static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
-                            const std::array<T, N>& val) {
-    return UpdateMetadata(metadata, tag, val.data(), N);
-  }
-
-  // Specialization for ArrayVectors.
-  template <typename T, size_t N>
-  static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
-                            const ArrayVector<T, N>& val) {
-    return UpdateMetadata(metadata, tag, val.data(), val.total_num_elements());
-  }
-
-  // Specialization for vectors of arrays.
-  template <typename T, size_t N>
-  static int UpdateMetadata(android::CameraMetadata* metadata, int32_t tag,
-                            const std::vector<std::array<T, N>>& val) {
-    // Convert to array vector so we know all the elements are contiguous.
-    ArrayVector<T, N> array_vector;
-    for (const auto& array : val) {
-      array_vector.push_back(array);
-    }
-    return UpdateMetadata(metadata, tag, array_vector);
-  }
-
-  // Get the data pointer of a given metadata entry. Enforces that |val| must
-  // be a type supported by camera_metadata.
-
-  static void GetDataPointer(camera_metadata_ro_entry_t& entry,
-                             const uint8_t** val) {
-    *val = entry.data.u8;
-  }
-
-  static void GetDataPointer(camera_metadata_ro_entry_t& entry,
-                             const int32_t** val) {
-    *val = entry.data.i32;
-  }
-
-  static void GetDataPointer(camera_metadata_ro_entry_t& entry,
-                             const float** val) {
-    *val = entry.data.f;
-  }
-
-  static void GetDataPointer(camera_metadata_ro_entry_t& entry,
-                             const int64_t** val) {
-    *val = entry.data.i64;
-  }
-
-  static void GetDataPointer(camera_metadata_ro_entry_t& entry,
-                             const double** val) {
-    *val = entry.data.d;
-  }
-
-  static void GetDataPointer(camera_metadata_ro_entry_t& entry,
-                             const camera_metadata_rational_t** val) {
-    *val = entry.data.r;
-  }
-
-  // Get a tag value that is expected to be a single item.
-  // Returns:
-  //   -ENOENT: The tag couldn't be found or was empty.
-  //   -EINVAL: The tag contained more than one item.
-  //   -ENODEV: The tag claims to be non-empty, but the data pointer is null.
-  //   0: Success. |*val| will contain the value for |tag|.
-
-  // Generic (one of the types supported by TagValue above).
-  template <typename T>
-  static int SingleTagValue(const android::CameraMetadata& metadata,
-                            int32_t tag, T* val) {
-    camera_metadata_ro_entry_t entry = metadata.find(tag);
-    if (entry.count == 0) {
-      HAL_LOGE("Metadata tag %d is empty.", tag);
-      return -ENOENT;
-    } else if (entry.count != 1) {
-      HAL_LOGE(
-          "Error: expected metadata tag %d to contain exactly 1 value "
-          "(had %d).",
-          tag, entry.count);
-      return -EINVAL;
-    }
-    const T* data = nullptr;
-    GetDataPointer(entry, &data);
-    if (data == nullptr) {
-      HAL_LOGE("Metadata tag %d is empty.", tag);
-      return -ENODEV;
-    }
-    *val = *data;
-    return 0;
-  }
-
-  // Specialization for std::array (of the types supported by TagValue above).
-  template <typename T, size_t N>
-  static int SingleTagValue(const android::CameraMetadata& metadata,
-                            int32_t tag, std::array<T, N>* val) {
-    camera_metadata_ro_entry_t entry = metadata.find(tag);
-    if (entry.count == 0) {
-      HAL_LOGE("Metadata tag %d is empty.", tag);
-      return -ENOENT;
-    } else if (entry.count != N) {
-      HAL_LOGE(
-          "Error: expected metadata tag %d to contain a single array of "
-          "exactly %d values (had %d).",
-          tag, N, entry.count);
-      return -EINVAL;
-    }
-    const T* data = nullptr;
-    GetDataPointer(entry, &data);
-    if (data == nullptr) {
-      HAL_LOGE("Metadata tag %d is empty.", tag);
-      return -ENODEV;
-    }
-    // Fill in the array.
-    for (size_t i = 0; i < N; ++i) {
-      (*val)[i] = data[i];
-    }
-    return 0;
-  }
 };
 
 }  // namespace v4l2_camera_hal
diff --git a/modules/camera/3_4/metadata/property.h b/modules/camera/3_4/metadata/property.h
index 78cd2fa..a3ed6bf 100644
--- a/modules/camera/3_4/metadata/property.h
+++ b/modules/camera/3_4/metadata/property.h
@@ -18,6 +18,7 @@
 #define V4L2_CAMERA_HAL_METADATA_PROPERTY_H_
 
 #include "../common.h"
+#include "metadata_common.h"
 #include "tagged_partial_metadata.h"
 
 namespace v4l2_camera_hal {
diff --git a/modules/camera/3_4/metadata/test_common.h b/modules/camera/3_4/metadata/test_common.h
new file mode 100644
index 0000000..6cbd611
--- /dev/null
+++ b/modules/camera/3_4/metadata/test_common.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef V4L2_CAMERA_HAL_METADATA_TEST_COMMON_H_
+#define V4L2_CAMERA_HAL_METADATA_TEST_COMMON_H_
+
+#include <array>
+#include <vector>
+
+#include <camera/CameraMetadata.h>
+#include <gtest/gtest.h>
+
+#include "array_vector.h"
+#include "metadata_common.h"
+
+namespace v4l2_camera_hal {
+
+// Check that metadata of a given tag matches expectations.
+// Generic.
+template <typename T>
+static void ExpectMetadataEq(const android::CameraMetadata& metadata,
+                             int32_t tag, const T* expected, size_t size) {
+  camera_metadata_ro_entry_t entry = metadata.find(tag);
+  ASSERT_EQ(entry.count, size);
+  const T* data = nullptr;
+  GetDataPointer(entry, &data);
+  ASSERT_NE(data, nullptr);
+  for (size_t i = 0; i < size; ++i) {
+    EXPECT_EQ(data[i], expected[i]);
+  }
+}
+
+// Single item.
+template <typename T>
+static void ExpectMetadataEq(const android::CameraMetadata& metadata,
+                             int32_t tag, T expected) {
+  ExpectMetadataEq(metadata, tag, &expected, 1);
+}
+
+// Vector of items.
+template <typename T>
+static void ExpectMetadataEq(const android::CameraMetadata& metadata,
+                             int32_t tag, const std::vector<T>& expected) {
+  ExpectMetadataEq(metadata, tag, expected.data(), expected.size());
+}
+
+// Array of items.
+template <typename T, size_t N>
+static void ExpectMetadataEq(const android::CameraMetadata& metadata,
+                             int32_t tag, const std::array<T, N>& expected) {
+  ExpectMetadataEq(metadata, tag, expected.data(), N);
+}
+
+// ArrayVector.
+template <typename T, size_t N>
+static void ExpectMetadataEq(const android::CameraMetadata& metadata,
+                             int32_t tag, const ArrayVector<T, N>& expected) {
+  ExpectMetadataEq(metadata, tag, expected.data(),
+                   expected.total_num_elements());
+}
+
+// Vector of arrays.
+template <typename T, size_t N>
+static int ExpectMetadataEq(const android::CameraMetadata& metadata,
+                            int32_t tag,
+                            const std::vector<std::array<T, N>>& expected) {
+  // Convert to array vector so we know all the elements are contiguous.
+  ArrayVector<T, N> array_vector;
+  for (const auto& array : expected) {
+    array_vector.push_back(array);
+  }
+  ExpectMetadataEq(metadata, tag, array_vector);
+}
+
+}  // namespace v4l2_camera_hal
+
+#endif  // V4L2_CAMERA_HAL_METADATA_TEST_COMMON_H_