Merge "Camera: synchronize access to mMemoryMap"
diff --git a/configstore/utils/Android.bp b/configstore/utils/Android.bp
index a4cad66..93e52f1 100644
--- a/configstore/utils/Android.bp
+++ b/configstore/utils/Android.bp
@@ -17,6 +17,9 @@
 cc_library_shared {
     name: "android.hardware.configstore-utils",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     defaults: ["hidl_defaults"],
 
     srcs: [ "ConfigStoreUtils.cpp" ],
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index a49307d..fb8d22e 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -17,7 +17,14 @@
 cc_test {
     name: "VtsHalSensorsV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
-    srcs: ["VtsHalSensorsV1_0TargetTest.cpp"],
-    static_libs: ["android.hardware.sensors@1.0"],
+    srcs: [
+        "GrallocWrapper.cpp",
+        "VtsHalSensorsV1_0TargetTest.cpp"
+    ],
+    static_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.sensors@1.0"
+    ]
 }
 
diff --git a/sensors/1.0/vts/functional/GrallocWrapper.cpp b/sensors/1.0/vts/functional/GrallocWrapper.cpp
new file mode 100644
index 0000000..e422d62
--- /dev/null
+++ b/sensors/1.0/vts/functional/GrallocWrapper.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#define LOG_TAG "GrallocWrapper"
+
+#include "GrallocWrapper.h"
+
+#include <utils/Log.h>
+
+namespace android {
+
+GrallocWrapper::GrallocWrapper() { init(); }
+
+void GrallocWrapper::init() {
+  mAllocator = allocator2::IAllocator::getService();
+  if (mAllocator == nullptr) {
+    ALOGE("Failed to get allocator service");
+  }
+
+  mMapper = mapper2::IMapper::getService();
+  if (mMapper == nullptr) {
+    ALOGE("Failed to get mapper service");
+  }
+  if (mMapper->isRemote()) {
+    ALOGE("Mapper is not in passthrough mode");
+  }
+}
+
+GrallocWrapper::~GrallocWrapper() {
+  for (auto bufferHandle : mClonedBuffers) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    native_handle_close(buffer);
+    native_handle_delete(buffer);
+  }
+  mClonedBuffers.clear();
+
+  for (auto bufferHandle : mImportedBuffers) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
+      ALOGE("Failed to free buffer %p", buffer);
+    }
+  }
+  mImportedBuffers.clear();
+}
+
+sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
+  return mAllocator;
+}
+
+std::string GrallocWrapper::dumpDebugInfo() {
+  std::string debugInfo;
+  mAllocator->dumpDebugInfo(
+      [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+
+  return debugInfo;
+}
+
+const native_handle_t* GrallocWrapper::cloneBuffer(
+    const hardware::hidl_handle& rawHandle) {
+  const native_handle_t* bufferHandle =
+      native_handle_clone(rawHandle.getNativeHandle());
+
+  if (bufferHandle) {
+    mClonedBuffers.insert(bufferHandle);
+  }
+  return bufferHandle;
+}
+
+std::vector<const native_handle_t*> GrallocWrapper::allocate(
+    const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import,
+    uint32_t* outStride) {
+  std::vector<const native_handle_t*> bufferHandles;
+  bufferHandles.reserve(count);
+  mAllocator->allocate(
+      descriptor, count,
+      [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
+        if (mapper2::Error::NONE != tmpError) {
+          ALOGE("Failed to allocate buffers");
+        }
+        if (count != tmpBuffers.size()) {
+          ALOGE("Invalid buffer array");
+        }
+
+        for (uint32_t i = 0; i < count; i++) {
+          if (import) {
+            bufferHandles.push_back(importBuffer(tmpBuffers[i]));
+          } else {
+            bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
+          }
+        }
+
+        if (outStride) {
+          *outStride = tmpStride;
+        }
+      });
+
+  return bufferHandles;
+}
+
+const native_handle_t* GrallocWrapper::allocate(
+    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
+    uint32_t* outStride) {
+  mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+  ALOGE("QQ");
+  auto buffers = allocate(descriptor, 1, import, outStride);
+  return buffers[0];
+}
+
+sp<mapper2::IMapper> GrallocWrapper::getMapper() const { return mMapper; }
+
+mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
+    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
+  mapper2::BufferDescriptor descriptor;
+  mMapper->createDescriptor(
+      descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+        if (tmpError != mapper2::Error::NONE) {
+          ALOGE("Failed to create descriptor");
+        }
+        descriptor = tmpDescriptor;
+      });
+
+  return descriptor;
+}
+
+const native_handle_t* GrallocWrapper::importBuffer(
+    const hardware::hidl_handle& rawHandle) {
+  const native_handle_t* bufferHandle = nullptr;
+  mMapper->importBuffer(
+      rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
+        if (tmpError != mapper2::Error::NONE) {
+          ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
+        }
+        bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
+      });
+
+  if (bufferHandle) {
+    mImportedBuffers.insert(bufferHandle);
+  }
+
+  return bufferHandle;
+}
+
+void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
+  auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+  if (mImportedBuffers.erase(bufferHandle)) {
+    mapper2::Error error = mMapper->freeBuffer(buffer);
+    if (error != mapper2::Error::NONE) {
+      ALOGE("Failed to free %p", buffer);
+    }
+  } else {
+    mClonedBuffers.erase(bufferHandle);
+    native_handle_close(buffer);
+    native_handle_delete(buffer);
+  }
+}
+
+void* GrallocWrapper::lock(const native_handle_t* bufferHandle,
+                           uint64_t cpuUsage,
+                           const mapper2::IMapper::Rect& accessRegion,
+                           int acquireFence) {
+  auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+  NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+  hardware::hidl_handle acquireFenceHandle;
+  if (acquireFence >= 0) {
+    auto h = native_handle_init(acquireFenceStorage, 1, 0);
+    h->data[0] = acquireFence;
+    acquireFenceHandle = h;
+  }
+
+  void* data = nullptr;
+  mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                [&](const auto& tmpError, const auto& tmpData) {
+                  if (tmpError != mapper2::Error::NONE) {
+                    ALOGE("Failed to lock buffer %p", buffer);
+                  }
+                  data = tmpData;
+                });
+
+  if (acquireFence >= 0) {
+    close(acquireFence);
+  }
+
+  return data;
+}
+
+int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
+  auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+  int releaseFence = -1;
+  mMapper->unlock(buffer, [&](const auto& tmpError,
+                              const auto& tmpReleaseFence) {
+    if (tmpError != mapper2::Error::NONE) {
+      ALOGE("Failed to unlock buffer %p", buffer);
+    }
+
+    auto fenceHandle = tmpReleaseFence.getNativeHandle();
+    if (fenceHandle) {
+      if (fenceHandle->numInts != 0) {
+        ALOGE("Invalid fence handle %p", fenceHandle);
+      }
+      if (fenceHandle->numFds == 1) {
+        releaseFence = dup(fenceHandle->data[0]);
+        if (releaseFence < 0){
+          ALOGE("Failed to dup fence fd");
+        }
+      } else {
+        if (fenceHandle->numFds != 0) {
+          ALOGE("Invalid fence handle %p", fenceHandle);
+        }
+      }
+    }
+  });
+
+  return releaseFence;
+}
+
+}  // namespace android
diff --git a/sensors/1.0/vts/functional/GrallocWrapper.h b/sensors/1.0/vts/functional/GrallocWrapper.h
new file mode 100644
index 0000000..e506fe1
--- /dev/null
+++ b/sensors/1.0/vts/functional/GrallocWrapper.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 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 GRALLO_WRAPPER_H_
+#define GRALLO_WRAPPER_H_
+
+#include <unordered_set>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace allocator2 = ::android::hardware::graphics::allocator::V2_0;
+namespace mapper2 = ::android::hardware::graphics::mapper::V2_0;
+
+namespace android {
+
+// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/
+class GrallocWrapper {
+ public:
+  GrallocWrapper();
+  ~GrallocWrapper();
+
+  sp<allocator2::IAllocator> getAllocator() const;
+  sp<mapper2::IMapper> getMapper() const;
+
+  std::string dumpDebugInfo();
+
+  // When import is false, this simply calls IAllocator::allocate. When import
+  // is true, the returned buffers are also imported into the mapper.
+  //
+  // Either case, the returned buffers must be freed with freeBuffer.
+  std::vector<const native_handle_t*> allocate(
+      const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import = true,
+      uint32_t* outStride = nullptr);
+  const native_handle_t* allocate(
+      const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true,
+      uint32_t* outStride = nullptr);
+
+  mapper2::BufferDescriptor createDescriptor(
+      const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo);
+
+  const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle);
+  void freeBuffer(const native_handle_t* bufferHandle);
+
+  // We use fd instead of hardware::hidl_handle in these functions to pass fences
+  // in and out of the mapper.  The ownership of the fd is always transferred
+  // with each of these functions.
+  void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+             const mapper2::IMapper::Rect& accessRegion, int acquireFence);
+
+  int unlock(const native_handle_t* bufferHandle);
+
+ private:
+  void init();
+  const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle);
+
+  sp<allocator2::IAllocator> mAllocator;
+  sp<mapper2::IMapper> mMapper;
+
+  // Keep track of all cloned and imported handles.  When a test fails with
+  // ASSERT_*, the destructor will free the handles for the test.
+  std::unordered_set<const native_handle_t*> mClonedBuffers;
+  std::unordered_set<const native_handle_t*> mImportedBuffers;
+};
+
+}  // namespace android
+#endif  // GRALLO_WRAPPER_H_
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index 4842946..19265c2 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "sensors_hidl_hal_test"
+#include "GrallocWrapper.h"
 #include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/sensors/1.0/ISensors.h>
