Merge "Added protections for RenderScript VTS tests." into oc-dev
diff --git a/audio/common/2.0/default/HidlUtils.cpp b/audio/common/2.0/default/HidlUtils.cpp
index 241ca90..79cb37c 100644
--- a/audio/common/2.0/default/HidlUtils.cpp
+++ b/audio/common/2.0/default/HidlUtils.cpp
@@ -28,6 +28,7 @@
 using ::android::hardware::audio::common::V2_0::AudioPortType;
 using ::android::hardware::audio::common::V2_0::AudioSource;
 using ::android::hardware::audio::common::V2_0::AudioStreamType;
+using ::android::hardware::audio::common::V2_0::AudioUsage;
 
 namespace android {
 
@@ -103,6 +104,9 @@
     offload->durationMicroseconds = halOffload.duration_us;
     offload->hasVideo = halOffload.has_video;
     offload->isStreaming = halOffload.is_streaming;
+    offload->bitWidth = halOffload.bit_width;
+    offload->bufferSize = halOffload.offload_buffer_size;
+    offload->usage = static_cast<AudioUsage>(halOffload.usage);
 }
 
 void HidlUtils::audioOffloadInfoToHal(
diff --git a/automotive/evs/1.0/default/EvsEnumerator.cpp b/automotive/evs/1.0/default/EvsEnumerator.cpp
index 731e21b..b25d418 100644
--- a/automotive/evs/1.0/default/EvsEnumerator.cpp
+++ b/automotive/evs/1.0/default/EvsEnumerator.cpp
@@ -99,7 +99,7 @@
     }
 
     // Construct a camera instance for the caller
-    pActiveCamera = new EvsCamera(cameraId);
+    pActiveCamera = new EvsCamera(cameraId.c_str());
     pRecord->activeInstance = pActiveCamera;
     if (pActiveCamera == nullptr) {
         ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
diff --git a/automotive/evs/1.0/default/service.cpp b/automotive/evs/1.0/default/service.cpp
index 1b64e44..d4181b9 100644
--- a/automotive/evs/1.0/default/service.cpp
+++ b/automotive/evs/1.0/default/service.cpp
@@ -19,9 +19,9 @@
 #include <unistd.h>
 
 #include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
 #include <utils/Errors.h>
 #include <utils/StrongPointer.h>
-#include <utils/Log.h>
 
 #include "ServiceNames.h"
 #include "EvsEnumerator.h"
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.cpp b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
index 01d9a0e..58c2f26 100644
--- a/automotive/evs/1.0/vts/functional/FrameHandler.cpp
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
@@ -23,7 +23,6 @@
 
 #include <android/log.h>
 #include <cutils/native_handle.h>
-#include <ui/GraphicBufferMapper.h>
 #include <ui/GraphicBuffer.h>
 
 #include <algorithm>    // std::min
@@ -135,11 +134,7 @@
     // Local flag we use to keep track of when the stream is stopping
     bool timeToStop = false;
 
-    // TODO:  Why do we get a gralloc crash if we don't clone the buffer here?
-    BufferDesc buffer(bufferArg);
-    ALOGD("Clone the received frame as %p", buffer.memHandle.getNativeHandle());
-
-    if (buffer.memHandle.getNativeHandle() == nullptr) {
+    if (bufferArg.memHandle.getNativeHandle() == nullptr) {
         // Signal that the last frame has been received and the stream is stopped
         timeToStop = true;
     } else {
@@ -157,13 +152,8 @@
                 printf("Didn't get target buffer - frame lost\n");
                 ALOGE("Didn't get requested output buffer -- skipping this frame.");
             } else {
-                // In order for the handles passed through HIDL and stored in the BufferDesc to
-                // be lockable, we must register them with GraphicBufferMapper
-                registerBufferHelper(tgtBuffer);
-                registerBufferHelper(buffer);
-
                 // Copy the contents of the of buffer.memHandle into tgtBuffer
-                copyBufferContents(tgtBuffer, buffer);
+                copyBufferContents(tgtBuffer, bufferArg);
 
                 // Send the target buffer back for display
                 Return <EvsResult> result = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
@@ -183,10 +173,6 @@
                     mFramesDisplayed++;
                     mLock.unlock();
                 }
-
-                // Now tell GraphicBufferMapper we won't be using these handles anymore
-                unregisterBufferHelper(tgtBuffer);
-                unregisterBufferHelper(buffer);
             }
         }
 
@@ -233,24 +219,22 @@
     const unsigned height    = std::min(tgtBuffer.height,
                                         srcBuffer.height);
 
-    android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
-
+    sp<android::GraphicBuffer> tgt = new android::GraphicBuffer(
+        tgtBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE,
+        tgtBuffer.width, tgtBuffer.height, tgtBuffer.format, 1, tgtBuffer.usage,
+        tgtBuffer.stride);
+    sp<android::GraphicBuffer> src = new android::GraphicBuffer(
+        srcBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE,
+        srcBuffer.width, srcBuffer.height, srcBuffer.format, 1, srcBuffer.usage,
+        srcBuffer.stride);
 
     // Lock our source buffer for reading
     unsigned char* srcPixels = nullptr;
-    mapper.registerBuffer(srcBuffer.memHandle);
-    mapper.lock(srcBuffer.memHandle,
-                GRALLOC_USAGE_SW_READ_OFTEN,
-                android::Rect(width, height),
-                (void **) &srcPixels);
+    src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels);
 
     // Lock our target buffer for writing
     unsigned char* tgtPixels = nullptr;
-    mapper.registerBuffer(tgtBuffer.memHandle);
-    mapper.lock(tgtBuffer.memHandle,
-                GRALLOC_USAGE_SW_WRITE_OFTEN,
-                android::Rect(width, height),
-                (void **) &tgtPixels);
+    tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels);
 
     if (srcPixels && tgtPixels) {
         for (unsigned row = 0; row < height; row++) {
@@ -267,45 +251,11 @@
     }
 
     if (srcPixels) {
-        mapper.unlock(srcBuffer.memHandle);
+        src->unlock();
     }
     if (tgtPixels) {
-        mapper.unlock(tgtBuffer.memHandle);
+        tgt->unlock();
     }
-    mapper.unregisterBuffer(srcBuffer.memHandle);
-    mapper.unregisterBuffer(tgtBuffer.memHandle);
 
     return success;
 }
-
-
-void FrameHandler::registerBufferHelper(const BufferDesc& buffer)
-{
-    // In order for the handles passed through HIDL and stored in the BufferDesc to
-    // be lockable, we must register them with GraphicBufferMapper.
-    // If the device upon which we're running supports gralloc1, we could just call
-    // registerBuffer directly with the handle.  But that call  is broken for gralloc0 devices
-    // (which we care about, at least for now).  As a result, we have to synthesize a GraphicBuffer
-    // object around the buffer handle in order to make a call to the overloaded alternate
-    // version of the registerBuffer call that does happen to work on gralloc0 devices.
-#if REGISTER_BUFFER_ALWAYS_WORKS
-    android::GraphicBufferMapper::get().registerBuffer(buffer.memHandle);
-#else
-    android::sp<android::GraphicBuffer> pGfxBuff = new android::GraphicBuffer(
-            buffer.width, buffer.height, buffer.format,
-            1, /* we always use exactly one layer */
-            buffer.usage, buffer.stride,
-            const_cast<native_handle_t*>(buffer.memHandle.getNativeHandle()),
-            false /* GraphicBuffer should not try to free the handle */
-    );
-
-    android::GraphicBufferMapper::get().registerBuffer(pGfxBuff.get());
-#endif
-}
-
-
-void FrameHandler::unregisterBufferHelper(const BufferDesc& buffer)
-{
-    // Now tell GraphicBufferMapper we won't be using these handles anymore
-    android::GraphicBufferMapper::get().unregisterBuffer(buffer.memHandle);
-}
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.h b/automotive/evs/1.0/vts/functional/FrameHandler.h
index d5c3f6b..17a3980 100644
--- a/automotive/evs/1.0/vts/functional/FrameHandler.h
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.h
@@ -68,8 +68,6 @@
 
     // Local implementation details
     bool copyBufferContents(const BufferDesc& tgtBuffer, const BufferDesc& srcBuffer);
-    void registerBufferHelper(const BufferDesc& buffer);
-    void unregisterBufferHelper(const BufferDesc& buffer);
 
     // Values initialized as startup
     android::sp <IEvsCamera>    mCamera;
diff --git a/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
index 6a0ae48..50b6581 100644
--- a/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
@@ -37,10 +37,10 @@
 #include <string.h>
 
 #include <hidl/HidlTransportSupport.h>
+#include <hwbinder/ProcessState.h>
+#include <log/log.h>
 #include <utils/Errors.h>
 #include <utils/StrongPointer.h>
-#include <utils/Log.h>
-#include <hwbinder/ProcessState.h>
 
 #include <android/log.h>
 #include <android/hardware/automotive/evs/1.0/IEvsCamera.h>
diff --git a/automotive/vehicle/2.0/default/Android.mk b/automotive/vehicle/2.0/default/Android.mk
index b8535bd..3c56159 100644
--- a/automotive/vehicle/2.0/default/Android.mk
+++ b/automotive/vehicle/2.0/default/Android.mk
@@ -25,6 +25,7 @@
     common/src/SubscriptionManager.cpp \
     common/src/VehicleHalManager.cpp \
     common/src/VehicleObjectPool.cpp \
+    common/src/VehiclePropertyStore.cpp \
     common/src/VehicleUtils.cpp \
 
 LOCAL_C_INCLUDES := \
@@ -72,9 +73,10 @@
 
 LOCAL_MODULE:= $(vhal_v2_0)-default-impl-lib
 LOCAL_SRC_FILES:= \
-    impl/vhal_v2_0/DefaultVehicleHal.cpp \
+    impl/vhal_v2_0/EmulatedVehicleHal.cpp \
+    impl/vhal_v2_0/VehicleEmulator.cpp \
     impl/vhal_v2_0/PipeComm.cpp \
-    impl/vhal_v2_0/SocketComm.cpp
+    impl/vhal_v2_0/SocketComm.cpp \
 
 LOCAL_C_INCLUDES := \
     $(LOCAL_PATH)/impl/vhal_v2_0
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 95057cc..e6d292e 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -21,14 +21,16 @@
 #include <iostream>
 
 #include <vhal_v2_0/VehicleHalManager.h>
-#include <vhal_v2_0/DefaultVehicleHal.h>
+#include <vhal_v2_0/EmulatedVehicleHal.h>
 
 using namespace android;
 using namespace android::hardware;
 using namespace android::hardware::automotive::vehicle::V2_0;
 
 int main(int /* argc */, char* /* argv */ []) {
-    auto hal = std::make_unique<impl::DefaultVehicleHal>();
+    auto store = std::make_unique<VehiclePropertyStore>();
+    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get());
+    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
     auto service = std::make_unique<VehicleHalManager>(hal.get());
 
     configureRpcThreadpool(1, true /* callerWillJoin */);
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
new file mode 100644
index 0000000..eda94b7
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
@@ -0,0 +1,104 @@
+/*
+ * 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_automotive_vehicle_V2_0_impl_PropertyDb_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_
+
+#include <cstdint>
+#include <unordered_map>
+#include <memory>
+#include <mutex>
+
+#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+/**
+ * Encapsulates work related to storing and accessing configuration, storing and modifying
+ * vehicle property values.
+ *
+ * VehiclePropertyValues stored in a sorted map thus it makes easier to get range of values, e.g.
+ * to get value for all areas for particular property.
+ *
+ * This class is thread-safe, however it uses blocking synchronization across all methods.
+ */
+class VehiclePropertyStore {
+public:
+    /* Function that used to calculate unique token for given VehiclePropValue */
+    using TokenFunction = std::function<int64_t(const VehiclePropValue& value)>;
+
+private:
+    struct RecordConfig {
+        VehiclePropConfig propConfig;
+        TokenFunction tokenFunction;
+    };
+
+    struct RecordId {
+        int32_t prop;
+        int32_t area;
+        int64_t token;
+
+        bool operator==(const RecordId& other) const;
+        bool operator<(const RecordId& other) const;
+    };
+
+    using PropertyMap = std::map<RecordId, VehiclePropValue>;
+    using PropertyMapRange = std::pair<PropertyMap::const_iterator, PropertyMap::const_iterator>;
+
+public:
+    void registerProperty(const VehiclePropConfig& config, TokenFunction tokenFunc = nullptr);
+
+    /* Stores provided value. Returns true if value was written returns false if config for
+     * example wasn't registered. */
+    bool writeValue(const VehiclePropValue& propValue);
+
+    void removeValue(const VehiclePropValue& propValue);
+    void removeValuesForProperty(int32_t propId);
+
+    std::vector<VehiclePropValue> readAllValues() const;
+    std::vector<VehiclePropValue> readValuesForProperty(int32_t propId) const;
+    std::unique_ptr<VehiclePropValue> readValueOrNull(const VehiclePropValue& request) const;
+    std::unique_ptr<VehiclePropValue> readValueOrNull(int32_t prop, int32_t area = 0,
+                                                      int64_t token = 0) const;
+
+    std::vector<VehiclePropConfig> getAllConfigs() const;
+    const VehiclePropConfig* getConfigOrNull(int32_t propId) const;
+    const VehiclePropConfig* getConfigOrDie(int32_t propId) const;
+
+private:
+    RecordId getRecordIdLocked(const VehiclePropValue& valuePrototype) const;
+    const VehiclePropValue* getValueOrNullLocked(const RecordId& recId) const;
+    PropertyMapRange findRangeLocked(int32_t propId) const;
+
+private:
+    using MuxGuard = std::lock_guard<std::mutex>;
+    mutable std::mutex mLock;
+    std::unordered_map<int32_t /* VehicleProperty */, RecordConfig> mConfigs;
+
+    PropertyMap mPropertyValues;  // Sorted map of RecordId : VehiclePropValue.
+};
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif //android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_
diff --git a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
new file mode 100644
index 0000000..2c3ebfc
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
@@ -0,0 +1,172 @@
+/*
+ * 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 "VehiclePropertyStore"
+#include <log/log.h>
+
+#include <common/include/vhal_v2_0/VehicleUtils.h>
+#include "VehiclePropertyStore.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const {
+    return prop == other.prop && area == other.area && token == other.token;
+}
+
+bool VehiclePropertyStore::RecordId::operator<(const VehiclePropertyStore::RecordId& other) const  {
+    return prop < other.prop
+           || (prop == other.prop && area < other.area)
+           || (prop == other.prop && area == other.area && token < other.token);
+}
+
+void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
+                                            VehiclePropertyStore::TokenFunction tokenFunc) {
+    MuxGuard g(mLock);
+    mConfigs.insert({ config.prop, RecordConfig { config, tokenFunc } });
+}
+
+bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue) {
+    MuxGuard g(mLock);
+    if (!mConfigs.count(propValue.prop)) return false;
+
+    RecordId recId = getRecordIdLocked(propValue);
+    VehiclePropValue* valueToUpdate = const_cast<VehiclePropValue*>(getValueOrNullLocked(recId));
+    if (valueToUpdate == nullptr) {
+        mPropertyValues.insert({ recId, propValue });
+    } else {
+        valueToUpdate->timestamp = propValue.timestamp;
+        valueToUpdate->value = propValue.value;
+    }
+    return true;
+}
+
+void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) {
+    MuxGuard g(mLock);
+    RecordId recId = getRecordIdLocked(propValue);
+    auto it = mPropertyValues.find(recId);
+    if (it != mPropertyValues.end()) {
+        mPropertyValues.erase(it);
+    }
+}
+
+void VehiclePropertyStore::removeValuesForProperty(int32_t propId) {
+    MuxGuard g(mLock);
+    auto range = findRangeLocked(propId);
+    mPropertyValues.erase(range.first, range.second);
+}
+
+std::vector<VehiclePropValue> VehiclePropertyStore::readAllValues() const {
+    MuxGuard g(mLock);
+    std::vector<VehiclePropValue> allValues;
+    allValues.reserve(mPropertyValues.size());
+    for (auto&& it : mPropertyValues) {
+        allValues.push_back(it.second);
+    }
+    return allValues;
+}
+
+std::vector<VehiclePropValue> VehiclePropertyStore::readValuesForProperty(int32_t propId) const {
+    std::vector<VehiclePropValue> values;
+    MuxGuard g(mLock);
+    auto range = findRangeLocked(propId);
+    for (auto it = range.first; it != range.second; ++it) {
+        values.push_back(it->second);
+    }
+
+    return values;
+}
+
+std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
+        const VehiclePropValue& request) const {
+    MuxGuard g(mLock);
+    RecordId recId = getRecordIdLocked(request);
+    const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
+    return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
+}
+
+std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
+        int32_t prop, int32_t area, int64_t token) const {
+    RecordId recId = {prop, isGlobalProp(prop) ? 0 : area, token };
+    MuxGuard g(mLock);
+    const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
+    return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
+}
+
+
+std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
+    MuxGuard g(mLock);
+    std::vector<VehiclePropConfig> configs;
+    configs.reserve(mConfigs.size());
+    for (auto&& recordConfigIt: mConfigs) {
+        configs.push_back(recordConfigIt.second.propConfig);
+    }
+    return configs;
+}
+
+const VehiclePropConfig* VehiclePropertyStore::getConfigOrNull(int32_t propId) const {
+    MuxGuard g(mLock);
+    auto recordConfigIt = mConfigs.find(propId);
+    return recordConfigIt != mConfigs.end() ? &recordConfigIt->second.propConfig : nullptr;
+}
+
+const VehiclePropConfig* VehiclePropertyStore::getConfigOrDie(int32_t propId) const {
+    auto cfg = getConfigOrNull(propId);
+    if (!cfg) {
+        ALOGW("%s: config not found for property: 0x%x", __func__, propId);
+        abort();
+    }
+    return cfg;
+}
+
+VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
+        const VehiclePropValue& valuePrototype) const {
+    RecordId recId = {
+        .prop = valuePrototype.prop,
+        .area = isGlobalProp(valuePrototype.prop) ? 0 : valuePrototype.areaId,
+        .token = 0
+    };
+
+    auto it = mConfigs.find(recId.prop);
+    if (it == mConfigs.end()) return {};
+
+    if (it->second.tokenFunction != nullptr) {
+        recId.token = it->second.tokenFunction(valuePrototype);
+    }
+    return recId;
+}
+
+const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked(
+        const VehiclePropertyStore::RecordId& recId) const  {
+    auto it = mPropertyValues.find(recId);
+    return it == mPropertyValues.end() ? nullptr : &it->second;
+}
+
+VehiclePropertyStore::PropertyMapRange VehiclePropertyStore::findRangeLocked(int32_t propId) const {
+    // Based on the fact that mPropertyValues is a sorted map by RecordId.
+    auto beginIt = mPropertyValues.lower_bound( RecordId { propId, INT32_MIN, 0 });
+    auto endIt = mPropertyValues.lower_bound( RecordId { propId + 1, INT32_MIN, 0 });
+
+    return  PropertyMapRange { beginIt, endIt };
+}
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 545de39..bf16a9b 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -33,176 +33,257 @@
     toInt(VehicleProperty::HVAC_FAN_DIRECTION),
 };
 
-const VehiclePropConfig kVehicleProperties[] = {
+struct ConfigDeclaration {
+    VehiclePropConfig config;
+
+    /* This value will be used as an initial value for the property. If this field is specified for
+     * property that supports multiple areas then it will be used for all areas unless particular
+     * area is overridden in initialAreaValue field. */
+    VehiclePropValue::RawValue initialValue;
+    /* Use initialAreaValues if it is necessary to specify different values per each area. */
+    std::map<int32_t, VehiclePropValue::RawValue> initialAreaValues;
+};
+
+const ConfigDeclaration kVehicleProperties[] {
     {
-        .prop = toInt(VehicleProperty::INFO_MAKE),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::STATIC,
+        .config = {
+            .prop = toInt(VehicleProperty::INFO_MAKE),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::STATIC,
+        },
+        .initialValue = { .stringValue = "Toy Vehicle" }
+    },
+    {
+        .config = {
+            .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        },
+        .initialValue = { .floatValues = {0.0f} }
     },
 
     {
-        .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .config = {
+            .prop = toInt(VehicleProperty::CURRENT_GEAR),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        },
+        .initialValue = { .int32Values = { toInt(VehicleGear::GEAR_PARK) } }
     },
 
     {
-        .prop = toInt(VehicleProperty::CURRENT_GEAR),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .config = {
+            .prop = toInt(VehicleProperty::PARKING_BRAKE_ON),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        },
+        .initialValue = { .int32Values = {1} }
     },
 
     {
-        .prop = toInt(VehicleProperty::PARKING_BRAKE_ON),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .config = {
+            .prop = toInt(VehicleProperty::FUEL_LEVEL_LOW),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        },
+        .initialValue = { .int32Values = {0} }
     },
 
     {
-        .prop = toInt(VehicleProperty::FUEL_LEVEL_LOW),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .config = {
+            .prop = toInt(VehicleProperty::HVAC_POWER_ON),
+            .access = VehiclePropertyAccess::READ_WRITE,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+            // TODO(bryaneyler): Ideally, this is generated dynamically from
+            // kHvacPowerProperties.
+            .configString = "0x12400500,0x12400501"  // HVAC_FAN_SPEED,HVAC_FAN_DIRECTION
+        },
+        .initialValue = { .int32Values = {1} }
     },
 
     {
-        .prop = toInt(VehicleProperty::HVAC_POWER_ON),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .supportedAreas = toInt(VehicleAreaZone::ROW_1),
-        // TODO(bryaneyler): Ideally, this is generated dynamically from
-        // kHvacPowerProperties.
-        .configString = "0x12400500,0x12400501"  // HVAC_FAN_SPEED,HVAC_FAN_DIRECTION
+        .config = {
+            .prop = toInt(VehicleProperty::HVAC_DEFROSTER),
+            .access = VehiclePropertyAccess::READ_WRITE,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            .supportedAreas =
+            VehicleAreaWindow::FRONT_WINDSHIELD
+            | VehicleAreaWindow::REAR_WINDSHIELD
+        },
+        .initialValue = { .int32Values = {0} }  // Will be used for all areas.
     },
 
     {
-        .prop = toInt(VehicleProperty::HVAC_DEFROSTER),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .supportedAreas =
-                VehicleAreaWindow::FRONT_WINDSHIELD
-                | VehicleAreaWindow::REAR_WINDSHIELD
+        .config = {
+            .prop = toInt(VehicleProperty::HVAC_RECIRC_ON),
+            .access = VehiclePropertyAccess::READ_WRITE,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+        },
+        .initialValue = { .int32Values = {1} }
     },
 
     {
-        .prop = toInt(VehicleProperty::HVAC_RECIRC_ON),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+        .config = {
+            .prop = toInt(VehicleProperty::HVAC_AC_ON),
+            .access = VehiclePropertyAccess::READ_WRITE,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+        },
+        .initialValue = { .int32Values = {1} }
     },
 
     {
-        .prop = toInt(VehicleProperty::HVAC_AC_ON),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+        .config = {
+            .prop = toInt(VehicleProperty::HVAC_AUTO_ON),
+            .access = VehiclePropertyAccess::READ_WRITE,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+        },
+        .initialValue = { .int32Values = {1} }
     },
 
     {
-        .prop = toInt(VehicleProperty::HVAC_AUTO_ON),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+        .config = {
+            .prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+            .access = VehiclePropertyAccess::READ_WRITE,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+            .areaConfigs = {
+                VehicleAreaConfig {
+                    .areaId = toInt(VehicleAreaZone::ROW_1),
+                    .minInt32Value = 1,
+                    .maxInt32Value = 7
+                }
+            }
+        },
+        .initialValue = { .int32Values = {3} }
     },
 
     {
-        .prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .supportedAreas = toInt(VehicleAreaZone::ROW_1),
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1),
-                .minInt32Value = 1,
-                .maxInt32Value = 7
+        .config = {
+            .prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION),
+            .access = VehiclePropertyAccess::READ_WRITE,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+        },
+        .initialValue = { .int32Values = { toInt(VehicleHvacFanDirection::FACE) } }
+    },
+
+    {
+        .config = {
+            .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
+            .access = VehiclePropertyAccess::READ_WRITE,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            .supportedAreas =
+            VehicleAreaZone::ROW_1_LEFT
+            | VehicleAreaZone::ROW_1_RIGHT,
+            .areaConfigs = {
+                VehicleAreaConfig {
+                    .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
+                    .minFloatValue = 16,
+                    .maxFloatValue = 32,
+                },
+                VehicleAreaConfig {
+                    .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
+                    .minFloatValue = 16,
+                    .maxFloatValue = 32,
+                }
+            }
+        },
+        .initialAreaValues = {
+            {
+                toInt(VehicleAreaZone::ROW_1_LEFT),
+                { .floatValues = {16} }
+            }, {
+                toInt(VehicleAreaZone::ROW_1_RIGHT),
+                { .floatValues = {20} }
             }
         }
     },
 
     {
-        .prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+        .config = {
+            .prop = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE),
+            .access = VehiclePropertyAccess::READ,
+            // TODO(bryaneyler): Support ON_CHANGE as well.
+            .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+            .minSampleRate = 1.0f,
+            .maxSampleRate = 2.0f,
+        },
+        .initialValue = { .floatValues = {25.0f} }
     },
 
     {
-        .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .supportedAreas =
-                VehicleAreaZone::ROW_1_LEFT
-                | VehicleAreaZone::ROW_1_RIGHT,
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
-                .minFloatValue = 16,
-                .maxFloatValue = 32,
-            },
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
-                .minFloatValue = 16,
-                .maxFloatValue = 32,
+        .config = {
+            .prop = toInt(VehicleProperty::NIGHT_MODE),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        },
+        .initialValue = { .int32Values = {0} }
+    },
+
+    {
+        .config = {
+            .prop = toInt(VehicleProperty::DRIVING_STATUS),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        },
+        .initialValue = { .int32Values = { toInt(VehicleDrivingStatus::UNRESTRICTED) } }
+    },
+
+    {
+        .config = {
+            .prop = toInt(VehicleProperty::GEAR_SELECTION),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        },
+        .initialValue = { .int32Values = { toInt(VehicleGear::GEAR_PARK) } }
+    },
+
+    {
+        .config = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::STATIC,
+        },
+        .initialValue = { .floatValues = { 123000.0f } }  // In Milliliters
+    },
+
+    {
+        .config = {
+            .prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
+            .access = VehiclePropertyAccess::READ_WRITE,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            .areaConfigs = {
+                VehicleAreaConfig {
+                    .minInt32Value = 0,
+                    .maxInt32Value = 10
+                }
             }
-        }
+        },
+        .initialValue = { .int32Values = {7} }
     },
 
     {
-        .prop = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE),
-        .access = VehiclePropertyAccess::READ,
-        // TODO(bryaneyler): Support ON_CHANGE as well.
-        .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
-        .minSampleRate = 1.0f,
-        .maxSampleRate = 2.0f,
+        .config = {
+            .prop = toInt(VehicleProperty::IGNITION_STATE),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        },
+        .initialValue = { .int32Values = { toInt(VehicleIgnitionState::ON) } }
     },
 
     {
-        .prop = toInt(VehicleProperty::NIGHT_MODE),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-    },
-
-    {
-        .prop = toInt(VehicleProperty::DRIVING_STATUS),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-    },
-
-    {
-        .prop = toInt(VehicleProperty::GEAR_SELECTION),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-    },
-
-    {
-        .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::STATIC,
-    },
-
-    {
-        .prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .minInt32Value = 0,
-                .maxInt32Value = 10
-            }
-        }
-    },
-
-    {
-        .prop = toInt(VehicleProperty::IGNITION_STATE),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-    },
-
-    {
-        .prop = toInt(VehicleProperty::ENGINE_OIL_TEMP),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
-        .minSampleRate = 0.1, // 0.1 Hz, every 10 seconds
-        .maxSampleRate = 10,  // 10 Hz, every 100 ms
+        .config = {
+            .prop = toInt(VehicleProperty::ENGINE_OIL_TEMP),
+            .access = VehiclePropertyAccess::READ,
+            .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+            .minSampleRate = 0.1, // 0.1 Hz, every 10 seconds
+            .maxSampleRate = 10,  // 10 Hz, every 100 ms
+        },
+        .initialValue = { .floatValues = {101.0f} }
     }
 };
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
deleted file mode 100644
index 03a65f3..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
+++ /dev/null
@@ -1,689 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "DefaultVehicleHal_v2_0"
-#include <android/log.h>
-
-#include <algorithm>
-#include <android-base/properties.h>
-#include <cstdio>
-
-#include "DefaultVehicleHal.h"
-#include "PipeComm.h"
-#include "SocketComm.h"
-#include "VehicleHalProto.pb.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-void DefaultVehicleHal::doGetConfig(emulator::EmulatorMessage& rxMsg,
-                                    emulator::EmulatorMessage& respMsg) {
-    std::vector<VehiclePropConfig> configs = listProperties();
-    emulator::VehiclePropGet getProp = rxMsg.prop(0);
-
-    respMsg.set_msg_type(emulator::GET_CONFIG_RESP);
-    respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
-
-    for (auto& config : configs) {
-        // Find the config we are looking for
-        if (config.prop == getProp.prop()) {
-            emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
-            populateProtoVehicleConfig(protoCfg, config);
-            respMsg.set_status(emulator::RESULT_OK);
-            break;
-        }
-    }
-}
-
-void DefaultVehicleHal::doGetConfigAll(emulator::EmulatorMessage& /* rxMsg */,
-                                       emulator::EmulatorMessage& respMsg) {
-    std::vector<VehiclePropConfig> configs = listProperties();
-
-    respMsg.set_msg_type(emulator::GET_CONFIG_ALL_RESP);
-    respMsg.set_status(emulator::RESULT_OK);
-
-    for (auto& config : configs) {
-        emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
-        populateProtoVehicleConfig(protoCfg, config);
-    }
-}
-
-void DefaultVehicleHal::doGetProperty(emulator::EmulatorMessage& rxMsg,
-                                      emulator::EmulatorMessage& respMsg) {
-    int32_t areaId = 0;
-    emulator::VehiclePropGet getProp = rxMsg.prop(0);
-    int32_t propId = getProp.prop();
-    emulator::Status status = emulator::ERROR_INVALID_PROPERTY;
-    VehiclePropValue* val;
-
-    respMsg.set_msg_type(emulator::GET_PROPERTY_RESP);
-
-    if (getProp.has_area_id()) {
-        areaId = getProp.area_id();
-    }
-
-    {
-        std::lock_guard<std::mutex> lock(mPropsMutex);
-
-        val = getVehiclePropValueLocked(propId, areaId);
-        if (val != nullptr) {
-            emulator::VehiclePropValue* protoVal = respMsg.add_value();
-            populateProtoVehiclePropValue(protoVal, val);
-            status = emulator::RESULT_OK;
-        }
-    }
-
-    respMsg.set_status(status);
-}
-
-void DefaultVehicleHal::doGetPropertyAll(emulator::EmulatorMessage& /* rxMsg */,
-                                         emulator::EmulatorMessage& respMsg) {
-    respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP);
-    respMsg.set_status(emulator::RESULT_OK);
-
-    {
-        std::lock_guard<std::mutex> lock(mPropsMutex);
-
-        for (auto& prop : mProps) {
-            emulator::VehiclePropValue* protoVal = respMsg.add_value();
-            populateProtoVehiclePropValue(protoVal, prop.second->get());
-        }
-    }
-}
-
-void DefaultVehicleHal::doSetProperty(emulator::EmulatorMessage& rxMsg,
-                                      emulator::EmulatorMessage& respMsg) {
-    emulator::VehiclePropValue protoVal = rxMsg.value(0);
-    VehiclePropValue val;
-
-    respMsg.set_msg_type(emulator::SET_PROPERTY_RESP);
-
-    val.prop = protoVal.prop();
-    val.areaId = protoVal.area_id();
-    val.timestamp = elapsedRealtimeNano();
-
-    // Copy value data if it is set.  This automatically handles complex data types if needed.
-    if (protoVal.has_string_value()) {
-        val.value.stringValue = protoVal.string_value().c_str();
-    }
-
-    if (protoVal.has_bytes_value()) {
-        std::vector<uint8_t> tmp(protoVal.bytes_value().begin(), protoVal.bytes_value().end());
-        val.value.bytes = tmp;
-    }
-
-    if (protoVal.int32_values_size() > 0) {
-        std::vector<int32_t> int32Values = std::vector<int32_t>(protoVal.int32_values_size());
-        for (int i=0; i<protoVal.int32_values_size(); i++) {
-            int32Values[i] = protoVal.int32_values(i);
-        }
-        val.value.int32Values = int32Values;
-    }
-
-    if (protoVal.int64_values_size() > 0) {
-        std::vector<int64_t> int64Values = std::vector<int64_t>(protoVal.int64_values_size());
-        for (int i=0; i<protoVal.int64_values_size(); i++) {
-            int64Values[i] = protoVal.int64_values(i);
-        }
-        val.value.int64Values = int64Values;
-    }
-
-    if (protoVal.float_values_size() > 0) {
-        std::vector<float> floatValues = std::vector<float>(protoVal.float_values_size());
-        for (int i=0; i<protoVal.float_values_size(); i++) {
-            floatValues[i] = protoVal.float_values(i);
-        }
-        val.value.floatValues = floatValues;
-    }
-
-    if (updateProperty(val) == StatusCode::OK) {
-        // Send property up to VehicleHalManager via callback
-        auto& pool = *getValuePool();
-        VehiclePropValuePtr v = pool.obtain(val);
-
-        doHalEvent(std::move(v));
-        respMsg.set_status(emulator::RESULT_OK);
-    } else {
-        respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
-    }
-}
-
-// This function should only be called while mPropsMutex is locked.
-VehiclePropValue* DefaultVehicleHal::getVehiclePropValueLocked(int32_t propId, int32_t areaId) {
-    if (getPropArea(propId) == VehicleArea::GLOBAL) {
-        // In VehicleHal, global properties have areaId = -1.  We use 0.
-        areaId = 0;
-    }
-
-    auto prop = mProps.find(std::make_pair(propId, areaId));
-    if (prop != mProps.end()) {
-        return prop->second->get();
-    }
-    ALOGW("%s: Property not found:  propId = 0x%x, areaId = 0x%x", __func__, propId, areaId);
-    return nullptr;
-}
-
-void DefaultVehicleHal::parseRxProtoBuf(std::vector<uint8_t>& msg) {
-    emulator::EmulatorMessage rxMsg;
-    emulator::EmulatorMessage respMsg;
-
-    if (rxMsg.ParseFromArray(msg.data(), msg.size())) {
-        switch (rxMsg.msg_type()) {
-        case emulator::GET_CONFIG_CMD:
-            doGetConfig(rxMsg, respMsg);
-            break;
-        case emulator::GET_CONFIG_ALL_CMD:
-            doGetConfigAll(rxMsg, respMsg);
-            break;
-        case emulator::GET_PROPERTY_CMD:
-            doGetProperty(rxMsg, respMsg);
-            break;
-        case emulator::GET_PROPERTY_ALL_CMD:
-            doGetPropertyAll(rxMsg, respMsg);
-            break;
-        case emulator::SET_PROPERTY_CMD:
-            doSetProperty(rxMsg, respMsg);
-            break;
-        default:
-            ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
-            respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD);
-            break;
-        }
-
-        // Send the reply
-        txMsg(respMsg);
-    } else {
-        ALOGE("%s: ParseFromString() failed. msgSize=%d", __func__, static_cast<int>(msg.size()));
-    }
-}
-
-// Copies internal VehiclePropConfig data structure to protobuf VehiclePropConfig
-void DefaultVehicleHal::populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
-                                                   const VehiclePropConfig& cfg) {
-    protoCfg->set_prop(cfg.prop);
-    protoCfg->set_access(toInt(cfg.access));
-    protoCfg->set_change_mode(toInt(cfg.changeMode));
-    protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
-
-    if (!isGlobalProp(cfg.prop)) {
-        protoCfg->set_supported_areas(cfg.supportedAreas);
-    }
-
-    for (auto& configElement : cfg.configArray) {
-        protoCfg->add_config_array(configElement);
-    }
-
-    if (cfg.configString.size() > 0) {
-        protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
-    }
-
-    // Populate the min/max values based on property type
-    switch (getPropType(cfg.prop)) {
-    case VehiclePropertyType::STRING:
-    case VehiclePropertyType::BOOLEAN:
-    case VehiclePropertyType::INT32_VEC:
-    case VehiclePropertyType::FLOAT_VEC:
-    case VehiclePropertyType::BYTES:
-    case VehiclePropertyType::COMPLEX:
-        // Do nothing.  These types don't have min/max values
-        break;
-    case VehiclePropertyType::INT64:
-        if (cfg.areaConfigs.size() > 0) {
-            emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
-            aCfg->set_min_int64_value(cfg.areaConfigs[0].minInt64Value);
-            aCfg->set_max_int64_value(cfg.areaConfigs[0].maxInt64Value);
-        }
-        break;
-    case VehiclePropertyType::FLOAT:
-        if (cfg.areaConfigs.size() > 0) {
-            emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
-            aCfg->set_min_float_value(cfg.areaConfigs[0].minFloatValue);
-            aCfg->set_max_float_value(cfg.areaConfigs[0].maxFloatValue);
-        }
-        break;
-    case VehiclePropertyType::INT32:
-        if (cfg.areaConfigs.size() > 0) {
-            emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
-            aCfg->set_min_int32_value(cfg.areaConfigs[0].minInt32Value);
-            aCfg->set_max_int32_value(cfg.areaConfigs[0].maxInt32Value);
-        }
-        break;
-    default:
-        ALOGW("%s: Unknown property type:  0x%x", __func__, toInt(getPropType(cfg.prop)));
-        break;
-    }
-
-    protoCfg->set_min_sample_rate(cfg.minSampleRate);
-    protoCfg->set_max_sample_rate(cfg.maxSampleRate);
-}
-
-// Copies internal VehiclePropValue data structure to protobuf VehiclePropValue
-void DefaultVehicleHal::populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
-                                                      const VehiclePropValue* val) {
-    protoVal->set_prop(val->prop);
-    protoVal->set_value_type(toInt(getPropType(val->prop)));
-    protoVal->set_timestamp(val->timestamp);
-    protoVal->set_area_id(val->areaId);
-
-    // Copy value data if it is set.
-    //  - for bytes and strings, this is indicated by size > 0
-    //  - for int32, int64, and float, copy the values if vectors have data
-    if (val->value.stringValue.size() > 0) {
-        protoVal->set_string_value(val->value.stringValue.c_str(), val->value.stringValue.size());
-    }
-
-    if (val->value.bytes.size() > 0) {
-        protoVal->set_bytes_value(val->value.bytes.data(), val->value.bytes.size());
-    }
-
-    for (auto& int32Value : val->value.int32Values) {
-        protoVal->add_int32_values(int32Value);
-    }
-
-    for (auto& int64Value : val->value.int64Values) {
-        protoVal->add_int64_values(int64Value);
-    }
-
-    for (auto& floatValue : val->value.floatValues) {
-        protoVal->add_float_values(floatValue);
-    }
-}
-
-void DefaultVehicleHal::rxMsg() {
-    int  numBytes = 0;
-
-    while (mExit == 0) {
-        std::vector<uint8_t> msg = mComm->read();
-
-        if (msg.size() > 0) {
-            // Received a message.
-            parseRxProtoBuf(msg);
-        } else {
-            // This happens when connection is closed
-            ALOGD("%s: numBytes=%d, msgSize=%d", __func__, numBytes,
-                  static_cast<int32_t>(msg.size()));
-            break;
-        }
-    }
-}
-
-void DefaultVehicleHal::rxThread() {
-    bool isEmulator = android::base::GetBoolProperty("ro.kernel.qemu", false);
-
-    if (isEmulator) {
-        // Initialize pipe to Emulator
-        mComm.reset(new PipeComm);
-    } else {
-        // Initialize socket over ADB
-        mComm.reset(new SocketComm);
-    }
-
-    int retVal = mComm->open();
-
-    if (retVal == 0) {
-        // Comms are properly opened
-        while (mExit == 0) {
-            retVal = mComm->connect();
-
-            if (retVal >= 0) {
-                rxMsg();
-            }
-
-            // Check every 100ms for a new connection
-            std::this_thread::sleep_for(std::chrono::milliseconds(100));
-        }
-    }
-}
-
-// This function sets the default value of a property if we are interested in setting it.
-// TODO:  Co-locate the default values with the configuration structure, to make it easier to
-//          add new properties and their defaults.
-void DefaultVehicleHal::setDefaultValue(VehiclePropValue* prop) {
-    switch (prop->prop) {
-    case toInt(VehicleProperty::INFO_MAKE):
-        prop->value.stringValue = "Default Car";
-        break;
-    case toInt(VehicleProperty::PERF_VEHICLE_SPEED):
-        prop->value.floatValues[0] = 0;
-        break;
-    case toInt(VehicleProperty::CURRENT_GEAR):
-        prop->value.int32Values[0] = toInt(VehicleGear::GEAR_PARK);
-        break;
-    case toInt(VehicleProperty::PARKING_BRAKE_ON):
-        prop->value.int32Values[0] = 1;
-        break;
-    case toInt(VehicleProperty::FUEL_LEVEL_LOW):
-        prop->value.int32Values[0] = 0;
-        break;
-    case toInt(VehicleProperty::HVAC_POWER_ON):
-        prop->value.int32Values[0] = 1;
-        break;
-    case toInt(VehicleProperty::HVAC_DEFROSTER):
-        prop->value.int32Values[0] = 0;
-        break;
-    case toInt(VehicleProperty::HVAC_RECIRC_ON):
-        prop->value.int32Values[0] = 1;
-        break;
-    case toInt(VehicleProperty::HVAC_AC_ON):
-        prop->value.int32Values[0] = 1;
-        break;
-    case toInt(VehicleProperty::HVAC_AUTO_ON):
-        prop->value.int32Values[0] = 1;
-        break;
-    case toInt(VehicleProperty::HVAC_FAN_SPEED):
-        prop->value.int32Values[0] = 3;
-        break;
-    case toInt(VehicleProperty::HVAC_FAN_DIRECTION):
-        prop->value.int32Values[0] = toInt(VehicleHvacFanDirection::FACE);
-        break;
-    case toInt(VehicleProperty::HVAC_TEMPERATURE_SET):
-        prop->value.floatValues[0] = 16;
-        break;
-    case toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE):
-        prop->value.floatValues[0] = 25;
-        break;
-    case toInt(VehicleProperty::NIGHT_MODE):
-        prop->value.int32Values[0] = 0;
-        break;
-    case toInt(VehicleProperty::DRIVING_STATUS):
-        prop->value.int32Values[0] = toInt(VehicleDrivingStatus::UNRESTRICTED);
-        break;
-    case toInt(VehicleProperty::GEAR_SELECTION):
-        prop->value.int32Values[0] = toInt(VehicleGear::GEAR_PARK);
-        break;
-    case toInt(VehicleProperty::INFO_FUEL_CAPACITY):
-        prop->value.floatValues[0] = 123000.0f;  // In milliliters
-        break;
-    case toInt(VehicleProperty::ENGINE_OIL_TEMP):
-        prop->value.floatValues[0] = 101;
-        break;
-    case toInt(VehicleProperty::DISPLAY_BRIGHTNESS):
-        prop->value.int32Values[0] = 7;
-        break;
-    case toInt(VehicleProperty::IGNITION_STATE):
-        prop->value.int32Values[0] = toInt(VehicleIgnitionState::ON);
-        break;
-    default:
-        ALOGW("%s: propId=0x%x not found", __func__, prop->prop);
-        break;
-    }
-}
-
-// Transmit a reply back to the emulator
-void DefaultVehicleHal::txMsg(emulator::EmulatorMessage& txMsg) {
-    int numBytes = txMsg.ByteSize();
-    std::vector<uint8_t> msg(numBytes);
-
-    if (txMsg.SerializeToArray(msg.data(), msg.size())) {
-        int retVal = 0;
-
-        // Send the message
-        if (mExit == 0) {
-            mComm->write(msg);
-        }
-
-        if (retVal < 0) {
-            ALOGE("%s: Failed to tx message: retval=%d, errno=%d", __func__, retVal, errno);
-        }
-    } else {
-        ALOGE("%s: SerializeToString failed!", __func__);
-    }
-}
-
-// Updates the property value held in the HAL
-StatusCode DefaultVehicleHal::updateProperty(const VehiclePropValue& propValue) {
-    auto propId = propValue.prop;
-    auto areaId = propValue.areaId;
-    StatusCode status = StatusCode::INVALID_ARG;
-
-    {
-        std::lock_guard<std::mutex> lock(mPropsMutex);
-
-        VehiclePropValue* internalPropValue = getVehiclePropValueLocked(propId, areaId);
-        if (internalPropValue != nullptr) {
-            internalPropValue->value = propValue.value;
-            internalPropValue->timestamp = propValue.timestamp;
-            status = StatusCode::OK;
-        }
-    }
-    return status;
-}
-
-VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
-        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
-    auto areaId = requestedPropValue.areaId;
-    auto& pool = *getValuePool();
-    auto propId = requestedPropValue.prop;
-    StatusCode status;
-    VehiclePropValuePtr v = nullptr;
-
-    switch (propId) {
-    default:
-        {
-            std::lock_guard<std::mutex> lock(mPropsMutex);
-
-            VehiclePropValue *internalPropValue = getVehiclePropValueLocked(propId, areaId);
-            if (internalPropValue != nullptr) {
-                v = pool.obtain(*internalPropValue);
-            }
-        }
-
-        if (v != nullptr) {
-            status = StatusCode::OK;
-        } else {
-            status = StatusCode::INVALID_ARG;
-        }
-        break;
-    }
-
-    *outStatus = status;
-    return v;
-}
-
-StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
-    auto propId = propValue.prop;
-    StatusCode status;
-    switch (propId) {
-        default:
-            if (mHvacPowerProps.count(propId)) {
-                std::lock_guard<std::mutex> lock(mPropsMutex);
-                auto hvacPowerOn = getVehiclePropValueLocked(toInt(VehicleProperty::HVAC_POWER_ON),
-                                                             toInt(VehicleAreaZone::ROW_1));
-
-                if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
-                        && hvacPowerOn->value.int32Values[0] == 0) {
-                    status = StatusCode::NOT_AVAILABLE;
-                    break;
-                }
-            }
-            status = updateProperty(propValue);
-            if (status == StatusCode::OK) {
-                // Send property update to emulator
-                emulator::EmulatorMessage msg;
-                emulator::VehiclePropValue *val = msg.add_value();
-                populateProtoVehiclePropValue(val, &propValue);
-                msg.set_status(emulator::RESULT_OK);
-                msg.set_msg_type(emulator::SET_PROPERTY_ASYNC);
-                txMsg(msg);
-            }
-            break;
-    }
-
-    return status;
-}
-
-V2_0::StatusCode DefaultVehicleHal::addCustomProperty(int32_t property,
-    std::unique_ptr<CustomVehiclePropertyHandler>&& handler) {
-    mProps[std::make_pair(property, 0)] = std::move(handler);
-    ALOGW("%s: Added custom property: propId = 0x%x", __func__, property);
-    return StatusCode::OK;
-}
-
-// Parse supported properties list and generate vector of property values to hold current values.
-void DefaultVehicleHal::onCreate() {
-    // Initialize member variables
-    mExit = 0;
-
-    for (auto& prop : kHvacPowerProperties) {
-        mHvacPowerProps.insert(prop);
-    }
-
-    // Get the list of configurations supported by this HAL
-    std::vector<VehiclePropConfig> configs = listProperties();
-
-    for (auto& cfg : configs) {
-        VehiclePropertyType propType = getPropType(cfg.prop);
-        int32_t supportedAreas = cfg.supportedAreas;
-        int32_t vecSize;
-
-        // Set the vector size based on property type
-        switch (propType) {
-        case VehiclePropertyType::BOOLEAN:
-        case VehiclePropertyType::INT32:
-        case VehiclePropertyType::INT64:
-        case VehiclePropertyType::FLOAT:
-            vecSize = 1;
-            break;
-        case VehiclePropertyType::INT32_VEC:
-        case VehiclePropertyType::FLOAT_VEC:
-        case VehiclePropertyType::BYTES:
-            // TODO:  Add proper support for these types
-            vecSize = 1;
-            break;
-        case VehiclePropertyType::STRING:
-            // Require individual handling
-            vecSize = 0;
-            break;
-        case VehiclePropertyType::COMPLEX:
-            switch (cfg.prop) {
-            default:
-                // Need to handle each complex property separately
-                break;
-            }
-            continue;
-        default:
-            ALOGE("%s: propType=0x%x not found", __func__, propType);
-            vecSize = 0;
-            break;
-        }
-
-        //  A global property will have supportedAreas = 0
-        if (getPropArea(cfg.prop) == VehicleArea::GLOBAL) {
-            supportedAreas = 0;
-        }
-
-        // This loop is a do-while so it executes at least once to handle global properties
-        do {
-            int32_t curArea = supportedAreas;
-
-            // Clear the right-most bit of supportedAreas
-            supportedAreas &= supportedAreas - 1;
-
-            // Set curArea to the previously cleared bit
-            curArea ^= supportedAreas;
-
-            // Create a separate instance for each individual zone
-            std::unique_ptr<VehiclePropValue> prop = createVehiclePropValue(propType, vecSize);
-            prop->areaId = curArea;
-            prop->prop = cfg.prop;
-            setDefaultValue(prop.get());
-            std::unique_ptr<CustomVehiclePropertyHandler> handler;
-            handler.reset(new StoredValueCustomVehiclePropertyHandler());
-            handler->set(*prop);
-            mProps[std::make_pair(prop->prop, prop->areaId)] =
-                    std::move(handler);
-        } while (supportedAreas != 0);
-    }
-
-    // Start rx thread
-    mThread = std::thread(&DefaultVehicleHal::rxThread, this);
-}
-
-void DefaultVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
-    VehiclePropValuePtr v;
-
-    auto& pool = *getValuePool();
-
-    for (int32_t property : properties) {
-        if (isContinuousProperty(property)) {
-            // In real implementation this value should be read from sensor, random
-            // value used for testing purpose only.
-            std::lock_guard<std::mutex> lock(mPropsMutex);
-
-            VehiclePropValue *internalPropValue = getVehiclePropValueLocked(property);
-            if (internalPropValue != nullptr) {
-                v = pool.obtain(*internalPropValue);
-            }
-            if (VehiclePropertyType::FLOAT == getPropType(property)) {
-                // Just get some randomness to continuous properties to see slightly differnt values
-                // on the other end.
-                v->value.floatValues[0] = v->value.floatValues[0] + std::rand() % 5;
-            }
-        } else {
-            ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
-        }
-
-        if (v.get()) {
-            v->timestamp = elapsedRealtimeNano();
-            doHalEvent(std::move(v));
-        }
-    }
-}
-
-StatusCode DefaultVehicleHal::subscribe(int32_t property, int32_t,
-                                        float sampleRate) {
-    ALOGI("subscribe called for property: 0x%x, sampleRate: %f", property, sampleRate);
-
-    if (isContinuousProperty(property)) {
-        mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
-    }
-    return StatusCode::OK;
-}
-
-StatusCode DefaultVehicleHal::unsubscribe(int32_t property) {
-    ALOGI("%s propId: 0x%x", __func__, property);
-    if (isContinuousProperty(property)) {
-        mRecurrentTimer.unregisterRecurrentEvent(property);
-    }
-    return StatusCode::OK;
-}
-
-const VehiclePropConfig* DefaultVehicleHal::getPropConfig(int32_t propId) const {
-    auto it = mPropConfigMap.find(propId);
-    return it == mPropConfigMap.end() ? nullptr : it->second;
-}
-
-bool DefaultVehicleHal::isContinuousProperty(int32_t propId) const {
-    const VehiclePropConfig* config = getPropConfig(propId);
-    if (config == nullptr) {
-        ALOGW("Config not found for property: 0x%x", propId);
-        return false;
-    }
-    return config->changeMode == VehiclePropertyChangeMode::CONTINUOUS;
-}
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
deleted file mode 100644
index c8310b3..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * 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 android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
-
-#include <map>
-#include <memory>
-#include <sys/socket.h>
-#include <thread>
-#include <unordered_set>
-
-#include <utils/SystemClock.h>
-
-#include "CommBase.h"
-#include "VehicleHalProto.pb.h"
-
-#include <vhal_v2_0/RecurrentTimer.h>
-#include <vhal_v2_0/VehicleHal.h>
-
-#include "DefaultConfig.h"
-#include "VehicleHalProto.pb.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-class DefaultVehicleHal : public VehicleHal {
-public:
-    class CustomVehiclePropertyHandler {
-    public:
-        virtual VehiclePropValue* get() = 0;
-        virtual StatusCode set(const VehiclePropValue& propValue) = 0;
-        virtual ~CustomVehiclePropertyHandler() = default;
-    };
-
-protected:
-    class StoredValueCustomVehiclePropertyHandler :
-        public CustomVehiclePropertyHandler {
-    public:
-        VehiclePropValue* get() override {
-            return mPropValue.get();
-        }
-
-        StatusCode set(const VehiclePropValue& propValue) {
-            *mPropValue = propValue;
-            return StatusCode::OK;
-        }
-private:
-    std::unique_ptr<VehiclePropValue> mPropValue{new VehiclePropValue()};
-};
-
-public:
-  DefaultVehicleHal() : mRecurrentTimer(
-            std::bind(&DefaultVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)) {
-        for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
-            mPropConfigMap[kVehicleProperties[i].prop] = &kVehicleProperties[i];
-        }
-    }
-
-    ~DefaultVehicleHal() override {
-        // Notify thread to finish and wait for it to terminate
-        mExit = 1;
-
-        // Close emulator socket if it is open
-        mComm->stop();
-
-        mThread.join();
-    }
-
-    std::vector<VehiclePropConfig> listProperties() override {
-        return std::vector<VehiclePropConfig>(std::begin(kVehicleProperties),
-                                              std::end(kVehicleProperties));
-    }
-
-    VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
-                            StatusCode* outStatus) override;
-
-    void onCreate() override;
-
-    StatusCode set(const VehiclePropValue& propValue) override;
-
-    StatusCode subscribe(int32_t property, int32_t areas, float sampleRate) override;
-
-    StatusCode unsubscribe(int32_t property) override;
-
-    /**
-     * Add custom property information to this HAL instance.
-     *
-     * This is useful for allowing later versions of Vehicle HAL to coalesce
-     * the list of properties they support with a previous version of the HAL.
-     *
-     * @param property The identifier of the new property
-     * @param handler The object that will handle get/set requests
-     * @return OK on success, an error code on failure
-     */
-    virtual StatusCode addCustomProperty(int32_t,
-        std::unique_ptr<CustomVehiclePropertyHandler>&&);
-
-    /**
-     * Add custom property information to this HAL instance.
-     *
-     * This is useful for allowing later versions of Vehicle HAL to coalesce
-     * the list of properties they support with a previous version of the HAL.
-     *
-     * @param initialValue The initial value for the new property. This is not
-     *                     constant data, as later set() operations can change
-     *                     this value at will
-     * @return OK on success, an error code on failure
-     */
-    virtual StatusCode addCustomProperty(
-        const VehiclePropValue& initialValue) {
-        std::unique_ptr<CustomVehiclePropertyHandler> handler;
-        handler.reset(new StoredValueCustomVehiclePropertyHandler());
-        StatusCode setResponse = handler->set(initialValue);
-        if (StatusCode::OK == setResponse) {
-          return addCustomProperty(initialValue.prop,
-                                   std::move(handler));
-        } else {
-          return setResponse;
-        }
-    }
-
-private:
-    void doGetConfig(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
-    void doGetConfigAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
-    void doGetProperty(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
-    void doGetPropertyAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
-    void doSetProperty(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
-    VehiclePropValue* getVehiclePropValueLocked(int32_t propId, int32_t areaId = 0);
-    const VehiclePropConfig* getPropConfig(int32_t propId) const;
-    bool isContinuousProperty(int32_t propId) const;
-    void parseRxProtoBuf(std::vector<uint8_t>& msg);
-    void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
-                                    const VehiclePropConfig& cfg);
-    void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
-                                       const VehiclePropValue* val);
-    void setDefaultValue(VehiclePropValue* prop);
-    void rxMsg();
-    void rxThread();
-    void txMsg(emulator::EmulatorMessage& txMsg);
-    StatusCode updateProperty(const VehiclePropValue& propValue);
-
-    constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
-        return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
-    }
-
-    void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
-
-private:
-    std::map<
-        std::pair<int32_t /*VehicleProperty*/, int32_t /*areaId*/>,
-        std::unique_ptr<CustomVehiclePropertyHandler>> mProps;
-    std::atomic<int> mExit;
-    std::unordered_set<int32_t> mHvacPowerProps;
-    std::mutex mPropsMutex;
-    std::thread mThread;
-    std::unique_ptr<CommBase> mComm{nullptr};
-    RecurrentTimer mRecurrentTimer;
-    std::unordered_map<int32_t, const VehiclePropConfig*> mPropConfigMap;
-};
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
new file mode 100644
index 0000000..0ac6ada
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "DefaultVehicleHal_v2_0"
+#include <android/log.h>
+
+#include "EmulatedVehicleHal.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
+    : mPropStore(propStore),
+      mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
+      mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer,
+                                  this, std::placeholders::_1)) {
+
+    for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
+        mPropStore->registerProperty(kVehicleProperties[i].config);
+    }
+}
+
+VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
+        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
+    VehiclePropValuePtr v = nullptr;
+
+    auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
+    if (internalPropValue != nullptr) {
+        v = getValuePool()->obtain(*internalPropValue);
+    }
+
+    *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
+    return v;
+}
+
+StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
+    if (mHvacPowerProps.count(propValue.prop)) {
+        auto hvacPowerOn = mPropStore->readValueOrNull(toInt(VehicleProperty::HVAC_POWER_ON),
+                                                      toInt(VehicleAreaZone::ROW_1));
+
+        if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
+                && hvacPowerOn->value.int32Values[0] == 0) {
+            return StatusCode::NOT_AVAILABLE;
+        }
+    }
+
+    if (!mPropStore->writeValue(propValue)) {
+        return StatusCode::INVALID_ARG;
+    }
+
+    getEmulatorOrDie()->doSetValueFromClient(propValue);
+
+    return StatusCode::OK;
+}
+
+// Parse supported properties list and generate vector of property values to hold current values.
+void EmulatedVehicleHal::onCreate() {
+    for (auto& it : kVehicleProperties) {
+        VehiclePropConfig cfg = it.config;
+        int32_t supportedAreas = cfg.supportedAreas;
+
+        //  A global property will have supportedAreas = 0
+        if (isGlobalProp(cfg.prop)) {
+            supportedAreas = 0;
+        }
+
+        // This loop is a do-while so it executes at least once to handle global properties
+        do {
+            int32_t curArea = supportedAreas;
+            supportedAreas &= supportedAreas - 1;  // Clear the right-most bit of supportedAreas.
+            curArea ^= supportedAreas;  // Set curArea to the previously cleared bit.
+
+            // Create a separate instance for each individual zone
+            VehiclePropValue prop = {
+                .prop = cfg.prop,
+                .areaId = curArea,
+            };
+            if (it.initialAreaValues.size() > 0) {
+                auto valueForAreaIt = it.initialAreaValues.find(curArea);
+                if (valueForAreaIt != it.initialAreaValues.end()) {
+                    prop.value = valueForAreaIt->second;
+                } else {
+                    ALOGW("%s failed to get default value for prop 0x%x area 0x%x",
+                            __func__, cfg.prop, curArea);
+                }
+            } else {
+                prop.value = it.initialValue;
+            }
+            mPropStore->writeValue(prop);
+
+        } while (supportedAreas != 0);
+    }
+}
+
+std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties()  {
+    return mPropStore->getAllConfigs();
+}
+
+void EmulatedVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
+    VehiclePropValuePtr v;
+
+    auto& pool = *getValuePool();
+
+    for (int32_t property : properties) {
+        if (isContinuousProperty(property)) {
+            auto internalPropValue = mPropStore->readValueOrNull(property);
+            if (internalPropValue != nullptr) {
+                v = pool.obtain(*internalPropValue);
+            }
+        } else {
+            ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
+        }
+
+        if (v.get()) {
+            v->timestamp = elapsedRealtimeNano();
+            doHalEvent(std::move(v));
+        }
+    }
+}
+
+StatusCode EmulatedVehicleHal::subscribe(int32_t property, int32_t,
+                                        float sampleRate) {
+    ALOGI("%s propId: 0x%x, sampleRate: %f", __func__, property, sampleRate);
+
+    if (isContinuousProperty(property)) {
+        mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
+    }
+    return StatusCode::OK;
+}
+
+StatusCode EmulatedVehicleHal::unsubscribe(int32_t property) {
+    ALOGI("%s propId: 0x%x", __func__, property);
+    if (isContinuousProperty(property)) {
+        mRecurrentTimer.unregisterRecurrentEvent(property);
+    }
+    return StatusCode::OK;
+}
+
+bool EmulatedVehicleHal::isContinuousProperty(int32_t propId) const {
+    const VehiclePropConfig* config = mPropStore->getConfigOrNull(propId);
+    if (config == nullptr) {
+        ALOGW("Config not found for property: 0x%x", propId);
+        return false;
+    }
+    return config->changeMode == VehiclePropertyChangeMode::CONTINUOUS;
+}
+
+bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
+    if (mPropStore->writeValue(propValue)) {
+        doHalEvent(getValuePool()->obtain(propValue));
+        return true;
+    } else {
+        return false;
+    }
+}
+
+std::vector<VehiclePropValue> EmulatedVehicleHal::getAllProperties() const  {
+    return mPropStore->readAllValues();
+}
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
new file mode 100644
index 0000000..e0874e2
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -0,0 +1,88 @@
+/*
+ * 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 android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
+
+#include <map>
+#include <memory>
+#include <sys/socket.h>
+#include <thread>
+#include <unordered_set>
+
+#include <utils/SystemClock.h>
+
+#include "VehicleHalProto.pb.h"
+
+#include <vhal_v2_0/RecurrentTimer.h>
+#include <vhal_v2_0/VehicleHal.h>
+#include "vhal_v2_0/VehiclePropertyStore.h"
+
+#include "DefaultConfig.h"
+#include "VehicleHalProto.pb.h"
+#include "VehicleEmulator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+/** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
+class EmulatedVehicleHal : public EmulatedVehicleHalIface {
+public:
+    EmulatedVehicleHal(VehiclePropertyStore* propStore);
+    ~EmulatedVehicleHal() = default;
+
+    //  Methods from VehicleHal
+    void onCreate() override;
+    std::vector<VehiclePropConfig> listProperties() override;
+    VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
+                            StatusCode* outStatus) override;
+    StatusCode set(const VehiclePropValue& propValue) override;
+    StatusCode subscribe(int32_t property, int32_t areas, float sampleRate) override;
+    StatusCode unsubscribe(int32_t property) override;
+
+    //  Methods from EmulatedVehicleHalIface
+    bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
+    std::vector<VehiclePropValue> getAllProperties() const override;
+
+private:
+    constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
+        return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
+    }
+
+    void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
+    bool isContinuousProperty(int32_t propId) const;
+
+private:
+    VehiclePropertyStore* mPropStore;
+    std::unordered_set<int32_t> mHvacPowerProps;
+    RecurrentTimer mRecurrentTimer;
+};
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
index 6f219fa..2b15aa3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
 #include <android/log.h>
+#include <log/log.h>
 #include <system/qemu_pipe.h>
 
 #include "PipeComm.h"
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
index a3ef4b1..42c1c78 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
 #include <android/log.h>
+#include <log/log.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
new file mode 100644
index 0000000..38cb743
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
@@ -0,0 +1,360 @@
+/*
+ * 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 "VehicleEmulator_v2_0"
+#include <android/log.h>
+
+#include <algorithm>
+#include <android-base/properties.h>
+#include <utils/SystemClock.h>
+
+#include <vhal_v2_0/VehicleUtils.h>
+
+#include "PipeComm.h"
+#include "SocketComm.h"
+
+#include "VehicleEmulator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+std::unique_ptr<CommBase> CommFactory::create() {
+    bool isEmulator = android::base::GetBoolProperty("ro.kernel.qemu", false);
+
+    if (isEmulator) {
+        return std::make_unique<PipeComm>();
+    } else {
+        return std::make_unique<SocketComm>();
+    }
+}
+
+VehicleEmulator::~VehicleEmulator() {
+    mExit = true;   // Notify thread to finish and wait for it to terminate.
+    mComm->stop();  // Close emulator socket if it is open.
+    if (mThread.joinable()) mThread.join();
+}
+
+void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) {
+    emulator::EmulatorMessage msg;
+    emulator::VehiclePropValue *val = msg.add_value();
+    populateProtoVehiclePropValue(val, &propValue);
+    msg.set_status(emulator::RESULT_OK);
+    msg.set_msg_type(emulator::SET_PROPERTY_ASYNC);
+    txMsg(msg);
+}
+
+void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage& rxMsg,
+                                  VehicleEmulator::EmulatorMessage& respMsg) {
+    std::vector<VehiclePropConfig> configs = mHal->listProperties();
+    emulator::VehiclePropGet getProp = rxMsg.prop(0);
+
+    respMsg.set_msg_type(emulator::GET_CONFIG_RESP);
+    respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
+
+    for (auto& config : configs) {
+        // Find the config we are looking for
+        if (config.prop == getProp.prop()) {
+            emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
+            populateProtoVehicleConfig(protoCfg, config);
+            respMsg.set_status(emulator::RESULT_OK);
+            break;
+        }
+    }
+}
+
+void VehicleEmulator::doGetConfigAll(VehicleEmulator::EmulatorMessage& /* rxMsg */,
+                                     VehicleEmulator::EmulatorMessage& respMsg) {
+    std::vector<VehiclePropConfig> configs = mHal->listProperties();
+
+    respMsg.set_msg_type(emulator::GET_CONFIG_ALL_RESP);
+    respMsg.set_status(emulator::RESULT_OK);
+
+    for (auto& config : configs) {
+        emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
+        populateProtoVehicleConfig(protoCfg, config);
+    }
+}
+
+void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage& rxMsg,
+                                    VehicleEmulator::EmulatorMessage& respMsg)  {
+    int32_t areaId = 0;
+    emulator::VehiclePropGet getProp = rxMsg.prop(0);
+    int32_t propId = getProp.prop();
+    emulator::Status status = emulator::ERROR_INVALID_PROPERTY;
+
+    respMsg.set_msg_type(emulator::GET_PROPERTY_RESP);
+
+    if (getProp.has_area_id()) {
+        areaId = getProp.area_id();
+    }
+
+    {
+        VehiclePropValue request = { .prop = propId, .areaId = areaId };
+        StatusCode halStatus;
+        auto val = mHal->get(request, &halStatus);
+        if (val != nullptr) {
+            emulator::VehiclePropValue* protoVal = respMsg.add_value();
+            populateProtoVehiclePropValue(protoVal, val.get());
+            status = emulator::RESULT_OK;
+        }
+    }
+
+    respMsg.set_status(status);
+}
+
+void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage& /* rxMsg */,
+                                       VehicleEmulator::EmulatorMessage& respMsg)  {
+    respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP);
+    respMsg.set_status(emulator::RESULT_OK);
+
+    {
+        for (const auto& prop : mHal->getAllProperties()) {
+            emulator::VehiclePropValue* protoVal = respMsg.add_value();
+            populateProtoVehiclePropValue(protoVal, &prop);
+        }
+    }
+}
+
+void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage& rxMsg,
+                                    VehicleEmulator::EmulatorMessage& respMsg) {
+    emulator::VehiclePropValue protoVal = rxMsg.value(0);
+    VehiclePropValue val = {
+        .prop = protoVal.prop(),
+        .areaId = protoVal.area_id(),
+        .timestamp = elapsedRealtimeNano(),
+    };
+
+    respMsg.set_msg_type(emulator::SET_PROPERTY_RESP);
+
+    // Copy value data if it is set.  This automatically handles complex data types if needed.
+    if (protoVal.has_string_value()) {
+        val.value.stringValue = protoVal.string_value().c_str();
+    }
+
+    if (protoVal.has_bytes_value()) {
+        val.value.bytes = std::vector<uint8_t> { protoVal.bytes_value().begin(),
+                                                 protoVal.bytes_value().end() };
+    }
+
+    if (protoVal.int32_values_size() > 0) {
+        val.value.int32Values = std::vector<int32_t> { protoVal.int32_values().begin(),
+                                                       protoVal.int32_values().end() };
+    }
+
+    if (protoVal.int64_values_size() > 0) {
+        val.value.int64Values = std::vector<int64_t> { protoVal.int64_values().begin(),
+                                                       protoVal.int64_values().end() };
+    }
+
+    if (protoVal.float_values_size() > 0) {
+        val.value.floatValues = std::vector<float> { protoVal.float_values().begin(),
+                                                     protoVal.float_values().end() };
+    }
+
+    bool halRes = mHal->setPropertyFromVehicle(val);
+    respMsg.set_status(halRes ? emulator::RESULT_OK : emulator::ERROR_INVALID_PROPERTY);
+}
+
+void VehicleEmulator::txMsg(emulator::EmulatorMessage& txMsg) {
+    int numBytes = txMsg.ByteSize();
+    std::vector<uint8_t> msg(static_cast<size_t>(numBytes));
+
+    if (!txMsg.SerializeToArray(msg.data(), static_cast<int32_t>(msg.size()))) {
+        ALOGE("%s: SerializeToString failed!", __func__);
+        return;
+    }
+
+    if (mExit) {
+        ALOGW("%s: unable to transmit a message, connection closed", __func__);
+        return;
+    }
+
+    // Send the message
+    int retVal = mComm->write(msg);
+    if (retVal < 0) {
+        ALOGE("%s: Failed to tx message: retval=%d, errno=%d", __func__, retVal, errno);
+    }
+}
+
+void VehicleEmulator::parseRxProtoBuf(std::vector<uint8_t>& msg) {
+    emulator::EmulatorMessage rxMsg;
+    emulator::EmulatorMessage respMsg;
+
+    if (rxMsg.ParseFromArray(msg.data(), static_cast<int32_t>(msg.size()))) {
+        switch (rxMsg.msg_type()) {
+            case emulator::GET_CONFIG_CMD:
+                doGetConfig(rxMsg, respMsg);
+                break;
+            case emulator::GET_CONFIG_ALL_CMD:
+                doGetConfigAll(rxMsg, respMsg);
+                break;
+            case emulator::GET_PROPERTY_CMD:
+                doGetProperty(rxMsg, respMsg);
+                break;
+            case emulator::GET_PROPERTY_ALL_CMD:
+                doGetPropertyAll(rxMsg, respMsg);
+                break;
+            case emulator::SET_PROPERTY_CMD:
+                doSetProperty(rxMsg, respMsg);
+                break;
+            default:
+                ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
+                respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD);
+                break;
+        }
+
+        // Send the reply
+        txMsg(respMsg);
+    } else {
+        ALOGE("%s: ParseFromString() failed. msgSize=%d", __func__, static_cast<int>(msg.size()));
+    }
+}
+
+void VehicleEmulator::populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
+                                                 const VehiclePropConfig& cfg) {
+    protoCfg->set_prop(cfg.prop);
+    protoCfg->set_access(toInt(cfg.access));
+    protoCfg->set_change_mode(toInt(cfg.changeMode));
+    protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
+
+    if (!isGlobalProp(cfg.prop)) {
+        protoCfg->set_supported_areas(cfg.supportedAreas);
+    }
+
+    for (auto& configElement : cfg.configArray) {
+        protoCfg->add_config_array(configElement);
+    }
+
+    if (cfg.configString.size() > 0) {
+        protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
+    }
+
+    // Populate the min/max values based on property type
+    switch (getPropType(cfg.prop)) {
+        case VehiclePropertyType::STRING:
+        case VehiclePropertyType::BOOLEAN:
+        case VehiclePropertyType::INT32_VEC:
+        case VehiclePropertyType::FLOAT_VEC:
+        case VehiclePropertyType::BYTES:
+        case VehiclePropertyType::COMPLEX:
+            // Do nothing.  These types don't have min/max values
+            break;
+        case VehiclePropertyType::INT64:
+            if (cfg.areaConfigs.size() > 0) {
+                emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
+                aCfg->set_min_int64_value(cfg.areaConfigs[0].minInt64Value);
+                aCfg->set_max_int64_value(cfg.areaConfigs[0].maxInt64Value);
+            }
+            break;
+        case VehiclePropertyType::FLOAT:
+            if (cfg.areaConfigs.size() > 0) {
+                emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
+                aCfg->set_min_float_value(cfg.areaConfigs[0].minFloatValue);
+                aCfg->set_max_float_value(cfg.areaConfigs[0].maxFloatValue);
+            }
+            break;
+        case VehiclePropertyType::INT32:
+            if (cfg.areaConfigs.size() > 0) {
+                emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
+                aCfg->set_min_int32_value(cfg.areaConfigs[0].minInt32Value);
+                aCfg->set_max_int32_value(cfg.areaConfigs[0].maxInt32Value);
+            }
+            break;
+        default:
+            ALOGW("%s: Unknown property type:  0x%x", __func__, toInt(getPropType(cfg.prop)));
+            break;
+    }
+
+    protoCfg->set_min_sample_rate(cfg.minSampleRate);
+    protoCfg->set_max_sample_rate(cfg.maxSampleRate);
+}
+
+void VehicleEmulator::populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
+                                                    const VehiclePropValue* val) {
+    protoVal->set_prop(val->prop);
+    protoVal->set_value_type(toInt(getPropType(val->prop)));
+    protoVal->set_timestamp(val->timestamp);
+    protoVal->set_area_id(val->areaId);
+
+    // Copy value data if it is set.
+    //  - for bytes and strings, this is indicated by size > 0
+    //  - for int32, int64, and float, copy the values if vectors have data
+    if (val->value.stringValue.size() > 0) {
+        protoVal->set_string_value(val->value.stringValue.c_str(), val->value.stringValue.size());
+    }
+
+    if (val->value.bytes.size() > 0) {
+        protoVal->set_bytes_value(val->value.bytes.data(), val->value.bytes.size());
+    }
+
+    for (auto& int32Value : val->value.int32Values) {
+        protoVal->add_int32_values(int32Value);
+    }
+
+    for (auto& int64Value : val->value.int64Values) {
+        protoVal->add_int64_values(int64Value);
+    }
+
+    for (auto& floatValue : val->value.floatValues) {
+        protoVal->add_float_values(floatValue);
+    }
+}
+
+void VehicleEmulator::rxMsg() {
+    while (!mExit) {
+        std::vector<uint8_t> msg = mComm->read();
+
+        if (msg.size() > 0) {
+            // Received a message.
+            parseRxProtoBuf(msg);
+        } else {
+            // This happens when connection is closed
+            ALOGD("%s: msgSize=%zu", __func__, msg.size());
+            break;
+        }
+    }
+}
+
+void VehicleEmulator::rxThread() {
+    if (mExit) return;
+
+    int retVal = mComm->open();
+    if (retVal != 0) mExit = true;
+
+    // Comms are properly opened
+    while (!mExit) {
+        retVal = mComm->connect();
+
+        if (retVal >= 0) {
+            rxMsg();
+        }
+
+        // Check every 100ms for a new connection
+        std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    }
+}
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
new file mode 100644
index 0000000..c8bcd60
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
@@ -0,0 +1,117 @@
+/*
+ * 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_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
+
+#include <log/log.h>
+#include <memory>
+#include <thread>
+#include <vector>
+
+#include "vhal_v2_0/VehicleHal.h"
+
+#include "CommBase.h"
+#include "VehicleHalProto.pb.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+class VehicleEmulator;  // Forward declaration.
+
+/** Extension of VehicleHal that used by VehicleEmulator. */
+class EmulatedVehicleHalIface : public VehicleHal {
+public:
+    virtual bool setPropertyFromVehicle(const VehiclePropValue& propValue) = 0;
+    virtual std::vector<VehiclePropValue> getAllProperties() const = 0;
+
+    void registerEmulator(VehicleEmulator* emulator) {
+        ALOGI("%s, emulator: %p", __func__, emulator);
+        std::lock_guard<std::mutex> g(mEmulatorLock);
+        mEmulator = emulator;
+    }
+
+protected:
+    VehicleEmulator* getEmulatorOrDie() {
+        std::lock_guard<std::mutex> g(mEmulatorLock);
+        ALOGI("%s, emulator: %p", __func__, mEmulator);
+        assert(mEmulator != nullptr);
+        return mEmulator;
+    }
+
+private:
+    mutable std::mutex mEmulatorLock;
+    VehicleEmulator* mEmulator;
+};
+
+struct CommFactory {
+    static std::unique_ptr<CommBase> create();
+};
+
+/**
+ * Emulates vehicle by providing controlling interface from host side either through ADB or Pipe.
+ */
+class VehicleEmulator {
+public:
+    VehicleEmulator(EmulatedVehicleHalIface* hal,
+                    std::unique_ptr<CommBase> comm = CommFactory::create())
+            : mHal { hal },
+              mComm(comm.release()),
+              mThread { &VehicleEmulator::rxThread, this} {
+        mHal->registerEmulator(this);
+    }
+    virtual ~VehicleEmulator();
+
+    void doSetValueFromClient(const VehiclePropValue& propValue);
+
+private:
+    using EmulatorMessage = emulator::EmulatorMessage;
+
+    void doGetConfig(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
+    void doGetConfigAll(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
+    void doGetProperty(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
+    void doGetPropertyAll(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
+    void doSetProperty(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
+    void txMsg(emulator::EmulatorMessage& txMsg);
+    void parseRxProtoBuf(std::vector<uint8_t>& msg);
+    void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
+                                    const VehiclePropConfig& cfg);
+    void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
+                                       const VehiclePropValue* val);
+    void rxMsg();
+    void rxThread();
+
+private:
+    std::atomic<bool> mExit { false };
+    EmulatedVehicleHalIface* mHal;
+    std::unique_ptr<CommBase> mComm;
+    std::thread mThread;
+};
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
diff --git a/automotive/vehicle/2.1/default/Android.mk b/automotive/vehicle/2.1/default/Android.mk
index 51cb146..32ec456 100644
--- a/automotive/vehicle/2.1/default/Android.mk
+++ b/automotive/vehicle/2.1/default/Android.mk
@@ -49,7 +49,7 @@
 
 LOCAL_MODULE:= $(vhal_v2_1)-default-impl-lib
 LOCAL_SRC_FILES:= \
-    impl/vhal_v2_1/DefaultVehicleHal.cpp \
+    impl/vhal_v2_1/EmulatedVehicleHal.cpp \
 
 LOCAL_C_INCLUDES := \
     $(LOCAL_PATH)/impl/vhal_v2_1 \
diff --git a/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h b/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
index 945e3e0..6c44626 100644
--- a/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
+++ b/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
@@ -55,8 +55,7 @@
     const std::vector<uint8_t>& getSensorsBitmask() const;
 
     // Given a stringValue, fill in a VehiclePropValue
-    void fillPropValue(V2_0::VehiclePropValue *propValue,
-            std::string dtc) const;
+    void fillPropValue(const std::string& dtc, V2_0::VehiclePropValue *propValue) const;
 
 private:
     class BitmaskInVector {
diff --git a/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp b/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
index b07717b..f4c63a9 100644
--- a/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
+++ b/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
@@ -99,8 +99,8 @@
     return mSensorsBitmask.getBitmask();
 }
 
-void Obd2SensorStore::fillPropValue(V2_0::VehiclePropValue *propValue,
-                                    std::string dtc) const {
+void Obd2SensorStore::fillPropValue(const std::string& dtc,
+                                    V2_0::VehiclePropValue *propValue) const {
     propValue->timestamp = elapsedRealtimeNano();
     propValue->value.int32Values = getIntegerSensors();
     propValue->value.floatValues = getFloatSensors();
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
index 6bdec59..aa9aa3c 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
@@ -28,41 +28,50 @@
 
 namespace impl {
 
+// Some handy constants to avoid conversions from enum to int.
+constexpr int OBD2_LIVE_FRAME = (int) V2_1::VehicleProperty::OBD2_LIVE_FRAME;
+constexpr int OBD2_FREEZE_FRAME = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME;
+constexpr int OBD2_FREEZE_FRAME_INFO = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO;
+constexpr int OBD2_FREEZE_FRAME_CLEAR = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR;
+constexpr int VEHICLE_MAP_SERVICE = (int) V2_1::VehicleProperty::VEHICLE_MAP_SERVICE;
+constexpr int WHEEL_TICK = (int) V2_1::VehicleProperty::WHEEL_TICK;
+
+
 const V2_0::VehiclePropConfig kVehicleProperties[] = {
     {
-        .prop = V2_0::toInt(V2_1::VehicleProperty::WHEEL_TICK),
+        .prop = WHEEL_TICK,
         .access = V2_0::VehiclePropertyAccess::READ,
         .changeMode = V2_0::VehiclePropertyChangeMode::CONTINUOUS,
     },
 
     {
-        .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME),
+        .prop = OBD2_LIVE_FRAME,
         .access = V2_0::VehiclePropertyAccess::READ,
         .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
         .configArray = {0,0}
     },
 
     {
-        .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME),
+        .prop = OBD2_FREEZE_FRAME,
         .access = V2_0::VehiclePropertyAccess::READ,
         .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
         .configArray = {0,0}
     },
 
     {
-        .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO),
+        .prop = OBD2_FREEZE_FRAME_INFO,
         .access = V2_0::VehiclePropertyAccess::READ,
         .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
     },
 
     {
-        .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR),
+        .prop = OBD2_FREEZE_FRAME_CLEAR,
         .access = V2_0::VehiclePropertyAccess::WRITE,
         .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
     },
 
     {
-        .prop = V2_0::toInt(VehicleProperty::VEHICLE_MAP_SERVICE),
+        .prop = VEHICLE_MAP_SERVICE,
         .access = V2_0::VehiclePropertyAccess::READ_WRITE,
         .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
     }
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h
deleted file mode 100644
index af21138..0000000
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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 android_hardware_automotive_vehicle_V2_1_impl_DefaultVehicleHal_H_
-#define android_hardware_automotive_vehicle_V2_1_impl_DefaultVehicleHal_H_
-
-#include <memory>
-
-#include <utils/SystemClock.h>
-
-#include <vhal_v2_0/VehicleHal.h>
-#include <vhal_v2_0/DefaultVehicleHal.h>
-#include <vhal_v2_1/Obd2SensorStore.h>
-
-#include "DefaultConfig.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_1 {
-
-namespace impl {
-
-using namespace std::placeholders;
-
-class DefaultVehicleHal : public V2_0::VehicleHal {
-public:
-    DefaultVehicleHal(V2_0::impl::DefaultVehicleHal* vhal20) :
-          mVehicleHal20(vhal20) {}
-
-    std::vector<V2_0::VehiclePropConfig> listProperties() override {
-        std::vector<V2_0::VehiclePropConfig> propConfigs(mVehicleHal20->listProperties());
-
-        // Join Vehicle Hal 2.0 and 2.1 configs.
-        propConfigs.insert(propConfigs.end(),
-                           std::begin(kVehicleProperties),
-                           std::end(kVehicleProperties));
-
-        return propConfigs;
-    }
-
-    VehiclePropValuePtr get(const V2_0::VehiclePropValue& requestedPropValue,
-                            V2_0::StatusCode* outStatus) override;
-
-    V2_0::StatusCode set(const V2_0::VehiclePropValue& propValue) override;
-
-    V2_0::StatusCode subscribe(int32_t property,
-                               int32_t areas,
-                               float sampleRate) override {
-        return mVehicleHal20->subscribe(property, areas, sampleRate);
-    }
-
-    V2_0::StatusCode unsubscribe(int32_t property) override {
-        return mVehicleHal20->unsubscribe(property);
-    }
-
-    void onCreate() override;
-
-private:
-    void initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig,
-        V2_0::VehiclePropValue* liveObd2Frame);
-    void initObd2FreezeFrame(V2_0::VehiclePropConfig& propConfig);
-    V2_0::StatusCode fillObd2FreezeFrame(const V2_0::VehiclePropValue& requestedPropValue,
-            V2_0::VehiclePropValue* v);
-    V2_0::StatusCode fillObd2DtcInfo(V2_0::VehiclePropValue *v);
-    V2_0::StatusCode clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue);
-
-private:
-    V2_0::impl::DefaultVehicleHal* mVehicleHal20;
-    std::vector<std::unique_ptr<V2_0::VehiclePropValue>> mFreezeObd2Frames;
-};
-
-}  // impl
-
-}  // namespace V2_1
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
similarity index 63%
rename from automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
rename to automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
index b147ce7..4dceae0 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
@@ -17,11 +17,12 @@
 #define LOG_TAG "DefaultVehicleHal_v2_1"
 #include <android/log.h>
 
-#include <algorithm>
+#include <log/log.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
+#include <algorithm>
 
-#include "DefaultVehicleHal.h"
+#include "EmulatedVehicleHal.h"
 #include "VehicleHalProto.pb.h"
 
 #define DEBUG_SOCKET    (33452)
@@ -120,118 +121,103 @@
     return sensorStore;
 }
 
-void DefaultVehicleHal::initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig,
-    V2_0::VehiclePropValue* liveObd2Frame) {
-    auto sensorStore = fillDefaultObd2Frame(propConfig.configArray[0],
-            propConfig.configArray[1]);
-    sensorStore->fillPropValue(liveObd2Frame, "");
-    liveObd2Frame->prop = V2_0::toInt(VehicleProperty::OBD2_LIVE_FRAME);
+void EmulatedVehicleHal::initObd2LiveFrame(const V2_0::VehiclePropConfig& propConfig) {
+    auto liveObd2Frame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
+    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+                                            static_cast<size_t>(propConfig.configArray[1]));
+    sensorStore->fillPropValue("", liveObd2Frame.get());
+    liveObd2Frame->prop = OBD2_LIVE_FRAME;
+
+    mPropStore->writeValue(*liveObd2Frame);
 }
 
-void DefaultVehicleHal::initObd2FreezeFrame(V2_0::VehiclePropConfig& propConfig) {
-    auto sensorStore = fillDefaultObd2Frame(propConfig.configArray[0],
-            propConfig.configArray[1]);
+void EmulatedVehicleHal::initObd2FreezeFrame(const V2_0::VehiclePropConfig& propConfig) {
+    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+                                            static_cast<size_t>(propConfig.configArray[1]));
 
-    mFreezeObd2Frames.push_back(
-            createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX,0));
-    mFreezeObd2Frames.push_back(
-            createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX,0));
-    mFreezeObd2Frames.push_back(
-            createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX,0));
-
-    sensorStore->fillPropValue(mFreezeObd2Frames[0].get(), "P0070");
-    sensorStore->fillPropValue(mFreezeObd2Frames[1].get(), "P0102");
-    sensorStore->fillPropValue(mFreezeObd2Frames[2].get(), "P0123");
+    static std::vector<std::string> sampleDtcs = { "P0070", "P0102" "P0123" };
+    for (auto&& dtc : sampleDtcs) {
+        auto freezeFrame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
+        sensorStore->fillPropValue(dtc, freezeFrame.get());
+        mPropStore->writeValue(*freezeFrame);
+    }
 }
 
-template<typename Iterable>
-typename Iterable::const_iterator findPropValueAtTimestamp(
-        const Iterable& frames,
-        int64_t timestamp) {
-    return std::find_if(frames.begin(),
-            frames.end(),
-            [timestamp] (const std::unique_ptr<V2_0::VehiclePropValue>&
-                         propValue) -> bool {
-                             return propValue->timestamp == timestamp;
-            });
-}
-
-V2_0::StatusCode DefaultVehicleHal::fillObd2FreezeFrame(
+V2_0::StatusCode EmulatedVehicleHal::fillObd2FreezeFrame(
         const V2_0::VehiclePropValue& requestedPropValue,
-        V2_0::VehiclePropValue* v) {
+        V2_0::VehiclePropValue* outValue) {
     if (requestedPropValue.value.int64Values.size() != 1) {
         ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
         return V2_0::StatusCode::INVALID_ARG;
     }
     auto timestamp = requestedPropValue.value.int64Values[0];
-    auto freezeFrameIter = findPropValueAtTimestamp(mFreezeObd2Frames,
-            timestamp);
-    if(mFreezeObd2Frames.end() == freezeFrameIter) {
+    auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
+    if(freezeFrame == nullptr) {
         ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
         return V2_0::StatusCode::INVALID_ARG;
     }
-    const auto& freezeFrame = *freezeFrameIter;
-    v->prop = V2_0::toInt(VehicleProperty::OBD2_FREEZE_FRAME);
-    v->value.int32Values = freezeFrame->value.int32Values;
-    v->value.floatValues = freezeFrame->value.floatValues;
-    v->value.bytes = freezeFrame->value.bytes;
-    v->value.stringValue = freezeFrame->value.stringValue;
-    v->timestamp = freezeFrame->timestamp;
+    outValue->prop = OBD2_FREEZE_FRAME;
+    outValue->value.int32Values = freezeFrame->value.int32Values;
+    outValue->value.floatValues = freezeFrame->value.floatValues;
+    outValue->value.bytes = freezeFrame->value.bytes;
+    outValue->value.stringValue = freezeFrame->value.stringValue;
+    outValue->timestamp = freezeFrame->timestamp;
     return V2_0::StatusCode::OK;
 }
 
-V2_0::StatusCode DefaultVehicleHal::clearObd2FreezeFrames(
-    const V2_0::VehiclePropValue& propValue) {
+V2_0::StatusCode EmulatedVehicleHal::clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue) {
     if (propValue.value.int64Values.size() == 0) {
-        mFreezeObd2Frames.clear();
+        mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
         return V2_0::StatusCode::OK;
     } else {
         for(int64_t timestamp: propValue.value.int64Values) {
-            auto freezeFrameIter = findPropValueAtTimestamp(mFreezeObd2Frames,
-                    timestamp);
-            if(mFreezeObd2Frames.end() == freezeFrameIter) {
+            auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
+            if(freezeFrame == nullptr) {
                 ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
                 return V2_0::StatusCode::INVALID_ARG;
             }
-            mFreezeObd2Frames.erase(freezeFrameIter);
+            mPropStore->removeValue(*freezeFrame);
         }
     }
     return V2_0::StatusCode::OK;
 }
 
-V2_0::StatusCode DefaultVehicleHal::fillObd2DtcInfo(V2_0::VehiclePropValue* v) {
+V2_0::StatusCode EmulatedVehicleHal::fillObd2DtcInfo(V2_0::VehiclePropValue* outValue) {
     std::vector<int64_t> timestamps;
-    for(const auto& freezeFrame: mFreezeObd2Frames) {
-        timestamps.push_back(freezeFrame->timestamp);
+    for(const auto& freezeFrame: mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
+        timestamps.push_back(freezeFrame.timestamp);
     }
-    v->value.int64Values = timestamps;
+    outValue->value.int64Values = timestamps;
     return V2_0::StatusCode::OK;
 }
 
-void DefaultVehicleHal::onCreate() {
-    mVehicleHal20->init(getValuePool(),
-                        std::bind(&DefaultVehicleHal::doHalEvent, this, _1),
-                        std::bind(&DefaultVehicleHal::doHalPropertySetError, this, _1, _2, _3));
+void EmulatedVehicleHal::onCreate() {
+    V2_0::impl::EmulatedVehicleHal::onCreate();
 
-    std::vector<V2_0::VehiclePropConfig> configs = listProperties();
-    for (auto& cfg : configs) {
-        switch(cfg.prop) {
-            case V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME): {
-                auto liveObd2Frame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
-                initObd2LiveFrame(cfg, liveObd2Frame.get());
-                mVehicleHal20->addCustomProperty(*liveObd2Frame);
+    initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
+    initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
+}
+
+void EmulatedVehicleHal::initStaticConfig() {
+    for (auto&& cfg = std::begin(kVehicleProperties); cfg != std::end(kVehicleProperties); ++cfg) {
+        V2_0::VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
+
+        switch (cfg->prop) {
+            case OBD2_FREEZE_FRAME: {
+                tokenFunction = [] (const V2_0::VehiclePropValue& propValue) {
+                    return propValue.timestamp;
+                };
+                break;
             }
-                break;
-            case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME):
-                initObd2FreezeFrame(cfg);
-                break;
             default:
                 break;
         }
+
+        mPropStore->registerProperty(*cfg, tokenFunction);
     }
 }
 
-DefaultVehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
+EmulatedVehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
         const V2_0::VehiclePropValue& requestedPropValue,
         V2_0::StatusCode* outStatus) {
 
@@ -240,34 +226,30 @@
     auto& pool = *getValuePool();
 
     switch (propId) {
-    case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME):
+    case OBD2_FREEZE_FRAME:
         v = pool.obtainComplex();
         *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
         return v;
-    case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO):
+    case OBD2_FREEZE_FRAME_INFO:
         v = pool.obtainComplex();
         *outStatus = fillObd2DtcInfo(v.get());
         return v;
     default:
-        return mVehicleHal20->get(requestedPropValue, outStatus);
+        return V2_0::impl::EmulatedVehicleHal::get(requestedPropValue, outStatus);
     }
 }
 
-V2_0::StatusCode DefaultVehicleHal::set(
-        const V2_0::VehiclePropValue& propValue) {
-
+V2_0::StatusCode EmulatedVehicleHal::set(const V2_0::VehiclePropValue& propValue) {
     auto propId = propValue.prop;
     switch (propId) {
-    case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR):
+    case OBD2_FREEZE_FRAME_CLEAR:
         return clearObd2FreezeFrames(propValue);
-        break;
-    case V2_0::toInt(V2_1::VehicleProperty::VEHICLE_MAP_SERVICE):
+    case VEHICLE_MAP_SERVICE:
         // Placeholder for future implementation of VMS property in the default hal. For now, just
         // returns OK; otherwise, hal clients crash with property not supported.
         return V2_0::StatusCode::OK;
-        break;
     default:
-        return mVehicleHal20->set(propValue);
+        return V2_0::impl::EmulatedVehicleHal::set(propValue);
     }
 }
 
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h
new file mode 100644
index 0000000..7cc3b79
--- /dev/null
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h
@@ -0,0 +1,77 @@
+/*
+ * 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 android_hardware_automotive_vehicle_V2_1_impl_EmulatedVehicleHal_H_
+#define android_hardware_automotive_vehicle_V2_1_impl_EmulatedVehicleHal_H_
+
+#include <memory>
+
+#include <utils/SystemClock.h>
+
+#include <vhal_v2_0/EmulatedVehicleHal.h>
+#include <vhal_v2_0/VehicleHal.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+#include <vhal_v2_1/Obd2SensorStore.h>
+
+#include "DefaultConfig.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_1 {
+
+namespace impl {
+
+using namespace std::placeholders;
+
+class EmulatedVehicleHal : public V2_0::impl::EmulatedVehicleHal {
+public:
+    EmulatedVehicleHal(V2_0::VehiclePropertyStore* propStore)
+        : V2_0::impl::EmulatedVehicleHal(propStore), mPropStore(propStore) {
+        initStaticConfig();
+    }
+
+    VehiclePropValuePtr get(const V2_0::VehiclePropValue& requestedPropValue,
+                            V2_0::StatusCode* outStatus) override;
+
+    V2_0::StatusCode set(const V2_0::VehiclePropValue& propValue) override;
+
+    void onCreate() override;
+
+private:
+    void initStaticConfig();
+    void initObd2LiveFrame(const V2_0::VehiclePropConfig& propConfig);
+    void initObd2FreezeFrame(const V2_0::VehiclePropConfig& propConfig);
+    V2_0::StatusCode fillObd2FreezeFrame(const V2_0::VehiclePropValue& requestedPropValue,
+                                        V2_0::VehiclePropValue* outValue);
+    V2_0::StatusCode fillObd2DtcInfo(V2_0::VehiclePropValue *outValue);
+    V2_0::StatusCode clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue);
+
+private:
+    V2_0::VehiclePropertyStore* mPropStore;
+};
+
+}  // impl
+
+}  // namespace V2_1
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
diff --git a/automotive/vehicle/2.1/default/service.cpp b/automotive/vehicle/2.1/default/service.cpp
index 0844622..4873279 100644
--- a/automotive/vehicle/2.1/default/service.cpp
+++ b/automotive/vehicle/2.1/default/service.cpp
@@ -23,9 +23,10 @@
 #include <android/hardware/automotive/vehicle/2.1/IVehicle.h>
 
 #include <vhal_v2_0/VehicleHalManager.h>
-#include <vhal_v2_0/DefaultVehicleHal.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+#include <vhal_v2_0/EmulatedVehicleHal.h>
 
-#include <vhal_v2_1/DefaultVehicleHal.h>
+#include <vhal_v2_1/EmulatedVehicleHal.h>
 
 using namespace android;
 using namespace android::hardware;
@@ -80,10 +81,10 @@
 };
 
 int main(int /* argc */, char* /* argv */ []) {
-    auto halImpl20 = std::make_unique<V2_0::impl::DefaultVehicleHal>();
-    auto halImpl21 = std::make_unique<V2_1::impl::DefaultVehicleHal>(halImpl20.get());
-
-    auto vehicleManager = std::make_unique<V2_0::VehicleHalManager>(halImpl21.get());
+    auto store = std::make_unique<V2_0::VehiclePropertyStore>();
+    auto hal = std::make_unique<V2_1::impl::EmulatedVehicleHal>(store.get());
+    auto emulator = std::make_unique<V2_0::impl::VehicleEmulator>(hal.get());
+    auto vehicleManager = std::make_unique<V2_0::VehicleHalManager>(hal.get());
 
     Vehicle_V2_1 vehicle21(vehicleManager.get());
 
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
index 5b00675..4f5aaf9 100644
--- a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
@@ -79,7 +79,7 @@
         case -28: return RequestStatus::SYS_ENOSPC;
         case -110: return RequestStatus::SYS_ETIMEDOUT;
         default:
-            ALOGE("An unknown error returned from fingerprint vendor library");
+            ALOGE("An unknown error returned from fingerprint vendor library: %d", error);
             return RequestStatus::SYS_UNKNOWN;
     }
 }
diff --git a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
index 8545d2f..0f76c39 100644
--- a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
+++ b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
@@ -2,3 +2,4 @@
     class hal
     user bluetooth
     group bluetooth
+    writepid /dev/stune/foreground/tasks
diff --git a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
index 9789ee6..f48a95d 100644
--- a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
+++ b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
@@ -30,6 +30,8 @@
 using ::android::hardware::hidl_string;
 using ::android::hardware::Return;
 using ::android::sp;
+using std::string;
+using std::vector;
 
 // The main test class for the Boot HIDL HAL.
 class BootHidlTest : public ::testing::VtsHalHidlTargetTestBase {
@@ -83,7 +85,7 @@
   {
     // Restore original flags to avoid problems on reboot
     CommandResult cr;
-    Return <void> result = boot->markBootSuccessful(generate_callback(&cr));
+    Return<void> result = boot->markBootSuccessful(generate_callback(&cr));
     EXPECT_TRUE(result.isOk());
     EXPECT_TRUE(cr.success);
   }
@@ -151,22 +153,21 @@
 
 // Sanity check Boot::getSuffix() on good and bad inputs.
 TEST_F(BootHidlTest, GetSuffix) {
-  const char *suffixPtr;
-  auto cb = [&](hidl_string suffix) { suffixPtr = suffix.c_str(); };
-  for (Slot i = 0; i < 2; i++) {
-    CommandResult cr;
-    Return<void> result = boot->getSuffix(i, cb);
-    EXPECT_TRUE(result.isOk());
-    char correctSuffix[3];
-    snprintf(correctSuffix, sizeof(correctSuffix), "_%c", 'a' + i);
-    ASSERT_EQ(0, strcmp(suffixPtr, correctSuffix));
-  }
-  {
-    char emptySuffix[] = "";
-    Return<void> result = boot->getSuffix(boot->getNumberSlots(), cb);
-    EXPECT_TRUE(result.isOk());
-    ASSERT_EQ(0, strcmp(emptySuffix, suffixPtr));
-  }
+    string suffixStr;
+    vector<string> correctSuffixes = {"_a", "_b"};
+    auto cb = [&](hidl_string suffix) { suffixStr = suffix.c_str(); };
+    for (Slot i = 0; i < 2; i++) {
+        CommandResult cr;
+        Return<void> result = boot->getSuffix(i, cb);
+        EXPECT_TRUE(result.isOk());
+        ASSERT_EQ(0, suffixStr.compare(correctSuffixes[i]));
+    }
+    {
+        string emptySuffix = "";
+        Return<void> result = boot->getSuffix(boot->getNumberSlots(), cb);
+        EXPECT_TRUE(result.isOk());
+        ASSERT_EQ(0, suffixStr.compare(emptySuffix));
+    }
 }
 
 int main(int argc, char **argv) {
diff --git a/camera/common/1.0/default/CameraMetadata.cpp b/camera/common/1.0/default/CameraMetadata.cpp
index 44c2040..0e7ef6e 100644
--- a/camera/common/1.0/default/CameraMetadata.cpp
+++ b/camera/common/1.0/default/CameraMetadata.cpp
@@ -17,7 +17,7 @@
 // #define LOG_NDEBUG 0
 
 #define LOG_TAG "CamComm1.0-MD"
-#include <utils/Log.h>
+#include <log/log.h>
 #include <utils/Errors.h>
 
 #include "CameraMetadata.h"
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index dee2973..e22f26f 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -15,8 +15,8 @@
  */
 
 #define LOG_TAG "HandleImporter"
-#include <utils/Log.h>
 #include "HandleImporter.h"
+#include <log/log.h>
 
 namespace android {
 namespace hardware {
diff --git a/camera/common/1.0/default/VendorTagDescriptor.cpp b/camera/common/1.0/default/VendorTagDescriptor.cpp
index db884a8..bc18270 100644
--- a/camera/common/1.0/default/VendorTagDescriptor.cpp
+++ b/camera/common/1.0/default/VendorTagDescriptor.cpp
@@ -16,13 +16,13 @@
 
 #define LOG_TAG "CamComm1.0-VTDesc"
 
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/Mutex.h>
-#include <utils/Vector.h>
-#include <utils/SortedVector.h>
+#include <log/log.h>
 #include <system/camera_metadata.h>
 #include <camera_metadata_hidden.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/SortedVector.h>
+#include <utils/Vector.h>
 
 #include "VendorTagDescriptor.h"
 
diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp
index 44a108c..81e41aa 100644
--- a/camera/device/1.0/Android.bp
+++ b/camera/device/1.0/Android.bp
@@ -66,7 +66,6 @@
         "libutils",
         "libcutils",
         "android.hardware.camera.common@1.0",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
@@ -76,7 +75,6 @@
         "libhwbinder",
         "libutils",
         "android.hardware.camera.common@1.0",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
diff --git a/camera/device/1.0/ICameraDevicePreviewCallback.hal b/camera/device/1.0/ICameraDevicePreviewCallback.hal
index 4c9b517..5421981 100644
--- a/camera/device/1.0/ICameraDevicePreviewCallback.hal
+++ b/camera/device/1.0/ICameraDevicePreviewCallback.hal
@@ -17,7 +17,6 @@
 package android.hardware.camera.device@1.0;
 
 import android.hardware.camera.common@1.0::types;
-import android.hardware.graphics.allocator@2.0::types;
 import android.hardware.graphics.common@1.0::types;
 
 /**
@@ -89,7 +88,7 @@
      *
      * @return Status The status code for this operation.
      */
-    setUsage(ProducerUsage usage) generates (Status status);
+    setUsage(BufferUsage usage) generates (Status status);
 
     /**
      * Set the expected buffering mode for the preview output.
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
index 877c6e7..cb20fec 100644
--- a/camera/device/1.0/default/CameraDevice.cpp
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -15,10 +15,10 @@
  */
 
 #define LOG_TAG "CamDev@1.0-impl"
-#include <utils/Log.h>
 #include <hardware/camera.h>
 #include <hardware/gralloc1.h>
 #include <hidlmemory/mapping.h>
+#include <log/log.h>
 #include <utils/Trace.h>
 
 #include "CameraDevice_1_0.h"
@@ -30,7 +30,7 @@
 namespace V1_0 {
 namespace implementation {
 
-using ::android::hardware::graphics::allocator::V2_0::ProducerUsage;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
 
 HandleImporter& CameraDevice::sHandleImporter = HandleImporter::getInstance();
@@ -259,7 +259,7 @@
     }
 
     object->cleanUpCirculatingBuffers();
-    return getStatusT(object->mPreviewCallback->setUsage((ProducerUsage) usage));
+    return getStatusT(object->mPreviewCallback->setUsage((BufferUsage)usage));
 }
 
 int CameraDevice::sSetSwapInterval(struct preview_stream_ops *w, int interval) {
diff --git a/camera/device/3.2/Android.bp b/camera/device/3.2/Android.bp
index fd7276f..7807a85 100644
--- a/camera/device/3.2/Android.bp
+++ b/camera/device/3.2/Android.bp
@@ -66,7 +66,6 @@
         "libutils",
         "libcutils",
         "android.hardware.camera.common@1.0",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
@@ -76,7 +75,6 @@
         "libhwbinder",
         "libutils",
         "android.hardware.camera.common@1.0",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index a742335..637a1e6 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -15,7 +15,7 @@
  */
 
 #define LOG_TAG "CamDev@3.2-impl"
-#include <utils/Log.h>
+#include <log/log.h>
 
 #include <utils/Vector.h>
 #include <utils/Trace.h>
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 5b3024b..5bb53c7 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -650,7 +650,8 @@
         mVideoStreamIds.clear();
         for (const auto& stream : requestedConfiguration.streams) {
             if (stream.streamType == StreamType::OUTPUT &&
-                    stream.usage & graphics::allocator::V2_0::ConsumerUsage::VIDEO_ENCODER) {
+                stream.usage &
+                    graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
                 mVideoStreamIds.push_back(stream.id);
             }
         }
diff --git a/camera/device/3.2/default/convert.cpp b/camera/device/3.2/default/convert.cpp
index 35676df..d878deb 100644
--- a/camera/device/3.2/default/convert.cpp
+++ b/camera/device/3.2/default/convert.cpp
@@ -15,7 +15,7 @@
  */
 
 #define LOG_TAG "android.hardware.camera.device@3.2-convert-impl"
-#include <android/log.h>
+#include <log/log.h>
 
 #include "include/convert.h"
 
@@ -28,8 +28,7 @@
 
 using ::android::hardware::graphics::common::V1_0::Dataspace;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::camera::device::V3_2::ConsumerUsageFlags;
-using ::android::hardware::camera::device::V3_2::ProducerUsageFlags;
+using ::android::hardware::camera::device::V3_2::BufferUsageFlags;
 
 bool convertFromHidl(const CameraMetadata &src, const camera_metadata_t** dst) {
     if (src.size() == 0) {
@@ -78,11 +77,11 @@
     dst->overrideFormat = (PixelFormat) src->format;
     dst->maxBuffers = src->max_buffers;
     if (src->stream_type == CAMERA3_STREAM_OUTPUT) {
-        dst->consumerUsage = (ConsumerUsageFlags) 0;
-        dst->producerUsage = (ProducerUsageFlags) src->usage;
+        dst->consumerUsage = (BufferUsageFlags)0;
+        dst->producerUsage = (BufferUsageFlags)src->usage;
     } else if (src->stream_type == CAMERA3_STREAM_INPUT) {
-        dst->producerUsage = (ProducerUsageFlags) 0;
-        dst->consumerUsage = (ConsumerUsageFlags) src->usage;
+        dst->producerUsage = (BufferUsageFlags)0;
+        dst->consumerUsage = (BufferUsageFlags)src->usage;
     } else {
         //Should not reach here per current HIDL spec, but we might end up adding
         // bi-directional stream to HIDL.
diff --git a/camera/device/3.2/types.hal b/camera/device/3.2/types.hal
index 5ae7a18..1632570 100644
--- a/camera/device/3.2/types.hal
+++ b/camera/device/3.2/types.hal
@@ -16,12 +16,10 @@
 
 package android.hardware.camera.device@3.2;
 
-import android.hardware.graphics.allocator@2.0::types;
 import android.hardware.graphics.common@1.0::types;
 
 typedef vec<uint8_t> CameraMetadata;
-typedef bitfield<ProducerUsage> ProducerUsageFlags;
-typedef bitfield<ConsumerUsage> ConsumerUsageFlags;
+typedef bitfield<BufferUsage> BufferUsageFlags;
 typedef bitfield<Dataspace> DataspaceFlags;
 
 /**
@@ -255,7 +253,7 @@
      * with ILLEGAL_ARGUMENT if the combined flags cannot be supported due to
      * imcompatible buffer format, dataSpace, or other hardware limitations.
      */
-    ConsumerUsageFlags usage;
+    BufferUsageFlags usage;
 
     /**
      * A field that describes the contents of the buffer. The format and buffer
@@ -373,8 +371,8 @@
      * consumerUsage must be set. For other types, producerUsage must be set,
      * and consumerUsage must be 0.
      */
-    ProducerUsageFlags producerUsage;
-    ConsumerUsageFlags consumerUsage;
+    BufferUsageFlags producerUsage;
+    BufferUsageFlags consumerUsage;
 
     /**
      * The maximum number of buffers the HAL device may need to have dequeued at
diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp
index 1656325..d295f3e 100644
--- a/camera/provider/2.4/Android.bp
+++ b/camera/provider/2.4/Android.bp
@@ -57,7 +57,6 @@
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
@@ -69,7 +68,6 @@
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
diff --git a/camera/provider/2.4/vts/functional/CameraParameters.cpp b/camera/provider/2.4/vts/functional/CameraParameters.cpp
index 0285154..97b263b 100644
--- a/camera/provider/2.4/vts/functional/CameraParameters.cpp
+++ b/camera/provider/2.4/vts/functional/CameraParameters.cpp
@@ -16,7 +16,7 @@
 */
 
 #define LOG_TAG "CameraParams"
-#include <utils/Log.h>
+#include <log/log.h>
 
 #include <string.h>
 #include <stdlib.h>
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 74e6efe..e37f989 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -52,8 +52,8 @@
 using ::android::BufferItemConsumer;
 using ::android::Surface;
 using ::android::CameraParameters;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::graphics::allocator::V2_0::ProducerUsage;
 using ::android::hardware::camera::common::V1_0::Status;
 using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
 using ::android::hardware::camera::common::V1_0::TorchMode;
@@ -233,7 +233,7 @@
     Return<Status> setCrop(int32_t left, int32_t top,
             int32_t right, int32_t bottom) override;
 
-    Return<Status> setUsage(ProducerUsage usage) override;
+    Return<Status> setUsage(BufferUsage usage) override;
 
     Return<Status> setSwapInterval(int32_t interval) override;
 
@@ -408,7 +408,7 @@
     return mapToStatus(rc);
 }
 
-Return<Status> PreviewWindowCb::setUsage(ProducerUsage usage) {
+Return<Status> PreviewWindowCb::setUsage(BufferUsage usage) {
     auto rc = native_window_set_usage(mAnw.get(), static_cast<int>(usage));
     if (rc == ::android::OK) {
         mPreviewUsage =  static_cast<int>(usage);
diff --git a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
index 765857f..5672824 100644
--- a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
+++ b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
@@ -16,12 +16,13 @@
 
 #define LOG_TAG "contexthub_hidl_hal_test"
 
+#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/contexthub/1.0/IContexthub.h>
 #include <android/hardware/contexthub/1.0/IContexthubCallback.h>
 #include <android/hardware/contexthub/1.0/types.h>
 #include <android/log.h>
-#include <VtsHalHidlTargetTestBase.h>
+#include <log/log.h>
 
 #include <cinttypes>
 #include <future>
diff --git a/drm/1.0/IDrmPlugin.hal b/drm/1.0/IDrmPlugin.hal
index 083b311..07b0832 100644
--- a/drm/1.0/IDrmPlugin.hal
+++ b/drm/1.0/IDrmPlugin.hal
@@ -179,10 +179,9 @@
      * certificate authority (CA) is an entity which issues digital certificates
      * for use by other parties. It is an example of a trusted third party.
      * @return status the status of the call. The status must be OK or one of
-     * the following errors: BAD_VALUE if the sessionId is invalid,
-     * ERROR_DRM_CANNOT_HANDLE if the drm scheme does not require provisioning
-     * or ERROR_DRM_INVALID_STATE if the HAL is in a state where the provision
-     * request cannot be generated.
+     * the following errors: ERROR_DRM_CANNOT_HANDLE if the drm scheme does not
+     * require provisioning or ERROR_DRM_INVALID_STATE if the HAL is in a state
+     * where the provision request cannot be generated.
      * @return request if successful the opaque certificate request blob
      * is returned
      * @return defaultUrl URL that the provisioning request should be
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index f2334a0..23a4506 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -38,9 +38,12 @@
 LOCAL_C_INCLUDES := \
   hardware/interfaces/drm
 
-# TODO: The legacy DRM plugins only support 32-bit. They need
-# to be migrated to 64-bit (b/18948909)
+# TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
+# migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
+# that device can turn on ENABLE_MEDIADRM_64 to build this service as 64-bit.
+ifneq ($(ENABLE_MEDIADRM_64), true)
 LOCAL_32_BIT_ONLY := true
+endif
 
 include $(BUILD_EXECUTABLE)
 
@@ -55,11 +58,13 @@
     DrmPlugin.cpp \
     CryptoFactory.cpp \
     CryptoPlugin.cpp \
+    LegacyPluginPath.cpp \
     TypeConvert.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
     android.hardware.drm@1.0 \
     android.hidl.memory@1.0 \
+    libcutils \
     libhidlbase \
     libhidlmemory \
     libhidltransport \
@@ -72,8 +77,11 @@
     frameworks/native/include \
     frameworks/av/include
 
-# TODO: The legacy DRM plugins only support 32-bit. They need
-# to be migrated to 64-bit (b/18948909)
+# TODO: Some legacy DRM plugins only support 32-bit. They need to be migrated to
+# 64-bit. (b/18948909) Once all of a device's legacy DRM plugins support 64-bit,
+# that device can turn on ENABLE_MEDIADRM_64 to build this impl as 64-bit.
+ifneq ($(ENABLE_MEDIADRM_64), true)
 LOCAL_32_BIT_ONLY := true
+endif
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/1.0/default/CryptoFactory.cpp b/drm/1.0/default/CryptoFactory.cpp
index e46233d..caab83b 100644
--- a/drm/1.0/default/CryptoFactory.cpp
+++ b/drm/1.0/default/CryptoFactory.cpp
@@ -16,9 +16,10 @@
 #define LOG_TAG "android.hardware.drm@1.0-impl"
 
 #include "CryptoFactory.h"
+#include <log/log.h>
 #include "CryptoPlugin.h"
+#include "LegacyPluginPath.h"
 #include "TypeConvert.h"
-#include <utils/Log.h>
 
 namespace android {
 namespace hardware {
@@ -27,7 +28,7 @@
 namespace implementation {
 
     CryptoFactory::CryptoFactory() :
-        loader("/vendor/lib/mediadrm", "createCryptoFactory") {
+        loader(getDrmPluginPath(), "createCryptoFactory") {
     }
 
     // Methods from ::android::hardware::drm::V1_0::ICryptoFactory follow.
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
index 9c51b15..591861a 100644
--- a/drm/1.0/default/CryptoPlugin.cpp
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -20,8 +20,8 @@
 
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
+#include <log/log.h>
 #include <media/stagefright/foundation/AString.h>
-#include <utils/Log.h>
 
 using android::hardware::hidl_memory;
 using android::hidl::memory::V1_0::IMemory;
@@ -35,7 +35,7 @@
     // Methods from ::android::hardware::drm::V1_0::ICryptoPlugin follow
     Return<bool> CryptoPlugin::requiresSecureDecoderComponent(
             const hidl_string& mime) {
-        return mLegacyPlugin->requiresSecureDecoderComponent(mime);
+        return mLegacyPlugin->requiresSecureDecoderComponent(mime.c_str());
     }
 
     Return<void> CryptoPlugin::notifyResolution(uint32_t width,
diff --git a/drm/1.0/default/DrmFactory.cpp b/drm/1.0/default/DrmFactory.cpp
index 9ec0ab7..7e5d998 100644
--- a/drm/1.0/default/DrmFactory.cpp
+++ b/drm/1.0/default/DrmFactory.cpp
@@ -1,6 +1,6 @@
 /*
  * 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
@@ -16,9 +16,10 @@
 #define LOG_TAG "android.hardware.drm@1.0-impl"
 
 #include "DrmFactory.h"
+#include <log/log.h>
 #include "DrmPlugin.h"
+#include "LegacyPluginPath.h"
 #include "TypeConvert.h"
-#include <utils/Log.h>
 
 namespace android {
 namespace hardware {
@@ -27,7 +28,7 @@
 namespace implementation {
 
     DrmFactory::DrmFactory() :
-        loader("/vendor/lib/mediadrm", "createDrmFactory") {
+        loader(getDrmPluginPath(), "createDrmFactory") {
     }
 
     // Methods from ::android::hardware::drm::V1_0::IDrmFactory follow.
diff --git a/drm/1.0/default/DrmPlugin.cpp b/drm/1.0/default/DrmPlugin.cpp
index c7428a5..1695ef7 100644
--- a/drm/1.0/default/DrmPlugin.cpp
+++ b/drm/1.0/default/DrmPlugin.cpp
@@ -70,15 +70,15 @@
         if (status == android::OK) {
             android::KeyedVector<String8, String8> legacyOptionalParameters;
             for (size_t i = 0; i < optionalParameters.size(); i++) {
-                legacyOptionalParameters.add(String8(optionalParameters[i].key),
-                        String8(optionalParameters[i].value));
+                legacyOptionalParameters.add(String8(optionalParameters[i].key.c_str()),
+                        String8(optionalParameters[i].value.c_str()));
             }
 
             android::DrmPlugin::KeyRequestType legacyRequestType =
                     android::DrmPlugin::kKeyRequestType_Unknown;
 
             status = mLegacyPlugin->getKeyRequest(toVector(scope),
-                    toVector(initData), String8(mimeType), legacyKeyType,
+                    toVector(initData), String8(mimeType.c_str()), legacyKeyType,
                     legacyOptionalParameters, legacyRequest, defaultUrl,
                     &legacyRequestType);
 
@@ -149,7 +149,7 @@
         Vector<uint8_t> legacyRequest;
         String8 legacyDefaultUrl;
         status_t status = mLegacyPlugin->getProvisionRequest(
-                String8(certificateType), String8(certificateAuthority),
+                String8(certificateType.c_str()), String8(certificateAuthority.c_str()),
                 legacyRequest, legacyDefaultUrl);
 
         _hidl_cb(toStatus(status), toHidlVec(legacyRequest),
@@ -217,7 +217,7 @@
             getPropertyString_cb _hidl_cb) {
         String8 legacyValue;
         status_t status = mLegacyPlugin->getPropertyString(
-                String8(propertyName), legacyValue);
+                String8(propertyName.c_str()), legacyValue);
         _hidl_cb(toStatus(status), legacyValue.string());
         return Void();
     }
@@ -226,7 +226,7 @@
             getPropertyByteArray_cb _hidl_cb) {
         Vector<uint8_t> legacyValue;
         status_t status = mLegacyPlugin->getPropertyByteArray(
-                String8(propertyName), legacyValue);
+                String8(propertyName.c_str()), legacyValue);
         _hidl_cb(toStatus(status), toHidlVec(legacyValue));
         return Void();
     }
@@ -234,15 +234,15 @@
     Return<Status> DrmPlugin::setPropertyString(const hidl_string& propertyName,
             const hidl_string& value) {
         status_t legacyStatus =
-            mLegacyPlugin->setPropertyString(String8(propertyName),
-                    String8(value));
+            mLegacyPlugin->setPropertyString(String8(propertyName.c_str()),
+                    String8(value.c_str()));
         return toStatus(legacyStatus);
     }
 
     Return<Status> DrmPlugin::setPropertyByteArray(
             const hidl_string& propertyName, const hidl_vec<uint8_t>& value) {
         status_t legacyStatus =
-            mLegacyPlugin->setPropertyByteArray(String8(propertyName),
+            mLegacyPlugin->setPropertyByteArray(String8(propertyName.c_str()),
                     toVector(value));
         return toStatus(legacyStatus);
     }
@@ -251,7 +251,7 @@
             const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
         status_t legacyStatus =
             mLegacyPlugin->setCipherAlgorithm(toVector(sessionId),
-                String8(algorithm));
+                String8(algorithm.c_str()));
         return toStatus(legacyStatus);
     }
 
@@ -259,7 +259,7 @@
             const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
         status_t legacyStatus =
             mLegacyPlugin->setMacAlgorithm(toVector(sessionId),
-                String8(algorithm));
+                String8(algorithm.c_str()));
         return toStatus(legacyStatus);
     }
 
@@ -313,7 +313,7 @@
 
         Vector<uint8_t> legacySignature;
         status_t status = mLegacyPlugin->signRSA(toVector(sessionId),
-                String8(algorithm), toVector(message), toVector(wrappedKey),
+                String8(algorithm.c_str()), toVector(message), toVector(wrappedKey),
                 legacySignature);
         _hidl_cb(toStatus(status), toHidlVec(legacySignature));
         return Void();
@@ -327,19 +327,25 @@
 
     Return<void> DrmPlugin::sendEvent(EventType eventType,
             const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
-        mListener->sendEvent(eventType, sessionId, data);
+        if (mListener != nullptr) {
+            mListener->sendEvent(eventType, sessionId, data);
+        }
         return Void();
     }
 
     Return<void> DrmPlugin::sendExpirationUpdate(
             const hidl_vec<uint8_t>& sessionId, int64_t expiryTimeInMS) {
-        mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+        if (mListener != nullptr) {
+            mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+        }
         return Void();
     }
 
     Return<void> DrmPlugin::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
             const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
-        mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+        if (mListener != nullptr) {
+            mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+        }
         return Void();
     }
 
diff --git a/drm/1.0/default/LegacyPluginPath.cpp b/drm/1.0/default/LegacyPluginPath.cpp
new file mode 100644
index 0000000..369059d
--- /dev/null
+++ b/drm/1.0/default/LegacyPluginPath.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#include "LegacyPluginPath.h"
+
+#include <cutils/properties.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+const char* getDrmPluginPath() {
+    if (property_get_bool("drm.64bit.enabled", false)) {
+        return "/vendor/lib64/mediadrm";
+    } else {
+        return "/vendor/lib/mediadrm";
+    }
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/LegacyPluginPath.h b/drm/1.0/default/LegacyPluginPath.h
new file mode 100644
index 0000000..7145f2e
--- /dev/null
+++ b/drm/1.0/default/LegacyPluginPath.h
@@ -0,0 +1,35 @@
+/*
+ * 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 LEGACY_PLUGIN_PATH_H_
+
+#define LEGACY_PLUGIN_PATH_H_
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+const char* getDrmPluginPath();
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // LEGACY_PLUGIN_PATH_H_
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 36d7d1c..43ea372 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -34,6 +34,8 @@
         "libhwbinder",
         "liblog",
         "libnativehelper",
+        "libssl",
+        "libcrypto",
         "libutils",
     ],
     static_libs: [
diff --git a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
index 2296d2d..e97ac10 100644
--- a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
@@ -26,6 +26,8 @@
 #include <gtest/gtest.h>
 #include <hidl/HidlSupport.h>
 #include <hidlmemory/mapping.h>
+#include <log/log.h>
+#include <openssl/aes.h>
 #include <memory>
 #include <random>
 
@@ -125,6 +127,39 @@
 }
 
 /**
+ * Ensure the factory doesn't support an empty UUID
+ */
+TEST_F(DrmHalClearkeyFactoryTest, EmptyPluginUUIDNotSupported) {
+    hidl_array<uint8_t, 16> emptyUUID;
+    EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID));
+    EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID));
+}
+
+/**
+ * Ensure empty content type is not supported
+ */
+TEST_F(DrmHalClearkeyFactoryTest, EmptyContentTypeNotSupported) {
+    hidl_string empty;
+    EXPECT_FALSE(drmFactory->isContentTypeSupported(empty));
+}
+
+/**
+ * Ensure invalid content type is not supported
+ */
+TEST_F(DrmHalClearkeyFactoryTest, InvalidContentTypeNotSupported) {
+    hidl_string invalid("abcdabcd");
+    EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid));
+}
+
+/**
+ * Ensure valid content type is supported
+ */
+TEST_F(DrmHalClearkeyFactoryTest, ValidContentTypeSupported) {
+    hidl_string cencType("cenc");
+    EXPECT_TRUE(drmFactory->isContentTypeSupported(cencType));
+}
+
+/**
  * Ensure clearkey drm plugin can be created
  */
 TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyDrmPlugin) {
@@ -418,6 +453,26 @@
 }
 
 /**
+ * Test that a removeKeys on an empty sessionID returns BAD_VALUE
+ */
+TEST_F(DrmHalClearkeyPluginTest, RemoveKeysEmptySessionId) {
+    SessionId sessionId;
+    Status status = drmPlugin->removeKeys(sessionId);
+    EXPECT_TRUE(status == Status::BAD_VALUE);
+}
+
+/**
+ * Remove keys is not supported for clearkey.
+ */
+TEST_F(DrmHalClearkeyPluginTest, RemoveKeysNewSession) {
+    SessionId sessionId = openSession();
+    Status status = drmPlugin->removeKeys(sessionId);
+    // Clearkey plugin doesn't support remove keys
+    EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+    closeSession(sessionId);
+}
+
+/**
  * Test that the clearkey plugin doesn't support getting
  * secure stops.
  */
@@ -617,7 +672,7 @@
     ;
     hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
     hidl_vec<uint8_t> input = {1, 2, 3, 4, 5};
-    hidl_vec<uint8_t> iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0);
     auto res = drmPlugin->encrypt(session, keyId, input, iv,
                                   [&](Status status, const hidl_vec<uint8_t>&) {
                                       EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE,
@@ -629,10 +684,9 @@
 
 TEST_F(DrmHalClearkeyPluginTest, GenericDecryptNotSupported) {
     SessionId session = openSession();
-    ;
     hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
     hidl_vec<uint8_t> input = {1, 2, 3, 4, 5};
-    hidl_vec<uint8_t> iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0);
     auto res = drmPlugin->decrypt(session, keyId, input, iv,
                                   [&](Status status, const hidl_vec<uint8_t>&) {
                                       EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE,
@@ -763,6 +817,17 @@
 }
 
 /**
+ * setMediaDrmSession with an empty session id: BAD_VALUE.  An
+ * empty session clears the previously set session and should
+ * return OK.
+ */
+TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionEmptySession) {
+    SessionId sessionId;
+    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+    EXPECT_EQ(Status::OK, status);
+}
+
+/**
  * Decrypt tests
  */
 
@@ -771,9 +836,15 @@
     void loadKeys(const SessionId& sessionId);
     void fillRandom(const sp<IMemory>& memory);
     hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
-        EXPECT_EQ(vec.size(), 16u);
+        EXPECT_EQ(16u, vec.size());
         return hidl_array<uint8_t, 16>(&vec[0]);
     }
+    uint32_t decrypt(Mode mode, uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+            const Pattern& pattern, Status status);
+    void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
+            const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
+    void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
+            const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
 };
 
 /**
@@ -847,36 +918,162 @@
     }
 }
 
-/**
- * Positive decrypt test.  "Decrypt" a single clear
- * segment.  Verify data matches.
- */
-TEST_F(DrmHalClearkeyDecryptTest, ClearSegmentTest) {
-    const size_t kSegmentSize = 1024;
+uint32_t DrmHalClearkeyDecryptTest::decrypt(Mode mode,
+        uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+        const Pattern& pattern, Status expectedStatus) {
     const size_t kSegmentIndex = 0;
     const vector<uint8_t> keyId = {0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47,
                                    0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d,
                                    0x1e, 0xd0, 0x0d, 0x1e};
-    uint8_t iv[16] = {0};
+    const vector<uint8_t> contentKey = {0x1a, 0x8a, 0x20, 0x95, 0xe4,
+                                        0xde, 0xb2, 0xd2, 0x9e, 0xc8,
+                                        0x16, 0xac, 0x7b, 0xae, 0x20, 0x82};
+    uint8_t localIv[AES_BLOCK_SIZE];
+    memcpy(localIv, iv, AES_BLOCK_SIZE);
 
+    size_t totalSize = 0;
+    for (size_t i = 0; i < subSamples.size(); i++) {
+        totalSize += subSamples[i].numBytesOfClearData;
+        totalSize += subSamples[i].numBytesOfEncryptedData;
+    }
+
+    // The first totalSize bytes of shared memory is the encrypted
+    // input, the second totalSize bytes is the decrypted output.
     sp<IMemory> sharedMemory =
-            getDecryptMemory(kSegmentSize * 2, kSegmentIndex);
+            getDecryptMemory(totalSize * 2, kSegmentIndex);
 
-    SharedBuffer sourceBuffer = {
-            .bufferId = kSegmentIndex, .offset = 0, .size = kSegmentSize};
+    const SharedBuffer sourceBuffer = {
+        .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
     fillRandom(sharedMemory);
 
-    DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
-                                    {.bufferId = kSegmentIndex,
-                                     .offset = kSegmentSize,
-                                     .size = kSegmentSize},
-                                    .secureMemory = nullptr};
+    const DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
+                                          {.bufferId = kSegmentIndex,
+                                           .offset = totalSize,
+                                           .size = totalSize},
+                                          .secureMemory = nullptr};
+    const uint64_t offset = 0;
+    const bool kNotSecure = false;
+    uint32_t bytesWritten = 0;
+    auto res = cryptoPlugin->decrypt(kNotSecure, toHidlArray(keyId), localIv, mode,
+            pattern, subSamples, sourceBuffer, offset, destBuffer,
+            [&](Status status, uint32_t count, string detailedError) {
+                EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
+                detailedError;
+                bytesWritten = count;
+            });
+    EXPECT_OK(res);
 
-    Pattern noPattern = {0, 0};
-    vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
-                                     .numBytesOfEncryptedData = 0}};
-    uint64_t offset = 0;
+    if (bytesWritten != totalSize) {
+        return bytesWritten;
+    }
+    uint8_t* base = static_cast<uint8_t*>(
+            static_cast<void*>(sharedMemory->getPointer()));
 
+    // generate reference vector
+    vector<uint8_t> reference(totalSize);
+
+    memcpy(localIv, iv, AES_BLOCK_SIZE);
+    switch (mode) {
+    case Mode::UNENCRYPTED:
+        memcpy(&reference[0], base, totalSize);
+        break;
+    case Mode::AES_CTR:
+        aes_ctr_decrypt(&reference[0], base, localIv, subSamples, contentKey);
+        break;
+    case Mode::AES_CBC:
+        aes_cbc_decrypt(&reference[0], base, localIv, subSamples, contentKey);
+        break;
+    case Mode::AES_CBC_CTS:
+        EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
+        break;
+    }
+
+    // compare reference to decrypted data which is at base + total size
+    EXPECT_EQ(0, memcmp(static_cast<void *>(&reference[0]),
+                        static_cast<void*>(base + totalSize), totalSize))
+            << "decrypt data mismatch";
+    return totalSize;
+}
+
+/**
+ * Decrypt a list of clear+encrypted subsamples using the specified key
+ * in AES-CTR mode
+ */
+void DrmHalClearkeyDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
+        uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+        const vector<uint8_t>& key) {
+    AES_KEY decryptionKey;
+    AES_set_encrypt_key(&key[0], 128, &decryptionKey);
+
+    size_t offset = 0;
+    unsigned int blockOffset = 0;
+    uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
+    memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);
+
+    for (size_t i = 0; i < subSamples.size(); i++) {
+        const SubSample& subSample = subSamples[i];
+
+        if (subSample.numBytesOfClearData > 0) {
+            memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
+            offset += subSample.numBytesOfClearData;
+        }
+
+        if (subSample.numBytesOfEncryptedData > 0) {
+            AES_ctr128_encrypt(src + offset, dest + offset,
+                    subSample.numBytesOfEncryptedData, &decryptionKey,
+                    iv, previousEncryptedCounter, &blockOffset);
+            offset += subSample.numBytesOfEncryptedData;
+        }
+    }
+}
+
+/**
+ * Decrypt a list of clear+encrypted subsamples using the specified key
+ * in AES-CBC mode
+ */
+void DrmHalClearkeyDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
+        uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+        const vector<uint8_t>& key) {
+    AES_KEY decryptionKey;
+    AES_set_encrypt_key(&key[0], 128, &decryptionKey);
+
+    size_t offset = 0;
+    size_t num = 0;
+    size_t ecount_buf = 0;
+    for (size_t i = 0; i < subSamples.size(); i++) {
+        memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData);
+        offset += subSamples[i].numBytesOfClearData;
+
+        AES_cbc_encrypt(src + offset, dest + offset, subSamples[i].numBytesOfEncryptedData,
+                &decryptionKey, iv, 0 /* decrypt */);
+        offset += subSamples[i].numBytesOfEncryptedData;
+    }
+}
+
+/**
+ * Test query key status
+ */
+TEST_F(DrmHalClearkeyDecryptTest, TestQueryKeyStatus) {
+    auto sessionId = openSession();
+    auto res = drmPlugin->queryKeyStatus(sessionId,
+            [&](Status status, KeyedVector /* info */) {
+                // clearkey doesn't support this method
+                EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+            });
+    EXPECT_OK(res);
+}
+
+
+/**
+ * Positive decrypt test.  "Decrypt" a single clear segment
+ */
+TEST_F(DrmHalClearkeyDecryptTest, ClearSegmentTest) {
+    vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+    const Pattern noPattern = {0, 0};
+    const uint32_t kByteCount = 256;
+    const vector<SubSample> subSamples = {
+        {.numBytesOfClearData = kByteCount,
+         .numBytesOfEncryptedData = 0}};
     auto sessionId = openSession();
     loadKeys(sessionId);
 
@@ -884,21 +1081,57 @@
     EXPECT_EQ(Status::OK, status);
 
     const bool kNotSecure = false;
-    auto res = cryptoPlugin->decrypt(
-            kNotSecure, toHidlArray(keyId), iv, Mode::UNENCRYPTED, noPattern,
-            subSamples, sourceBuffer, offset, destBuffer,
-            [&](Status status, uint32_t bytesWritten, string detailedError) {
-                EXPECT_EQ(Status::OK, status) << "Failure in decryption:"
-                                              << detailedError;
-                EXPECT_EQ(bytesWritten, kSegmentSize);
-            });
-    EXPECT_OK(res);
+    uint32_t byteCount = decrypt(Mode::UNENCRYPTED, &iv[0], subSamples,
+            noPattern, Status::OK);
+    EXPECT_EQ(kByteCount, byteCount);
 
-    uint8_t* base = static_cast<uint8_t*>(
-            static_cast<void*>(sharedMemory->getPointer()));
+    closeSession(sessionId);
+}
 
-    EXPECT_EQ(0, memcmp(static_cast<void*>(base),
-                        static_cast<void*>(base + kSegmentSize), kSegmentSize))
-            << "decrypt data mismatch";
+/**
+ * Positive decrypt test.  Decrypt a single segment using AES_CTR.
+ * Verify data matches.
+ */
+TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTest) {
+    vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+    const Pattern noPattern = {0, 0};
+    const uint32_t kClearBytes = 512;
+    const uint32_t kEncryptedBytes = 512;
+    const vector<SubSample> subSamples = {
+        {.numBytesOfClearData = kClearBytes,
+         .numBytesOfEncryptedData = kEncryptedBytes
+        }};
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+
+    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+    EXPECT_EQ(Status::OK, status);
+
+    const bool kNotSecure = false;
+    uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
+            noPattern, Status::OK);
+    EXPECT_EQ(kClearBytes + kEncryptedBytes, byteCount);
+
+    closeSession(sessionId);
+}
+/**
+ * Negative decrypt test. Decrypt without loading keys.
+ */
+TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
+    vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+    const Pattern noPattern = {0, 0};
+    const vector<SubSample> subSamples = {
+        {.numBytesOfClearData = 256,
+         .numBytesOfEncryptedData = 256}};
+    auto sessionId = openSession();
+
+    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+    EXPECT_EQ(Status::OK, status);
+
+    const bool kNotSecure = false;
+    uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
+            noPattern, Status::ERROR_DRM_NO_LICENSE);
+    EXPECT_EQ(0u, byteCount);
+
     closeSession(sessionId);
 }
diff --git a/drm/1.0/vts/functional/drm_hal_vendor_module_api.h b/drm/1.0/vts/functional/drm_hal_vendor_module_api.h
index db19719..73e0cfe 100644
--- a/drm/1.0/vts/functional/drm_hal_vendor_module_api.h
+++ b/drm/1.0/vts/functional/drm_hal_vendor_module_api.h
@@ -73,21 +73,21 @@
      * value with initial version 1. The API version indicates which subclass
      * version DrmHalVTSVendorModule this instance is.
      */
-    virtual uint32_t getAPIVersion() = 0;
+    virtual uint32_t getAPIVersion() const = 0;
 
     /**
      * Return the UUID for the DRM HAL implementation. Protection System
      * Specific
      * UUID (see http://dashif.org/identifiers/protection/)
      */
-    virtual std::vector<uint8_t> getUUID() = 0;
+    virtual std::vector<uint8_t> getUUID() const = 0;
 
     /**
      * Return the service name for the DRM HAL implementation. If the hal is a
      * legacy
      * drm plugin, i.e. not running as a HIDL service, return the empty string.
      */
-    virtual std::string getServiceName() = 0;
+    virtual std::string getServiceName() const = 0;
 
    private:
     DrmHalVTSVendorModule(const DrmHalVTSVendorModule&) = delete;
@@ -103,7 +103,7 @@
     DrmHalVTSVendorModule_V1() {}
     virtual ~DrmHalVTSVendorModule_V1() {}
 
-    virtual uint32_t getAPIVersion() { return 1; }
+    virtual uint32_t getAPIVersion() const { return 1; }
 
     /**
      * Handle a provisioning request. This function will be called if the HAL
@@ -178,11 +178,10 @@
             const std::vector<uint8_t> keyId;
 
             /**
-             * The key value is provided to generate expected values for
-             * validating
-             * decryption.  If isSecure is false, no key value is required.
+             * The clear content key is provided to generate expected values for
+             * validating decryption.
              */
-            const std::vector<uint8_t> keyValue;
+            const std::vector<uint8_t> clearContentKey;
         };
         std::vector<Key> keys;
     };
@@ -191,7 +190,8 @@
      * Return a list of content configurations that can be exercised by the
      * VTS test.
      */
-    virtual std::vector<ContentConfiguration> getContentConfigurations() = 0;
+    virtual std::vector<ContentConfiguration>
+            getContentConfigurations() const = 0;
 
     /**
      * Handle a key request. This function will be called if the HAL
diff --git a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
index bd78442c..5945c05 100644
--- a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
@@ -21,27 +21,35 @@
 #include <android/hardware/drm/1.0/ICryptoPlugin.h>
 #include <android/hardware/drm/1.0/IDrmFactory.h>
 #include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/IDrmPluginListener.h>
 #include <android/hardware/drm/1.0/types.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <gtest/gtest.h>
 #include <hidlmemory/mapping.h>
+#include <log/log.h>
+#include <openssl/aes.h>
 #include <memory>
 #include <random>
 
-#include "VtsHalHidlTargetTestBase.h"
 #include "drm_hal_vendor_module_api.h"
 #include "vendor_modules.h"
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
 
 using ::android::hardware::drm::V1_0::BufferType;
 using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::EventType;
 using ::android::hardware::drm::V1_0::ICryptoFactory;
 using ::android::hardware::drm::V1_0::ICryptoPlugin;
 using ::android::hardware::drm::V1_0::IDrmFactory;
 using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::V1_0::IDrmPluginListener;
 using ::android::hardware::drm::V1_0::KeyedVector;
-using ::android::hardware::drm::V1_0::KeyValue;
 using ::android::hardware::drm::V1_0::KeyRequestType;
+using ::android::hardware::drm::V1_0::KeyStatus;
+using ::android::hardware::drm::V1_0::KeyStatusType;
 using ::android::hardware::drm::V1_0::KeyType;
+using ::android::hardware::drm::V1_0::KeyValue;
 using ::android::hardware::drm::V1_0::Mode;
 using ::android::hardware::drm::V1_0::Pattern;
 using ::android::hardware::drm::V1_0::SecureStop;
@@ -56,6 +64,7 @@
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
+using ::android::hardware::Void;
 using ::android::hidl::allocator::V1_0::IAllocator;
 using ::android::hidl::memory::V1_0::IMemory;
 using ::android::sp;
@@ -67,6 +76,10 @@
 using std::mt19937;
 using std::vector;
 
+using ContentConfiguration = ::DrmHalVTSVendorModule_V1::ContentConfiguration;
+using Key = ::DrmHalVTSVendorModule_V1::ContentConfiguration::Key;
+using VtsTestBase = ::testing::VtsHalHidlTargetTestBase;
+
 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
 
@@ -80,10 +93,9 @@
 class DrmHalVendorFactoryTest : public testing::TestWithParam<std::string> {
    public:
     DrmHalVendorFactoryTest()
-        : vendorModule(gVendorModules ? static_cast<DrmHalVTSVendorModule_V1*>(
-                                                gVendorModules->getVendorModule(
-                                                        GetParam()))
-                                      : nullptr) {}
+        : vendorModule(static_cast<DrmHalVTSVendorModule_V1*>(
+                        gVendorModules->getModule(GetParam()))),
+          contentConfigurations(vendorModule->getContentConfigurations()) {}
 
     virtual ~DrmHalVendorFactoryTest() {}
 
@@ -95,14 +107,22 @@
               GetParam().c_str());
 
         ASSERT_NE(vendorModule, nullptr);
+
+        // First try the binderized service name provided by the vendor module.
+        // If that fails, which it can on non-binderized devices, try the default
+        // service.
         string name = vendorModule->getServiceName();
-        drmFactory =
-                ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>(
-                        name != "default" ? name : "drm");
+        drmFactory = VtsTestBase::getService<IDrmFactory>(name);
+        if (drmFactory == nullptr) {
+            drmFactory = VtsTestBase::getService<IDrmFactory>("drm");
+        }
         ASSERT_NE(drmFactory, nullptr);
-        cryptoFactory =
-                ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>(
-                        name != "default" ? name : "crypto");
+
+        // Dot the same for the crypto factory
+        cryptoFactory = VtsTestBase::getService<ICryptoFactory>(name);
+        if (cryptoFactory == nullptr) {
+            VtsTestBase::getService<ICryptoFactory>("crypto");
+        }
         ASSERT_NE(cryptoFactory, nullptr);
     }
 
@@ -117,14 +137,27 @@
     sp<IDrmFactory> drmFactory;
     sp<ICryptoFactory> cryptoFactory;
     unique_ptr<DrmHalVTSVendorModule_V1> vendorModule;
+    const vector<ContentConfiguration> contentConfigurations;
 };
 
-/**
- * Ensure the factory supports its scheme UUID
- */
-TEST_P(DrmHalVendorFactoryTest, VendorPluginSupported) {
-    EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getVendorUUID()));
-    EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getVendorUUID()));
+TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) {
+    const char* kVendorStr = "Vendor module ";
+    for (auto config : contentConfigurations) {
+        ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name";
+        ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr
+                                                 << "has no serverUrl";
+        ASSERT_TRUE(config.initData.size() > 0) << kVendorStr
+                                                << "has no init data";
+        ASSERT_TRUE(config.mimeType.size() > 0) << kVendorStr
+                                                << "has no mime type";
+        ASSERT_TRUE(config.keys.size() >= 1) << kVendorStr << "has no keys";
+        for (auto key : config.keys) {
+            ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
+                                              << " has zero length keyId";
+            ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
+                                              << " has zero length key value";
+        }
+    }
 }
 
 /**
@@ -136,6 +169,48 @@
 }
 
 /**
+ * Ensure the factory doesn't support an empty UUID
+ */
+TEST_P(DrmHalVendorFactoryTest, EmptyPluginUUIDNotSupported) {
+    hidl_array<uint8_t, 16> emptyUUID;
+    EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID));
+    EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID));
+}
+
+/**
+ * Ensure the factory supports the scheme uuid in the config
+ */
+TEST_P(DrmHalVendorFactoryTest, EmptyPluginConfigUUIDSupported) {
+    EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getVendorUUID()));
+    EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getVendorUUID()));
+}
+
+/**
+ * Ensure empty content type is not supported
+ */
+TEST_P(DrmHalVendorFactoryTest, EmptyContentTypeNotSupported) {
+    hidl_string empty;
+    EXPECT_FALSE(drmFactory->isContentTypeSupported(empty));
+}
+
+/**
+ * Ensure invalid content type is not supported
+ */
+TEST_P(DrmHalVendorFactoryTest, InvalidContentTypeNotSupported) {
+    hidl_string invalid("abcdabcd");
+    EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid));
+}
+
+/**
+ * Ensure valid content types in the configs are supported
+ */
+TEST_P(DrmHalVendorFactoryTest, ValidContentTypeSupported) {
+    for (auto config : contentConfigurations) {
+        EXPECT_TRUE(drmFactory->isContentTypeSupported(config.mimeType));
+    }
+}
+
+/**
  * Ensure vendor drm plugin can be created
  */
 TEST_P(DrmHalVendorFactoryTest, CreateVendorDrmPlugin) {
@@ -393,6 +468,26 @@
 }
 
 /**
+ * Test that a removeKeys on an empty sessionID returns BAD_VALUE
+ */
+TEST_P(DrmHalVendorPluginTest, RemoveKeysEmptySessionId) {
+    SessionId sessionId;
+    Status status = drmPlugin->removeKeys(sessionId);
+    EXPECT_TRUE(status == Status::BAD_VALUE);
+}
+
+/**
+ * Test that remove keys returns okay on an initialized session
+ * that has no keys.
+ */
+TEST_P(DrmHalVendorPluginTest, RemoveKeysNewSession) {
+    SessionId sessionId = openSession();
+    Status status = drmPlugin->removeKeys(sessionId);
+    EXPECT_TRUE(status == Status::OK);
+    closeSession(sessionId);
+}
+
+/**
  * Test that the plugin either doesn't support getting
  * secure stops, or has no secure stops available after
  * clearing them.
@@ -722,6 +817,166 @@
 }
 
 /**
+ * Verify that requiresSecureDecoderComponent returns true for secure
+ * configurations
+ */
+TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) {
+    const char* kVendorStr = "Vendor module ";
+    for (auto config : contentConfigurations) {
+        for (auto key : config.keys) {
+            if (key.isSecure) {
+                EXPECT_TRUE(cryptoPlugin->requiresSecureDecoderComponent(config.mimeType));
+                break;
+            }
+        }
+    }
+}
+
+/**
+ *  Event Handling tests
+ */
+struct ListenerEventArgs {
+    EventType eventType;
+    SessionId sessionId;
+    hidl_vec<uint8_t> data;
+    int64_t expiryTimeInMS;
+    hidl_vec<KeyStatus> keyStatusList;
+    bool hasNewUsableKey;
+};
+
+const char *kCallbackEvent = "SendEvent";
+const char *kCallbackExpirationUpdate = "SendExpirationUpdate";
+const char *kCallbackKeysChange = "SendKeysChange";
+
+class TestDrmPluginListener
+    : public ::testing::VtsHalHidlTargetCallbackBase<ListenerEventArgs>,
+      public IDrmPluginListener {
+public:
+    TestDrmPluginListener() {
+        SetWaitTimeoutDefault(std::chrono::milliseconds(500));
+    }
+    virtual ~TestDrmPluginListener() {}
+
+    virtual Return<void> sendEvent(EventType eventType, const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& data) override {
+        ListenerEventArgs args;
+        args.eventType = eventType;
+        args.sessionId = sessionId;
+        args.data = data;
+        NotifyFromCallback(kCallbackEvent, args);
+        return Void();
+    }
+
+    virtual Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+            int64_t expiryTimeInMS) override {
+        ListenerEventArgs args;
+        args.sessionId = sessionId;
+        args.expiryTimeInMS = expiryTimeInMS;
+        NotifyFromCallback(kCallbackExpirationUpdate, args);
+        return Void();
+    }
+
+    virtual Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) override {
+        ListenerEventArgs args;
+        args.sessionId = sessionId;
+        args.keyStatusList = keyStatusList;
+        args.hasNewUsableKey = hasNewUsableKey;
+        NotifyFromCallback(kCallbackKeysChange, args);
+        return Void();
+    }
+};
+
+
+/**
+ * Simulate the plugin sending events. Make sure the listener
+ * gets them.
+ */
+TEST_P(DrmHalVendorPluginTest, ListenerEvents) {
+    sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
+    drmPlugin->setListener(listener);
+    auto sessionId = openSession();
+    hidl_vec<uint8_t> data = {0, 1, 2};
+    EventType eventTypes[] = {EventType::PROVISION_REQUIRED,
+                              EventType::KEY_NEEDED,
+                              EventType::KEY_EXPIRED,
+                              EventType::VENDOR_DEFINED,
+                              EventType::SESSION_RECLAIMED};
+    for (auto eventType : eventTypes) {
+        drmPlugin->sendEvent(eventType, sessionId, data);
+        auto result = listener->WaitForCallback(kCallbackEvent);
+        EXPECT_TRUE(result.no_timeout);
+        EXPECT_TRUE(result.args);
+        EXPECT_EQ(eventType, result.args->eventType);
+        EXPECT_EQ(sessionId, result.args->sessionId);
+        EXPECT_EQ(data, result.args->data);
+    }
+    closeSession(sessionId);
+}
+
+/**
+ * Simulate the plugin sending expiration updates and make sure
+ * the listener gets them.
+ */
+TEST_P(DrmHalVendorPluginTest, ListenerExpirationUpdate) {
+    sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
+    drmPlugin->setListener(listener);
+    auto sessionId = openSession();
+    drmPlugin->sendExpirationUpdate(sessionId, 100);
+    auto result = listener->WaitForCallback(kCallbackExpirationUpdate);
+    EXPECT_TRUE(result.no_timeout);
+    EXPECT_TRUE(result.args);
+    EXPECT_EQ(sessionId, result.args->sessionId);
+    EXPECT_EQ(100, result.args->expiryTimeInMS);
+    closeSession(sessionId);
+}
+
+/**
+ * Simulate the plugin sending keys change and make sure
+ * the listener gets them.
+ */
+TEST_P(DrmHalVendorPluginTest, ListenerKeysChange) {
+    sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
+    drmPlugin->setListener(listener);
+    auto sessionId = openSession();
+    const hidl_vec<KeyStatus> keyStatusList = {
+        {{1}, KeyStatusType::USABLE},
+        {{2}, KeyStatusType::EXPIRED},
+        {{3}, KeyStatusType::OUTPUTNOTALLOWED},
+        {{4}, KeyStatusType::STATUSPENDING},
+        {{5}, KeyStatusType::INTERNALERROR},
+    };
+
+    drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
+    auto result = listener->WaitForCallback(kCallbackKeysChange);
+    EXPECT_TRUE(result.no_timeout);
+    EXPECT_TRUE(result.args);
+    EXPECT_EQ(sessionId, result.args->sessionId);
+    EXPECT_EQ(keyStatusList, result.args->keyStatusList);
+}
+
+/**
+ * Negative listener tests. Call send methods with no
+ * listener set.
+ */
+TEST_P(DrmHalVendorPluginTest, NotListening) {
+    sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
+    drmPlugin->setListener(listener);
+    drmPlugin->setListener(nullptr);
+
+    SessionId sessionId;
+    hidl_vec<uint8_t> data;
+    hidl_vec<KeyStatus> keyStatusList;
+    drmPlugin->sendEvent(EventType::PROVISION_REQUIRED, sessionId, data);
+    drmPlugin->sendExpirationUpdate(sessionId, 100);
+    drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
+    auto result = listener->WaitForCallbackAny(
+            {kCallbackEvent, kCallbackExpirationUpdate, kCallbackKeysChange});
+    EXPECT_FALSE(result.no_timeout);
+}
+
+
+/**
  *  CryptoPlugin tests
  */
 
@@ -786,6 +1041,15 @@
 }
 
 /**
+ * setMediaDrmSession with a empty session id: BAD_VALUE
+ */
+TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionEmptySession) {
+    SessionId sessionId;
+    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+    EXPECT_EQ(Status::BAD_VALUE, status);
+}
+
+/**
  * Decrypt tests
  */
 
@@ -796,14 +1060,23 @@
 
    protected:
     void loadKeys(const SessionId& sessionId,
-                  const DrmHalVTSVendorModule_V1::ContentConfiguration&
-                          configuration);
+                  const ContentConfiguration& configuration);
     void fillRandom(const sp<IMemory>& memory);
     KeyedVector toHidlKeyedVector(const map<string, string>& params);
     hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
         EXPECT_EQ(vec.size(), 16u);
         return hidl_array<uint8_t, 16>(&vec[0]);
     }
+    hidl_vec<KeyValue> queryKeyStatus(SessionId sessionId);
+    void removeKeys(SessionId sessionId);
+    uint32_t decrypt(Mode mode, bool isSecure,
+            const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
+            const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
+            const vector<uint8_t>& key, Status expectedStatus);
+    void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
+            const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
+    void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
+            const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
 };
 
 KeyedVector DrmHalVendorDecryptTest::toHidlKeyedVector(
@@ -823,9 +1096,8 @@
  * These tests use predetermined key request/response to
  * avoid requiring a round trip to a license server.
  */
-void DrmHalVendorDecryptTest::loadKeys(
-        const SessionId& sessionId,
-        const DrmHalVTSVendorModule_V1::ContentConfiguration& configuration) {
+void DrmHalVendorDecryptTest::loadKeys(const SessionId& sessionId,
+        const ContentConfiguration& configuration) {
     hidl_vec<uint8_t> keyRequest;
     auto res = drmPlugin->getKeyRequest(
             sessionId, configuration.initData, configuration.mimeType,
@@ -874,111 +1146,326 @@
     }
 }
 
-TEST_P(DrmHalVendorDecryptTest, ValidateConfigurations) {
-    vector<DrmHalVTSVendorModule_V1::ContentConfiguration> configurations =
-            vendorModule->getContentConfigurations();
-    const char* kVendorStr = "Vendor module ";
-    for (auto config : configurations) {
-        ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name";
-        ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr
-                                                 << "has no serverUrl";
-        ASSERT_TRUE(config.initData.size() > 0) << kVendorStr
-                                                << "has no init data";
-        ASSERT_TRUE(config.mimeType.size() > 0) << kVendorStr
-                                                << "has no mime type";
-        ASSERT_TRUE(config.keys.size() >= 1) << kVendorStr << "has no keys";
-        for (auto key : config.keys) {
-            ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
-                                              << " has zero length keyId";
-            ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
-                                              << " has zero length key value";
+hidl_vec<KeyValue> DrmHalVendorDecryptTest::queryKeyStatus(SessionId sessionId) {
+    hidl_vec<KeyValue> keyStatus;
+    auto res = drmPlugin->queryKeyStatus(sessionId,
+            [&](Status status, KeyedVector info) {
+                EXPECT_EQ(Status::OK, status);
+                keyStatus = info;
+            });
+    EXPECT_OK(res);
+    return keyStatus;
+}
+
+void DrmHalVendorDecryptTest::removeKeys(SessionId sessionId) {
+    auto res = drmPlugin->removeKeys(sessionId);
+    EXPECT_OK(res);
+}
+
+uint32_t DrmHalVendorDecryptTest::decrypt(Mode mode, bool isSecure,
+        const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
+        const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
+        const vector<uint8_t>& key, Status expectedStatus) {
+    const size_t kSegmentIndex = 0;
+
+    uint8_t localIv[AES_BLOCK_SIZE];
+    memcpy(localIv, iv, AES_BLOCK_SIZE);
+
+    size_t totalSize = 0;
+    for (size_t i = 0; i < subSamples.size(); i++) {
+        totalSize += subSamples[i].numBytesOfClearData;
+        totalSize += subSamples[i].numBytesOfEncryptedData;
+    }
+
+    // The first totalSize bytes of shared memory is the encrypted
+    // input, the second totalSize bytes is the decrypted output.
+    sp<IMemory> sharedMemory =
+            getDecryptMemory(totalSize * 2, kSegmentIndex);
+
+    SharedBuffer sourceBuffer = {
+            .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
+    fillRandom(sharedMemory);
+
+    DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
+                                    {.bufferId = kSegmentIndex,
+                                     .offset = totalSize,
+                                     .size = totalSize},
+                                    .secureMemory = nullptr};
+    uint64_t offset = 0;
+    uint32_t bytesWritten = 0;
+    auto res = cryptoPlugin->decrypt(isSecure, keyId, localIv, mode, pattern,
+            subSamples, sourceBuffer, offset, destBuffer,
+            [&](Status status, uint32_t count, string detailedError) {
+                EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
+                detailedError;
+                bytesWritten = count;
+            });
+    EXPECT_OK(res);
+
+    if (bytesWritten != totalSize) {
+        return bytesWritten;
+    }
+    uint8_t* base = static_cast<uint8_t*>(
+            static_cast<void*>(sharedMemory->getPointer()));
+
+    // generate reference vector
+    vector<uint8_t> reference(totalSize);
+
+    memcpy(localIv, iv, AES_BLOCK_SIZE);
+    switch (mode) {
+    case Mode::UNENCRYPTED:
+        memcpy(&reference[0], base, totalSize);
+        break;
+    case Mode::AES_CTR:
+        aes_ctr_decrypt(&reference[0], base, localIv, subSamples, key);
+        break;
+    case Mode::AES_CBC:
+        aes_cbc_decrypt(&reference[0], base, localIv, subSamples, key);
+        break;
+    case Mode::AES_CBC_CTS:
+        EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
+        break;
+    }
+
+    // compare reference to decrypted data which is at base + total size
+    EXPECT_EQ(0, memcmp(static_cast<void*>(&reference[0]),
+                        static_cast<void*>(base + totalSize), totalSize))
+            << "decrypt data mismatch";
+    return totalSize;
+}
+
+/**
+ * Decrypt a list of clear+encrypted subsamples using the specified key
+ * in AES-CTR mode
+ */
+void DrmHalVendorDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
+        uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+        const vector<uint8_t>& key) {
+
+    AES_KEY decryptionKey;
+    AES_set_encrypt_key(&key[0], 128, &decryptionKey);
+
+    size_t offset = 0;
+    unsigned blockOffset = 0;
+    uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
+    memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);
+
+    for (size_t i = 0; i < subSamples.size(); i++) {
+        const SubSample& subSample = subSamples[i];
+
+        if (subSample.numBytesOfClearData > 0) {
+            memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
+            offset += subSample.numBytesOfClearData;
+        }
+
+        if (subSample.numBytesOfEncryptedData > 0) {
+            AES_ctr128_encrypt(src + offset, dest + offset,
+                    subSample.numBytesOfEncryptedData, &decryptionKey,
+                    iv, previousEncryptedCounter, &blockOffset);
+            offset += subSample.numBytesOfEncryptedData;
         }
     }
 }
 
 /**
- * Positive decrypt test.  "Decrypt" a single clear
- * segment.  Verify data matches.
+ * Decrypt a list of clear+encrypted subsamples using the specified key
+ * in AES-CBC mode
  */
-TEST_P(DrmHalVendorDecryptTest, ClearSegmentTest) {
-    vector<DrmHalVTSVendorModule_V1::ContentConfiguration> configurations =
-            vendorModule->getContentConfigurations();
-    for (auto config : configurations) {
-        const size_t kSegmentSize = 1024;
-        const size_t kSegmentIndex = 0;
-        uint8_t iv[16] = {0};
+void DrmHalVendorDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
+        uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+        const vector<uint8_t>& key) {
+    AES_KEY decryptionKey;
+    AES_set_encrypt_key(&key[0], 128, &decryptionKey);
 
-        sp<IMemory> sharedMemory =
-                getDecryptMemory(kSegmentSize * 2, kSegmentIndex);
+    size_t offset = 0;
+    size_t num = 0;
+    size_t ecount_buf = 0;
+    for (size_t i = 0; i < subSamples.size(); i++) {
+        const SubSample& subSample = subSamples[i];
 
-        SharedBuffer sourceBuffer = {
-                .bufferId = kSegmentIndex, .offset = 0, .size = kSegmentSize};
-        fillRandom(sharedMemory);
+        memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
+        offset += subSample.numBytesOfClearData;
 
-        DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
-                                        {.bufferId = kSegmentIndex,
-                                         .offset = kSegmentSize,
-                                         .size = kSegmentSize},
-                                        .secureMemory = nullptr};
+        AES_cbc_encrypt(src + offset, dest + offset, subSample.numBytesOfEncryptedData,
+                &decryptionKey, iv, 0 /* decrypt */);
+        offset += subSample.numBytesOfEncryptedData;
+    }
+}
 
-        Pattern noPattern = {0, 0};
-        vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
-                                         .numBytesOfEncryptedData = 0}};
-        uint64_t offset = 0;
 
+/**
+ * Test key status with empty session id, should return BAD_VALUE
+ */
+TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusInvalidSession) {
+    SessionId sessionId;
+    auto res = drmPlugin->queryKeyStatus(sessionId,
+            [&](Status status, KeyedVector /* info */) {
+                EXPECT_EQ(Status::BAD_VALUE, status);
+            });
+    EXPECT_OK(res);
+}
+
+
+/**
+ * Test key status.  There should be no key status prior to loading keys
+ */
+TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusWithNoKeys) {
+    auto sessionId = openSession();
+    auto keyStatus = queryKeyStatus(sessionId);
+    EXPECT_EQ(0u, keyStatus.size());
+    closeSession(sessionId);
+}
+
+
+/**
+ * Test key status.  There should be key status after loading keys.
+ */
+TEST_P(DrmHalVendorDecryptTest, QueryKeyStatus) {
+    for (auto config : contentConfigurations) {
         auto sessionId = openSession();
         loadKeys(sessionId, config);
-
-        Status status = cryptoPlugin->setMediaDrmSession(sessionId);
-        EXPECT_EQ(Status::OK, status);
-
-        const bool kNotSecure = false;
-        auto res = cryptoPlugin->decrypt(
-                kNotSecure, toHidlArray(config.keys[0].keyId), iv,
-                Mode::UNENCRYPTED, noPattern, subSamples, sourceBuffer, offset,
-                destBuffer, [&](Status status, uint32_t bytesWritten,
-                                string detailedError) {
-                    EXPECT_EQ(Status::OK, status) << "Failure in decryption "
-                                                     "for configuration "
-                                                  << config.name << ": "
-                                                  << detailedError;
-                    EXPECT_EQ(bytesWritten, kSegmentSize);
-                });
-        EXPECT_OK(res);
-        uint8_t* base = static_cast<uint8_t*>(
-                static_cast<void*>(sharedMemory->getPointer()));
-
-        EXPECT_EQ(0,
-                  memcmp(static_cast<void*>(base),
-                         static_cast<void*>(base + kSegmentSize), kSegmentSize))
-                << "decrypt data mismatch";
+        auto keyStatus = queryKeyStatus(sessionId);
+        EXPECT_NE(0u, keyStatus.size());
         closeSession(sessionId);
     }
 }
 
 /**
+ * Positive decrypt test. "Decrypt" a single clear segment and verify.
+ */
+TEST_P(DrmHalVendorDecryptTest, ClearSegmentTest) {
+    for (auto config : contentConfigurations) {
+        for (auto key : config.keys) {
+            const size_t kSegmentSize = 1024;
+            vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+            const Pattern noPattern = {0, 0};
+            const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
+                                                   .numBytesOfEncryptedData = 0}};
+            auto sessionId = openSession();
+            loadKeys(sessionId, config);
+
+            Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+            EXPECT_EQ(Status::OK, status);
+
+            uint32_t byteCount = decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId),
+                    &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
+            EXPECT_EQ(kSegmentSize, byteCount);
+
+            closeSession(sessionId);
+        }
+    }
+}
+
+/**
+ * Positive decrypt test.  Decrypt a single segment using aes_ctr.
+ * Verify data matches.
+ */
+TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTest) {
+    for (auto config : contentConfigurations) {
+        for (auto key : config.keys) {
+            const size_t kSegmentSize = 1024;
+            vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+            const Pattern noPattern = {0, 0};
+            const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
+                                                   .numBytesOfEncryptedData = 0}};
+            auto sessionId = openSession();
+            loadKeys(sessionId, config);
+
+            Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+            EXPECT_EQ(Status::OK, status);
+
+            uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, toHidlArray(key.keyId),
+                    &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
+            EXPECT_EQ(kSegmentSize, byteCount);
+
+            closeSession(sessionId);
+        }
+    }
+}
+
+/**
+ * Negative decrypt test. Decrypt without loading keys.
+ */
+TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
+    for (auto config : contentConfigurations) {
+        for (auto key : config.keys) {
+            vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+            const Pattern noPattern = {0, 0};
+            const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
+                                                   .numBytesOfEncryptedData = 256}};
+            auto sessionId = openSession();
+
+            Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+            EXPECT_EQ(Status::OK, status);
+
+            uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
+                    toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
+                    key.clearContentKey, Status::ERROR_DRM_NO_LICENSE);
+            EXPECT_EQ(0u, byteCount);
+
+            closeSession(sessionId);
+        }
+    }
+}
+
+/**
+ * Test key removal.  Load keys then remove them and verify that
+ * decryption can't be performed.
+ */
+TEST_P(DrmHalVendorDecryptTest, AttemptDecryptWithKeysRemoved) {
+    for (auto config : contentConfigurations) {
+        for (auto key : config.keys) {
+            vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+            const Pattern noPattern = {0, 0};
+            const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
+                                                   .numBytesOfEncryptedData = 256}};
+            auto sessionId = openSession();
+
+            Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+            EXPECT_EQ(Status::OK, status);
+
+            loadKeys(sessionId, config);
+            removeKeys(sessionId);
+
+            uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
+                    toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
+                    key.clearContentKey, Status::ERROR_DRM_DECRYPT);
+            EXPECT_EQ(0u, byteCount);
+
+            closeSession(sessionId);
+        }
+    }
+}
+
+
+/**
  * Instantiate the set of test cases for each vendor module
  */
 
 INSTANTIATE_TEST_CASE_P(
         DrmHalVendorFactoryTestCases, DrmHalVendorFactoryTest,
-        testing::ValuesIn(gVendorModules->getVendorModulePaths()));
+        testing::ValuesIn(gVendorModules->getPathList()));
 
 INSTANTIATE_TEST_CASE_P(
         DrmHalVendorPluginTestCases, DrmHalVendorPluginTest,
-        testing::ValuesIn(gVendorModules->getVendorModulePaths()));
+        testing::ValuesIn(gVendorModules->getPathList()));
 
 INSTANTIATE_TEST_CASE_P(
         DrmHalVendorDecryptTestCases, DrmHalVendorDecryptTest,
-        testing::ValuesIn(gVendorModules->getVendorModulePaths()));
+        testing::ValuesIn(gVendorModules->getPathList()));
 
 int main(int argc, char** argv) {
 #if defined(__LP64__)
-    const char *kModulePath = "/data/local/tmp/64/lib";
+    const char* kModulePath = "/data/local/tmp/64/lib";
 #else
-    const char *kModulePath = "/data/local/tmp/32/lib";
+    const char* kModulePath = "/data/local/tmp/32/lib";
 #endif
     gVendorModules = new drm_vts::VendorModules(kModulePath);
+    if (gVendorModules->getPathList().size() == 0) {
+        std::cerr << "No vendor modules found in " << kModulePath <<
+                ", exiting" << std::endl;
+        exit(-1);
+    }
     ::testing::InitGoogleTest(&argc, argv);
     return RUN_ALL_TESTS();
 }
diff --git a/drm/1.0/vts/functional/vendor_modules.cpp b/drm/1.0/vts/functional/vendor_modules.cpp
index 34af6f8..2bf0b28 100644
--- a/drm/1.0/vts/functional/vendor_modules.cpp
+++ b/drm/1.0/vts/functional/vendor_modules.cpp
@@ -18,7 +18,7 @@
 
 #include <dirent.h>
 #include <dlfcn.h>
-#include <utils/Log.h>
+#include <log/log.h>
 #include <memory>
 
 #include "shared_library.h"
@@ -29,44 +29,37 @@
 using std::unique_ptr;
 
 namespace drm_vts {
-vector<string> VendorModules::getVendorModulePaths() {
-    if (mModuleList.size() > 0) {
-        return mModuleList;
-    }
-
-    DIR* dir = opendir(mModulesPath.c_str());
+void VendorModules::scanModules(const std::string &directory) {
+    DIR* dir = opendir(directory.c_str());
     if (dir == NULL) {
-        ALOGE("Unable to open drm VTS vendor directory %s",
-              mModulesPath.c_str());
-        return mModuleList;
-    }
-
-    struct dirent* entry;
-    while ((entry = readdir(dir))) {
-        string fullpath = mModulesPath + "/" + entry->d_name;
-        if (endsWith(fullpath, ".so")) {
-            mModuleList.push_back(fullpath);
+        ALOGE("Unable to open drm VTS vendor directory %s", directory.c_str());
+    } else {
+        struct dirent* entry;
+        while ((entry = readdir(dir))) {
+            ALOGD("checking file %s", entry->d_name);
+            string fullpath = directory + "/" + entry->d_name;
+            if (endsWith(fullpath, ".so")) {
+                mPathList.push_back(fullpath);
+            }
         }
+        closedir(dir);
     }
-
-    closedir(dir);
-    return mModuleList;
 }
 
-DrmHalVTSVendorModule* VendorModules::getVendorModule(const string& path) {
-    unique_ptr<SharedLibrary>& library = mOpenLibraries[path];
-    if (!library) {
-        library = unique_ptr<SharedLibrary>(new SharedLibrary(path));
+DrmHalVTSVendorModule* VendorModules::getModule(const string& path) {
+    if (mOpenLibraries.find(path) == mOpenLibraries.end()) {
+        auto library = std::make_unique<SharedLibrary>(path);
         if (!library) {
             ALOGE("failed to map shared library %s", path.c_str());
             return NULL;
         }
+        mOpenLibraries[path] = std::move(library);
     }
+    const unique_ptr<SharedLibrary>& library = mOpenLibraries[path];
     void* symbol = library->lookup("vendorModuleFactory");
     if (symbol == NULL) {
         ALOGE("getVendorModule failed to lookup 'vendorModuleFactory' in %s: "
-              "%s",
-              path.c_str(), library->lastError());
+              "%s", path.c_str(), library->lastError());
         return NULL;
     }
     typedef DrmHalVTSVendorModule* (*ModuleFactory)();
diff --git a/drm/1.0/vts/functional/vendor_modules.h b/drm/1.0/vts/functional/vendor_modules.h
index 5371a0d..ca538f6 100644
--- a/drm/1.0/vts/functional/vendor_modules.h
+++ b/drm/1.0/vts/functional/vendor_modules.h
@@ -30,27 +30,33 @@
      * Initialize with a file system path where the shared libraries
      * are to be found.
      */
-    explicit VendorModules(const std::string& path) : mModulesPath(path) {}
+    explicit VendorModules(const std::string& dir) {
+        scanModules(dir);
+    }
     ~VendorModules() {}
 
     /**
-     * Return a list of paths to available vendor modules.
-     */
-    std::vector<std::string> getVendorModulePaths();
-
-    /**
      * Retrieve a DrmHalVTSVendorModule given its full path.  The
      * getAPIVersion method can be used to determine the versioned
      * subclass type.
      */
-    DrmHalVTSVendorModule* getVendorModule(const std::string& path);
+    DrmHalVTSVendorModule* getModule(const std::string& path);
+
+    /**
+     * Return the list of paths to available vendor modules.
+     */
+    std::vector<std::string> getPathList() const {return mPathList;}
 
    private:
-    std::string mModulesPath;
-    std::vector<std::string> mModuleList;
+    std::vector<std::string> mPathList;
     std::map<std::string, std::unique_ptr<SharedLibrary>> mOpenLibraries;
 
-    inline bool endsWith(const std::string& str, const std::string& suffix) {
+    /**
+     * Scan the list of paths to available vendor modules.
+     */
+    void scanModules(const std::string& dir);
+
+    inline bool endsWith(const std::string& str, const std::string& suffix) const {
         if (suffix.size() > str.size()) return false;
         return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
     }
diff --git a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
index 391dea0..e9a44eb 100644
--- a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
+++ b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
@@ -30,6 +30,8 @@
 #include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
 #include <android/hardware/gatekeeper/1.0/types.h>
 
+#include <log/log.h>
+
 #include <VtsHalHidlTargetTestBase.h>
 
 using ::android::hardware::hidl_string;
diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
index bd5cc2e..fde3171 100644
--- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
+++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "VtsHalGnssV1_0TargetTest"
 #include <android/hardware/gnss/1.0/IGnss.h>
-#include <android/log.h>
+#include <log/log.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 
@@ -35,11 +35,11 @@
 using android::hardware::gnss::V1_0::IGnssMeasurement;
 using android::sp;
 
-#define TIMEOUT_SEC 3  // for basic commands/responses
+#define TIMEOUT_SEC 2  // for basic commands/responses
 
-// Set these false for release, true for stronger test
-#define GNSS_SIGNAL_IS_PRESENT false
-#define GNSS_ASSISTANCE_IS_PRESENT false
+// for command line argument on how strictly to run the test
+bool sAgpsIsPresent = false;  // if SUPL or XTRA assistance available
+bool sSignalIsWeak = false;  // if GNSS signals are weak (e.g. light indoor)
 
 // The main test class for GNSS HAL.
 class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
@@ -204,7 +204,6 @@
  * CheckLocation:
  * Helper function to vet Location fields
  */
-
 void CheckLocation(GnssLocation& location, bool checkAccuracies) {
   EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
   EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
@@ -270,6 +269,39 @@
 }
 
 /*
+ * StartAndGetSingleLocation:
+ * Helper function to get one Location and check fields
+ *
+ * returns  true if a location was successfully generated
+ */
+bool StartAndGetSingleLocation(GnssHalTest* test, bool checkAccuracies) {
+  auto result = test->gnss_hal_->start();
+
+  EXPECT_TRUE(result.isOk());
+  EXPECT_TRUE(result);
+
+  /*
+   * GPS signals initially optional for this test, so don't expect fast fix,
+   * or no timeout, unless signal is present
+   */
+  int firstGnssLocationTimeoutSeconds = sAgpsIsPresent ? 15 : 45;
+  if (sSignalIsWeak) {
+    // allow more time for weak signals
+    firstGnssLocationTimeoutSeconds += 30;
+  }
+
+  test->wait(firstGnssLocationTimeoutSeconds);
+  if (sAgpsIsPresent) {
+    EXPECT_EQ(test->location_called_count_, 1);
+  }
+  if (test->location_called_count_ > 0) {
+    CheckLocation(test->last_location_, checkAccuracies);
+    return true;
+  }
+  return false;
+}
+
+/*
  * GetLocation:
  * Turns on location, waits 45 second for at least 5 locations,
  * and checks them for reasonable validity.
@@ -279,12 +311,6 @@
 #define PREFERRED_ACCURACY 0   // Ideally perfect (matches GnssLocationProvider)
 #define PREFERRED_TIME_MSEC 0  // Ideally immediate
 
-#if GNSS_ASSISTANCE_IS_PRESENT
-#define LOCATION_TIMEOUT_FIRST_SEC 15
-#else
-#define LOCATION_TIMEOUT_FIRST_SEC 45
-#endif
-
 #define LOCATION_TIMEOUT_SUBSEQUENT_SEC 3
 #define LOCATIONS_TO_CHECK 5
 
@@ -299,26 +325,17 @@
   ASSERT_TRUE(result.isOk());
   EXPECT_TRUE(result);
 
-  result = gnss_hal_->start();
-
-  ASSERT_TRUE(result.isOk());
-  EXPECT_TRUE(result);
-
   /*
    * GPS signals initially optional for this test, so don't expect no timeout
    * yet
    */
-  wait(LOCATION_TIMEOUT_FIRST_SEC);
-  if (GNSS_SIGNAL_IS_PRESENT) {
-    ASSERT_GT(location_called_count_, 0);
-  }
-  if (location_called_count_ > 0) {
-    CheckLocation(last_location_, checkMoreAccuracies);
-  }
+  bool gotLocation = StartAndGetSingleLocation(this, checkMoreAccuracies);
 
-  for (int i = 1; i < LOCATIONS_TO_CHECK; i++) {
-    wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC);
-    if (location_called_count_ > 0) {
+  if (gotLocation) {
+    for (int i = 1; i < LOCATIONS_TO_CHECK; i++) {
+      EXPECT_EQ(std::cv_status::no_timeout,
+          wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC));
+      EXPECT_EQ(location_called_count_, i + 1);
       CheckLocation(last_location_, checkMoreAccuracies);
     }
   }
@@ -332,13 +349,11 @@
 /*
  * InjectDelete:
  * Ensures that calls to inject and/or delete information state are handled.
- * Better tests await GPS signal
  */
 TEST_F(GnssHalTest, InjectDelete) {
   // confidently, well north of Alaska
   auto result = gnss_hal_->injectLocation(80.0, -170.0, 1000.0);
 
-  // TODO: full self-diff including TODO's :)
   ASSERT_TRUE(result.isOk());
   EXPECT_TRUE(result);
 
@@ -351,6 +366,9 @@
   auto resultVoid = gnss_hal_->deleteAidingData(IGnss::GnssAidingData::DELETE_ALL);
 
   ASSERT_TRUE(resultVoid.isOk());
+
+  // Ensure we can get a good location after a bad injection has been deleted
+  StartAndGetSingleLocation(this, false);
 }
 
 /*
@@ -413,6 +431,18 @@
 
 int main(int argc, char** argv) {
   ::testing::InitGoogleTest(&argc, argv);
+  /*
+   * These arguments not used by automated VTS testing.
+   * Only for use in manual testing, when wanting to run
+   * stronger tests that require the presence of GPS signal.
+   */
+  for (int i = 1; i < argc; i++) {
+    if (strcmp(argv[i],"-agps") == 0) {
+      sAgpsIsPresent = true;
+    } else if (strcmp(argv[i],"-weak") == 0) {
+      sSignalIsWeak = true;
+    }
+  }
   int status = RUN_ALL_TESTS();
   ALOGI("Test result = %d", status);
   return status;
diff --git a/graphics/Android.bp b/graphics/Android.bp
index f4f7db4..9aea85f 100644
--- a/graphics/Android.bp
+++ b/graphics/Android.bp
@@ -2,7 +2,6 @@
 subdirs = [
     "allocator/2.0",
     "allocator/2.0/default",
-    "allocator/2.0/vts/functional",
     "bufferqueue/1.0",
     "common/1.0",
     "composer/2.1",
diff --git a/graphics/allocator/2.0/Android.bp b/graphics/allocator/2.0/Android.bp
index 271f2ce..f707468 100644
--- a/graphics/allocator/2.0/Android.bp
+++ b/graphics/allocator/2.0/Android.bp
@@ -3,9 +3,7 @@
 filegroup {
     name: "android.hardware.graphics.allocator@2.0_hal",
     srcs: [
-        "types.hal",
         "IAllocator.hal",
-        "IAllocatorClient.hal",
     ],
 }
 
@@ -17,9 +15,7 @@
         ":android.hardware.graphics.allocator@2.0_hal",
     ],
     out: [
-        "android/hardware/graphics/allocator/2.0/types.cpp",
         "android/hardware/graphics/allocator/2.0/AllocatorAll.cpp",
-        "android/hardware/graphics/allocator/2.0/AllocatorClientAll.cpp",
     ],
 }
 
@@ -31,18 +27,11 @@
         ":android.hardware.graphics.allocator@2.0_hal",
     ],
     out: [
-        "android/hardware/graphics/allocator/2.0/types.h",
-        "android/hardware/graphics/allocator/2.0/hwtypes.h",
         "android/hardware/graphics/allocator/2.0/IAllocator.h",
         "android/hardware/graphics/allocator/2.0/IHwAllocator.h",
         "android/hardware/graphics/allocator/2.0/BnHwAllocator.h",
         "android/hardware/graphics/allocator/2.0/BpHwAllocator.h",
         "android/hardware/graphics/allocator/2.0/BsAllocator.h",
-        "android/hardware/graphics/allocator/2.0/IAllocatorClient.h",
-        "android/hardware/graphics/allocator/2.0/IHwAllocatorClient.h",
-        "android/hardware/graphics/allocator/2.0/BnHwAllocatorClient.h",
-        "android/hardware/graphics/allocator/2.0/BpHwAllocatorClient.h",
-        "android/hardware/graphics/allocator/2.0/BsAllocatorClient.h",
     ],
 }
 
@@ -59,6 +48,7 @@
         "libutils",
         "libcutils",
         "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
         "android.hidl.base@1.0",
     ],
     export_shared_lib_headers: [
@@ -67,6 +57,7 @@
         "libhwbinder",
         "libutils",
         "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
         "android.hidl.base@1.0",
     ],
 }
diff --git a/graphics/allocator/2.0/IAllocator.hal b/graphics/allocator/2.0/IAllocator.hal
index bf0e141..43a3916 100644
--- a/graphics/allocator/2.0/IAllocator.hal
+++ b/graphics/allocator/2.0/IAllocator.hal
@@ -16,38 +16,9 @@
 
 package android.hardware.graphics.allocator@2.0;
 
-import IAllocatorClient;
+import android.hardware.graphics.mapper@2.0;
 
 interface IAllocator {
-    enum Capability : int32_t {
-        /** reserved */
-        INVALID = 0,
-
-        /**
-         * IAllocatorClient::testAllocate must always return UNDEFINED unless
-         * this capability is supported.
-         */
-        TEST_ALLOCATE = 1,
-
-        /**
-         * IAllocatorClient::BufferDescriptorInfo::layerCount must be 1 unless
-         * this capability is supported.
-         */
-        LAYERED_BUFFERS = 2,
-    };
-
-    /**
-     * Provides a list of supported capabilities (as described in the
-     * definition of Capability above). This list must not change after
-     * initialization.
-     *
-     * @return capabilities is a list of supported capabilities.
-     */
-    @entry
-    @exit
-    @callflow(next="*")
-    getCapabilities() generates (vec<Capability> capabilities);
-
     /**
      * Retrieves implementation-defined debug information, which will be
      * displayed during, for example, `dumpsys SurfaceFlinger`.
@@ -60,15 +31,27 @@
     dumpDebugInfo() generates (string debugInfo);
 
     /**
-     * Creates a client of the allocator. All resources created by the client
-     * are owned by the client and are only visible to the client, unless they
-     * are exported by exportHandle.
+     * Allocates buffers with the properties specified by the descriptor.
      *
+     * @param descriptor specifies the properties of the buffers to allocate.
+     * @param count is the number of buffers to allocate.
      * @return error is NONE upon success. Otherwise,
-     *         NO_RESOURCES when no more client can currently be created.
-     * @return client is the newly created client.
+     *         BAD_DESCRIPTOR when the descriptor is invalid.
+     *         NO_RESOURCES when the allocation cannot be fulfilled at this
+     *                      time.
+     *         UNSUPPORTED when any of the property encoded in the descriptor
+     *                     is not supported.
+     * @return stride is the number of pixels between two consecutive rows of
+     *         the buffers, when the concept of consecutive rows is defined.
+     *         Otherwise, it has no meaning.
+     * @return buffers is an array of raw handles to the newly allocated
+     *         buffers.
      */
     @entry
+    @exit
     @callflow(next="*")
-    createClient() generates (Error error, IAllocatorClient client);
+    allocate(BufferDescriptor descriptor, uint32_t count)
+        generates (Error error,
+                   uint32_t stride,
+                   vec<handle> buffers);
 };
diff --git a/graphics/allocator/2.0/IAllocatorClient.hal b/graphics/allocator/2.0/IAllocatorClient.hal
deleted file mode 100644
index 8ca568f..0000000
--- a/graphics/allocator/2.0/IAllocatorClient.hal
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.
- */
-
-package android.hardware.graphics.allocator@2.0;
-
-import android.hardware.graphics.common@1.0::PixelFormat;
-
-interface IAllocatorClient {
-    struct BufferDescriptorInfo {
-        /**
-         * The width specifies how many columns of pixels must be in the
-         * allocated buffer, but does not necessarily represent the offset in
-         * columns between the same column in adjacent rows. The rows may be
-         * padded.
-         */
-        uint32_t width;
-
-       /**
-        * The height specifies how many rows of pixels must be in the
-        * allocated buffer.
-        */
-        uint32_t height;
-
-       /**
-        * The number of image layers that must be in the allocated buffer.
-        */
-        uint32_t layerCount;
-
-        /** Buffer pixel format. */
-        PixelFormat format;
-
-        /**
-         * Buffer producer usage mask; valid flags can be found in the
-         * definition of ProducerUsage.
-         */
-        uint64_t producerUsageMask;
-
-        /**
-         * Buffer consumer usage mask; valid flags can be found in the
-         * definition of ConsumerUsage.
-         */
-        uint64_t consumerUsageMask;
-    };
-
-    /**
-     * Creates a new, opaque buffer descriptor.
-     *
-     * @param descriptorInfo specifies the attributes of the buffer
-     *        descriptor.
-     * @return error is NONE upon success. Otherwise,
-     *         BAD_VALUE when any attribute in descriptorInfo is invalid.
-     *         NO_RESOURCES when no more descriptors can currently be created.
-     * @return descriptor is the newly created buffer descriptor.
-     */
-    @entry
-    @callflow(next="*")
-    createDescriptor(BufferDescriptorInfo descriptorInfo)
-          generates (Error error,
-                     BufferDescriptor descriptor);
-
-    /**
-     * Destroys an existing buffer descriptor.
-     *
-     * @param descriptor is the descriptor to destroy.
-     * @return error is either NONE or BAD_DESCRIPTOR.
-     */
-    @exit
-    @callflow(next="*")
-    destroyDescriptor(BufferDescriptor descriptor) generates (Error error);
-
-    /**
-     * Tests whether a buffer allocation can succeed, ignoring potential
-     * resource contention which might lead to a NO_RESOURCES error.
-     *
-     * @param descriptors is a list of buffer descriptors.
-     * @return error is NONE or NOT_SHARED upon success;
-     *         NONE when buffers can be created and share a backing store.
-     *         NOT_SHARED when buffers can be created but require more than a
-     *                    backing store.
-     *         Otherwise,
-     *         BAD_DESCRIPTOR when any of the descriptors is invalid.
-     *         UNSUPPORTED when any of the descriptors can never be satisfied.
-     *         UNDEFINED when TEST_ALLOCATE is not listed in getCapabilities.
-     */
-    @callflow(next="allocate")
-    testAllocate(vec<BufferDescriptor> descriptors) generates (Error error);
-
-    /**
-     * Attempts to allocate a list of buffers sharing a backing store.
-     *
-     * Each buffer must correspond to one of the descriptors passed into the
-     * function and must hold a reference to its backing store. If the device
-     * is unable to share the backing store between the buffers, it must
-     * attempt to allocate the buffers with different backing stores and
-     * return NOT_SHARED if it is successful.
-     *
-     * @param descriptors is the buffer descriptors to attempt to allocate.
-     * @return error is NONE or NOT_SHARED upon success;
-     *         NONE when buffers can be created and share a backing store.
-     *         NOT_SHARED when buffers can be created but require more than a
-     *                    backing store.
-     *         Otherwise,
-     *         BAD_DESCRIPTOR when any of the descriptors is invalid.
-     *         UNSUPPORTED when any of the descriptors can never be satisfied.
-     *         NO_RESOURCES when any of the buffers cannot be created at this
-     *                      time.
-     * @return buffers is the allocated buffers.
-     */
-    @callflow(next="exportHandle")
-    allocate(vec<BufferDescriptor> descriptors)
-        generates (Error error,
-                   vec<Buffer> buffers);
-
-    /**
-     * Frees a buffer.
-     *
-     * @param buffer is the buffer to be freed.
-     * @return error is NONE upon success. Otherwise,
-     *         BAD_BUFFER when the buffer is invalid.
-     */
-    @exit
-    @callflow(next="*")
-    free(Buffer buffer) generates (Error error);
-
-    /**
-     * Exports a buffer for use in other client libraries or for cross-process
-     * sharing.
-     *
-     * The exported handle is a handle to the backing store of the buffer, not
-     * to the buffer itself. It however may not hold any reference to the
-     * backing store and may be considered invalid by client libraries. To use
-     * it and, in most cases, to save it for later use, a client must make a
-     * clone of the handle and have the cloned handle hold a reference to the
-     * backing store. Such a cloned handle will stay valid even after the
-     * original buffer is freed. Refer to native_handle_clone and IMapper for
-     * how a handle is cloned and how a reference is added.
-     *
-     * @param descriptor is the descriptor used to allocate the buffer.
-     * @param buffer is the buffer to be exported.
-     * @return error is NONE upon success. Otherwise,
-     *         BAD_DESCRIPTOR when the descriptor is invalid.
-     *         BAD_BUFFER when the buffer is invalid.
-     *         BAD_VALUE when descriptor and buffer do not match.
-     *         NO_RESOURCES when the buffer cannot be exported at this time.
-     * @return bufferHandle is the exported handle.
-     */
-    @callflow(next="free")
-    exportHandle(BufferDescriptor descriptor,
-                 Buffer buffer)
-      generates (Error error,
-                 handle bufferHandle);
-};
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index 0baef89..6adfa71 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -3,7 +3,7 @@
     defaults: ["hidl_defaults"],
     proprietary: true,
     relative_install_path: "hw",
-    srcs: ["Gralloc.cpp"],
+    srcs: ["Gralloc.cpp", "Gralloc0Allocator.cpp", "Gralloc1Allocator.cpp"],
     cppflags: ["-Wall", "-Wextra"],
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
@@ -15,6 +15,7 @@
         "liblog",
         "libutils",
     ],
+    static_libs: ["libgrallocmapperincludes"],
 }
 
 cc_binary {
diff --git a/graphics/allocator/2.0/default/Gralloc.cpp b/graphics/allocator/2.0/default/Gralloc.cpp
index 0b9e863..273d3f5 100644
--- a/graphics/allocator/2.0/default/Gralloc.cpp
+++ b/graphics/allocator/2.0/default/Gralloc.cpp
@@ -16,17 +16,11 @@
 
 #define LOG_TAG "GrallocPassthrough"
 
-#include <mutex>
-#include <type_traits>
-#include <unordered_set>
-#include <vector>
-
-#include <string.h>
-
-#include <hardware/gralloc1.h>
-#include <log/log.h>
-
 #include "Gralloc.h"
+#include "Gralloc0Allocator.h"
+#include "Gralloc1Allocator.h"
+
+#include <log/log.h>
 
 namespace android {
 namespace hardware {
@@ -35,417 +29,6 @@
 namespace V2_0 {
 namespace implementation {
 
-class GrallocHal : public IAllocator {
-public:
-    GrallocHal(const hw_module_t* module);
-    virtual ~GrallocHal();
-
-    // IAllocator interface
-    Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
-    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-    Return<void> createClient(createClient_cb hidl_cb) override;
-
-    Error createDescriptor(
-            const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-            BufferDescriptor* outDescriptor);
-    Error destroyDescriptor(BufferDescriptor descriptor);
-
-    Error testAllocate(const hidl_vec<BufferDescriptor>& descriptors);
-    Error allocate(const hidl_vec<BufferDescriptor>& descriptors,
-            hidl_vec<Buffer>* outBuffers);
-    Error free(Buffer buffer);
-
-    Error exportHandle(Buffer buffer, const native_handle_t** outHandle);
-
-private:
-    void initCapabilities();
-
-    template<typename T>
-    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
-    void initDispatch();
-
-    bool hasCapability(Capability capability) const;
-
-    gralloc1_device_t* mDevice;
-
-    std::unordered_set<Capability> mCapabilities;
-
-    struct {
-        GRALLOC1_PFN_DUMP dump;
-        GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
-        GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
-        GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
-        GRALLOC1_PFN_SET_FORMAT setFormat;
-        GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
-        GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
-        GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
-        GRALLOC1_PFN_ALLOCATE allocate;
-        GRALLOC1_PFN_RELEASE release;
-    } mDispatch;
-};
-
-class GrallocClient : public IAllocatorClient {
-public:
-    GrallocClient(GrallocHal& hal);
-    virtual ~GrallocClient();
-
-    // IAllocatorClient interface
-    Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
-            createDescriptor_cb hidl_cb) override;
-    Return<Error> destroyDescriptor(BufferDescriptor descriptor) override;
-
-    Return<Error> testAllocate(
-            const hidl_vec<BufferDescriptor>& descriptors) override;
-    Return<void> allocate(const hidl_vec<BufferDescriptor>& descriptors,
-            allocate_cb hidl_cb) override;
-    Return<Error> free(Buffer buffer) override;
-
-    Return<void> exportHandle(BufferDescriptor descriptor,
-            Buffer buffer, exportHandle_cb hidl_cb) override;
-
-private:
-    GrallocHal& mHal;
-
-    std::mutex mMutex;
-    std::unordered_set<BufferDescriptor> mDescriptors;
-    std::unordered_set<Buffer> mBuffers;
-};
-
-GrallocHal::GrallocHal(const hw_module_t* module)
-    : mDevice(nullptr), mDispatch()
-{
-    int status = gralloc1_open(module, &mDevice);
-    if (status) {
-        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
-                strerror(-status));
-    }
-
-    initCapabilities();
-    initDispatch();
-}
-
-GrallocHal::~GrallocHal()
-{
-    gralloc1_close(mDevice);
-}
-
-void GrallocHal::initCapabilities()
-{
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<Capability> caps(count);
-    mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
-              std::underlying_type<Capability>::type*>(caps.data()));
-    caps.resize(count);
-
-    mCapabilities.insert(caps.cbegin(), caps.cend());
-}
-
-template<typename T>
-void GrallocHal::initDispatch(gralloc1_function_descriptor_t desc, T* outPfn)
-{
-    auto pfn = mDevice->getFunction(mDevice, desc);
-    if (!pfn) {
-        LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
-    }
-
-    *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void GrallocHal::initDispatch()
-{
-    initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump);
-    initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR,
-            &mDispatch.createDescriptor);
-    initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR,
-            &mDispatch.destroyDescriptor);
-    initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions);
-    initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat);
-    if (hasCapability(Capability::LAYERED_BUFFERS)) {
-        initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT,
-                &mDispatch.setLayerCount);
-    }
-    initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE,
-            &mDispatch.setConsumerUsage);
-    initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE,
-            &mDispatch.setProducerUsage);
-    initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate);
-    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
-}
-
-bool GrallocHal::hasCapability(Capability capability) const
-{
-    return (mCapabilities.count(capability) > 0);
-}
-
-Return<void> GrallocHal::getCapabilities(getCapabilities_cb hidl_cb)
-{
-    std::vector<Capability> caps(
-            mCapabilities.cbegin(), mCapabilities.cend());
-
-    hidl_vec<Capability> reply;
-    reply.setToExternal(caps.data(), caps.size());
-    hidl_cb(reply);
-
-    return Void();
-}
-
-Return<void> GrallocHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
-{
-    uint32_t len = 0;
-    mDispatch.dump(mDevice, &len, nullptr);
-
-    std::vector<char> buf(len + 1);
-    mDispatch.dump(mDevice, &len, buf.data());
-    buf.resize(len + 1);
-    buf[len] = '\0';
-
-    hidl_string reply;
-    reply.setToExternal(buf.data(), len);
-    hidl_cb(reply);
-
-    return Void();
-}
-
-Return<void> GrallocHal::createClient(createClient_cb hidl_cb)
-{
-    sp<IAllocatorClient> client = new GrallocClient(*this);
-    hidl_cb(Error::NONE, client);
-
-    return Void();
-}
-
-Error GrallocHal::createDescriptor(
-        const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-        BufferDescriptor* outDescriptor)
-{
-    gralloc1_buffer_descriptor_t descriptor;
-    int32_t err = mDispatch.createDescriptor(mDevice, &descriptor);
-    if (err != GRALLOC1_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    err = mDispatch.setDimensions(mDevice, descriptor,
-            descriptorInfo.width, descriptorInfo.height);
-    if (err == GRALLOC1_ERROR_NONE) {
-        err = mDispatch.setFormat(mDevice, descriptor,
-                static_cast<int32_t>(descriptorInfo.format));
-    }
-    if (err == GRALLOC1_ERROR_NONE) {
-        if (hasCapability(Capability::LAYERED_BUFFERS)) {
-            err = mDispatch.setLayerCount(mDevice, descriptor,
-                    descriptorInfo.layerCount);
-        } else if (descriptorInfo.layerCount != 1) {
-            err = GRALLOC1_ERROR_BAD_VALUE;
-        }
-    }
-    if (err == GRALLOC1_ERROR_NONE) {
-        uint64_t producerUsageMask = descriptorInfo.producerUsageMask;
-        if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN) {
-            producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
-        }
-        if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN) {
-            producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
-        }
-        err = mDispatch.setProducerUsage(mDevice, descriptor,
-                descriptorInfo.producerUsageMask);
-    }
-    if (err == GRALLOC1_ERROR_NONE) {
-        uint64_t consumerUsageMask = descriptorInfo.consumerUsageMask;
-        if (consumerUsageMask & GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) {
-            consumerUsageMask |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
-        }
-        err = mDispatch.setConsumerUsage(mDevice, descriptor,
-                consumerUsageMask);
-    }
-
-    if (err == GRALLOC1_ERROR_NONE) {
-        *outDescriptor = descriptor;
-    } else {
-        mDispatch.destroyDescriptor(mDevice, descriptor);
-    }
-
-    return static_cast<Error>(err);
-}
-
-Error GrallocHal::destroyDescriptor(BufferDescriptor descriptor)
-{
-    int32_t err = mDispatch.destroyDescriptor(mDevice, descriptor);
-    return static_cast<Error>(err);
-}
-
-Error GrallocHal::testAllocate(const hidl_vec<BufferDescriptor>& descriptors)
-{
-    if (!hasCapability(Capability::TEST_ALLOCATE)) {
-        return Error::UNDEFINED;
-    }
-
-    int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
-            descriptors.data(), nullptr);
-    return static_cast<Error>(err);
-}
-
-Error GrallocHal::allocate(const hidl_vec<BufferDescriptor>& descriptors,
-        hidl_vec<Buffer>* outBuffers)
-{
-    std::vector<buffer_handle_t> buffers(descriptors.size());
-    int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
-            descriptors.data(), buffers.data());
-    if (err == GRALLOC1_ERROR_NONE || err == GRALLOC1_ERROR_NOT_SHARED) {
-        outBuffers->resize(buffers.size());
-        for (size_t i = 0; i < outBuffers->size(); i++) {
-            (*outBuffers)[i] = static_cast<Buffer>(
-                    reinterpret_cast<uintptr_t>(buffers[i]));
-        }
-    }
-
-    return static_cast<Error>(err);
-}
-
-Error GrallocHal::free(Buffer buffer)
-{
-    buffer_handle_t handle = reinterpret_cast<buffer_handle_t>(
-            static_cast<uintptr_t>(buffer));
-
-    int32_t err = mDispatch.release(mDevice, handle);
-    return static_cast<Error>(err);
-}
-
-Error GrallocHal::exportHandle(Buffer buffer,
-        const native_handle_t** outHandle)
-{
-    // we rely on the caller to validate buffer here
-    *outHandle = reinterpret_cast<buffer_handle_t>(
-            static_cast<uintptr_t>(buffer));
-    return Error::NONE;
-}
-
-GrallocClient::GrallocClient(GrallocHal& hal)
-    : mHal(hal)
-{
-}
-
-GrallocClient::~GrallocClient()
-{
-    if (!mBuffers.empty()) {
-        ALOGW("client destroyed with valid buffers");
-        for (auto buf : mBuffers) {
-            mHal.free(buf);
-        }
-    }
-
-    if (!mDescriptors.empty()) {
-        ALOGW("client destroyed with valid buffer descriptors");
-        for (auto desc : mDescriptors) {
-            mHal.destroyDescriptor(desc);
-        }
-    }
-}
-
-Return<void> GrallocClient::createDescriptor(
-        const BufferDescriptorInfo& descriptorInfo,
-        createDescriptor_cb hidl_cb)
-{
-    BufferDescriptor descriptor = 0;
-    Error err = mHal.createDescriptor(descriptorInfo, &descriptor);
-
-    if (err == Error::NONE) {
-        std::lock_guard<std::mutex> lock(mMutex);
-
-        auto result = mDescriptors.insert(descriptor);
-        if (!result.second) {
-            ALOGW("duplicated buffer descriptor id returned");
-            mHal.destroyDescriptor(descriptor);
-            err = Error::NO_RESOURCES;
-        }
-    }
-
-    hidl_cb(err, descriptor);
-    return Void();
-}
-
-Return<Error> GrallocClient::destroyDescriptor(BufferDescriptor descriptor)
-{
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        if (!mDescriptors.erase(descriptor)) {
-            return Error::BAD_DESCRIPTOR;
-        }
-    }
-
-    return mHal.destroyDescriptor(descriptor);
-}
-
-Return<Error> GrallocClient::testAllocate(
-        const hidl_vec<BufferDescriptor>& descriptors)
-{
-    return mHal.testAllocate(descriptors);
-}
-
-Return<void> GrallocClient::allocate(
-        const hidl_vec<BufferDescriptor>& descriptors,
-        allocate_cb hidl_cb) {
-    hidl_vec<Buffer> buffers;
-    Error err = mHal.allocate(descriptors, &buffers);
-
-    if (err == Error::NONE || err == Error::NOT_SHARED) {
-        std::lock_guard<std::mutex> lock(mMutex);
-
-        for (size_t i = 0; i < buffers.size(); i++) {
-            auto result = mBuffers.insert(buffers[i]);
-            if (!result.second) {
-                ALOGW("duplicated buffer id returned");
-
-                for (size_t j = 0; j < buffers.size(); j++) {
-                    if (j < i) {
-                        mBuffers.erase(buffers[i]);
-                    }
-                    mHal.free(buffers[i]);
-                }
-
-                buffers = hidl_vec<Buffer>();
-                err = Error::NO_RESOURCES;
-                break;
-            }
-        }
-    }
-
-    hidl_cb(err, buffers);
-    return Void();
-}
-
-Return<Error> GrallocClient::free(Buffer buffer)
-{
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        if (!mBuffers.erase(buffer)) {
-            return Error::BAD_BUFFER;
-        }
-    }
-
-    return mHal.free(buffer);
-}
-
-Return<void> GrallocClient::exportHandle(BufferDescriptor /*descriptor*/,
-        Buffer buffer, exportHandle_cb hidl_cb)
-{
-    const native_handle_t* handle = nullptr;
-
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        if (mBuffers.count(buffer) == 0) {
-            hidl_cb(Error::BAD_BUFFER, handle);
-            return Void();
-        }
-    }
-
-    Error err = mHal.exportHandle(buffer, &handle);
-
-    hidl_cb(err, handle);
-    return Void();
-}
-
 IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
     const hw_module_t* module = nullptr;
     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
@@ -455,12 +38,15 @@
     }
 
     uint8_t major = (module->module_api_version >> 8) & 0xff;
-    if (major != 1) {
-        ALOGE("unknown gralloc module major version %d", major);
-        return nullptr;
+    switch (major) {
+        case 1:
+            return new Gralloc1Allocator(module);
+        case 0:
+            return new Gralloc0Allocator(module);
+        default:
+            ALOGE("unknown gralloc module major version %d", major);
+            return nullptr;
     }
-
-    return new GrallocHal(module);
 }
 
 } // namespace implementation
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.cpp b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
new file mode 100644
index 0000000..3b62bb3
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "Gralloc0Allocator"
+
+#include "Gralloc0Allocator.h"
+#include "GrallocBufferDescriptor.h"
+
+#include <vector>
+
+#include <string.h>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::mapper::V2_0::implementation::
+    grallocDecodeBufferDescriptor;
+
+Gralloc0Allocator::Gralloc0Allocator(const hw_module_t* module) {
+    int result = gralloc_open(module, &mDevice);
+    if (result) {
+        LOG_ALWAYS_FATAL("failed to open gralloc0 device: %s",
+                         strerror(-result));
+    }
+}
+
+Gralloc0Allocator::~Gralloc0Allocator() {
+    gralloc_close(mDevice);
+}
+
+Return<void> Gralloc0Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
+    char buf[4096] = {};
+    if (mDevice->dump) {
+        mDevice->dump(mDevice, buf, sizeof(buf));
+        buf[sizeof(buf) - 1] = '\0';
+    }
+
+    hidl_cb(hidl_string(buf));
+
+    return Void();
+}
+
+Return<void> Gralloc0Allocator::allocate(const BufferDescriptor& descriptor,
+                                         uint32_t count, allocate_cb hidl_cb) {
+    IMapper::BufferDescriptorInfo descriptorInfo;
+    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+        hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
+        return Void();
+    }
+
+    Error error = Error::NONE;
+    uint32_t stride = 0;
+    std::vector<hidl_handle> buffers;
+    buffers.reserve(count);
+
+    // allocate the buffers
+    for (uint32_t i = 0; i < count; i++) {
+        buffer_handle_t tmpBuffer;
+        uint32_t tmpStride;
+        error = allocateOne(descriptorInfo, &tmpBuffer, &tmpStride);
+        if (error != Error::NONE) {
+            break;
+        }
+
+        if (stride == 0) {
+            stride = tmpStride;
+        } else if (stride != tmpStride) {
+            // non-uniform strides
+            mDevice->free(mDevice, tmpBuffer);
+            stride = 0;
+            error = Error::UNSUPPORTED;
+            break;
+        }
+
+        buffers.emplace_back(hidl_handle(tmpBuffer));
+    }
+
+    // return the buffers
+    hidl_vec<hidl_handle> hidl_buffers;
+    if (error == Error::NONE) {
+        hidl_buffers.setToExternal(buffers.data(), buffers.size());
+    }
+    hidl_cb(error, stride, hidl_buffers);
+
+    // free the buffers
+    for (const auto& buffer : buffers) {
+        mDevice->free(mDevice, buffer.getNativeHandle());
+    }
+
+    return Void();
+}
+
+Error Gralloc0Allocator::allocateOne(const IMapper::BufferDescriptorInfo& info,
+                                     buffer_handle_t* outBuffer,
+                                     uint32_t* outStride) {
+    if (info.layerCount > 1 || (info.usage >> 32) != 0) {
+        return Error::BAD_VALUE;
+    }
+
+    buffer_handle_t buffer = nullptr;
+    int stride = 0;
+    int result = mDevice->alloc(mDevice, info.width, info.height,
+                                static_cast<int>(info.format), info.usage,
+                                &buffer, &stride);
+    if (result) {
+        switch (result) {
+            case -EINVAL:
+                return Error::BAD_VALUE;
+            default:
+                return Error::NO_RESOURCES;
+        }
+    }
+
+    *outBuffer = buffer;
+    *outStride = stride;
+
+    return Error::NONE;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.h b/graphics/allocator/2.0/default/Gralloc0Allocator.h
new file mode 100644
index 0000000..0e90527
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc0Allocator.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 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 ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
+#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <hardware/gralloc.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::mapper::V2_0::IMapper;
+using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
+using android::hardware::graphics::mapper::V2_0::Error;
+
+class Gralloc0Allocator : public IAllocator {
+   public:
+    Gralloc0Allocator(const hw_module_t* module);
+    virtual ~Gralloc0Allocator();
+
+    // IAllocator interface
+    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
+    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
+                          allocate_cb hidl_cb) override;
+
+   private:
+    Error allocateOne(const IMapper::BufferDescriptorInfo& info,
+                      buffer_handle_t* outBuffer, uint32_t* outStride);
+
+    alloc_device_t* mDevice;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.cpp b/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
new file mode 100644
index 0000000..c0a5e1e
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "Gralloc1Allocator"
+
+#include "Gralloc1Allocator.h"
+#include "GrallocBufferDescriptor.h"
+
+#include <vector>
+
+#include <string.h>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using android::hardware::graphics::mapper::V2_0::implementation::
+    grallocDecodeBufferDescriptor;
+
+Gralloc1Allocator::Gralloc1Allocator(const hw_module_t* module)
+    : mDevice(nullptr), mCapabilities(), mDispatch() {
+    int result = gralloc1_open(module, &mDevice);
+    if (result) {
+        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
+                         strerror(-result));
+    }
+
+    initCapabilities();
+    initDispatch();
+}
+
+Gralloc1Allocator::~Gralloc1Allocator() {
+    gralloc1_close(mDevice);
+}
+
+void Gralloc1Allocator::initCapabilities() {
+    uint32_t count = 0;
+    mDevice->getCapabilities(mDevice, &count, nullptr);
+
+    std::vector<int32_t> capabilities(count);
+    mDevice->getCapabilities(mDevice, &count, capabilities.data());
+    capabilities.resize(count);
+
+    for (auto capability : capabilities) {
+        if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
+            mCapabilities.layeredBuffers = true;
+            break;
+        }
+    }
+}
+
+template <typename T>
+void Gralloc1Allocator::initDispatch(gralloc1_function_descriptor_t desc,
+                                     T* outPfn) {
+    auto pfn = mDevice->getFunction(mDevice, desc);
+    if (!pfn) {
+        LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
+    }
+
+    *outPfn = reinterpret_cast<T>(pfn);
+}
+
+void Gralloc1Allocator::initDispatch() {
+    initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump);
+    initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR,
+                 &mDispatch.createDescriptor);
+    initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR,
+                 &mDispatch.destroyDescriptor);
+    initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions);
+    initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat);
+    if (mCapabilities.layeredBuffers) {
+        initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT,
+                     &mDispatch.setLayerCount);
+    }
+    initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE,
+                 &mDispatch.setConsumerUsage);
+    initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE,
+                 &mDispatch.setProducerUsage);
+    initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
+    initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate);
+    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
+}
+
+Return<void> Gralloc1Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
+    uint32_t len = 0;
+    mDispatch.dump(mDevice, &len, nullptr);
+
+    std::vector<char> buf(len + 1);
+    mDispatch.dump(mDevice, &len, buf.data());
+    buf.resize(len + 1);
+    buf[len] = '\0';
+
+    hidl_string reply;
+    reply.setToExternal(buf.data(), len);
+    hidl_cb(reply);
+
+    return Void();
+}
+
+Return<void> Gralloc1Allocator::allocate(const BufferDescriptor& descriptor,
+                                         uint32_t count, allocate_cb hidl_cb) {
+    IMapper::BufferDescriptorInfo descriptorInfo;
+    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+        hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
+        return Void();
+    }
+
+    gralloc1_buffer_descriptor_t desc;
+    Error error = createDescriptor(descriptorInfo, &desc);
+    if (error != Error::NONE) {
+        hidl_cb(error, 0, hidl_vec<hidl_handle>());
+        return Void();
+    }
+
+    uint32_t stride = 0;
+    std::vector<hidl_handle> buffers;
+    buffers.reserve(count);
+
+    // allocate the buffers
+    for (uint32_t i = 0; i < count; i++) {
+        buffer_handle_t tmpBuffer;
+        uint32_t tmpStride;
+        error = allocateOne(desc, &tmpBuffer, &tmpStride);
+        if (error != Error::NONE) {
+            break;
+        }
+
+        if (stride == 0) {
+            stride = tmpStride;
+        } else if (stride != tmpStride) {
+            // non-uniform strides
+            mDispatch.release(mDevice, tmpBuffer);
+            stride = 0;
+            error = Error::UNSUPPORTED;
+            break;
+        }
+
+        buffers.emplace_back(hidl_handle(tmpBuffer));
+    }
+
+    mDispatch.destroyDescriptor(mDevice, desc);
+
+    // return the buffers
+    hidl_vec<hidl_handle> hidl_buffers;
+    if (error == Error::NONE) {
+        hidl_buffers.setToExternal(buffers.data(), buffers.size());
+    }
+    hidl_cb(error, stride, hidl_buffers);
+
+    // free the buffers
+    for (const auto& buffer : buffers) {
+        mDispatch.release(mDevice, buffer.getNativeHandle());
+    }
+
+    return Void();
+}
+
+Error Gralloc1Allocator::toError(int32_t error) {
+    switch (error) {
+        case GRALLOC1_ERROR_NONE:
+            return Error::NONE;
+        case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+            return Error::BAD_DESCRIPTOR;
+        case GRALLOC1_ERROR_BAD_HANDLE:
+            return Error::BAD_BUFFER;
+        case GRALLOC1_ERROR_BAD_VALUE:
+            return Error::BAD_VALUE;
+        case GRALLOC1_ERROR_NOT_SHARED:
+            return Error::NONE;  // this is fine
+        case GRALLOC1_ERROR_NO_RESOURCES:
+            return Error::NO_RESOURCES;
+        case GRALLOC1_ERROR_UNDEFINED:
+        case GRALLOC1_ERROR_UNSUPPORTED:
+        default:
+            return Error::UNSUPPORTED;
+    }
+}
+
+uint64_t Gralloc1Allocator::toProducerUsage(uint64_t usage) {
+    // this is potentially broken as we have no idea which private flags
+    // should be filtered out
+    uint64_t producerUsage =
+        usage &
+        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK |
+                               BufferUsage::CPU_WRITE_MASK);
+
+    switch (usage & BufferUsage::CPU_WRITE_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    switch (usage & BufferUsage::CPU_READ_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    return producerUsage;
+}
+
+uint64_t Gralloc1Allocator::toConsumerUsage(uint64_t usage) {
+    // this is potentially broken as we have no idea which private flags
+    // should be filtered out
+    uint64_t consumerUsage =
+        usage &
+        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK |
+                               BufferUsage::CPU_WRITE_MASK);
+
+    switch (usage & BufferUsage::CPU_READ_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    return consumerUsage;
+}
+
+Error Gralloc1Allocator::createDescriptor(
+    const IMapper::BufferDescriptorInfo& info,
+    gralloc1_buffer_descriptor_t* outDescriptor) {
+    gralloc1_buffer_descriptor_t descriptor;
+
+    int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setDimensions(mDevice, descriptor, info.width,
+                                        info.height);
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setFormat(mDevice, descriptor,
+                                    static_cast<int32_t>(info.format));
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        if (mCapabilities.layeredBuffers) {
+            error =
+                mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
+        } else if (info.layerCount > 1) {
+            error = GRALLOC1_ERROR_UNSUPPORTED;
+        }
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setProducerUsage(mDevice, descriptor,
+                                           toProducerUsage(info.usage));
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setConsumerUsage(mDevice, descriptor,
+                                           toConsumerUsage(info.usage));
+    }
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        *outDescriptor = descriptor;
+    } else {
+        mDispatch.destroyDescriptor(mDevice, descriptor);
+    }
+
+    return toError(error);
+}
+
+Error Gralloc1Allocator::allocateOne(gralloc1_buffer_descriptor_t descriptor,
+                                     buffer_handle_t* outBuffer,
+                                     uint32_t* outStride) {
+    buffer_handle_t buffer = nullptr;
+    int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
+    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
+        return toError(error);
+    }
+
+    uint32_t stride = 0;
+    error = mDispatch.getStride(mDevice, buffer, &stride);
+    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
+        mDispatch.release(mDevice, buffer);
+        return toError(error);
+    }
+
+    *outBuffer = buffer;
+    *outStride = stride;
+
+    return Error::NONE;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.h b/graphics/allocator/2.0/default/Gralloc1Allocator.h
new file mode 100644
index 0000000..7b5a966
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc1Allocator.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 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 ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
+#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <hardware/gralloc1.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::mapper::V2_0::IMapper;
+using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
+using android::hardware::graphics::mapper::V2_0::Error;
+
+class Gralloc1Allocator : public IAllocator {
+   public:
+    Gralloc1Allocator(const hw_module_t* module);
+    virtual ~Gralloc1Allocator();
+
+    // IAllocator interface
+    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
+    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
+                          allocate_cb hidl_cb) override;
+
+   private:
+    void initCapabilities();
+
+    template <typename T>
+    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
+    void initDispatch();
+
+    static Error toError(int32_t error);
+    static uint64_t toProducerUsage(uint64_t usage);
+    static uint64_t toConsumerUsage(uint64_t usage);
+
+    Error createDescriptor(const IMapper::BufferDescriptorInfo& info,
+                           gralloc1_buffer_descriptor_t* outDescriptor);
+    Error allocateOne(gralloc1_buffer_descriptor_t descriptor,
+                      buffer_handle_t* outBuffer, uint32_t* outStride);
+
+    gralloc1_device_t* mDevice;
+
+    struct {
+        bool layeredBuffers;
+    } mCapabilities;
+
+    struct {
+        GRALLOC1_PFN_DUMP dump;
+        GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
+        GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
+        GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
+        GRALLOC1_PFN_SET_FORMAT setFormat;
+        GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
+        GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
+        GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
+        GRALLOC1_PFN_GET_STRIDE getStride;
+        GRALLOC1_PFN_ALLOCATE allocate;
+        GRALLOC1_PFN_RELEASE release;
+    } mDispatch;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
diff --git a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp b/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
index f722429..be055ec 100644
--- a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
+++ b/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
@@ -25,7 +25,7 @@
 
 #include <hardware/gralloc.h>
 
-#include <utils/Log.h>
+#include <log/log.h>
 #include <sync/sync.h>
 
 #include <inttypes.h>
diff --git a/graphics/allocator/2.0/types.hal b/graphics/allocator/2.0/types.hal
deleted file mode 100644
index d9b184b..0000000
--- a/graphics/allocator/2.0/types.hal
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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.
- */
-
-package android.hardware.graphics.allocator@2.0;
-
-enum Error : int32_t {
-    NONE            = 0, /** no error */
-    BAD_DESCRIPTOR  = 1, /** invalid BufferDescriptor */
-    BAD_BUFFER      = 2, /** invalid Buffer */
-    BAD_VALUE       = 3, /** invalid width, height, etc. */
-    NOT_SHARED      = 4, /** buffers not sharing backing store */
-    NO_RESOURCES    = 5, /** temporary failure due to resource contention */
-    UNDEFINED       = 6, /** an operation has no defined meaning */
-    UNSUPPORTED     = 7, /** permanent failure */
-};
-
-enum ProducerUsage : uint64_t {
-    /** bit 0 is reserved */
-
-    /** buffer is read by CPU occasionally */
-    CPU_READ        = 1ULL << 1,
-    /** buffer is read by CPU frequently */
-    CPU_READ_OFTEN  = 1ULL << 2,
-
-    /** bit 3 is reserved */
-    /** bit 4 is reserved */
-
-    /** buffer is written by CPU occasionally */
-    CPU_WRITE       = 1ULL << 5,
-    /** buffer is written by CPU frequently */
-    CPU_WRITE_OFTEN = 1ULL << 6,
-
-    /** bit 7 is reserved */
-    /** bit 8 is reserved */
-
-    /** buffer is used as a GPU render target */
-    GPU_RENDER_TARGET = 1ULL << 9,
-
-    /** bit 10 is reserved */
-    /** bit 11 is reserved */
-    /** bit 12 is reserved */
-    /** bit 13 is reserved */
-
-    /**
-     * Buffer is allocated with hardware-level protection against copying the
-     * contents (or information derived from the contents) into unprotected
-     * memory.
-     */
-    PROTECTED         = 1ULL << 14,
-
-    /** bit 15 is reserved */
-    /** bit 16 is reserved */
-
-    /** buffer is used as a camera HAL output */
-    CAMERA            = 1ULL << 17,
-
-    /** bit 18 is reserved */
-    /** bit 19 is reserved */
-    /** bit 20 is reserved */
-    /** bit 21 is reserved */
-
-    /** buffer is used as a video decoder output */
-    VIDEO_DECODER     = 1ULL << 22,
-
-    /** buffer is used as a sensor direct report output */
-    SENSOR_DIRECT_DATA = 1ULL << 23,
-
-    /** bits 24-27 are reserved for future versions */
-    /** bits 28-31 are reserved for vendor extensions */
-
-    /** bits 32-47 are reserved for future versions */
-    /** bits 48-63 are reserved for vendor extensions */
-};
-
-enum ConsumerUsage : uint64_t {
-    /** bit 0 is reserved */
-
-    /** buffer is read by CPU occasionally */
-    CPU_READ          = 1ULL << 1,
-    /** buffer is read by CPU frequently */
-    CPU_READ_OFTEN    = 1ULL << 2,
-
-    /** bit 3 is reserved */
-    /** bit 4 is reserved */
-    /** bit 5 is reserved */
-    /** bit 6 is reserved */
-    /** bit 7 is reserved */
-
-    /** buffer is used as a GPU texture */
-    GPU_TEXTURE       = 1ULL << 8,
-
-    /** bit 9 is reserved */
-    /** bit 10 is reserved */
-
-    /** buffer is used by hwcomposer HAL */
-    HWCOMPOSER        = 1ULL << 11,
-    /** buffer is a hwcomposer HAL client target */
-    CLIENT_TARGET     = 1ULL << 12,
-
-    /** bit 13 is reserved */
-    /** bit 14 is reserved */
-
-    /** buffer is used as a hwcomposer HAL cursor */
-    CURSOR            = 1ULL << 15,
-
-    /** buffer is used as a video encoder input */
-    VIDEO_ENCODER     = 1ULL << 16,
-
-    /** bit 17 is reserved */
-
-    /** buffer is used as a camera HAL input */
-    CAMERA            = 1ULL << 18,
-
-    /** bit 19 is reserved */
-
-    /** buffer is used as a renderscript allocation */
-    RENDERSCRIPT      = 1ULL << 20,
-
-    /** bit 21 is reserved */
-    /** bit 22 is reserved */
-
-    /**
-     * buffer is used as as an OpenGL shader storage or uniform
-       buffer object */
-    GPU_DATA_BUFFER    = 1ULL << 23,
-
-    /** bits 24-27 are reserved for future versions */
-    /** bits 28-31 are reserved for vendor extensions */
-
-    /** bits 32-47 are reserved for future versions */
-    /** bits 48-63 are reserved for vendor extensions */
-};
-
-typedef uint64_t BufferDescriptor;
-typedef uint64_t Buffer;
diff --git a/graphics/allocator/2.0/vts/functional/Android.bp b/graphics/allocator/2.0/vts/functional/Android.bp
deleted file mode 100644
index fb77ab3..0000000
--- a/graphics/allocator/2.0/vts/functional/Android.bp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// 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.
-//
-
-cc_library_static {
-    name: "libVtsHalGraphicsAllocatorTestUtils",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalGraphicsAllocatorTestUtils.cpp"],
-    shared_libs: [
-        "android.hardware.graphics.allocator@2.0",
-    ],
-    static_libs: [
-        "VtsHalHidlTargetTestBase",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-    ],
-    export_include_dirs: ["."],
-}
-
-cc_test {
-    name: "VtsHalGraphicsAllocatorV2_0TargetTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalGraphicsAllocatorV2_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.graphics.allocator@2.0",
-    ],
-    static_libs: [
-        "libVtsHalGraphicsAllocatorTestUtils",
-        "VtsHalHidlTargetTestBase",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-    ]
-}
diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp
deleted file mode 100644
index 0dc43be..0000000
--- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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.
- */
-
-#include <VtsHalHidlTargetTestBase.h>
-
-#include "VtsHalGraphicsAllocatorTestUtils.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace tests {
-
-Allocator::Allocator() { init(); }
-
-void Allocator::init() {
-  mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>();
-  ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
-
-  std::vector<IAllocator::Capability> capabilities = getCapabilities();
-  mCapabilities.insert(capabilities.begin(), capabilities.end());
-}
-
-sp<IAllocator> Allocator::getRaw() const { return mAllocator; }
-
-bool Allocator::hasCapability(IAllocator::Capability capability) const {
-  return mCapabilities.count(capability) > 0;
-}
-
-std::vector<IAllocator::Capability> Allocator::getCapabilities() {
-  std::vector<IAllocator::Capability> capabilities;
-  mAllocator->getCapabilities(
-      [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
-
-  return capabilities;
-}
-
-std::string Allocator::dumpDebugInfo() {
-  std::string debugInfo;
-  mAllocator->dumpDebugInfo(
-      [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
-  return debugInfo;
-}
-
-std::unique_ptr<AllocatorClient> Allocator::createClient() {
-  std::unique_ptr<AllocatorClient> client;
-  mAllocator->createClient([&](const auto& tmpError, const auto& tmpClient) {
-    ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
-    client = std::make_unique<AllocatorClient>(tmpClient);
-  });
-
-  return client;
-}
-
-AllocatorClient::AllocatorClient(const sp<IAllocatorClient>& client)
-    : mClient(client) {}
-
-AllocatorClient::~AllocatorClient() {
-  for (auto buffer : mBuffers) {
-    EXPECT_EQ(Error::NONE, mClient->free(buffer))
-        << "failed to free buffer " << buffer;
-  }
-  mBuffers.clear();
-
-  for (auto descriptor : mDescriptors) {
-    EXPECT_EQ(Error::NONE, mClient->destroyDescriptor(descriptor))
-        << "failed to destroy descriptor " << descriptor;
-  }
-  mDescriptors.clear();
-}
-
-sp<IAllocatorClient> AllocatorClient::getRaw() const { return mClient; }
-
-BufferDescriptor AllocatorClient::createDescriptor(
-    const IAllocatorClient::BufferDescriptorInfo& info) {
-  BufferDescriptor descriptor = 0;
-  mClient->createDescriptor(
-      info, [&](const auto& tmpError, const auto& tmpDescriptor) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
-        descriptor = tmpDescriptor;
-
-        EXPECT_TRUE(mDescriptors.insert(descriptor).second)
-            << "duplicated descriptor id " << descriptor;
-      });
-
-  return descriptor;
-}
-
-void AllocatorClient::destroyDescriptor(BufferDescriptor descriptor) {
-  ASSERT_EQ(Error::NONE, mClient->destroyDescriptor(descriptor))
-      << "failed to destroy descriptor " << descriptor;
-
-  mDescriptors.erase(descriptor);
-}
-
-Error AllocatorClient::testAllocate(
-    const std::vector<BufferDescriptor>& descriptors) {
-  return mClient->testAllocate(descriptors);
-}
-
-bool AllocatorClient::testAllocate(BufferDescriptor descriptor) {
-  std::vector<BufferDescriptor> descriptors(1, descriptor);
-  Error error = testAllocate(descriptors);
-  return (error == Error::NONE || error == Error::NOT_SHARED);
-}
-
-Error AllocatorClient::allocate(
-    const std::vector<BufferDescriptor>& descriptors,
-    std::vector<Buffer>& buffers) {
-  Error error = Error::NO_RESOURCES;
-  mClient->allocate(descriptors, [&](const auto& tmpError,
-                                     const auto& tmpBuffers) {
-    ASSERT_TRUE(tmpError == Error::NONE || tmpError == Error::NOT_SHARED)
-        << "failed to allocate buffer";
-    ASSERT_EQ(descriptors.size(), tmpBuffers.size()) << "invalid buffer count";
-
-    error = tmpError;
-    buffers = tmpBuffers;
-
-    for (auto buffer : buffers) {
-      EXPECT_TRUE(mBuffers.insert(buffer).second)
-          << "duplicated buffer id " << buffer;
-    }
-  });
-
-  return error;
-}
-
-Buffer AllocatorClient::allocate(BufferDescriptor descriptor) {
-  std::vector<BufferDescriptor> descriptors(1, descriptor);
-  std::vector<Buffer> buffers;
-  allocate(descriptors, buffers);
-  if (::testing::Test::HasFatalFailure()) {
-    return 0;
-  }
-
-  return buffers[0];
-}
-
-void AllocatorClient::free(Buffer buffer) {
-  ASSERT_EQ(Error::NONE, mClient->free(buffer))
-      << "failed to free buffer " << buffer;
-
-  mBuffers.erase(buffer);
-}
-
-native_handle_t* AllocatorClient::exportHandle(BufferDescriptor descriptor,
-                                               Buffer buffer) {
-  native_handle_t* handle;
-  mClient->exportHandle(
-      descriptor, buffer, [&](const auto& tmpError, const auto& tmpHandle) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to export buffer handle";
-        ASSERT_NE(nullptr, tmpHandle.getNativeHandle())
-            << "invalid buffer handle";
-
-        handle = native_handle_clone(tmpHandle.getNativeHandle());
-        ASSERT_NE(nullptr, handle) << "failed to clone handle";
-      });
-
-  return handle;
-}
-
-}  // namespace tests
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h
deleted file mode 100644
index c9bfe8f..0000000
--- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 VTS_HAL_GRAPHICS_ALLOCATOR_UTILS
-#define VTS_HAL_GRAPHICS_ALLOCATOR_UTILS
-
-#include <memory>
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace tests {
-
-class AllocatorClient;
-
-// A wrapper to IAllocator.
-class Allocator {
- public:
-  Allocator();
-
-  sp<IAllocator> getRaw() const;
-
-  // Returns true when the allocator supports the specified capability.
-  bool hasCapability(IAllocator::Capability capability) const;
-
-  std::vector<IAllocator::Capability> getCapabilities();
-  std::string dumpDebugInfo();
-  std::unique_ptr<AllocatorClient> createClient();
-
- private:
-  void init();
-
-  sp<IAllocator> mAllocator;
-  std::unordered_set<IAllocator::Capability> mCapabilities;
-};
-
-// A wrapper to IAllocatorClient.
-class AllocatorClient {
- public:
-  AllocatorClient(const sp<IAllocatorClient>& client);
-  ~AllocatorClient();
-
-  sp<IAllocatorClient> getRaw() const;
-
-  BufferDescriptor createDescriptor(
-      const IAllocatorClient::BufferDescriptorInfo& info);
-  void destroyDescriptor(BufferDescriptor descriptor);
-
-  Error testAllocate(const std::vector<BufferDescriptor>& descriptors);
-  bool testAllocate(BufferDescriptor descriptor);
-
-  Error allocate(const std::vector<BufferDescriptor>& descriptors,
-                 std::vector<Buffer>& buffers);
-  Buffer allocate(BufferDescriptor descriptor);
-  void free(Buffer buffer);
-
-  // Returns a handle to the buffer.  The ownership of the handle is
-  // transferred to the caller.
-  native_handle_t* exportHandle(BufferDescriptor descriptor, Buffer buffer);
-
- private:
-  sp<IAllocatorClient> mClient;
-
-  // Keep track of all descriptors and buffers.  When a test fails with
-  // ASSERT_*, the destructor will clean up the resources for the test.
-  std::unordered_set<BufferDescriptor> mDescriptors;
-  std::unordered_set<Buffer> mBuffers;
-};
-
-}  // namespace tests
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // VTS_HAL_GRAPHICS_ALLOCATOR_UTILS
diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp
deleted file mode 100644
index b1c764f..0000000
--- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "graphics_allocator_hidl_hal_test"
-
-#include <android-base/logging.h>
-#include <VtsHalHidlTargetTestBase.h>
-
-#include "VtsHalGraphicsAllocatorTestUtils.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace tests {
-namespace {
-
-using android::hardware::graphics::common::V1_0::PixelFormat;
-
-#define CHECK_FEATURE_OR_SKIP(FEATURE_NAME)                 \
-  do {                                                      \
-    if (!mAllocator->hasCapability(FEATURE_NAME)) {         \
-      std::cout << "[  SKIPPED ] Feature " << #FEATURE_NAME \
-                << " not supported" << std::endl;           \
-      return;                                               \
-    }                                                       \
-  } while (0)
-
-class GraphicsAllocatorHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- protected:
-  void SetUp() override {
-    ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique<Allocator>());
-    ASSERT_NO_FATAL_FAILURE(mClient = mAllocator->createClient());
-
-    mDummyDescriptorInfo.width = 64;
-    mDummyDescriptorInfo.height = 64;
-    mDummyDescriptorInfo.layerCount = 1;
-    mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
-    mDummyDescriptorInfo.producerUsageMask =
-        static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
-    mDummyDescriptorInfo.consumerUsageMask =
-        static_cast<uint64_t>(ConsumerUsage::CPU_READ);
-  }
-
-  void TearDown() override {}
-
-  std::unique_ptr<Allocator> mAllocator;
-  std::unique_ptr<AllocatorClient> mClient;
-  IAllocatorClient::BufferDescriptorInfo mDummyDescriptorInfo{};
-};
-
-TEST_F(GraphicsAllocatorHidlTest, GetCapabilities) {
-  auto capabilities = mAllocator->getCapabilities();
-  for (auto cap : capabilities) {
-    EXPECT_NE(IAllocator::Capability::INVALID, cap);
-  }
-}
-
-TEST_F(GraphicsAllocatorHidlTest, DumpDebugInfo) {
-  mAllocator->dumpDebugInfo();
-}
-
-TEST_F(GraphicsAllocatorHidlTest, CreateDestroyDescriptor) {
-  BufferDescriptor descriptor;
-  ASSERT_NO_FATAL_FAILURE(descriptor =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-  mClient->destroyDescriptor(descriptor);
-}
-
-/**
- * Test testAllocate with a single buffer descriptor.
- */
-TEST_F(GraphicsAllocatorHidlTest, TestAllocateBasic) {
-  CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE);
-
-  BufferDescriptor descriptor;
-  ASSERT_NO_FATAL_FAILURE(descriptor =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  ASSERT_TRUE(mClient->testAllocate(descriptor));
-}
-
-/**
- * Test testAllocate with two buffer descriptors.
- */
-TEST_F(GraphicsAllocatorHidlTest, TestAllocateArray) {
-  CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE);
-
-  BufferDescriptor descriptor;
-  ASSERT_NO_FATAL_FAILURE(descriptor =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  hidl_vec<BufferDescriptor> descriptors;
-  descriptors.resize(2);
-  descriptors[0] = descriptor;
-  descriptors[1] = descriptor;
-
-  auto error = mClient->testAllocate(descriptors);
-  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
-}
-
-/**
- * Test allocate/free with a single buffer descriptor.
- */
-TEST_F(GraphicsAllocatorHidlTest, AllocateFreeBasic) {
-  BufferDescriptor descriptor;
-  ASSERT_NO_FATAL_FAILURE(descriptor =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  Buffer buffer;
-  ASSERT_NO_FATAL_FAILURE(buffer = mClient->allocate(descriptor));
-
-  mClient->free(buffer);
-}
-
-/**
- * Test allocate/free with an array of buffer descriptors.
- */
-TEST_F(GraphicsAllocatorHidlTest, AllocateFreeArray) {
-  BufferDescriptor descriptor1;
-  ASSERT_NO_FATAL_FAILURE(descriptor1 =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  BufferDescriptor descriptor2;
-  ASSERT_NO_FATAL_FAILURE(descriptor2 =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  hidl_vec<BufferDescriptor> descriptors;
-  descriptors.resize(3);
-  descriptors[0] = descriptor1;
-  descriptors[1] = descriptor1;
-  descriptors[2] = descriptor2;
-
-  std::vector<Buffer> buffers;
-  ASSERT_NO_FATAL_FAILURE(mClient->allocate(descriptors, buffers));
-
-  for (auto buf : buffers) {
-    mClient->free(buf);
-  }
-}
-
-TEST_F(GraphicsAllocatorHidlTest, ExportHandle) {
-  BufferDescriptor descriptor;
-  ASSERT_NO_FATAL_FAILURE(descriptor =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  Buffer buffer;
-  ASSERT_NO_FATAL_FAILURE(buffer = mClient->allocate(descriptor));
-
-  native_handle_t* handle;
-  ASSERT_NO_FATAL_FAILURE(handle = mClient->exportHandle(descriptor, buffer));
-
-  native_handle_close(handle);
-  native_handle_delete(handle);
-}
-
-}  // namespace anonymous
-}  // namespace tests
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-
-  int status = RUN_ALL_TESTS();
-  LOG(INFO) << "Test result = " << status;
-
-  return status;
-}
diff --git a/graphics/common/1.0/Android.mk b/graphics/common/1.0/Android.mk
index c08053d..ae80c6a 100644
--- a/graphics/common/1.0/Android.mk
+++ b/graphics/common/1.0/Android.mk
@@ -13,6 +13,25 @@
 HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
 
 #
+# Build types.hal (BufferUsage)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/BufferUsage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.BufferUsage
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (ColorMode)
 #
 GEN := $(intermediates)/android/hardware/graphics/common/V1_0/ColorMode.java
@@ -139,6 +158,25 @@
 HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
 
 #
+# Build types.hal (BufferUsage)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/BufferUsage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.BufferUsage
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (ColorMode)
 #
 GEN := $(intermediates)/android/hardware/graphics/common/V1_0/ColorMode.java
diff --git a/graphics/common/1.0/types.hal b/graphics/common/1.0/types.hal
index 979e4c4..3bd1ec1 100644
--- a/graphics/common/1.0/types.hal
+++ b/graphics/common/1.0/types.hal
@@ -181,9 +181,17 @@
      *    - GRALLOC_USAGE_SW_*
      *    - GRALLOC_USAGE_RENDERSCRIPT
      *
-     * When used with ANativeWindow, the dataSpace should be
-     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
-     * extra metadata to define.
+     * When used with ANativeWindow, the mapping of the dataSpace field to
+     * buffer contents for RAW16 is as follows:
+     *
+     *  dataSpace value               | Buffer contents
+     * -------------------------------+-----------------------------------------
+     *  HAL_DATASPACE_ARBITRARY       | Raw image sensor data, layout is as
+     *                                | defined above.
+     *  HAL_DATASPACE_DEPTH           | Unprocessed implementation-dependent raw
+     *                                | depth measurements, opaque with 16 bit
+     *                                | samples.
+     *  Other                         | Unsupported
      */
     RAW16 = 0x20,
 
@@ -442,6 +450,90 @@
 };
 
 /**
+ * Buffer usage definitions.
+ */
+enum BufferUsage : uint64_t {
+    /** bit 0-3 is an enum */
+    CPU_READ_MASK   = 0xfULL,
+    /** buffer is never read by CPU */
+    CPU_READ_NEVER  = 0,
+    /** buffer is rarely read by CPU */
+    CPU_READ_RARELY = 2,
+    /** buffer is often read by CPU */
+    CPU_READ_OFTEN  = 3,
+
+    /** bit 4-7 is an enum */
+    CPU_WRITE_MASK   = 0xfULL << 4,
+    /** buffer is never written by CPU */
+    CPU_WRITE_NEVER  = 0 << 4,
+    /** buffer is rarely written by CPU */
+    CPU_WRITE_RARELY = 2 << 4,
+    /** buffer is often written by CPU */
+    CPU_WRITE_OFTEN  = 3 << 4,
+
+    /** buffer is used as a GPU texture */
+    GPU_TEXTURE       = 1ULL << 8,
+
+    /** buffer is used as a GPU render target */
+    GPU_RENDER_TARGET = 1ULL << 9,
+
+    /** bit 10 must be zero */
+
+    /** buffer is used as a composer HAL overlay layer */
+    COMPOSER_OVERLAY  = 1ULL << 11,
+    /** buffer is used as a composer HAL client target */
+    COMPOSER_CLIENT_TARGET = 1ULL << 12,
+
+    /** bit 13 must be zero */
+
+    /**
+     * Buffer is allocated with hardware-level protection against copying the
+     * contents (or information derived from the contents) into unprotected
+     * memory.
+     */
+    PROTECTED         = 1ULL << 14,
+
+    /** buffer is used as a hwcomposer HAL cursor layer */
+    COMPOSER_CURSOR   = 1ULL << 15,
+
+    /** buffer is used as a video encoder input */
+    VIDEO_ENCODER     = 1ULL << 16,
+
+    /** buffer is used as a camera HAL output */
+    CAMERA_OUTPUT     = 1ULL << 17,
+
+    /** buffer is used as a camera HAL input */
+    CAMERA_INPUT      = 1ULL << 18,
+
+    /** bit 19 must be zero */
+
+    /** buffer is used as a renderscript allocation */
+    RENDERSCRIPT      = 1ULL << 20,
+
+    /** bit 21 must be zero */
+
+    /** buffer is used as a video decoder output */
+    VIDEO_DECODER     = 1ULL << 22,
+
+    /** buffer is used as a sensor direct report output */
+    SENSOR_DIRECT_DATA = 1ULL << 23,
+
+    /**
+     * buffer is used as as an OpenGL shader storage or uniform
+     * buffer object
+     */
+    GPU_DATA_BUFFER   = 1ULL << 24,
+
+    /** bits 25-27 must be zero and are reserved for future versions */
+    /** bits 28-31 are reserved for vendor extensions */
+    VENDOR_MASK       = 0xfULL << 28,
+
+    /** bits 32-47 must be zero and are reserved for future versions */
+    /** bits 48-63 are reserved for vendor extensions */
+    VENDOR_MASK_HI    = 0xffffULL << 48,
+};
+
+/**
  * Transformation definitions
  *
  * IMPORTANT NOTE:
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 8e1f925..66323d4 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -52,7 +52,6 @@
     ],
     static_libs: [
         "libhwcomposer-command-buffer",
-        "libVtsHalGraphicsAllocatorTestUtils",
         "libVtsHalGraphicsComposerTestUtils",
         "libVtsHalGraphicsMapperTestUtils",
         "VtsHalHidlTargetTestBase",
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 0da3a33..387222f 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -18,7 +18,6 @@
 
 #include <IComposerCommandBuffer.h>
 #include <android-base/logging.h>
-#include "VtsHalGraphicsAllocatorTestUtils.h"
 #include "VtsHalGraphicsComposerTestUtils.h"
 #include "VtsHalGraphicsMapperTestUtils.h"
 
@@ -40,22 +39,15 @@
 namespace tests {
 namespace {
 
-using android::hardware::graphics::allocator::V2_0::Buffer;
-using android::hardware::graphics::allocator::V2_0::BufferDescriptor;
-using android::hardware::graphics::allocator::V2_0::ConsumerUsage;
-using android::hardware::graphics::allocator::V2_0::IAllocator;
-using android::hardware::graphics::allocator::V2_0::IAllocatorClient;
-using android::hardware::graphics::allocator::V2_0::ProducerUsage;
-using android::hardware::graphics::allocator::V2_0::tests::Allocator;
-using android::hardware::graphics::allocator::V2_0::tests::AllocatorClient;
+using android::hardware::graphics::common::V1_0::BufferUsage;
 using android::hardware::graphics::common::V1_0::ColorMode;
 using android::hardware::graphics::common::V1_0::ColorTransform;
 using android::hardware::graphics::common::V1_0::Dataspace;
 using android::hardware::graphics::common::V1_0::PixelFormat;
 using android::hardware::graphics::common::V1_0::Transform;
 using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::tests::Mapper;
-using GrallocError = android::hardware::graphics::allocator::V2_0::Error;
+using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
+using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
 
 // IComposerCallback to be installed with IComposerClient::registerCallback.
 class GraphicsComposerCallback : public IComposerCallback {
@@ -409,9 +401,7 @@
   void SetUp() override {
     ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
 
-    ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique<Allocator>());
-    ASSERT_NO_FATAL_FAILURE(mAllocatorClient = mAllocator->createClient());
-    ASSERT_NO_FATAL_FAILURE(mMapper = std::make_unique<Mapper>());
+    ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
 
     mWriter = std::make_unique<CommandWriterBase>(1024);
     mReader = std::make_unique<CommandReader>();
@@ -422,15 +412,15 @@
   }
 
   const native_handle_t* allocate() {
-    IAllocatorClient::BufferDescriptorInfo info{};
-    info.width = 64;
-    info.height = 64;
-    info.layerCount = 1;
-    info.format = PixelFormat::RGBA_8888;
-    info.producerUsageMask = static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
-    info.consumerUsageMask = static_cast<uint64_t>(ConsumerUsage::CPU_READ);
+      IMapper::BufferDescriptorInfo info{};
+      info.width = 64;
+      info.height = 64;
+      info.layerCount = 1;
+      info.format = PixelFormat::RGBA_8888;
+      info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN |
+                                         BufferUsage::CPU_READ_OFTEN);
 
-    return mMapper->allocate(mAllocatorClient, info);
+      return mGralloc->allocate(info);
   }
 
   void execute() {
@@ -507,9 +497,7 @@
   std::unique_ptr<CommandReader> mReader;
 
  private:
-  std::unique_ptr<Allocator> mAllocator;
-  std::unique_ptr<AllocatorClient> mAllocatorClient;
-  std::unique_ptr<Mapper> mMapper;
+  std::unique_ptr<Gralloc> mGralloc;
 };
 
 /**
diff --git a/graphics/mapper/2.0/Android.bp b/graphics/mapper/2.0/Android.bp
index 98a509b..cc2bd73 100644
--- a/graphics/mapper/2.0/Android.bp
+++ b/graphics/mapper/2.0/Android.bp
@@ -51,7 +51,6 @@
         "liblog",
         "libutils",
         "libcutils",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
@@ -60,7 +59,6 @@
         "libhidltransport",
         "libhwbinder",
         "libutils",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
diff --git a/graphics/mapper/2.0/IMapper.hal b/graphics/mapper/2.0/IMapper.hal
index 573dcd0..246be24 100644
--- a/graphics/mapper/2.0/IMapper.hal
+++ b/graphics/mapper/2.0/IMapper.hal
@@ -16,10 +16,39 @@
 
 package android.hardware.graphics.mapper@2.0;
 
-import android.hardware.graphics.common@1.0::PixelFormat;
-import android.hardware.graphics.allocator@2.0;
+import android.hardware.graphics.common@1.0;
 
 interface IMapper {
+    struct BufferDescriptorInfo {
+        /**
+         * The width specifies how many columns of pixels must be in the
+         * allocated buffer, but does not necessarily represent the offset in
+         * columns between the same column in adjacent rows. The rows may be
+         * padded.
+         */
+        uint32_t width;
+
+       /**
+        * The height specifies how many rows of pixels must be in the
+        * allocated buffer.
+        */
+        uint32_t height;
+
+       /**
+        * The number of image layers that must be in the allocated buffer.
+        */
+        uint32_t layerCount;
+
+        /** Buffer pixel format. */
+        PixelFormat format;
+
+        /**
+         * Buffer usage mask; valid flags can be found in the definition of
+         * BufferUsage.
+         */
+        bitfield<BufferUsage> usage;
+    };
+
     struct Rect {
         int32_t left;
         int32_t top;
@@ -28,170 +57,76 @@
     };
 
     /**
-     * Adds a reference to the given buffer handle.
+     * Creates a buffer descriptor. The descriptor can be used with IAllocator
+     * to allocate buffers.
      *
-     * A buffer handle received from a remote process or exported by
-     * IAllocator::exportHandle is unknown to the mapper. There is also no
-     * guarantee that the buffer's backing store will stay alive. This
-     * function must be called at least once in both cases to intrdouce the
-     * buffer handle to the mapper and to secure the backing store. It may
-     * also be called more than once to increase the reference count if two
-     * components in the same process want to interact with the buffer
-     * independently.
+     * Since the buffer descriptor fully describes a buffer, any device
+     * dependent or device independent checks must be performed here whenever
+     * possible. Specifically, when layered buffers are not supported, this
+     * function must return UNSUPPORTED if layerCount is great than 1.
      *
-     * @param bufferHandle is the buffer to which a reference must be added.
+     * @param descriptorInfo specifies the attributes of the descriptor.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid
-     *                  NO_RESOURCES when it is not possible to add a
-     *                               reference to this buffer at this time
+     *                  BAD_VALUE when any of the specified attributes is
+     *                            invalid or conflicting.
+     *                  NO_RESOURCES when the creation cannot be fullfilled at
+     *                               this time.
+     *                  UNSUPPORTED when any of the specified attributes is
+     *                              not supported.
+     * @return descriptor is the newly created buffer descriptor.
      */
     @entry
     @callflow(next="*")
-    retain(handle bufferHandle) generates (Error error);
+    createDescriptor(BufferDescriptorInfo descriptorInfo)
+          generates (Error error,
+                     BufferDescriptor descriptor);
 
     /**
-     * Removes a reference from the given buffer buffer.
+     * Imports a raw buffer handle to create an imported buffer handle for use
+     * with the rest of the mapper or with other in-process libraries.
      *
-     * If no references remain, the buffer handle must be freed with
-     * native_handle_close/native_handle_delete by the mapper. When the last
-     * buffer handle referring to a particular backing store is freed, that
-     * backing store must also be freed.
+     * A buffer handle is considered raw when it is cloned or when it is
+     * received from another HAL or another process. A raw buffer handle must
+     * not be used to access the underlying graphics buffer. It must be
+     * imported to create an imported handle first.
      *
-     * @param bufferHandle is the buffer from which a reference must be
-     *        removed.
+     * This function must at least validate the raw handle before creating the
+     * imported handle. It must also support importing the same raw handle
+     * multiple times to create multiple imported handles. The imported handle
+     * must be considered valid everywhere in the process, including in
+     * another instance of the mapper.
+     *
+     * @param rawHandle is the raw buffer handle to import.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
+     *                  BAD_BUFFER when the raw handle is invalid.
+     *                  NO_RESOURCES when the raw handle cannot be imported at
+     *                               this time.
+     * @return buffer is the imported buffer handle and has the type
+     *         buffer_handle_t.
+     */
+    @entry
+    @callflow(next="*")
+    importBuffer(handle rawHandle) generates (Error error, pointer buffer);
+
+    /**
+     * Frees a buffer handle. Buffer handles returned by importBuffer must be
+     * freed with this function when no longer needed.
+     *
+     * This function must free up all resources allocated by importBuffer for
+     * the imported handle. For example, if the imported handle was created
+     * with native_handle_create, this function must call native_handle_close
+     * and native_handle_delete.
+     *
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer is invalid.
      */
     @exit
-    release(handle bufferHandle) generates (Error error);
-
-    /**
-     * Gets the width and height of the buffer in pixels.
-     *
-     * See IAllocator::BufferDescriptorInfo for more information.
-     *
-     * @param bufferHandle is the buffer from which to get the dimensions.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return width is the width of the buffer in pixels.
-     * @return height is the height of the buffer in pixels.
-     */
     @callflow(next="*")
-    getDimensions(handle bufferHandle)
-       generates (Error error,
-                  uint32_t width,
-                  uint32_t height);
-
-    /**
-     * Gets the format of the buffer.
-     *
-     * See IAllocator::BufferDescriptorInfo for more information.
-     *
-     * @param bufferHandle is the buffer from which to get format.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return format is the format of the buffer.
-     */
-    @callflow(next="*")
-    getFormat(handle bufferHandle)
-        generates (Error error,
-                   PixelFormat format);
-
-    /**
-     * Gets the number of layers of the buffer.
-     *
-     * See IAllocator::BufferDescriptorInfo for more information.
-     *
-     * @param bufferHandle is the buffer from which to get format.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return layerCount is the number of layers of the buffer.
-     */
-    @callflow(next="*")
-    getLayerCount(handle bufferHandle)
-       generates (Error error,
-                  uint32_t layerCount);
-
-    /**
-     * Gets the producer usage flags which were used to allocate this buffer.
-     *
-     * See IAllocator::BufferDescriptorInfo for more information.
-     *
-     * @param bufferHandle is the buffer from which to get the producer usage
-     *        flags.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return usageMask contains the producer usage flags of the buffer.
-     */
-    @callflow(next="*")
-    getProducerUsageMask(handle bufferHandle)
-              generates (Error error,
-                         uint64_t usageMask);
-
-    /**
-     * Gets the consumer usage flags which were used to allocate this buffer.
-     *
-     * See IAllocator::BufferDescriptorInfo for more information.
-     *
-     * @param bufferHandle is the buffer from which to get the consumer usage
-     *        flags.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return usageMask contains the consumer usage flags of the buffer.
-     */
-    @callflow(next="*")
-    getConsumerUsageMask(handle bufferHandle)
-              generates (Error error,
-                         uint64_t usageMask);
-
-    /**
-     * Gets a value that uniquely identifies the backing store of the given
-     * buffer.
-     *
-     * Buffers which share a backing store should return the same value from
-     * this function. If the buffer is present in more than one process, the
-     * backing store value for that buffer is not required to be the same in
-     * every process.
-     *
-     * @param device is the mapper device.
-     * @param bufferHandle is the buffer from which to get the backing store
-     *        identifier.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return store is the backing store identifier for this buffer.
-     */
-    @callflow(next="*")
-    getBackingStore(handle bufferHandle)
-         generates (Error error,
-                    BackingStore store);
-
-    /**
-     * Gets the stride of the buffer in pixels.
-     *
-     * The stride is the offset in pixel-sized elements between the same
-     * column in two adjacent rows of pixels. This may not be equal to the
-     * width of the buffer.
-     *
-     * @param device is the mapper device.
-     * @param bufferHandle is the buffer from which to get the stride.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     *                  UNDEFINED when the notion of a stride is not
-     *                            meaningful for the buffer format.
-     * @return store is the stride in pixels.
-     */
-    @callflow(next="*")
-    getStride(handle bufferHandle)
-        generates (Error error,
-                   uint32_t stride);
+    freeBuffer(pointer buffer) generates (Error error);
 
     /**
      * Locks the given buffer for the specified CPU usage.
      *
-     * Exactly one of producerUsageMask and consumerUsageMask must be 0. The
-     * usage which is not 0 must be one of the *Usage::CPU* values, as
-     * applicable. Locking a buffer for a non-CPU usage is not supported.
-     *
      * Locking the same buffer simultaneously from multiple threads is
      * permitted, but if any of the threads attempt to lock the buffer for
      * writing, the behavior is undefined, except that it must not cause
@@ -209,39 +144,27 @@
      * address will represent the top-left corner of the entire buffer, even
      * if accessRegion does not begin at the top-left corner.
      *
-     * acquireFence is a file descriptor referring to a acquire sync fence
-     * object, which will be signaled when it is safe for the device to access
-     * the contents of the buffer (prior to locking). If it is already safe to
-     * access the buffer contents, -1 may be passed instead.
-     *
-     * @param bufferHandle is the buffer to lock.
-     * @param producerUsageMask contains the producer usage flags to request;
-     *        either this or consumerUsagemask must be 0, and the other must
-     *        be a CPU usage.
-     * @param consumerUsageMask contains the consumer usage flags to request;
-     *        either this or producerUsageMask must be 0, and the other must
-     *        be a CPU usage.
+     * @param buffer is the buffer to lock.
+     * @param cpuUsage specifies one or more CPU usage flags to request.
      * @param accessRegion is the portion of the buffer that the client
      *        intends to access.
-     * @param acquireFence is a sync fence file descriptor as described above.
+     * @param acquireFence, when non-empty, is a handle containing a file
+     *        descriptor referring to a sync fence object, which will be
+     *        signaled when it is safe for the mapper to lock the buffer. If
+     *        it is already safe to lock, acquireFence is empty.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     *                  BAD_VALUE when neither or both of producerUsageMask
-     *                            and consumerUsageMask were 0, or the usage
-     *                            which was not 0 was not a CPU usage.
+     *                  BAD_BUFFER when the buffer is invalid or is
+     *                             incompatible with this function.
+     *                  BAD_VALUE when cpuUsage is 0, contains non-CPU usage
+     *                            flags, or is incompatible with the buffer.
      *                  NO_RESOURCES when the buffer cannot be locked at this
      *                               time, but locking may succeed at a future
      *                               time.
-     *                  UNSUPPORTED when the buffer cannot be locked with the
-     *                              given usage, and any future attempts at
-     *                              locking will also fail.
-     * @return data will be filled with a CPU-accessible pointer to the buffer
-     *         data.
+     * @return data is a CPU-accessible pointer to the buffer data.
      */
     @callflow(next="unlock")
-    lock(handle bufferHandle,
-         uint64_t producerUsageMask,
-         uint64_t consumerUsageMask,
+    lock(pointer buffer,
+         bitfield<BufferUsage> cpuUsage,
          Rect accessRegion,
          handle acquireFence)
         generates (Error error,
@@ -249,7 +172,7 @@
 
     /**
      * This is largely the same as lock(), except that instead of returning a
-     * pointer directly to the buffer data, it returns an FlexLayout struct
+     * pointer directly to the buffer data, it returns an YCbCrLayout struct
      * describing how to access the data planes.
      *
      * This function must work on buffers with PixelFormat::YCbCr_*_888 if
@@ -257,67 +180,46 @@
      * multimedia codecs when they are configured with a
      * flexible-YUV-compatible color format.
      *
-     * This function may also be called on buffers of other formats, including
-     * non-YUV formats, but if the buffer format is not compatible with a
-     * flexible representation, it may return UNSUPPORTED.
-     *
-     * @param device is the mapper device.
-     * @param bufferHandle is the buffer to lock.
-     * @param producerUsageMask contains the producer usage flags to request;
-     *        either this or consumerUsagemask must be 0, and the other must
-     *        be a CPU usage.
-     * @param consumerUsageMask contains the consumer usage flags to request;
-     *        either this or producerUsageMask must be 0, and the other must
-     *        be a CPU usage.
+     * @param buffer is the buffer to lock.
+     * @param cpuUsage specifies one or more CPU usage flags to request.
      * @param accessRegion is the portion of the buffer that the client
      *        intends to access.
-     * @param acquireFence is a sync fence file descriptor as described in
-     *        lock().
+     * @param acquireFence, when non-empty, is a handle containing a file
+     *        descriptor referring to a sync fence object, which will be
+     *        signaled when it is safe for the mapper to lock the buffer. If
+     *        it is already safe to lock, acquireFence is empty.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     *                  BAD_VALUE when neither or both of producerUsageMask
-     *                            and consumerUsageMask were 0, or the usage
-     *                            which was not 0 was not a CPU usage.
+     *                  BAD_BUFFER when the buffer is invalid or is
+     *                             incompatible with this function.
+     *                  BAD_VALUE when cpuUsage is 0, contains non-CPU usage
+     *                            flags, or is incompatible with the buffer.
      *                  NO_RESOURCES when the buffer cannot be locked at this
      *                               time, but locking may succeed at a future
      *                               time.
-     *                  UNSUPPORTED when the buffer cannot be locked with the
-     *                              given usage, and any future attempts at
-     *                              locking will also fail.
-     * @return flexLayout will be filled with the description of the planes in
-     *         the buffer.
+     * @return layout is the data layout of the buffer.
      */
     @callflow(next="unlock")
-    lockFlex(handle bufferHandle,
-             uint64_t producerUsageMask,
-             uint64_t consumerUsageMask,
-             Rect accessRegion,
-             handle acquireFence)
+    lockYCbCr(pointer buffer,
+              bitfield<BufferUsage> cpuUsage,
+              Rect accessRegion,
+              handle acquireFence)
         generates (Error error,
-                   FlexLayout layout);
+                   YCbCrLayout layout);
 
     /**
-     * This function indicates to the device that the client will be done with
-     * the buffer when releaseFence signals.
+     * Unlocks a buffer to indicate all CPU accesses to the buffer have
+     * completed.
      *
-     * releaseFence will be filled with a file descriptor referring to a
-     * release sync fence object, which will be signaled when it is safe to
-     * access the contents of the buffer (after the buffer has been unlocked).
-     * If it is already safe to access the buffer contents, then -1 may be
-     * returned instead.
-     *
-     * This function is used to unlock both buffers locked by lock() and those
-     * locked by lockFlex().
-     *
-     * @param device is the mapper device.
-     * @param bufferHandle is the buffer to unlock.
+     * @param buffer is the buffer to unlock.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return releaseFence is a sync fence file descriptor as described
-     *         above.
+     *                  BAD_BUFFER when the buffer is invalid or not locked.
+     * @return releaseFence, when non-empty, is a handle containing a file
+     *         descriptor referring to a sync fence object. The sync fence
+     *         object will be signaled when the mapper has completed any
+     *         pending work.
      */
     @callflow(next="*")
-    unlock(handle bufferHandle)
+    unlock(pointer buffer)
         generates (Error error,
                    handle releaseFence);
 };
diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp
index 1dc5aea..090c61f 100644
--- a/graphics/mapper/2.0/default/Android.bp
+++ b/graphics/mapper/2.0/default/Android.bp
@@ -18,10 +18,9 @@
     defaults: ["hidl_defaults"],
     proprietary: true,
     relative_install_path: "hw",
-    srcs: ["GrallocMapper.cpp"],
+    srcs: ["GrallocMapper.cpp", "Gralloc0Mapper.cpp", "Gralloc1Mapper.cpp"],
     cppflags: ["-Wall", "-Wextra"],
     shared_libs: [
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
         "libbase",
         "libcutils",
@@ -29,6 +28,12 @@
         "libhidlbase",
         "libhidltransport",
         "liblog",
+        "libsync",
         "libutils",
     ],
 }
+
+cc_library_static {
+    name: "libgrallocmapperincludes",
+    export_include_dirs: ["."],
+}
diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.cpp b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp
new file mode 100644
index 0000000..28f5016
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "Gralloc0Mapper"
+
+#include "Gralloc0Mapper.h"
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+Gralloc0Mapper::Gralloc0Mapper(const hw_module_t* module)
+    : mModule(reinterpret_cast<const gralloc_module_t*>(module)),
+      mMinor(module->module_api_version & 0xff) {
+    mCapabilities.highUsageBits = false;
+    mCapabilities.layeredBuffers = false;
+    mCapabilities.unregisterImplyDelete = false;
+}
+
+Error Gralloc0Mapper::registerBuffer(buffer_handle_t bufferHandle) {
+    int result = mModule->registerBuffer(mModule, bufferHandle);
+    return result ? Error::BAD_BUFFER : Error::NONE;
+}
+
+void Gralloc0Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
+    mModule->unregisterBuffer(mModule, bufferHandle);
+}
+
+Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
+                                 uint64_t cpuUsage,
+                                 const IMapper::Rect& accessRegion, int fenceFd,
+                                 void** outData) {
+    int result;
+    void* data = nullptr;
+    if (mMinor >= 3 && mModule->lockAsync) {
+        // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
+        // gralloc's responsibility to close it, even on locking errors.
+        if (fenceFd >= 0) {
+            fenceFd = dup(fenceFd);
+            if (fenceFd < 0) {
+                return Error::NO_RESOURCES;
+            }
+        }
+
+        result = mModule->lockAsync(mModule, bufferHandle, cpuUsage,
+                                    accessRegion.left, accessRegion.top,
+                                    accessRegion.width, accessRegion.height,
+                                    &data, fenceFd);
+    } else {
+        waitFenceFd(fenceFd, "Gralloc0Mapper::lock");
+
+        result = mModule->lock(mModule, bufferHandle, cpuUsage,
+                               accessRegion.left, accessRegion.top,
+                               accessRegion.width, accessRegion.height, &data);
+    }
+
+    if (result) {
+        return Error::BAD_VALUE;
+    } else {
+        *outData = data;
+        return Error::NONE;
+    }
+}
+
+Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
+                                 uint64_t cpuUsage,
+                                 const IMapper::Rect& accessRegion, int fenceFd,
+                                 YCbCrLayout* outLayout) {
+    int result;
+    android_ycbcr ycbcr = {};
+    if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
+        // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
+        // gralloc's responsibility to close it, even on locking errors.
+        if (fenceFd >= 0) {
+            fenceFd = dup(fenceFd);
+            if (fenceFd < 0) {
+                return Error::NO_RESOURCES;
+            }
+        }
+
+        result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage,
+                                          accessRegion.left, accessRegion.top,
+                                          accessRegion.width,
+                                          accessRegion.height, &ycbcr, fenceFd);
+    } else {
+        waitFenceFd(fenceFd, "Gralloc0Mapper::lockYCbCr");
+
+        if (mModule->lock_ycbcr) {
+            result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage,
+                                         accessRegion.left, accessRegion.top,
+                                         accessRegion.width,
+                                         accessRegion.height, &ycbcr);
+        } else {
+            result = -EINVAL;
+        }
+    }
+
+    if (result) {
+        return Error::BAD_VALUE;
+    } else {
+        outLayout->y = ycbcr.y;
+        outLayout->cb = ycbcr.cb;
+        outLayout->cr = ycbcr.cr;
+        outLayout->yStride = ycbcr.ystride;
+        outLayout->cStride = ycbcr.cstride;
+        outLayout->chromaStep = ycbcr.chroma_step;
+        return Error::NONE;
+    }
+}
+
+Error Gralloc0Mapper::unlockBuffer(buffer_handle_t bufferHandle,
+                                   int* outFenceFd) {
+    int result;
+    int fenceFd = -1;
+    if (mMinor >= 3 && mModule->unlockAsync) {
+        result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
+    } else {
+        result = mModule->unlock(mModule, bufferHandle);
+    }
+
+    if (result) {
+        // we always own the fenceFd even when unlock failed
+        if (fenceFd >= 0) {
+            close(fenceFd);
+        }
+
+        return Error::BAD_VALUE;
+    } else {
+        *outFenceFd = fenceFd;
+        return Error::NONE;
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.h b/graphics/mapper/2.0/default/Gralloc0Mapper.h
new file mode 100644
index 0000000..e792a69
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc0Mapper.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 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 ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
+
+#include "GrallocMapper.h"
+
+#include <hardware/gralloc.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+class Gralloc0Mapper : public GrallocMapper {
+   public:
+    Gralloc0Mapper(const hw_module_t* module);
+
+   private:
+    Error registerBuffer(buffer_handle_t bufferHandle) override;
+    void unregisterBuffer(buffer_handle_t bufferHandle) override;
+    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                     const IMapper::Rect& accessRegion, int fenceFd,
+                     void** outData) override;
+    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                     const IMapper::Rect& accessRegion, int fenceFd,
+                     YCbCrLayout* outLayout) override;
+    Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
+
+    const gralloc_module_t* mModule;
+    uint8_t mMinor;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.cpp b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp
new file mode 100644
index 0000000..c1e5adc
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "Gralloc1Mapper"
+
+#include "Gralloc1Mapper.h"
+
+#include <vector>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+
+Gralloc1Mapper::Gralloc1Mapper(const hw_module_t* module)
+    : mDevice(nullptr), mDispatch() {
+    int result = gralloc1_open(module, &mDevice);
+    if (result) {
+        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
+                         strerror(-result));
+    }
+
+    initCapabilities();
+    initDispatch();
+}
+
+Gralloc1Mapper::~Gralloc1Mapper() {
+    gralloc1_close(mDevice);
+}
+
+void Gralloc1Mapper::initCapabilities() {
+    mCapabilities.highUsageBits = true;
+    mCapabilities.layeredBuffers = false;
+    mCapabilities.unregisterImplyDelete = false;
+
+    uint32_t count = 0;
+    mDevice->getCapabilities(mDevice, &count, nullptr);
+
+    std::vector<int32_t> capabilities(count);
+    mDevice->getCapabilities(mDevice, &count, capabilities.data());
+    capabilities.resize(count);
+
+    for (auto capability : capabilities) {
+        switch (capability) {
+            case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
+                mCapabilities.layeredBuffers = true;
+                break;
+            case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
+                mCapabilities.unregisterImplyDelete = true;
+                break;
+        }
+    }
+}
+
+template <typename T>
+void Gralloc1Mapper::initDispatch(gralloc1_function_descriptor_t desc,
+                                  T* outPfn) {
+    auto pfn = mDevice->getFunction(mDevice, desc);
+    if (!pfn) {
+        LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
+    }
+
+    *outPfn = reinterpret_cast<T>(pfn);
+}
+
+void Gralloc1Mapper::initDispatch() {
+    initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
+    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
+    initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES,
+                 &mDispatch.getNumFlexPlanes);
+    initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock);
+    initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex);
+    initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock);
+}
+
+Error Gralloc1Mapper::toError(int32_t error) {
+    switch (error) {
+        case GRALLOC1_ERROR_NONE:
+            return Error::NONE;
+        case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+            return Error::BAD_DESCRIPTOR;
+        case GRALLOC1_ERROR_BAD_HANDLE:
+            return Error::BAD_BUFFER;
+        case GRALLOC1_ERROR_BAD_VALUE:
+            return Error::BAD_VALUE;
+        case GRALLOC1_ERROR_NOT_SHARED:
+            return Error::NONE;  // this is fine
+        case GRALLOC1_ERROR_NO_RESOURCES:
+            return Error::NO_RESOURCES;
+        case GRALLOC1_ERROR_UNDEFINED:
+        case GRALLOC1_ERROR_UNSUPPORTED:
+        default:
+            return Error::UNSUPPORTED;
+    }
+}
+
+bool Gralloc1Mapper::toYCbCrLayout(const android_flex_layout& flex,
+                                   YCbCrLayout* outLayout) {
+    // must be YCbCr
+    if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
+        return false;
+    }
+
+    for (int i = 0; i < 3; i++) {
+        const auto& plane = flex.planes[i];
+        // must have 8-bit depth
+        if (plane.bits_per_component != 8 || plane.bits_used != 8) {
+            return false;
+        }
+
+        if (plane.component == FLEX_COMPONENT_Y) {
+            // Y must not be interleaved
+            if (plane.h_increment != 1) {
+                return false;
+            }
+        } else {
+            // Cb and Cr can be interleaved
+            if (plane.h_increment != 1 && plane.h_increment != 2) {
+                return false;
+            }
+        }
+
+        if (!plane.v_increment) {
+            return false;
+        }
+    }
+
+    if (flex.planes[0].component != FLEX_COMPONENT_Y ||
+        flex.planes[1].component != FLEX_COMPONENT_Cb ||
+        flex.planes[2].component != FLEX_COMPONENT_Cr) {
+        return false;
+    }
+
+    const auto& y = flex.planes[0];
+    const auto& cb = flex.planes[1];
+    const auto& cr = flex.planes[2];
+
+    if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
+        return false;
+    }
+
+    outLayout->y = y.top_left;
+    outLayout->cb = cb.top_left;
+    outLayout->cr = cr.top_left;
+    outLayout->yStride = y.v_increment;
+    outLayout->cStride = cb.v_increment;
+    outLayout->chromaStep = cb.h_increment;
+
+    return true;
+}
+
+gralloc1_rect_t Gralloc1Mapper::asGralloc1Rect(const IMapper::Rect& rect) {
+    return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
+}
+
+Error Gralloc1Mapper::registerBuffer(buffer_handle_t bufferHandle) {
+    return toError(mDispatch.retain(mDevice, bufferHandle));
+}
+
+void Gralloc1Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
+    mDispatch.release(mDevice, bufferHandle);
+}
+
+Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
+                                 uint64_t cpuUsage,
+                                 const IMapper::Rect& accessRegion, int fenceFd,
+                                 void** outData) {
+    // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
+    // gralloc's responsibility to close it, even on locking errors.
+    if (fenceFd >= 0) {
+        fenceFd = dup(fenceFd);
+        if (fenceFd < 0) {
+            return Error::NO_RESOURCES;
+        }
+    }
+
+    const uint64_t consumerUsage =
+        cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+    const auto accessRect = asGralloc1Rect(accessRegion);
+    void* data = nullptr;
+    int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage,
+                                   consumerUsage, &accessRect, &data, fenceFd);
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        *outData = data;
+    }
+
+    return toError(error);
+}
+
+Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
+                                 uint64_t cpuUsage,
+                                 const IMapper::Rect& accessRegion, int fenceFd,
+                                 YCbCrLayout* outLayout) {
+    // prepare flex layout
+    android_flex_layout flex = {};
+    int32_t error =
+        mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
+    if (error != GRALLOC1_ERROR_NONE) {
+        return toError(error);
+    }
+    std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
+    flex.planes = flexPlanes.data();
+
+    // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
+    // gralloc's responsibility to close it, even on locking errors.
+    if (fenceFd >= 0) {
+        fenceFd = dup(fenceFd);
+        if (fenceFd < 0) {
+            return Error::NO_RESOURCES;
+        }
+    }
+
+    const uint64_t consumerUsage =
+        cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+    const auto accessRect = asGralloc1Rect(accessRegion);
+    error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage,
+                               &accessRect, &flex, fenceFd);
+    if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
+        ALOGD("unable to convert android_flex_layout to YCbCrLayout");
+
+        // undo the lock
+        fenceFd = -1;
+        mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
+        if (fenceFd >= 0) {
+            close(fenceFd);
+        }
+
+        error = GRALLOC1_ERROR_BAD_HANDLE;
+    }
+
+    return toError(error);
+}
+
+Error Gralloc1Mapper::unlockBuffer(buffer_handle_t bufferHandle,
+                                   int* outFenceFd) {
+    int fenceFd = -1;
+    int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        *outFenceFd = fenceFd;
+    } else if (fenceFd >= 0) {
+        // we always own the fenceFd even when unlock failed
+        close(fenceFd);
+    }
+
+    return toError(error);
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.h b/graphics/mapper/2.0/default/Gralloc1Mapper.h
new file mode 100644
index 0000000..452afdf
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc1Mapper.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 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 ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
+
+#include "GrallocMapper.h"
+
+#include <hardware/gralloc1.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+class Gralloc1Mapper : public GrallocMapper {
+   public:
+    Gralloc1Mapper(const hw_module_t* module);
+    ~Gralloc1Mapper();
+
+   private:
+    void initCapabilities();
+
+    template <typename T>
+    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
+    void initDispatch();
+
+    static Error toError(int32_t error);
+    static bool toYCbCrLayout(const android_flex_layout& flex,
+                              YCbCrLayout* outLayout);
+    static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect);
+
+    Error registerBuffer(buffer_handle_t bufferHandle) override;
+    void unregisterBuffer(buffer_handle_t bufferHandle) override;
+    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                     const IMapper::Rect& accessRegion, int fenceFd,
+                     void** outData) override;
+    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                     const IMapper::Rect& accessRegion, int fenceFd,
+                     YCbCrLayout* outLayout) override;
+    Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
+
+    gralloc1_device_t* mDevice;
+
+    struct {
+        GRALLOC1_PFN_RETAIN retain;
+        GRALLOC1_PFN_RELEASE release;
+        GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
+        GRALLOC1_PFN_LOCK lock;
+        GRALLOC1_PFN_LOCK_FLEX lockFlex;
+        GRALLOC1_PFN_UNLOCK unlock;
+    } mDispatch;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
diff --git a/graphics/mapper/2.0/default/GrallocBufferDescriptor.h b/graphics/mapper/2.0/default/GrallocBufferDescriptor.h
new file mode 100644
index 0000000..9b5ab04
--- /dev/null
+++ b/graphics/mapper/2.0/default/GrallocBufferDescriptor.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 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 ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+/**
+ * BufferDescriptor is created by IMapper and consumed by IAllocator. It is
+ * versioned so that IMapper and IAllocator can be updated independently.
+ */
+constexpr uint32_t grallocBufferDescriptorSize = 7;
+constexpr uint32_t grallocBufferDescriptorMagicVersion = ((0x9487 << 16) | 0);
+
+inline BufferDescriptor grallocEncodeBufferDescriptor(
+    const IMapper::BufferDescriptorInfo& descriptorInfo) {
+    BufferDescriptor descriptor;
+    descriptor.resize(grallocBufferDescriptorSize);
+    descriptor[0] = grallocBufferDescriptorMagicVersion;
+    descriptor[1] = descriptorInfo.width;
+    descriptor[2] = descriptorInfo.height;
+    descriptor[3] = descriptorInfo.layerCount;
+    descriptor[4] = static_cast<uint32_t>(descriptorInfo.format);
+    descriptor[5] = static_cast<uint32_t>(descriptorInfo.usage);
+    descriptor[6] = static_cast<uint32_t>(descriptorInfo.usage >> 32);
+
+    return descriptor;
+}
+
+inline bool grallocDecodeBufferDescriptor(
+    const BufferDescriptor& descriptor,
+    IMapper::BufferDescriptorInfo* outDescriptorInfo) {
+    if (descriptor.size() != grallocBufferDescriptorSize ||
+        descriptor[0] != grallocBufferDescriptorMagicVersion) {
+        return false;
+    }
+
+    *outDescriptorInfo = IMapper::BufferDescriptorInfo{
+        descriptor[1],
+        descriptor[2],
+        descriptor[3],
+        static_cast<PixelFormat>(descriptor[4]),
+        (static_cast<uint64_t>(descriptor[6]) << 32) | descriptor[5],
+    };
+
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
diff --git a/graphics/mapper/2.0/default/GrallocMapper.cpp b/graphics/mapper/2.0/default/GrallocMapper.cpp
index 526aca2..339317a 100644
--- a/graphics/mapper/2.0/default/GrallocMapper.cpp
+++ b/graphics/mapper/2.0/default/GrallocMapper.cpp
@@ -17,14 +17,14 @@
 
 #include "GrallocMapper.h"
 
-#include <mutex>
-#include <vector>
-#include <unordered_map>
+#include "Gralloc0Mapper.h"
+#include "Gralloc1Mapper.h"
+#include "GrallocBufferDescriptor.h"
 
-#include <string.h>
+#include <inttypes.h>
 
-#include <hardware/gralloc1.h>
 #include <log/log.h>
+#include <sync/sync.h>
 
 namespace android {
 namespace hardware {
@@ -33,374 +33,251 @@
 namespace V2_0 {
 namespace implementation {
 
-namespace {
-
-using android::hardware::graphics::allocator::V2_0::Error;
+using android::hardware::graphics::common::V1_0::BufferUsage;
 using android::hardware::graphics::common::V1_0::PixelFormat;
 
-class GrallocMapperHal : public IMapper {
-public:
-    GrallocMapperHal(const hw_module_t* module);
-    ~GrallocMapperHal();
+std::mutex GrallocMapper::mMutex;
+std::unordered_set<buffer_handle_t> GrallocMapper::mRegisteredHandles;
 
-    // IMapper interface
-    Return<Error> retain(const hidl_handle& bufferHandle) override;
-    Return<Error> release(const hidl_handle& bufferHandle) override;
-    Return<void> getDimensions(const hidl_handle& bufferHandle,
-            getDimensions_cb hidl_cb) override;
-    Return<void> getFormat(const hidl_handle& bufferHandle,
-            getFormat_cb hidl_cb) override;
-    Return<void> getLayerCount(const hidl_handle& bufferHandle,
-            getLayerCount_cb hidl_cb) override;
-    Return<void> getProducerUsageMask(const hidl_handle& bufferHandle,
-            getProducerUsageMask_cb hidl_cb) override;
-    Return<void> getConsumerUsageMask(const hidl_handle& bufferHandle,
-            getConsumerUsageMask_cb hidl_cb) override;
-    Return<void> getBackingStore(const hidl_handle& bufferHandle,
-            getBackingStore_cb hidl_cb) override;
-    Return<void> getStride(const hidl_handle& bufferHandle,
-            getStride_cb hidl_cb) override;
-    Return<void> lock(const hidl_handle& bufferHandle,
-            uint64_t producerUsageMask, uint64_t consumerUsageMask,
-            const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
-            lock_cb hidl_cb) override;
-    Return<void> lockFlex(const hidl_handle& bufferHandle,
-            uint64_t producerUsageMask, uint64_t consumerUsageMask,
-            const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
-            lockFlex_cb hidl_cb) override;
-    Return<void> unlock(const hidl_handle& bufferHandle,
-            unlock_cb hidl_cb) override;
+bool GrallocMapper::validateDescriptorInfo(
+    const BufferDescriptorInfo& descriptorInfo) const {
+    const uint64_t validUsageBits =
+        BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+        BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET |
+        BufferUsage::COMPOSER_OVERLAY | BufferUsage::COMPOSER_CLIENT_TARGET |
+        BufferUsage::PROTECTED | BufferUsage::COMPOSER_CURSOR |
+        BufferUsage::VIDEO_ENCODER | BufferUsage::CAMERA_OUTPUT |
+        BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
+        BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
+        BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
+        (mCapabilities.highUsageBits ? BufferUsage::VENDOR_MASK_HI
+                                     : static_cast<BufferUsage>(0));
 
-private:
-    void initCapabilities();
-
-    template<typename T>
-    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
-    void initDispatch();
-
-    static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect);
-    static bool dupFence(const hidl_handle& fenceHandle, int* outFd);
-
-    gralloc1_device_t* mDevice;
-
-    struct {
-        bool layeredBuffers;
-    } mCapabilities;
-
-    struct {
-        GRALLOC1_PFN_RETAIN retain;
-        GRALLOC1_PFN_RELEASE release;
-        GRALLOC1_PFN_GET_DIMENSIONS getDimensions;
-        GRALLOC1_PFN_GET_FORMAT getFormat;
-        GRALLOC1_PFN_GET_LAYER_COUNT getLayerCount;
-        GRALLOC1_PFN_GET_PRODUCER_USAGE getProducerUsage;
-        GRALLOC1_PFN_GET_CONSUMER_USAGE getConsumerUsage;
-        GRALLOC1_PFN_GET_BACKING_STORE getBackingStore;
-        GRALLOC1_PFN_GET_STRIDE getStride;
-        GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
-        GRALLOC1_PFN_LOCK lock;
-        GRALLOC1_PFN_LOCK_FLEX lockFlex;
-        GRALLOC1_PFN_UNLOCK unlock;
-    } mDispatch;
-
-    std::mutex mMutex;
-    std::unordered_map<buffer_handle_t, size_t> mBufferReferenceCounts;
-};
-
-GrallocMapperHal::GrallocMapperHal(const hw_module_t* module)
-    : mDevice(nullptr), mCapabilities(), mDispatch()
-{
-    int status = gralloc1_open(module, &mDevice);
-    if (status) {
-        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
-                strerror(-status));
-    }
-
-    initCapabilities();
-    initDispatch();
-}
-
-GrallocMapperHal::~GrallocMapperHal()
-{
-    gralloc1_close(mDevice);
-}
-
-void GrallocMapperHal::initCapabilities()
-{
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<int32_t> caps(count);
-    mDevice->getCapabilities(mDevice, &count, caps.data());
-    caps.resize(count);
-
-    for (auto cap : caps) {
-        switch (cap) {
-        case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
-            mCapabilities.layeredBuffers = true;
-            break;
-        default:
-            break;
-        }
-    }
-}
-
-template<typename T>
-void GrallocMapperHal::initDispatch(gralloc1_function_descriptor_t desc,
-        T* outPfn)
-{
-    auto pfn = mDevice->getFunction(mDevice, desc);
-    if (!pfn) {
-        LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
-    }
-
-    *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void GrallocMapperHal::initDispatch()
-{
-    initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
-    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
-    initDispatch(GRALLOC1_FUNCTION_GET_DIMENSIONS, &mDispatch.getDimensions);
-    initDispatch(GRALLOC1_FUNCTION_GET_FORMAT, &mDispatch.getFormat);
-    if (mCapabilities.layeredBuffers) {
-        initDispatch(GRALLOC1_FUNCTION_GET_LAYER_COUNT,
-                &mDispatch.getLayerCount);
-    }
-    initDispatch(GRALLOC1_FUNCTION_GET_PRODUCER_USAGE,
-            &mDispatch.getProducerUsage);
-    initDispatch(GRALLOC1_FUNCTION_GET_CONSUMER_USAGE,
-            &mDispatch.getConsumerUsage);
-    initDispatch(GRALLOC1_FUNCTION_GET_BACKING_STORE,
-            &mDispatch.getBackingStore);
-    initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
-    initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES,
-            &mDispatch.getNumFlexPlanes);
-    initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock);
-    initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex);
-    initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock);
-}
-
-gralloc1_rect_t GrallocMapperHal::asGralloc1Rect(const IMapper::Rect& rect)
-{
-    return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
-}
-
-bool GrallocMapperHal::dupFence(const hidl_handle& fenceHandle, int* outFd)
-{
-    auto handle = fenceHandle.getNativeHandle();
-    if (!handle || handle->numFds == 0) {
-        *outFd = -1;
-        return true;
-    }
-
-    if (handle->numFds > 1) {
-        ALOGE("invalid fence handle with %d fds", handle->numFds);
+    if (!descriptorInfo.width || !descriptorInfo.height ||
+        !descriptorInfo.layerCount) {
         return false;
     }
 
-    *outFd = dup(handle->data[0]);
-    return (*outFd >= 0);
-}
-
-Return<Error> GrallocMapperHal::retain(const hidl_handle& bufferHandle)
-{
-    int32_t err = mDispatch.retain(mDevice, bufferHandle);
-    if (err == GRALLOC1_ERROR_NONE) {
-        auto nativeHandle = bufferHandle.getNativeHandle();
-        std::lock_guard<std::mutex> lock(mMutex);
-
-        ++mBufferReferenceCounts[nativeHandle];
-    }
-    return static_cast<Error>(err);
-}
-
-Return<Error> GrallocMapperHal::release(const hidl_handle& bufferHandle)
-{
-    int32_t err = mDispatch.release(mDevice, bufferHandle);
-    if (err == GRALLOC1_ERROR_NONE) {
-        auto nativeHandle = bufferHandle.getNativeHandle();
-        std::lock_guard<std::mutex> lock(mMutex);
-
-        auto iter = mBufferReferenceCounts.find(bufferHandle);
-        if (iter == mBufferReferenceCounts.end()) {
-            // this should never happen
-            err = GRALLOC1_ERROR_BAD_HANDLE;
-        } else if (--iter->second == 0) {
-            native_handle_close(nativeHandle);
-            native_handle_delete(const_cast<native_handle_t*>(nativeHandle));
-
-            mBufferReferenceCounts.erase(iter);
-        }
+    if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) {
+        return false;
     }
 
-    return static_cast<Error>(err);
-}
-
-Return<void> GrallocMapperHal::getDimensions(const hidl_handle& bufferHandle,
-        getDimensions_cb hidl_cb)
-{
-    uint32_t width = 0;
-    uint32_t height = 0;
-    int32_t err = mDispatch.getDimensions(mDevice, bufferHandle,
-            &width, &height);
-
-    hidl_cb(static_cast<Error>(err), width, height);
-    return Void();
-}
-
-Return<void> GrallocMapperHal::getFormat(const hidl_handle& bufferHandle,
-        getFormat_cb hidl_cb)
-{
-    int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-    int32_t err = mDispatch.getFormat(mDevice, bufferHandle, &format);
-
-    hidl_cb(static_cast<Error>(err), static_cast<PixelFormat>(format));
-    return Void();
-}
-
-Return<void> GrallocMapperHal::getLayerCount(const hidl_handle& bufferHandle,
-        getLayerCount_cb hidl_cb)
-{
-    int32_t err = GRALLOC1_ERROR_NONE;
-    uint32_t count = 1;
-    if (mCapabilities.layeredBuffers) {
-        err = mDispatch.getLayerCount(mDevice, bufferHandle, &count);
+    if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
+        return false;
     }
 
-    hidl_cb(static_cast<Error>(err), count);
+    if (descriptorInfo.usage & ~validUsageBits) {
+        // could not fail as gralloc may use the reserved bits...
+        ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
+              descriptorInfo.usage & ~validUsageBits);
+    }
+
+    return true;
+}
+
+Return<void> GrallocMapper::createDescriptor(
+    const BufferDescriptorInfo& descriptorInfo, createDescriptor_cb hidl_cb) {
+    if (validateDescriptorInfo(descriptorInfo)) {
+        hidl_cb(Error::NONE, grallocEncodeBufferDescriptor(descriptorInfo));
+    } else {
+        hidl_cb(Error::BAD_VALUE, BufferDescriptor());
+    }
+
     return Void();
 }
 
-Return<void> GrallocMapperHal::getProducerUsageMask(
-        const hidl_handle& bufferHandle, getProducerUsageMask_cb hidl_cb)
-{
-    uint64_t mask = 0x0;
-    int32_t err = mDispatch.getProducerUsage(mDevice, bufferHandle, &mask);
-
-    hidl_cb(static_cast<Error>(err), mask);
-    return Void();
+bool GrallocMapper::addRegisteredHandle(buffer_handle_t bufferHandle) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mRegisteredHandles.insert(bufferHandle).second;
 }
 
-Return<void> GrallocMapperHal::getConsumerUsageMask(
-        const hidl_handle& bufferHandle, getConsumerUsageMask_cb hidl_cb)
-{
-    uint64_t mask = 0x0;
-    int32_t err = mDispatch.getConsumerUsage(mDevice, bufferHandle, &mask);
+native_handle_t* GrallocMapper::popRegisteredHandle(void* buffer) {
+    auto bufferHandle = static_cast<native_handle_t*>(buffer);
 
-    hidl_cb(static_cast<Error>(err), mask);
-    return Void();
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mRegisteredHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
 }
 
-Return<void> GrallocMapperHal::getBackingStore(
-        const hidl_handle& bufferHandle, getBackingStore_cb hidl_cb)
-{
-    uint64_t store = 0;
-    int32_t err = mDispatch.getBackingStore(mDevice, bufferHandle, &store);
+buffer_handle_t GrallocMapper::getRegisteredHandle(const void* buffer) {
+    auto bufferHandle = static_cast<buffer_handle_t>(buffer);
 
-    hidl_cb(static_cast<Error>(err), store);
-    return Void();
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mRegisteredHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
 }
 
-Return<void> GrallocMapperHal::getStride(const hidl_handle& bufferHandle,
-        getStride_cb hidl_cb)
-{
-    uint32_t stride = 0;
-    int32_t err = mDispatch.getStride(mDevice, bufferHandle, &stride);
+Return<void> GrallocMapper::importBuffer(const hidl_handle& rawHandle,
+                                         importBuffer_cb hidl_cb) {
+    // importing an already imported handle rather than a raw handle
+    if (getRegisteredHandle(rawHandle.getNativeHandle())) {
+        hidl_cb(Error::BAD_BUFFER, nullptr);
+        return Void();
+    }
 
-    hidl_cb(static_cast<Error>(err), stride);
-    return Void();
-}
+    if (!rawHandle.getNativeHandle()) {
+        hidl_cb(Error::BAD_BUFFER, nullptr);
+        return Void();
+    }
 
-Return<void> GrallocMapperHal::lock(const hidl_handle& bufferHandle,
-        uint64_t producerUsageMask, uint64_t consumerUsageMask,
-        const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
-        lock_cb hidl_cb)
-{
-    gralloc1_rect_t rect = asGralloc1Rect(accessRegion);
-
-    int fence = -1;
-    if (!dupFence(acquireFence, &fence)) {
+    native_handle_t* bufferHandle =
+        native_handle_clone(rawHandle.getNativeHandle());
+    if (!bufferHandle) {
         hidl_cb(Error::NO_RESOURCES, nullptr);
         return Void();
     }
 
+    Error error = registerBuffer(bufferHandle);
+    if (error != Error::NONE) {
+        native_handle_close(bufferHandle);
+        native_handle_delete(bufferHandle);
+
+        hidl_cb(error, nullptr);
+        return Void();
+    }
+
+    // The newly cloned handle is already registered?  This can only happen
+    // when a handle previously registered was native_handle_delete'd instead
+    // of freeBuffer'd.
+    if (!addRegisteredHandle(bufferHandle)) {
+        ALOGE("handle %p has already been imported; potential fd leaking",
+              bufferHandle);
+        unregisterBuffer(bufferHandle);
+        if (!mCapabilities.unregisterImplyDelete) {
+            native_handle_close(bufferHandle);
+            native_handle_delete(bufferHandle);
+        }
+
+        hidl_cb(Error::NO_RESOURCES, nullptr);
+        return Void();
+    }
+
+    hidl_cb(Error::NONE, bufferHandle);
+    return Void();
+}
+
+Return<Error> GrallocMapper::freeBuffer(void* buffer) {
+    native_handle_t* bufferHandle = popRegisteredHandle(buffer);
+    if (!bufferHandle) {
+        return Error::BAD_BUFFER;
+    }
+
+    unregisterBuffer(bufferHandle);
+    if (!mCapabilities.unregisterImplyDelete) {
+        native_handle_close(bufferHandle);
+        native_handle_delete(bufferHandle);
+    }
+
+    return Error::NONE;
+}
+
+void GrallocMapper::waitFenceFd(int fenceFd, const char* logname) {
+    if (fenceFd < 0) {
+        return;
+    }
+
+    const int warningTimeout = 3500;
+    const int error = sync_wait(fenceFd, warningTimeout);
+    if (error < 0 && errno == ETIME) {
+        ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd,
+              warningTimeout);
+        sync_wait(fenceFd, -1);
+    }
+}
+
+bool GrallocMapper::getFenceFd(const hidl_handle& fenceHandle,
+                               int* outFenceFd) {
+    auto handle = fenceHandle.getNativeHandle();
+    if (handle && handle->numFds > 1) {
+        ALOGE("invalid fence handle with %d fds", handle->numFds);
+        return false;
+    }
+
+    *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+    return true;
+}
+
+hidl_handle GrallocMapper::getFenceHandle(int fenceFd, char* handleStorage) {
+    native_handle_t* handle = nullptr;
+    if (fenceFd >= 0) {
+        handle = native_handle_init(handleStorage, 1, 0);
+        handle->data[0] = fenceFd;
+    }
+
+    return hidl_handle(handle);
+}
+
+Return<void> GrallocMapper::lock(void* buffer, uint64_t cpuUsage,
+                                 const IMapper::Rect& accessRegion,
+                                 const hidl_handle& acquireFence,
+                                 lock_cb hidl_cb) {
+    buffer_handle_t bufferHandle = getRegisteredHandle(buffer);
+    if (!bufferHandle) {
+        hidl_cb(Error::BAD_BUFFER, nullptr);
+        return Void();
+    }
+
+    int fenceFd;
+    if (!getFenceFd(acquireFence, &fenceFd)) {
+        hidl_cb(Error::BAD_VALUE, nullptr);
+        return Void();
+    }
+
     void* data = nullptr;
-    int32_t err = mDispatch.lock(mDevice, bufferHandle, producerUsageMask,
-            consumerUsageMask, &rect, &data, fence);
-    if (err != GRALLOC1_ERROR_NONE) {
-        close(fence);
-    }
+    Error error =
+        lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data);
 
-    hidl_cb(static_cast<Error>(err), data);
+    hidl_cb(error, data);
     return Void();
 }
 
-Return<void> GrallocMapperHal::lockFlex(const hidl_handle& bufferHandle,
-        uint64_t producerUsageMask, uint64_t consumerUsageMask,
-        const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
-        lockFlex_cb hidl_cb)
-{
-    FlexLayout layout_reply{};
+Return<void> GrallocMapper::lockYCbCr(void* buffer, uint64_t cpuUsage,
+                                      const IMapper::Rect& accessRegion,
+                                      const hidl_handle& acquireFence,
+                                      lockYCbCr_cb hidl_cb) {
+    YCbCrLayout layout = {};
 
-    uint32_t planeCount = 0;
-    int32_t err = mDispatch.getNumFlexPlanes(mDevice, bufferHandle,
-            &planeCount);
-    if (err != GRALLOC1_ERROR_NONE) {
-        hidl_cb(static_cast<Error>(err), layout_reply);
+    buffer_handle_t bufferHandle = getRegisteredHandle(buffer);
+    if (!bufferHandle) {
+        hidl_cb(Error::BAD_BUFFER, layout);
         return Void();
     }
 
-    gralloc1_rect_t rect = asGralloc1Rect(accessRegion);
-
-    int fence = -1;
-    if (!dupFence(acquireFence, &fence)) {
-        hidl_cb(Error::NO_RESOURCES, layout_reply);
+    int fenceFd;
+    if (!getFenceFd(acquireFence, &fenceFd)) {
+        hidl_cb(Error::BAD_VALUE, layout);
         return Void();
     }
 
-    std::vector<android_flex_plane_t> planes(planeCount);
-    android_flex_layout_t layout{};
-    layout.num_planes = planes.size();
-    layout.planes = planes.data();
+    Error error =
+        lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &layout);
 
-    err = mDispatch.lockFlex(mDevice, bufferHandle, producerUsageMask,
-            consumerUsageMask, &rect, &layout, fence);
-    if (err == GRALLOC1_ERROR_NONE) {
-        layout_reply.format = static_cast<FlexFormat>(layout.format);
+    hidl_cb(error, layout);
+    return Void();
+}
 
-        planes.resize(layout.num_planes);
-        layout_reply.planes.setToExternal(
-                reinterpret_cast<FlexPlane*>(planes.data()), planes.size());
+Return<void> GrallocMapper::unlock(void* buffer, unlock_cb hidl_cb) {
+    buffer_handle_t bufferHandle = getRegisteredHandle(buffer);
+    if (!bufferHandle) {
+        hidl_cb(Error::BAD_BUFFER, nullptr);
+        return Void();
+    }
+
+    int fenceFd;
+    Error error = unlockBuffer(bufferHandle, &fenceFd);
+    if (error == Error::NONE) {
+        NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+
+        hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
+
+        if (fenceFd >= 0) {
+            close(fenceFd);
+        }
     } else {
-        close(fence);
+        hidl_cb(error, nullptr);
     }
 
-    hidl_cb(static_cast<Error>(err), layout_reply);
     return Void();
 }
 
-Return<void> GrallocMapperHal::unlock(const hidl_handle& bufferHandle,
-        unlock_cb hidl_cb)
-{
-    int32_t fence = -1;
-    int32_t err = mDispatch.unlock(mDevice, bufferHandle, &fence);
-
-    NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
-    hidl_handle fenceHandle;
-    if (err == GRALLOC1_ERROR_NONE && fence >= 0) {
-        auto nativeHandle = native_handle_init(fenceStorage, 1, 0);
-        nativeHandle->data[0] = fence;
-
-        fenceHandle = nativeHandle;
-    }
-
-    hidl_cb(static_cast<Error>(err), fenceHandle);
-    return Void();
-}
-
-} // anonymous namespace
-
 IMapper* HIDL_FETCH_IMapper(const char* /* name */) {
     const hw_module_t* module = nullptr;
     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
@@ -410,12 +287,15 @@
     }
 
     uint8_t major = (module->module_api_version >> 8) & 0xff;
-    if (major != 1) {
-        ALOGE("unknown gralloc module major version %d", major);
-        return nullptr;
+    switch (major) {
+        case 1:
+            return new Gralloc1Mapper(module);
+        case 0:
+            return new Gralloc0Mapper(module);
+        default:
+            ALOGE("unknown gralloc module major version %d", major);
+            return nullptr;
     }
-
-    return new GrallocMapperHal(module);
 }
 
 } // namespace implementation
diff --git a/graphics/mapper/2.0/default/GrallocMapper.h b/graphics/mapper/2.0/default/GrallocMapper.h
index a2f89d1..c9c6d8a 100644
--- a/graphics/mapper/2.0/default/GrallocMapper.h
+++ b/graphics/mapper/2.0/default/GrallocMapper.h
@@ -18,6 +18,10 @@
 #define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
 
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <system/window.h>
+
+#include <mutex>
+#include <unordered_set>
 
 namespace android {
 namespace hardware {
@@ -26,6 +30,68 @@
 namespace V2_0 {
 namespace implementation {
 
+class GrallocMapper : public IMapper {
+   public:
+    // IMapper interface
+    Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
+                                  createDescriptor_cb hidl_cb) override;
+    Return<void> importBuffer(const hidl_handle& rawHandle,
+                              importBuffer_cb hidl_cb) override;
+    Return<Error> freeBuffer(void* buffer) override;
+    Return<void> lock(void* buffer, uint64_t cpuUsage,
+                      const IMapper::Rect& accessRegion,
+                      const hidl_handle& acquireFence,
+                      lock_cb hidl_cb) override;
+    Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage,
+                           const IMapper::Rect& accessRegion,
+                           const hidl_handle& acquireFence,
+                           lockYCbCr_cb hidl_cb) override;
+    Return<void> unlock(void* buffer, unlock_cb hidl_cb) override;
+
+   protected:
+    static void waitFenceFd(int fenceFd, const char* logname);
+
+    struct {
+        bool highUsageBits;
+        bool layeredBuffers;
+        bool unregisterImplyDelete;
+    } mCapabilities = {};
+
+   private:
+    virtual bool validateDescriptorInfo(
+        const BufferDescriptorInfo& descriptorInfo) const;
+
+    // Register a buffer.  The handle is already cloned by the caller.
+    virtual Error registerBuffer(buffer_handle_t bufferHandle) = 0;
+
+    // Unregister a buffer.  The handle is closed and deleted by the
+    // callee if and only if mCapabilities.unregisterImplyDelete is set.
+    virtual void unregisterBuffer(buffer_handle_t bufferHandle) = 0;
+
+    // Lock a buffer.  The fence is owned by the caller.
+    virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                             const IMapper::Rect& accessRegion, int fenceFd,
+                             void** outData) = 0;
+    virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                             const IMapper::Rect& accessRegion, int fenceFd,
+                             YCbCrLayout* outLayout) = 0;
+
+    // Unlock a buffer.  The returned fence is owned by the caller.
+    virtual Error unlockBuffer(buffer_handle_t bufferHandle,
+                               int* outFenceFd) = 0;
+
+    static bool addRegisteredHandle(buffer_handle_t bufferHandle);
+    static buffer_handle_t getRegisteredHandle(const void* buffer);
+    static native_handle_t* popRegisteredHandle(void* buffer);
+
+    static bool getFenceFd(const hidl_handle& fenceHandle, int* outFenceFd);
+    static hidl_handle getFenceHandle(int fenceFd, char* handleStorage);
+
+    // these are static and shared by all mappers
+    static std::mutex mMutex;
+    static std::unordered_set<buffer_handle_t> mRegisteredHandles;
+};
+
 extern "C" IMapper* HIDL_FETCH_IMapper(const char* name);
 
 } // namespace implementation
diff --git a/graphics/mapper/2.0/types.hal b/graphics/mapper/2.0/types.hal
index 2946e85..e9b2f3a 100644
--- a/graphics/mapper/2.0/types.hal
+++ b/graphics/mapper/2.0/types.hal
@@ -16,101 +16,50 @@
 
 package android.hardware.graphics.mapper@2.0;
 
+enum Error : int32_t {
+    NONE            = 0, /** no error */
+    BAD_DESCRIPTOR  = 1, /** invalid BufferDescriptor */
+    BAD_BUFFER      = 2, /** invalid buffer handle */
+    BAD_VALUE       = 3, /** invalid width, height, etc. */
+    /* 4 is reserved */
+    NO_RESOURCES    = 5, /** temporary failure due to resource contention */
+    /* 6 is reserved */
+    UNSUPPORTED     = 7, /** permanent failure */
+};
+
 /**
- * Structures for describing flexible YUVA/RGBA formats for consumption by
- * applications. Such flexible formats contain a plane for each component (e.g.
- * red, green, blue), where each plane is laid out in a grid-like pattern
- * occupying unique byte addresses and with consistent byte offsets between
- * neighboring pixels.
- *
- * The FlexLayout structure is used with any pixel format that can be
- * represented by it, such as:
- *  - PixelFormat::YCBCR_*_888
- *  - PixelFormat::FLEX_RGB*_888
- *  - PixelFormat::RGB[AX]_888[8],BGRA_8888,RGB_888
- *  - PixelFormat::YV12,Y8,Y16,YCBCR_422_SP/I,YCRCB_420_SP
- *  - even implementation defined formats that can be represented by
- *    the structures
- *
- * Vertical increment (aka. row increment or stride) describes the distance in
- * bytes from the first pixel of one row to the first pixel of the next row
- * (below) for the component plane. This can be negative.
- *
- * Horizontal increment (aka. column or pixel increment) describes the distance
- * in bytes from one pixel to the next pixel (to the right) on the same row for
- * the component plane. This can be negative.
- *
- * Each plane can be subsampled either vertically or horizontally by
- * a power-of-two factor.
- *
- * The bit-depth of each component can be arbitrary, as long as the pixels are
- * laid out on whole bytes, in native byte-order, using the most significant
- * bits of each unit.
+ * A buffer descriptor is an implementation-defined opaque data returned by
+ * createDescriptor. It describes the properties of a buffer and is consumed
+ * by the allocator.
  */
+typedef vec<uint32_t> BufferDescriptor;
 
-enum FlexComponent : int32_t {
-    Y  = 1 << 0, /** luma */
-    CB = 1 << 1, /** chroma blue */
-    CR = 1 << 2, /** chroma red */
-
-    R  = 1 << 10, /** red */
-    G  = 1 << 11, /** green */
-    B  = 1 << 12, /** blue */
-
-    A  = 1 << 30, /** alpha */
+/**
+ * Structure for describing YCbCr formats for consumption by applications.
+ * This is used with PixelFormat::YCBCR_*_888.
+ *
+ * Buffer chroma subsampling is defined in the format.
+ * e.g. PixelFormat::YCBCR_420_888 has subsampling 4:2:0.
+ *
+ * Buffers must have a 8 bit depth.
+ *
+ * y, cb, and cr point to the first byte of their respective planes.
+ *
+ * Stride describes the distance in bytes from the first value of one row of
+ * the image to the first value of the next row. It includes the width of the
+ * image plus padding.
+ * yStride is the stride of the luma plane.
+ * cStride is the stride of the chroma planes.
+ *
+ * chromaStep is the distance in bytes from one chroma pixel value to the
+ * next. This is 2 bytes for semiplanar (because chroma values are interleaved
+ * and each chroma value is one byte) and 1 for planar.
+ */
+struct YCbCrLayout {
+    pointer y;
+    pointer cb;
+    pointer cr;
+    uint32_t yStride;
+    uint32_t cStride;
+    uint32_t chromaStep;
 };
-
-enum FlexFormat : int32_t {
-    /** not a flexible format */
-    INVALID = 0x0,
-
-    Y       = FlexComponent:Y,
-    YCBCR   = Y | FlexComponent:CB | FlexComponent:CR,
-    YCBCRA  = YCBCR | FlexComponent:A,
-
-    RGB     = FlexComponent:R | FlexComponent:G | FlexComponent:B,
-    RGBA    = RGB | FlexComponent:A,
-};
-
-struct FlexPlane {
-    /** Pointer to the first byte of the top-left pixel of the plane. */
-    pointer topLeft;
-
-    FlexComponent component;
-
-    /**
-     * Bits allocated for the component in each pixel. Must be a positive
-     * multiple of 8.
-     */
-    int32_t bitsPerComponent;
-
-    /**
-     * Number of the most significant bits used in the format for this
-     * component. Must be between 1 and bitsPerComponent, inclusive.
-     */
-    int32_t bitsUsed;
-
-    /** Horizontal increment. */
-    int32_t hIncrement;
-    /** Vertical increment. */
-    int32_t vIncrement;
-    /** Horizontal subsampling. Must be a positive power of 2. */
-    int32_t hSubsampling;
-    /** Vertical subsampling. Must be a positive power of 2. */
-    int32_t vSubsampling;
-};
-
-struct FlexLayout {
-    /** The kind of flexible format. */
-    FlexFormat format;
-
-    /**
-     * A plane for each component; ordered in increasing component value
-     * order. E.g. FlexFormat::RGBA maps 0 -> R, 1 -> G, etc.  Can have size 0
-     * for FlexFormat::INVALID.
-     */
-    vec<FlexPlane> planes;
-};
-
-/** Backing store ID of a buffer. See IMapper::getBackingStore. */
-typedef uint64_t BackingStore;
diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp
index e26f087..1c0e4c5 100644
--- a/graphics/mapper/2.0/vts/functional/Android.bp
+++ b/graphics/mapper/2.0/vts/functional/Android.bp
@@ -24,7 +24,6 @@
     ],
     static_libs: [
         "VtsHalHidlTargetTestBase",
-        "libVtsHalGraphicsAllocatorTestUtils",
     ],
     cflags: [
         "-Wall",
@@ -54,7 +53,6 @@
         "android.hardware.graphics.common@1.0",
     ],
     static_libs: [
-        "libVtsHalGraphicsAllocatorTestUtils",
         "libVtsHalGraphicsMapperTestUtils",
         "VtsHalHidlTargetTestBase",
     ],
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
index f6a26ac..c534889 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
@@ -25,228 +25,233 @@
 namespace V2_0 {
 namespace tests {
 
-using android::hardware::graphics::allocator::V2_0::Buffer;
-using android::hardware::graphics::allocator::V2_0::BufferDescriptor;
-using android::hardware::graphics::allocator::V2_0::Error;
-
-Mapper::Mapper() { init(); }
-
-void Mapper::init() {
-  mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>();
-  ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
-  ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
+Gralloc::Gralloc() {
+    init();
 }
 
-Mapper::~Mapper() {
-  for (auto it : mHandles) {
-    while (it.second) {
-      EXPECT_EQ(Error::NONE, mMapper->release(it.first))
-          << "failed to release handle " << it.first;
-      it.second--;
+void Gralloc::init() {
+    mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>();
+    ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
+
+    mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>();
+    ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
+    ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
+}
+
+Gralloc::~Gralloc() {
+    for (auto bufferHandle : mClonedBuffers) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+        native_handle_close(buffer);
+        native_handle_delete(buffer);
     }
-  }
-  mHandles.clear();
+    mClonedBuffers.clear();
+
+    for (auto bufferHandle : mImportedBuffers) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+        EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer))
+            << "failed to free buffer " << buffer;
+    }
+    mImportedBuffers.clear();
 }
 
-sp<IMapper> Mapper::getRaw() const { return mMapper; }
-
-void Mapper::retain(const native_handle_t* handle) {
-  Error error = mMapper->retain(handle);
-  ASSERT_EQ(Error::NONE, error) << "failed to retain handle " << handle;
-
-  mHandles[handle]++;
+sp<IAllocator> Gralloc::getAllocator() const {
+    return mAllocator;
 }
 
-void Mapper::release(const native_handle_t* handle) {
-  Error error = mMapper->release(handle);
-  ASSERT_EQ(Error::NONE, error) << "failed to release handle " << handle;
+std::string Gralloc::dumpDebugInfo() {
+    std::string debugInfo;
+    mAllocator->dumpDebugInfo(
+        [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
 
-  if (--mHandles[handle] == 0) {
-    mHandles.erase(handle);
-  }
+    return debugInfo;
 }
 
-Mapper::Dimensions Mapper::getDimensions(const native_handle_t* handle) {
-  Dimensions dimensions = {};
-  mMapper->getDimensions(handle, [&](const auto& tmpError, const auto& tmpWidth,
-                                     const auto& tmpHeight) {
-    ASSERT_EQ(Error::NONE, tmpError)
-        << "failed to get dimensions for handle " << handle;
-    dimensions.width = tmpWidth;
-    dimensions.height = tmpHeight;
-  });
+const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
+    const native_handle_t* bufferHandle =
+        native_handle_clone(rawHandle.getNativeHandle());
+    EXPECT_NE(nullptr, bufferHandle);
 
-  return dimensions;
+    if (bufferHandle) {
+        mClonedBuffers.insert(bufferHandle);
+    }
+
+    return bufferHandle;
 }
 
-PixelFormat Mapper::getFormat(const native_handle_t* handle) {
-  PixelFormat format = static_cast<PixelFormat>(0);
-  mMapper->getFormat(handle, [&](const auto& tmpError, const auto& tmpFormat) {
-    ASSERT_EQ(Error::NONE, tmpError)
-        << "failed to get format for handle " << handle;
-    format = tmpFormat;
-  });
+std::vector<const native_handle_t*> Gralloc::allocate(
+    const 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) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
+            ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
 
-  return format;
+            for (uint32_t i = 0; i < count; i++) {
+                if (import) {
+                    ASSERT_NO_FATAL_FAILURE(
+                        bufferHandles.push_back(importBuffer(tmpBuffers[i])));
+                } else {
+                    ASSERT_NO_FATAL_FAILURE(
+                        bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
+                }
+            }
+
+            if (outStride) {
+                *outStride = tmpStride;
+            }
+        });
+
+    if (::testing::Test::HasFatalFailure()) {
+        bufferHandles.clear();
+    }
+
+    return bufferHandles;
 }
 
-uint32_t Mapper::getLayerCount(const native_handle_t* handle) {
-  uint32_t count = 0;
-  mMapper->getLayerCount(
-      handle, [&](const auto& tmpError, const auto& tmpCount) {
-        ASSERT_EQ(Error::NONE, tmpError)
-            << "failed to get layer count for handle " << handle;
-        count = tmpCount;
-      });
+const native_handle_t* Gralloc::allocate(
+    const IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
+    uint32_t* outStride) {
+    BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+    if (::testing::Test::HasFatalFailure()) {
+        return nullptr;
+    }
 
-  return count;
+    auto buffers = allocate(descriptor, 1, import, outStride);
+    if (::testing::Test::HasFatalFailure()) {
+        return nullptr;
+    }
+
+    return buffers[0];
 }
 
-uint64_t Mapper::getProducerUsageMask(const native_handle_t* handle) {
-  uint64_t usageMask = 0;
-  mMapper->getProducerUsageMask(
-      handle, [&](const auto& tmpError, const auto& tmpUsageMask) {
-        ASSERT_EQ(Error::NONE, tmpError)
-            << "failed to get producer usage mask for handle " << handle;
-        usageMask = tmpUsageMask;
-      });
-
-  return usageMask;
+sp<IMapper> Gralloc::getMapper() const {
+    return mMapper;
 }
 
-uint64_t Mapper::getConsumerUsageMask(const native_handle_t* handle) {
-  uint64_t usageMask = 0;
-  mMapper->getConsumerUsageMask(
-      handle, [&](const auto& tmpError, const auto& tmpUsageMask) {
-        ASSERT_EQ(Error::NONE, tmpError)
-            << "failed to get consumer usage mask for handle " << handle;
-        usageMask = tmpUsageMask;
-      });
+BufferDescriptor Gralloc::createDescriptor(
+    const IMapper::BufferDescriptorInfo& descriptorInfo) {
+    BufferDescriptor descriptor;
+    mMapper->createDescriptor(
+        descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
+            descriptor = tmpDescriptor;
+        });
 
-  return usageMask;
+    return descriptor;
 }
 
-BackingStore Mapper::getBackingStore(const native_handle_t* handle) {
-  BackingStore backingStore = 0;
-  mMapper->getBackingStore(
-      handle, [&](const auto& tmpError, const auto& tmpBackingStore) {
-        ASSERT_EQ(Error::NONE, tmpError)
-            << "failed to get backing store for handle " << handle;
-        backingStore = tmpBackingStore;
-      });
+const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
+    const native_handle_t* bufferHandle = nullptr;
+    mMapper->importBuffer(
+        rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to import buffer %p"
+                                             << rawHandle.getNativeHandle();
+            bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
+        });
 
-  return backingStore;
+    if (bufferHandle) {
+        mImportedBuffers.insert(bufferHandle);
+    }
+
+    return bufferHandle;
 }
 
-uint32_t Mapper::getStride(const native_handle_t* handle) {
-  uint32_t stride = 0;
-  mMapper->getStride(handle, [&](const auto& tmpError, const auto& tmpStride) {
-    ASSERT_EQ(Error::NONE, tmpError)
-        << "failed to get stride for handle " << handle;
-    stride = tmpStride;
-  });
+void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
 
-  return stride;
+    if (mImportedBuffers.erase(bufferHandle)) {
+        Error error = mMapper->freeBuffer(buffer);
+        ASSERT_EQ(Error::NONE, error) << "failed to free buffer " << buffer;
+    } else {
+        mClonedBuffers.erase(bufferHandle);
+        native_handle_close(buffer);
+        native_handle_delete(buffer);
+    }
 }
 
-void* Mapper::lock(const native_handle_t* handle, uint64_t producerUsageMask,
-                   uint64_t consumerUsageMask,
-                   const IMapper::Rect& accessRegion, int acquireFence) {
-  NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 0, 1);
-  native_handle_t* acquireFenceHandle = nullptr;
-  if (acquireFence >= 0) {
-    acquireFenceHandle = native_handle_init(acquireFenceStorage, 0, 1);
-    acquireFenceHandle->data[0] = acquireFence;
-  }
+void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                    const IMapper::Rect& accessRegion, int acquireFence) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
 
-  void* data = nullptr;
-  mMapper->lock(
-      handle, producerUsageMask, consumerUsageMask, accessRegion,
-      acquireFenceHandle, [&](const auto& tmpError, const auto& tmpData) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to lock handle " << handle;
-        data = tmpData;
-      });
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    hidl_handle acquireFenceHandle;
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
 
-  if (acquireFence >= 0) {
-    close(acquireFence);
-  }
-
-  return data;
-}
-
-FlexLayout Mapper::lockFlex(const native_handle_t* handle,
-                            uint64_t producerUsageMask,
-                            uint64_t consumerUsageMask,
-                            const IMapper::Rect& accessRegion,
-                            int acquireFence) {
-  NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 0, 1);
-  native_handle_t* acquireFenceHandle = nullptr;
-  if (acquireFence >= 0) {
-    acquireFenceHandle = native_handle_init(acquireFenceStorage, 0, 1);
-    acquireFenceHandle->data[0] = acquireFence;
-  }
-
-  FlexLayout layout = {};
-  mMapper->lockFlex(handle, producerUsageMask, consumerUsageMask, accessRegion,
-                    acquireFenceHandle,
-                    [&](const auto& tmpError, const auto& tmpLayout) {
+    void* data = nullptr;
+    mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                  [&](const auto& tmpError, const auto& tmpData) {
                       ASSERT_EQ(Error::NONE, tmpError)
-                          << "failed to lockFlex handle " << handle;
-                      layout = tmpLayout;
-                    });
+                          << "failed to lock buffer " << buffer;
+                      data = tmpData;
+                  });
 
-  if (acquireFence >= 0) {
-    close(acquireFence);
-  }
-
-  return layout;
-}
-
-int Mapper::unlock(const native_handle_t* handle) {
-  int releaseFence = -1;
-  mMapper->unlock(handle, [&](const auto& tmpError,
-                              const auto& tmpReleaseFence) {
-    ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock handle " << handle;
-
-    auto handle = tmpReleaseFence.getNativeHandle();
-    if (handle) {
-      ASSERT_EQ(0, handle->numInts) << "invalid fence handle " << handle;
-      if (handle->numFds == 1) {
-        releaseFence = dup(handle->data[0]);
-        ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
-      } else {
-        ASSERT_EQ(0, handle->numFds) << " invalid fence handle " << handle;
-      }
+    if (acquireFence >= 0) {
+        close(acquireFence);
     }
-  });
 
-  return releaseFence;
+    return data;
 }
 
-const native_handle_t* Mapper::allocate(
-    std::unique_ptr<AllocatorClient>& allocatorClient,
-    const IAllocatorClient::BufferDescriptorInfo& info) {
-  BufferDescriptor descriptor = allocatorClient->createDescriptor(info);
-  if (::testing::Test::HasFatalFailure()) {
-    return nullptr;
-  }
+YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle,
+                               uint64_t cpuUsage,
+                               const IMapper::Rect& accessRegion,
+                               int acquireFence) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
 
-  Buffer buffer = allocatorClient->allocate(descriptor);
-  if (::testing::Test::HasFatalFailure()) {
-    allocatorClient->destroyDescriptor(descriptor);
-    return nullptr;
-  }
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    hidl_handle acquireFenceHandle;
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
 
-  const native_handle_t* handle =
-      allocatorClient->exportHandle(descriptor, buffer);
-  if (handle) {
-    retain(handle);
-  }
+    YCbCrLayout layout = {};
+    mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                       [&](const auto& tmpError, const auto& tmpLayout) {
+                           ASSERT_EQ(Error::NONE, tmpError)
+                               << "failed to lockYCbCr buffer " << buffer;
+                           layout = tmpLayout;
+                       });
 
-  allocatorClient->free(buffer);
-  allocatorClient->destroyDescriptor(descriptor);
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
 
-  return handle;
+    return layout;
+}
+
+int Gralloc::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) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer "
+                                             << buffer;
+
+            auto fenceHandle = tmpReleaseFence.getNativeHandle();
+            if (fenceHandle) {
+                ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle "
+                                                   << fenceHandle;
+                if (fenceHandle->numFds == 1) {
+                    releaseFence = dup(fenceHandle->data[0]);
+                    ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
+                } else {
+                    ASSERT_EQ(0, fenceHandle->numFds)
+                        << " invalid fence handle " << fenceHandle;
+                }
+            }
+        });
+
+    return releaseFence;
 }
 
 }  // namespace tests
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
index c186b00..757f20b 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
@@ -17,14 +17,12 @@
 #ifndef VTS_HAL_GRAPHICS_MAPPER_UTILS
 #define VTS_HAL_GRAPHICS_MAPPER_UTILS
 
-#include <memory>
-#include <unordered_map>
+#include <unordered_set>
 
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <utils/StrongPointer.h>
 
-#include "VtsHalGraphicsAllocatorTestUtils.h"
-
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -32,59 +30,62 @@
 namespace V2_0 {
 namespace tests {
 
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::hardware::graphics::allocator::V2_0::IAllocatorClient;
-using android::hardware::graphics::allocator::V2_0::tests::AllocatorClient;
+using android::hardware::graphics::allocator::V2_0::IAllocator;
 
-// A wrapper to IMapper.
-class Mapper {
- public:
-  Mapper();
-  ~Mapper();
+// A wrapper to IAllocator and IMapper.
+class Gralloc {
+   public:
+    Gralloc();
+    ~Gralloc();
 
-  sp<IMapper> getRaw() const;
+    // IAllocator methods
 
-  void retain(const native_handle_t* handle);
-  void release(const native_handle_t* handle);
+    sp<IAllocator> getAllocator() const;
 
-  struct Dimensions {
-    uint32_t width;
-    uint32_t height;
-  };
-  Dimensions getDimensions(const native_handle_t* handle);
+    std::string dumpDebugInfo();
 
-  PixelFormat getFormat(const native_handle_t* handle);
-  uint32_t getLayerCount(const native_handle_t* handle);
-  uint64_t getProducerUsageMask(const native_handle_t* handle);
-  uint64_t getConsumerUsageMask(const native_handle_t* handle);
-  BackingStore getBackingStore(const native_handle_t* handle);
-  uint32_t getStride(const native_handle_t* handle);
+    // 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 BufferDescriptor& descriptor, uint32_t count, bool import = true,
+        uint32_t* outStride = nullptr);
+    const native_handle_t* allocate(
+        const IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true,
+        uint32_t* outStride = nullptr);
 
-  // We use fd instead of 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* handle, uint64_t producerUsageMask,
-             uint64_t consumerUsageMask, const IMapper::Rect& accessRegion,
-             int acquireFence);
-  FlexLayout lockFlex(const native_handle_t* handle, uint64_t producerUsageMask,
-                      uint64_t consumerUsageMask,
-                      const IMapper::Rect& accessRegion, int acquireFence);
-  int unlock(const native_handle_t* handle);
+    // IMapper methods
 
-  // Requests AllocatorClient to allocate a buffer, export the handle, and
-  // register the handle with mapper.
-  const native_handle_t* allocate(
-      std::unique_ptr<AllocatorClient>& allocatorClient,
-      const IAllocatorClient::BufferDescriptorInfo& info);
+    sp<IMapper> getMapper() const;
 
- private:
-  void init();
+    BufferDescriptor createDescriptor(
+        const IMapper::BufferDescriptorInfo& descriptorInfo);
 
-  sp<IMapper> mMapper;
+    const native_handle_t* importBuffer(const hidl_handle& rawHandle);
+    void freeBuffer(const native_handle_t* bufferHandle);
 
-  // Keep track of all registered (retained) handles.  When a test fails with
-  // ASSERT_*, the destructor will release the handles for the test.
-  std::unordered_map<const native_handle_t*, uint64_t> mHandles;
+    // We use fd instead of 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 IMapper::Rect& accessRegion, int acquireFence);
+    YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle,
+                          uint64_t cpuUsage, const IMapper::Rect& accessRegion,
+                          int acquireFence);
+    int unlock(const native_handle_t* bufferHandle);
+
+   private:
+    void init();
+    const native_handle_t* cloneBuffer(const hidl_handle& rawHandle);
+
+    sp<IAllocator> mAllocator;
+    sp<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 tests
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
index 92d74d5..f066a1e 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "graphics_mapper_hidl_hal_test"
+#define LOG_TAG "VtsHalGraphicsMapperV2_0TargetTest"
 
-#include <android-base/logging.h>
 #include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
 #include <sync/sync.h>
 #include "VtsHalGraphicsMapperTestUtils.h"
 
@@ -29,202 +29,384 @@
 namespace tests {
 namespace {
 
-using namespace android::hardware::graphics::allocator::V2_0;
-using namespace android::hardware::graphics::allocator::V2_0::tests;
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using android::hardware::graphics::common::V1_0::PixelFormat;
 
 class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
  protected:
   void SetUp() override {
-    ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique<Allocator>());
-    ASSERT_NO_FATAL_FAILURE(mAllocatorClient = mAllocator->createClient());
-    ASSERT_NO_FATAL_FAILURE(mMapper = std::make_unique<Mapper>());
+      ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
 
-    mDummyDescriptorInfo.width = 64;
-    mDummyDescriptorInfo.height = 64;
-    mDummyDescriptorInfo.layerCount = 1;
-    mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
-    mDummyDescriptorInfo.producerUsageMask =
-        static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
-    mDummyDescriptorInfo.consumerUsageMask =
-        static_cast<uint64_t>(ConsumerUsage::CPU_READ);
+      mDummyDescriptorInfo.width = 64;
+      mDummyDescriptorInfo.height = 64;
+      mDummyDescriptorInfo.layerCount = 1;
+      mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
+      mDummyDescriptorInfo.usage = static_cast<uint64_t>(
+          BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
   }
 
   void TearDown() override {}
 
-  std::unique_ptr<Allocator> mAllocator;
-  std::unique_ptr<AllocatorClient> mAllocatorClient;
-  std::unique_ptr<Mapper> mMapper;
-  IAllocatorClient::BufferDescriptorInfo mDummyDescriptorInfo{};
+  std::unique_ptr<Gralloc> mGralloc;
+  IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
 };
 
 /**
- * Test IMapper::retain and IMapper::release.
+ * Test IAllocator::dumpDebugInfo by calling it.
  */
-TEST_F(GraphicsMapperHidlTest, RetainRelease) {
-  const native_handle_t* buffer;
-  ASSERT_NO_FATAL_FAILURE(
-      buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo));
-
-  const int maxRefs = 10;
-  for (int i = 0; i < maxRefs; i++) {
-    ASSERT_NO_FATAL_FAILURE(mMapper->retain(buffer));
-  }
-  for (int i = 0; i < maxRefs; i++) {
-    ASSERT_NO_FATAL_FAILURE(mMapper->release(buffer));
-  }
-
-  ASSERT_NO_FATAL_FAILURE(mMapper->release(buffer));
+TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
+    mGralloc->dumpDebugInfo();
 }
 
 /**
- * Test IMapper::get* getters.
+ * Test IAllocator::allocate with valid buffer descriptors.
  */
-TEST_F(GraphicsMapperHidlTest, Getters) {
-  const native_handle_t* buffer;
-  ASSERT_NO_FATAL_FAILURE(
-      buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo));
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
+    BufferDescriptor descriptor;
+    ASSERT_NO_FATAL_FAILURE(
+        descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
 
-  IAllocatorClient::BufferDescriptorInfo info = {};
+    for (uint32_t count = 0; count < 5; count++) {
+        std::vector<const native_handle_t*> bufferHandles;
+        uint32_t stride;
+        ASSERT_NO_FATAL_FAILURE(bufferHandles = mGralloc->allocate(
+                                    descriptor, count, false, &stride));
 
-  Mapper::Dimensions dimensions;
-  ASSERT_NO_FATAL_FAILURE(dimensions = mMapper->getDimensions(buffer));
-  info.width = dimensions.width;
-  info.height = dimensions.height;
+        if (count >= 1) {
+            EXPECT_LE(mDummyDescriptorInfo.width, stride)
+                << "invalid buffer stride";
+        }
 
-  ASSERT_NO_FATAL_FAILURE(info.format = mMapper->getFormat(buffer));
-  ASSERT_NO_FATAL_FAILURE(info.producerUsageMask =
-                              mMapper->getProducerUsageMask(buffer));
-  ASSERT_NO_FATAL_FAILURE(info.consumerUsageMask =
-                              mMapper->getConsumerUsageMask(buffer));
+        for (auto bufferHandle : bufferHandles) {
+            mGralloc->freeBuffer(bufferHandle);
+        }
+    }
+}
 
-  EXPECT_EQ(mDummyDescriptorInfo.width, info.width);
-  EXPECT_EQ(mDummyDescriptorInfo.height, info.height);
-  EXPECT_EQ(mDummyDescriptorInfo.format, info.format);
-  EXPECT_EQ(mDummyDescriptorInfo.producerUsageMask, info.producerUsageMask);
-  EXPECT_EQ(mDummyDescriptorInfo.consumerUsageMask, info.consumerUsageMask);
+/**
+ * Test IAllocator::allocate with invalid buffer descriptors.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
+    // this assumes any valid descriptor is non-empty
+    BufferDescriptor descriptor;
+    mGralloc->getAllocator()->allocate(
+        descriptor, 1, [&](const auto& tmpError, const auto&, const auto&) {
+            EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
+        });
+}
 
-  ASSERT_NO_FATAL_FAILURE(mMapper->getBackingStore(buffer));
+/**
+ * Test IAllocator::allocate does not leak.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 1024;
+    info.height = 1024;
 
-  uint32_t stride;
-  ASSERT_NO_FATAL_FAILURE(stride = mMapper->getStride(buffer));
-  EXPECT_LE(info.width, stride);
+    for (int i = 0; i < 2048; i++) {
+        auto bufferHandle = mGralloc->allocate(info, false);
+        mGralloc->freeBuffer(bufferHandle);
+    }
+}
+
+/**
+ * Test IMapper::createDescriptor with valid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
+    ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
+}
+
+/**
+ * Test IMapper::createDescriptor with invalid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 0;
+    mGralloc->getMapper()->createDescriptor(
+        info, [&](const auto& tmpError, const auto&) {
+            EXPECT_EQ(Error::BAD_VALUE, tmpError)
+                << "createDescriptor did not fail with BAD_VALUE";
+        });
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
+    const native_handle_t* bufferHandle;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle =
+                                mGralloc->allocate(mDummyDescriptorInfo, true));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
+    const native_handle_t* clonedBufferHandle;
+    ASSERT_NO_FATAL_FAILURE(
+        clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+
+    // A cloned handle is a raw handle. Check that we can import it multiple
+    // times.
+    const native_handle_t* importedBufferHandles[2];
+    ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] =
+                                mGralloc->importBuffer(clonedBufferHandle));
+    ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] =
+                                mGralloc->importBuffer(clonedBufferHandle));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0]));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1]));
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(clonedBufferHandle));
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
+    const native_handle_t* rawHandle;
+    ASSERT_NO_FATAL_FAILURE(
+        rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+
+    native_handle_t* importedHandle = nullptr;
+    mGralloc->getMapper()->importBuffer(
+        rawHandle, [&](const auto& tmpError, const auto& buffer) {
+            ASSERT_EQ(Error::NONE, tmpError);
+            importedHandle = static_cast<native_handle_t*>(buffer);
+        });
+
+    // free the imported handle with another mapper
+    std::unique_ptr<Gralloc> anotherGralloc;
+    ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>());
+    Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
+    ASSERT_EQ(Error::NONE, error);
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawHandle));
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer do not leak.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 1024;
+    info.height = 1024;
+
+    for (int i = 0; i < 2048; i++) {
+        auto bufferHandle = mGralloc->allocate(info, true);
+        mGralloc->freeBuffer(bufferHandle);
+    }
+}
+
+/**
+ * Test IMapper::importBuffer with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
+    native_handle_t* invalidHandle = nullptr;
+    mGralloc->getMapper()->importBuffer(
+        invalidHandle, [&](const auto& tmpError, const auto&) {
+            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+                << "importBuffer with nullptr did not fail with BAD_BUFFER";
+        });
+
+    invalidHandle = native_handle_create(0, 0);
+    mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError,
+                                                           const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "importBuffer with invalid handle did not fail with BAD_BUFFER";
+    });
+    native_handle_delete(invalidHandle);
+
+    const native_handle_t* importedHandle;
+    ASSERT_NO_FATAL_FAILURE(importedHandle =
+                                mGralloc->allocate(mDummyDescriptorInfo, true));
+    mGralloc->getMapper()->importBuffer(
+        importedHandle, [&](const auto& tmpError, const auto&) {
+            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+                << "importBuffer with an "
+                   "already imported handle did "
+                   "not fail with BAD_BUFFER";
+        });
+    mGralloc->freeBuffer(importedHandle);
+}
+
+/**
+ * Test IMapper::freeBuffer with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
+    native_handle_t* invalidHandle = nullptr;
+    Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+    EXPECT_EQ(Error::BAD_BUFFER, error)
+        << "freeBuffer with nullptr did not fail with BAD_BUFFER";
+
+    invalidHandle = native_handle_create(0, 0);
+    error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+    EXPECT_EQ(Error::BAD_BUFFER, error)
+        << "freeBuffer with invalid handle did not fail with BAD_BUFFER";
+    native_handle_delete(invalidHandle);
+
+    const native_handle_t* clonedBufferHandle;
+    ASSERT_NO_FATAL_FAILURE(
+        clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+    error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+    EXPECT_EQ(Error::BAD_BUFFER, error)
+        << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
+
+    mGralloc->freeBuffer(clonedBufferHandle);
 }
 
 /**
  * Test IMapper::lock and IMapper::unlock.
  */
-TEST_F(GraphicsMapperHidlTest, LockBasic) {
-  const auto& info = mDummyDescriptorInfo;
+TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
+    const auto& info = mDummyDescriptorInfo;
 
-  const native_handle_t* buffer;
-  ASSERT_NO_FATAL_FAILURE(
-      buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo));
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle =
+                                mGralloc->allocate(info, true, &stride));
 
-  uint32_t stride;
-  ASSERT_NO_FATAL_FAILURE(stride = mMapper->getStride(buffer));
+    // lock buffer for writing
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    int fence = -1;
+    uint8_t* data;
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
+                                bufferHandle, info.usage, region, fence)));
 
-  // lock buffer for writing
-  const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
-                             static_cast<int32_t>(info.height)};
-  int fence = -1;
-  uint32_t* data;
-  ASSERT_NO_FATAL_FAILURE(
-      data = static_cast<uint32_t*>(
-          mMapper->lock(buffer, info.producerUsageMask, 0, region, fence)));
+    // RGBA_8888
+    size_t strideInBytes = stride * 4;
+    size_t writeInBytes = info.width * 4;
 
-  for (uint32_t y = 0; y < info.height; y++) {
-    for (uint32_t x = 0; x < info.width; x++) {
-      data[stride * y + x] = info.height * y + x;
+    for (uint32_t y = 0; y < info.height; y++) {
+        memset(data, y, writeInBytes);
+        data += strideInBytes;
     }
-  }
 
-  ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
 
-  // lock buffer for reading
-  ASSERT_NO_FATAL_FAILURE(
-      data = static_cast<uint32_t*>(
-          mMapper->lock(buffer, 0, info.consumerUsageMask, region, fence)));
-  for (uint32_t y = 0; y < info.height; y++) {
-    for (uint32_t x = 0; x < info.width; x++) {
-      EXPECT_EQ(info.height * y + x, data[stride * y + x]);
+    // lock again for reading
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
+                                bufferHandle, info.usage, region, fence)));
+    for (uint32_t y = 0; y < info.height; y++) {
+        for (size_t i = 0; i < writeInBytes; i++) {
+            EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
+        }
+        data += strideInBytes;
     }
-  }
 
-  ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
-  if (fence >= 0) {
-    close(fence);
-  }
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+    if (fence >= 0) {
+        close(fence);
+    }
 }
 
 /**
- * Test IMapper::lockFlex.  This locks a YV12 buffer, and makes sure we can
+ * Test IMapper::lockYCbCr.  This locks a YV12 buffer, and makes sure we can
  * write to and read from it.
  */
-TEST_F(GraphicsMapperHidlTest, LockFlexBasic) {
-  auto info = mDummyDescriptorInfo;
-  info.format = PixelFormat::YV12;
+TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::YV12;
 
-  const native_handle_t* buffer;
-  ASSERT_NO_FATAL_FAILURE(buffer = mMapper->allocate(mAllocatorClient, info));
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle =
+                                mGralloc->allocate(info, true, &stride));
 
-  // lock buffer for writing
-  const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
-                             static_cast<int32_t>(info.height)};
-  int fence = -1;
-  FlexLayout layout;
-  ASSERT_NO_FATAL_FAILURE(
-      layout =
-          mMapper->lockFlex(buffer, info.producerUsageMask, 0, region, fence));
-  ASSERT_EQ(FlexFormat::YCBCR, layout.format);
-  ASSERT_EQ(3u, layout.planes.size());
+    // lock buffer for writing
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    int fence = -1;
+    YCbCrLayout layout;
+    ASSERT_NO_FATAL_FAILURE(
+        layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
 
-  const auto y_stride = layout.planes[0].vIncrement;
-  const auto c_stride = layout.planes[1].vIncrement;
-  auto y_data = static_cast<uint8_t*>(layout.planes[0].topLeft);
-  auto cb_data = static_cast<uint8_t*>(layout.planes[1].topLeft);
-  auto cr_data = static_cast<uint8_t*>(layout.planes[2].topLeft);
+    auto yData = static_cast<uint8_t*>(layout.y);
+    auto cbData = static_cast<uint8_t*>(layout.cb);
+    auto crData = static_cast<uint8_t*>(layout.cr);
+    for (uint32_t y = 0; y < info.height; y++) {
+        for (uint32_t x = 0; x < info.width; x++) {
+            auto val = static_cast<uint8_t>(info.height * y + x);
 
-  for (uint32_t y = 0; y < info.height; y++) {
-    for (uint32_t x = 0; x < info.width; x++) {
-      auto val = static_cast<uint8_t>(info.height * y + x);
-
-      y_data[y_stride * y + x] = val;
-      if (y % 2 == 0 && x % 2 == 0) {
-        cb_data[c_stride * y / 2 + x / 2] = val;
-        cr_data[c_stride * y / 2 + x / 2] = val;
-      }
+            yData[layout.yStride * y + x] = val;
+            if (y % 2 == 0 && x % 2 == 0) {
+                cbData[layout.cStride * y / 2 + x / 2] = val;
+                crData[layout.cStride * y / 2 + x / 2] = val;
+            }
+        }
     }
-  }
 
-  ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
 
-  // lock buffer for reading
-  ASSERT_NO_FATAL_FAILURE(
-      layout =
-          mMapper->lockFlex(buffer, 0, info.consumerUsageMask, region, fence));
+    // lock again for reading
+    ASSERT_NO_FATAL_FAILURE(
+        layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
 
-  y_data = static_cast<uint8_t*>(layout.planes[0].topLeft);
-  cb_data = static_cast<uint8_t*>(layout.planes[1].topLeft);
-  cr_data = static_cast<uint8_t*>(layout.planes[2].topLeft);
-  for (uint32_t y = 0; y < info.height; y++) {
-    for (uint32_t x = 0; x < info.width; x++) {
-      auto val = static_cast<uint8_t>(info.height * y + x);
+    yData = static_cast<uint8_t*>(layout.y);
+    cbData = static_cast<uint8_t*>(layout.cb);
+    crData = static_cast<uint8_t*>(layout.cr);
+    for (uint32_t y = 0; y < info.height; y++) {
+        for (uint32_t x = 0; x < info.width; x++) {
+            auto val = static_cast<uint8_t>(info.height * y + x);
 
-      EXPECT_EQ(val, y_data[y_stride * y + x]);
-      if (y % 2 == 0 && x % 2 == 0) {
-        EXPECT_EQ(val, cb_data[c_stride * y / 2 + x / 2]);
-        EXPECT_EQ(val, cr_data[c_stride * y / 2 + x / 2]);
-      }
+            EXPECT_EQ(val, yData[layout.yStride * y + x]);
+            if (y % 2 == 0 && x % 2 == 0) {
+                EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]);
+                EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]);
+            }
+        }
     }
-  }
 
-  ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
-  if (fence >= 0) {
-    close(fence);
-  }
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+    if (fence >= 0) {
+        close(fence);
+    }
 }
 
-}  // namespace anonymous
+/**
+ * Test IMapper::unlock with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
+    native_handle_t* invalidHandle = nullptr;
+    mGralloc->getMapper()->unlock(
+        invalidHandle, [&](const auto& tmpError, const auto&) {
+            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+                << "unlock with nullptr did not fail with BAD_BUFFER";
+        });
+
+    invalidHandle = native_handle_create(0, 0);
+    mGralloc->getMapper()->unlock(
+        invalidHandle, [&](const auto& tmpError, const auto&) {
+            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+                << "unlock with invalid handle did not fail with BAD_BUFFER";
+        });
+    native_handle_delete(invalidHandle);
+
+    ASSERT_NO_FATAL_FAILURE(invalidHandle =
+                                const_cast<native_handle_t*>(mGralloc->allocate(
+                                    mDummyDescriptorInfo, false)));
+    mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError,
+                                                     const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "unlock with un-imported handle did not fail with BAD_BUFFER";
+    });
+    mGralloc->freeBuffer(invalidHandle);
+
+// disabled as it fails on many existing drivers
+#if 0
+  ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
+                              mGralloc->allocate(mDummyDescriptorInfo, true)));
+  mGralloc->getMapper()->unlock(
+      invalidHandle, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "unlock with unlocked handle did not fail with BAD_BUFFER";
+      });
+  mGralloc->freeBuffer(invalidHandle);
+#endif
+}
+
+}  // namespace
 }  // namespace tests
 }  // namespace V2_0
 }  // namespace mapper
diff --git a/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
index fd43178..849d270 100644
--- a/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
+++ b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
@@ -1,4 +1,4 @@
 service keymaster-3-0 /vendor/bin/hw/android.hardware.keymaster@3.0-service
-    class hal
+    class early_hal
     user system
     group system drmrpc
diff --git a/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp b/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp
index a8d8aea..6ff566e 100644
--- a/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp
+++ b/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp
@@ -22,6 +22,7 @@
 
 #include <VtsHalHidlTargetTestBase.h>
 
+#include <fcntl.h>
 #include <algorithm>
 #include <vector>
 
diff --git a/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp b/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
index cd1a261..c94fa4f 100644
--- a/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
+++ b/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
@@ -24,6 +24,7 @@
 
 #include <VtsHalHidlTargetTestBase.h>
 
+#include <fcntl.h>
 #include <algorithm>
 
 using ::android::hardware::power::V1_0::IPower;
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
index 9094f39..d40f15a 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
@@ -18,7 +18,7 @@
 
 void RadioHidlTest::SetUp() {
   radio = ::testing::VtsHalHidlTargetTestBase::getService<IRadio>(
-      hidl_string("rild"));
+      hidl_string(RADIO_SERVICE_NAME));
   ASSERT_NE(radio, nullptr);
 
   radioRsp = new RadioResponse(*this);
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_utils.h b/radio/1.0/vts/functional/radio_hidl_hal_utils.h
index 6826238..51db87b 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_utils.h
+++ b/radio/1.0/vts/functional/radio_hidl_hal_utils.h
@@ -81,6 +81,7 @@
 using ::android::sp;
 
 #define TIMEOUT_PERIOD 40
+#define RADIO_SERVICE_NAME "slot1"
 
 class RadioHidlTest;
 extern CardStatus cardStatus;
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
index 88274cd..02accef 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
@@ -18,7 +18,7 @@
 
 void SapHidlTest::SetUp() {
   sap = ::testing::VtsHalHidlTargetTestBase::getService<ISap>(
-      hidl_string("sap_uim_socket1"));
+      hidl_string(SAP_SERVICE_NAME));
   ASSERT_NE(sap, nullptr);
 
   sapCb = new SapCallback(*this);
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_utils.h b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
index 2ee3c96..38fb003 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_utils.h
+++ b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
@@ -34,6 +34,7 @@
 using ::android::sp;
 
 #define TIMEOUT_PERIOD 40
+#define SAP_SERVICE_NAME "slot1"
 
 class SapHidlTest;
 
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index a65c7b8..f757a64 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -15,14 +15,14 @@
  */
 
 #define LOG_TAG "sensors_hidl_hal_test"
+#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <android/hardware/sensors/1.0/types.h>
-#include <android/log.h>
 #include <cutils/ashmem.h>
+#include <hardware/sensors.h>  // for sensor type strings
+#include <log/log.h>
 #include <utils/SystemClock.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <hardware/sensors.h>       // for sensor type strings
 
 #include <algorithm>
 #include <cinttypes>
@@ -616,7 +616,7 @@
 
   switch (type) {
 #define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \
-    case SensorType::type: ASSERT_STREQ(SENSOR_STRING_TYPE_ ## type, stringType); break;
+    case SensorType::type: ASSERT_STREQ(SENSOR_STRING_TYPE_ ## type, stringType.c_str()); break;
     CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
     CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
     CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
diff --git a/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp b/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
index 3fbef18..2eca8f4 100644
--- a/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
+++ b/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
@@ -23,6 +23,7 @@
 
 #include <android/log.h>
 #include <cutils/native_handle.h>
+#include <log/log.h>
 
 #include <android/hardware/audio/common/2.0/types.h>
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
diff --git a/tests/baz/1.0/Android.bp b/tests/baz/1.0/Android.bp
index 8f327e3..1d5013b 100644
--- a/tests/baz/1.0/Android.bp
+++ b/tests/baz/1.0/Android.bp
@@ -7,6 +7,7 @@
         "IBase.hal",
         "IBaz.hal",
         "IBazCallback.hal",
+        "IQuux.hal",
     ],
 }
 
@@ -22,6 +23,7 @@
         "android/hardware/tests/baz/1.0/BaseAll.cpp",
         "android/hardware/tests/baz/1.0/BazAll.cpp",
         "android/hardware/tests/baz/1.0/BazCallbackAll.cpp",
+        "android/hardware/tests/baz/1.0/QuuxAll.cpp",
     ],
 }
 
@@ -50,6 +52,11 @@
         "android/hardware/tests/baz/1.0/BnHwBazCallback.h",
         "android/hardware/tests/baz/1.0/BpHwBazCallback.h",
         "android/hardware/tests/baz/1.0/BsBazCallback.h",
+        "android/hardware/tests/baz/1.0/IQuux.h",
+        "android/hardware/tests/baz/1.0/IHwQuux.h",
+        "android/hardware/tests/baz/1.0/BnHwQuux.h",
+        "android/hardware/tests/baz/1.0/BpHwQuux.h",
+        "android/hardware/tests/baz/1.0/BsQuux.h",
     ],
 }
 
diff --git a/tests/baz/1.0/Android.mk b/tests/baz/1.0/Android.mk
index 40026ec..9d4d6b6 100644
--- a/tests/baz/1.0/Android.mk
+++ b/tests/baz/1.0/Android.mk
@@ -76,6 +76,25 @@
 $(GEN): $(LOCAL_PATH)/IBazCallback.hal
 	$(transform-generated-source)
 LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IQuux.hal
+#
+GEN := $(intermediates)/android/hardware/tests/baz/V1_0/IQuux.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IQuux.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tests.baz@1.0::IQuux
+
+$(GEN): $(LOCAL_PATH)/IQuux.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
 include $(BUILD_JAVA_LIBRARY)
 
 
@@ -153,6 +172,25 @@
 $(GEN): $(LOCAL_PATH)/IBazCallback.hal
 	$(transform-generated-source)
 LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IQuux.hal
+#
+GEN := $(intermediates)/android/hardware/tests/baz/V1_0/IQuux.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IQuux.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tests.baz@1.0::IQuux
+
+$(GEN): $(LOCAL_PATH)/IQuux.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 
diff --git a/tests/baz/1.0/IQuux.hal b/tests/baz/1.0/IQuux.hal
new file mode 100644
index 0000000..ccf3212
--- /dev/null
+++ b/tests/baz/1.0/IQuux.hal
@@ -0,0 +1,20 @@
+/*
+ * 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.baz@1.0;
+
+interface IQuux {
+};
diff --git a/usb/1.0/default/Usb.h b/usb/1.0/default/Usb.h
index c34d080..ddfcac6 100644
--- a/usb/1.0/default/Usb.h
+++ b/usb/1.0/default/Usb.h
@@ -4,7 +4,7 @@
 #include <android/hardware/usb/1.0/IUsb.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
-#include <utils/Log.h>
+#include <log/log.h>
 
 #ifdef LOG_TAG
 #undef LOG_TAG
diff --git a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
index ea6d4a9..b77398f 100644
--- a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
+++ b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
@@ -22,6 +22,7 @@
 #include <android/hardware/usb/1.0/types.h>
 
 #include <VtsHalHidlTargetTestBase.h>
+#include <log/log.h>
 #include <stdlib.h>
 #include <chrono>
 #include <condition_variable>
diff --git a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
index a983731..23f4c71 100644
--- a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
+++ b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
@@ -15,11 +15,11 @@
  */
 
 #define LOG_TAG "vr_hidl_hal_test"
+#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/vr/1.0/IVr.h>
-#include <android/log.h>
-#include <VtsHalHidlTargetTestBase.h>
 #include <hardware/vr.h>
+#include <log/log.h>
 
 using ::android::hardware::vr::V1_0::IVr;
 using ::android::hardware::Return;
diff --git a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
index 42d9a96..c0af30b 100644
--- a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -20,9 +20,13 @@
 
 #include <VtsHalHidlTargetTestBase.h>
 
+#include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
 
+using ::android::hardware::wifi::V1_0::IfaceType;
 using ::android::hardware::wifi::V1_0::IWifiApIface;
+using ::android::hardware::wifi::V1_0::WifiBand;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
 using ::android::sp;
 
 /**
@@ -30,11 +34,15 @@
  */
 class WifiApIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
-    virtual void SetUp() override {}
+    virtual void SetUp() override {
+        wifi_ap_iface_ = getWifiApIface();
+        ASSERT_NE(nullptr, wifi_ap_iface_.get());
+    }
 
     virtual void TearDown() override { stopWifi(); }
 
    protected:
+    sp<IWifiApIface> wifi_ap_iface_;
 };
 
 /*
@@ -46,3 +54,36 @@
     EXPECT_NE(nullptr, getWifiApIface().get());
     stopWifi();
 }
+
+/*
+ * GetType:
+ * Ensures that the correct interface type is returned for AP interface.
+ */
+TEST_F(WifiApIfaceHidlTest, GetType) {
+    const auto& status_and_type = HIDL_INVOKE(wifi_ap_iface_, getType);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_type.first.code);
+    EXPECT_EQ(IfaceType::AP, status_and_type.second);
+}
+
+/*
+ * SetCountryCode:
+ * Ensures that a call to set the country code will return with a success
+ * status code.
+ */
+TEST_F(WifiApIfaceHidlTest, SetCountryCode) {
+    const android::hardware::hidl_array<int8_t, 2> kCountryCode{
+        std::array<int8_t, 2>{{0x55, 0x53}}};
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_ap_iface_, setCountryCode, kCountryCode).code);
+}
+
+/*
+ * GetValidFrequenciesForBand:
+ * Ensures that we can retrieve valid frequencies for 2.4 GHz band.
+ */
+TEST_F(WifiApIfaceHidlTest, GetValidFrequenciesForBand) {
+    const auto& status_and_freqs = HIDL_INVOKE(
+        wifi_ap_iface_, getValidFrequenciesForBand, WifiBand::BAND_24GHZ);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_freqs.first.code);
+    EXPECT_GT(status_and_freqs.second.size(), 0u);
+}
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
index 084067c..0627a99 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
@@ -76,15 +76,14 @@
     // Helper function to configure the Chip in one of the supported modes.
     // Most of the non-mode-configuration-related methods require chip
     // to be first configured.
-    ChipModeId configureChipForIfaceType(IfaceType type) {
+    ChipModeId configureChipForIfaceType(IfaceType type, bool expectSuccess) {
         ChipModeId mode_id;
-        EXPECT_TRUE(
-            configureChipToSupportIfaceType(wifi_chip_, type, &mode_id));
+        EXPECT_EQ(expectSuccess, configureChipToSupportIfaceType(wifi_chip_, type, &mode_id));
         return mode_id;
     }
 
     uint32_t configureChipForStaIfaceAndGetCapabilities() {
-        configureChipForIfaceType(IfaceType::STA);
+        configureChipForIfaceType(IfaceType::STA, true);
         const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
         EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
         return status_and_caps.second;
@@ -183,7 +182,7 @@
  * GetCapabilities:
  */
 TEST_F(WifiChipHidlTest, GetCapabilities) {
-    configureChipForIfaceType(IfaceType::STA);
+    configureChipForIfaceType(IfaceType::STA, true);
     const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
     EXPECT_NE(0u, status_and_caps.second);
@@ -193,7 +192,7 @@
  * GetMode:
  */
 TEST_F(WifiChipHidlTest, GetMode) {
-    ChipModeId chip_mode_id = configureChipForIfaceType(IfaceType::STA);
+    ChipModeId chip_mode_id = configureChipForIfaceType(IfaceType::STA, true);
     const auto& status_and_mode = HIDL_INVOKE(wifi_chip_, getMode);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_mode.first.code);
     EXPECT_EQ(chip_mode_id, status_and_mode.second);
@@ -203,7 +202,7 @@
  * RequestChipDebugInfo:
  */
 TEST_F(WifiChipHidlTest, RequestChipDebugInfo) {
-    configureChipForIfaceType(IfaceType::STA);
+    configureChipForIfaceType(IfaceType::STA, true);
     const auto& status_and_chip_info =
         HIDL_INVOKE(wifi_chip_, requestChipDebugInfo);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_chip_info.first.code);
@@ -236,8 +235,10 @@
     if (caps & IWifiChip::ChipCapabilityMask::DEBUG_MEMORY_DRIVER_DUMP) {
         EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_driver_dump.first.code);
     } else {
-        EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED,
-                  status_and_driver_dump.first.code);
+      // API semantics (today) are such that function cannot be called if not capable!
+      //
+      //  EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED,
+      //            status_and_driver_dump.first.code);
     }
 }
 
@@ -336,7 +337,7 @@
  * succeeds. The 2nd iface creation should be rejected.
  */
 TEST_F(WifiChipHidlTest, CreateApIface) {
-    configureChipForIfaceType(IfaceType::AP);
+    configureChipForIfaceType(IfaceType::AP, true);
 
     sp<IWifiApIface> iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createApIface(&iface));
@@ -352,7 +353,7 @@
  * iface name is returned via the list.
  */
 TEST_F(WifiChipHidlTest, GetApIfaceNames) {
-    configureChipForIfaceType(IfaceType::AP);
+    configureChipForIfaceType(IfaceType::AP, true);
 
     const auto& status_and_iface_names1 =
         HIDL_INVOKE(wifi_chip_, getApIfaceNames);
@@ -384,7 +385,7 @@
  * doesn't retrieve an iface object.
  */
 TEST_F(WifiChipHidlTest, GetApIface) {
-    configureChipForIfaceType(IfaceType::AP);
+    configureChipForIfaceType(IfaceType::AP, true);
 
     sp<IWifiApIface> ap_iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createApIface(&ap_iface));
@@ -410,7 +411,7 @@
  * doesn't remove the iface.
  */
 TEST_F(WifiChipHidlTest, RemoveApIface) {
-    configureChipForIfaceType(IfaceType::AP);
+    configureChipForIfaceType(IfaceType::AP, true);
 
     sp<IWifiApIface> ap_iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createApIface(&ap_iface));
@@ -431,13 +432,10 @@
  * succeeds. The 2nd iface creation should be rejected.
  */
 TEST_F(WifiChipHidlTest, CreateNanIface) {
-    configureChipForIfaceType(IfaceType::NAN);
+    configureChipForIfaceType(IfaceType::NAN, false);
 
     sp<IWifiNanIface> iface;
-    EXPECT_EQ(WifiStatusCode::SUCCESS, createNanIface(&iface));
-    EXPECT_NE(nullptr, iface.get());
-
-    EXPECT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createNanIface(&iface));
+    ASSERT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createNanIface(&iface));
 }
 
 /*
@@ -447,29 +445,12 @@
  * iface name is returned via the list.
  */
 TEST_F(WifiChipHidlTest, GetNanIfaceNames) {
-    configureChipForIfaceType(IfaceType::NAN);
+    configureChipForIfaceType(IfaceType::NAN, false);
 
     const auto& status_and_iface_names1 =
         HIDL_INVOKE(wifi_chip_, getNanIfaceNames);
-    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface_names1.first.code);
+    ASSERT_EQ(WifiStatusCode::SUCCESS, status_and_iface_names1.first.code);
     EXPECT_EQ(0u, status_and_iface_names1.second.size());
-
-    sp<IWifiNanIface> iface;
-    EXPECT_EQ(WifiStatusCode::SUCCESS, createNanIface(&iface));
-    EXPECT_NE(nullptr, iface.get());
-
-    std::string iface_name = getIfaceName(iface);
-    const auto& status_and_iface_names2 =
-        HIDL_INVOKE(wifi_chip_, getNanIfaceNames);
-    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface_names2.first.code);
-    EXPECT_EQ(1u, status_and_iface_names2.second.size());
-    EXPECT_EQ(iface_name, status_and_iface_names2.second[0]);
-
-    EXPECT_EQ(WifiStatusCode::SUCCESS, removeNanIface(iface_name));
-    const auto& status_and_iface_names3 =
-        HIDL_INVOKE(wifi_chip_, getNanIfaceNames);
-    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface_names3.first.code);
-    EXPECT_EQ(0u, status_and_iface_names3.second.size());
 }
 
 /*
@@ -479,23 +460,10 @@
  * doesn't retrieve an iface object.
  */
 TEST_F(WifiChipHidlTest, GetNanIface) {
-    configureChipForIfaceType(IfaceType::NAN);
+    configureChipForIfaceType(IfaceType::NAN, false);
 
     sp<IWifiNanIface> nan_iface;
-    EXPECT_EQ(WifiStatusCode::SUCCESS, createNanIface(&nan_iface));
-    EXPECT_NE(nullptr, nan_iface.get());
-
-    std::string iface_name = getIfaceName(nan_iface);
-    const auto& status_and_iface1 =
-        HIDL_INVOKE(wifi_chip_, getNanIface, iface_name);
-    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface1.first.code);
-    EXPECT_NE(nullptr, status_and_iface1.second.get());
-
-    std::string invalid_name = iface_name + "0";
-    const auto& status_and_iface2 =
-        HIDL_INVOKE(wifi_chip_, getNanIface, invalid_name);
-    EXPECT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, status_and_iface2.first.code);
-    EXPECT_EQ(nullptr, status_and_iface2.second.get());
+    ASSERT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createNanIface(&nan_iface));
 }
 
 /*
@@ -505,20 +473,10 @@
  * doesn't remove the iface.
  */
 TEST_F(WifiChipHidlTest, RemoveNanIface) {
-    configureChipForIfaceType(IfaceType::NAN);
+    configureChipForIfaceType(IfaceType::NAN, false);
 
     sp<IWifiNanIface> nan_iface;
-    EXPECT_EQ(WifiStatusCode::SUCCESS, createNanIface(&nan_iface));
-    EXPECT_NE(nullptr, nan_iface.get());
-
-    std::string iface_name = getIfaceName(nan_iface);
-    std::string invalid_name = iface_name + "0";
-    EXPECT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, removeNanIface(invalid_name));
-
-    EXPECT_EQ(WifiStatusCode::SUCCESS, removeNanIface(iface_name));
-
-    // No such iface exists now. So, this should return failure.
-    EXPECT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, removeNanIface(iface_name));
+    ASSERT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createNanIface(&nan_iface));
 }
 
 /*
@@ -527,7 +485,7 @@
  * succeeds. The 2nd iface creation should be rejected.
  */
 TEST_F(WifiChipHidlTest, CreateP2pIface) {
-    configureChipForIfaceType(IfaceType::P2P);
+    configureChipForIfaceType(IfaceType::P2P, true);
 
     sp<IWifiP2pIface> iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createP2pIface(&iface));
@@ -543,7 +501,7 @@
  * iface name is returned via the list.
  */
 TEST_F(WifiChipHidlTest, GetP2pIfaceNames) {
-    configureChipForIfaceType(IfaceType::P2P);
+    configureChipForIfaceType(IfaceType::P2P, true);
 
     const auto& status_and_iface_names1 =
         HIDL_INVOKE(wifi_chip_, getP2pIfaceNames);
@@ -575,7 +533,7 @@
  * doesn't retrieve an iface object.
  */
 TEST_F(WifiChipHidlTest, GetP2pIface) {
-    configureChipForIfaceType(IfaceType::P2P);
+    configureChipForIfaceType(IfaceType::P2P, true);
 
     sp<IWifiP2pIface> p2p_iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createP2pIface(&p2p_iface));
@@ -601,7 +559,7 @@
  * doesn't remove the iface.
  */
 TEST_F(WifiChipHidlTest, RemoveP2pIface) {
-    configureChipForIfaceType(IfaceType::P2P);
+    configureChipForIfaceType(IfaceType::P2P, true);
 
     sp<IWifiP2pIface> p2p_iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createP2pIface(&p2p_iface));
@@ -622,7 +580,7 @@
  * succeeds. The 2nd iface creation should be rejected.
  */
 TEST_F(WifiChipHidlTest, CreateStaIface) {
-    configureChipForIfaceType(IfaceType::STA);
+    configureChipForIfaceType(IfaceType::STA, true);
 
     sp<IWifiStaIface> iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&iface));
@@ -638,7 +596,7 @@
  * iface name is returned via the list.
  */
 TEST_F(WifiChipHidlTest, GetStaIfaceNames) {
-    configureChipForIfaceType(IfaceType::STA);
+    configureChipForIfaceType(IfaceType::STA, true);
 
     const auto& status_and_iface_names1 =
         HIDL_INVOKE(wifi_chip_, getStaIfaceNames);
@@ -670,7 +628,7 @@
  * doesn't retrieve an iface object.
  */
 TEST_F(WifiChipHidlTest, GetStaIface) {
-    configureChipForIfaceType(IfaceType::STA);
+    configureChipForIfaceType(IfaceType::STA, true);
 
     sp<IWifiStaIface> sta_iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&sta_iface));
@@ -696,7 +654,7 @@
  * doesn't remove the iface.
  */
 TEST_F(WifiChipHidlTest, RemoveStaIface) {
-    configureChipForIfaceType(IfaceType::STA);
+    configureChipForIfaceType(IfaceType::STA, true);
 
     sp<IWifiStaIface> sta_iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&sta_iface));
@@ -715,7 +673,7 @@
  * CreateRttController
  */
 TEST_F(WifiChipHidlTest, CreateRttController) {
-    configureChipForIfaceType(IfaceType::AP);
+    configureChipForIfaceType(IfaceType::AP, true);
 
     sp<IWifiApIface> iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createApIface(&iface));
diff --git a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
index 95add61..83f83b6 100644
--- a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -24,7 +24,16 @@
 #include "wifi_hidl_test_utils.h"
 
 using ::android::sp;
+using ::android::hardware::wifi::V1_0::Bssid;
+using ::android::hardware::wifi::V1_0::CommandId;
+using ::android::hardware::wifi::V1_0::IfaceType;
 using ::android::hardware::wifi::V1_0::IWifiStaIface;
+using ::android::hardware::wifi::V1_0::Rssi;
+using ::android::hardware::wifi::V1_0::Ssid;
+using ::android::hardware::wifi::V1_0::StaApfPacketFilterCapabilities;
+using ::android::hardware::wifi::V1_0::StaRoamingConfig;
+using ::android::hardware::wifi::V1_0::StaRoamingState;
+using ::android::hardware::wifi::V1_0::WifiBand;
 using ::android::hardware::wifi::V1_0::WifiStatus;
 using ::android::hardware::wifi::V1_0::WifiStatusCode;
 
@@ -41,6 +50,13 @@
     virtual void TearDown() override { stopWifi(); }
 
    protected:
+    bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask cap_mask) {
+        const auto& status_and_caps =
+            HIDL_INVOKE(wifi_sta_iface_, getCapabilities);
+        EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+        return (status_and_caps.second & cap_mask) != 0;
+    }
+
     sp<IWifiStaIface> wifi_sta_iface_;
 };
 
@@ -60,5 +76,190 @@
 TEST_F(WifiStaIfaceHidlTest, GetCapabilities) {
     const auto& status_and_caps = HIDL_INVOKE(wifi_sta_iface_, getCapabilities);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
-    EXPECT_NE(0u, status_and_caps.second);
+    EXPECT_GT(status_and_caps.second, 0u);
+}
+
+/*
+ * GetType:
+ * Ensures that the correct interface type is returned for station interface.
+ */
+TEST_F(WifiStaIfaceHidlTest, GetType) {
+    const auto& status_and_type = HIDL_INVOKE(wifi_sta_iface_, getType);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_type.first.code);
+    EXPECT_EQ(IfaceType::STA, status_and_type.second);
+}
+
+/*
+ * GetApfPacketFilterCapabilities:
+ * Ensures that we can retrieve APF packet filter capabilites.
+ */
+TEST_F(WifiStaIfaceHidlTest, GetApfPacketFilterCapabilities) {
+    if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::APF)) {
+        // No-op if APF packet filer is not supported.
+        return;
+    }
+
+    const auto& status_and_caps =
+        HIDL_INVOKE(wifi_sta_iface_, getApfPacketFilterCapabilities);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+}
+
+/*
+ * GetBackgroundScanCapabilities:
+ * Ensures that we can retrieve background scan capabilities.
+ */
+TEST_F(WifiStaIfaceHidlTest, GetBackgroundScanCapabilities) {
+    if (!isCapabilitySupported(
+            IWifiStaIface::StaIfaceCapabilityMask::BACKGROUND_SCAN)) {
+        // No-op if background scan is not supported.
+        return;
+    }
+
+    const auto& status_and_caps =
+        HIDL_INVOKE(wifi_sta_iface_, getBackgroundScanCapabilities);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+}
+
+/*
+ * GetValidFrequenciesForBand:
+ * Ensures that we can retrieve valid frequencies for 2.4 GHz band.
+ */
+TEST_F(WifiStaIfaceHidlTest, GetValidFrequenciesForBand) {
+    const auto& status_and_freqs = HIDL_INVOKE(
+        wifi_sta_iface_, getValidFrequenciesForBand, WifiBand::BAND_24GHZ);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_freqs.first.code);
+    EXPECT_GT(status_and_freqs.second.size(), 0u);
+}
+
+/*
+ * LinkLayerStatsCollection:
+ * Ensures that calls to enable, disable, and retrieve link layer stats
+ * will return a success status code.
+ */
+TEST_F(WifiStaIfaceHidlTest, LinkLayerStatsCollection) {
+    if (!isCapabilitySupported(
+            IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) {
+        // No-op if link layer stats is not supported.
+        return;
+    }
+
+    // Enable link layer stats collection.
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true)
+                  .code);
+    // Retrieve link layer stats.
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, getLinkLayerStats).first.code);
+    // Disable link layer stats collection.
+    EXPECT_EQ(
+        WifiStatusCode::SUCCESS,
+        HIDL_INVOKE(wifi_sta_iface_, disableLinkLayerStatsCollection).code);
+}
+
+/*
+ * RSSIMonitoring:
+ * Ensures that calls to enable and disable RSSI monitoring will return
+ * a success status code.
+ */
+TEST_F(WifiStaIfaceHidlTest, RSSIMonitoring) {
+    if (!isCapabilitySupported(
+            IWifiStaIface::StaIfaceCapabilityMask::RSSI_MONITOR)) {
+        // No-op if RSSI monitor is not supported.
+        return;
+    }
+
+    const CommandId kCmd = 1;
+    const Rssi kMaxRssi = -50;
+    const Rssi kMinRssi = -90;
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, startRssiMonitoring, kCmd, kMaxRssi,
+                          kMinRssi)
+                  .code);
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, stopRssiMonitoring, kCmd).code);
+}
+
+/*
+ * RoamingControl:
+ * Ensures that calls to configure and enable roaming will return a success
+ * status code.
+ */
+TEST_F(WifiStaIfaceHidlTest, RoamingControl) {
+    if (!isCapabilitySupported(
+            IWifiStaIface::StaIfaceCapabilityMask::CONTROL_ROAMING)) {
+        // No-op if roaming control is not supported.
+        return;
+    }
+
+    // Retrieve roaming capabilities.
+    const auto& status_and_cap =
+        HIDL_INVOKE(wifi_sta_iface_, getRoamingCapabilities);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_cap.first.code);
+
+    // Setup roaming configuration based on roaming capabilities.
+    const auto& cap = status_and_cap.second;
+    StaRoamingConfig roaming_config;
+    if (cap.maxBlacklistSize > 0) {
+        Bssid black_list_bssid{
+            std::array<uint8_t, 6>{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}};
+        roaming_config.bssidBlacklist =
+            android::hardware::hidl_vec<Bssid>{black_list_bssid};
+    }
+    if (cap.maxWhitelistSize > 0) {
+        Ssid white_list_ssid{
+            std::array<uint8_t, 32>{{0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC}}};
+        roaming_config.ssidWhitelist =
+            android::hardware::hidl_vec<Ssid>{white_list_ssid};
+    }
+
+    // Configure roaming.
+    EXPECT_EQ(
+        WifiStatusCode::SUCCESS,
+        HIDL_INVOKE(wifi_sta_iface_, configureRoaming, roaming_config).code);
+
+    // Enable roaming.
+    EXPECT_EQ(
+        WifiStatusCode::SUCCESS,
+        HIDL_INVOKE(wifi_sta_iface_, setRoamingState, StaRoamingState::ENABLED)
+            .code);
+}
+
+/*
+ * EnableNDOffload:
+ * Ensures that calls to enable neighbor discovery offload will return a success
+ * status code.
+ */
+TEST_F(WifiStaIfaceHidlTest, EnableNDOffload) {
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, enableNdOffload, true).code);
+}
+
+/*
+ * SetScanningMacOui:
+ * Ensures that calls to set scanning MAC OUI will return a success status
+ * code.
+ */
+TEST_F(WifiStaIfaceHidlTest, SetScanningMacOui) {
+    const android::hardware::hidl_array<uint8_t, 3> kOui{
+        std::array<uint8_t, 3>{{0x10, 0x22, 0x33}}};
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, setScanningMacOui, kOui).code);
+}
+
+/*
+ * PacketFateMonitoring:
+ * Ensures that calls to start packet fate monitoring and retrieve TX/RX
+ * packets will return a success status code.
+ */
+TEST_F(WifiStaIfaceHidlTest, PacketFateMonitoring) {
+    // Start packet fate monitoring.
+    EXPECT_EQ(
+        WifiStatusCode::SUCCESS,
+        HIDL_INVOKE(wifi_sta_iface_, startDebugPacketFateMonitoring).code);
+
+    // Retrieve packets.
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, getDebugTxPacketFates).first.code);
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, getDebugRxPacketFates).first.code);
 }
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_call_util.h b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_call_util.h
new file mode 100644
index 0000000..1c0fcec
--- /dev/null
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_call_util.h
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+// This file is copied from
+// hardware/interfaces/wifi/1.0/vts/functional/wifi_hidl_call_util.h
+// Please make sure these two file are consistent.
+
+#pragma once
+
+#include <functional>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace {
+namespace detail {
+template <typename>
+struct functionArgSaver;
+
+// Provides a std::function that takes one argument, and a buffer
+// wherein the function will store its argument. The buffer has
+// the same type as the argument, but with const and reference
+// modifiers removed.
+template <typename ArgT>
+struct functionArgSaver<std::function<void(ArgT)>> final {
+    using StorageT = typename std::remove_const<
+        typename std::remove_reference<ArgT>::type>::type;
+
+    std::function<void(ArgT)> saveArgs = [this](ArgT arg) {
+        this->saved_values = arg;
+    };
+
+    StorageT saved_values;
+};
+
+// Provides a std::function that takes two arguments, and a buffer
+// wherein the function will store its arguments. The buffer is a
+// std::pair, whose elements have the same types as the arguments
+// (but with const and reference modifiers removed).
+template <typename Arg1T, typename Arg2T>
+struct functionArgSaver<std::function<void(Arg1T, Arg2T)>> final {
+    using StorageT =
+        std::pair<typename std::remove_const<
+                      typename std::remove_reference<Arg1T>::type>::type,
+                  typename std::remove_const<
+                      typename std::remove_reference<Arg2T>::type>::type>;
+
+    std::function<void(Arg1T, Arg2T)> saveArgs = [this](Arg1T arg1,
+                                                        Arg2T arg2) {
+        this->saved_values = {arg1, arg2};
+    };
+
+    StorageT saved_values;
+};
+
+// Provides a std::function that takes three or more arguments, and a
+// buffer wherein the function will store its arguments. The buffer is a
+// std::tuple whose elements have the same types as the arguments (but
+// with const and reference modifiers removed).
+template <typename... ArgT>
+struct functionArgSaver<std::function<void(ArgT...)>> final {
+    using StorageT = std::tuple<typename std::remove_const<
+        typename std::remove_reference<ArgT>::type>::type...>;
+
+    std::function<void(ArgT...)> saveArgs = [this](ArgT... arg) {
+        this->saved_values = {arg...};
+    };
+
+    StorageT saved_values;
+};
+
+// Invokes |method| on |object|, providing |method| a CallbackT as the
+// final argument. Returns a copy of the parameters that |method| provided
+// to CallbackT. (The parameters are returned by value.)
+template <typename CallbackT, typename MethodT, typename ObjectT,
+          typename... ArgT>
+typename functionArgSaver<CallbackT>::StorageT invokeMethod(
+    MethodT method, ObjectT object, ArgT&&... methodArg) {
+    functionArgSaver<CallbackT> result_buffer;
+    const auto& res = ((*object).*method)(std::forward<ArgT>(methodArg)...,
+                                          result_buffer.saveArgs);
+    EXPECT_TRUE(res.isOk());
+    return result_buffer.saved_values;
+}
+}  // namespace detail
+}  // namespace
+
+// Invokes |method| on |strong_pointer|, passing provided arguments through to
+// |method|.
+//
+// Returns either:
+// - A copy of the result callback parameter (for callbacks with a single
+//   parameter), OR
+// - A pair containing a copy of the result callback parameters (for callbacks
+//   with two parameters), OR
+// - A tuple containing a copy of the result callback paramters (for callbacks
+//   with three or more parameters).
+//
+// Example usage:
+//   EXPECT_EQ(WifiStatusCode::SUCCESS,
+//       HIDL_INVOKE(strong_pointer, methodReturningWifiStatus).code);
+//   EXPECT_EQ(WifiStatusCode::SUCCESS,
+//       HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndOneMore)
+//         .first.code);
+//   EXPECT_EQ(WifiStatusCode::SUCCESS, std::get<0>(
+//       HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndTwoMore))
+//         .code);
+#define HIDL_INVOKE(strong_pointer, method, ...)                              \
+    (detail::invokeMethod<                                                    \
+        std::remove_reference<decltype(*strong_pointer)>::type::method##_cb>( \
+        &std::remove_reference<decltype(*strong_pointer)>::type::method,      \
+        strong_pointer, ##__VA_ARGS__))
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index 72a3c42..7bb43b8 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -219,10 +219,6 @@
     p2p_iface_->stopFind([](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
-
-    p2p_iface_->stopFind([](const SupplicantStatus& status) {
-        EXPECT_NE(SupplicantStatusCode::SUCCESS, status.code);
-    });
 }
 
 /*