Merge "Support IMapper@3.0 in OMX VTS" into qt-dev am: 56e9dd901e am: 72a92733e8
am: e5af6c8605

Change-Id: I0c01283a73c4fdbc8bcfde17dec5a918e5fe1149
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
index 90d9b98..62a163c 100644
--- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
@@ -80,8 +80,7 @@
 
     Return<void> createClient(IComposer::createClient_cb hidl_cb) override {
         std::unique_lock<std::mutex> lock(mClientMutex);
-        bool destroyed = waitForClientDestroyedLocked(lock);
-        if (!destroyed) {
+        if (!waitForClientDestroyedLocked(lock)) {
             hidl_cb(Error::NO_RESOURCES, nullptr);
             return Void();
         }
diff --git a/graphics/composer/2.1/utils/vts/Android.bp b/graphics/composer/2.1/utils/vts/Android.bp
index fcb327f..88b1a8b 100644
--- a/graphics/composer/2.1/utils/vts/Android.bp
+++ b/graphics/composer/2.1/utils/vts/Android.bp
@@ -28,9 +28,18 @@
         "android.hardware.graphics.mapper@2.0-vts",
         "android.hardware.graphics.mapper@3.0-vts",
     ],
+    export_static_lib_headers: [
+        "VtsHalHidlTargetTestBase",
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.mapper@2.0-vts",
+        "android.hardware.graphics.mapper@3.0-vts",
+    ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
     ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
     cflags: [
         "-O0",
         "-g",
diff --git a/graphics/composer/2.2/utils/OWNERS b/graphics/composer/2.2/utils/OWNERS
index a17a50c..3f1e82c 100644
--- a/graphics/composer/2.2/utils/OWNERS
+++ b/graphics/composer/2.2/utils/OWNERS
@@ -3,7 +3,3 @@
 lpy@google.com
 stoza@google.com
 vhau@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
diff --git a/graphics/composer/2.2/utils/command-buffer/Android.bp b/graphics/composer/2.2/utils/command-buffer/Android.bp
index efaabd4..c4ceaab 100644
--- a/graphics/composer/2.2/utils/command-buffer/Android.bp
+++ b/graphics/composer/2.2/utils/command-buffer/Android.bp
@@ -3,11 +3,16 @@
     defaults: ["hidl_defaults"],
     vendor_available: true,
     shared_libs: [
-        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.2",
+    ],
+    export_shared_lib_headers: [
         "android.hardware.graphics.composer@2.2",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
     ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
     export_include_dirs: ["include"],
 }
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index dd979cb..1754a43 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -19,26 +19,32 @@
     defaults: ["hidl_defaults"],
     srcs: [
         "ComposerVts.cpp",
+        "ReadbackVts.cpp",
+        "RenderEngineVts.cpp",
+    ],
+    shared_libs: [
+        "libui",
     ],
     static_libs: [
         "VtsHalHidlTargetTestBase",
-        "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
-        "android.hardware.graphics.mapper@2.1",
         "android.hardware.graphics.mapper@2.1-vts",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@3.0-vts",
+        "libarect",
+        "libmath",
+        "libnativewindow",
+        "librenderengine",
     ],
     export_static_lib_headers: [
+        "VtsHalHidlTargetTestBase",
         "android.hardware.graphics.composer@2.1-vts",
+        "android.hardware.graphics.composer@2.2",
+        "android.hardware.graphics.mapper@2.1-vts",
     ],
     header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
         "android.hardware.graphics.composer@2.2-command-buffer",
     ],
     export_header_lib_headers: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
         "android.hardware.graphics.composer@2.2-command-buffer",
     ],
     cflags: [
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index cd6772a..a380fc0 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -187,11 +187,11 @@
                                                                        /*errOnFailure=*/false));
         if (mGralloc3->getMapper() == nullptr || mGralloc3->getAllocator() == nullptr) {
             mGralloc3 = nullptr;
-            ALOGD("Failed to create gralloc3, initializing gralloc2_1");
+            ALOGD("Failed to initialize gralloc3, initializing gralloc2_1");
             mGralloc2_1 = std::make_shared<Gralloc2_1>(/*errOnFailure*/ false);
             if (!mGralloc2_1->getMapper()) {
                 mGralloc2_1 = nullptr;
-                ALOGD("Failed to create gralloc2_1, initializing gralloc2");
+                ALOGD("Failed to initialize gralloc2_1, initializing gralloc2");
                 ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared<Gralloc2>());
             }
         }
diff --git a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
new file mode 100644
index 0000000..91efc6f
--- /dev/null
+++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2019 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 <composer-vts/2.2/ReadbackVts.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace vts {
+
+void TestLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
+    writer->selectLayer(mLayer);
+    writer->setLayerDisplayFrame(mDisplayFrame);
+    writer->setLayerSourceCrop(mSourceCrop);
+    writer->setLayerZOrder(mZOrder);
+    writer->setLayerSurfaceDamage(mSurfaceDamage);
+    writer->setLayerTransform(mTransform);
+    writer->setLayerPlaneAlpha(mAlpha);
+    writer->setLayerBlendMode(mBlendMode);
+}
+
+const std::vector<ColorMode> ReadbackHelper::colorModes = {ColorMode::SRGB, ColorMode::DISPLAY_P3};
+const std::vector<Dataspace> ReadbackHelper::dataspaces = {Dataspace::V0_SRGB,
+                                                           Dataspace::DISPLAY_P3};
+
+std::string ReadbackHelper::getColorModeString(ColorMode mode) {
+    switch (mode) {
+        case ColorMode::SRGB:
+            return std::string("SRGB");
+        case ColorMode::DISPLAY_P3:
+            return std::string("DISPLAY_P3");
+        default:
+            return std::string("Unsupported color mode for readback");
+    }
+}
+
+std::string ReadbackHelper::getDataspaceString(Dataspace dataspace) {
+    switch (dataspace) {
+        case Dataspace::V0_SRGB:
+            return std::string("V0_SRGB");
+        case Dataspace::DISPLAY_P3:
+            return std::string("DISPLAY_P3");
+        default:
+            return std::string("Unsupported dataspace for readback");
+    }
+}
+
+LayerSettings TestLayer::toRenderEngineLayerSettings() {
+    LayerSettings layerSettings;
+
+    layerSettings.alpha = half(mAlpha);
+    layerSettings.disableBlending = mBlendMode == IComposerClient::BlendMode::NONE;
+    layerSettings.geometry.boundaries = FloatRect(
+            static_cast<float>(mDisplayFrame.left), static_cast<float>(mDisplayFrame.top),
+            static_cast<float>(mDisplayFrame.right), static_cast<float>(mDisplayFrame.bottom));
+
+    const mat4 translation = mat4::translate(vec4(
+            (mTransform & Transform::FLIP_H ? -1.0f : 0.0f) * mDisplayFrame.right,
+            (mTransform & Transform::FLIP_V ? -1.0f : 0.0f) * mDisplayFrame.bottom, 0.0f, 1.0f));
+
+    const mat4 scale = mat4::scale(vec4(mTransform & Transform::FLIP_H ? -1.0f : 1.0f,
+                                        mTransform & Transform::FLIP_V ? -1.0f : 1.0f, 1.0f, 1.0f));
+
+    layerSettings.geometry.positionTransform = translation * scale;
+
+    return layerSettings;
+}
+
+int32_t ReadbackHelper::GetBytesPerPixel(PixelFormat pixelFormat) {
+    switch (pixelFormat) {
+        case PixelFormat::RGBA_8888:
+            return 4;
+        case PixelFormat::RGB_888:
+            return 3;
+        default:
+            return -1;
+    }
+}
+
+void ReadbackHelper::fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData,
+                                PixelFormat pixelFormat,
+                                std::vector<IComposerClient::Color> desiredPixelColors) {
+    ASSERT_TRUE(pixelFormat == PixelFormat::RGB_888 || pixelFormat == PixelFormat::RGBA_8888);
+    int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat);
+    ASSERT_NE(-1, bytesPerPixel);
+    for (int row = 0; row < height; row++) {
+        for (int col = 0; col < width; col++) {
+            int pixel = row * width + col;
+            IComposerClient::Color srcColor = desiredPixelColors[pixel];
+
+            int offset = (row * stride + col) * bytesPerPixel;
+            uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+            pixelColor[0] = srcColor.r;
+            pixelColor[1] = srcColor.g;
+            pixelColor[2] = srcColor.b;
+
+            if (bytesPerPixel == 4) {
+                pixelColor[3] = srcColor.a;
+            }
+        }
+    }
+}
+
+void ReadbackHelper::clearColors(std::vector<IComposerClient::Color>& expectedColors, int32_t width,
+                                 int32_t height, int32_t displayWidth) {
+    for (int row = 0; row < height; row++) {
+        for (int col = 0; col < width; col++) {
+            int pixel = row * displayWidth + col;
+            expectedColors[pixel] = BLACK;
+        }
+    }
+}
+
+void ReadbackHelper::fillColorsArea(std::vector<IComposerClient::Color>& expectedColors,
+                                    int32_t stride, IComposerClient::Rect area,
+                                    IComposerClient::Color color) {
+    for (int row = area.top; row < area.bottom; row++) {
+        for (int col = area.left; col < area.right; col++) {
+            int pixel = row * stride + col;
+            expectedColors[pixel] = color;
+        }
+    }
+}
+
+bool ReadbackHelper::readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace,
+                                       const Error error) {
+    if (error != Error::NONE) {
+        return false;
+    }
+    // TODO: add support for RGBA_1010102
+    if (pixelFormat != PixelFormat::RGB_888 && pixelFormat != PixelFormat::RGBA_8888) {
+        return false;
+    }
+    if (std::find(dataspaces.begin(), dataspaces.end(), dataspace) == dataspaces.end()) {
+        return false;
+    }
+    return true;
+}
+
+void ReadbackHelper::compareColorBuffers(std::vector<IComposerClient::Color>& expectedColors,
+                                         void* bufferData, const uint32_t stride,
+                                         const uint32_t width, const uint32_t height,
+                                         const PixelFormat pixelFormat) {
+    const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat);
+    ASSERT_NE(-1, bytesPerPixel);
+    for (int row = 0; row < height; row++) {
+        for (int col = 0; col < width; col++) {
+            int pixel = row * width + col;
+            int offset = (row * stride + col) * bytesPerPixel;
+            uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+
+            ASSERT_EQ(expectedColors[pixel].r, pixelColor[0]);
+            ASSERT_EQ(expectedColors[pixel].g, pixelColor[1]);
+            ASSERT_EQ(expectedColors[pixel].b, pixelColor[2]);
+        }
+    }
+}
+
+ReadbackBuffer::ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
+                               const std::shared_ptr<Gralloc>& gralloc, uint32_t width,
+                               uint32_t height, PixelFormat pixelFormat, Dataspace dataspace) {
+    mDisplay = display;
+
+    mComposerClient = client;
+    mGralloc = gralloc;
+
+    mPixelFormat = pixelFormat;
+    mDataspace = dataspace;
+
+    mWidth = width;
+    mHeight = height;
+    mLayerCount = 1;
+    mFormat = mPixelFormat;
+    mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
+
+    mAccessRegion.top = 0;
+    mAccessRegion.left = 0;
+    mAccessRegion.width = width;
+    mAccessRegion.height = height;
+}
+
+ReadbackBuffer::~ReadbackBuffer() {
+    if (mBufferHandle != nullptr) {
+        mGralloc->freeBuffer(mBufferHandle);
+    }
+}
+
+void ReadbackBuffer::setReadbackBuffer() {
+    if (mBufferHandle != nullptr) {
+        mGralloc->freeBuffer(mBufferHandle);
+        mBufferHandle = nullptr;
+    }
+    mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
+                                       /*import*/ true, &mStride);
+    ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount,
+                                                  mFormat, mUsage, mStride));
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1));
+}
+
+void ReadbackBuffer::checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors) {
+    // lock buffer for reading
+    int32_t fenceHandle;
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
+
+    void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, fenceHandle);
+    ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
+    ReadbackHelper::compareColorBuffers(expectedColors, bufData, mStride, mWidth, mHeight,
+                                        mPixelFormat);
+    int32_t unlockFence = mGralloc->unlock(mBufferHandle);
+    if (unlockFence != -1) {
+        sync_wait(unlockFence, -1);
+        close(unlockFence);
+    }
+}
+
+void TestColorLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
+    TestLayer::write(writer);
+    writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
+    writer->setLayerColor(mColor);
+}
+
+LayerSettings TestColorLayer::toRenderEngineLayerSettings() {
+    LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
+
+    layerSettings.source.solidColor =
+            half3(static_cast<half>(mColor.r) / 255.0, static_cast<half>(mColor.g) / 255.0,
+                  static_cast<half>(mColor.b) / 255.0);
+    layerSettings.alpha = mAlpha * (static_cast<half>(mColor.a) / 255.0);
+    return layerSettings;
+}
+
+TestBufferLayer::TestBufferLayer(const std::shared_ptr<ComposerClient>& client,
+                                 const std::shared_ptr<Gralloc>& gralloc, Display display,
+                                 int32_t width, int32_t height, PixelFormat format,
+                                 IComposerClient::Composition composition)
+    : TestLayer{client, display} {
+    mGralloc = gralloc;
+    mComposition = composition;
+    mWidth = width;
+    mHeight = height;
+    mLayerCount = 1;
+    mFormat = format;
+    mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                   BufferUsage::COMPOSER_OVERLAY);
+
+    mAccessRegion.top = 0;
+    mAccessRegion.left = 0;
+    mAccessRegion.width = width;
+    mAccessRegion.height = height;
+
+    setSourceCrop({0, 0, (float)width, (float)height});
+}
+
+TestBufferLayer::~TestBufferLayer() {
+    if (mBufferHandle != nullptr) {
+        mGralloc->freeBuffer(mBufferHandle);
+    }
+}
+
+void TestBufferLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
+    TestLayer::write(writer);
+    writer->setLayerCompositionType(mComposition);
+    writer->setLayerDataspace(Dataspace::UNKNOWN);
+    writer->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, mDisplayFrame));
+    if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle, mFillFence);
+}
+
+LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
+    LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
+    layerSettings.source.buffer.buffer =
+            new GraphicBuffer(mBufferHandle, GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
+                              static_cast<int32_t>(mFormat), 1, mUsage, mStride);
+    // TODO(b/136483187): Why does this break the premultiply test
+    // layerSettings.source.buffer.usePremultipliedAlpha =
+    //      mBlendMode == IComposerClient::BlendMode::PREMULTIPLIED;
+
+    const float scaleX = (mSourceCrop.right - mSourceCrop.left) / (mWidth);
+    const float scaleY = (mSourceCrop.bottom - mSourceCrop.top) / (mHeight);
+    const float translateX = mSourceCrop.left / (mWidth);
+    const float translateY = mSourceCrop.top / (mHeight);
+
+    layerSettings.source.buffer.textureTransform =
+            mat4::translate(vec4(translateX, translateY, 0, 1)) *
+            mat4::scale(vec4(scaleX, scaleY, 1.0, 1.0));
+
+    return layerSettings;
+}
+
+void TestBufferLayer::fillBuffer(std::vector<IComposerClient::Color> expectedColors) {
+    void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, -1);
+    ASSERT_NO_FATAL_FAILURE(
+            ReadbackHelper::fillBuffer(mWidth, mHeight, mStride, bufData, mFormat, expectedColors));
+    mFillFence = mGralloc->unlock(mBufferHandle);
+    if (mFillFence != -1) {
+        sync_wait(mFillFence, -1);
+        close(mFillFence);
+    }
+}
+
+void TestBufferLayer::setBuffer(std::vector<IComposerClient::Color> colors) {
+    if (mBufferHandle != nullptr) {
+        mGralloc->freeBuffer(mBufferHandle);
+        mBufferHandle = nullptr;
+    }
+    mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
+                                       /*import*/ true, &mStride);
+    ASSERT_NE(nullptr, mBufferHandle);
+    ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
+    ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount,
+                                                  mFormat, mUsage, mStride));
+}
+
+void TestBufferLayer::setToClientComposition(const std::shared_ptr<CommandWriterBase>& writer) {
+    writer->selectLayer(mLayer);
+    writer->setLayerCompositionType(IComposerClient::Composition::CLIENT);
+}
+
+}  // namespace vts
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
new file mode 100644
index 0000000..d910169
--- /dev/null
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2019 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 <composer-vts/2.2/RenderEngineVts.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace vts {
+
+using mapper::V2_1::IMapper;
+using renderengine::DisplaySettings;
+using renderengine::LayerSettings;
+
+TestRenderEngine::TestRenderEngine(common::V1_1::PixelFormat hwcFormat,
+                                   uint32_t renderEngineFeatures) {
+    mFormat = hwcFormat;
+    mRenderEngine = renderengine::RenderEngine::create(
+            static_cast<int32_t>(mFormat), renderEngineFeatures, mMaxFrameBufferAcquireBuffers);
+}
+
+void TestRenderEngine::setRenderLayers(std::vector<std::shared_ptr<TestLayer>> layers) {
+    sort(layers.begin(), layers.end(),
+         [](const std::shared_ptr<TestLayer>& lhs, const std::shared_ptr<TestLayer>& rhs) -> bool {
+             return lhs->mZOrder < rhs->mZOrder;
+         });
+
+    if (!mCompositionLayers.empty()) {
+        mCompositionLayers.clear();
+    }
+    for (auto& layer : layers) {
+        LayerSettings settings = layer->toRenderEngineLayerSettings();
+        mCompositionLayers.push_back(settings);
+    }
+}
+
+void TestRenderEngine::initGraphicBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
+                                         uint64_t usage) {
+    mGraphicBuffer =
+            new GraphicBuffer(width, height, static_cast<int32_t>(mFormat), layerCount, usage);
+}
+
+void TestRenderEngine::drawLayers() {
+    base::unique_fd bufferFence;
+    base::unique_fd readyFence;
+    mRenderEngine->drawLayers(mDisplaySettings, mCompositionLayers,
+                              mGraphicBuffer->getNativeBuffer(), true, std::move(bufferFence),
+                              &readyFence);
+    int fd = readyFence.release();
+    if (fd != -1) {
+        ASSERT_EQ(0, sync_wait(fd, -1));
+        ASSERT_EQ(0, close(fd));
+    }
+}
+
+void TestRenderEngine::checkColorBuffer(std::vector<V2_2::IComposerClient::Color>& expectedColors) {
+    void* bufferData;
+    ASSERT_EQ(0, mGraphicBuffer->lock(mGraphicBuffer->getUsage(), &bufferData));
+    ReadbackHelper::compareColorBuffers(expectedColors, bufferData, mGraphicBuffer->getStride(),
+                                        mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(),
+                                        mFormat);
+    ASSERT_EQ(0, mGraphicBuffer->unlock());
+}
+
+}  // namespace vts
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
new file mode 100644
index 0000000..5304cd4
--- /dev/null
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.h>
+#include <composer-vts/2.2/ComposerVts.h>
+#include <mapper-vts/2.1/MapperVts.h>
+#include <renderengine/RenderEngine.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace vts {
+
+using android::hardware::hidl_handle;
+using common::V1_1::BufferUsage;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using IMapper2_1 = mapper::V2_1::IMapper;
+using Gralloc2_1 = mapper::V2_1::vts::Gralloc;
+using renderengine::LayerSettings;
+using V2_1::Display;
+using V2_1::Layer;
+using V2_1::vts::AccessRegion;
+using V2_1::vts::TestCommandReader;
+
+static const IComposerClient::Color BLACK = {0, 0, 0, 0xff};
+static const IComposerClient::Color RED = {0xff, 0, 0, 0xff};
+static const IComposerClient::Color TRANSLUCENT_RED = {0xff, 0, 0, 0x33};
+static const IComposerClient::Color GREEN = {0, 0xff, 0, 0xff};
+static const IComposerClient::Color BLUE = {0, 0, 0xff, 0xff};
+
+class TestLayer {
+  public:
+    TestLayer(const std::shared_ptr<ComposerClient>& client, Display display)
+        : mLayer(client->createLayer(display, kBufferSlotCount)), mComposerClient(client) {}
+
+    // ComposerClient will take care of destroying layers, no need to explicitly
+    // call destroyLayers here
+    virtual ~TestLayer(){};
+
+    virtual void write(const std::shared_ptr<CommandWriterBase>& writer);
+    virtual LayerSettings toRenderEngineLayerSettings();
+
+    void setDisplayFrame(IComposerClient::Rect frame) { mDisplayFrame = frame; }
+    void setSourceCrop(IComposerClient::FRect crop) { mSourceCrop = crop; }
+    void setZOrder(uint32_t z) { mZOrder = z; }
+
+    void setSurfaceDamage(std::vector<IComposerClient::Rect> surfaceDamage) {
+        mSurfaceDamage = surfaceDamage;
+    }
+
+    void setTransform(Transform transform) { mTransform = transform; }
+    void setAlpha(float alpha) { mAlpha = alpha; }
+    void setBlendMode(IComposerClient::BlendMode blendMode) { mBlendMode = blendMode; }
+
+    static constexpr uint32_t kBufferSlotCount = 64;
+
+    IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0};
+    uint32_t mZOrder = 0;
+    std::vector<IComposerClient::Rect> mSurfaceDamage;
+    Transform mTransform = static_cast<Transform>(0);
+    IComposerClient::FRect mSourceCrop = {0, 0, 0, 0};
+    float mAlpha = 1.0;
+    IComposerClient::BlendMode mBlendMode = IComposerClient::BlendMode::NONE;
+
+  protected:
+    Layer mLayer;
+
+  private:
+    std::shared_ptr<ComposerClient> const mComposerClient;
+};
+
+class TestColorLayer : public TestLayer {
+  public:
+    TestColorLayer(const std::shared_ptr<ComposerClient>& client, Display display)
+        : TestLayer{client, display} {}
+
+    void write(const std::shared_ptr<CommandWriterBase>& writer) override;
+
+    LayerSettings toRenderEngineLayerSettings() override;
+
+    void setColor(IComposerClient::Color color) { mColor = color; }
+
+  private:
+    IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff};
+};
+
+class TestBufferLayer : public TestLayer {
+  public:
+    TestBufferLayer(
+            const std::shared_ptr<ComposerClient>& client, const std::shared_ptr<Gralloc>& gralloc,
+            Display display, int32_t width, int32_t height, PixelFormat format,
+            IComposerClient::Composition composition = IComposerClient::Composition::DEVICE);
+
+    ~TestBufferLayer();
+
+    void write(const std::shared_ptr<CommandWriterBase>& writer) override;
+
+    LayerSettings toRenderEngineLayerSettings() override;
+
+    void fillBuffer(std::vector<IComposerClient::Color> expectedColors);
+
+    void setBuffer(std::vector<IComposerClient::Color> colors);
+
+    void setToClientComposition(const std::shared_ptr<CommandWriterBase>& writer);
+
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mLayerCount;
+    PixelFormat mFormat;
+    uint64_t mUsage;
+    AccessRegion mAccessRegion;
+    uint32_t mStride;
+
+  protected:
+    IComposerClient::Composition mComposition;
+    std::shared_ptr<Gralloc> mGralloc;
+    int32_t mFillFence;
+    const native_handle_t* mBufferHandle = nullptr;
+};
+
+class ReadbackHelper : public ::testing::VtsHalHidlTargetTestBase {
+  public:
+    static std::string getColorModeString(ColorMode mode);
+
+    static std::string getDataspaceString(Dataspace dataspace);
+
+    static int32_t GetBytesPerPixel(PixelFormat pixelFormat);
+
+    static void fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData,
+                           PixelFormat pixelFormat,
+                           std::vector<IComposerClient::Color> desiredPixelColors);
+
+    static void clearColors(std::vector<IComposerClient::Color>& expectedColors, int32_t width,
+                            int32_t height, int32_t displayWidth);
+
+    static void fillColorsArea(std::vector<IComposerClient::Color>& expectedColors, int32_t stride,
+                               IComposerClient::Rect area, IComposerClient::Color color);
+
+    static bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace,
+                                  const Error error);
+
+    static const std::vector<ColorMode> colorModes;
+    static const std::vector<Dataspace> dataspaces;
+
+    static void compareColorBuffers(std::vector<IComposerClient::Color>& expectedColors,
+                                    void* bufferData, const uint32_t stride, const uint32_t width,
+                                    const uint32_t height, const PixelFormat pixelFormat);
+};
+
+class ReadbackBuffer {
+  public:
+    ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
+                   const std::shared_ptr<Gralloc>& gralloc, uint32_t width, uint32_t height,
+                   PixelFormat pixelFormat, Dataspace dataspace);
+    ~ReadbackBuffer();
+
+    void setReadbackBuffer();
+
+    void checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors);
+
+  protected:
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mLayerCount;
+    PixelFormat mFormat;
+    uint64_t mUsage;
+    AccessRegion mAccessRegion;
+    uint32_t mStride;
+    const native_handle_t* mBufferHandle = nullptr;
+    PixelFormat mPixelFormat;
+    Dataspace mDataspace;
+    Display mDisplay;
+    std::shared_ptr<Gralloc> mGralloc;
+    std::shared_ptr<ComposerClient> mComposerClient;
+};
+
+}  // namespace vts
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
new file mode 100644
index 0000000..0ac5a22
--- /dev/null
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019 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 <composer-vts/2.2/ReadbackVts.h>
+#include <math/half.h>
+#include <math/vec3.h>
+#include <renderengine/RenderEngine.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace vts {
+
+using mapper::V2_1::IMapper;
+using renderengine::DisplaySettings;
+using vts::Gralloc;
+
+class TestRenderEngine {
+  public:
+    TestRenderEngine(common::V1_1::PixelFormat hwcFormat, uint32_t renderEngineFeatures);
+    ~TestRenderEngine() = default;
+
+    void setRenderLayers(std::vector<std::shared_ptr<TestLayer>> layers);
+    void initGraphicBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint64_t usage);
+    void setDisplaySettings(DisplaySettings& displaySettings) {
+        mDisplaySettings = displaySettings;
+    };
+    void drawLayers();
+    void checkColorBuffer(std::vector<V2_2::IComposerClient::Color>& expectedColors);
+
+  private:
+    static constexpr uint32_t mMaxFrameBufferAcquireBuffers = 2;
+    common::V1_1::PixelFormat mFormat;
+    std::vector<renderengine::LayerSettings> mCompositionLayers;
+    std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
+    std::vector<renderengine::LayerSettings> mRenderLayers;
+    sp<GraphicBuffer> mGraphicBuffer;
+    DisplaySettings mDisplaySettings;
+};
+
+}  // namespace vts
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 9f7e1cd..cc24774 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -20,6 +20,7 @@
     srcs: [
         "VtsHalGraphicsComposerV2_2ReadbackTest.cpp",
         "VtsHalGraphicsComposerV2_2TargetTest.cpp",
+        "VtsHalGraphicsComposerV2_2CompositionComparisonTest.cpp",
     ],
 
     // TODO(b/64437680): Assume these libs are always available on the device.