@@ -36,6 +37,7 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
+using ::android::GrallocWrapper;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::hidl_string;
@@ -230,6 +232,7 @@
   native_handle_t* mNativeHandle;
   size_t mSize;
   char* mBuffer;
+  std::unique_ptr<GrallocWrapper> mGrallocWrapper;
 
   DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
 };
@@ -265,6 +268,7 @@
   while (offset + kEventSize <= mSize) {
     int64_t atomicCounter = *reinterpret_cast<uint32_t *>(mBuffer + offset + kOffsetAtomicCounter);
     if (atomicCounter <= lastCounter) {
+      ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter, lastCounter);
       break;
     }
 
@@ -324,7 +328,34 @@
       break;
     }
     case SharedMemType::GRALLOC: {
+      mGrallocWrapper = std::make_unique<GrallocWrapper>();
+      if (mGrallocWrapper->getAllocator() == nullptr || mGrallocWrapper->getMapper() == nullptr) {
+        break;
+      }
+      using android::hardware::graphics::common::V1_0::BufferUsage;
+      using android::hardware::graphics::common::V1_0::PixelFormat;
+      mapper2::IMapper::BufferDescriptorInfo buf_desc_info = {
+        .width = static_cast<uint32_t>(size),
+        .height = 1,
+        .layerCount = 1,
+        .usage = static_cast<uint64_t> (BufferUsage::SENSOR_DIRECT_DATA |
+            BufferUsage::CPU_READ_OFTEN),
+        .format = PixelFormat::BLOB
+      };
 
+      handle = const_cast<native_handle_t *>(mGrallocWrapper->allocate(buf_desc_info));
+      if (handle != nullptr) {
+        mapper2::IMapper::Rect region{0, 0,
+            static_cast<int32_t>(buf_desc_info.width),
+            static_cast<int32_t>(buf_desc_info.height)};
+        buffer = static_cast<char *>
+                (mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1));
+        if (buffer != nullptr) {
+          break;
+        }
+        mGrallocWrapper->freeBuffer(handle);
+        handle = nullptr;
+      }
       break;
     }
     default:
@@ -353,6 +384,16 @@
       }
       break;
     }
+    case SharedMemType::GRALLOC: {
+      if (mSize != 0) {
+        mGrallocWrapper->unlock(mNativeHandle);
+        mGrallocWrapper->freeBuffer(mNativeHandle);
+
+        mNativeHandle = nullptr;
+        mSize = 0;
+      }
+      break;
+    }
     default: {
       if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
         ALOGE("SensorsTestSharedMemory %p not properly destructed: "
@@ -1223,7 +1264,7 @@
 void SensorsHidlTest::testDirectReportOperation(
     SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker) {
   constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
-  constexpr size_t kNEvent = 500;
+  constexpr size_t kNEvent = 4096;
   constexpr size_t kMemSize = kEventSize * kNEvent;
 
   constexpr float kNormalNominal = 50;
@@ -1379,6 +1420,60 @@
       SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::VERY_FAST, NullChecker());
 }
 
+// Test sensor event direct report with gralloc for accel sensor at normal rate
+TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
+  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                            sAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at fast rate
+TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
+  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST,
+                            sAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at very fast rate
+TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
+  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
+                            sAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at normal rate
+TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
+  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                            sGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at fast rate
+TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
+  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
+                            sGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at very fast rate
+TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
+  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
+                            sGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for mag sensor at normal rate
+TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
+  testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                            NullChecker());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at fast rate
+TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
+  testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST,
+                            NullChecker());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at very fast rate
+TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
+  testDirectReportOperation(
+      SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::VERY_FAST, NullChecker());
+}
+
 int main(int argc, char **argv) {
   ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironment::Instance());
   ::testing::InitGoogleTest(&argc, argv);