@@ -27,9 +28,19 @@
         "libfmq",
         "libhidlbase",
         "libhidltransport",
+        "libhwbinder",
         "libsync",
+        "libui",
+        "libgui",
+        "libEGL",
+        "libGLESv1_CM",
+        "libGLESv2",
     ],
     static_libs: [
+        "librenderengine",
+        "libmath",
+        "libarect",
+        "libnativewindow",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.1",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2CompositionComparisonTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2CompositionComparisonTest.cpp
new file mode 100644
index 0000000..d694a5b
--- /dev/null
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2CompositionComparisonTest.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2019 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_composer_hidl_hal_readback_tests@2.2"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.h>
+#include <composer-vts/2.2/ComposerVts.h>
+#include <composer-vts/2.2/ReadbackVts.h>
+#include <composer-vts/2.2/RenderEngineVts.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace vts {
+namespace {
+
+using android::GraphicBuffer;
+using android::Rect;
+using android::hardware::hidl_handle;
+using common::V1_1::BufferUsage;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using mapper::V2_1::IMapper;
+using V2_1::Config;
+using V2_1::Display;
+using V2_1::vts::TestCommandReader;
+using vts::Gralloc;
+
+// Test environment for graphics.composer
+class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+  public:
+    // get the test environment singleton
+    static GraphicsComposerHidlEnvironment* Instance() {
+        static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment;
+        return instance;
+    }
+    virtual void registerTestServices() override { registerTestService<IComposer>(); }
+
+  private:
+    GraphicsComposerHidlEnvironment() {}
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment);
+};
+
+class GraphicsCompositionComparisonTest : public ::testing::VtsHalHidlTargetTestBase {
+  protected:
+    using PowerMode = V2_1::IComposerClient::PowerMode;
+    void SetUp() override {
+        VtsHalHidlTargetTestBase::SetUp();
+        ASSERT_NO_FATAL_FAILURE(
+                mComposer = std::make_unique<Composer>(
+                        GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+        ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
+        mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
+        mComposerClient->registerCallback(mComposerCallback);
+
+        // assume the first display is primary and is never removed
+        mPrimaryDisplay = waitForFirstDisplay();
+        Config activeConfig;
+        ASSERT_NO_FATAL_FAILURE(activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay));
+        ASSERT_NO_FATAL_FAILURE(
+                mDisplayWidth = mComposerClient->getDisplayAttribute(
+                        mPrimaryDisplay, activeConfig, IComposerClient::Attribute::WIDTH));
+        ASSERT_NO_FATAL_FAILURE(
+                mDisplayHeight = mComposerClient->getDisplayAttribute(
+                        mPrimaryDisplay, activeConfig, IComposerClient::Attribute::HEIGHT));
+
+        setTestColorModes();
+
+        // explicitly disable vsync
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, false));
+        mComposerCallback->setVsyncAllowed(false);
+
+        // set up command writer/reader and gralloc
+        mWriter = std::make_shared<CommandWriterBase>(1024);
+        mReader = std::make_unique<TestCommandReader>();
+        mGralloc = std::make_shared<Gralloc>();
+
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON));
+
+        ASSERT_NO_FATAL_FAILURE(
+                mTestRenderEngine = std::unique_ptr<TestRenderEngine>(new TestRenderEngine(
+                        PixelFormat::RGBA_8888,
+                        renderengine::RenderEngine::USE_COLOR_MANAGEMENT |
+                                renderengine::RenderEngine::USE_HIGH_PRIORITY_CONTEXT)));
+
+        renderengine::DisplaySettings clientCompositionDisplay;
+        clientCompositionDisplay.physicalDisplay = Rect(mDisplayWidth, mDisplayHeight);
+        clientCompositionDisplay.clip = clientCompositionDisplay.physicalDisplay;
+        clientCompositionDisplay.clearRegion = Region(clientCompositionDisplay.physicalDisplay);
+
+        mTestRenderEngine->initGraphicBuffer(
+                static_cast<uint32_t>(mDisplayWidth), static_cast<uint32_t>(mDisplayHeight), 1,
+                static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN));
+        mTestRenderEngine->setDisplaySettings(clientCompositionDisplay);
+    }
+
+    void TearDown() override {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF));
+        EXPECT_EQ(0, mReader->mErrors.size());
+        EXPECT_EQ(0, mReader->mCompositionChanges.size());
+        if (mComposerCallback != nullptr) {
+            EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+        }
+        VtsHalHidlTargetTestBase::TearDown();
+    }
+
+    void clearCommandReaderState() {
+        mReader->mCompositionChanges.clear();
+        mReader->mErrors.clear();
+    }
+
+    void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) {
+        for (auto layer : layers) {
+            layer->write(mWriter);
+        }
+        execute();
+    }
+
+    void execute() {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->execute(mReader.get(), mWriter.get()));
+    }
+
+    std::unique_ptr<Composer> mComposer;
+    std::shared_ptr<ComposerClient> mComposerClient;
+
+    sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
+    // the first display and is assumed never to be removed
+    Display mPrimaryDisplay;
+    int32_t mDisplayWidth;
+    int32_t mDisplayHeight;
+    std::vector<ColorMode> mTestColorModes;
+    std::shared_ptr<CommandWriterBase> mWriter;
+    std::unique_ptr<TestCommandReader> mReader;
+    std::shared_ptr<Gralloc> mGralloc;
+    std::unique_ptr<TestRenderEngine> mTestRenderEngine;
+
+    bool mHasReadbackBuffer;
+    PixelFormat mPixelFormat;
+    Dataspace mDataspace;
+
+  private:
+    Display waitForFirstDisplay() {
+        while (true) {
+            std::vector<Display> displays = mComposerCallback->getDisplays();
+            if (displays.empty()) {
+                usleep(5 * 1000);
+                continue;
+            }
+            return displays[0];
+        }
+    }
+
+    void setTestColorModes() {
+        mTestColorModes.clear();
+        mComposerClient->getRaw()->getColorModes_2_2(mPrimaryDisplay, [&](const auto& tmpError,
+                                                                          const auto& tmpModes) {
+            ASSERT_EQ(Error::NONE, tmpError);
+            for (ColorMode mode : tmpModes) {
+                if (std::find(ReadbackHelper::colorModes.begin(), ReadbackHelper::colorModes.end(),
+                              mode) != ReadbackHelper::colorModes.end()) {
+                    mTestColorModes.push_back(mode);
+                }
+            }
+        });
+    }
+};
+
+TEST_F(GraphicsCompositionComparisonTest, SingleSolidColorLayer) {
+    for (ColorMode mode : mTestColorModes) {
+        std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
+                  << std::endl;
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+                mPrimaryDisplay,
+                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
+                                                                           tmpDataspace, tmpError);
+                    mPixelFormat = tmpPixelFormat;
+                    mDataspace = tmpDataspace;
+                });
+
+        if (!mHasReadbackBuffer) {
+            std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setColor(BLUE);
+        layer->setDisplayFrame(coloredSquare);
+        layer->setZOrder(10);
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        // expected color for each pixel
+        std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->validateDisplay();
+        execute();
+        // if hwc cannot handle and asks for composition change,
+        // just succeed the test
+        if (mReader->mCompositionChanges.size() != 0) {
+            clearCommandReaderState();
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(layers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+}  // namespace
+}  // namespace vts
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index 0648b34..72c9496 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018 The Android Open Source Project
+ * Copyright 2019 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.
@@ -18,13 +18,10 @@
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
-#include <android-base/unique_fd.h>
-#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
-#include <composer-vts/2.2/ComposerVts.h>
-#include <mapper-vts/2.1/MapperVts.h>
+#include <composer-vts/2.2/ReadbackVts.h>
 
 namespace android {
 namespace hardware {
@@ -41,15 +38,8 @@
 using mapper::V2_1::IMapper;
 using V2_1::Display;
 using V2_1::Layer;
-using V2_1::vts::AccessRegion;
 using V2_1::vts::TestCommandReader;
 
-static const IComposerClient::Color BLACK = {0, 0, 0, 0xff};
-static const IComposerClient::Color RED = {0xff, 0, 0, 0xff};
-static const IComposerClient::Color TRANSLUCENT_RED = {0xff, 0, 0, 0x33};
-static const IComposerClient::Color GREEN = {0, 0xff, 0, 0xff};
-static const IComposerClient::Color BLUE = {0, 0, 0xff, 0xff};
-
 // Test environment for graphics.composer
 class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
    public:
@@ -65,92 +55,7 @@
     GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment);
 };
 
-class TestLayer {
-   public:
-    TestLayer(const std::shared_ptr<ComposerClient>& client, Display display)
-        : mLayer(client->createLayer(display, kBufferSlotCount)), mComposerClient(client) {}
-
-    // ComposerClient will take care of destroying layers, no need to explicitly
-    // call destroyLayers here
-    virtual ~TestLayer(){};
-
-    virtual void write(const std::shared_ptr<CommandWriterBase>& writer) {
-        writer->selectLayer(mLayer);
-        writer->setLayerDisplayFrame(mDisplayFrame);
-        writer->setLayerSourceCrop(mSourceCrop);
-        writer->setLayerZOrder(mZOrder);
-        writer->setLayerSurfaceDamage(mSurfaceDamage);
-        writer->setLayerTransform(mTransform);
-        writer->setLayerPlaneAlpha(mAlpha);
-        writer->setLayerBlendMode(mBlendMode);
-    }
-
-    void setDisplayFrame(IComposerClient::Rect frame) { mDisplayFrame = frame; }
-    void setSourceCrop(IComposerClient::FRect crop) { mSourceCrop = crop; }
-    void setZOrder(uint32_t z) { mZOrder = z; }
-
-    void setSurfaceDamage(std::vector<IComposerClient::Rect> surfaceDamage) {
-        mSurfaceDamage = surfaceDamage;
-    }
-
-    void setTransform(Transform transform) { mTransform = transform; }
-    void setAlpha(float alpha) { mAlpha = alpha; }
-    void setBlendMode(IComposerClient::BlendMode blendMode) { mBlendMode = blendMode; }
-
-    static constexpr uint32_t kBufferSlotCount = 64;
-
-    IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0};
-    uint32_t mZOrder = 0;
-    std::vector<IComposerClient::Rect> mSurfaceDamage;
-    Transform mTransform = static_cast<Transform>(0);
-    IComposerClient::FRect mSourceCrop = {0, 0, 0, 0};
-    float mAlpha = 1.0;
-    IComposerClient::BlendMode mBlendMode = IComposerClient::BlendMode::NONE;
-
-   protected:
-    Layer mLayer;
-
-   private:
-    std::shared_ptr<ComposerClient> const mComposerClient;
-};
-
 class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase {
-   public:
-    static int32_t GetBytesPerPixel(PixelFormat pixelFormat) {
-        switch (pixelFormat) {
-            case PixelFormat::RGBA_8888:
-                return 4;
-            case PixelFormat::RGB_888:
-                return 3;
-            default:
-                return -1;
-        }
-    }
-
-    static void fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData,
-                           PixelFormat pixelFormat,
-                           std::vector<IComposerClient::Color> desiredPixelColors) {
-        ASSERT_TRUE(pixelFormat == PixelFormat::RGB_888 || pixelFormat == PixelFormat::RGBA_8888);
-        int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat);
-        ASSERT_NE(-1, bytesPerPixel);
-        for (int row = 0; row < height; row++) {
-            for (int col = 0; col < width; col++) {
-                int pixel = row * width + col;
-                IComposerClient::Color srcColor = desiredPixelColors[pixel];
-
-                int offset = (row * stride + col) * bytesPerPixel;
-                uint8_t* pixelColor = (uint8_t*)bufferData + offset;
-                pixelColor[0] = srcColor.r;
-                pixelColor[1] = srcColor.g;
-                pixelColor[2] = srcColor.b;
-
-                if (bytesPerPixel == 4) {
-                    pixelColor[3] = srcColor.a;
-                }
-            }
-        }
-    }
-
    protected:
     using PowerMode = V2_1::IComposerClient::PowerMode;
     void SetUp() override {
@@ -173,6 +78,8 @@
             mDisplayHeight = mComposerClient->getDisplayAttribute(
                 mPrimaryDisplay, activeConfig, IComposerClient::Attribute::HEIGHT));
 
+        setTestColorModes();
+
         // explicitly disable vsync
         ASSERT_NO_FATAL_FAILURE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, false));
         mComposerCallback->setVsyncAllowed(false);
@@ -182,13 +89,6 @@
         mReader = std::make_unique<TestCommandReader>();
         mGralloc = std::make_shared<Gralloc>();
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-            mPrimaryDisplay,
-            [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                mHasReadbackBuffer = readbackSupported(tmpPixelFormat, tmpDataspace, tmpError);
-                mPixelFormat = tmpPixelFormat;
-                mDataspace = tmpDataspace;
-            });
         ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON));
     }
 
@@ -209,10 +109,6 @@
         mReader->mErrors.clear();
     }
 
-    void execute() {
-        ASSERT_NO_FATAL_FAILURE(mComposerClient->execute(mReader.get(), mWriter.get()));
-    }
-
     void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) {
         for (auto layer : layers) {
             layer->write(mWriter);
@@ -220,42 +116,10 @@
         execute();
     }
 
-    void clearColors(std::vector<IComposerClient::Color>& expectedColors, int32_t width,
-                     int32_t height) {
-        for (int row = 0; row < height; row++) {
-            for (int col = 0; col < width; col++) {
-                int pixel = row * mDisplayWidth + col;
-                expectedColors[pixel] = BLACK;
-            }
-        }
+    void execute() {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->execute(mReader.get(), mWriter.get()));
     }
 
-    void fillColorsArea(std::vector<IComposerClient::Color>& expectedColors, int32_t stride,
-                        IComposerClient::Rect area, IComposerClient::Color color) {
-        for (int row = area.top; row < area.bottom; row++) {
-            for (int col = area.left; col < area.right; col++) {
-                int pixel = row * stride + col;
-                expectedColors[pixel] = color;
-            }
-        }
-    }
-
-    bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace,
-                           const Error error) {
-        if (error != Error::NONE) {
-            return false;
-        }
-        // TODO: add support for RGBA_1010102
-        if (pixelFormat != PixelFormat::RGB_888 && pixelFormat != PixelFormat::RGBA_8888) {
-            return false;
-        }
-        if (dataspace != Dataspace::V0_SRGB) {
-            return false;
-        }
-        return true;
-    }
-
-
     std::unique_ptr<Composer> mComposer;
     std::shared_ptr<ComposerClient> mComposerClient;
 
@@ -264,6 +128,7 @@
     Display mPrimaryDisplay;
     int32_t mDisplayWidth;
     int32_t mDisplayHeight;
+    std::vector<ColorMode> mTestColorModes;
     std::shared_ptr<CommandWriterBase> mWriter;
     std::unique_ptr<TestCommandReader> mReader;
     std::shared_ptr<Gralloc> mGralloc;
@@ -285,368 +150,373 @@
             return displays[0];
         }
     }
-};
-class ReadbackBuffer {
-   public:
-    ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
-                   const std::shared_ptr<Gralloc>& gralloc, uint32_t width, uint32_t height,
-                   PixelFormat pixelFormat, Dataspace dataspace) {
-        mDisplay = display;
 
-        mComposerClient = client;
-        mGralloc = gralloc;
-
-        mFormat = pixelFormat;
-        mDataspace = dataspace;
-
-        mWidth = width;
-        mHeight = height;
-        mLayerCount = 1;
-        mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
-
-        mAccessRegion.top = 0;
-        mAccessRegion.left = 0;
-        mAccessRegion.width = width;
-        mAccessRegion.height = height;
-    };
-
-    ~ReadbackBuffer() {
-        if (mBufferHandle != nullptr) {
-            mGralloc->freeBuffer(mBufferHandle);
-        }
-    }
-
-    void setReadbackBuffer() {
-        if (mBufferHandle != nullptr) {
-            mGralloc->freeBuffer(mBufferHandle);
-            mBufferHandle = nullptr;
-        }
-        mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
-                                           /*import*/ true, &mStride);
-        ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount,
-                                                      mFormat, mUsage, mStride));
-        ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1));
-    }
-
-    void checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors) {
-        // lock buffer for reading
-        int32_t fenceHandle;
-        ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
-
-        void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, fenceHandle);
-        ASSERT_TRUE(mFormat == PixelFormat::RGB_888 || mFormat == PixelFormat::RGBA_8888);
-        int32_t bytesPerPixel = GraphicsComposerReadbackTest::GetBytesPerPixel(mFormat);
-        ASSERT_NE(-1, bytesPerPixel);
-        for (int row = 0; row < mHeight; row++) {
-            for (int col = 0; col < mWidth; col++) {
-                int pixel = row * mWidth + col;
-                int offset = (row * mStride + col) * bytesPerPixel;
-                uint8_t* pixelColor = (uint8_t*)bufData + offset;
-
-                ASSERT_EQ(expectedColors[pixel].r, pixelColor[0]);
-                ASSERT_EQ(expectedColors[pixel].g, pixelColor[1]);
-                ASSERT_EQ(expectedColors[pixel].b, pixelColor[2]);
+    void setTestColorModes() {
+        mTestColorModes.clear();
+        mComposerClient->getRaw()->getColorModes_2_2(mPrimaryDisplay, [&](const auto& tmpError,
+                                                                          const auto& tmpModes) {
+            ASSERT_EQ(Error::NONE, tmpError);
+            for (ColorMode mode : tmpModes) {
+                if (std::find(ReadbackHelper::colorModes.begin(), ReadbackHelper::colorModes.end(),
+                              mode) != ReadbackHelper::colorModes.end()) {
+                    mTestColorModes.push_back(mode);
+                }
             }
-        }
-        int32_t unlockFence = mGralloc->unlock(mBufferHandle);
-        if (unlockFence != -1) {
-            sync_wait(unlockFence, -1);
-            close(unlockFence);
-        }
+        });
     }
-
-    uint32_t mWidth;
-    uint32_t mHeight;
-    uint32_t mLayerCount;
-    PixelFormat mFormat;
-    uint64_t mUsage;
-    AccessRegion mAccessRegion;
-
-  protected:
-    uint32_t mStride;
-    const native_handle_t* mBufferHandle = nullptr;
-    Dataspace mDataspace;
-    Display mDisplay;
-    std::shared_ptr<Gralloc> mGralloc;
-    std::shared_ptr<ComposerClient> mComposerClient;
-};
-
-class TestColorLayer : public TestLayer {
-   public:
-    TestColorLayer(const std::shared_ptr<ComposerClient>& client, Display display)
-        : TestLayer{client, display} {}
-
-    void write(const std::shared_ptr<CommandWriterBase>& writer) override {
-        TestLayer::write(writer);
-        writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
-        writer->setLayerColor(mColor);
-    }
-
-    void setColor(IComposerClient::Color color) { mColor = color; }
-
-   private:
-    IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff};
-};
-
-class TestBufferLayer : public TestLayer {
-   public:
-    TestBufferLayer(const std::shared_ptr<ComposerClient>& client,
-                    const std::shared_ptr<Gralloc>& gralloc, Display display, int32_t width,
-                    int32_t height, PixelFormat format,
-                    IComposerClient::Composition composition = IComposerClient::Composition::DEVICE)
-        : TestLayer{client, display} {
-        mGralloc = gralloc;
-        mComposition = composition;
-        mWidth = width;
-        mHeight = height;
-        mLayerCount = 1;
-        mFormat = format;
-        mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                       BufferUsage::COMPOSER_OVERLAY);
-
-        mAccessRegion.top = 0;
-        mAccessRegion.left = 0;
-        mAccessRegion.width = width;
-        mAccessRegion.height = height;
-
-        setSourceCrop({0, 0, (float)width, (float)height});
-    }
-
-    ~TestBufferLayer() {
-        if (mBufferHandle != nullptr) {
-            mGralloc->freeBuffer(mBufferHandle);
-        }
-    }
-
-    void write(const std::shared_ptr<CommandWriterBase>& writer) override {
-        TestLayer::write(writer);
-        writer->setLayerCompositionType(mComposition);
-        writer->setLayerDataspace(Dataspace::UNKNOWN);
-        writer->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, mDisplayFrame));
-        if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle, mFillFence);
-    }
-
-    void fillBuffer(std::vector<IComposerClient::Color> expectedColors) {
-        void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, -1);
-        ASSERT_NO_FATAL_FAILURE(GraphicsComposerReadbackTest::fillBuffer(
-                mWidth, mHeight, mStride, bufData, mFormat, expectedColors));
-        mFillFence = mGralloc->unlock(mBufferHandle);
-        if (mFillFence != -1) {
-            sync_wait(mFillFence, -1);
-            close(mFillFence);
-        }
-    }
-    void setBuffer(std::vector<IComposerClient::Color> colors) {
-        if (mBufferHandle != nullptr) {
-            mGralloc->freeBuffer(mBufferHandle);
-            mBufferHandle = nullptr;
-        }
-        mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
-                                           /*import*/ true, &mStride);
-        ASSERT_NE(nullptr, mBufferHandle);
-        ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
-        ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount,
-                                                      mFormat, mUsage, mStride));
-    }
-
-    void setToClientComposition(const std::shared_ptr<CommandWriterBase>& writer) {
-        writer->selectLayer(mLayer);
-        writer->setLayerCompositionType(IComposerClient::Composition::CLIENT);
-    }
-
-    AccessRegion mAccessRegion;
-    uint32_t mStride;
-    uint32_t mWidth;
-    uint32_t mHeight;
-    uint32_t mLayerCount;
-    PixelFormat mFormat;
-
-  protected:
-    uint64_t mUsage;
-    IComposerClient::Composition mComposition;
-    std::shared_ptr<Gralloc> mGralloc;
-    int32_t mFillFence;
-    const native_handle_t* mBufferHandle = nullptr;
 };
 
 TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) {
-    if (!mHasReadbackBuffer) {
-        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
-        return;
+    for (ColorMode mode : mTestColorModes) {
+        std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
+                  << std::endl;
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+                mPrimaryDisplay,
+                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
+                                                                           tmpDataspace, tmpError);
+                    mPixelFormat = tmpPixelFormat;
+                    mDataspace = tmpDataspace;
+                });
+
+        if (!mHasReadbackBuffer) {
+            std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setColor(BLUE);
+        layer->setDisplayFrame(coloredSquare);
+        layer->setZOrder(10);
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        // expected color for each pixel
+        std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->validateDisplay();
+        execute();
+        // if hwc cannot handle and asks for composition change,
+        // just succeed the test
+        if (mReader->mCompositionChanges.size() != 0) {
+            clearCommandReaderState();
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
     }
-    mWriter->selectDisplay(mPrimaryDisplay);
-    ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB,
-                                                          RenderIntent::COLORIMETRIC));
-
-    auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
-    IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight});
-    layer->setColor(BLUE);
-    layer->setDisplayFrame(coloredSquare);
-    layer->setZOrder(10);
-
-    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
-
-    // expected color for each pixel
-    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
-
-    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                  mDisplayHeight, mPixelFormat, mDataspace);
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-
-    writeLayers(layers);
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->validateDisplay();
-    execute();
-    // if hwc cannot handle and asks for composition change,
-    // just succeed the test
-    if (mReader->mCompositionChanges.size() != 0) {
-        clearCommandReaderState();
-        GTEST_SUCCEED();
-        return;
-    }
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->presentDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 }
 
 TEST_F(GraphicsComposerReadbackTest, SetLayerBuffer) {
-    if (!mHasReadbackBuffer) {
-        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
-        return;
+    for (ColorMode mode : mTestColorModes) {
+        std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
+                  << std::endl;
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+                mPrimaryDisplay,
+                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
+                                                                           tmpDataspace, tmpError);
+                    mPixelFormat = tmpPixelFormat;
+                    mDataspace = tmpDataspace;
+                });
+
+        if (!mHasReadbackBuffer) {
+            std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        mWriter->selectDisplay(mPrimaryDisplay);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+        std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2},
+                                       GREEN);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
+                                       BLUE);
+
+        auto layer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
+                                                       mDisplayWidth, mDisplayHeight,
+                                                       PixelFormat::RGBA_8888);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        writeLayers(layers);
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->validateDisplay();
+        execute();
+
+        if (mReader->mCompositionChanges.size() != 0) {
+            clearCommandReaderState();
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        mWriter->presentDisplay();
+        execute();
+
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
     }
-
-    mWriter->selectDisplay(mPrimaryDisplay);
-
-    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                  mDisplayHeight, mPixelFormat, mDataspace);
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2}, GREEN);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE);
-
-    auto layer =
-        std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
-                                          mDisplayHeight, PixelFormat::RGBA_8888);
-    layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
-    layer->setZOrder(10);
-    ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
-
-    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
-
-    writeLayers(layers);
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->validateDisplay();
-    execute();
-
-    if (mReader->mCompositionChanges.size() != 0) {
-        clearCommandReaderState();
-        GTEST_SUCCEED();
-        return;
-    }
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    mWriter->presentDisplay();
-    execute();
-
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 }
 
 TEST_F(GraphicsComposerReadbackTest, SetLayerBufferNoEffect) {
-    if (!mHasReadbackBuffer) {
-        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
-        return;
+    for (ColorMode mode : mTestColorModes) {
+        std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
+                  << std::endl;
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+                mPrimaryDisplay,
+                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
+                                                                           tmpDataspace, tmpError);
+                    mPixelFormat = tmpPixelFormat;
+                    mDataspace = tmpDataspace;
+                });
+
+        if (!mHasReadbackBuffer) {
+            std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setColor(BLUE);
+        layer->setDisplayFrame(coloredSquare);
+        layer->setZOrder(10);
+        layer->write(mWriter);
+
+        // This following buffer call should have no effect
+        uint64_t usage =
+                static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN);
+        const native_handle_t* bufferHandle =
+                mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage);
+        mWriter->setLayerBuffer(0, bufferHandle, -1);
+
+        // expected color for each pixel
+        std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        mWriter->validateDisplay();
+        execute();
+
+        if (mReader->mCompositionChanges.size() != 0) {
+            clearCommandReaderState();
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
     }
-
-    mWriter->selectDisplay(mPrimaryDisplay);
-    ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB,
-                                                          RenderIntent::COLORIMETRIC));
-
-    auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
-    IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight});
-    layer->setColor(BLUE);
-    layer->setDisplayFrame(coloredSquare);
-    layer->setZOrder(10);
-    layer->write(mWriter);
-
-    // This following buffer call should have no effect
-    PixelFormat format = PixelFormat::RGBA_8888;
-    uint64_t usage =
-            static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN);
-    const native_handle_t* bufferHandle =
-            mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, format, usage);
-    mWriter->setLayerBuffer(0, bufferHandle, -1);
-
-    // expected color for each pixel
-    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
-
-    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                  mDisplayHeight, mPixelFormat, mDataspace);
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-
-    mWriter->validateDisplay();
-    execute();
-
-    if (mReader->mCompositionChanges.size() != 0) {
-        clearCommandReaderState();
-        GTEST_SUCCEED();
-        return;
-    }
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->presentDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 }
 
 TEST_F(GraphicsComposerReadbackTest, ClientComposition) {
-    if (!mHasReadbackBuffer) {
-        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
-        return;
-    }
-
-    mWriter->selectDisplay(mPrimaryDisplay);
-
-    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2}, GREEN);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE);
-
-    auto layer =
-        std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
-                                          mDisplayHeight, PixelFormat::RGBA_FP16);
-    layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
-    layer->setZOrder(10);
-
-    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
-
-    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                  mDisplayHeight, mPixelFormat, mDataspace);
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-    writeLayers(layers);
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->validateDisplay();
-    execute();
-
-    if (mReader->mCompositionChanges.size() != 0) {
-        ASSERT_EQ(1, mReader->mCompositionChanges.size());
-        ASSERT_EQ(1, mReader->mCompositionChanges[0].second);
-
-        ASSERT_NO_FATAL_FAILURE(
+    ASSERT_NO_FATAL_FAILURE(
             mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount));
 
+    for (ColorMode mode : mTestColorModes) {
+        std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
+                  << std::endl;
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+                mPrimaryDisplay,
+                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
+                                                                           tmpDataspace, tmpError);
+                    mPixelFormat = tmpPixelFormat;
+                    mDataspace = tmpDataspace;
+                });
+
+        if (!mHasReadbackBuffer) {
+            std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        mWriter->selectDisplay(mPrimaryDisplay);
+
+        std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2},
+                                       GREEN);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
+                                       BLUE);
+
+        auto layer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
+                                                       mDisplayWidth, mDisplayHeight,
+                                                       PixelFormat::RGBA_FP16);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+        writeLayers(layers);
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->validateDisplay();
+        execute();
+
+        if (mReader->mCompositionChanges.size() != 0) {
+            ASSERT_EQ(1, mReader->mCompositionChanges.size());
+            ASSERT_EQ(1, mReader->mCompositionChanges[0].second);
+
+            // create client target buffer
+            uint32_t clientStride;
+            PixelFormat clientFormat = PixelFormat::RGBA_8888;
+            uint64_t clientUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN |
+                                                         BufferUsage::CPU_WRITE_OFTEN |
+                                                         BufferUsage::COMPOSER_CLIENT_TARGET);
+            const native_handle_t* clientBufferHandle =
+                    mGralloc->allocate(layer->mWidth, layer->mHeight, layer->mLayerCount,
+                                       clientFormat, clientUsage, /*import*/ true, &clientStride);
+            ASSERT_NE(nullptr, clientBufferHandle);
+
+            void* clientBufData =
+                    mGralloc->lock(clientBufferHandle, clientUsage, layer->mAccessRegion, -1);
+
+            ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(layer->mWidth, layer->mHeight,
+                                                               clientStride, clientBufData,
+                                                               clientFormat, expectedColors));
+            int clientFence = mGralloc->unlock(clientBufferHandle);
+            if (clientFence != -1) {
+                sync_wait(clientFence, -1);
+                close(clientFence);
+            }
+
+            IComposerClient::Rect damage{0, 0, mDisplayWidth, mDisplayHeight};
+            mWriter->setClientTarget(0, clientBufferHandle, clientFence, Dataspace::UNKNOWN,
+                                     std::vector<IComposerClient::Rect>(1, damage));
+
+            layer->setToClientComposition(mWriter);
+            mWriter->validateDisplay();
+            execute();
+            ASSERT_EQ(0, mReader->mCompositionChanges.size());
+        }
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        mWriter->presentDisplay();
+        execute();
+
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+    }
+}
+
+TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) {
+    ASSERT_NO_FATAL_FAILURE(
+            mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount));
+
+    for (ColorMode mode : mTestColorModes) {
+        std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
+                  << std::endl;
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+                mPrimaryDisplay,
+                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
+                                                                           tmpDataspace, tmpError);
+                    mPixelFormat = tmpPixelFormat;
+                    mDataspace = tmpDataspace;
+                });
+
+        if (!mHasReadbackBuffer) {
+            std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight / 2}, GREEN);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        auto deviceLayer = std::make_shared<TestBufferLayer>(
+                mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, mDisplayHeight / 2,
+                PixelFormat::RGBA_8888);
+        std::vector<IComposerClient::Color> deviceColors(deviceLayer->mWidth *
+                                                         deviceLayer->mHeight);
+        ReadbackHelper::fillColorsArea(deviceColors, deviceLayer->mWidth,
+                                       {0, 0, static_cast<int32_t>(deviceLayer->mWidth),
+                                        static_cast<int32_t>(deviceLayer->mHeight)},
+                                       GREEN);
+        deviceLayer->setDisplayFrame({0, 0, static_cast<int32_t>(deviceLayer->mWidth),
+                                      static_cast<int32_t>(deviceLayer->mHeight)});
+        deviceLayer->setZOrder(10);
+        ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors));
+        deviceLayer->write(mWriter);
+
+        auto clientLayer = std::make_shared<TestBufferLayer>(
+                mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, mDisplayHeight / 2,
+                PixelFormat::RGBA_8888, IComposerClient::Composition::CLIENT);
+        IComposerClient::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight};
+        clientLayer->setDisplayFrame(clientFrame);
+        clientLayer->setZOrder(0);
+        clientLayer->write(mWriter);
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+
         // create client target buffer
         uint32_t clientStride;
         PixelFormat clientFormat = PixelFormat::RGBA_8888;
@@ -654,349 +524,335 @@
                 static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                                       BufferUsage::COMPOSER_CLIENT_TARGET);
         const native_handle_t* clientBufferHandle =
-                mGralloc->allocate(layer->mWidth, layer->mHeight, layer->mLayerCount, clientFormat,
-                                   clientUsage, /*import*/ true, &clientStride);
+                mGralloc->allocate(mDisplayWidth, mDisplayHeight, clientLayer->mLayerCount,
+                                   clientFormat, clientUsage, /*import*/ true, &clientStride);
         ASSERT_NE(nullptr, clientBufferHandle);
 
-        void* clientBufData =
-                mGralloc->lock(clientBufferHandle, clientUsage, layer->mAccessRegion, -1);
+        void* clientBufData = mGralloc->lock(clientBufferHandle, clientUsage,
+                                             {0, 0, mDisplayWidth, mDisplayHeight}, -1);
 
-        ASSERT_NO_FATAL_FAILURE(fillBuffer(layer->mWidth, layer->mHeight, clientStride,
-                                           clientBufData, clientFormat, expectedColors));
+        std::vector<IComposerClient::Color> clientColors(mDisplayWidth * mDisplayHeight);
+        ReadbackHelper::fillColorsArea(clientColors, mDisplayWidth, clientFrame, RED);
+        ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mDisplayWidth, mDisplayHeight,
+                                                           clientStride, clientBufData,
+                                                           clientFormat, clientColors));
         int clientFence = mGralloc->unlock(clientBufferHandle);
         if (clientFence != -1) {
             sync_wait(clientFence, -1);
             close(clientFence);
         }
 
-        IComposerClient::Rect damage{0, 0, mDisplayWidth, mDisplayHeight};
         mWriter->setClientTarget(0, clientBufferHandle, clientFence, Dataspace::UNKNOWN,
-                                 std::vector<IComposerClient::Rect>(1, damage));
-
-        layer->setToClientComposition(mWriter);
+                                 std::vector<IComposerClient::Rect>(1, clientFrame));
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
         mWriter->validateDisplay();
         execute();
-        ASSERT_EQ(0, mReader->mCompositionChanges.size());
+        if (mReader->mCompositionChanges.size() != 0) {
+            clearCommandReaderState();
+            std::cout << "Composition change requested, skipping test" << std::endl;
+            GTEST_SUCCEED() << "Composition change requested, skipping test";
+            return;
+        }
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
     }
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    mWriter->presentDisplay();
-    execute();
-
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-}
-
-TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) {
-    if (!mHasReadbackBuffer) {
-        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
-        return;
-    }
-
-    mWriter->selectDisplay(mPrimaryDisplay);
-    ASSERT_NO_FATAL_FAILURE(
-        mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount));
-
-    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 2}, GREEN);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED);
-
-    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                  mDisplayHeight, mPixelFormat, mDataspace);
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-
-    auto deviceLayer =
-        std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
-                                          mDisplayHeight / 2, PixelFormat::RGBA_8888);
-    std::vector<IComposerClient::Color> deviceColors(deviceLayer->mWidth * deviceLayer->mHeight);
-    fillColorsArea(deviceColors, deviceLayer->mWidth,
-                   {0, 0, static_cast<int32_t>(deviceLayer->mWidth),
-                    static_cast<int32_t>(deviceLayer->mHeight)},
-                   GREEN);
-    deviceLayer->setDisplayFrame({0, 0, static_cast<int32_t>(deviceLayer->mWidth),
-                                  static_cast<int32_t>(deviceLayer->mHeight)});
-    deviceLayer->setZOrder(10);
-    ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors));
-    deviceLayer->write(mWriter);
-
-    auto clientLayer = std::make_shared<TestBufferLayer>(
-        mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, mDisplayHeight / 2,
-        PixelFormat::RGBA_8888, IComposerClient::Composition::CLIENT);
-    IComposerClient::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight};
-    clientLayer->setDisplayFrame(clientFrame);
-    clientLayer->setZOrder(0);
-    clientLayer->write(mWriter);
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    uint64_t clientUsage =
-            static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                  BufferUsage::COMPOSER_CLIENT_TARGET);
-    uint32_t clientStride;
-    const native_handle_t* clientBufferHandle =
-            mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888,
-                               clientUsage, /*import*/ true, &clientStride);
-    ASSERT_NE(nullptr, clientBufferHandle);
-
-    AccessRegion clientAccessRegion;
-    clientAccessRegion.left = 0;
-    clientAccessRegion.top = 0;
-    clientAccessRegion.width = mDisplayWidth;
-    clientAccessRegion.height = mDisplayHeight;
-    void* clientData = mGralloc->lock(clientBufferHandle, clientUsage, clientAccessRegion, -1);
-    std::vector<IComposerClient::Color> clientColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(clientColors, mDisplayWidth, clientFrame, RED);
-    ASSERT_NO_FATAL_FAILURE(fillBuffer(mDisplayWidth, mDisplayHeight, clientStride, clientData,
-                                       PixelFormat::RGBA_8888, clientColors));
-    int clientFence = mGralloc->unlock(clientBufferHandle);
-    if (clientFence != -1) {
-        sync_wait(clientFence, -1);
-        close(clientFence);
-    }
-
-    mWriter->setClientTarget(0, clientBufferHandle, clientFence, Dataspace::UNKNOWN,
-                             std::vector<IComposerClient::Rect>(1, clientFrame));
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->validateDisplay();
-    execute();
-    if (mReader->mCompositionChanges.size() != 0) {
-        clearCommandReaderState();
-        GTEST_SUCCEED();
-        return;
-    }
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->presentDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 }
 
 TEST_F(GraphicsComposerReadbackTest, SetLayerDamage) {
-    if (!mHasReadbackBuffer) {
-        GTEST_SUCCEED() << "Readback not supported or unsupported pixelformat/dataspace";
-        return;
+    for (ColorMode mode : mTestColorModes) {
+        std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
+                  << std::endl;
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+                mPrimaryDisplay,
+                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
+                                                                           tmpDataspace, tmpError);
+                    mPixelFormat = tmpPixelFormat;
+                    mDataspace = tmpDataspace;
+                });
+
+        if (!mHasReadbackBuffer) {
+            std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        mWriter->selectDisplay(mPrimaryDisplay);
+
+        IComposerClient::Rect redRect = {0, 0, mDisplayWidth / 4, mDisplayHeight / 4};
+
+        std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+
+        auto layer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
+                                                       mDisplayWidth, mDisplayHeight,
+                                                       PixelFormat::RGBA_8888);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->validateDisplay();
+        execute();
+        if (mReader->mCompositionChanges.size() != 0) {
+            clearCommandReaderState();
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+
+        // update surface damage and recheck
+        redRect = {mDisplayWidth / 4, mDisplayHeight / 4, mDisplayWidth / 2, mDisplayHeight / 2};
+        ReadbackHelper::clearColors(expectedColors, mDisplayWidth, mDisplayHeight, mDisplayWidth);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+
+        ASSERT_NO_FATAL_FAILURE(layer->fillBuffer(expectedColors));
+        layer->setSurfaceDamage(std::vector<IComposerClient::Rect>(
+                1, {0, 0, mDisplayWidth / 2, mDisplayWidth / 2}));
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->validateDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+        ASSERT_EQ(0, mReader->mCompositionChanges.size());
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
     }