diff --git a/tests/Android.bp b/tests/Android.bp
index 9583bfd..18fc473 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -25,4 +25,6 @@
     "pointer/1.0",
     "pointer/1.0/default",
     "pointer/1.0/default/lib",
+    "trie/1.0",
+    "trie/1.0/default",
 ]
diff --git a/tests/foo/1.0/IFoo.hal b/tests/foo/1.0/IFoo.hal
index 00337a6..c1ce7b0 100644
--- a/tests/foo/1.0/IFoo.hal
+++ b/tests/foo/1.0/IFoo.hal
@@ -126,6 +126,24 @@
     typedef multidimArrayOne[8][9][10] multidimArrayTwo;
     typedef multidimArrayTwo[2][3][4] multidimArrayThree;
 
+    struct InnerTestStruct {};
+    typedef InnerTestStruct InnerTestStructTypedef;
+    struct S1 {
+        struct InnerTestStruct {};
+        InnerTestStructTypedef foo;
+    };
+
+    enum InnerTestEnum : int32_t {
+        VALUE = 0
+    };
+    typedef InnerTestEnum InnerTestEnumTypedef;
+    struct S2 {
+        enum InnerTestEnum : int32_t {
+            VALUE = 1
+        };
+        InnerTestEnumTypedef foo;
+    };
+
     doThis(float param);
     doThatAndReturnSomething(int64_t param) generates (int32_t result);
     doQuiteABit(int32_t a, int64_t b, float c, double d) generates (double something);
diff --git a/tests/libhwbinder/1.0/default/Android.bp b/tests/libhwbinder/1.0/default/Android.bp
index 13f9c18..f1f99a6 100644
--- a/tests/libhwbinder/1.0/default/Android.bp
+++ b/tests/libhwbinder/1.0/default/Android.bp
@@ -6,9 +6,12 @@
         "ScheduleTest.cpp",
     ],
     shared_libs: [
+        "libcutils",
         "libhidlbase",
         "libhidltransport",
+        "libhwbinder",
+        "liblog",
         "libutils",
-        "android.hardware.tests.libhwbinder@1.0",
     ],