-
-    mWriter->selectDisplay(mPrimaryDisplay);
-
-    IComposerClient::Rect redRect = {0, 0, mDisplayWidth / 4, mDisplayHeight / 4};
-
-    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
-
-    auto layer =
-        std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
-                                          mDisplayHeight, PixelFormat::RGBA_8888);
-    layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
-    layer->setZOrder(10);
-    ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
-
-    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
-
-    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                  mDisplayHeight, mPixelFormat, mDataspace);
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-
-    writeLayers(layers);
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->validateDisplay();
-    execute();
-    if (mReader->mCompositionChanges.size() != 0) {
-        clearCommandReaderState();
-        GTEST_SUCCEED();
-        return;
-    }
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->presentDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-
-    // update surface damage and recheck
-    redRect = {mDisplayWidth / 4, mDisplayHeight / 4, mDisplayWidth / 2, mDisplayHeight / 2};
-    clearColors(expectedColors, mDisplayWidth, mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
-
-    ASSERT_NO_FATAL_FAILURE(layer->fillBuffer(expectedColors));
-    layer->setSurfaceDamage(
-        std::vector<IComposerClient::Rect>(1, {0, 0, mDisplayWidth / 2, mDisplayWidth / 2}));
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-
-    writeLayers(layers);
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->validateDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-    ASSERT_EQ(0, mReader->mCompositionChanges.size());
-    mWriter->presentDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 }
 
 TEST_F(GraphicsComposerReadbackTest, SetLayerPlaneAlpha) {
-    if (!mHasReadbackBuffer) {
-        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
-        return;
+    for (ColorMode mode : mTestColorModes) {
+        std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
+                  << std::endl;
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+                mPrimaryDisplay,
+                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
+                                                                           tmpDataspace, tmpError);
+                    mPixelFormat = tmpPixelFormat;
+                    mDataspace = tmpDataspace;
+                });
+
+        if (!mHasReadbackBuffer) {
+            std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        layer->setColor(RED);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        layer->setAlpha(0);
+        layer->setBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->validateDisplay();
+        execute();
+        if (mReader->mCompositionChanges.size() != 0) {
+            clearCommandReaderState();
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
     }
-
-    mWriter->selectDisplay(mPrimaryDisplay);
-    ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB,
-                                                          RenderIntent::COLORIMETRIC));
-
-    auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
-    layer->setColor(RED);
-    layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
-    layer->setZOrder(10);
-    layer->setAlpha(0);
-    layer->setBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
-
-    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
-
-    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                  mDisplayHeight, mPixelFormat, mDataspace);
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-
-    writeLayers(layers);
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->validateDisplay();
-    execute();
-    if (mReader->mCompositionChanges.size() != 0) {
-        clearCommandReaderState();
-        GTEST_SUCCEED();
-        return;
-    }
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    mWriter->presentDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 }
 
 TEST_F(GraphicsComposerReadbackTest, SetLayerSourceCrop) {
-    if (!mHasReadbackBuffer) {
-        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
-        return;
+    for (ColorMode mode : mTestColorModes) {
+        std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
+                  << std::endl;
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+                mPrimaryDisplay,
+                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
+                                                                           tmpDataspace, tmpError);
+                    mPixelFormat = tmpPixelFormat;
+                    mDataspace = tmpDataspace;
+                });
+
+        if (!mHasReadbackBuffer) {
+            std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        mWriter->selectDisplay(mPrimaryDisplay);
+
+        std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
+                                       BLUE);
+
+        auto layer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
+                                                       mDisplayWidth, mDisplayHeight,
+                                                       PixelFormat::RGBA_8888);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        layer->setSourceCrop({0, static_cast<float>(mDisplayHeight / 2),
+                              static_cast<float>(mDisplayWidth),
+                              static_cast<float>(mDisplayHeight)});
+        ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        // update expected colors to match crop
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight}, BLUE);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+        writeLayers(layers);
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->validateDisplay();
+        execute();
+        if (mReader->mCompositionChanges.size() != 0) {
+            clearCommandReaderState();
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
     }
-
-    mWriter->selectDisplay(mPrimaryDisplay);
-
-    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE);
-
-    auto layer =
-        std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
-                                          mDisplayHeight, PixelFormat::RGBA_8888);
-    layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
-    layer->setZOrder(10);
-    layer->setSourceCrop({0, static_cast<float>(mDisplayHeight / 2),
-                          static_cast<float>(mDisplayWidth), static_cast<float>(mDisplayHeight)});
-    ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
-
-    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
-
-    // update expected colors to match crop
-    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight}, BLUE);
-    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                  mDisplayHeight, mPixelFormat, mDataspace);
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-    writeLayers(layers);
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->validateDisplay();
-    execute();
-    if (mReader->mCompositionChanges.size() != 0) {
-        clearCommandReaderState();
-        GTEST_SUCCEED();
-        return;
-    }
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->presentDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 }
 
 TEST_F(GraphicsComposerReadbackTest, SetLayerZOrder) {
-    if (!mHasReadbackBuffer) {
-        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
-        return;
+    for (ColorMode mode : mTestColorModes) {
+        std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
+                  << std::endl;
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+                mPrimaryDisplay,
+                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
+                                                                           tmpDataspace, tmpError);
+                    mPixelFormat = tmpPixelFormat;
+                    mDataspace = tmpDataspace;
+                });
+
+        if (!mHasReadbackBuffer) {
+            std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        IComposerClient::Rect redRect = {0, 0, mDisplayWidth, mDisplayHeight / 2};
+        IComposerClient::Rect blueRect = {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight};
+        auto redLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        redLayer->setColor(RED);
+        redLayer->setDisplayFrame(redRect);
+
+        auto blueLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        blueLayer->setColor(BLUE);
+        blueLayer->setDisplayFrame(blueRect);
+        blueLayer->setZOrder(5);
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, blueLayer};
+        std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+
+        // red in front of blue
+        redLayer->setZOrder(10);
+
+        // fill blue first so that red will overwrite on overlap
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->validateDisplay();
+        execute();
+        if (mReader->mCompositionChanges.size() != 0) {
+            clearCommandReaderState();
+            GTEST_SUCCEED();
+            return;
+        }
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+
+        redLayer->setZOrder(1);
+        ReadbackHelper::clearColors(expectedColors, mDisplayWidth, mDisplayHeight, mDisplayWidth);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->validateDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mCompositionChanges.size());
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
     }
-
-    mWriter->selectDisplay(mPrimaryDisplay);
-    ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB,
-                                                          RenderIntent::COLORIMETRIC));
-
-    IComposerClient::Rect redRect = {0, 0, mDisplayWidth, mDisplayHeight / 2};
-    IComposerClient::Rect blueRect = {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight};
-    auto redLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
-    redLayer->setColor(RED);
-    redLayer->setDisplayFrame(redRect);
-
-    auto blueLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
-    blueLayer->setColor(BLUE);
-    blueLayer->setDisplayFrame(blueRect);
-    blueLayer->setZOrder(5);
-
-    std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, blueLayer};
-    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-
-    // red in front of blue
-    redLayer->setZOrder(10);
-
-    // fill blue first so that red will overwrite on overlap
-    fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
-    fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
-
-    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                  mDisplayHeight, mPixelFormat, mDataspace);
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-
-    writeLayers(layers);
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->validateDisplay();
-    execute();
-    if (mReader->mCompositionChanges.size() != 0) {
-        clearCommandReaderState();
-        GTEST_SUCCEED();
-        return;
-    }
-    mWriter->presentDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
-
-    redLayer->setZOrder(1);
-    clearColors(expectedColors, mDisplayWidth, mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
-    fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
-
-    writeLayers(layers);
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->validateDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mCompositionChanges.size());
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mWriter->presentDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-
-    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 }
 
 class GraphicsComposerBlendModeReadbackTest : public GraphicsComposerReadbackTest,
@@ -1017,8 +873,8 @@
     void setUpLayers(IComposerClient::BlendMode blendMode) {
         mLayers.clear();
         std::vector<IComposerClient::Color> topLayerPixelColors(mDisplayWidth * mDisplayHeight);
-        fillColorsArea(topLayerPixelColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight},
-                       mTopLayerColor);
+        ReadbackHelper::fillColorsArea(topLayerPixelColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight}, mTopLayerColor);
 
         auto backgroundLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
         backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
@@ -1041,7 +897,7 @@
 
     void setExpectedColors(std::vector<IComposerClient::Color>& expectedColors) {
         ASSERT_EQ(2, mLayers.size());
-        clearColors(expectedColors, mDisplayWidth, mDisplayHeight);
+        ReadbackHelper::clearColors(expectedColors, mDisplayWidth, mDisplayHeight, mDisplayWidth);
 
         auto layer = mLayers[1];
         IComposerClient::BlendMode blendMode = layer->mBlendMode;
@@ -1194,8 +1050,6 @@
         GraphicsComposerReadbackTest::SetUp();
 
         mWriter->selectDisplay(mPrimaryDisplay);
-        ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB,
-                                                              RenderIntent::COLORIMETRIC));
 
         auto backgroundLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
         backgroundLayer->setColor({0, 0, 0, 0});
@@ -1214,8 +1068,8 @@
         mLayer->setZOrder(10);
 
         std::vector<IComposerClient::Color> baseColors(mSideLength * mSideLength);
-        fillColorsArea(baseColors, mSideLength, redRect, RED);
-        fillColorsArea(baseColors, mSideLength, blueRect, BLUE);
+        ReadbackHelper::fillColorsArea(baseColors, mSideLength, redRect, RED);
+        ReadbackHelper::fillColorsArea(baseColors, mSideLength, blueRect, BLUE);
         ASSERT_NO_FATAL_FAILURE(mLayer->setBuffer(baseColors));
 
         mLayers = {backgroundLayer, mLayer};
@@ -1238,10 +1092,10 @@
     ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
     mLayer->setTransform(Transform::FLIP_H);
     std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {mSideLength / 2, 0, mSideLength, mSideLength / 2}, RED);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {0, mSideLength / 2, mSideLength / 2, mSideLength}, BLUE);
+    ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                   {mSideLength / 2, 0, mSideLength, mSideLength / 2}, RED);
+    ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                   {0, mSideLength / 2, mSideLength / 2, mSideLength}, BLUE);
 
     writeLayers(mLayers);
     ASSERT_EQ(0, mReader->mErrors.size());
@@ -1272,10 +1126,10 @@
     mLayer->setTransform(Transform::FLIP_V);
 
     std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {0, mSideLength / 2, mSideLength / 2, mSideLength}, RED);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {mSideLength / 2, 0, mSideLength, mSideLength / 2}, BLUE);
+    ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                   {0, mSideLength / 2, mSideLength / 2, mSideLength}, RED);
+    ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                   {mSideLength / 2, 0, mSideLength, mSideLength / 2}, BLUE);
 
     writeLayers(mLayers);
     ASSERT_EQ(0, mReader->mErrors.size());
@@ -1305,9 +1159,11 @@
     mLayer->setTransform(Transform::ROT_180);
 
     std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
-    fillColorsArea(expectedColors, mDisplayWidth,
-                   {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength}, RED);
-    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mSideLength / 2, mSideLength / 2}, BLUE);
+    ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                   {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength},
+                                   RED);
+    ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                   {0, 0, mSideLength / 2, mSideLength / 2}, BLUE);
 
     writeLayers(mLayers);
     ASSERT_EQ(0, mReader->mErrors.size());
diff --git a/graphics/composer/2.3/utils/OWNERS b/graphics/composer/2.3/utils/OWNERS
index b3ea6be..cc6d937 100644
--- a/graphics/composer/2.3/utils/OWNERS
+++ b/graphics/composer/2.3/utils/OWNERS
@@ -2,7 +2,3 @@
 lpy@google.com
 stoza@google.com
 vhau@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
diff --git a/graphics/composer/2.3/utils/command-buffer/Android.bp b/graphics/composer/2.3/utils/command-buffer/Android.bp
index c48fe7a..36ac297 100644
--- a/graphics/composer/2.3/utils/command-buffer/Android.bp
+++ b/graphics/composer/2.3/utils/command-buffer/Android.bp
@@ -3,12 +3,15 @@
     defaults: ["hidl_defaults"],
     vendor_available: true,
     shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.composer@2.2",
+        "android.hardware.graphics.composer@2.3",
+    ],
+    export_shared_lib_headers: [
         "android.hardware.graphics.composer@2.3",
     ],
     header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
+        "android.hardware.graphics.composer@2.2-command-buffer",
+    ],
+    export_header_lib_headers: [
         "android.hardware.graphics.composer@2.2-command-buffer",
     ],
     export_include_dirs: ["include"],
diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp
index 2fe6cd6..f65a9c4 100644
--- a/graphics/composer/2.3/utils/vts/Android.bp
+++ b/graphics/composer/2.3/utils/vts/Android.bp
@@ -21,22 +21,17 @@
         "ComposerVts.cpp",
     ],
     static_libs: [
-        "VtsHalHidlTargetTestBase",
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.composer@2.1-vts",
-        "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.2-vts",
         "android.hardware.graphics.composer@2.3",
-	"android.hardware.graphics.mapper@2.0",
-	"android.hardware.graphics.mapper@2.0-vts",
-	"android.hardware.graphics.mapper@2.1",
-	"android.hardware.graphics.mapper@2.1-vts",
-	"android.hardware.graphics.mapper@3.0",
-	"android.hardware.graphics.mapper@3.0-vts",
+    ],
+    export_static_lib_headers: [
+        "android.hardware.graphics.composer@2.2-vts",
+        "android.hardware.graphics.composer@2.3",
     ],
     header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
-        "android.hardware.graphics.composer@2.2-command-buffer",
+        "android.hardware.graphics.composer@2.3-command-buffer",
+    ],
+    export_header_lib_headers: [
         "android.hardware.graphics.composer@2.3-command-buffer",
     ],
     cflags: [
diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.0/support/Keymaster.cpp
index 1eb9a68..f20f951 100644
--- a/keymaster/4.0/support/Keymaster.cpp
+++ b/keymaster/4.0/support/Keymaster.cpp
@@ -80,8 +80,7 @@
 }
 
 template <typename Wrapper>
-std::vector<std::unique_ptr<Keymaster>> enumerateDevices(
-    const sp<IServiceManager>& serviceManager) {
+Keymaster::KeymasterSet enumerateDevices(const sp<IServiceManager>& serviceManager) {
     Keymaster::KeymasterSet result;
 
     bool foundDefault = false;
@@ -92,7 +91,7 @@
             auto device = Wrapper::WrappedIKeymasterDevice::getService(name);
             CHECK(device) << "Failed to get service for " << descriptor << " with interface name "
                           << name;
-            result.push_back(std::unique_ptr<Keymaster>(new Wrapper(device, name)));
+            result.push_back(new Wrapper(device, name));
         }
     });
 
@@ -100,7 +99,7 @@
         // "default" wasn't provided by listManifestByInterface.  Maybe there's a passthrough
         // implementation.
         auto device = Wrapper::WrappedIKeymasterDevice::getService("default");
-        if (device) result.push_back(std::unique_ptr<Keymaster>(new Wrapper(device, "default")));
+        if (device) result.push_back(new Wrapper(device, "default"));
     }
 
     return result;
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
index 43a34b0..ad83f17 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
@@ -39,8 +39,8 @@
  * while still having to use only the latest interface.
  */
 class Keymaster : public IKeymasterDevice {
-   public:
-    using KeymasterSet = std::vector<std::unique_ptr<Keymaster>>;
+  public:
+    using KeymasterSet = std::vector<android::sp<Keymaster>>;
 
     Keymaster(const hidl_string& descriptor, const hidl_string& instanceName)
         : descriptor_(descriptor), instanceName_(instanceName) {}
@@ -86,7 +86,7 @@
      */
     static void performHmacKeyAgreement(const KeymasterSet& keymasters);
 
-   private:
+  private:
     hidl_string descriptor_;
     hidl_string instanceName_;
 };
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 0fb18f1..0d70816 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -15,21 +15,19 @@
 //
 
 cc_library_static {
-    name: "VtsHalNeuralnetworksTest_utils",
+    name: "VtsHalNeuralNetworksV1_0_utils",
     srcs: [
         "Callbacks.cpp",
-        "GeneratedTestHarness.cpp",
+        "Utils.cpp",
     ],
     defaults: ["VtsHalTargetTestDefaults"],
-    export_include_dirs: ["."],
+    export_include_dirs: ["include"],
     shared_libs: [
         "libfmq",
         "libnativewindow",
     ],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
-        "android.hardware.neuralnetworks@1.1",
-        "android.hardware.neuralnetworks@1.2",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libgmock",
@@ -44,12 +42,13 @@
 }
 
 cc_defaults {
-    name: "VtsHalNeuralNetworksTargetTestDefaults",
+    name: "VtsHalNeuralNetworksV1_0TargetTestDefaults",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "ValidateModel.cpp",
         "ValidateRequest.cpp",
         "VtsHalNeuralnetworks.cpp",
+        "GeneratedTestHarness.cpp",
     ],
     shared_libs: [
         "libfmq",
@@ -57,14 +56,12 @@
     ],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
-        "android.hardware.neuralnetworks@1.1",
-        "android.hardware.neuralnetworks@1.2",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_utils",
-        "VtsHalNeuralnetworksTest_utils",
+        "VtsHalNeuralNetworksV1_0_utils",
     ],
     header_libs: [
         "libneuralnetworks_headers",
@@ -76,19 +73,19 @@
 
 cc_test {
     name: "VtsHalNeuralnetworksV1_0TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalNeuralNetworksV1_0TargetTestDefaults"],
     srcs: [
         "BasicTests.cpp",
-        "GeneratedTests.cpp",
+        "GeneratedTestsV1_0.cpp",
     ],
 }
 
 cc_test {
     name: "PresubmitHalNeuralnetworksV1_0TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalNeuralNetworksV1_0TargetTestDefaults"],
     srcs: [
         "BasicTests.cpp",
-        "GeneratedTests.cpp",
+        "GeneratedTestsV1_0.cpp",
     ],
     cflags: [
         "-DPRESUBMIT_NOT_VTS",
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.cpp b/neuralnetworks/1.0/vts/functional/Callbacks.cpp
index c30702c..2b5723d 100644
--- a/neuralnetworks/1.0/vts/functional/Callbacks.cpp
+++ b/neuralnetworks/1.0/vts/functional/Callbacks.cpp
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-#include "Callbacks.h"
+#include "1.0/Callbacks.h"
 #include <android-base/logging.h>
 
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-namespace V1_2 {
+namespace V1_0 {
 namespace implementation {
 
 CallbackBase::CallbackBase() : mNotified(false) {}
@@ -111,14 +111,6 @@
     return Void();
 }
 
-Return<void> PreparedModelCallback::notify_1_2(ErrorStatus errorStatus,
-                                               const sp<V1_2::IPreparedModel>& preparedModel) {
-    mErrorStatus = errorStatus;
-    mPreparedModel = preparedModel;
-    CallbackBase::notify();
-    return Void();
-}
-
 ErrorStatus PreparedModelCallback::getStatus() {
     wait();
     return mErrorStatus;
@@ -135,18 +127,6 @@
 
 Return<void> ExecutionCallback::notify(ErrorStatus errorStatus) {
     mErrorStatus = errorStatus;
-    mOutputShapes = {};
-    mTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX};
-    CallbackBase::notify();
-    return Void();
-}
-
-Return<void> ExecutionCallback::notify_1_2(ErrorStatus errorStatus,
-                                           const hidl_vec<OutputShape>& outputShapes,
-                                           const Timing& timing) {
-    mErrorStatus = errorStatus;
-    mOutputShapes = outputShapes;
-    mTiming = timing;
     CallbackBase::notify();
     return Void();
 }
@@ -156,18 +136,8 @@
     return mErrorStatus;
 }
 
-const std::vector<OutputShape>& ExecutionCallback::getOutputShapes() {
-    wait();
-    return mOutputShapes;
-}
-
-Timing ExecutionCallback::getTiming() {
-    wait();
-    return mTiming;
-}
-
 }  // namespace implementation
-}  // namespace V1_2
+}  // namespace V1_0
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index c819b52..603054d 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -15,129 +15,47 @@
  */
 
 #include "GeneratedTestHarness.h"
-#include "Callbacks.h"
-#include "ExecutionBurstController.h"
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "MemoryUtils.h"
 #include "TestHarness.h"
-#include "Utils.h"
 
 #include <android-base/logging.h>
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
 #include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
 #include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.1/IDevice.h>
-#include <android/hardware/neuralnetworks/1.2/IDevice.h>
-#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
+
 #include <iostream>
 
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-
 namespace generated_tests {
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::test_helper::bool8;
+
+using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
+using ::android::hardware::neuralnetworks::V1_0::IDevice;
+using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
+using ::android::hardware::neuralnetworks::V1_0::Model;
+using ::android::hardware::neuralnetworks::V1_0::Request;
+using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hidl::memory::V1_0::IMemory;
 using ::test_helper::compare;
-using ::test_helper::expectMultinomialDistributionWithinTolerance;
 using ::test_helper::filter;
 using ::test_helper::for_all;
-using ::test_helper::for_each;
 using ::test_helper::MixedTyped;
 using ::test_helper::MixedTypedExample;
 using ::test_helper::resize_accordingly;
-using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
-
-template <typename T>
-void copy_back_(std::map<int, std::vector<T>>* dst, const std::vector<RequestArgument>& ra,
-                char* src) {
-    for_each<T>(*dst, [&ra, src](int index, std::vector<T>& m) {
-        ASSERT_EQ(m.size(), ra[index].location.length / sizeof(T));
-        char* begin = src + ra[index].location.offset;
-        memcpy(m.data(), begin, ra[index].location.length);
-    });
-}
-
-void copy_back(MixedTyped* dst, const std::vector<RequestArgument>& ra, char* src) {
-    copy_back_(&dst->float32Operands, ra, src);
-    copy_back_(&dst->int32Operands, ra, src);
-    copy_back_(&dst->quant8AsymmOperands, ra, src);
-    copy_back_(&dst->quant16SymmOperands, ra, src);
-    copy_back_(&dst->float16Operands, ra, src);
-    copy_back_(&dst->bool8Operands, ra, src);
-    copy_back_(&dst->quant8ChannelOperands, ra, src);
-    copy_back_(&dst->quant16AsymmOperands, ra, src);
-    copy_back_(&dst->quant8SymmOperands, ra, src);
-    static_assert(9 == MixedTyped::kNumTypes,
-                  "Number of types in MixedTyped changed, but copy_back function wasn't updated");
-}
-
-static bool isZeroSized(const MixedTyped& example, uint32_t index) {
-    for (auto i : example.operandDimensions.at(index)) {
-        if (i == 0) return true;
-    }
-    return false;
-}
 
 // Top level driver for models and examples generated by test_generator.py
 // Test driver for those generated from ml/nn/runtime/test/spec
-static Return<ErrorStatus> ExecutePreparedModel(sp<V1_0::IPreparedModel>& preparedModel,
-                                                const Request& request, MeasureTiming,
-                                                sp<ExecutionCallback>& callback) {
-    return preparedModel->execute(request, callback);
-}
-static Return<ErrorStatus> ExecutePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
-                                                const Request& request, MeasureTiming measure,
-                                                sp<ExecutionCallback>& callback) {
-    return preparedModel->execute_1_2(request, measure, callback);
-}
-static Return<ErrorStatus> ExecutePreparedModel(sp<V1_0::IPreparedModel>&, const Request&,
-                                                MeasureTiming, hidl_vec<OutputShape>*, Timing*) {
-    ADD_FAILURE() << "asking for synchronous execution at V1_0";
-    return ErrorStatus::GENERAL_FAILURE;
-}
-static Return<ErrorStatus> ExecutePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
-                                                const Request& request, MeasureTiming measure,
-                                                hidl_vec<OutputShape>* outputShapes,
-                                                Timing* timing) {
-    ErrorStatus result;
-    Return<void> ret = preparedModel->executeSynchronously(
-            request, measure,
-            [&result, outputShapes, timing](ErrorStatus error, const hidl_vec<OutputShape>& shapes,
-                                            const Timing& time) {
-                result = error;
-                *outputShapes = shapes;
-                *timing = time;
-            });
-    if (!ret.isOk()) {
-        return ErrorStatus::GENERAL_FAILURE;
-    }
-    return result;
-}
-static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst(
-        const sp<V1_0::IPreparedModel>&) {
-    ADD_FAILURE() << "asking for burst execution at V1_0";
-    return nullptr;
-}
-static std::shared_ptr<::android::nn::ExecutionBurstController> CreateBurst(
-        const sp<V1_2::IPreparedModel>& preparedModel) {
-    return ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true);
-}
-enum class Executor { ASYNC, SYNC, BURST };
-enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
-const float kDefaultAtol = 1e-5f;
-const float kDefaultRtol = 1e-5f;
-template <typename T_IPreparedModel>
-void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
-                           const std::vector<MixedTypedExample>& examples,
-                           bool hasRelaxedFloat32Model, float fpAtol, float fpRtol,
-                           Executor executor, MeasureTiming measure, OutputType outputType) {
+void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
+                           const std::vector<MixedTypedExample>& examples, float fpAtol,
+                           float fpRtol) {
     const uint32_t INPUT = 0;
     const uint32_t OUTPUT = 1;
 
@@ -147,14 +65,7 @@
         const MixedTyped& inputs = example.operands.first;
         const MixedTyped& golden = example.operands.second;
 
-        const bool hasFloat16Inputs = !inputs.float16Operands.empty();
-        if (hasRelaxedFloat32Model || hasFloat16Inputs) {
-            // TODO: Adjust the error limit based on testing.
-            // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16.
-            fpAtol = 5.0f * 0.0009765625f;
-            // Set the relative tolerance to be 5ULP of the corresponding FP precision.
-            fpRtol = 5.0f * 0.0009765625f;
-        }
+        CHECK(inputs.float16Operands.empty()) << "float16 is not supported in 1.0";
 
         std::vector<RequestArgument> inputs_info, outputs_info;
         uint32_t inputSize = 0, outputSize = 0;
@@ -163,11 +74,13 @@
         for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
             if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
             RequestArgument arg = {
-                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
+                    .location = {.poolIndex = INPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
             };
             RequestArgument arg_empty = {
-                .hasNoValue = true,
+                    .hasNoValue = true,
             };
             inputs_info[index] = s ? arg : arg_empty;
             inputSize += s;
@@ -185,31 +98,17 @@
 
         // Go through all outputs, initialize RequestArgument descriptors
         resize_accordingly(golden, test);
-        bool sizeLargerThanOne = true;
-        for_all(golden, [&golden, &outputs_info, &outputSize, &outputType, &sizeLargerThanOne](
-                                int index, auto, auto s) {
+        for_all(golden, [&outputs_info, &outputSize](int index, auto, auto s) {
             if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
-            if (index == 0) {
-                // On OutputType::INSUFFICIENT, set the output operand with index 0 with
-                // buffer size one byte less than needed.
-                if (outputType == OutputType::INSUFFICIENT) {
-                    if (s > 1 && !isZeroSized(golden, index)) {
-                        s -= 1;
-                    } else {
-                        sizeLargerThanOne = false;
-                    }
-                }
-            }
             RequestArgument arg = {
-                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
+                    .location = {.poolIndex = OUTPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
             };
             outputs_info[index] = arg;
             outputSize += s;
         });
-        // If output0 does not have size larger than one byte,
-        // we can not provide an insufficient buffer
-        if (!sizeLargerThanOne && outputType == OutputType::INSUFFICIENT) return;
         // Compute offset for outputs 1 and so on
         {
             size_t offset = 0;
@@ -248,107 +147,17 @@
 
         const Request request = {.inputs = inputs_info, .outputs = outputs_info, .pools = pools};
 
-        ErrorStatus executionStatus;
-        hidl_vec<OutputShape> outputShapes;
-        Timing timing;
-        switch (executor) {
-            case Executor::ASYNC: {
-                SCOPED_TRACE("asynchronous");
+        // launch execution
+        sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+        ASSERT_NE(nullptr, executionCallback.get());
+        Return<ErrorStatus> executionLaunchStatus =
+                preparedModel->execute(request, executionCallback);
+        ASSERT_TRUE(executionLaunchStatus.isOk());
+        EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
 
-                // launch execution
-                sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-                ASSERT_NE(nullptr, executionCallback.get());
-                Return<ErrorStatus> executionLaunchStatus =
-                        ExecutePreparedModel(preparedModel, request, measure, executionCallback);
-                ASSERT_TRUE(executionLaunchStatus.isOk());
-                EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
-
-                // retrieve execution status
-                executionCallback->wait();
-                executionStatus = executionCallback->getStatus();
-                outputShapes = executionCallback->getOutputShapes();
-                timing = executionCallback->getTiming();
-
-                break;
-            }
-            case Executor::SYNC: {
-                SCOPED_TRACE("synchronous");
-
-                // execute
-                Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
-                        preparedModel, request, measure, &outputShapes, &timing);
-                ASSERT_TRUE(executionReturnStatus.isOk());
-                executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
-
-                break;
-            }
-            case Executor::BURST: {
-                SCOPED_TRACE("burst");
-
-                // create burst
-                const std::shared_ptr<::android::nn::ExecutionBurstController> controller =
-                        CreateBurst(preparedModel);
-                ASSERT_NE(nullptr, controller.get());
-
-                // create memory keys
-                std::vector<intptr_t> keys(request.pools.size());
-                for (size_t i = 0; i < keys.size(); ++i) {
-                    keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
-                }
-
-                // execute burst
-                std::tie(executionStatus, outputShapes, timing) =
-                        controller->compute(request, measure, keys);
-
-                break;
-            }
-        }
-
-        if (outputType != OutputType::FULLY_SPECIFIED &&
-            executionStatus == ErrorStatus::GENERAL_FAILURE) {
-            LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                         "execute model that it does not support.";
-            std::cout << "[          ]   Early termination of test because vendor service cannot "
-                         "execute model that it does not support."
-                      << std::endl;
-            GTEST_SKIP();
-        }
-        if (measure == MeasureTiming::NO) {
-            EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
-            EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
-        } else {
-            if (timing.timeOnDevice != UINT64_MAX && timing.timeInDriver != UINT64_MAX) {
-                EXPECT_LE(timing.timeOnDevice, timing.timeInDriver);
-            }
-        }
-
-        switch (outputType) {
-            case OutputType::FULLY_SPECIFIED:
-                // If the model output operands are fully specified, outputShapes must be either
-                // either empty, or have the same number of elements as the number of outputs.
-                ASSERT_EQ(ErrorStatus::NONE, executionStatus);
-                ASSERT_TRUE(outputShapes.size() == 0 ||
-                            outputShapes.size() == test.operandDimensions.size());
-                break;
-            case OutputType::UNSPECIFIED:
-                // If the model output operands are not fully specified, outputShapes must have
-                // the same number of elements as the number of outputs.
-                ASSERT_EQ(ErrorStatus::NONE, executionStatus);
-                ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
-                break;
-            case OutputType::INSUFFICIENT:
-                ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
-                ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
-                ASSERT_FALSE(outputShapes[0].isSufficient);
-                return;
-        }
-        // Go through all outputs, overwrite output dimensions with returned output shapes
-        if (outputShapes.size() > 0) {
-            for_each<uint32_t>(test.operandDimensions,
-                               [&outputShapes](int idx, std::vector<uint32_t>& dim) {
-                                   dim = outputShapes[idx].dimensions;
-                               });
-        }
+        // retrieve execution status
+        executionCallback->wait();
+        ASSERT_EQ(ErrorStatus::NONE, executionCallback->getStatus());
 
         // validate results
         outputMemory->read();
@@ -360,89 +169,22 @@
 
         // We want "close-enough" results for float
         compare(filtered_golden, filtered_test, fpAtol, fpRtol);
-
-        if (example.expectedMultinomialDistributionTolerance > 0) {
-            expectMultinomialDistributionWithinTolerance(test, example);
-        }
-    }
-}
-template <typename T_IPreparedModel>
-void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
-                           const std::vector<MixedTypedExample>& examples,
-                           bool hasRelaxedFloat32Model, Executor executor, MeasureTiming measure,
-                           OutputType outputType) {
-    EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol,
-                          kDefaultRtol, executor, measure, outputType);
-}
-
-void EvaluatePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
-                           std::function<bool(int)> is_ignored,
-                           const std::vector<MixedTypedExample>& examples,
-                           bool hasRelaxedFloat32Model, bool testDynamicOutputShape) {
-    if (testDynamicOutputShape) {
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::NO, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::YES, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::NO, OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::YES, OutputType::INSUFFICIENT);
-    } else {
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
     }
 }
 
-static void getPreparedModel(sp<PreparedModelCallback> callback,
-                             sp<V1_0::IPreparedModel>* preparedModel) {
-    *preparedModel = callback->getPreparedModel();
-}
-static void getPreparedModel(sp<PreparedModelCallback> callback,
-                             sp<V1_2::IPreparedModel>* preparedModel) {
-    sp<V1_0::IPreparedModel> preparedModelV1_0 = callback->getPreparedModel();
-    *preparedModel = V1_2::IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr);
-}
-
-void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
+void Execute(const sp<IDevice>& device, std::function<Model(void)> create_model,
              std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
-    V1_0::Model model = create_model();
+    Model model = create_model();
 
     // see if service can handle model
     bool fullySupportsModel = false;
     Return<void> supportedCall = device->getSupportedOperations(
-        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
-            ASSERT_EQ(ErrorStatus::NONE, status);
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
+            model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
+                ASSERT_EQ(ErrorStatus::NONE, status);
+                ASSERT_NE(0ul, supported.size());
+                fullySupportsModel = std::all_of(supported.begin(), supported.end(),
+                                                 [](bool valid) { return valid; });
+            });
     ASSERT_TRUE(supportedCall.isOk());
 
     // launch prepare model
@@ -455,8 +197,7 @@
     // retrieve prepared model
     preparedModelCallback->wait();
     ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    sp<V1_0::IPreparedModel> preparedModel;
-    getPreparedModel(preparedModelCallback, &preparedModel);
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
 
     // early termination if vendor service cannot fully prepare model
     if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
@@ -472,115 +213,10 @@
     ASSERT_NE(nullptr, preparedModel.get());
 
     float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f;
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Executor::ASYNC,
-                          MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
-}
-
-void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
-    V1_1::Model model = create_model();
-
-    // see if service can handle model
-    bool fullySupportsModel = false;
-    Return<void> supportedCall = device->getSupportedOperations_1_1(
-        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
-            ASSERT_EQ(ErrorStatus::NONE, status);
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
-    ASSERT_TRUE(supportedCall.isOk());
-
-    // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_1(
-        model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    // retrieve prepared model
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    sp<V1_0::IPreparedModel> preparedModel;
-    getPreparedModel(preparedModelCallback, &preparedModel);
-
-    // early termination if vendor service cannot fully prepare model
-    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
-        ASSERT_EQ(nullptr, preparedModel.get());
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "prepare model that it does not support."
-                  << std::endl;
-        GTEST_SKIP();
-    }
-    EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    ASSERT_NE(nullptr, preparedModel.get());
-
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Executor::ASYNC,
-                          MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
-}
-
-void PrepareModel(const sp<V1_2::IDevice>& device, const V1_2::Model& model,
-                  sp<V1_2::IPreparedModel>* preparedModel) {
-    // see if service can handle model
-    bool fullySupportsModel = false;
-    Return<void> supportedCall = device->getSupportedOperations_1_2(
-        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
-            ASSERT_EQ(ErrorStatus::NONE, status);
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
-    ASSERT_TRUE(supportedCall.isOk());
-
-    // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_2(
-            model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec<hidl_handle>(),
-            hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    // retrieve prepared model
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    getPreparedModel(preparedModelCallback, preparedModel);
-
-    // early termination if vendor service cannot fully prepare model
-    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
-        ASSERT_EQ(nullptr, preparedModel->get());
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "prepare model that it does not support."
-                  << std::endl;
-        return;
-    }
-    EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    ASSERT_NE(nullptr, preparedModel->get());
-}
-
-// TODO: Reduce code duplication.
-void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
-             bool testDynamicOutputShape) {
-    V1_2::Model model = create_model();
-    sp<V1_2::IPreparedModel> preparedModel = nullptr;
-    PrepareModel(device, model, &preparedModel);
-    if (preparedModel == nullptr) {
-        GTEST_SKIP();
-    }
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, testDynamicOutputShape);
+    EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol);
 }
 
 }  // namespace generated_tests
-
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
index c7d2399..11950d9 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
@@ -14,14 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
-#define VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
-
-#include "TestHarness.h"
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_GENERATED_TEST_HARNESS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_GENERATED_TEST_HARNESS_H
 
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
-#include <android/hardware/neuralnetworks/1.1/IDevice.h>
-#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include "TestHarness.h"
 
 namespace android {
 namespace hardware {
@@ -30,28 +27,13 @@
 namespace generated_tests {
 using ::test_helper::MixedTypedExample;
 
-void PrepareModel(const sp<V1_2::IDevice>& device, const V1_2::Model& model,
-                  sp<V1_2::IPreparedModel>* preparedModel);
-
-void EvaluatePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
-                           std::function<bool(int)> is_ignored,
-                           const std::vector<MixedTypedExample>& examples,
-                           bool hasRelaxedFloat32Model, bool testDynamicOutputShape);
-
 void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
              std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples);
 
-void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples);
-
-void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
-             bool testDynamicOutputShape = false);
-
 }  // namespace generated_tests
 
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
 
-#endif  // VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestsV1_0.cpp
similarity index 86%
rename from neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
rename to neuralnetworks/1.0/vts/functional/GeneratedTestsV1_0.cpp
index d1c7de3..74946a5 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestsV1_0.cpp
@@ -16,17 +16,16 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+#include "1.0/Callbacks.h"
+#include "GeneratedTestHarness.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
@@ -34,8 +33,9 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hidl::memory::V1_0::IMemory;
 using ::android::nn::allocateSharedMemory;
 using ::test_helper::MixedTypedExample;
 
diff --git a/neuralnetworks/1.0/vts/functional/Utils.cpp b/neuralnetworks/1.0/vts/functional/Utils.cpp
new file mode 100644
index 0000000..521e524
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Utils.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 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 "GeneratedTestHarness.h"
+#include "TestHarness.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+
+#include <cstring>
+#include <map>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+
+using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
+using ::test_helper::for_each;
+using ::test_helper::MixedTyped;
+
+template <typename T>
+void copy_back_(std::map<int, std::vector<T>>* dst, const std::vector<RequestArgument>& ra,
+                char* src) {
+    for_each<T>(*dst, [&ra, src](int index, std::vector<T>& m) {
+        ASSERT_EQ(m.size(), ra[index].location.length / sizeof(T));
+        char* begin = src + ra[index].location.offset;
+        memcpy(m.data(), begin, ra[index].location.length);
+    });
+}
+
+void copy_back(MixedTyped* dst, const std::vector<RequestArgument>& ra, char* src) {
+    copy_back_(&dst->float32Operands, ra, src);
+    copy_back_(&dst->int32Operands, ra, src);
+    copy_back_(&dst->quant8AsymmOperands, ra, src);
+    copy_back_(&dst->quant16SymmOperands, ra, src);
+    copy_back_(&dst->float16Operands, ra, src);
+    copy_back_(&dst->bool8Operands, ra, src);
+    copy_back_(&dst->quant8ChannelOperands, ra, src);
+    copy_back_(&dst->quant16AsymmOperands, ra, src);
+    copy_back_(&dst->quant8SymmOperands, ra, src);
+    static_assert(9 == MixedTyped::kNumTypes,
+                  "Number of types in MixedTyped changed, but copy_back function wasn't updated");
+}
+
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
index 5d24fb5..72c4a2b 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
@@ -18,7 +18,7 @@
 
 #include "VtsHalNeuralnetworks.h"
 