+    static_libs: ["android.hardware.tests.libhwbinder@1.0"],
 }
diff --git a/tests/trie/1.0/Android.bp b/tests/trie/1.0/Android.bp
new file mode 100644
index 0000000..fcc4325
--- /dev/null
+++ b/tests/trie/1.0/Android.bp
@@ -0,0 +1,66 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.tests.trie@1.0_hal",
+    srcs: [
+        "types.hal",
+        "ITrie.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tests.trie@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.trie@1.0",
+    srcs: [
+        ":android.hardware.tests.trie@1.0_hal",
+    ],
+    out: [
+        "android/hardware/tests/trie/1.0/types.cpp",
+        "android/hardware/tests/trie/1.0/TrieAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tests.trie@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.trie@1.0",
+    srcs: [
+        ":android.hardware.tests.trie@1.0_hal",
+    ],
+    out: [
+        "android/hardware/tests/trie/1.0/types.h",
+        "android/hardware/tests/trie/1.0/hwtypes.h",
+        "android/hardware/tests/trie/1.0/ITrie.h",
+        "android/hardware/tests/trie/1.0/IHwTrie.h",
+        "android/hardware/tests/trie/1.0/BnHwTrie.h",
+        "android/hardware/tests/trie/1.0/BpHwTrie.h",
+        "android/hardware/tests/trie/1.0/BsTrie.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.tests.trie@1.0",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.tests.trie@1.0_genc++"],
+    generated_headers: ["android.hardware.tests.trie@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.tests.trie@1.0_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/tests/trie/1.0/ITrie.hal b/tests/trie/1.0/ITrie.hal
new file mode 100644
index 0000000..5d009ca
--- /dev/null
+++ b/tests/trie/1.0/ITrie.hal
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package android.hardware.tests.trie@1.0;
+
+interface ITrie {
+    newTrie() generates (TrieNode trie);
+    addStrings(TrieNode trie, vec<string> strings) generates (TrieNode trie);
+    containsStrings(TrieNode trie, vec<string> strings) generates (vec<bool> contains);
+};
diff --git a/tests/trie/1.0/default/Android.bp b/tests/trie/1.0/default/Android.bp
new file mode 100644
index 0000000..315c8bb
--- /dev/null
+++ b/tests/trie/1.0/default/Android.bp
@@ -0,0 +1,16 @@
+cc_library_shared {
+    name: "android.hardware.tests.trie@1.0-impl",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    srcs: [
+        "Trie.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.tests.trie@1.0",
+    ],
+}
diff --git a/tests/trie/1.0/default/Trie.cpp b/tests/trie/1.0/default/Trie.cpp
new file mode 100644
index 0000000..c81c508
--- /dev/null
+++ b/tests/trie/1.0/default/Trie.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#define LOG_TAG "hidl_test"
+
+#include "Trie.h"
+#include <android-base/logging.h>
+#include <inttypes.h>
+#include <string>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace trie {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::tests::trie::V1_0::ITrie follow.
+Return<void> Trie::newTrie(newTrie_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(Trie) newTrie()";
+
+    TrieNode ret;
+    ret.isTerminal = false;
+    _hidl_cb(ret);
+    return Void();
+}
+
+Return<void> Trie::addStrings(const TrieNode& trie, const hidl_vec<hidl_string>& strings,
+                              addStrings_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(Trie) addStrings(trie, " << strings.size() << " strings)";
+
+    // Make trie modifiable.
+    TrieNode newTrie = trie;
+
+    for (const auto& str : strings) {
+        addString(&newTrie, str);
+    }
+    _hidl_cb(newTrie);
+    return Void();
+}
+
+Return<void> Trie::containsStrings(const TrieNode& trie, const hidl_vec<hidl_string>& strings,
+                                   containsStrings_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(Trie) containsStrings(trie, " << strings.size() << " strings)";
+
+    std::vector<bool> ret(strings.size());
+    for (size_t i = 0; i != strings.size(); ++i) {
+        ret[i] = containsString(&trie, strings[i]);
+    }
+    _hidl_cb(ret);
+    return Void();
+}
+
+void Trie::addString(TrieNode* trieRoot, const std::string& str) {
+    TrieNode* currNode = trieRoot;
+
+    for (char ch : str) {
+        auto& vec = currNode->next;
+
+        auto it = std::find_if(vec.begin(), vec.end(),
+                               [&](const TrieEdge& edge) { return ch == edge.character; });
+
+        if (it == vec.end()) {
+            vec.resize(vec.size() + 1);
+            it = vec.end() - 1;
+            it->character = ch;
+            it->node.isTerminal = false;
+        }
+
+        currNode = &(it->node);
+    }
+
+    currNode->isTerminal = true;
+}
+
+bool Trie::containsString(const TrieNode* trieRoot, const std::string& str) {
+    const TrieNode* currNode = trieRoot;
+
+    for (char ch : str) {
+        const auto& vec = currNode->next;
+
+        auto it = std::find_if(vec.begin(), vec.end(),
+                               [&](const TrieEdge& edge) { return ch == edge.character; });
+
+        if (it == vec.end()) return false;
+        currNode = &(it->node);
+    }
+
+    return currNode->isTerminal;
+}
+
+ITrie* HIDL_FETCH_ITrie(const char* /* name */) {
+    return new Trie();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace trie
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
diff --git a/tests/trie/1.0/default/Trie.h b/tests/trie/1.0/default/Trie.h
new file mode 100644
index 0000000..c2ef40b
--- /dev/null
+++ b/tests/trie/1.0/default/Trie.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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 ANDROID_HARDWARE_TESTS_TRIE_V1_0_TRIE_H
+#define ANDROID_HARDWARE_TESTS_TRIE_V1_0_TRIE_H
+
+#include <android/hardware/tests/trie/1.0/ITrie.h>
+#include <hidl/Status.h>
+
+#include <string>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace trie {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::tests::trie::V1_0::ITrie;
+using ::android::hardware::tests::trie::V1_0::TrieNode;
+
+struct Trie : public ITrie {
+    // Methods from ::android::hardware::tests::trie::V1_0::ITrie follow.
+    virtual Return<void> newTrie(newTrie_cb _hidl_cb) override;
+    virtual Return<void> addStrings(const TrieNode& trie, const hidl_vec<hidl_string>& strings,
+                                    addStrings_cb _hidl_cb) override;
+    virtual Return<void> containsStrings(const TrieNode& trie, const hidl_vec<hidl_string>& strings,
+                                         containsStrings_cb _hidl_cb) override;
+
+   private:
+    void addString(TrieNode* trieRoot, const std::string& str);
+    bool containsString(const TrieNode* trieRoot, const std::string& str);
+};
+
+extern "C" ITrie* HIDL_FETCH_ITrie(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace trie
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TESTS_TRIE_V1_0_TRIE_H
diff --git a/tests/trie/1.0/types.hal b/tests/trie/1.0/types.hal
new file mode 100644
index 0000000..c626909
--- /dev/null
+++ b/tests/trie/1.0/types.hal
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package android.hardware.tests.trie@1.0;
+
+struct TrieEdge {
+    int8_t character;
+    TrieNode node; // Requires reordering.
+};
+
+struct TrieNode {
+    vec<TrieEdge> next;
+    bool isTerminal;
+};
+
+// Some forward reference tests.
+
+struct A {
+    ref<B> b;
+};
+
+struct B {
+    ref<A> a;
+};
+
+typedef ref<S> refS;
+struct S {
+    refS f;
+};
+
+enum E2 : E1 {
+    ACCEPT,
+};
+
+enum E1 : int32_t {
+    OK = E2:ACCEPT + ANOTHER,
+    ANOTHER = 100,
+};