-#include "Callbacks.h"
+#include "1.0/Callbacks.h"
 
 namespace android {
 namespace hardware {
@@ -27,8 +27,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
diff --git a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
index f0c93b7..058eb25 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
@@ -16,16 +16,15 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+#include "1.0/Callbacks.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
@@ -33,7 +32,7 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
 using ::android::hidl::memory::V1_0::IMemory;
 using test_helper::for_all;
 using test_helper::MixedTyped;
@@ -121,11 +120,13 @@
         for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
             if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
             RequestArgument arg = {
-                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
+                    .location = {.poolIndex = INPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
             };
             RequestArgument arg_empty = {
-                .hasNoValue = true,
+                    .hasNoValue = true,
             };
             inputs_info[index] = s ? arg : arg_empty;
             inputSize += s;
@@ -143,8 +144,10 @@
         for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
             if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
             RequestArgument arg = {
-                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
+                    .location = {.poolIndex = OUTPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
             };
             outputs_info[index] = arg;
             outputSize += s;
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
index aee2f85..95b7ad3 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
@@ -20,7 +20,7 @@
 
 #include <android-base/logging.h>
 
-#include "Callbacks.h"
+#include "1.0/Callbacks.h"
 
 namespace android {
 namespace hardware {
@@ -29,7 +29,7 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
 
 static void createPreparedModel(const sp<IDevice>& device, const V1_0::Model& model,
                                 sp<IPreparedModel>* preparedModel) {
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
index 22285be..c32a91d 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
-#define VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_VTS_HAL_NEURALNETWORKS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_VTS_HAL_NEURALNETWORKS_H
 
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
 #include <android/hardware/neuralnetworks/1.0/types.h>
@@ -89,4 +89,4 @@
 
 }  // namespace android::hardware::neuralnetworks::V1_0
 
-#endif  // VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_VTS_HAL_NEURALNETWORKS_H
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.h b/neuralnetworks/1.0/vts/functional/include/1.0/Callbacks.h
similarity index 64%
copy from neuralnetworks/1.0/vts/functional/Callbacks.h
copy to neuralnetworks/1.0/vts/functional/include/1.0/Callbacks.h
index 4707d0a..36318ea 100644
--- a/neuralnetworks/1.0/vts/functional/Callbacks.h
+++ b/neuralnetworks/1.0/vts/functional/include/1.0/Callbacks.h
@@ -19,9 +19,6 @@
 
 #include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
 #include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
-#include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 #include <chrono>
 #include <condition_variable>
@@ -32,11 +29,9 @@
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-namespace V1_2 {
+namespace V1_0 {
 namespace implementation {
 
-using V1_0::ErrorStatus;
-
 /**
  * The CallbackBase class is used internally by the NeuralNetworks runtime to
  * synchronize between different threads. An asynchronous task is launched
@@ -60,7 +55,7 @@
  * std::condition_variable, or std::experimental::latch instead.
  */
 class CallbackBase {
- public:
+  public:
     CallbackBase();
     ~CallbackBase();
 
@@ -79,8 +74,8 @@
      *                before the time duration expired, std::cv_status::timeout
      *                otherwise.
      */
-    template<class Rep, class Period>
-    std::cv_status wait_for(const std::chrono::duration<Rep,Period>& timeout_duration);
+    template <class Rep, class Period>
+    std::cv_status wait_for(const std::chrono::duration<Rep, Period>& timeout_duration);
 
     /**
      * CallbackBase::on_finish binds a function to the callback object. This
@@ -144,7 +139,7 @@
      */
     void join_thread();
 
- protected:
+  protected:
     /**
      * CallbackBase::notify enables all prior and future wait* calls on the
      * callback object to proceed. The call to CallbackBase::notify happens
@@ -158,16 +153,16 @@
      */
     void notify();
 
- private:
+  private:
     // Same as CallbackBase::join_thread but assumes we already hold a lock on
     // mMutex.
     void join_thread_locked();
 
-    bool                      mNotified;
-    std::mutex                mMutex;
-    std::condition_variable   mCondition;
+    bool mNotified;
+    std::mutex mMutex;
+    std::condition_variable mCondition;
     std::function<bool(void)> mPostWork;
-    std::thread               mThread;
+    std::thread mThread;
 };
 
 /**
@@ -176,29 +171,29 @@
  * asynchronously with respect to the runtime. If a calling thread calls wait*
  * or get* on a PreparedModelCallback object and the corresponding asynchronous
  * task has not finished preparing the model, the calling thread will block
- * until the asynchronous task has either called notify or notify_1_2. For more
- * information on the synchronization behavior, refer to the CallbackBase class.
+ * until the asynchronous task has called notify. For more information on the
+ * synchronization behavior, refer to the CallbackBase class.
  *
  * This class inherits the basic blocking and signaling calls from
- * CallbackBase, and implements the HIDL notify and notify_1_2 calls from
+ * CallbackBase, and implements the HIDL notify call from
  * IPreparedModelCallback. This callback object is passed as an argument to
  * IDevice::prepareModel.
  */
 class PreparedModelCallback : public CallbackBase, public IPreparedModelCallback {
- public:
+  public:
     PreparedModelCallback();
     ~PreparedModelCallback() override;
 
     /**
-     * IPreparedModelCallback::notify and IPreparedModelCallback::notify_1_2
-     * mark the callback object with the return status of the asynchronous
-     * model preparation along with the prepared model, and call
-     * CallbackBase::notify, enabling all prior and future wait* calls on the
-     * PreparedModelCallback object to proceed. For more information on the
-     * synchronization behavior, refer to the CallbackBase class.
+     * IPreparedModelCallback::notify marks the callback object with the return
+     * status of the asynchronous model preparation along with the prepared
+     * model and calls CallbackBase::notify, enabling all prior and future
+     * wait* calls on the PreparedModelCallback object to proceed.
+     * For more information on the synchronization behavior, refer to the
+     * CallbackBase class.
      *
-     * Either IPreparedModelCallback::notify or IPreparedModelCallback::notify_1_2
-     * must be called exactly once on a given PreparedModelCallback object.
+     * IPreparedModelCallback::notify must be called exactly once on a given
+     * PreparedModelCallback object.
      *
      * @param status Error status returned from asynchronously preparing the
      *               model; will be:
@@ -210,8 +205,6 @@
      *                      nullptr if the model was unable to be prepared.
      */
     Return<void> notify(ErrorStatus status, const sp<V1_0::IPreparedModel>& preparedModel) override;
-    Return<void> notify_1_2(ErrorStatus status,
-                            const sp<V1_2::IPreparedModel>& preparedModel) override;
 
     /**
      * Retrieves the error status returned from the asynchronous task launched
@@ -241,8 +234,8 @@
      */
     sp<V1_0::IPreparedModel> getPreparedModel();
 
-   private:
-    ErrorStatus        mErrorStatus;
+  private:
+    ErrorStatus mErrorStatus;
     sp<V1_0::IPreparedModel> mPreparedModel;
 };
 
@@ -251,29 +244,28 @@
  * execution from a task executing asynchronously with respect to the runtime.
  * If a calling thread calls wait* or get* on a PreparedModelCallback object and
  * the corresponding asynchronous task has not finished the execution, the
- * calling thread will block until the asynchronous task has either called notify
- * or notify_1_2. For more information on the synchronization behavior, refer to
- * the CallbackBase class.
+ * calling thread will block until the asynchronous task has called notify.
+ * For more information on the synchronization behavior, refer to the
+ * CallbackBase class.
  *
  * This class inherits the basic blocking and signaling calls from
- * CallbackBase, and implements the HIDL notify and notify_1_2 calls from
- * IExecutionCallback. This callback object is passed as an argument to
- * IPreparedModel::execute.
+ * CallbackBase, and implements the HIDL notify call from IExecutionCallback.
+ * This callback object is passed as an argument to IPreparedModel::execute.
  */
-class ExecutionCallback : public CallbackBase,  public IExecutionCallback {
- public:
+class ExecutionCallback : public CallbackBase, public IExecutionCallback {
+  public:
     ExecutionCallback();
     ~ExecutionCallback() override;
 
     /**
-     * IExecutionCallback::notify and IExecutionCallback::notify_1_2 mark the
-     * callback object with the return status of the asynchronous execution that
-     * held this callback and enable all prior and future wait* calls on the
-     * ExecutionCallback object to proceed. For more information on the
-     * synchronization behavior, refer to the CallbackBase class.
+     * IExecutionCallback::notify marks the callback object with the return
+     * status of the asynchronous execution that held this callback and enable
+     * all prior and future wait* calls on the ExecutionCallback object to
+     * proceed. For more information on the synchronization behavior, refer to
+     * the CallbackBase class.
      *
-     * Either IExecutionCallback::notify or IExecutionCallback::notify_1_2 must
-     * be called exactly once on a given ExecutionCallback object.
+     * IExecutionCallback::notify must be called exactly once on a given
+     * ExecutionCallback object.
      *
      * @param status Error status returned from launching the asynchronous task
      *               (if the launch fails) or from the asynchronous task itself
@@ -288,47 +280,10 @@
     Return<void> notify(ErrorStatus status) override;
 
     /**
-     * Similar to IExecutionCallback::notify, but for V1_2::IPreparedModel to
-     * also notify output shapes along with error status.
-     *
-     * @param status Error status returned from launching the asynchronous task
-     *               (if the launch fails) or from the asynchronous task itself
-     *               (if the launch succeeds). Must be:
-     *               - NONE if the asynchronous execution was successful
-     *               - DEVICE_UNAVAILABLE if driver is offline or busy
-     *               - GENERAL_FAILURE if the asynchronous task resulted in an
-     *                 unspecified error
-     *               - OUTPUT_INSUFFICIENT_SIZE if at least one output
-     *                 operand buffer is not large enough to store the
-     *                 corresponding output
-     *               - INVALID_ARGUMENT if one of the input arguments to
-     *                 prepareModel is invalid
-     * @param outputShapes A list of shape information of model output operands.
-     *                     The index into "outputShapes" corresponds to the index
-     *                     of the output operand in the Request outputs vector.
-     *                     outputShapes must be empty unless the status is either
-     *                     NONE or OUTPUT_INSUFFICIENT_SIZE.
-     * @return Timing Duration of execution. Unless MeasureTiming::YES was passed when
-     *                launching the execution and status is NONE, all times must
-     *                be reported as UINT64_MAX. A driver may choose to report
-     *                any time as UINT64_MAX, indicating that particular measurement is
-     *                not available.
-     */
-    Return<void> notify_1_2(ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
-                            const Timing& timing) override;
-
-    // An overload of the latest notify interface to hide the version from ExecutionBuilder.
-    Return<void> notify(ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
-                        const Timing& timing) {
-        return notify_1_2(status, outputShapes, timing);
-    }
-
-    /**
      * Retrieves the error status returned from the asynchronous task launched
-     * by either IPreparedModel::execute or IPreparedModel::execute_1_2. If
-     * IPreparedModel::execute or IPreparedModel::execute_1_2 has not finished
-     * asynchronously executing, this call will block until the asynchronous task
-     * notifies the object.
+     * by IPreparedModel::execute. If IPreparedModel::execute has not finished
+     * asynchronously executing, this call will block until the asynchronous
+     * task notifies the object.
      *
      * @return status Error status returned from launching the asynchronous task
      *                (if the launch fails) or from the asynchronous task itself
@@ -345,50 +300,17 @@
      */
     ErrorStatus getStatus();
 
-    /**
-     * Retrieves the output shapes returned from the asynchronous task launched
-     * by IPreparedModel::execute_1_2. If IPreparedModel::execute_1_2 has not finished
-     * asynchronously executing, this call will block until the asynchronous task
-     * notifies the object.
-     *
-     * If the asynchronous task was launched by IPreparedModel::execute, an empty vector
-     * will be returned.
-     *
-     * @return outputShapes A list of shape information of model output operands.
-     *                      The index into "outputShapes" corresponds to the index
-     *                      of the output operand in the Request outputs vector.
-     *                      outputShapes must be empty unless the status is either
-     *                      NONE or OUTPUT_INSUFFICIENT_SIZE.
-     */
-    const std::vector<OutputShape>& getOutputShapes();
-
-    /**
-     * Retrieves the duration of execution ofthe asynchronous task launched
-     * by IPreparedModel::execute_1_2. If IPreparedModel::execute_1_2 has not finished
-     * asynchronously executing, this call will block until the asynchronous task
-     * notifies the object.
-     *
-     * If the asynchronous task was launched by IPreparedModel::execute, every time
-     * must be UINT64_MAX.
-     *
-     * @return timing Duration of the execution. Every time must be UINT64_MAX unless
-     *                the status is NONE.
-     */
-    Timing getTiming();
-
-   private:
+  private:
     ErrorStatus mErrorStatus = ErrorStatus::GENERAL_FAILURE;
-    std::vector<OutputShape> mOutputShapes = {};
-    Timing mTiming = {};
 };
 
-
 // template function implementation(s) below this point
 
-template<class Rep, class Period>
-std::cv_status CallbackBase::wait_for(const std::chrono::duration<Rep,Period>& timeout_duration) {
+template <class Rep, class Period>
+std::cv_status CallbackBase::wait_for(const std::chrono::duration<Rep, Period>& timeout_duration) {
     std::unique_lock<std::mutex> lock(mMutex);
-    std::cv_status status = mCondition.wait_for(lock, timeout_duration, [this]{return mNotified;});
+    std::cv_status status =
+            mCondition.wait_for(lock, timeout_duration, [this] { return mNotified; });
     if (status != std::cv_status::timeout) {
         join_thread_locked();
     }
@@ -396,7 +318,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_2
+}  // namespace V1_0
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h b/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h
new file mode 100644
index 0000000..b270c20
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 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_NEURALNETWORKS_V1_0_UTILS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <algorithm>
+#include <vector>
+#include "TestHarness.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+
+void copy_back(::test_helper::MixedTyped* dst, const std::vector<V1_0::RequestArgument>& ra,
+               char* src);
+
+// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
+// so this is efficiently accomplished by moving the element to the end and
+// resizing the hidl_vec to one less.
+template <typename Type>
+inline void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
+    if (vec) {
+        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+        vec->resize(vec->size() - 1);
+    }
+}
+
+template <typename Type>
+inline uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
+    // assume vec is valid
+    const uint32_t index = vec->size();
+    vec->resize(index + 1);
+    (*vec)[index] = value;
+    return index;
+}
+
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 4fbeac9..ee90ec6 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -14,10 +14,41 @@
 // limitations under the License.
 //
 
+cc_defaults {
+    name: "VtsHalNeuralNetworksV1_1TargetTestDefaults",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "ValidateModel.cpp",
+        "ValidateRequest.cpp",
+        "VtsHalNeuralnetworks.cpp",
+        "GeneratedTestHarness.cpp",
+    ],
+    shared_libs: [
+        "libfmq",
+        "libnativewindow",
+    ],
+    static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libgmock",
+        "libhidlmemory",
+        "libneuralnetworks_utils",
+        "VtsHalNeuralNetworksV1_0_utils",
+    ],
+    header_libs: [
+        "libneuralnetworks_headers",
+        "libneuralnetworks_generated_test_harness_headers",
+        "libneuralnetworks_generated_tests",
+    ],
+    test_suites: ["general-tests"],
+}
+
 // Tests for V1_0 models using the V1_1 HAL.
 cc_test {
     name: "VtsHalNeuralnetworksV1_1CompatV1_0TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalNeuralNetworksV1_1TargetTestDefaults"],
     srcs: [
         "GeneratedTestsV1_0.cpp",
     ],
@@ -26,19 +57,19 @@
 // Tests for V1_1 models.
 cc_test {
     name: "VtsHalNeuralnetworksV1_1TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalNeuralNetworksV1_1TargetTestDefaults"],
     srcs: [
         "BasicTests.cpp",
-        "GeneratedTests.cpp",
+        "GeneratedTestsV1_1.cpp",
     ],
 }
 
 cc_test {
     name: "PresubmitHalNeuralnetworksV1_1TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalNeuralNetworksV1_1TargetTestDefaults"],
     srcs: [
         "BasicTests.cpp",
-        "GeneratedTests.cpp",
+        "GeneratedTestsV1_1.cpp",
     ],
     cflags: [
         "-DPRESUBMIT_NOT_VTS",
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
new file mode 100644
index 0000000..d9f64fd
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GeneratedTestHarness.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+#include <iostream>
+
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace generated_tests {
+
+using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
+using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
+using ::android::hardware::neuralnetworks::V1_0::Request;
+using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_1::ExecutionPreference;
+using ::android::hardware::neuralnetworks::V1_1::IDevice;
+using ::android::hardware::neuralnetworks::V1_1::Model;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::test_helper::compare;
+using ::test_helper::filter;
+using ::test_helper::for_all;
+using ::test_helper::MixedTyped;
+using ::test_helper::MixedTypedExample;
+using ::test_helper::resize_accordingly;
+
+// Top level driver for models and examples generated by test_generator.py
+// Test driver for those generated from ml/nn/runtime/test/spec
+void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
+                           const std::vector<MixedTypedExample>& examples,
+                           bool hasRelaxedFloat32Model, float fpAtol, float fpRtol) {
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+
+    int example_no = 1;
+    for (auto& example : examples) {
+        SCOPED_TRACE(example_no++);
+        const MixedTyped& inputs = example.operands.first;
+        const MixedTyped& golden = example.operands.second;
+
+        const bool hasFloat16Inputs = !inputs.float16Operands.empty();
+        if (hasRelaxedFloat32Model || hasFloat16Inputs) {
+            // TODO: Adjust the error limit based on testing.
+            // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16.
+            fpAtol = 5.0f * 0.0009765625f;
+            // Set the relative tolerance to be 5ULP of the corresponding FP precision.
+            fpRtol = 5.0f * 0.0009765625f;
+        }
+
+        std::vector<RequestArgument> inputs_info, outputs_info;
+        uint32_t inputSize = 0, outputSize = 0;
+        // This function only partially specifies the metadata (vector of RequestArguments).
+        // The contents are copied over below.
+        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
+            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
+            RequestArgument arg = {
+                    .location = {.poolIndex = INPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
+            };
+            RequestArgument arg_empty = {
+                    .hasNoValue = true,
+            };
+            inputs_info[index] = s ? arg : arg_empty;
+            inputSize += s;
+        });
+        // Compute offset for inputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : inputs_info) {
+                if (!i.hasNoValue) i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+
+        MixedTyped test;  // holding test results
+
+        // Go through all outputs, initialize RequestArgument descriptors
+        resize_accordingly(golden, test);
+        for_all(golden, [&outputs_info, &outputSize](int index, auto, auto s) {
+            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
+            RequestArgument arg = {
+                    .location = {.poolIndex = OUTPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
+            };
+            outputs_info[index] = arg;
+            outputSize += s;
+        });
+        // Compute offset for outputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : outputs_info) {
+                i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
+                                          nn::allocateSharedMemory(outputSize)};
+        ASSERT_NE(0ull, pools[INPUT].size());
+        ASSERT_NE(0ull, pools[OUTPUT].size());
+
+        // load data
+        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
+        sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
+        ASSERT_NE(nullptr, inputMemory.get());
+        ASSERT_NE(nullptr, outputMemory.get());
+        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
+        char* outputPtr = reinterpret_cast<char*>(static_cast<void*>(outputMemory->getPointer()));
+        ASSERT_NE(nullptr, inputPtr);
+        ASSERT_NE(nullptr, outputPtr);
+        inputMemory->update();
+        outputMemory->update();
+
+        // Go through all inputs, copy the values
+        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
+            char* begin = (char*)p;
+            char* end = begin + s;
+            // TODO: handle more than one input
+            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
+        });
+
+        inputMemory->commit();
+        outputMemory->commit();
+
+        const Request request = {.inputs = inputs_info, .outputs = outputs_info, .pools = pools};
+
+        // launch execution
+        sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+        ASSERT_NE(nullptr, executionCallback.get());
+        Return<ErrorStatus> executionLaunchStatus =
+                preparedModel->execute(request, executionCallback);
+        ASSERT_TRUE(executionLaunchStatus.isOk());
+        EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
+
+        // retrieve execution status
+        executionCallback->wait();
+        ASSERT_EQ(ErrorStatus::NONE, executionCallback->getStatus());
+
+        // validate results
+        outputMemory->read();
+        copy_back(&test, outputs_info, outputPtr);
+        outputMemory->commit();
+        // Filter out don't cares
+        MixedTyped filtered_golden = filter(golden, is_ignored);
+        MixedTyped filtered_test = filter(test, is_ignored);
+
+        // We want "close-enough" results for float
+        compare(filtered_golden, filtered_test, fpAtol, fpRtol);
+    }
+}
+
+void Execute(const sp<IDevice>& device, std::function<Model(void)> create_model,
+             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
+    Model model = create_model();
+
+    // see if service can handle model
+    bool fullySupportsModel = false;
+    Return<void> supportedCall = device->getSupportedOperations_1_1(
+            model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
+                ASSERT_EQ(ErrorStatus::NONE, status);
+                ASSERT_NE(0ul, supported.size());
+                fullySupportsModel = std::all_of(supported.begin(), supported.end(),
+                                                 [](bool valid) { return valid; });
+            });
+    ASSERT_TRUE(supportedCall.isOk());
+
+    // launch prepare model
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_1(
+            model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+
+    // early termination if vendor service cannot fully prepare model
+    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
+        ASSERT_EQ(nullptr, preparedModel.get());
+        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+                     "prepare model that it does not support.";
+        std::cout << "[          ]   Early termination of test because vendor service cannot "
+                     "prepare model that it does not support."
+                  << std::endl;
+        GTEST_SKIP();
+    }
+    EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    ASSERT_NE(nullptr, preparedModel.get());
+
+    EvaluatePreparedModel(preparedModel, is_ignored, examples,
+                          model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f);
+}
+
+}  // namespace generated_tests
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
new file mode 100644
index 0000000..ab71b2b
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 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_NEURALNETWORKS_V1_1_GENERATED_TEST_HARNESS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_1_GENERATED_TEST_HARNESS_H
+
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <functional>
+#include <vector>
+#include "TestHarness.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace generated_tests {
+
+void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
+             std::function<bool(int)> is_ignored,
+             const std::vector<::test_helper::MixedTypedExample>& examples);
+
+}  // namespace generated_tests
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_1_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
index e67ef8e..10cf5a9 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
@@ -16,17 +16,16 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+#include "1.0/Callbacks.h"
+#include "GeneratedTestHarness.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
@@ -34,8 +33,10 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hidl::memory::V1_0::IMemory;
 using ::android::nn::allocateSharedMemory;
 using ::test_helper::MixedTypedExample;
 
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_1.cpp
similarity index 83%
rename from neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
rename to neuralnetworks/1.1/vts/functional/GeneratedTestsV1_1.cpp
index 4db1276..079c18c 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_1.cpp
@@ -16,17 +16,16 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+#include "1.0/Callbacks.h"
+#include "GeneratedTestHarness.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
@@ -34,8 +33,10 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hidl::memory::V1_0::IMemory;
 using ::android::nn::allocateSharedMemory;
 using ::test_helper::MixedTypedExample;
 
diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
index b35a901..fb80d13 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
@@ -16,25 +16,22 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
 #include "VtsHalNeuralnetworks.h"
 
-#include "Callbacks.h"
-
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
 namespace V1_1 {
-
-using V1_0::IPreparedModel;
-using V1_0::Operand;
-using V1_0::OperandLifeTime;
-using V1_0::OperandType;
-
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
+using ::android::hardware::neuralnetworks::V1_0::Operand;
+using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
+using ::android::hardware::neuralnetworks::V1_0::OperandType;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
@@ -42,10 +39,10 @@
                                            const V1_1::Model& model) {
     SCOPED_TRACE(message + " [getSupportedOperations_1_1]");
 
-    Return<void> ret =
-        device->getSupportedOperations_1_1(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-        });
+    Return<void> ret = device->getSupportedOperations_1_1(
+            model, [&](ErrorStatus status, const hidl_vec<bool>&) {
+                EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+            });
     EXPECT_TRUE(ret.isOk());
 }
 
@@ -56,7 +53,7 @@
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
     ASSERT_NE(nullptr, preparedModelCallback.get());
     Return<ErrorStatus> prepareLaunchStatus =
-        device->prepareModel_1_1(model, preference, preparedModelCallback);
+            device->prepareModel_1_1(model, preference, preparedModelCallback);
     ASSERT_TRUE(prepareLaunchStatus.isOk());
     ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
 
@@ -87,36 +84,16 @@
     validatePrepareModel(device, message, model, preference);
 }
 
-// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
-// so this is efficiently accomplished by moving the element to the end and
-// resizing the hidl_vec to one less.
-template <typename Type>
-static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
-    if (vec) {
-        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
-        vec->resize(vec->size() - 1);
-    }
-}
-
-template <typename Type>
-static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
-    // assume vec is valid
-    const uint32_t index = vec->size();
-    vec->resize(index + 1);
-    (*vec)[index] = value;
-    return index;
-}
-
 static uint32_t addOperand(Model* model) {
     return hidl_vec_push_back(&model->operands,
                               {
-                                  .type = OperandType::INT32,
-                                  .dimensions = {},
-                                  .numberOfConsumers = 0,
-                                  .scale = 0.0f,
-                                  .zeroPoint = 0,
-                                  .lifetime = OperandLifeTime::MODEL_INPUT,
-                                  .location = {.poolIndex = 0, .offset = 0, .length = 0},
+                                      .type = OperandType::INT32,
+                                      .dimensions = {},
+                                      .numberOfConsumers = 0,
+                                      .scale = 0.0f,
+                                      .zeroPoint = 0,
+                                      .lifetime = OperandLifeTime::MODEL_INPUT,
+                                      .location = {.poolIndex = 0, .offset = 0, .length = 0},
                               });
 }
 
@@ -130,10 +107,10 @@
 ///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
 
 static const int32_t invalidOperandTypes[] = {
-    static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
-    static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
-    static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
-    static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
+        static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
+        static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
+        static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
+        static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
 };
 
 static void mutateOperandTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
@@ -226,7 +203,7 @@
 static void mutateOperandZeroPointTest(const sp<IDevice>& device, const V1_1::Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const std::vector<int32_t> invalidZeroPoints =
-            getInvalidZeroPoints(model.operands[operand].type);
+                getInvalidZeroPoints(model.operands[operand].type);
         for (int32_t invalidZeroPoint : invalidZeroPoints) {
             const std::string message = "mutateOperandZeroPointTest: operand " +
                                         std::to_string(operand) + " has zero point of " +
@@ -258,18 +235,18 @@
             break;
         case OperandType::TENSOR_FLOAT32:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = 0.0f;
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_INT32:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_QUANT8_ASYMM:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
             break;
         case OperandType::OEM:
@@ -319,10 +296,10 @@
 ///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
 
 static const int32_t invalidOperationTypes[] = {
-    static_cast<int32_t>(OperationType::ADD) - 1,            // lower bound fundamental
-    static_cast<int32_t>(OperationType::TRANSPOSE) + 1,      // upper bound fundamental
-    static_cast<int32_t>(OperationType::OEM_OPERATION) - 1,  // lower bound OEM
-    static_cast<int32_t>(OperationType::OEM_OPERATION) + 1,  // upper bound OEM
+        static_cast<int32_t>(OperationType::ADD) - 1,            // lower bound fundamental
+        static_cast<int32_t>(OperationType::TRANSPOSE) + 1,      // upper bound fundamental
+        static_cast<int32_t>(OperationType::OEM_OPERATION) - 1,  // lower bound OEM
+        static_cast<int32_t>(OperationType::OEM_OPERATION) + 1,  // upper bound OEM
 };
 
 static void mutateOperationTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
@@ -333,7 +310,7 @@
                                         std::to_string(invalidOperationType);
             validate(device, message, model, [operation, invalidOperationType](Model* model) {
                 model->operations[operation].type =
-                    static_cast<OperationType>(invalidOperationType);
+                        static_cast<OperationType>(invalidOperationType);
             });
         }
     }
@@ -486,7 +463,7 @@
 static void addOperationOutputTest(const sp<IDevice>& device, const V1_1::Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message =
-            "addOperationOutputTest: operation " + std::to_string(operation);
+                "addOperationOutputTest: operation " + std::to_string(operation);
         validate(device, message, model, [operation](Model* model) {
             uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
             hidl_vec_push_back(&model->operations[operation].outputs, index);
@@ -498,14 +475,14 @@
 ///////////////////////// VALIDATE EXECUTION PREFERENCE /////////////////////////
 
 static const int32_t invalidExecutionPreferences[] = {
-    static_cast<int32_t>(ExecutionPreference::LOW_POWER) - 1,        // lower bound
-    static_cast<int32_t>(ExecutionPreference::SUSTAINED_SPEED) + 1,  // upper bound
+        static_cast<int32_t>(ExecutionPreference::LOW_POWER) - 1,        // lower bound
+        static_cast<int32_t>(ExecutionPreference::SUSTAINED_SPEED) + 1,  // upper bound
 };
 
 static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const V1_1::Model& model) {
     for (int32_t preference : invalidExecutionPreferences) {
         const std::string message =
-            "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
+                "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
         validate(device, message, model, [](Model*) {},
                  static_cast<ExecutionPreference>(preference));
     }
diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
index f4adbab..c549728 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
@@ -16,16 +16,16 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
@@ -33,11 +33,15 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
+using ::android::hardware::neuralnetworks::V1_0::Request;
+using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_1::IPreparedModel;
 using ::android::hidl::memory::V1_0::IMemory;
-using test_helper::for_all;
-using test_helper::MixedTyped;
-using test_helper::MixedTypedExample;
+using ::test_helper::for_all;
+using ::test_helper::MixedTyped;
+using ::test_helper::MixedTypedExample;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
@@ -61,26 +65,6 @@
     ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
 }
 
-// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
-// so this is efficiently accomplished by moving the element to the end and
-// resizing the hidl_vec to one less.
-template <typename Type>
-static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
-    if (vec) {
-        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
-        vec->resize(vec->size() - 1);
-    }
-}
-
-template <typename Type>
-static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
-    // assume vec is valid
-    const uint32_t index = vec->size();
-    vec->resize(index + 1);
-    (*vec)[index] = value;
-    return index;
-}
-
 ///////////////////////// REMOVE INPUT ////////////////////////////////////
 
 static void removeInputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
@@ -121,11 +105,13 @@
         for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
             if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
             RequestArgument arg = {
-                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
+                    .location = {.poolIndex = INPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
             };
             RequestArgument arg_empty = {
-                .hasNoValue = true,
+                    .hasNoValue = true,
             };
             inputs_info[index] = s ? arg : arg_empty;
             inputSize += s;
@@ -143,8 +129,10 @@
         for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
             if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
             RequestArgument arg = {
-                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
+                    .location = {.poolIndex = OUTPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
             };
             outputs_info[index] = arg;
             outputSize += s;
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
index 08069f2..12bdd3f 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
@@ -20,7 +20,7 @@
 
 #include <android-base/logging.h>
 
-#include "Callbacks.h"
+#include "1.0/Callbacks.h"
 
 namespace android {
 namespace hardware {
@@ -29,7 +29,7 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
 
 static void createPreparedModel(const sp<IDevice>& device, const V1_1::Model& model,
                                 sp<IPreparedModel>* preparedModel) {
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
index f3f587b..3156784 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef VTS_HAL_NEURALNETWORKS_V1_1_H
-#define VTS_HAL_NEURALNETWORKS_V1_1_H
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_1_VTS_HAL_NEURALNETWORKS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_1_VTS_HAL_NEURALNETWORKS_H
 
 #include <android/hardware/neuralnetworks/1.0/types.h>
 #include <android/hardware/neuralnetworks/1.1/IDevice.h>
@@ -98,4 +98,4 @@
 
 }  // namespace android::hardware::neuralnetworks::V1_0
 
-#endif  // VTS_HAL_NEURALNETWORKS_V1_1_H
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_1_VTS_HAL_NEURALNETWORKS_H
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 6c26820..b48646f 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -14,10 +14,44 @@
 // limitations under the License.
 //
 
+cc_defaults {
+    name: "VtsHalNeuralNetworksV1_2TargetTestDefaults",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "ValidateModel.cpp",
+        "ValidateRequest.cpp",
+        "VtsHalNeuralnetworks.cpp",
+        "Callbacks.cpp",
+        "GeneratedTestHarness.cpp",
+    ],
+    local_include_dirs: ["include"],
+    shared_libs: [
+        "libfmq",
+        "libnativewindow",
+    ],
+    static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hardware.neuralnetworks@1.2",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libgmock",
+        "libhidlmemory",
+        "libneuralnetworks_utils",
+        "VtsHalNeuralNetworksV1_0_utils",
+    ],
+    header_libs: [
+        "libneuralnetworks_headers",
+        "libneuralnetworks_generated_test_harness_headers",
+        "libneuralnetworks_generated_tests",
+    ],
+    test_suites: ["general-tests"],
+}
+
 // Tests for V1_0 models using the V1_2 HAL.
 cc_test {
     name: "VtsHalNeuralnetworksV1_2CompatV1_0TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalNeuralNetworksV1_2TargetTestDefaults"],
     srcs: [
         "GeneratedTestsV1_0.cpp",
         "ValidateBurst.cpp",
@@ -30,7 +64,7 @@
 // Tests for V1_1 models using the V1_2 HAL.
 cc_test {
     name: "VtsHalNeuralnetworksV1_2CompatV1_1TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalNeuralNetworksV1_2TargetTestDefaults"],
     srcs: [
         "GeneratedTestsV1_1.cpp",
         "ValidateBurst.cpp",
@@ -43,11 +77,11 @@
 // Tests for V1_2 models.
 cc_test {
     name: "VtsHalNeuralnetworksV1_2TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalNeuralNetworksV1_2TargetTestDefaults"],
     srcs: [
         "BasicTests.cpp",
         "CompilationCachingTests.cpp",
-        "GeneratedTests.cpp",
+        "GeneratedTestsV1_2.cpp",
         "ValidateBurst.cpp",
     ],
     cflags: [
@@ -57,10 +91,10 @@
 
 cc_test {
     name: "PresubmitHalNeuralnetworksV1_2TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalNeuralNetworksV1_2TargetTestDefaults"],
     srcs: [
         "BasicTests.cpp",
-        "GeneratedTests.cpp",
+        "GeneratedTestsV1_2.cpp",
         "ValidateBurst.cpp",
     ],
     cflags: [
diff --git a/neuralnetworks/1.2/vts/functional/Callbacks.cpp b/neuralnetworks/1.2/vts/functional/Callbacks.cpp
new file mode 100644
index 0000000..cfaf91d
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/Callbacks.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2019 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 "1.2/Callbacks.h"
+#include <android-base/logging.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_2 {
+namespace implementation {
+
+CallbackBase::CallbackBase() : mNotified(false) {}
+
+CallbackBase::~CallbackBase() {
+    // Note that we cannot call CallbackBase::join_thread from here:
+    // CallbackBase is intended to be reference counted, and it is possible that
+    // the reference count drops to zero in the bound thread, causing the
+    // bound thread to call this destructor. If a thread tries to join
+    // itself, it throws an exception, producing a message like the
+    // following:
+    //
+    //     terminating with uncaught exception of type std::__1::system_error:
+    //     thread::join failed: Resource deadlock would occur
+}
+
+void CallbackBase::wait() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mCondition.wait(lock, [this] { return mNotified; });
+    join_thread_locked();
+}
+
+bool CallbackBase::on_finish(std::function<bool(void)> post_work) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mPostWork != nullptr) {
+        LOG(ERROR) << "CallbackBase::on_finish -- a post-work function has already been bound to "
+                      "this callback object";
+        return false;
+    }
+    if (post_work == nullptr) {
+        LOG(ERROR) << "CallbackBase::on_finish -- the new post-work function is invalid";
+        return false;
+    }
+    mPostWork = std::move(post_work);
+    return true;
+}
+
+bool CallbackBase::bind_thread(std::thread&& asyncThread) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mThread.joinable()) {
+        LOG(ERROR) << "CallbackBase::bind_thread -- a thread has already been bound to this "
+                      "callback object";
+        return false;
+    }
+    if (!asyncThread.joinable()) {
+        LOG(ERROR) << "CallbackBase::bind_thread -- the new thread is not joinable";
+        return false;
+    }
+    mThread = std::move(asyncThread);
+    return true;
+}
+
+void CallbackBase::join_thread() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    join_thread_locked();
+}
+
+void CallbackBase::notify() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mNotified = true;
+        if (mPostWork != nullptr) {
+            bool success = mPostWork();
+            if (!success) {
+                LOG(ERROR) << "CallbackBase::notify -- post work failed";
+            }
+        }
+    }
+    mCondition.notify_all();
+}
+
+void CallbackBase::join_thread_locked() {
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+PreparedModelCallback::PreparedModelCallback()
+    : mErrorStatus(ErrorStatus::GENERAL_FAILURE), mPreparedModel(nullptr) {}
+
+PreparedModelCallback::~PreparedModelCallback() {}
+
+Return<void> PreparedModelCallback::notify(ErrorStatus errorStatus,
+                                           const sp<V1_0::IPreparedModel>& preparedModel) {
+    mErrorStatus = errorStatus;
+    mPreparedModel = preparedModel;
+    CallbackBase::notify();
+    return Void();
+}
+
+Return<void> PreparedModelCallback::notify_1_2(ErrorStatus errorStatus,
+                                               const sp<V1_2::IPreparedModel>& preparedModel) {
+    mErrorStatus = errorStatus;
+    mPreparedModel = preparedModel;
+    CallbackBase::notify();
+    return Void();
+}
+
+ErrorStatus PreparedModelCallback::getStatus() {
+    wait();
+    return mErrorStatus;
+}
+
+sp<V1_0::IPreparedModel> PreparedModelCallback::getPreparedModel() {
+    wait();
+    return mPreparedModel;
+}
+
+ExecutionCallback::ExecutionCallback() : mErrorStatus(ErrorStatus::GENERAL_FAILURE) {}
+
+ExecutionCallback::~ExecutionCallback() {}
+
+Return<void> ExecutionCallback::notify(ErrorStatus errorStatus) {
+    mErrorStatus = errorStatus;
+    mOutputShapes = {};
+    mTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX};
+    CallbackBase::notify();
+    return Void();
+}
+
+Return<void> ExecutionCallback::notify_1_2(ErrorStatus errorStatus,
+                                           const hidl_vec<OutputShape>& outputShapes,
+                                           const Timing& timing) {
+    mErrorStatus = errorStatus;
+    mOutputShapes = outputShapes;
+    mTiming = timing;
+    CallbackBase::notify();
+    return Void();
+}
+
+ErrorStatus ExecutionCallback::getStatus() {
+    wait();
+    return mErrorStatus;
+}
+
+const std::vector<OutputShape>& ExecutionCallback::getOutputShapes() {
+    wait();
+    return mOutputShapes;
+}
+
+Timing ExecutionCallback::getTiming() {
+    wait();
+    return mTiming;
+}
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index 4411b90..9cabb7b 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -27,8 +27,9 @@
 #include <cstdlib>
 #include <random>
 
-#include "Callbacks.h"
+#include "1.2/Callbacks.h"
 #include "GeneratedTestHarness.h"
+#include "MemoryUtils.h"
 #include "TestHarness.h"
 #include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
new file mode 100644
index 0000000..c3578cd
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2019 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 "GeneratedTestHarness.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/IDevice.h>
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+#include <iostream>
+
+#include "1.0/Utils.h"
+#include "1.2/Callbacks.h"
+#include "ExecutionBurstController.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "Utils.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace generated_tests {
+
+using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
+using ::android::hardware::neuralnetworks::V1_0::Request;
+using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
+using ::android::hardware::neuralnetworks::V1_1::ExecutionPreference;
+using ::android::hardware::neuralnetworks::V1_2::IDevice;
+using ::android::hardware::neuralnetworks::V1_2::IPreparedModel;
+using ::android::hardware::neuralnetworks::V1_2::Model;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::test_helper::compare;
+using ::test_helper::expectMultinomialDistributionWithinTolerance;
+using ::test_helper::filter;
+using ::test_helper::for_all;
+using ::test_helper::for_each;
+using ::test_helper::MixedTyped;
+using ::test_helper::MixedTypedExample;
+using ::test_helper::resize_accordingly;
+using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
+
+static bool isZeroSized(const MixedTyped& example, uint32_t index) {
+    for (auto i : example.operandDimensions.at(index)) {
+        if (i == 0) return true;
+    }
+    return false;
+}
+
+static Return<ErrorStatus> ExecutePreparedModel(sp<IPreparedModel>& preparedModel,
+                                                const Request& request, MeasureTiming measure,
+                                                sp<ExecutionCallback>& callback) {
+    return preparedModel->execute_1_2(request, measure, callback);
+}
+static Return<ErrorStatus> ExecutePreparedModel(sp<IPreparedModel>& preparedModel,
+                                                const Request& request, MeasureTiming measure,
+                                                hidl_vec<OutputShape>* outputShapes,
+                                                Timing* timing) {
+    ErrorStatus result;
+    Return<void> ret = preparedModel->executeSynchronously(
+            request, measure,
+            [&result, outputShapes, timing](ErrorStatus error, const hidl_vec<OutputShape>& shapes,
+                                            const Timing& time) {
+                result = error;
+                *outputShapes = shapes;
+                *timing = time;
+            });
+    if (!ret.isOk()) {
+        return ErrorStatus::GENERAL_FAILURE;
+    }
+    return result;
+}
+static std::shared_ptr<::android::nn::ExecutionBurstController> CreateBurst(
+        const sp<IPreparedModel>& preparedModel) {
+    return ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true);
+}
+enum class Executor { ASYNC, SYNC, BURST };
+enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
+const float kDefaultAtol = 1e-5f;
+const float kDefaultRtol = 1e-5f;
+void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
+                           const std::vector<MixedTypedExample>& examples,
+                           bool hasRelaxedFloat32Model, float fpAtol, float fpRtol,
+                           Executor executor, MeasureTiming measure, OutputType outputType) {
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+
+    int example_no = 1;
+    for (auto& example : examples) {
+        SCOPED_TRACE(example_no++);
+        const MixedTyped& inputs = example.operands.first;
+        const MixedTyped& golden = example.operands.second;
+
+        const bool hasFloat16Inputs = !inputs.float16Operands.empty();
+        if (hasRelaxedFloat32Model || hasFloat16Inputs) {
+            // TODO: Adjust the error limit based on testing.
+            // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16.
+            fpAtol = 5.0f * 0.0009765625f;
+            // Set the relative tolerance to be 5ULP of the corresponding FP precision.
+            fpRtol = 5.0f * 0.0009765625f;
+        }
+
+        std::vector<RequestArgument> inputs_info, outputs_info;
+        uint32_t inputSize = 0, outputSize = 0;
+        // This function only partially specifies the metadata (vector of RequestArguments).
+        // The contents are copied over below.
+        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
+            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
+            RequestArgument arg = {
+                    .location = {.poolIndex = INPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
+            };
+            RequestArgument arg_empty = {
+                    .hasNoValue = true,
+            };
+            inputs_info[index] = s ? arg : arg_empty;
+            inputSize += s;
+        });
+        // Compute offset for inputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : inputs_info) {
+                if (!i.hasNoValue) i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+
+        MixedTyped test;  // holding test results
+
+        // Go through all outputs, initialize RequestArgument descriptors
+        resize_accordingly(golden, test);
+        bool sizeLargerThanOne = true;
+        for_all(golden, [&golden, &outputs_info, &outputSize, &outputType, &sizeLargerThanOne](
+                                int index, auto, auto s) {
+            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
+            if (index == 0) {
+                // On OutputType::INSUFFICIENT, set the output operand with index 0 with
+                // buffer size one byte less than needed.
+                if (outputType == OutputType::INSUFFICIENT) {
+                    if (s > 1 && !isZeroSized(golden, index)) {
+                        s -= 1;
+                    } else {
+                        sizeLargerThanOne = false;
+                    }
+                }
+            }
+            RequestArgument arg = {
+                    .location = {.poolIndex = OUTPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
+            };
+            outputs_info[index] = arg;
+            outputSize += s;
+        });
+        // If output0 does not have size larger than one byte,
+        // we can not provide an insufficient buffer
+        if (!sizeLargerThanOne && outputType == OutputType::INSUFFICIENT) return;
+        // Compute offset for outputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : outputs_info) {
+                i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
+                                          nn::allocateSharedMemory(outputSize)};
+        ASSERT_NE(0ull, pools[INPUT].size());
+        ASSERT_NE(0ull, pools[OUTPUT].size());
+
+        // load data
+        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
+        sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
+        ASSERT_NE(nullptr, inputMemory.get());
+        ASSERT_NE(nullptr, outputMemory.get());
+        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
+        char* outputPtr = reinterpret_cast<char*>(static_cast<void*>(outputMemory->getPointer()));
+        ASSERT_NE(nullptr, inputPtr);
+        ASSERT_NE(nullptr, outputPtr);
+        inputMemory->update();
+        outputMemory->update();
+
+        // Go through all inputs, copy the values
+        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
+            char* begin = (char*)p;
+            char* end = begin + s;
+            // TODO: handle more than one input
+            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
+        });
+
+        inputMemory->commit();
+        outputMemory->commit();
+
+        const Request request = {.inputs = inputs_info, .outputs = outputs_info, .pools = pools};
+
+        ErrorStatus executionStatus;
+        hidl_vec<OutputShape> outputShapes;
+        Timing timing;
+        switch (executor) {
+            case Executor::ASYNC: {
+                SCOPED_TRACE("asynchronous");
+
+                // launch execution
+                sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+                ASSERT_NE(nullptr, executionCallback.get());
+                Return<ErrorStatus> executionLaunchStatus =
+                        ExecutePreparedModel(preparedModel, request, measure, executionCallback);
+                ASSERT_TRUE(executionLaunchStatus.isOk());
+                EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
+
+                // retrieve execution status
+                executionCallback->wait();
+                executionStatus = executionCallback->getStatus();
+                outputShapes = executionCallback->getOutputShapes();
+                timing = executionCallback->getTiming();
+
+                break;
+            }
+            case Executor::SYNC: {
+                SCOPED_TRACE("synchronous");
+
+                // execute
+                Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
+                        preparedModel, request, measure, &outputShapes, &timing);
+                ASSERT_TRUE(executionReturnStatus.isOk());
+                executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
+
+                break;
+            }
+            case Executor::BURST: {
+                SCOPED_TRACE("burst");
+
+                // create burst
+                const std::shared_ptr<::android::nn::ExecutionBurstController> controller =
+                        CreateBurst(preparedModel);
+                ASSERT_NE(nullptr, controller.get());
+
+                // create memory keys
+                std::vector<intptr_t> keys(request.pools.size());
+                for (size_t i = 0; i < keys.size(); ++i) {
+                    keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
+                }
+
+                // execute burst
+                std::tie(executionStatus, outputShapes, timing) =
+                        controller->compute(request, measure, keys);
+
+                break;
+            }
+        }
+
+        if (outputType != OutputType::FULLY_SPECIFIED &&
+            executionStatus == ErrorStatus::GENERAL_FAILURE) {
+            LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+                         "execute model that it does not support.";
+            std::cout << "[          ]   Early termination of test because vendor service cannot "
+                         "execute model that it does not support."
+                      << std::endl;
+            GTEST_SKIP();
+        }
+        if (measure == MeasureTiming::NO) {
+            EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
+            EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
+        } else {
+            if (timing.timeOnDevice != UINT64_MAX && timing.timeInDriver != UINT64_MAX) {
+                EXPECT_LE(timing.timeOnDevice, timing.timeInDriver);
+            }
+        }
+
+        switch (outputType) {
+            case OutputType::FULLY_SPECIFIED:
+                // If the model output operands are fully specified, outputShapes must be either
+                // either empty, or have the same number of elements as the number of outputs.
+                ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+                ASSERT_TRUE(outputShapes.size() == 0 ||
+                            outputShapes.size() == test.operandDimensions.size());
+                break;
+            case OutputType::UNSPECIFIED:
+                // If the model output operands are not fully specified, outputShapes must have
+                // the same number of elements as the number of outputs.
+                ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+                ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
+                break;
+            case OutputType::INSUFFICIENT:
+                ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
+                ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
+                ASSERT_FALSE(outputShapes[0].isSufficient);
+                return;
+        }
+        // Go through all outputs, overwrite output dimensions with returned output shapes
+        if (outputShapes.size() > 0) {
+            for_each<uint32_t>(test.operandDimensions,
+                               [&outputShapes](int idx, std::vector<uint32_t>& dim) {
+                                   dim = outputShapes[idx].dimensions;
+                               });
+        }
+
+        // validate results
+        outputMemory->read();
+        copy_back(&test, outputs_info, outputPtr);
+        outputMemory->commit();
+        // Filter out don't cares
+        MixedTyped filtered_golden = filter(golden, is_ignored);
+        MixedTyped filtered_test = filter(test, is_ignored);
+
+        // We want "close-enough" results for float
+        compare(filtered_golden, filtered_test, fpAtol, fpRtol);
+
+        if (example.expectedMultinomialDistributionTolerance > 0) {
+            expectMultinomialDistributionWithinTolerance(test, example);
+        }
+    }
+}
+void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
+                           const std::vector<MixedTypedExample>& examples,
+                           bool hasRelaxedFloat32Model, Executor executor, MeasureTiming measure,
+                           OutputType outputType) {
+    EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol,
+                          kDefaultRtol, executor, measure, outputType);
+}
+
+void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
+                           const std::vector<MixedTypedExample>& examples,
+                           bool hasRelaxedFloat32Model, bool testDynamicOutputShape) {
+    if (testDynamicOutputShape) {
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::NO, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::YES, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::NO, OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::YES, OutputType::INSUFFICIENT);
+    } else {
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
+    }
+}
+
+void PrepareModel(const sp<IDevice>& device, const Model& model,
+                  sp<IPreparedModel>* preparedModel) {
+    // see if service can handle model
+    bool fullySupportsModel = false;
+    Return<void> supportedCall = device->getSupportedOperations_1_2(
+            model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
+                ASSERT_EQ(ErrorStatus::NONE, status);
+                ASSERT_NE(0ul, supported.size());
+                fullySupportsModel = std::all_of(supported.begin(), supported.end(),
+                                                 [](bool valid) { return valid; });
+            });
+    ASSERT_TRUE(supportedCall.isOk());
+
+    // launch prepare model
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_2(
+            model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec<hidl_handle>(),
+            hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    sp<V1_0::IPreparedModel> preparedModelV1_0 = preparedModelCallback->getPreparedModel();
+    *preparedModel = IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr);
+
+    // early termination if vendor service cannot fully prepare model
+    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
+        ASSERT_EQ(nullptr, preparedModel->get());
+        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+                     "prepare model that it does not support.";
+        std::cout << "[          ]   Early termination of test because vendor service cannot "
+                     "prepare model that it does not support."
+                  << std::endl;
+        return;
+    }
+    EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    ASSERT_NE(nullptr, preparedModel->get());
+}
+
+void Execute(const sp<IDevice>& device, std::function<Model(void)> create_model,
+             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
+             bool testDynamicOutputShape) {
+    Model model = create_model();
+    sp<IPreparedModel> preparedModel = nullptr;
+    PrepareModel(device, model, &preparedModel);
+    if (preparedModel == nullptr) {
+        GTEST_SKIP();
+    }
+    EvaluatePreparedModel(preparedModel, is_ignored, examples,
+                          model.relaxComputationFloat32toFloat16, testDynamicOutputShape);
+}
+
+}  // namespace generated_tests
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
new file mode 100644
index 0000000..30e5578
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 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_NEURALNETWORKS_V1_2_GENERATED_TEST_HARNESS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_2_GENERATED_TEST_HARNESS_H
+
+#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <functional>
+#include <vector>
+#include "TestHarness.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace generated_tests {
+
+using ::test_helper::MixedTypedExample;
+
+void PrepareModel(const sp<V1_2::IDevice>& device, const V1_2::Model& model,
+                  sp<V1_2::IPreparedModel>* preparedModel);
+
+void EvaluatePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
+                           std::function<bool(int)> is_ignored,
+                           const std::vector<MixedTypedExample>& examples,
+                           bool hasRelaxedFloat32Model, bool testDynamicOutputShape);
+
+void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
+             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
+             bool testDynamicOutputShape = false);
+
+}  // namespace generated_tests
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_2_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
index 990cab9..d48c73e 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
@@ -16,17 +16,17 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+#include "1.2/Callbacks.h"
+#include "GeneratedTestHarness.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "Utils.h"
+#include "VtsHalNeuralnetworks.h"
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
index fa6d54d..1adb371 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
@@ -16,17 +16,17 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+#include "1.2/Callbacks.h"
+#include "GeneratedTestHarness.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "Utils.h"
+#include "VtsHalNeuralnetworks.h"
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_2.cpp
similarity index 97%
rename from neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
rename to neuralnetworks/1.2/vts/functional/GeneratedTestsV1_2.cpp
index 5af3255..f9cecf8 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_2.cpp
@@ -16,17 +16,17 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+#include "1.2/Callbacks.h"
+#include "GeneratedTestHarness.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "Utils.h"
+#include "VtsHalNeuralnetworks.h"
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
diff --git a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
index 8c6391e..4d6bdbb 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
@@ -18,7 +18,7 @@
 
 #include "VtsHalNeuralnetworks.h"
 
-#include "Callbacks.h"
+#include "1.2/Callbacks.h"
 #include "ExecutionBurstController.h"
 #include "ExecutionBurstServer.h"
 #include "TestHarness.h"
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index f87ca89..78bb194 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -16,10 +16,10 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
+#include "1.0/Utils.h"
+#include "1.2/Callbacks.h"
 #include "VtsHalNeuralnetworks.h"
 
-#include "Callbacks.h"
-
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
@@ -41,10 +41,10 @@
                                            const Model& model) {
     SCOPED_TRACE(message + " [getSupportedOperations_1_2]");
 
-    Return<void> ret =
-        device->getSupportedOperations_1_2(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-        });
+    Return<void> ret = device->getSupportedOperations_1_2(
+            model, [&](ErrorStatus status, const hidl_vec<bool>&) {
+                EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+            });
     EXPECT_TRUE(ret.isOk());
 }
 
@@ -87,36 +87,16 @@
     validatePrepareModel(device, message, model, preference);
 }
 
-// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
-// so this is efficiently accomplished by moving the element to the end and
-// resizing the hidl_vec to one less.
-template <typename Type>
-static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
-    if (vec) {
-        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
-        vec->resize(vec->size() - 1);
-    }
-}
-
-template <typename Type>
-static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
-    // assume vec is valid
-    const uint32_t index = vec->size();
-    vec->resize(index + 1);
-    (*vec)[index] = value;
-    return index;
-}
-
 static uint32_t addOperand(Model* model) {
     return hidl_vec_push_back(&model->operands,
                               {
-                                  .type = OperandType::INT32,
-                                  .dimensions = {},
-                                  .numberOfConsumers = 0,
-                                  .scale = 0.0f,
-                                  .zeroPoint = 0,
-                                  .lifetime = OperandLifeTime::MODEL_INPUT,
-                                  .location = {.poolIndex = 0, .offset = 0, .length = 0},
+                                      .type = OperandType::INT32,
+                                      .dimensions = {},
+                                      .numberOfConsumers = 0,
+                                      .scale = 0.0f,
+                                      .zeroPoint = 0,
+                                      .lifetime = OperandLifeTime::MODEL_INPUT,
+                                      .location = {.poolIndex = 0, .offset = 0, .length = 0},
                               });
 }
 
@@ -243,7 +223,7 @@
         case OperandType::TENSOR_QUANT8_ASYMM:
             return {-1, 256};
         case OperandType::TENSOR_QUANT8_SYMM:
-          return {-129, -1, 1, 128};
+            return {-129, -1, 1, 128};
         case OperandType::TENSOR_QUANT16_ASYMM:
             return {-1, 65536};
         case OperandType::TENSOR_QUANT16_SYMM:
@@ -256,7 +236,7 @@
 static void mutateOperandZeroPointTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const std::vector<int32_t> invalidZeroPoints =
-            getInvalidZeroPoints(model.operands[operand].type);
+                getInvalidZeroPoints(model.operands[operand].type);
         for (int32_t invalidZeroPoint : invalidZeroPoints) {
             const std::string message = "mutateOperandZeroPointTest: operand " +
                                         std::to_string(operand) + " has zero point of " +
@@ -292,13 +272,13 @@
         case OperandType::TENSOR_FLOAT16:
         case OperandType::TENSOR_FLOAT32:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = 0.0f;
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_INT32:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_QUANT8_ASYMM:
@@ -306,19 +286,20 @@
         case OperandType::TENSOR_QUANT16_ASYMM:
         case OperandType::TENSOR_QUANT16_SYMM:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
             break;
         case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL: {
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = 0.0f;
             newOperand.zeroPoint = 0;
 
             SymmPerChannelQuantParams channelQuant;
             channelQuant.channelDim = 0;
             channelQuant.scales = hidl_vec<float>(
-                operand->dimensions.size() > 0 ? static_cast<size_t>(operand->dimensions[0]) : 0);
+                    operand->dimensions.size() > 0 ? static_cast<size_t>(operand->dimensions[0])
+                                                   : 0);
             for (size_t i = 0; i < channelQuant.scales.size(); ++i) {
                 channelQuant.scales[i] = 1.0f;
             }
@@ -435,7 +416,7 @@
                                         std::to_string(invalidOperationType);
             validate(device, message, model, [operation, invalidOperationType](Model* model) {
                 model->operations[operation].type =
-                    static_cast<OperationType>(invalidOperationType);
+                        static_cast<OperationType>(invalidOperationType);
             });
         }
     }
@@ -508,15 +489,15 @@
                 }
             }
         }
-        // BIDIRECTIONAL_SEQUENCE_LSTM and BIDIRECTIONAL_SEQUENCE_RNN can have
-        // either one or two outputs depending on their mergeOutputs parameter.
+        // BIDIRECTIONAL_SEQUENCE_LSTM and BIDIRECTIONAL_SEQUENCE_RNN can have either one or two
+        // outputs depending on their mergeOutputs parameter.
         if (operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_LSTM ||
             operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_RNN) {
-          for (const size_t outOprand : operation.outputs) {
-            if (operand == outOprand) {
-              return true;
+            for (const size_t outOprand : operation.outputs) {
+                if (operand == outOprand) {
+                    return true;
+                }
             }
-          }
         }
     }
     return false;
@@ -690,7 +671,7 @@
 static void addOperationOutputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message =
-            "addOperationOutputTest: operation " + std::to_string(operation);
+                "addOperationOutputTest: operation " + std::to_string(operation);
         validate(device, message, model, [operation](Model* model) {
             uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
             hidl_vec_push_back(&model->operations[operation].outputs, index);
@@ -702,14 +683,14 @@
 ///////////////////////// VALIDATE EXECUTION PREFERENCE /////////////////////////
 
 static const int32_t invalidExecutionPreferences[] = {
-    static_cast<int32_t>(ExecutionPreference::LOW_POWER) - 1,        // lower bound
-    static_cast<int32_t>(ExecutionPreference::SUSTAINED_SPEED) + 1,  // upper bound
+        static_cast<int32_t>(ExecutionPreference::LOW_POWER) - 1,        // lower bound
+        static_cast<int32_t>(ExecutionPreference::SUSTAINED_SPEED) + 1,  // upper bound
 };
 
 static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const Model& model) {
     for (int32_t preference : invalidExecutionPreferences) {
         const std::string message =
-            "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
+                "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
         validate(device, message, model, [](Model*) {},
                  static_cast<ExecutionPreference>(preference));
     }
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index e935aaa..a7e8328 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -16,17 +16,18 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "ExecutionBurstController.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+#include "1.0/Utils.h"
+#include "1.2/Callbacks.h"
+#include "ExecutionBurstController.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "Utils.h"
+#include "VtsHalNeuralnetworks.h"
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
@@ -137,26 +138,6 @@
     }
 }
 
-// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
-// so this is efficiently accomplished by moving the element to the end and
-// resizing the hidl_vec to one less.
-template <typename Type>
-static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
-    if (vec) {
-        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
-        vec->resize(vec->size() - 1);
-    }
-}
-
-template <typename Type>
-static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
-    // assume vec is valid
-    const uint32_t index = vec->size();
-    vec->resize(index + 1);
-    (*vec)[index] = value;
-    return index;
-}
-
 ///////////////////////// REMOVE INPUT ////////////////////////////////////
 
 static void removeInputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
@@ -197,11 +178,13 @@
         for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
             if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
             RequestArgument arg = {
-                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
+                    .location = {.poolIndex = INPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
             };
             RequestArgument arg_empty = {
-                .hasNoValue = true,
+                    .hasNoValue = true,
             };
             inputs_info[index] = s ? arg : arg_empty;
             inputSize += s;
@@ -219,8 +202,10 @@
         for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
             if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
             RequestArgument arg = {
-                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
+                    .location = {.poolIndex = OUTPUT,
+                                 .offset = 0,
+                                 .length = static_cast<uint32_t>(s)},
+                    .dimensions = {},
             };
             outputs_info[index] = arg;
             outputSize += s;
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
index 666f9b5..bd24edc 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
@@ -20,7 +20,7 @@
 
 #include <android-base/logging.h>
 
-#include "Callbacks.h"
+#include "1.2/Callbacks.h"
 
 namespace android {
 namespace hardware {
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
index 80e810a..90dfe25 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
@@ -14,24 +14,23 @@
  * limitations under the License.
  */
 
-#ifndef VTS_HAL_NEURALNETWORKS_V1_2_H
-#define VTS_HAL_NEURALNETWORKS_V1_2_H
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_2_VTS_HAL_NEURALNETWORKS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_2_VTS_HAL_NEURALNETWORKS_H
 
-#include "Callbacks.h"
-
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/macros.h>
 #include <android/hardware/neuralnetworks/1.0/types.h>
 #include <android/hardware/neuralnetworks/1.1/types.h>
 #include <android/hardware/neuralnetworks/1.2/IDevice.h>
 #include <android/hardware/neuralnetworks/1.2/types.h>
-
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-
-#include <android-base/macros.h>
 #include <gtest/gtest.h>
+
 #include <iostream>
 #include <vector>
 
+#include "1.2/Callbacks.h"
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
@@ -50,7 +49,7 @@
     NeuralnetworksHidlEnvironment();
     ~NeuralnetworksHidlEnvironment() override;
 
-   public:
+  public:
     static NeuralnetworksHidlEnvironment* getInstance();
     void registerTestServices() override;
 };
@@ -59,30 +58,30 @@
 class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
     DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
 
-   public:
+  public:
     NeuralnetworksHidlTest();
     ~NeuralnetworksHidlTest() override;
     void SetUp() override;
     void TearDown() override;
 
-   protected:
+  protected:
     sp<IDevice> device;
 };
 
 // Tag for the validation tests
 class ValidationTest : public NeuralnetworksHidlTest {
-   protected:
-     void validateEverything(const Model& model, const std::vector<Request>& requests);
-     void validateFailure(const Model& model, const std::vector<Request>& requests);
+  protected:
+    void validateEverything(const Model& model, const std::vector<Request>& requests);
+    void validateFailure(const Model& model, const std::vector<Request>& requests);
 
-   private:
-     void validateModel(const Model& model);
-     void validateRequests(const sp<IPreparedModel>& preparedModel,
-                           const std::vector<Request>& requests);
-     void validateRequestFailure(const sp<IPreparedModel>& preparedModel,
-                                 const std::vector<Request>& requests);
-     void validateBurst(const sp<IPreparedModel>& preparedModel,
-                        const std::vector<Request>& requests);
+  private:
+    void validateModel(const Model& model);
+    void validateRequests(const sp<IPreparedModel>& preparedModel,
+                          const std::vector<Request>& requests);
+    void validateRequestFailure(const sp<IPreparedModel>& preparedModel,
+                                const std::vector<Request>& requests);
+    void validateBurst(const sp<IPreparedModel>& preparedModel,
+                       const std::vector<Request>& requests);
 };
 
 // Tag for the generated tests
@@ -93,7 +92,7 @@
 
 // Utility function to get PreparedModel from callback and downcast to V1_2.
 sp<IPreparedModel> getPreparedModel_1_2(
-    const sp<V1_2::implementation::PreparedModelCallback>& callback);
+        const sp<V1_2::implementation::PreparedModelCallback>& callback);
 
 }  // namespace functional
 }  // namespace vts
@@ -110,4 +109,4 @@
 
 }  // namespace android::hardware::neuralnetworks::V1_0
 
-#endif  // VTS_HAL_NEURALNETWORKS_V1_2_H
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_2_VTS_HAL_NEURALNETWORKS_H
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.h b/neuralnetworks/1.2/vts/functional/include/1.2/Callbacks.h
similarity index 94%
rename from neuralnetworks/1.0/vts/functional/Callbacks.h
rename to neuralnetworks/1.2/vts/functional/include/1.2/Callbacks.h
index 4707d0a..212a887 100644
--- a/neuralnetworks/1.0/vts/functional/Callbacks.h
+++ b/neuralnetworks/1.2/vts/functional/include/1.2/Callbacks.h
@@ -14,14 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
-#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_2_CALLBACKS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_2_CALLBACKS_H
 
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
 #include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
 #include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
-#include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 #include <chrono>
 #include <condition_variable>
@@ -60,7 +57,7 @@
  * std::condition_variable, or std::experimental::latch instead.
  */
 class CallbackBase {
- public:
+  public:
     CallbackBase();
     ~CallbackBase();
 
@@ -79,8 +76,8 @@
      *                before the time duration expired, std::cv_status::timeout
      *                otherwise.
      */
-    template<class Rep, class Period>
-    std::cv_status wait_for(const std::chrono::duration<Rep,Period>& timeout_duration);
+    template <class Rep, class Period>
+    std::cv_status wait_for(const std::chrono::duration<Rep, Period>& timeout_duration);
 
     /**
      * CallbackBase::on_finish binds a function to the callback object. This
@@ -144,7 +141,7 @@
      */
     void join_thread();
 
- protected:
+  protected:
     /**
      * CallbackBase::notify enables all prior and future wait* calls on the
      * callback object to proceed. The call to CallbackBase::notify happens
@@ -158,16 +155,16 @@
      */
     void notify();
 
- private:
+  private:
     // Same as CallbackBase::join_thread but assumes we already hold a lock on
     // mMutex.
     void join_thread_locked();
 
-    bool                      mNotified;
-    std::mutex                mMutex;
-    std::condition_variable   mCondition;
+    bool mNotified;
+    std::mutex mMutex;
+    std::condition_variable mCondition;
     std::function<bool(void)> mPostWork;
-    std::thread               mThread;
+    std::thread mThread;
 };
 
 /**
@@ -185,7 +182,7 @@
  * IDevice::prepareModel.
  */
 class PreparedModelCallback : public CallbackBase, public IPreparedModelCallback {
- public:
+  public:
     PreparedModelCallback();
     ~PreparedModelCallback() override;
 
@@ -241,8 +238,8 @@
      */
     sp<V1_0::IPreparedModel> getPreparedModel();
 
-   private:
-    ErrorStatus        mErrorStatus;
+  private:
+    ErrorStatus mErrorStatus;
     sp<V1_0::IPreparedModel> mPreparedModel;
 };
 
@@ -260,8 +257,8 @@
  * IExecutionCallback. This callback object is passed as an argument to
  * IPreparedModel::execute.
  */
-class ExecutionCallback : public CallbackBase,  public IExecutionCallback {
- public:
+class ExecutionCallback : public CallbackBase, public IExecutionCallback {
+  public:
     ExecutionCallback();
     ~ExecutionCallback() override;
 
@@ -376,19 +373,19 @@
      */
     Timing getTiming();
 
-   private:
+  private:
     ErrorStatus mErrorStatus = ErrorStatus::GENERAL_FAILURE;
     std::vector<OutputShape> mOutputShapes = {};
     Timing mTiming = {};
 };
 
-
 // template function implementation(s) below this point
 
-template<class Rep, class Period>
-std::cv_status CallbackBase::wait_for(const std::chrono::duration<Rep,Period>& timeout_duration) {
+template <class Rep, class Period>
+std::cv_status CallbackBase::wait_for(const std::chrono::duration<Rep, Period>& timeout_duration) {
     std::unique_lock<std::mutex> lock(mMutex);
-    std::cv_status status = mCondition.wait_for(lock, timeout_duration, [this]{return mNotified;});
+    std::cv_status status =
+            mCondition.wait_for(lock, timeout_duration, [this] { return mNotified; });
     if (status != std::cv_status::timeout) {
         join_thread_locked();
     }
@@ -401,4 +398,4 @@
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_2_CALLBACKS_H
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
index 03fcc17..dc54f27 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -130,8 +130,8 @@
 
 void SensorsHidlEnvironmentV2_0::startPollingThread() {
     mStopThread = false;
-    mPollThread = std::thread(pollingThread, this);
     mEvents.reserve(MAX_RECEIVE_BUFFER_EVENT_COUNT);
+    mPollThread = std::thread(pollingThread, this);
 }
 
 void SensorsHidlEnvironmentV2_0::readEvents() {