Merge changes from topic "hwcomposer-cleanup"

* changes:
  graphics: add composer 2.2 default impl
  graphics: convert composer default impl to a library
  graphics: add Composer to HAL support library
  graphics: move ComposerClient to HAL support library
  graphics: add ComposerCommandEngine
  graphics: add ComposerResources
  graphics: move ComposerBase to HAL support library
  graphics: add libhwc2on{1,fb}adapter
  graphics: more reusable libVtsHalGraphicsComposerTestUtils
  graphics: clang-format composer VTS
  graphics: move libVtsHalGraphicsComposerTestUtils
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index b46a1de..2de1e3c 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -1,34 +1,12 @@
-cc_library_static {
-    name: "libhwcomposer-client",
-    vendor_available: true,
-    defaults: ["hidl_defaults"],
-    export_include_dirs: ["."],
-    srcs: ["ComposerClient.cpp"],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.mapper@2.0",
-        "libbase",
-        "libcutils",
-        "libfmq",
-        "libhardware",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libsync",
-        "libutils",
-    ],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
-    ],
-}
-
 cc_library_shared {
     name: "android.hardware.graphics.composer@2.1-impl",
     defaults: ["hidl_defaults"],
-    proprietary: true,
+    vendor: true,
     relative_install_path: "hw",
-    srcs: ["Hwc.cpp"],
-    static_libs: ["libhwcomposer-client"],
+    srcs: ["passthrough.cpp"],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-passthrough",
+    ],
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
@@ -44,26 +22,21 @@
         "libhwc2on1adapter",
         "libhwc2onfbadapter",
     ],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
+    cflags: [
+        "-DLOG_TAG=\"ComposerHal\""
     ],
 }
 
 cc_binary {
     name: "android.hardware.graphics.composer@2.1-service",
     defaults: ["hidl_defaults"],
-    proprietary: true,
+    vendor: true,
     relative_install_path: "hw",
     srcs: ["service.cpp"],
     init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
-    static_libs: ["libhwcomposer-client"],
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
-        "libbase",
         "libbinder",
-        "libcutils",
-        "libfmq",
-        "libhardware",
         "libhidlbase",
         "libhidltransport",
         "liblog",
diff --git a/graphics/composer/2.1/default/ComposerBase.h b/graphics/composer/2.1/default/ComposerBase.h
deleted file mode 100644
index e1c9d33..0000000
--- a/graphics/composer/2.1/default/ComposerBase.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
-#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#include <hardware/hwcomposer2.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::hardware::graphics::common::V1_0::Transform;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Hdr;
-
-class ComposerBase {
-public:
-    virtual ~ComposerBase() {};
-
-    virtual bool hasCapability(hwc2_capability_t capability) = 0;
-
-    virtual void removeClient() = 0;
-    virtual void enableCallback(bool enable) = 0;
-    virtual uint32_t getMaxVirtualDisplayCount() = 0;
-    virtual Error createVirtualDisplay(uint32_t width, uint32_t height,
-        PixelFormat* format, Display* outDisplay) = 0;
-    virtual Error destroyVirtualDisplay(Display display) = 0;
-    virtual Error createLayer(Display display, Layer* outLayer) = 0;
-    virtual Error destroyLayer(Display display, Layer layer) = 0;
-
-    virtual Error getActiveConfig(Display display, Config* outConfig) = 0;
-    virtual Error getClientTargetSupport(Display display,
-            uint32_t width, uint32_t height,
-            PixelFormat format, Dataspace dataspace) = 0;
-    virtual Error getColorModes(Display display,
-            hidl_vec<ColorMode>* outModes) = 0;
-    virtual Error getDisplayAttribute(Display display, Config config,
-            IComposerClient::Attribute attribute, int32_t* outValue) = 0;
-    virtual Error getDisplayConfigs(Display display,
-            hidl_vec<Config>* outConfigs) = 0;
-    virtual Error getDisplayName(Display display, hidl_string* outName) = 0;
-    virtual Error getDisplayType(Display display,
-            IComposerClient::DisplayType* outType) = 0;
-    virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
-    virtual Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
-            float* outMaxLuminance, float* outMaxAverageLuminance,
-            float* outMinLuminance) = 0;
-
-    virtual Error setActiveConfig(Display display, Config config) = 0;
-    virtual Error setColorMode(Display display, ColorMode mode) = 0;
-    virtual Error setPowerMode(Display display,
-            IComposerClient::PowerMode mode) = 0;
-    virtual Error setVsyncEnabled(Display display,
-            IComposerClient::Vsync enabled) = 0;
-
-    virtual Error setColorTransform(Display display, const float* matrix,
-            int32_t hint) = 0;
-    virtual Error setClientTarget(Display display, buffer_handle_t target,
-            int32_t acquireFence, int32_t dataspace,
-            const std::vector<hwc_rect_t>& damage) = 0;
-    virtual Error setOutputBuffer(Display display, buffer_handle_t buffer,
-            int32_t releaseFence) = 0;
-    virtual Error validateDisplay(Display display,
-            std::vector<Layer>* outChangedLayers,
-            std::vector<IComposerClient::Composition>* outCompositionTypes,
-            uint32_t* outDisplayRequestMask,
-            std::vector<Layer>* outRequestedLayers,
-            std::vector<uint32_t>* outRequestMasks) = 0;
-    virtual Error acceptDisplayChanges(Display display) = 0;
-    virtual Error presentDisplay(Display display, int32_t* outPresentFence,
-            std::vector<Layer>* outLayers,
-            std::vector<int32_t>* outReleaseFences) = 0;
-
-    virtual Error setLayerCursorPosition(Display display, Layer layer,
-            int32_t x, int32_t y) = 0;
-    virtual Error setLayerBuffer(Display display, Layer layer,
-            buffer_handle_t buffer, int32_t acquireFence) = 0;
-    virtual Error setLayerSurfaceDamage(Display display, Layer layer,
-            const std::vector<hwc_rect_t>& damage) = 0;
-    virtual Error setLayerBlendMode(Display display, Layer layer,
-            int32_t mode) = 0;
-    virtual Error setLayerColor(Display display, Layer layer,
-            IComposerClient::Color color) = 0;
-    virtual Error setLayerCompositionType(Display display, Layer layer,
-            int32_t type) = 0;
-    virtual Error setLayerDataspace(Display display, Layer layer,
-            int32_t dataspace) = 0;
-    virtual Error setLayerDisplayFrame(Display display, Layer layer,
-            const hwc_rect_t& frame) = 0;
-    virtual Error setLayerPlaneAlpha(Display display, Layer layer,
-            float alpha) = 0;
-    virtual Error setLayerSidebandStream(Display display, Layer layer,
-            buffer_handle_t stream) = 0;
-    virtual Error setLayerSourceCrop(Display display, Layer layer,
-            const hwc_frect_t& crop) = 0;
-    virtual Error setLayerTransform(Display display, Layer layer,
-            int32_t transform) = 0;
-    virtual Error setLayerVisibleRegion(Display display, Layer layer,
-            const std::vector<hwc_rect_t>& visible) = 0;
-    virtual Error setLayerZOrder(Display display, Layer layer,
-            uint32_t z) = 0;
-};
-
-}  // namespace implementation
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp
deleted file mode 100644
index 0fcb9de..0000000
--- a/graphics/composer/2.1/default/ComposerClient.cpp
+++ /dev/null
@@ -1,1205 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "HwcPassthrough"
-
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <log/log.h>
-
-#include "ComposerBase.h"
-#include "ComposerClient.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-namespace {
-
-using MapperError = android::hardware::graphics::mapper::V2_0::Error;
-using android::hardware::graphics::mapper::V2_0::IMapper;
-
-class HandleImporter {
-public:
-    bool initialize()
-    {
-        // allow only one client
-        if (mInitialized) {
-            return false;
-        }
-
-        mMapper = IMapper::getService();
-
-        mInitialized = true;
-        return true;
-    }
-
-    void cleanup()
-    {
-        mMapper.clear();
-        mInitialized = false;
-    }
-
-    // In IComposer, any buffer_handle_t is owned by the caller and we need to
-    // make a clone for hwcomposer2.  We also need to translate empty handle
-    // to nullptr.  This function does that, in-place.
-    bool importBuffer(buffer_handle_t& handle)
-    {
-        if (!handle) {
-            return true;
-        }
-
-        if (!handle->numFds && !handle->numInts) {
-            handle = nullptr;
-            return true;
-        }
-
-        MapperError error;
-        buffer_handle_t importedHandle;
-        mMapper->importBuffer(
-            hidl_handle(handle),
-            [&](const auto& tmpError, const auto& tmpBufferHandle) {
-                error = tmpError;
-                importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
-            });
-        if (error != MapperError::NONE) {
-            return false;
-        }
-
-        handle = importedHandle;
-
-        return true;
-    }
-
-    void freeBuffer(buffer_handle_t handle)
-    {
-        if (!handle) {
-            return;
-        }
-
-        mMapper->freeBuffer(const_cast<native_handle_t*>(handle));
-    }
-
-private:
- bool mInitialized = false;
- sp<IMapper> mMapper;
-};
-
-HandleImporter sHandleImporter;
-
-} // anonymous namespace
-
-BufferCacheEntry::BufferCacheEntry()
-    : mHandle(nullptr)
-{
-}
-
-BufferCacheEntry::BufferCacheEntry(BufferCacheEntry&& other)
-{
-    mHandle = other.mHandle;
-    other.mHandle = nullptr;
-}
-
-BufferCacheEntry& BufferCacheEntry::operator=(buffer_handle_t handle)
-{
-    clear();
-    mHandle = handle;
-    return *this;
-}
-
-BufferCacheEntry::~BufferCacheEntry()
-{
-    clear();
-}
-
-void BufferCacheEntry::clear()
-{
-    if (mHandle) {
-        sHandleImporter.freeBuffer(mHandle);
-    }
-}
-
-ComposerClient::ComposerClient(ComposerBase& hal)
-    : mHal(hal), mWriter(kWriterInitialSize)
-{
-}
-
-ComposerClient::~ComposerClient()
-{
-    // We want to call hwc2_close here (and move hwc2_open to the
-    // constructor), with the assumption that hwc2_close would
-    //
-    //  - clean up all resources owned by the client
-    //  - make sure all displays are blank (since there is no layer)
-    //
-    // But since SF used to crash at this point, different hwcomposer2
-    // implementations behave differently on hwc2_close.  Our only portable
-    // choice really is to abort().  But that is not an option anymore
-    // because we might also have VTS or VR as clients that can come and go.
-    //
-    // Below we manually clean all resources (layers and virtual
-    // displays), and perform a presentDisplay afterwards.
-    ALOGW("destroying composer client");
-
-    mHal.enableCallback(false);
-
-    // no need to grab the mutex as any in-flight hwbinder call would have
-    // kept the client alive
-    for (const auto& dpy : mDisplayData) {
-        ALOGW("destroying client resources for display %" PRIu64, dpy.first);
-
-        for (const auto& ly : dpy.second.Layers) {
-            mHal.destroyLayer(dpy.first, ly.first);
-        }
-
-        if (dpy.second.IsVirtual) {
-            mHal.destroyVirtualDisplay(dpy.first);
-        } else {
-            ALOGW("performing a final presentDisplay");
-
-            std::vector<Layer> changedLayers;
-            std::vector<IComposerClient::Composition> compositionTypes;
-            uint32_t displayRequestMask = 0;
-            std::vector<Layer> requestedLayers;
-            std::vector<uint32_t> requestMasks;
-            mHal.validateDisplay(dpy.first, &changedLayers, &compositionTypes,
-                    &displayRequestMask, &requestedLayers, &requestMasks);
-
-            mHal.acceptDisplayChanges(dpy.first);
-
-            int32_t presentFence = -1;
-            std::vector<Layer> releasedLayers;
-            std::vector<int32_t> releaseFences;
-            mHal.presentDisplay(dpy.first, &presentFence, &releasedLayers, &releaseFences);
-            if (presentFence >= 0) {
-                close(presentFence);
-            }
-            for (auto fence : releaseFences) {
-                if (fence >= 0) {
-                    close(fence);
-                }
-            }
-        }
-    }
-
-    mDisplayData.clear();
-
-    sHandleImporter.cleanup();
-
-    mHal.removeClient();
-
-    ALOGW("removed composer client");
-}
-
-void ComposerClient::initialize()
-{
-    mReader = createCommandReader();
-    if (!sHandleImporter.initialize()) {
-        LOG_ALWAYS_FATAL("failed to initialize handle importer");
-    }
-}
-
-void ComposerClient::onHotplug(Display display,
-        IComposerCallback::Connection connected)
-{
-    {
-        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
-        if (connected == IComposerCallback::Connection::CONNECTED) {
-            mDisplayData.emplace(display, DisplayData(false));
-        } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
-            mDisplayData.erase(display);
-        }
-    }
-
-    auto ret = mCallback->onHotplug(display, connected);
-    ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s",
-            ret.description().c_str());
-}
-
-void ComposerClient::onRefresh(Display display)
-{
-    auto ret = mCallback->onRefresh(display);
-    ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s",
-            ret.description().c_str());
-}
-
-void ComposerClient::onVsync(Display display, int64_t timestamp)
-{
-    auto ret = mCallback->onVsync(display, timestamp);
-    ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s",
-            ret.description().c_str());
-}
-
-Return<void> ComposerClient::registerCallback(
-        const sp<IComposerCallback>& callback)
-{
-    // no locking as we require this function to be called only once
-    mCallback = callback;
-    mHal.enableCallback(callback != nullptr);
-
-    return Void();
-}
-
-Return<uint32_t> ComposerClient::getMaxVirtualDisplayCount()
-{
-    return mHal.getMaxVirtualDisplayCount();
-}
-
-Return<void> ComposerClient::createVirtualDisplay(uint32_t width,
-        uint32_t height, PixelFormat formatHint, uint32_t outputBufferSlotCount,
-        createVirtualDisplay_cb hidl_cb)
-{
-    Display display = 0;
-    Error err = mHal.createVirtualDisplay(width, height,
-            &formatHint, &display);
-    if (err == Error::NONE) {
-        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
-        auto dpy = mDisplayData.emplace(display, DisplayData(true)).first;
-        dpy->second.OutputBuffers.resize(outputBufferSlotCount);
-    }
-
-    hidl_cb(err, display, formatHint);
-    return Void();
-}
-
-Return<Error> ComposerClient::destroyVirtualDisplay(Display display)
-{
-    Error err = mHal.destroyVirtualDisplay(display);
-    if (err == Error::NONE) {
-        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
-        mDisplayData.erase(display);
-    }
-
-    return err;
-}
-
-Return<void> ComposerClient::createLayer(Display display,
-        uint32_t bufferSlotCount, createLayer_cb hidl_cb)
-{
-    Layer layer = 0;
-    Error err = mHal.createLayer(display, &layer);
-    if (err == Error::NONE) {
-        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-        auto dpy = mDisplayData.find(display);
-        // The display entry may have already been removed by onHotplug.
-        if (dpy != mDisplayData.end()) {
-            auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
-            ly->second.Buffers.resize(bufferSlotCount);
-        } else {
-            err = Error::BAD_DISPLAY;
-            // Note: We do not destroy the layer on this error as the hotplug
-            // disconnect invalidates the display id. The implementation should
-            // ensure all layers for the display are destroyed.
-        }
-    }
-
-    hidl_cb(err, layer);
-    return Void();
-}
-
-Return<Error> ComposerClient::destroyLayer(Display display, Layer layer)
-{
-    Error err = mHal.destroyLayer(display, layer);
-    if (err == Error::NONE) {
-        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
-        auto dpy = mDisplayData.find(display);
-        // The display entry may have already been removed by onHotplug.
-        if (dpy != mDisplayData.end()) {
-            dpy->second.Layers.erase(layer);
-        }
-    }
-
-    return err;
-}
-
-Return<void> ComposerClient::getActiveConfig(Display display,
-        getActiveConfig_cb hidl_cb)
-{
-    Config config = 0;
-    Error err = mHal.getActiveConfig(display, &config);
-
-    hidl_cb(err, config);
-    return Void();
-}
-
-Return<Error> ComposerClient::getClientTargetSupport(Display display,
-        uint32_t width, uint32_t height,
-        PixelFormat format, Dataspace dataspace)
-{
-    Error err = mHal.getClientTargetSupport(display,
-            width, height, format, dataspace);
-    return err;
-}
-
-Return<void> ComposerClient::getColorModes(Display display,
-          getColorModes_cb hidl_cb)
-{
-    hidl_vec<ColorMode> modes;
-    Error err = mHal.getColorModes(display, &modes);
-
-    hidl_cb(err, modes);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayAttribute(Display display,
-        Config config, Attribute attribute,
-        getDisplayAttribute_cb hidl_cb)
-{
-    int32_t value = 0;
-    Error err = mHal.getDisplayAttribute(display, config, attribute, &value);
-
-    hidl_cb(err, value);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayConfigs(Display display,
-        getDisplayConfigs_cb hidl_cb)
-{
-    hidl_vec<Config> configs;
-    Error err = mHal.getDisplayConfigs(display, &configs);
-
-    hidl_cb(err, configs);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayName(Display display,
-        getDisplayName_cb hidl_cb)
-{
-    hidl_string name;
-    Error err = mHal.getDisplayName(display, &name);
-
-    hidl_cb(err, name);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayType(Display display,
-        getDisplayType_cb hidl_cb)
-{
-    DisplayType type = DisplayType::INVALID;
-    Error err = mHal.getDisplayType(display, &type);
-
-    hidl_cb(err, type);
-    return Void();
-}
-
-Return<void> ComposerClient::getDozeSupport(Display display,
-        getDozeSupport_cb hidl_cb)
-{
-    bool support = false;
-    Error err = mHal.getDozeSupport(display, &support);
-
-    hidl_cb(err, support);
-    return Void();
-}
-
-Return<void> ComposerClient::getHdrCapabilities(Display display,
-        getHdrCapabilities_cb hidl_cb)
-{
-    hidl_vec<Hdr> types;
-    float max_lumi = 0.0f;
-    float max_avg_lumi = 0.0f;
-    float min_lumi = 0.0f;
-    Error err = mHal.getHdrCapabilities(display, &types,
-            &max_lumi, &max_avg_lumi, &min_lumi);
-
-    hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi);
-    return Void();
-}
-
-Return<Error> ComposerClient::setClientTargetSlotCount(Display display,
-        uint32_t clientTargetSlotCount)
-{
-    std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
-    auto dpy = mDisplayData.find(display);
-    if (dpy == mDisplayData.end()) {
-        return Error::BAD_DISPLAY;
-    }
-
-    dpy->second.ClientTargets.resize(clientTargetSlotCount);
-
-    return Error::NONE;
-}
-
-Return<Error> ComposerClient::setActiveConfig(Display display, Config config)
-{
-    Error err = mHal.setActiveConfig(display, config);
-    return err;
-}
-
-Return<Error> ComposerClient::setColorMode(Display display, ColorMode mode)
-{
-    Error err = mHal.setColorMode(display, mode);
-    return err;
-}
-
-Return<Error> ComposerClient::setPowerMode(Display display, PowerMode mode)
-{
-    Error err = mHal.setPowerMode(display, mode);
-    return err;
-}
-
-Return<Error> ComposerClient::setVsyncEnabled(Display display, Vsync enabled)
-{
-    Error err = mHal.setVsyncEnabled(display, enabled);
-    return err;
-}
-
-Return<Error> ComposerClient::setInputCommandQueue(
-        const MQDescriptorSync<uint32_t>& descriptor)
-{
-    std::lock_guard<std::mutex> lock(mCommandMutex);
-    return mReader->setMQDescriptor(descriptor) ?
-        Error::NONE : Error::NO_RESOURCES;
-}
-
-Return<void> ComposerClient::getOutputCommandQueue(
-        getOutputCommandQueue_cb hidl_cb)
-{
-    // no locking as we require this function to be called inside
-    // executeCommands_cb
-
-    auto outDescriptor = mWriter.getMQDescriptor();
-    if (outDescriptor) {
-        hidl_cb(Error::NONE, *outDescriptor);
-    } else {
-        hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
-    }
-
-    return Void();
-}
-
-Return<void> ComposerClient::executeCommands(uint32_t inLength,
-        const hidl_vec<hidl_handle>& inHandles,
-        executeCommands_cb hidl_cb)
-{
-    std::lock_guard<std::mutex> lock(mCommandMutex);
-
-    bool outChanged = false;
-    uint32_t outLength = 0;
-    hidl_vec<hidl_handle> outHandles;
-
-    if (!mReader->readQueue(inLength, inHandles)) {
-        hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
-        return Void();
-    }
-
-    Error err = mReader->parse();
-    if (err == Error::NONE &&
-            !mWriter.writeQueue(&outChanged, &outLength, &outHandles)) {
-        err = Error::NO_RESOURCES;
-    }
-
-    hidl_cb(err, outChanged, outLength, outHandles);
-
-    mReader->reset();
-    mWriter.reset();
-
-    return Void();
-}
-
-std::unique_ptr<ComposerClient::CommandReader>
-ComposerClient::createCommandReader()
-{
-    return std::unique_ptr<ComposerClient::CommandReader>(
-        new CommandReader(*this));
-}
-
-ComposerClient::CommandReader::CommandReader(ComposerClient& client)
-    : mClient(client), mHal(client.mHal), mWriter(client.mWriter)
-{
-}
-
-ComposerClient::CommandReader::~CommandReader()
-{
-}
-
-Error ComposerClient::CommandReader::parse()
-{
-    IComposerClient::Command command;
-    uint16_t length = 0;
-
-    while (!isEmpty()) {
-        if (!beginCommand(&command, &length)) {
-            break;
-        }
-
-        bool parsed = parseCommand(command, length);
-        endCommand();
-
-        if (!parsed) {
-            ALOGE("failed to parse command 0x%x, length %" PRIu16,
-                    command, length);
-            break;
-        }
-    }
-
-    return (isEmpty()) ? Error::NONE : Error::BAD_PARAMETER;
-}
-
-bool ComposerClient::CommandReader::parseCommand(
-        IComposerClient::Command command, uint16_t length) {
-    switch (command) {
-    case IComposerClient::Command::SELECT_DISPLAY:
-        return parseSelectDisplay(length);
-    case IComposerClient::Command::SELECT_LAYER:
-        return parseSelectLayer(length);
-    case IComposerClient::Command::SET_COLOR_TRANSFORM:
-        return parseSetColorTransform(length);
-    case IComposerClient::Command::SET_CLIENT_TARGET:
-        return parseSetClientTarget(length);
-    case IComposerClient::Command::SET_OUTPUT_BUFFER:
-        return parseSetOutputBuffer(length);
-    case IComposerClient::Command::VALIDATE_DISPLAY:
-        return parseValidateDisplay(length);
-    case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
-        return parsePresentOrValidateDisplay(length);
-    case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
-        return parseAcceptDisplayChanges(length);
-    case IComposerClient::Command::PRESENT_DISPLAY:
-        return parsePresentDisplay(length);
-    case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
-        return parseSetLayerCursorPosition(length);
-    case IComposerClient::Command::SET_LAYER_BUFFER:
-        return parseSetLayerBuffer(length);
-    case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
-        return parseSetLayerSurfaceDamage(length);
-    case IComposerClient::Command::SET_LAYER_BLEND_MODE:
-        return parseSetLayerBlendMode(length);
-    case IComposerClient::Command::SET_LAYER_COLOR:
-        return parseSetLayerColor(length);
-    case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
-        return parseSetLayerCompositionType(length);
-    case IComposerClient::Command::SET_LAYER_DATASPACE:
-        return parseSetLayerDataspace(length);
-    case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
-        return parseSetLayerDisplayFrame(length);
-    case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
-        return parseSetLayerPlaneAlpha(length);
-    case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
-        return parseSetLayerSidebandStream(length);
-    case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
-        return parseSetLayerSourceCrop(length);
-    case IComposerClient::Command::SET_LAYER_TRANSFORM:
-        return parseSetLayerTransform(length);
-    case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
-        return parseSetLayerVisibleRegion(length);
-    case IComposerClient::Command::SET_LAYER_Z_ORDER:
-        return parseSetLayerZOrder(length);
-    default:
-        return false;
-    }
-}
-
-bool ComposerClient::CommandReader::parseSelectDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kSelectDisplayLength) {
-        return false;
-    }
-
-    mDisplay = read64();
-    mWriter.selectDisplay(mDisplay);
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSelectLayer(uint16_t length)
-{
-    if (length != CommandWriterBase::kSelectLayerLength) {
-        return false;
-    }
-
-    mLayer = read64();
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetColorTransform(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetColorTransformLength) {
-        return false;
-    }
-
-    float matrix[16];
-    for (int i = 0; i < 16; i++) {
-        matrix[i] = readFloat();
-    }
-    auto transform = readSigned();
-
-    auto err = mHal.setColorTransform(mDisplay, matrix, transform);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetClientTarget(uint16_t length)
-{
-    // 4 parameters followed by N rectangles
-    if ((length - 4) % 4 != 0) {
-        return false;
-    }
-
-    bool useCache = false;
-    auto slot = read();
-    auto clientTarget = readHandle(&useCache);
-    auto fence = readFence();
-    auto dataspace = readSigned();
-    auto damage = readRegion((length - 4) / 4);
-    bool closeFence = true;
-
-    auto err = lookupBuffer(BufferCache::CLIENT_TARGETS,
-            slot, useCache, clientTarget, &clientTarget);
-    if (err == Error::NONE) {
-        err = mHal.setClientTarget(mDisplay, clientTarget, fence,
-                dataspace, damage);
-        auto updateBufErr = updateBuffer(BufferCache::CLIENT_TARGETS, slot,
-                useCache, clientTarget);
-        if (err == Error::NONE) {
-            closeFence = false;
-            err = updateBufErr;
-        }
-    }
-    if (closeFence) {
-        close(fence);
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetOutputBuffer(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetOutputBufferLength) {
-        return false;
-    }
-
-    bool useCache = false;
-    auto slot = read();
-    auto outputBuffer = readHandle(&useCache);
-    auto fence = readFence();
-    bool closeFence = true;
-
-    auto err = lookupBuffer(BufferCache::OUTPUT_BUFFERS,
-            slot, useCache, outputBuffer, &outputBuffer);
-    if (err == Error::NONE) {
-        err = mHal.setOutputBuffer(mDisplay, outputBuffer, fence);
-        auto updateBufErr = updateBuffer(BufferCache::OUTPUT_BUFFERS,
-                slot, useCache, outputBuffer);
-        if (err == Error::NONE) {
-            closeFence = false;
-            err = updateBufErr;
-        }
-    }
-    if (closeFence) {
-        close(fence);
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseValidateDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kValidateDisplayLength) {
-        return false;
-    }
-
-    std::vector<Layer> changedLayers;
-    std::vector<IComposerClient::Composition> compositionTypes;
-    uint32_t displayRequestMask = 0x0;
-    std::vector<Layer> requestedLayers;
-    std::vector<uint32_t> requestMasks;
-
-    auto err = mHal.validateDisplay(mDisplay, &changedLayers,
-            &compositionTypes, &displayRequestMask,
-            &requestedLayers, &requestMasks);
-    if (err == Error::NONE) {
-        mWriter.setChangedCompositionTypes(changedLayers,
-                compositionTypes);
-        mWriter.setDisplayRequests(displayRequestMask,
-                requestedLayers, requestMasks);
-    } else {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parsePresentOrValidateDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kPresentOrValidateDisplayLength) {
-        return false;
-    }
-
-    // First try to Present as is.
-    if (mHal.hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
-        int presentFence = -1;
-        std::vector<Layer> layers;
-        std::vector<int> fences;
-        auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
-        if (err == Error::NONE) {
-            mWriter.setPresentOrValidateResult(1);
-            mWriter.setPresentFence(presentFence);
-            mWriter.setReleaseFences(layers, fences);
-            return true;
-        }
-    }
-
-    // Present has failed. We need to fallback to validate
-    std::vector<Layer> changedLayers;
-    std::vector<IComposerClient::Composition> compositionTypes;
-    uint32_t displayRequestMask = 0x0;
-    std::vector<Layer> requestedLayers;
-    std::vector<uint32_t> requestMasks;
-
-    auto err = mHal.validateDisplay(mDisplay, &changedLayers, &compositionTypes,
-                                    &displayRequestMask, &requestedLayers, &requestMasks);
-    if (err == Error::NONE) {
-        mWriter.setPresentOrValidateResult(0);
-        mWriter.setChangedCompositionTypes(changedLayers,
-                                           compositionTypes);
-        mWriter.setDisplayRequests(displayRequestMask,
-                                   requestedLayers, requestMasks);
-    } else {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseAcceptDisplayChanges(uint16_t length)
-{
-    if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
-        return false;
-    }
-
-    auto err = mHal.acceptDisplayChanges(mDisplay);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parsePresentDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kPresentDisplayLength) {
-        return false;
-    }
-
-    int presentFence = -1;
-    std::vector<Layer> layers;
-    std::vector<int> fences;
-    auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
-    if (err == Error::NONE) {
-        mWriter.setPresentFence(presentFence);
-        mWriter.setReleaseFences(layers, fences);
-    } else {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerCursorPosition(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerCursorPositionLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerCursorPosition(mDisplay, mLayer,
-            readSigned(), readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerBuffer(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerBufferLength) {
-        return false;
-    }
-
-    bool useCache = false;
-    auto slot = read();
-    auto buffer = readHandle(&useCache);
-    auto fence = readFence();
-    bool closeFence = true;
-
-    auto err = lookupBuffer(BufferCache::LAYER_BUFFERS,
-            slot, useCache, buffer, &buffer);
-    if (err == Error::NONE) {
-        err = mHal.setLayerBuffer(mDisplay, mLayer, buffer, fence);
-        auto updateBufErr = updateBuffer(BufferCache::LAYER_BUFFERS, slot,
-                useCache, buffer);
-        if (err == Error::NONE) {
-            closeFence = false;
-            err = updateBufErr;
-        }
-    }
-    if (closeFence) {
-        close(fence);
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSurfaceDamage(uint16_t length)
-{
-    // N rectangles
-    if (length % 4 != 0) {
-        return false;
-    }
-
-    auto damage = readRegion(length / 4);
-    auto err = mHal.setLayerSurfaceDamage(mDisplay, mLayer, damage);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerBlendMode(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerBlendModeLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerBlendMode(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerColor(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerColorLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerColor(mDisplay, mLayer, readColor());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerCompositionType(
-        uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerCompositionTypeLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerCompositionType(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerDataspace(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerDataspaceLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerDataspace(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerDisplayFrame(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerDisplayFrameLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerDisplayFrame(mDisplay, mLayer, readRect());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerPlaneAlpha(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerPlaneAlpha(mDisplay, mLayer, readFloat());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSidebandStream(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerSidebandStreamLength) {
-        return false;
-    }
-
-    auto stream = readHandle();
-
-    auto err = lookupLayerSidebandStream(stream, &stream);
-    if (err == Error::NONE) {
-        err = mHal.setLayerSidebandStream(mDisplay, mLayer, stream);
-        auto updateErr = updateLayerSidebandStream(stream);
-        if (err == Error::NONE) {
-            err = updateErr;
-        }
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSourceCrop(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerSourceCropLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerSourceCrop(mDisplay, mLayer, readFRect());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerTransform(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerTransformLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerTransform(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerVisibleRegion(uint16_t length)
-{
-    // N rectangles
-    if (length % 4 != 0) {
-        return false;
-    }
-
-    auto region = readRegion(length / 4);
-    auto err = mHal.setLayerVisibleRegion(mDisplay, mLayer, region);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerZOrder(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerZOrderLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerZOrder(mDisplay, mLayer, read());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-hwc_rect_t ComposerClient::CommandReader::readRect()
-{
-    return hwc_rect_t{
-        readSigned(),
-        readSigned(),
-        readSigned(),
-        readSigned(),
-    };
-}
-
-std::vector<hwc_rect_t> ComposerClient::CommandReader::readRegion(size_t count)
-{
-    std::vector<hwc_rect_t> region;
-    region.reserve(count);
-    while (count > 0) {
-        region.emplace_back(readRect());
-        count--;
-    }
-
-    return region;
-}
-
-hwc_frect_t ComposerClient::CommandReader::readFRect()
-{
-    return hwc_frect_t{
-        readFloat(),
-        readFloat(),
-        readFloat(),
-        readFloat(),
-    };
-}
-
-Error ComposerClient::CommandReader::lookupBufferCacheEntryLocked(
-        BufferCache cache, uint32_t slot, BufferCacheEntry** outEntry)
-{
-    auto dpy = mClient.mDisplayData.find(mDisplay);
-    if (dpy == mClient.mDisplayData.end()) {
-        return Error::BAD_DISPLAY;
-    }
-
-    BufferCacheEntry* entry = nullptr;
-    switch (cache) {
-    case BufferCache::CLIENT_TARGETS:
-        if (slot < dpy->second.ClientTargets.size()) {
-            entry = &dpy->second.ClientTargets[slot];
-        }
-        break;
-    case BufferCache::OUTPUT_BUFFERS:
-        if (slot < dpy->second.OutputBuffers.size()) {
-            entry = &dpy->second.OutputBuffers[slot];
-        }
-        break;
-    case BufferCache::LAYER_BUFFERS:
-        {
-            auto ly = dpy->second.Layers.find(mLayer);
-            if (ly == dpy->second.Layers.end()) {
-                return Error::BAD_LAYER;
-            }
-            if (slot < ly->second.Buffers.size()) {
-                entry = &ly->second.Buffers[slot];
-            }
-        }
-        break;
-    case BufferCache::LAYER_SIDEBAND_STREAMS:
-        {
-            auto ly = dpy->second.Layers.find(mLayer);
-            if (ly == dpy->second.Layers.end()) {
-                return Error::BAD_LAYER;
-            }
-            if (slot == 0) {
-                entry = &ly->second.SidebandStream;
-            }
-        }
-        break;
-    default:
-        break;
-    }
-
-    if (!entry) {
-        ALOGW("invalid buffer slot %" PRIu32, slot);
-        return Error::BAD_PARAMETER;
-    }
-
-    *outEntry = entry;
-
-    return Error::NONE;
-}
-
-Error ComposerClient::CommandReader::lookupBuffer(BufferCache cache,
-        uint32_t slot, bool useCache, buffer_handle_t handle,
-        buffer_handle_t* outHandle)
-{
-    if (useCache) {
-        std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
-
-        BufferCacheEntry* entry;
-        Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
-        if (error != Error::NONE) {
-            return error;
-        }
-
-        // input handle is ignored
-        *outHandle = entry->getHandle();
-    } else if (cache == BufferCache::LAYER_SIDEBAND_STREAMS) {
-        if (handle) {
-            *outHandle = native_handle_clone(handle);
-            if (*outHandle == nullptr) {
-                return Error::NO_RESOURCES;
-            }
-        }
-    } else {
-        if (!sHandleImporter.importBuffer(handle)) {
-            return Error::NO_RESOURCES;
-        }
-
-        *outHandle = handle;
-    }
-
-    return Error::NONE;
-}
-
-Error ComposerClient::CommandReader::updateBuffer(BufferCache cache,
-        uint32_t slot, bool useCache, buffer_handle_t handle)
-{
-    // handle was looked up from cache
-    if (useCache) {
-        return Error::NONE;
-    }
-
-    std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
-
-    BufferCacheEntry* entry = nullptr;
-    Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
-    if (error != Error::NONE) {
-      return error;
-    }
-
-    *entry = handle;
-    return Error::NONE;
-}
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/composer/2.1/default/ComposerClient.h b/graphics/composer/2.1/default/ComposerClient.h
deleted file mode 100644
index 104ed5a..0000000
--- a/graphics/composer/2.1/default/ComposerClient.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
-#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
-
-#include <mutex>
-#include <unordered_map>
-#include <vector>
-
-#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
-#include <hardware/hwcomposer2.h>
-#include "ComposerBase.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-class BufferCacheEntry {
-public:
-    BufferCacheEntry();
-    BufferCacheEntry(BufferCacheEntry&& other);
-
-    BufferCacheEntry(const BufferCacheEntry& other) = delete;
-    BufferCacheEntry& operator=(const BufferCacheEntry& other) = delete;
-
-    BufferCacheEntry& operator=(buffer_handle_t handle);
-    ~BufferCacheEntry();
-
-    buffer_handle_t getHandle() const { return mHandle; }
-
-private:
-    void clear();
-
-    buffer_handle_t mHandle;
-};
-
-class ComposerClient : public IComposerClient {
-public:
-    ComposerClient(ComposerBase& hal);
-    virtual ~ComposerClient();
-
-    void initialize();
-
-    void onHotplug(Display display, IComposerCallback::Connection connected);
-    void onRefresh(Display display);
-    void onVsync(Display display, int64_t timestamp);
-
-    // IComposerClient interface
-    Return<void> registerCallback(
-            const sp<IComposerCallback>& callback) override;
-    Return<uint32_t> getMaxVirtualDisplayCount() override;
-    Return<void> createVirtualDisplay(uint32_t width, uint32_t height,
-            PixelFormat formatHint, uint32_t outputBufferSlotCount,
-            createVirtualDisplay_cb hidl_cb) override;
-    Return<Error> destroyVirtualDisplay(Display display) override;
-    Return<void> createLayer(Display display, uint32_t bufferSlotCount,
-            createLayer_cb hidl_cb) override;
-    Return<Error> destroyLayer(Display display, Layer layer) override;
-    Return<void> getActiveConfig(Display display,
-            getActiveConfig_cb hidl_cb) override;
-    Return<Error> getClientTargetSupport(Display display,
-            uint32_t width, uint32_t height,
-            PixelFormat format, Dataspace dataspace) override;
-    Return<void> getColorModes(Display display,
-            getColorModes_cb hidl_cb) override;
-    Return<void> getDisplayAttribute(Display display,
-            Config config, Attribute attribute,
-            getDisplayAttribute_cb hidl_cb) override;
-    Return<void> getDisplayConfigs(Display display,
-            getDisplayConfigs_cb hidl_cb) override;
-    Return<void> getDisplayName(Display display,
-            getDisplayName_cb hidl_cb) override;
-    Return<void> getDisplayType(Display display,
-            getDisplayType_cb hidl_cb) override;
-    Return<void> getDozeSupport(Display display,
-            getDozeSupport_cb hidl_cb) override;
-    Return<void> getHdrCapabilities(Display display,
-            getHdrCapabilities_cb hidl_cb) override;
-    Return<Error> setActiveConfig(Display display, Config config) override;
-    Return<Error> setColorMode(Display display, ColorMode mode) override;
-    Return<Error> setPowerMode(Display display, PowerMode mode) override;
-    Return<Error> setVsyncEnabled(Display display, Vsync enabled) override;
-    Return<Error> setClientTargetSlotCount(Display display,
-            uint32_t clientTargetSlotCount) override;
-    Return<Error> setInputCommandQueue(
-            const MQDescriptorSync<uint32_t>& descriptor) override;
-    Return<void> getOutputCommandQueue(
-            getOutputCommandQueue_cb hidl_cb) override;
-    Return<void> executeCommands(uint32_t inLength,
-            const hidl_vec<hidl_handle>& inHandles,
-            executeCommands_cb hidl_cb) override;
-
-protected:
-    struct LayerBuffers {
-        std::vector<BufferCacheEntry> Buffers;
-        // the handle is a sideband stream handle, not a buffer handle
-        BufferCacheEntry SidebandStream;
-    };
-
-    struct DisplayData {
-        bool IsVirtual;
-
-        std::vector<BufferCacheEntry> ClientTargets;
-        std::vector<BufferCacheEntry> OutputBuffers;
-
-        std::unordered_map<Layer, LayerBuffers> Layers;
-
-        DisplayData(bool isVirtual) : IsVirtual(isVirtual) {}
-    };
-
-    class CommandReader : public CommandReaderBase {
-    public:
-        CommandReader(ComposerClient& client);
-        virtual ~CommandReader();
-
-        Error parse();
-
-    protected:
-        virtual bool parseCommand(IComposerClient::Command command,
-                uint16_t length);
-
-        bool parseSelectDisplay(uint16_t length);
-        bool parseSelectLayer(uint16_t length);
-        bool parseSetColorTransform(uint16_t length);
-        bool parseSetClientTarget(uint16_t length);
-        bool parseSetOutputBuffer(uint16_t length);
-        bool parseValidateDisplay(uint16_t length);
-        bool parsePresentOrValidateDisplay(uint16_t length);
-        bool parseAcceptDisplayChanges(uint16_t length);
-        bool parsePresentDisplay(uint16_t length);
-        bool parseSetLayerCursorPosition(uint16_t length);
-        bool parseSetLayerBuffer(uint16_t length);
-        bool parseSetLayerSurfaceDamage(uint16_t length);
-        bool parseSetLayerBlendMode(uint16_t length);
-        bool parseSetLayerColor(uint16_t length);
-        bool parseSetLayerCompositionType(uint16_t length);
-        bool parseSetLayerDataspace(uint16_t length);
-        bool parseSetLayerDisplayFrame(uint16_t length);
-        bool parseSetLayerPlaneAlpha(uint16_t length);
-        bool parseSetLayerSidebandStream(uint16_t length);
-        bool parseSetLayerSourceCrop(uint16_t length);
-        bool parseSetLayerTransform(uint16_t length);
-        bool parseSetLayerVisibleRegion(uint16_t length);
-        bool parseSetLayerZOrder(uint16_t length);
-
-        hwc_rect_t readRect();
-        std::vector<hwc_rect_t> readRegion(size_t count);
-        hwc_frect_t readFRect();
-
-        enum class BufferCache {
-            CLIENT_TARGETS,
-            OUTPUT_BUFFERS,
-            LAYER_BUFFERS,
-            LAYER_SIDEBAND_STREAMS,
-        };
-        Error lookupBufferCacheEntryLocked(BufferCache cache, uint32_t slot,
-                BufferCacheEntry** outEntry);
-        Error lookupBuffer(BufferCache cache, uint32_t slot,
-                bool useCache, buffer_handle_t handle,
-                buffer_handle_t* outHandle);
-        Error updateBuffer(BufferCache cache, uint32_t slot,
-                bool useCache, buffer_handle_t handle);
-
-        Error lookupLayerSidebandStream(buffer_handle_t handle,
-                buffer_handle_t* outHandle)
-        {
-            return lookupBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
-                    0, false, handle, outHandle);
-        }
-        Error updateLayerSidebandStream(buffer_handle_t handle)
-        {
-            return updateBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
-                    0, false, handle);
-        }
-
-        ComposerClient& mClient;
-        ComposerBase& mHal;
-        CommandWriterBase& mWriter;
-
-        Display mDisplay;
-        Layer mLayer;
-    };
-
-    virtual std::unique_ptr<CommandReader> createCommandReader();
-
-    ComposerBase& mHal;
-
-    // 64KiB minus a small space for metadata such as read/write pointers
-    static constexpr size_t kWriterInitialSize =
-        64 * 1024 / sizeof(uint32_t) - 16;
-    std::mutex mCommandMutex;
-    std::unique_ptr<CommandReader> mReader;
-    CommandWriterBase mWriter;
-
-    sp<IComposerCallback> mCallback;
-
-    std::mutex mDisplayDataMutex;
-    std::unordered_map<Display, DisplayData> mDisplayData;
-};
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp
deleted file mode 100644
index cb393ec..0000000
--- a/graphics/composer/2.1/default/Hwc.cpp
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "HwcPassthrough"
-
-#include "Hwc.h"
-
-#include <chrono>
-#include <type_traits>
-#include <log/log.h>
-
-#include "ComposerClient.h"
-#include "hardware/fb.h"
-#include "hardware/hwcomposer.h"
-#include "hwc2on1adapter/HWC2On1Adapter.h"
-#include "hwc2onfbadapter/HWC2OnFbAdapter.h"
-
-using namespace std::chrono_literals;
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-HwcHal::HwcHal(const hw_module_t* module)
-    : mDevice(nullptr), mDispatch(), mMustValidateDisplay(true), mAdapter() {
-    uint32_t majorVersion;
-    if (module->id && strcmp(module->id, GRALLOC_HARDWARE_MODULE_ID) == 0) {
-        majorVersion = initWithFb(module);
-    } else {
-        majorVersion = initWithHwc(module);
-    }
-
-    initCapabilities();
-    if (majorVersion >= 2 && hasCapability(HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE)) {
-        ALOGE("Present fence must be reliable from HWC2 on.");
-        abort();
-    }
-
-    initDispatch();
-}
-
-HwcHal::~HwcHal()
-{
-    hwc2_close(mDevice);
-}
-
-uint32_t HwcHal::initWithHwc(const hw_module_t* module)
-{
-    // Determine what kind of module is available (HWC2 vs HWC1.X).
-    hw_device_t* device = nullptr;
-    int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
-    if (error != 0) {
-        ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
-        abort();
-    }
-    uint32_t majorVersion = (device->version >> 24) & 0xF;
-
-    // If we don't have a HWC2, we need to wrap whatever we have in an adapter.
-    if (majorVersion != 2) {
-        uint32_t minorVersion = device->version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
-        minorVersion = (minorVersion >> 16) & 0xF;
-        ALOGI("Found HWC implementation v%d.%d", majorVersion, minorVersion);
-        if (minorVersion < 1) {
-            ALOGE("Cannot adapt to HWC version %d.%d. Minimum supported is 1.1",
-                  majorVersion, minorVersion);
-            abort();
-        }
-        mAdapter = std::make_unique<HWC2On1Adapter>(
-                reinterpret_cast<hwc_composer_device_1*>(device));
-
-        // Place the adapter in front of the device module.
-        mDevice = mAdapter.get();
-    } else {
-        mDevice = reinterpret_cast<hwc2_device_t*>(device);
-    }
-
-    return majorVersion;
-}
-
-uint32_t HwcHal::initWithFb(const hw_module_t* module)
-{
-    framebuffer_device_t* fb_device;
-    int error = framebuffer_open(module, &fb_device);
-    if (error != 0) {
-        ALOGE("Failed to open FB device (%s), aborting", strerror(-error));
-        abort();
-    }
-
-    mFbAdapter = std::make_unique<HWC2OnFbAdapter>(fb_device);
-    mDevice = mFbAdapter.get();
-
-    return 0;
-}
-
-void HwcHal::initCapabilities()
-{
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<int32_t> caps(count);
-    mDevice->getCapabilities(mDevice, &count, caps.data());
-    caps.resize(count);
-
-    mCapabilities.reserve(count);
-    for (auto cap : caps) {
-        mCapabilities.insert(static_cast<hwc2_capability_t>(cap));
-    }
-}
-
-template<typename T>
-void HwcHal::initDispatch(hwc2_function_descriptor_t desc, T* outPfn)
-{
-    auto pfn = mDevice->getFunction(mDevice, desc);
-    if (!pfn) {
-        LOG_ALWAYS_FATAL("failed to get hwcomposer2 function %d", desc);
-    }
-
-    *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void HwcHal::initDispatch()
-{
-    initDispatch(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
-            &mDispatch.acceptDisplayChanges);
-    initDispatch(HWC2_FUNCTION_CREATE_LAYER, &mDispatch.createLayer);
-    initDispatch(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY,
-            &mDispatch.createVirtualDisplay);
-    initDispatch(HWC2_FUNCTION_DESTROY_LAYER, &mDispatch.destroyLayer);
-    initDispatch(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
-            &mDispatch.destroyVirtualDisplay);
-    initDispatch(HWC2_FUNCTION_DUMP, &mDispatch.dump);
-    initDispatch(HWC2_FUNCTION_GET_ACTIVE_CONFIG, &mDispatch.getActiveConfig);
-    initDispatch(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
-            &mDispatch.getChangedCompositionTypes);
-    initDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
-            &mDispatch.getClientTargetSupport);
-    initDispatch(HWC2_FUNCTION_GET_COLOR_MODES, &mDispatch.getColorModes);
-    initDispatch(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE,
-            &mDispatch.getDisplayAttribute);
-    initDispatch(HWC2_FUNCTION_GET_DISPLAY_CONFIGS,
-            &mDispatch.getDisplayConfigs);
-    initDispatch(HWC2_FUNCTION_GET_DISPLAY_NAME, &mDispatch.getDisplayName);
-    initDispatch(HWC2_FUNCTION_GET_DISPLAY_REQUESTS,
-            &mDispatch.getDisplayRequests);
-    initDispatch(HWC2_FUNCTION_GET_DISPLAY_TYPE, &mDispatch.getDisplayType);
-    initDispatch(HWC2_FUNCTION_GET_DOZE_SUPPORT, &mDispatch.getDozeSupport);
-    initDispatch(HWC2_FUNCTION_GET_HDR_CAPABILITIES,
-            &mDispatch.getHdrCapabilities);
-    initDispatch(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
-            &mDispatch.getMaxVirtualDisplayCount);
-    initDispatch(HWC2_FUNCTION_GET_RELEASE_FENCES,
-            &mDispatch.getReleaseFences);
-    initDispatch(HWC2_FUNCTION_PRESENT_DISPLAY, &mDispatch.presentDisplay);
-    initDispatch(HWC2_FUNCTION_REGISTER_CALLBACK,
-            &mDispatch.registerCallback);
-    initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG, &mDispatch.setActiveConfig);
-    initDispatch(HWC2_FUNCTION_SET_CLIENT_TARGET, &mDispatch.setClientTarget);
-    initDispatch(HWC2_FUNCTION_SET_COLOR_MODE, &mDispatch.setColorMode);
-    initDispatch(HWC2_FUNCTION_SET_COLOR_TRANSFORM,
-            &mDispatch.setColorTransform);
-    initDispatch(HWC2_FUNCTION_SET_CURSOR_POSITION,
-            &mDispatch.setCursorPosition);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
-            &mDispatch.setLayerBlendMode);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_BUFFER, &mDispatch.setLayerBuffer);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_COLOR, &mDispatch.setLayerColor);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
-            &mDispatch.setLayerCompositionType);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_DATASPACE,
-            &mDispatch.setLayerDataspace);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME,
-            &mDispatch.setLayerDisplayFrame);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA,
-            &mDispatch.setLayerPlaneAlpha);
-
-    if (hasCapability(HWC2_CAPABILITY_SIDEBAND_STREAM)) {
-        initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM,
-                &mDispatch.setLayerSidebandStream);
-    }
-
-    initDispatch(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP,
-            &mDispatch.setLayerSourceCrop);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
-            &mDispatch.setLayerSurfaceDamage);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_TRANSFORM,
-            &mDispatch.setLayerTransform);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
-            &mDispatch.setLayerVisibleRegion);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_Z_ORDER, &mDispatch.setLayerZOrder);
-    initDispatch(HWC2_FUNCTION_SET_OUTPUT_BUFFER, &mDispatch.setOutputBuffer);
-    initDispatch(HWC2_FUNCTION_SET_POWER_MODE, &mDispatch.setPowerMode);
-    initDispatch(HWC2_FUNCTION_SET_VSYNC_ENABLED, &mDispatch.setVsyncEnabled);
-    initDispatch(HWC2_FUNCTION_VALIDATE_DISPLAY, &mDispatch.validateDisplay);
-}
-
-bool HwcHal::hasCapability(hwc2_capability_t capability) {
-    return (mCapabilities.count(capability) > 0);
-}
-
-Return<void> HwcHal::getCapabilities(getCapabilities_cb hidl_cb)
-{
-    std::vector<Capability> caps;
-    caps.reserve(mCapabilities.size());
-    for (auto cap : mCapabilities) {
-        switch (cap) {
-            case HWC2_CAPABILITY_SIDEBAND_STREAM:
-            case HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM:
-            case HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE:
-                caps.push_back(static_cast<Capability>(cap));
-                break;
-            default:
-                // not all HWC2 caps are defined in HIDL
-                break;
-        }
-    }
-
-    hidl_vec<Capability> caps_reply;
-    caps_reply.setToExternal(caps.data(), caps.size());
-    hidl_cb(caps_reply);
-
-    return Void();
-}
-
-Return<void> HwcHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
-{
-    uint32_t len = 0;
-    mDispatch.dump(mDevice, &len, nullptr);
-
-    std::vector<char> buf(len + 1);
-    mDispatch.dump(mDevice, &len, buf.data());
-    buf.resize(len + 1);
-    buf[len] = '\0';
-
-    hidl_string buf_reply;
-    buf_reply.setToExternal(buf.data(), len);
-    hidl_cb(buf_reply);
-
-    return Void();
-}
-
-Return<void> HwcHal::createClient(createClient_cb hidl_cb)
-{
-    Error err = Error::NONE;
-    sp<ComposerClient> client;
-
-    {
-        std::unique_lock<std::mutex> lock(mClientMutex);
-
-        if (mClient != nullptr) {
-            // In surface flinger we delete a composer client on one thread and
-            // then create a new client on another thread. Although surface
-            // flinger ensures the calls are made in that sequence (destroy and
-            // then create), sometimes the calls land in the composer service
-            // inverted (create and then destroy). Wait for a brief period to
-            // see if the existing client is destroyed.
-            ALOGI("HwcHal::createClient: Client already exists. Waiting for"
-                    " it to be destroyed.");
-            mClientDestroyedWait.wait_for(lock, 1s,
-                    [this] { return mClient == nullptr; });
-            std::string doneMsg = mClient == nullptr ?
-                    "Existing client was destroyed." :
-                    "Existing client was never destroyed!";
-            ALOGI("HwcHal::createClient: Done waiting. %s", doneMsg.c_str());
-        }
-
-        // only one client is allowed
-        if (mClient == nullptr) {
-            client = new ComposerClient(*this);
-            client->initialize();
-            mClient = client;
-        } else {
-            err = Error::NO_RESOURCES;
-        }
-    }
-
-    hidl_cb(err, client);
-
-    return Void();
-}
-
-sp<ComposerClient> HwcHal::getClient()
-{
-    std::lock_guard<std::mutex> lock(mClientMutex);
-    return (mClient != nullptr) ? mClient.promote() : nullptr;
-}
-
-void HwcHal::removeClient()
-{
-    std::lock_guard<std::mutex> lock(mClientMutex);
-    mClient = nullptr;
-    mClientDestroyedWait.notify_all();
-}
-
-void HwcHal::hotplugHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display, int32_t connected)
-{
-    auto hal = reinterpret_cast<HwcHal*>(callbackData);
-    auto client = hal->getClient();
-    if (client != nullptr) {
-        client->onHotplug(display,
-                static_cast<IComposerCallback::Connection>(connected));
-    }
-}
-
-void HwcHal::refreshHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display)
-{
-    auto hal = reinterpret_cast<HwcHal*>(callbackData);
-    hal->mMustValidateDisplay = true;
-
-    auto client = hal->getClient();
-    if (client != nullptr) {
-        client->onRefresh(display);
-    }
-}
-
-void HwcHal::vsyncHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display, int64_t timestamp)
-{
-    auto hal = reinterpret_cast<HwcHal*>(callbackData);
-    auto client = hal->getClient();
-    if (client != nullptr) {
-        client->onVsync(display, timestamp);
-    }
-}
-
-void HwcHal::enableCallback(bool enable)
-{
-    if (enable) {
-        mMustValidateDisplay = true;
-
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
-                reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
-                reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
-                reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
-    } else {
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
-                nullptr);
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
-                nullptr);
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
-                nullptr);
-    }
-}
-
-uint32_t HwcHal::getMaxVirtualDisplayCount()
-{
-    return mDispatch.getMaxVirtualDisplayCount(mDevice);
-}
-
-Error HwcHal::createVirtualDisplay(uint32_t width, uint32_t height,
-    PixelFormat* format, Display* outDisplay)
-{
-    int32_t hwc_format = static_cast<int32_t>(*format);
-    int32_t err = mDispatch.createVirtualDisplay(mDevice, width, height,
-            &hwc_format, outDisplay);
-    *format = static_cast<PixelFormat>(hwc_format);
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::destroyVirtualDisplay(Display display)
-{
-    int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::createLayer(Display display, Layer* outLayer)
-{
-    int32_t err = mDispatch.createLayer(mDevice, display, outLayer);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::destroyLayer(Display display, Layer layer)
-{
-    int32_t err = mDispatch.destroyLayer(mDevice, display, layer);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getActiveConfig(Display display, Config* outConfig)
-{
-    int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getClientTargetSupport(Display display,
-        uint32_t width, uint32_t height,
-        PixelFormat format, Dataspace dataspace)
-{
-    int32_t err = mDispatch.getClientTargetSupport(mDevice, display,
-            width, height, static_cast<int32_t>(format),
-            static_cast<int32_t>(dataspace));
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getColorModes(Display display, hidl_vec<ColorMode>* outModes)
-{
-    uint32_t count = 0;
-    int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    outModes->resize(count);
-    err = mDispatch.getColorModes(mDevice, display, &count,
-            reinterpret_cast<std::underlying_type<ColorMode>::type*>(
-                outModes->data()));
-    if (err != HWC2_ERROR_NONE) {
-        *outModes = hidl_vec<ColorMode>();
-        return static_cast<Error>(err);
-    }
-
-    return Error::NONE;
-}
-
-Error HwcHal::getDisplayAttribute(Display display, Config config,
-        IComposerClient::Attribute attribute, int32_t* outValue)
-{
-    int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config,
-            static_cast<int32_t>(attribute), outValue);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs)
-{
-    uint32_t count = 0;
-    int32_t err = mDispatch.getDisplayConfigs(mDevice, display,
-            &count, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    outConfigs->resize(count);
-    err = mDispatch.getDisplayConfigs(mDevice, display,
-            &count, outConfigs->data());
-    if (err != HWC2_ERROR_NONE) {
-        *outConfigs = hidl_vec<Config>();
-        return static_cast<Error>(err);
-    }
-
-    return Error::NONE;
-}
-
-Error HwcHal::getDisplayName(Display display, hidl_string* outName)
-{
-    uint32_t count = 0;
-    int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    std::vector<char> buf(count + 1);
-    err = mDispatch.getDisplayName(mDevice, display, &count, buf.data());
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-    buf.resize(count + 1);
-    buf[count] = '\0';
-
-    *outName = buf.data();
-
-    return Error::NONE;
-}
-
-Error HwcHal::getDisplayType(Display display,
-        IComposerClient::DisplayType* outType)
-{
-    int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID;
-    int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type);
-    *outType = static_cast<IComposerClient::DisplayType>(hwc_type);
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getDozeSupport(Display display, bool* outSupport)
-{
-    int32_t hwc_support = 0;
-    int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support);
-    *outSupport = hwc_support;
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
-        float* outMaxLuminance, float* outMaxAverageLuminance,
-        float* outMinLuminance)
-{
-    uint32_t count = 0;
-    int32_t err = mDispatch.getHdrCapabilities(mDevice, display, &count,
-            nullptr, outMaxLuminance, outMaxAverageLuminance,
-            outMinLuminance);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    outTypes->resize(count);
-    err = mDispatch.getHdrCapabilities(mDevice, display, &count,
-            reinterpret_cast<std::underlying_type<Hdr>::type*>(
-                outTypes->data()), outMaxLuminance,
-            outMaxAverageLuminance, outMinLuminance);
-    if (err != HWC2_ERROR_NONE) {
-        *outTypes = hidl_vec<Hdr>();
-        return static_cast<Error>(err);
-    }
-
-    return Error::NONE;
-}
-
-Error HwcHal::setActiveConfig(Display display, Config config)
-{
-    int32_t err = mDispatch.setActiveConfig(mDevice, display, config);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setColorMode(Display display, ColorMode mode)
-{
-    int32_t err = mDispatch.setColorMode(mDevice, display,
-            static_cast<int32_t>(mode));
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setPowerMode(Display display, IComposerClient::PowerMode mode)
-{
-    int32_t err = mDispatch.setPowerMode(mDevice, display,
-            static_cast<int32_t>(mode));
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setVsyncEnabled(Display display, IComposerClient::Vsync enabled)
-{
-    int32_t err = mDispatch.setVsyncEnabled(mDevice, display,
-            static_cast<int32_t>(enabled));
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setColorTransform(Display display, const float* matrix,
-        int32_t hint)
-{
-    int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setClientTarget(Display display, buffer_handle_t target,
-        int32_t acquireFence, int32_t dataspace,
-        const std::vector<hwc_rect_t>& damage)
-{
-    hwc_region region = { damage.size(), damage.data() };
-    int32_t err = mDispatch.setClientTarget(mDevice, display, target,
-            acquireFence, dataspace, region);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setOutputBuffer(Display display, buffer_handle_t buffer,
-        int32_t releaseFence)
-{
-    int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer,
-            releaseFence);
-    // unlike in setClientTarget, releaseFence is owned by us
-    if (err == HWC2_ERROR_NONE && releaseFence >= 0) {
-        close(releaseFence);
-    }
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::validateDisplay(Display display,
-        std::vector<Layer>* outChangedLayers,
-        std::vector<IComposerClient::Composition>* outCompositionTypes,
-        uint32_t* outDisplayRequestMask,
-        std::vector<Layer>* outRequestedLayers,
-        std::vector<uint32_t>* outRequestMasks)
-{
-    uint32_t types_count = 0;
-    uint32_t reqs_count = 0;
-    int32_t err = mDispatch.validateDisplay(mDevice, display,
-            &types_count, &reqs_count);
-    mMustValidateDisplay = false;
-
-    if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
-        return static_cast<Error>(err);
-    }
-
-    err = mDispatch.getChangedCompositionTypes(mDevice, display,
-            &types_count, nullptr, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    outChangedLayers->resize(types_count);
-    outCompositionTypes->resize(types_count);
-    err = mDispatch.getChangedCompositionTypes(mDevice, display,
-            &types_count, outChangedLayers->data(),
-            reinterpret_cast<
-            std::underlying_type<IComposerClient::Composition>::type*>(
-                outCompositionTypes->data()));
-    if (err != HWC2_ERROR_NONE) {
-        outChangedLayers->clear();
-        outCompositionTypes->clear();
-        return static_cast<Error>(err);
-    }
-
-    int32_t display_reqs = 0;
-    err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs,
-            &reqs_count, nullptr, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        outChangedLayers->clear();
-        outCompositionTypes->clear();
-        return static_cast<Error>(err);
-    }
-
-    outRequestedLayers->resize(reqs_count);
-    outRequestMasks->resize(reqs_count);
-    err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs,
-            &reqs_count, outRequestedLayers->data(),
-            reinterpret_cast<int32_t*>(outRequestMasks->data()));
-    if (err != HWC2_ERROR_NONE) {
-        outChangedLayers->clear();
-        outCompositionTypes->clear();
-
-        outRequestedLayers->clear();
-        outRequestMasks->clear();
-        return static_cast<Error>(err);
-    }
-
-    *outDisplayRequestMask = display_reqs;
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::acceptDisplayChanges(Display display)
-{
-    int32_t err = mDispatch.acceptDisplayChanges(mDevice, display);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::presentDisplay(Display display, int32_t* outPresentFence,
-        std::vector<Layer>* outLayers, std::vector<int32_t>* outReleaseFences)
-{
-    if (mMustValidateDisplay) {
-        return Error::NOT_VALIDATED;
-    }
-
-    *outPresentFence = -1;
-    int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    uint32_t count = 0;
-    err = mDispatch.getReleaseFences(mDevice, display, &count,
-            nullptr, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        ALOGW("failed to get release fences");
-        return Error::NONE;
-    }
-
-    outLayers->resize(count);
-    outReleaseFences->resize(count);
-    err = mDispatch.getReleaseFences(mDevice, display, &count,
-            outLayers->data(), outReleaseFences->data());
-    if (err != HWC2_ERROR_NONE) {
-        ALOGW("failed to get release fences");
-        outLayers->clear();
-        outReleaseFences->clear();
-        return Error::NONE;
-    }
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerCursorPosition(Display display, Layer layer,
-        int32_t x, int32_t y)
-{
-    int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerBuffer(Display display, Layer layer,
-        buffer_handle_t buffer, int32_t acquireFence)
-{
-    int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer,
-            buffer, acquireFence);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerSurfaceDamage(Display display, Layer layer,
-        const std::vector<hwc_rect_t>& damage)
-{
-    hwc_region region = { damage.size(), damage.data() };
-    int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer,
-            region);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerBlendMode(Display display, Layer layer, int32_t mode)
-{
-    int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerColor(Display display, Layer layer,
-        IComposerClient::Color color)
-{
-    hwc_color_t hwc_color{color.r, color.g, color.b, color.a};
-    int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerCompositionType(Display display, Layer layer,
-        int32_t type)
-{
-    int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer,
-            type);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerDataspace(Display display, Layer layer,
-        int32_t dataspace)
-{
-    int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer,
-            dataspace);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerDisplayFrame(Display display, Layer layer,
-        const hwc_rect_t& frame)
-{
-    int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer,
-            frame);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerPlaneAlpha(Display display, Layer layer, float alpha)
-{
-    int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer,
-            alpha);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerSidebandStream(Display display, Layer layer,
-        buffer_handle_t stream)
-{
-    int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer,
-            stream);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerSourceCrop(Display display, Layer layer,
-        const hwc_frect_t& crop)
-{
-    int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerTransform(Display display, Layer layer,
-        int32_t transform)
-{
-    int32_t err = mDispatch.setLayerTransform(mDevice, display, layer,
-            transform);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerVisibleRegion(Display display, Layer layer,
-        const std::vector<hwc_rect_t>& visible)
-{
-    hwc_region_t region = { visible.size(), visible.data() };
-    int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer,
-            region);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerZOrder(Display display, Layer layer, uint32_t z)
-{
-    int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z);
-    return static_cast<Error>(err);
-}
-
-IComposer* HIDL_FETCH_IComposer(const char*)
-{
-    const hw_module_t* module = nullptr;
-    int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
-    if (err) {
-        ALOGI("falling back to FB HAL");
-        err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    }
-    if (err) {
-        ALOGE("failed to get hwcomposer or fb module");
-        return nullptr;
-    }
-
-    return new HwcHal(module);
-}
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/composer/2.1/default/Hwc.h b/graphics/composer/2.1/default/Hwc.h
deleted file mode 100644
index e3f5ce6..0000000
--- a/graphics/composer/2.1/default/Hwc.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
-#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
-
-#include <atomic>
-#include <condition_variable>
-#include <memory>
-#include <mutex>
-#include <unordered_set>
-#include <vector>
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-#include "ComposerBase.h"
-
-namespace android {
-    class HWC2On1Adapter;
-    class HWC2OnFbAdapter;
-}
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::hardware::graphics::common::V1_0::Transform;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Hdr;
-
-class ComposerClient;
-
-class HwcHal : public IComposer, public ComposerBase {
-public:
-    HwcHal(const hw_module_t* module);
-    virtual ~HwcHal();
-
-    // IComposer interface
-    Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
-    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-    Return<void> createClient(createClient_cb hidl_cb) override;
-
-    // ComposerBase interface
-    bool hasCapability(hwc2_capability_t capability) override;
-    void removeClient() override;
-    void enableCallback(bool enable) override;
-    uint32_t getMaxVirtualDisplayCount() override;
-    Error createVirtualDisplay(uint32_t width, uint32_t height,
-        PixelFormat* format, Display* outDisplay) override;
-    Error destroyVirtualDisplay(Display display) override;
-
-    Error createLayer(Display display, Layer* outLayer) override;
-    Error destroyLayer(Display display, Layer layer) override;
-
-    Error getActiveConfig(Display display, Config* outConfig) override;
-    Error getClientTargetSupport(Display display,
-            uint32_t width, uint32_t height,
-            PixelFormat format, Dataspace dataspace) override;
-    Error getColorModes(Display display,
-            hidl_vec<ColorMode>* outModes) override;
-    Error getDisplayAttribute(Display display, Config config,
-            IComposerClient::Attribute attribute, int32_t* outValue) override;
-    Error getDisplayConfigs(Display display,
-            hidl_vec<Config>* outConfigs) override;
-    Error getDisplayName(Display display, hidl_string* outName) override;
-    Error getDisplayType(Display display,
-            IComposerClient::DisplayType* outType) override;
-    Error getDozeSupport(Display display, bool* outSupport) override;
-    Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
-            float* outMaxLuminance, float* outMaxAverageLuminance,
-            float* outMinLuminance) override;
-
-    Error setActiveConfig(Display display, Config config) override;
-    Error setColorMode(Display display, ColorMode mode) override;
-    Error setPowerMode(Display display,
-            IComposerClient::PowerMode mode) override;
-    Error setVsyncEnabled(Display display,
-            IComposerClient::Vsync enabled) override;
-
-    Error setColorTransform(Display display, const float* matrix,
-            int32_t hint) override;
-    Error setClientTarget(Display display, buffer_handle_t target,
-            int32_t acquireFence, int32_t dataspace,
-            const std::vector<hwc_rect_t>& damage) override;
-    Error setOutputBuffer(Display display, buffer_handle_t buffer,
-            int32_t releaseFence) override;
-    Error validateDisplay(Display display,
-            std::vector<Layer>* outChangedLayers,
-            std::vector<IComposerClient::Composition>* outCompositionTypes,
-            uint32_t* outDisplayRequestMask,
-            std::vector<Layer>* outRequestedLayers,
-            std::vector<uint32_t>* outRequestMasks) override;
-    Error acceptDisplayChanges(Display display) override;
-    Error presentDisplay(Display display, int32_t* outPresentFence,
-            std::vector<Layer>* outLayers,
-            std::vector<int32_t>* outReleaseFences) override;
-
-    Error setLayerCursorPosition(Display display, Layer layer,
-            int32_t x, int32_t y) override;
-    Error setLayerBuffer(Display display, Layer layer,
-            buffer_handle_t buffer, int32_t acquireFence) override;
-    Error setLayerSurfaceDamage(Display display, Layer layer,
-            const std::vector<hwc_rect_t>& damage) override;
-    Error setLayerBlendMode(Display display, Layer layer,
-            int32_t mode) override;
-    Error setLayerColor(Display display, Layer layer,
-            IComposerClient::Color color) override;
-    Error setLayerCompositionType(Display display, Layer layer,
-            int32_t type) override;
-    Error setLayerDataspace(Display display, Layer layer,
-            int32_t dataspace) override;
-    Error setLayerDisplayFrame(Display display, Layer layer,
-            const hwc_rect_t& frame) override;
-    Error setLayerPlaneAlpha(Display display, Layer layer,
-            float alpha) override;
-    Error setLayerSidebandStream(Display display, Layer layer,
-            buffer_handle_t stream) override;
-    Error setLayerSourceCrop(Display display, Layer layer,
-            const hwc_frect_t& crop) override;
-    Error setLayerTransform(Display display, Layer layer,
-            int32_t transform) override;
-    Error setLayerVisibleRegion(Display display, Layer layer,
-            const std::vector<hwc_rect_t>& visible) override;
-    Error setLayerZOrder(Display display, Layer layer, uint32_t z) override;
-
-private:
-    uint32_t initWithHwc(const hw_module_t* module);
-    uint32_t initWithFb(const hw_module_t* module);
-
-    void initCapabilities();
-
-    template<typename T>
-    void initDispatch(hwc2_function_descriptor_t desc, T* outPfn);
-    void initDispatch();
-
-    sp<ComposerClient> getClient();
-
-    static void hotplugHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display, int32_t connected);
-    static void refreshHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display);
-    static void vsyncHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display, int64_t timestamp);
-
-    hwc2_device_t* mDevice;
-
-    std::unordered_set<hwc2_capability_t> mCapabilities;
-
-    struct {
-        HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges;
-        HWC2_PFN_CREATE_LAYER createLayer;
-        HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay;
-        HWC2_PFN_DESTROY_LAYER destroyLayer;
-        HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay;
-        HWC2_PFN_DUMP dump;
-        HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig;
-        HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes;
-        HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport;
-        HWC2_PFN_GET_COLOR_MODES getColorModes;
-        HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute;
-        HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs;
-        HWC2_PFN_GET_DISPLAY_NAME getDisplayName;
-        HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests;
-        HWC2_PFN_GET_DISPLAY_TYPE getDisplayType;
-        HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport;
-        HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities;
-        HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount;
-        HWC2_PFN_GET_RELEASE_FENCES getReleaseFences;
-        HWC2_PFN_PRESENT_DISPLAY presentDisplay;
-        HWC2_PFN_REGISTER_CALLBACK registerCallback;
-        HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig;
-        HWC2_PFN_SET_CLIENT_TARGET setClientTarget;
-        HWC2_PFN_SET_COLOR_MODE setColorMode;
-        HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform;
-        HWC2_PFN_SET_CURSOR_POSITION setCursorPosition;
-        HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode;
-        HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer;
-        HWC2_PFN_SET_LAYER_COLOR setLayerColor;
-        HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType;
-        HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace;
-        HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame;
-        HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha;
-        HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream;
-        HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop;
-        HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage;
-        HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform;
-        HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion;
-        HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder;
-        HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer;
-        HWC2_PFN_SET_POWER_MODE setPowerMode;
-        HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled;
-        HWC2_PFN_VALIDATE_DISPLAY validateDisplay;
-    } mDispatch;
-
-    std::mutex mClientMutex;
-    std::condition_variable mClientDestroyedWait;
-    wp<ComposerClient> mClient;
-
-    std::atomic<bool> mMustValidateDisplay;
-
-    // If the HWC implementation version is < 2.0, use an adapter to interface
-    // between HWC 2.0 <-> HWC 1.X.
-    std::unique_ptr<HWC2On1Adapter> mAdapter;
-
-    // If there is no HWC implementation, use an adapter to interface between
-    // HWC 2.0 <-> FB HAL.
-    std::unique_ptr<HWC2OnFbAdapter> mFbAdapter;
-};
-
-extern "C" IComposer* HIDL_FETCH_IComposer(const char* name);
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
diff --git a/graphics/composer/2.1/default/passthrough.cpp b/graphics/composer/2.1/default/passthrough.cpp
new file mode 100644
index 0000000..ef7ed7c
--- /dev/null
+++ b/graphics/composer/2.1/default/passthrough.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-passthrough/2.1/HwcLoader.h>
+
+using android::hardware::graphics::composer::V2_1::IComposer;
+using android::hardware::graphics::composer::V2_1::passthrough::HwcLoader;
+
+extern "C" IComposer* HIDL_FETCH_IComposer(const char* /* name */) {
+    return HwcLoader::load();
+}
diff --git a/graphics/composer/2.1/utils/command-buffer/Android.bp b/graphics/composer/2.1/utils/command-buffer/Android.bp
index e8d41c2..140d9bb 100644
--- a/graphics/composer/2.1/utils/command-buffer/Android.bp
+++ b/graphics/composer/2.1/utils/command-buffer/Android.bp
@@ -2,6 +2,15 @@
     name: "android.hardware.graphics.composer@2.1-command-buffer",
     defaults: ["hidl_defaults"],
     vendor_available: true,
-    shared_libs: ["android.hardware.graphics.composer@2.1"],
+    shared_libs: [
+        "android.hardware.graphics.composer@2.1",
+        "libfmq",
+        "libsync",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.composer@2.1",
+        "libfmq",
+        "libsync",
+    ],
     export_include_dirs: ["include"],
 }
diff --git a/graphics/composer/2.1/utils/hal/Android.bp b/graphics/composer/2.1/utils/hal/Android.bp
new file mode 100644
index 0000000..f24e768
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_headers {
+    name: "android.hardware.graphics.composer@2.1-hal",
+    defaults: ["hidl_defaults"],
+    vendor_available: true,
+    shared_libs: [
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware", // TODO remove hwcomposer2.h dependency
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+    ],
+    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.1/utils/hal/include/composer-hal/2.1/Composer.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
new file mode 100644
index 0000000..581dc96
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Composer.h included without LOG_TAG"
+#endif
+
+#include <array>
+#include <chrono>
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
+#include <composer-hal/2.1/ComposerClient.h>
+#include <composer-hal/2.1/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+namespace detail {
+
+// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerImpl : public Interface {
+   public:
+    static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) {
+        return std::make_unique<ComposerImpl>(std::move(hal));
+    }
+
+    ComposerImpl(std::unique_ptr<Hal> hal) : mHal(std::move(hal)) {}
+
+    // IComposer 2.1 interface
+
+    Return<void> getCapabilities(IComposer::getCapabilities_cb hidl_cb) override {
+        const std::array<IComposer::Capability, 3> all_caps = {{
+            IComposer::Capability::SIDEBAND_STREAM,
+            IComposer::Capability::SKIP_CLIENT_COLOR_TRANSFORM,
+            IComposer::Capability::PRESENT_FENCE_IS_NOT_RELIABLE,
+        }};
+
+        std::vector<IComposer::Capability> caps;
+        for (auto cap : all_caps) {
+            if (mHal->hasCapability(static_cast<hwc2_capability_t>(cap))) {
+                caps.push_back(cap);
+            }
+        }
+
+        hidl_vec<IComposer::Capability> caps_reply;
+        caps_reply.setToExternal(caps.data(), caps.size());
+        hidl_cb(caps_reply);
+        return Void();
+    }
+
+    Return<void> dumpDebugInfo(IComposer::dumpDebugInfo_cb hidl_cb) override {
+        hidl_cb(mHal->dumpDebugInfo());
+        return Void();
+    }
+
+    Return<void> createClient(IComposer::createClient_cb hidl_cb) override {
+        std::unique_lock<std::mutex> lock(mClientMutex);
+        if (!waitForClientDestroyedLocked(lock)) {
+            hidl_cb(Error::NO_RESOURCES, nullptr);
+            return Void();
+        }
+
+        sp<IComposerClient> client = createClient();
+        if (!client) {
+            hidl_cb(Error::NO_RESOURCES, nullptr);
+            return Void();
+        }
+
+        mClient = client;
+        hidl_cb(Error::NONE, client);
+        return Void();
+    }
+
+   protected:
+    bool waitForClientDestroyedLocked(std::unique_lock<std::mutex>& lock) {
+        if (mClient != nullptr) {
+            using namespace std::chrono_literals;
+
+            // In surface flinger we delete a composer client on one thread and
+            // then create a new client on another thread. Although surface
+            // flinger ensures the calls are made in that sequence (destroy and
+            // then create), sometimes the calls land in the composer service
+            // inverted (create and then destroy). Wait for a brief period to
+            // see if the existing client is destroyed.
+            ALOGD("waiting for previous client to be destroyed");
+            mClientDestroyedCondition.wait_for(
+                lock, 1s, [this]() -> bool { return mClient.promote() == nullptr; });
+            if (mClient.promote() != nullptr) {
+                ALOGD("previous client was not destroyed");
+            } else {
+                mClient.clear();
+            }
+        }
+
+        return mClient == nullptr;
+    }
+
+    void onClientDestroyed() {
+        std::lock_guard<std::mutex> lock(mClientMutex);
+        mClient.clear();
+        mClientDestroyedCondition.notify_all();
+    }
+
+    virtual IComposerClient* createClient() {
+        auto client = ComposerClient::create(mHal.get());
+        if (!client) {
+            return nullptr;
+        }
+
+        auto clientDestroyed = [this]() { onClientDestroyed(); };
+        client->setOnClientDestroyed(clientDestroyed);
+
+        return client.release();
+    }
+
+    const std::unique_ptr<Hal> mHal;
+
+    std::mutex mClientMutex;
+    wp<IComposerClient> mClient;
+    std::condition_variable mClientDestroyedCondition;
+};
+
+}  // namespace detail
+
+using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
new file mode 100644
index 0000000..86525b8
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerClient.h included without LOG_TAG"
+#endif
+
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
+#include <composer-hal/2.1/ComposerCommandEngine.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#include <composer-hal/2.1/ComposerResources.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+namespace detail {
+
+// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerClientImpl : public Interface {
+   public:
+    static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
+        auto client = std::make_unique<ComposerClientImpl>(hal);
+        return client->init() ? std::move(client) : nullptr;
+    }
+
+    ComposerClientImpl(Hal* hal) : mHal(hal) {}
+
+    virtual ~ComposerClientImpl() {
+        // not initialized
+        if (!mCommandEngine) {
+            return;
+        }
+
+        ALOGD("destroying composer client");
+
+        mHal->unregisterEventCallback();
+        destroyResources();
+        if (mOnClientDestroyed) {
+            mOnClientDestroyed();
+        }
+
+        ALOGD("removed composer client");
+    }
+
+    bool init() {
+        mResources = createResources();
+        if (!mResources) {
+            ALOGE("failed to create composer resources");
+            return false;
+        }
+
+        mCommandEngine = createCommandEngine();
+
+        return true;
+    }
+
+    void setOnClientDestroyed(std::function<void()> onClientDestroyed) {
+        mOnClientDestroyed = onClientDestroyed;
+    }
+
+    // IComposerClient 2.1 interface
+
+    class HalEventCallback : public Hal::EventCallback {
+       public:
+        HalEventCallback(const sp<IComposerCallback> callback, ComposerResources* resources)
+            : mCallback(callback), mResources(resources) {}
+
+        void onHotplug(Display display, IComposerCallback::Connection connected) {
+            if (connected == IComposerCallback::Connection::CONNECTED) {
+                mResources->addPhysicalDisplay(display);
+            } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
+                mResources->removeDisplay(display);
+            }
+
+            auto ret = mCallback->onHotplug(display, connected);
+            ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str());
+        }
+
+        void onRefresh(Display display) {
+            auto ret = mCallback->onRefresh(display);
+            ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str());
+        }
+
+        void onVsync(Display display, int64_t timestamp) {
+            auto ret = mCallback->onVsync(display, timestamp);
+            ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str());
+        }
+
+       protected:
+        const sp<IComposerCallback> mCallback;
+        ComposerResources* const mResources;
+    };
+
+    Return<void> registerCallback(const sp<IComposerCallback>& callback) override {
+        // no locking as we require this function to be called only once
+        mHalEventCallback = std::make_unique<HalEventCallback>(callback, mResources.get());
+        mHal->registerEventCallback(mHalEventCallback.get());
+        return Void();
+    }
+
+    Return<uint32_t> getMaxVirtualDisplayCount() override {
+        return mHal->getMaxVirtualDisplayCount();
+    }
+
+    Return<void> createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint,
+                                      uint32_t outputBufferSlotCount,
+                                      IComposerClient::createVirtualDisplay_cb hidl_cb) override {
+        Display display = 0;
+        Error err = mHal->createVirtualDisplay(width, height, &formatHint, &display);
+        if (err == Error::NONE) {
+            mResources->addVirtualDisplay(display, outputBufferSlotCount);
+        }
+
+        hidl_cb(err, display, formatHint);
+        return Void();
+    }
+
+    Return<Error> destroyVirtualDisplay(Display display) override {
+        Error err = mHal->destroyVirtualDisplay(display);
+        if (err == Error::NONE) {
+            mResources->removeDisplay(display);
+        }
+
+        return err;
+    }
+
+    Return<void> createLayer(Display display, uint32_t bufferSlotCount,
+                             IComposerClient::createLayer_cb hidl_cb) override {
+        Layer layer = 0;
+        Error err = mHal->createLayer(display, &layer);
+        if (err == Error::NONE) {
+            err = mResources->addLayer(display, layer, bufferSlotCount);
+            if (err != Error::NONE) {
+                // The display entry may have already been removed by onHotplug.
+                // Note: We do not destroy the layer on this error as the hotplug
+                // disconnect invalidates the display id. The implementation should
+                // ensure all layers for the display are destroyed.
+                layer = 0;
+            }
+        }
+
+        hidl_cb(err, layer);
+        return Void();
+    }
+
+    Return<Error> destroyLayer(Display display, Layer layer) override {
+        Error err = mHal->destroyLayer(display, layer);
+        if (err == Error::NONE) {
+            mResources->removeLayer(display, layer);
+        }
+
+        return err;
+    }
+
+    Return<void> getActiveConfig(Display display,
+                                 IComposerClient::getActiveConfig_cb hidl_cb) override {
+        Config config = 0;
+        Error err = mHal->getActiveConfig(display, &config);
+        hidl_cb(err, config);
+        return Void();
+    }
+
+    Return<Error> getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                         PixelFormat format, Dataspace dataspace) override {
+        Error err = mHal->getClientTargetSupport(display, width, height, format, dataspace);
+        return err;
+    }
+
+    Return<void> getColorModes(Display display,
+                               IComposerClient::getColorModes_cb hidl_cb) override {
+        hidl_vec<ColorMode> modes;
+        Error err = mHal->getColorModes(display, &modes);
+        hidl_cb(err, modes);
+        return Void();
+    }
+
+    Return<void> getDisplayAttribute(Display display, Config config,
+                                     IComposerClient::Attribute attribute,
+                                     IComposerClient::getDisplayAttribute_cb hidl_cb) override {
+        int32_t value = 0;
+        Error err = mHal->getDisplayAttribute(display, config, attribute, &value);
+        hidl_cb(err, value);
+        return Void();
+    }
+
+    Return<void> getDisplayConfigs(Display display,
+                                   IComposerClient::getDisplayConfigs_cb hidl_cb) override {
+        hidl_vec<Config> configs;
+        Error err = mHal->getDisplayConfigs(display, &configs);
+        hidl_cb(err, configs);
+        return Void();
+    }
+
+    Return<void> getDisplayName(Display display,
+                                IComposerClient::getDisplayName_cb hidl_cb) override {
+        hidl_string name;
+        Error err = mHal->getDisplayName(display, &name);
+        hidl_cb(err, name);
+        return Void();
+    }
+
+    Return<void> getDisplayType(Display display,
+                                IComposerClient::getDisplayType_cb hidl_cb) override {
+        IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
+        Error err = mHal->getDisplayType(display, &type);
+        hidl_cb(err, type);
+        return Void();
+    }
+
+    Return<void> getDozeSupport(Display display,
+                                IComposerClient::getDozeSupport_cb hidl_cb) override {
+        bool support = false;
+        Error err = mHal->getDozeSupport(display, &support);
+        hidl_cb(err, support);
+        return Void();
+    }
+
+    Return<void> getHdrCapabilities(Display display,
+                                    IComposerClient::getHdrCapabilities_cb hidl_cb) override {
+        hidl_vec<Hdr> types;
+        float max_lumi = 0.0f;
+        float max_avg_lumi = 0.0f;
+        float min_lumi = 0.0f;
+        Error err = mHal->getHdrCapabilities(display, &types, &max_lumi, &max_avg_lumi, &min_lumi);
+        hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi);
+        return Void();
+    }
+
+    Return<Error> setActiveConfig(Display display, Config config) override {
+        Error err = mHal->setActiveConfig(display, config);
+        return err;
+    }
+
+    Return<Error> setColorMode(Display display, ColorMode mode) override {
+        Error err = mHal->setColorMode(display, mode);
+        return err;
+    }
+
+    Return<Error> setPowerMode(Display display, IComposerClient::PowerMode mode) override {
+        Error err = mHal->setPowerMode(display, mode);
+        return err;
+    }
+
+    Return<Error> setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override {
+        Error err = mHal->setVsyncEnabled(display, enabled);
+        return err;
+    }
+
+    Return<Error> setClientTargetSlotCount(Display display,
+                                           uint32_t clientTargetSlotCount) override {
+        return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount);
+    }
+
+    Return<Error> setInputCommandQueue(const MQDescriptorSync<uint32_t>& descriptor) override {
+        std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+        return mCommandEngine->setInputMQDescriptor(descriptor) ? Error::NONE : Error::NO_RESOURCES;
+    }
+
+    Return<void> getOutputCommandQueue(IComposerClient::getOutputCommandQueue_cb hidl_cb) override {
+        // no locking as we require this function to be called inside
+        // executeCommands_cb
+        auto outDescriptor = mCommandEngine->getOutputMQDescriptor();
+        if (outDescriptor) {
+            hidl_cb(Error::NONE, *outDescriptor);
+        } else {
+            hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
+        }
+
+        return Void();
+    }
+
+    Return<void> executeCommands(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+                                 IComposerClient::executeCommands_cb hidl_cb) override {
+        std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+        bool outChanged = false;
+        uint32_t outLength = 0;
+        hidl_vec<hidl_handle> outHandles;
+        Error error =
+            mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles);
+
+        hidl_cb(error, outChanged, outLength, outHandles);
+
+        mCommandEngine->reset();
+
+        return Void();
+    }
+
+   protected:
+    virtual std::unique_ptr<ComposerResources> createResources() {
+        return ComposerResources::create();
+    }
+
+    virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine() {
+        return std::make_unique<ComposerCommandEngine>(mHal, mResources.get());
+    }
+
+    void destroyResources() {
+        // We want to call hwc2_close here (and move hwc2_open to the
+        // constructor), with the assumption that hwc2_close would
+        //
+        //  - clean up all resources owned by the client
+        //  - make sure all displays are blank (since there is no layer)
+        //
+        // But since SF used to crash at this point, different hwcomposer2
+        // implementations behave differently on hwc2_close.  Our only portable
+        // choice really is to abort().  But that is not an option anymore
+        // because we might also have VTS or VR as clients that can come and go.
+        //
+        // Below we manually clean all resources (layers and virtual
+        // displays), and perform a presentDisplay afterwards.
+        mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) {
+            ALOGW("destroying client resources for display %" PRIu64, display);
+
+            for (auto layer : layers) {
+                mHal->destroyLayer(display, layer);
+            }
+
+            if (isVirtual) {
+                mHal->destroyVirtualDisplay(display);
+            } else {
+                ALOGW("performing a final presentDisplay");
+
+                std::vector<Layer> changedLayers;
+                std::vector<IComposerClient::Composition> compositionTypes;
+                uint32_t displayRequestMask = 0;
+                std::vector<Layer> requestedLayers;
+                std::vector<uint32_t> requestMasks;
+                mHal->validateDisplay(display, &changedLayers, &compositionTypes,
+                                      &displayRequestMask, &requestedLayers, &requestMasks);
+
+                mHal->acceptDisplayChanges(display);
+
+                int32_t presentFence = -1;
+                std::vector<Layer> releasedLayers;
+                std::vector<int32_t> releaseFences;
+                mHal->presentDisplay(display, &presentFence, &releasedLayers, &releaseFences);
+                if (presentFence >= 0) {
+                    close(presentFence);
+                }
+                for (auto fence : releaseFences) {
+                    if (fence >= 0) {
+                        close(fence);
+                    }
+                }
+            }
+        });
+
+        mResources.reset();
+    }
+
+    Hal* const mHal;
+
+    std::unique_ptr<ComposerResources> mResources;
+
+    std::mutex mCommandEngineMutex;
+    std::unique_ptr<ComposerCommandEngine> mCommandEngine;
+
+    std::function<void()> mOnClientDestroyed;
+    std::unique_ptr<HalEventCallback> mHalEventCallback;
+};
+
+}  // namespace detail
+
+using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
new file mode 100644
index 0000000..36aa64e
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
@@ -0,0 +1,594 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerCommandEngine.h included without LOG_TAG"
+#endif
+
+#include <vector>
+
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#include <composer-hal/2.1/ComposerResources.h>
+// TODO remove hwcomposer_defs.h dependency
+#include <hardware/hwcomposer_defs.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+// TODO own a CommandReaderBase rather than subclassing
+class ComposerCommandEngine : protected CommandReaderBase {
+   public:
+    ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
+        : mHal(hal), mResources(resources) {}
+
+    virtual ~ComposerCommandEngine() = default;
+
+    bool setInputMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor) {
+        return setMQDescriptor(descriptor);
+    }
+
+    Error execute(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles, bool* outQueueChanged,
+                  uint32_t* outCommandLength, hidl_vec<hidl_handle>* outCommandHandles) {
+        if (!readQueue(inLength, inHandles)) {
+            return Error::BAD_PARAMETER;
+        }
+
+        IComposerClient::Command command;
+        uint16_t length = 0;
+        while (!isEmpty()) {
+            if (!beginCommand(&command, &length)) {
+                break;
+            }
+
+            bool parsed = executeCommand(command, length);
+            endCommand();
+
+            if (!parsed) {
+                ALOGE("failed to parse command 0x%x, length %" PRIu16, command, length);
+                break;
+            }
+        }
+
+        if (!isEmpty()) {
+            return Error::BAD_PARAMETER;
+        }
+
+        return mWriter.writeQueue(outQueueChanged, outCommandLength, outCommandHandles)
+                   ? Error::NONE
+                   : Error::NO_RESOURCES;
+    }
+
+    const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter.getMQDescriptor(); }
+
+    void reset() {
+        CommandReaderBase::reset();
+        mWriter.reset();
+    }
+
+   protected:
+    virtual bool executeCommand(IComposerClient::Command command, uint16_t length) {
+        switch (command) {
+            case IComposerClient::Command::SELECT_DISPLAY:
+                return executeSelectDisplay(length);
+            case IComposerClient::Command::SELECT_LAYER:
+                return executeSelectLayer(length);
+            case IComposerClient::Command::SET_COLOR_TRANSFORM:
+                return executeSetColorTransform(length);
+            case IComposerClient::Command::SET_CLIENT_TARGET:
+                return executeSetClientTarget(length);
+            case IComposerClient::Command::SET_OUTPUT_BUFFER:
+                return executeSetOutputBuffer(length);
+            case IComposerClient::Command::VALIDATE_DISPLAY:
+                return executeValidateDisplay(length);
+            case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
+                return executePresentOrValidateDisplay(length);
+            case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
+                return executeAcceptDisplayChanges(length);
+            case IComposerClient::Command::PRESENT_DISPLAY:
+                return executePresentDisplay(length);
+            case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
+                return executeSetLayerCursorPosition(length);
+            case IComposerClient::Command::SET_LAYER_BUFFER:
+                return executeSetLayerBuffer(length);
+            case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
+                return executeSetLayerSurfaceDamage(length);
+            case IComposerClient::Command::SET_LAYER_BLEND_MODE:
+                return executeSetLayerBlendMode(length);
+            case IComposerClient::Command::SET_LAYER_COLOR:
+                return executeSetLayerColor(length);
+            case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
+                return executeSetLayerCompositionType(length);
+            case IComposerClient::Command::SET_LAYER_DATASPACE:
+                return executeSetLayerDataspace(length);
+            case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
+                return executeSetLayerDisplayFrame(length);
+            case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
+                return executeSetLayerPlaneAlpha(length);
+            case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
+                return executeSetLayerSidebandStream(length);
+            case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
+                return executeSetLayerSourceCrop(length);
+            case IComposerClient::Command::SET_LAYER_TRANSFORM:
+                return executeSetLayerTransform(length);
+            case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
+                return executeSetLayerVisibleRegion(length);
+            case IComposerClient::Command::SET_LAYER_Z_ORDER:
+                return executeSetLayerZOrder(length);
+            default:
+                return false;
+        }
+    }
+
+    bool executeSelectDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kSelectDisplayLength) {
+            return false;
+        }
+
+        mCurrentDisplay = read64();
+        mWriter.selectDisplay(mCurrentDisplay);
+
+        return true;
+    }
+
+    bool executeSelectLayer(uint16_t length) {
+        if (length != CommandWriterBase::kSelectLayerLength) {
+            return false;
+        }
+
+        mCurrentLayer = read64();
+
+        return true;
+    }
+
+    bool executeSetColorTransform(uint16_t length) {
+        if (length != CommandWriterBase::kSetColorTransformLength) {
+            return false;
+        }
+
+        float matrix[16];
+        for (int i = 0; i < 16; i++) {
+            matrix[i] = readFloat();
+        }
+        auto transform = readSigned();
+
+        auto err = mHal->setColorTransform(mCurrentDisplay, matrix, transform);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetClientTarget(uint16_t length) {
+        // 4 parameters followed by N rectangles
+        if ((length - 4) % 4 != 0) {
+            return false;
+        }
+
+        bool useCache = false;
+        auto slot = read();
+        auto rawHandle = readHandle(&useCache);
+        auto fence = readFence();
+        auto dataspace = readSigned();
+        auto damage = readRegion((length - 4) / 4);
+        bool closeFence = true;
+
+        const native_handle_t* clientTarget;
+        ComposerResources::ReplacedBufferHandle replacedClientTarget;
+        auto err = mResources->getDisplayClientTarget(mCurrentDisplay, slot, useCache, rawHandle,
+                                                      &clientTarget, &replacedClientTarget);
+        if (err == Error::NONE) {
+            err = mHal->setClientTarget(mCurrentDisplay, clientTarget, fence, dataspace, damage);
+            if (err == Error::NONE) {
+                closeFence = false;
+            }
+        }
+        if (closeFence) {
+            close(fence);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetOutputBuffer(uint16_t length) {
+        if (length != CommandWriterBase::kSetOutputBufferLength) {
+            return false;
+        }
+
+        bool useCache = false;
+        auto slot = read();
+        auto rawhandle = readHandle(&useCache);
+        auto fence = readFence();
+        bool closeFence = true;
+
+        const native_handle_t* outputBuffer;
+        ComposerResources::ReplacedBufferHandle replacedOutputBuffer;
+        auto err = mResources->getDisplayOutputBuffer(mCurrentDisplay, slot, useCache, rawhandle,
+                                                      &outputBuffer, &replacedOutputBuffer);
+        if (err == Error::NONE) {
+            err = mHal->setOutputBuffer(mCurrentDisplay, outputBuffer, fence);
+            if (err == Error::NONE) {
+                closeFence = false;
+            }
+        }
+        if (closeFence) {
+            close(fence);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeValidateDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kValidateDisplayLength) {
+            return false;
+        }
+
+        std::vector<Layer> changedLayers;
+        std::vector<IComposerClient::Composition> compositionTypes;
+        uint32_t displayRequestMask = 0x0;
+        std::vector<Layer> requestedLayers;
+        std::vector<uint32_t> requestMasks;
+
+        auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
+                                         &displayRequestMask, &requestedLayers, &requestMasks);
+        if (err == Error::NONE) {
+            mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+            mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+        } else {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executePresentOrValidateDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kPresentOrValidateDisplayLength) {
+            return false;
+        }
+
+        // First try to Present as is.
+        if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
+            int presentFence = -1;
+            std::vector<Layer> layers;
+            std::vector<int> fences;
+            auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
+            if (err == Error::NONE) {
+                mWriter.setPresentOrValidateResult(1);
+                mWriter.setPresentFence(presentFence);
+                mWriter.setReleaseFences(layers, fences);
+                return true;
+            }
+        }
+
+        // Present has failed. We need to fallback to validate
+        std::vector<Layer> changedLayers;
+        std::vector<IComposerClient::Composition> compositionTypes;
+        uint32_t displayRequestMask = 0x0;
+        std::vector<Layer> requestedLayers;
+        std::vector<uint32_t> requestMasks;
+
+        auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
+                                         &displayRequestMask, &requestedLayers, &requestMasks);
+        if (err == Error::NONE) {
+            mWriter.setPresentOrValidateResult(0);
+            mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+            mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+        } else {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeAcceptDisplayChanges(uint16_t length) {
+        if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
+            return false;
+        }
+
+        auto err = mHal->acceptDisplayChanges(mCurrentDisplay);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executePresentDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kPresentDisplayLength) {
+            return false;
+        }
+
+        int presentFence = -1;
+        std::vector<Layer> layers;
+        std::vector<int> fences;
+        auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
+        if (err == Error::NONE) {
+            mWriter.setPresentFence(presentFence);
+            mWriter.setReleaseFences(layers, fences);
+        } else {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerCursorPosition(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerCursorPositionLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerCursorPosition(mCurrentDisplay, mCurrentLayer, readSigned(),
+                                                readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerBuffer(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerBufferLength) {
+            return false;
+        }
+
+        bool useCache = false;
+        auto slot = read();
+        auto rawHandle = readHandle(&useCache);
+        auto fence = readFence();
+        bool closeFence = true;
+
+        const native_handle_t* buffer;
+        ComposerResources::ReplacedBufferHandle replacedBuffer;
+        auto err = mResources->getLayerBuffer(mCurrentDisplay, mCurrentLayer, slot, useCache,
+                                              rawHandle, &buffer, &replacedBuffer);
+        if (err == Error::NONE) {
+            err = mHal->setLayerBuffer(mCurrentDisplay, mCurrentLayer, buffer, fence);
+            if (err == Error::NONE) {
+                closeFence = false;
+            }
+        }
+        if (closeFence) {
+            close(fence);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerSurfaceDamage(uint16_t length) {
+        // N rectangles
+        if (length % 4 != 0) {
+            return false;
+        }
+
+        auto damage = readRegion(length / 4);
+        auto err = mHal->setLayerSurfaceDamage(mCurrentDisplay, mCurrentLayer, damage);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerBlendMode(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerBlendModeLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerBlendMode(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerColor(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerColorLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerColor(mCurrentDisplay, mCurrentLayer, readColor());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerCompositionType(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerCompositionTypeLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerCompositionType(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerDataspace(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerDataspaceLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerDataspace(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerDisplayFrame(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerDisplayFrameLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerDisplayFrame(mCurrentDisplay, mCurrentLayer, readRect());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerPlaneAlpha(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerPlaneAlpha(mCurrentDisplay, mCurrentLayer, readFloat());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerSidebandStream(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerSidebandStreamLength) {
+            return false;
+        }
+
+        auto rawHandle = readHandle();
+
+        const native_handle_t* stream;
+        ComposerResources::ReplacedStreamHandle replacedStream;
+        auto err = mResources->getLayerSidebandStream(mCurrentDisplay, mCurrentLayer, rawHandle,
+                                                      &stream, &replacedStream);
+        if (err == Error::NONE) {
+            err = mHal->setLayerSidebandStream(mCurrentDisplay, mCurrentLayer, stream);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerSourceCrop(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerSourceCropLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerSourceCrop(mCurrentDisplay, mCurrentLayer, readFRect());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerTransform(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerTransformLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerTransform(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerVisibleRegion(uint16_t length) {
+        // N rectangles
+        if (length % 4 != 0) {
+            return false;
+        }
+
+        auto region = readRegion(length / 4);
+        auto err = mHal->setLayerVisibleRegion(mCurrentDisplay, mCurrentLayer, region);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerZOrder(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerZOrderLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerZOrder(mCurrentDisplay, mCurrentLayer, read());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    hwc_rect_t readRect() {
+        return hwc_rect_t{
+            readSigned(), readSigned(), readSigned(), readSigned(),
+        };
+    }
+
+    std::vector<hwc_rect_t> readRegion(size_t count) {
+        std::vector<hwc_rect_t> region;
+        region.reserve(count);
+        while (count > 0) {
+            region.emplace_back(readRect());
+            count--;
+        }
+
+        return region;
+    }
+
+    hwc_frect_t readFRect() {
+        return hwc_frect_t{
+            readFloat(), readFloat(), readFloat(), readFloat(),
+        };
+    }
+
+    ComposerHal* mHal;
+    ComposerResources* mResources;
+
+    // 64KiB minus a small space for metadata such as read/write pointers
+    static constexpr size_t kWriterInitialSize = 64 * 1024 / sizeof(uint32_t) - 16;
+    CommandWriterBase mWriter{kWriterInitialSize};
+
+    Display mCurrentDisplay = 0;
+    Layer mCurrentLayer = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h
new file mode 100644
index 0000000..c9793fd
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2018 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 <string>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
+
+// TODO remove hwcomposer2.h dependency
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+using common::V1_0::ColorMode;
+using common::V1_0::ColorTransform;
+using common::V1_0::Dataspace;
+using common::V1_0::Hdr;
+using common::V1_0::PixelFormat;
+using common::V1_0::Transform;
+
+class ComposerHal {
+   public:
+    virtual ~ComposerHal() = default;
+
+    virtual bool hasCapability(hwc2_capability_t capability) = 0;
+
+    // dump the debug information
+    virtual std::string dumpDebugInfo() = 0;
+
+    class EventCallback {
+       public:
+        virtual ~EventCallback() = default;
+        virtual void onHotplug(Display display, IComposerCallback::Connection connected) = 0;
+        virtual void onRefresh(Display display) = 0;
+        virtual void onVsync(Display display, int64_t timestamp) = 0;
+    };
+
+    // Register the event callback object.  The event callback object is valid
+    // until it is unregistered.  A hotplug event must be generated for each
+    // connected physical display, before or after this function returns.
+    virtual void registerEventCallback(EventCallback* callback) = 0;
+
+    // Unregister the event callback object.  It must block if there is any
+    // callback in-flight.
+    virtual void unregisterEventCallback() = 0;
+
+    virtual uint32_t getMaxVirtualDisplayCount() = 0;
+    virtual Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
+                                       Display* outDisplay) = 0;
+    virtual Error destroyVirtualDisplay(Display display) = 0;
+    virtual Error createLayer(Display display, Layer* outLayer) = 0;
+    virtual Error destroyLayer(Display display, Layer layer) = 0;
+
+    virtual Error getActiveConfig(Display display, Config* outConfig) = 0;
+    virtual Error getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                         PixelFormat format, Dataspace dataspace) = 0;
+    virtual Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) = 0;
+    virtual Error getDisplayAttribute(Display display, Config config,
+                                      IComposerClient::Attribute attribute, int32_t* outValue) = 0;
+    virtual Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) = 0;
+    virtual Error getDisplayName(Display display, hidl_string* outName) = 0;
+    virtual Error getDisplayType(Display display, IComposerClient::DisplayType* outType) = 0;
+    virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
+    virtual Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
+                                     float* outMaxLuminance, float* outMaxAverageLuminance,
+                                     float* outMinLuminance) = 0;
+
+    virtual Error setActiveConfig(Display display, Config config) = 0;
+    virtual Error setColorMode(Display display, ColorMode mode) = 0;
+    virtual Error setPowerMode(Display display, IComposerClient::PowerMode mode) = 0;
+    virtual Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) = 0;
+
+    virtual Error setColorTransform(Display display, const float* matrix, int32_t hint) = 0;
+    virtual Error setClientTarget(Display display, buffer_handle_t target, int32_t acquireFence,
+                                  int32_t dataspace, const std::vector<hwc_rect_t>& damage) = 0;
+    virtual Error setOutputBuffer(Display display, buffer_handle_t buffer,
+                                  int32_t releaseFence) = 0;
+    virtual Error validateDisplay(Display display, std::vector<Layer>* outChangedLayers,
+                                  std::vector<IComposerClient::Composition>* outCompositionTypes,
+                                  uint32_t* outDisplayRequestMask,
+                                  std::vector<Layer>* outRequestedLayers,
+                                  std::vector<uint32_t>* outRequestMasks) = 0;
+    virtual Error acceptDisplayChanges(Display display) = 0;
+    virtual Error presentDisplay(Display display, int32_t* outPresentFence,
+                                 std::vector<Layer>* outLayers,
+                                 std::vector<int32_t>* outReleaseFences) = 0;
+
+    virtual Error setLayerCursorPosition(Display display, Layer layer, int32_t x, int32_t y) = 0;
+    virtual Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer,
+                                 int32_t acquireFence) = 0;
+    virtual Error setLayerSurfaceDamage(Display display, Layer layer,
+                                        const std::vector<hwc_rect_t>& damage) = 0;
+    virtual Error setLayerBlendMode(Display display, Layer layer, int32_t mode) = 0;
+    virtual Error setLayerColor(Display display, Layer layer, IComposerClient::Color color) = 0;
+    virtual Error setLayerCompositionType(Display display, Layer layer, int32_t type) = 0;
+    virtual Error setLayerDataspace(Display display, Layer layer, int32_t dataspace) = 0;
+    virtual Error setLayerDisplayFrame(Display display, Layer layer, const hwc_rect_t& frame) = 0;
+    virtual Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) = 0;
+    virtual Error setLayerSidebandStream(Display display, Layer layer, buffer_handle_t stream) = 0;
+    virtual Error setLayerSourceCrop(Display display, Layer layer, const hwc_frect_t& crop) = 0;
+    virtual Error setLayerTransform(Display display, Layer layer, int32_t transform) = 0;
+    virtual Error setLayerVisibleRegion(Display display, Layer layer,
+                                        const std::vector<hwc_rect_t>& visible) = 0;
+    virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
new file mode 100644
index 0000000..7bb3692
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
@@ -0,0 +1,536 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerResources.h included without LOG_TAG"
+#endif
+
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+// wrapper for IMapper to import buffers and sideband streams
+class ComposerHandleImporter {
+   public:
+    bool init() {
+        mMapper = mapper::V2_0::IMapper::getService();
+        ALOGE_IF(!mMapper, "failed to get mapper service");
+        return mMapper != nullptr;
+    }
+
+    Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) {
+        if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) {
+            *outBufferHandle = nullptr;
+            return Error::NONE;
+        }
+
+        mapper::V2_0::Error error;
+        const native_handle_t* bufferHandle;
+        mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
+            error = tmpError;
+            bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
+        });
+        if (error != mapper::V2_0::Error::NONE) {
+            return Error::NO_RESOURCES;
+        }
+
+        *outBufferHandle = bufferHandle;
+        return Error::NONE;
+    }
+
+    void freeBuffer(const native_handle_t* bufferHandle) {
+        if (bufferHandle) {
+            mMapper->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
+        }
+    }
+
+    Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle) {
+        const native_handle_t* streamHandle = nullptr;
+        if (rawHandle) {
+            streamHandle = native_handle_clone(rawHandle);
+            if (!streamHandle) {
+                return Error::NO_RESOURCES;
+            }
+        }
+
+        *outStreamHandle = streamHandle;
+        return Error::NONE;
+    }
+
+    void freeStream(const native_handle_t* streamHandle) {
+        if (streamHandle) {
+            native_handle_close(streamHandle);
+            native_handle_delete(const_cast<native_handle_t*>(streamHandle));
+        }
+    }
+
+   private:
+    sp<mapper::V2_0::IMapper> mMapper;
+};
+
+class ComposerHandleCache {
+   public:
+    enum class HandleType {
+        INVALID,
+        BUFFER,
+        STREAM,
+    };
+
+    ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize)
+        : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {}
+
+    // must be initialized later with initCache
+    ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {}
+
+    ~ComposerHandleCache() {
+        switch (mHandleType) {
+            case HandleType::BUFFER:
+                for (auto handle : mHandles) {
+                    mImporter.freeBuffer(handle);
+                }
+                break;
+            case HandleType::STREAM:
+                for (auto handle : mHandles) {
+                    mImporter.freeStream(handle);
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    ComposerHandleCache(const ComposerHandleCache&) = delete;
+    ComposerHandleCache& operator=(const ComposerHandleCache&) = delete;
+
+    bool initCache(HandleType type, uint32_t cacheSize) {
+        // already initialized
+        if (mHandleType != HandleType::INVALID) {
+            return false;
+        }
+
+        mHandleType = type;
+        mHandles.resize(cacheSize, nullptr);
+
+        return true;
+    }
+
+    Error lookupCache(uint32_t slot, const native_handle_t** outHandle) {
+        if (slot < mHandles.size()) {
+            *outHandle = mHandles[slot];
+            return Error::NONE;
+        } else {
+            return Error::BAD_PARAMETER;
+        }
+    }
+
+    Error updateCache(uint32_t slot, const native_handle_t* handle,
+                      const native_handle** outReplacedHandle) {
+        if (slot < mHandles.size()) {
+            auto& cachedHandle = mHandles[slot];
+            *outReplacedHandle = cachedHandle;
+            cachedHandle = handle;
+            return Error::NONE;
+        } else {
+            return Error::BAD_PARAMETER;
+        }
+    }
+
+    // when fromCache is true, look up in the cache; otherwise, update the cache
+    Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+                    const native_handle_t** outHandle, const native_handle** outReplacedHandle) {
+        if (fromCache) {
+            *outReplacedHandle = nullptr;
+            return lookupCache(slot, outHandle);
+        } else {
+            *outHandle = inHandle;
+            return updateCache(slot, inHandle, outReplacedHandle);
+        }
+    }
+
+   private:
+    ComposerHandleImporter& mImporter;
+    HandleType mHandleType = HandleType::INVALID;
+    std::vector<const native_handle_t*> mHandles;
+};
+
+// layer resource
+class ComposerLayerResource {
+   public:
+    ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize)
+        : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize),
+          mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {}
+
+    Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+                    const native_handle_t** outHandle, const native_handle** outReplacedHandle) {
+        return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle);
+    }
+
+    Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+                            const native_handle_t** outHandle,
+                            const native_handle** outReplacedHandle) {
+        return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle,
+                                              outReplacedHandle);
+    }
+
+   protected:
+    ComposerHandleCache mBufferCache;
+    ComposerHandleCache mSidebandStreamCache;
+};
+
+// display resource
+class ComposerDisplayResource {
+   public:
+    enum class DisplayType {
+        PHYSICAL,
+        VIRTUAL,
+    };
+
+    ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+                            uint32_t outputBufferCacheSize)
+        : mType(type),
+          mClientTargetCache(importer),
+          mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER,
+                             outputBufferCacheSize) {}
+
+    bool initClientTargetCache(uint32_t cacheSize) {
+        return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize);
+    }
+
+    bool isVirtual() const { return mType == DisplayType::VIRTUAL; }
+
+    Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+                          const native_handle_t** outHandle,
+                          const native_handle** outReplacedHandle) {
+        return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle,
+                                            outReplacedHandle);
+    }
+
+    Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+                          const native_handle_t** outHandle,
+                          const native_handle** outReplacedHandle) {
+        return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle,
+                                            outReplacedHandle);
+    }
+
+    bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource) {
+        auto result = mLayerResources.emplace(layer, std::move(layerResource));
+        return result.second;
+    }
+
+    bool removeLayer(Layer layer) { return mLayerResources.erase(layer) > 0; }
+
+    ComposerLayerResource* findLayerResource(Layer layer) {
+        auto layerIter = mLayerResources.find(layer);
+        if (layerIter == mLayerResources.end()) {
+            return nullptr;
+        }
+
+        return layerIter->second.get();
+    }
+
+    std::vector<Layer> getLayers() const {
+        std::vector<Layer> layers;
+        layers.reserve(mLayerResources.size());
+        for (const auto& layerKey : mLayerResources) {
+            layers.push_back(layerKey.first);
+        }
+        return layers;
+    }
+
+   protected:
+    const DisplayType mType;
+    ComposerHandleCache mClientTargetCache;
+    ComposerHandleCache mOutputBufferCache;
+
+    std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources;
+};
+
+class ComposerResources {
+   private:
+    template <bool isBuffer>
+    class ReplacedHandle;
+
+   public:
+    static std::unique_ptr<ComposerResources> create() {
+        auto resources = std::make_unique<ComposerResources>();
+        return resources->init() ? std::move(resources) : nullptr;
+    }
+
+    ComposerResources() = default;
+    virtual ~ComposerResources() = default;
+
+    bool init() { return mImporter.init(); }
+
+    using RemoveDisplay =
+        std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>;
+    void clear(RemoveDisplay removeDisplay) {
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        for (const auto& displayKey : mDisplayResources) {
+            Display display = displayKey.first;
+            const ComposerDisplayResource& displayResource = *displayKey.second;
+            removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers());
+        }
+        mDisplayResources.clear();
+    }
+
+    Error addPhysicalDisplay(Display display) {
+        auto displayResource =
+            createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0);
+
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        auto result = mDisplayResources.emplace(display, std::move(displayResource));
+        return result.second ? Error::NONE : Error::BAD_DISPLAY;
+    }
+
+    Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) {
+        auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL,
+                                                     outputBufferCacheSize);
+
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        auto result = mDisplayResources.emplace(display, std::move(displayResource));
+        return result.second ? Error::NONE : Error::BAD_DISPLAY;
+    }
+
+    Error removeDisplay(Display display) {
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY;
+    }
+
+    Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize) {
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+        if (!displayResource) {
+            return Error::BAD_DISPLAY;
+        }
+
+        return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE
+                                                                             : Error::BAD_PARAMETER;
+    }
+
+    Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize) {
+        auto layerResource = createLayerResource(bufferCacheSize);
+
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+        if (!displayResource) {
+            return Error::BAD_DISPLAY;
+        }
+
+        return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE
+                                                                          : Error::BAD_LAYER;
+    }
+
+    Error removeLayer(Display display, Layer layer) {
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+        if (!displayResource) {
+            return Error::BAD_DISPLAY;
+        }
+
+        return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER;
+    }
+
+    using ReplacedBufferHandle = ReplacedHandle<true>;
+    using ReplacedStreamHandle = ReplacedHandle<false>;
+
+    Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache,
+                                 const native_handle_t* rawHandle,
+                                 const native_handle_t** outBufferHandle,
+                                 ReplacedBufferHandle* outReplacedBuffer) {
+        return getHandle<Cache::CLIENT_TARGET>(display, 0, slot, fromCache, rawHandle,
+                                               outBufferHandle, outReplacedBuffer);
+    }
+
+    Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache,
+                                 const native_handle_t* rawHandle,
+                                 const native_handle_t** outBufferHandle,
+                                 ReplacedBufferHandle* outReplacedBuffer) {
+        return getHandle<Cache::OUTPUT_BUFFER>(display, 0, slot, fromCache, rawHandle,
+                                               outBufferHandle, outReplacedBuffer);
+    }
+
+    Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache,
+                         const native_handle_t* rawHandle, const native_handle_t** outBufferHandle,
+                         ReplacedBufferHandle* outReplacedBuffer) {
+        return getHandle<Cache::LAYER_BUFFER>(display, layer, slot, fromCache, rawHandle,
+                                              outBufferHandle, outReplacedBuffer);
+    }
+
+    Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle,
+                                 const native_handle_t** outStreamHandle,
+                                 ReplacedStreamHandle* outReplacedStream) {
+        return getHandle<Cache::LAYER_SIDEBAND_STREAM>(display, layer, 0, false, rawHandle,
+                                                       outStreamHandle, outReplacedStream);
+    }
+
+   protected:
+    virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource(
+        ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) {
+        return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
+    }
+
+    virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize) {
+        return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize);
+    }
+
+    ComposerDisplayResource* findDisplayResourceLocked(Display display) {
+        auto iter = mDisplayResources.find(display);
+        if (iter == mDisplayResources.end()) {
+            return nullptr;
+        }
+        return iter->second.get();
+    }
+
+    ComposerHandleImporter mImporter;
+
+    std::mutex mDisplayResourcesMutex;
+    std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources;
+
+   private:
+    enum class Cache {
+        CLIENT_TARGET,
+        OUTPUT_BUFFER,
+        LAYER_BUFFER,
+        LAYER_SIDEBAND_STREAM,
+    };
+
+    // When a buffer in the cache is replaced by a new one, we must keep it
+    // alive until it has been replaced in ComposerHal.
+    template <bool isBuffer>
+    class ReplacedHandle {
+       public:
+        ReplacedHandle() = default;
+        ReplacedHandle(const ReplacedHandle&) = delete;
+        ReplacedHandle& operator=(const ReplacedHandle&) = delete;
+
+        ~ReplacedHandle() { reset(); }
+
+        void reset(ComposerHandleImporter* importer = nullptr,
+                   const native_handle_t* handle = nullptr) {
+            if (mHandle) {
+                if (isBuffer) {
+                    mImporter->freeBuffer(mHandle);
+                } else {
+                    mImporter->freeStream(mHandle);
+                }
+            }
+
+            mImporter = importer;
+            mHandle = handle;
+        }
+
+       private:
+        ComposerHandleImporter* mImporter = nullptr;
+        const native_handle_t* mHandle = nullptr;
+    };
+
+    template <Cache cache, bool isBuffer>
+    Error getHandle(Display display, Layer layer, uint32_t slot, bool fromCache,
+                    const native_handle_t* rawHandle, const native_handle_t** outHandle,
+                    ReplacedHandle<isBuffer>* outReplacedHandle) {
+        Error error;
+
+        // import the raw handle (or ignore raw handle when fromCache is true)
+        const native_handle_t* importedHandle = nullptr;
+        if (!fromCache) {
+            error = (isBuffer) ? mImporter.importBuffer(rawHandle, &importedHandle)
+                               : mImporter.importStream(rawHandle, &importedHandle);
+            if (error != Error::NONE) {
+                return error;
+            }
+        }
+
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+
+        // find display/layer resource
+        const bool needLayerResource =
+            (cache == Cache::LAYER_BUFFER || cache == Cache::LAYER_SIDEBAND_STREAM);
+        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+        ComposerLayerResource* layerResource = (displayResource && needLayerResource)
+                                                   ? displayResource->findLayerResource(layer)
+                                                   : nullptr;
+
+        // lookup or update cache
+        const native_handle_t* replacedHandle = nullptr;
+        if (displayResource && (!needLayerResource || layerResource)) {
+            switch (cache) {
+                case Cache::CLIENT_TARGET:
+                    error = displayResource->getClientTarget(slot, fromCache, importedHandle,
+                                                             outHandle, &replacedHandle);
+                    break;
+                case Cache::OUTPUT_BUFFER:
+                    error = displayResource->getOutputBuffer(slot, fromCache, importedHandle,
+                                                             outHandle, &replacedHandle);
+                    break;
+                case Cache::LAYER_BUFFER:
+                    error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle,
+                                                     &replacedHandle);
+                    break;
+                case Cache::LAYER_SIDEBAND_STREAM:
+                    error = layerResource->getSidebandStream(slot, fromCache, importedHandle,
+                                                             outHandle, &replacedHandle);
+                    break;
+                default:
+                    error = Error::BAD_PARAMETER;
+                    break;
+            }
+
+            if (error != Error::NONE) {
+                ALOGW("invalid cache %d slot %d", int(cache), int(slot));
+            }
+        } else if (!displayResource) {
+            error = Error::BAD_DISPLAY;
+        } else {
+            error = Error::BAD_LAYER;
+        }
+
+        // clean up on errors
+        if (error != Error::NONE) {
+            if (!fromCache) {
+                if (isBuffer) {
+                    mImporter.freeBuffer(importedHandle);
+                } else {
+                    mImporter.freeStream(importedHandle);
+                }
+            }
+            return error;
+        }
+
+        outReplacedHandle->reset(&mImporter, replacedHandle);
+
+        return Error::NONE;
+    }
+};
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
new file mode 100644
index 0000000..420a1f6
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
@@ -0,0 +1,76 @@
+// Copyright 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+    name: "libhwc2on1adapter",
+    vendor: true,
+
+    clang: true,
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-user-defined-warnings",
+    ],
+    cppflags: [
+        "-Weverything",
+        "-Wunused",
+        "-Wunreachable-code",
+
+        // The static constructors and destructors in this library have not been noted to
+        // introduce significant overheads
+        "-Wno-exit-time-destructors",
+        "-Wno-global-constructors",
+
+        // We only care about compiling as C++14
+        "-Wno-c++98-compat-pedantic",
+
+        // android/sensors.h uses nested anonymous unions and anonymous structs
+        "-Wno-nested-anon-types",
+        "-Wno-gnu-anonymous-struct",
+
+        // Don't warn about struct padding
+        "-Wno-padded",
+
+        // hwcomposer2.h features switch covering all cases.
+        "-Wno-covered-switch-default",
+
+        // hwcomposer.h features zero size array.
+        "-Wno-zero-length-array",
+
+        // Disabling warning specific to hwc2on1adapter code
+        "-Wno-double-promotion",
+        "-Wno-sign-conversion",
+        "-Wno-switch-enum",
+        "-Wno-float-equal",
+        "-Wno-shorten-64-to-32",
+        "-Wno-sign-compare",
+        "-Wno-missing-prototypes",
+    ],
+
+    srcs: [
+        "HWC2On1Adapter.cpp",
+        "MiniFence.cpp",
+    ],
+
+    shared_libs: [
+        "libutils",
+        "libcutils",
+        "liblog",
+        "libhardware",
+    ],
+
+    export_include_dirs: ["include"],
+
+    export_shared_lib_headers: ["libutils"],
+}
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk b/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk
new file mode 100644
index 0000000..7fc2216
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk
@@ -0,0 +1,52 @@
+# 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhwc2on1adapter_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libhwc2on1adapter.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/libhwc2on1adapter.so)
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
new file mode 100644
index 0000000..77f06bb
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -0,0 +1,2637 @@
+/*
+ * Copyright 2015 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 "hwc2on1adapter/HWC2On1Adapter.h"
+
+//#define LOG_NDEBUG 0
+
+#undef LOG_TAG
+#define LOG_TAG "HWC2On1Adapter"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+
+#include <inttypes.h>
+
+#include <chrono>
+#include <cstdlib>
+#include <sstream>
+
+#include <hardware/hwcomposer.h>
+#include <log/log.h>
+#include <utils/Trace.h>
+
+using namespace std::chrono_literals;
+
+static uint8_t getMinorVersion(struct hwc_composer_device_1* device)
+{
+    auto version = device->common.version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+    return (version >> 16) & 0xF;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function)
+{
+    static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+    return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+using namespace HWC2;
+
+static constexpr Attribute ColorMode = static_cast<Attribute>(6);
+
+namespace android {
+
+class HWC2On1Adapter::Callbacks : public hwc_procs_t {
+    public:
+        explicit Callbacks(HWC2On1Adapter& adapter) : mAdapter(adapter) {
+            invalidate = &invalidateHook;
+            vsync = &vsyncHook;
+            hotplug = &hotplugHook;
+        }
+
+        static void invalidateHook(const hwc_procs_t* procs) {
+            auto callbacks = static_cast<const Callbacks*>(procs);
+            callbacks->mAdapter.hwc1Invalidate();
+        }
+
+        static void vsyncHook(const hwc_procs_t* procs, int display,
+                int64_t timestamp) {
+            auto callbacks = static_cast<const Callbacks*>(procs);
+            callbacks->mAdapter.hwc1Vsync(display, timestamp);
+        }
+
+        static void hotplugHook(const hwc_procs_t* procs, int display,
+                int connected) {
+            auto callbacks = static_cast<const Callbacks*>(procs);
+            callbacks->mAdapter.hwc1Hotplug(display, connected);
+        }
+
+    private:
+        HWC2On1Adapter& mAdapter;
+};
+
+static int closeHook(hw_device_t* /*device*/)
+{
+    // Do nothing, since the real work is done in the class destructor, but we
+    // need to provide a valid function pointer for hwc2_close to call
+    return 0;
+}
+
+HWC2On1Adapter::HWC2On1Adapter(hwc_composer_device_1_t* hwc1Device)
+  : mDumpString(),
+    mHwc1Device(hwc1Device),
+    mHwc1MinorVersion(getMinorVersion(hwc1Device)),
+    mHwc1SupportsVirtualDisplays(false),
+    mHwc1SupportsBackgroundColor(false),
+    mHwc1Callbacks(std::make_unique<Callbacks>(*this)),
+    mCapabilities(),
+    mLayers(),
+    mHwc1VirtualDisplay(),
+    mStateMutex(),
+    mCallbacks(),
+    mHasPendingInvalidate(false),
+    mPendingVsyncs(),
+    mPendingHotplugs(),
+    mDisplays(),
+    mHwc1DisplayMap()
+{
+    common.close = closeHook;
+    getCapabilities = getCapabilitiesHook;
+    getFunction = getFunctionHook;
+    populateCapabilities();
+    populatePrimary();
+    mHwc1Device->registerProcs(mHwc1Device,
+            static_cast<const hwc_procs_t*>(mHwc1Callbacks.get()));
+}
+
+HWC2On1Adapter::~HWC2On1Adapter() {
+    hwc_close_1(mHwc1Device);
+}
+
+void HWC2On1Adapter::doGetCapabilities(uint32_t* outCount,
+        int32_t* outCapabilities) {
+    if (outCapabilities == nullptr) {
+        *outCount = mCapabilities.size();
+        return;
+    }
+
+    auto capabilityIter = mCapabilities.cbegin();
+    for (size_t written = 0; written < *outCount; ++written) {
+        if (capabilityIter == mCapabilities.cend()) {
+            return;
+        }
+        outCapabilities[written] = static_cast<int32_t>(*capabilityIter);
+        ++capabilityIter;
+    }
+}
+
+hwc2_function_pointer_t HWC2On1Adapter::doGetFunction(
+        FunctionDescriptor descriptor) {
+    switch (descriptor) {
+        // Device functions
+        case FunctionDescriptor::CreateVirtualDisplay:
+            return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
+                    createVirtualDisplayHook);
+        case FunctionDescriptor::DestroyVirtualDisplay:
+            return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
+                    destroyVirtualDisplayHook);
+        case FunctionDescriptor::Dump:
+            return asFP<HWC2_PFN_DUMP>(dumpHook);
+        case FunctionDescriptor::GetMaxVirtualDisplayCount:
+            return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
+                    getMaxVirtualDisplayCountHook);
+        case FunctionDescriptor::RegisterCallback:
+            return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+        // Display functions
+        case FunctionDescriptor::AcceptDisplayChanges:
+            return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
+                    displayHook<decltype(&Display::acceptChanges),
+                    &Display::acceptChanges>);
+        case FunctionDescriptor::CreateLayer:
+            return asFP<HWC2_PFN_CREATE_LAYER>(
+                    displayHook<decltype(&Display::createLayer),
+                    &Display::createLayer, hwc2_layer_t*>);
+        case FunctionDescriptor::DestroyLayer:
+            return asFP<HWC2_PFN_DESTROY_LAYER>(
+                    displayHook<decltype(&Display::destroyLayer),
+                    &Display::destroyLayer, hwc2_layer_t>);
+        case FunctionDescriptor::GetActiveConfig:
+            return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(
+                    displayHook<decltype(&Display::getActiveConfig),
+                    &Display::getActiveConfig, hwc2_config_t*>);
+        case FunctionDescriptor::GetChangedCompositionTypes:
+            return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
+                    displayHook<decltype(&Display::getChangedCompositionTypes),
+                    &Display::getChangedCompositionTypes, uint32_t*,
+                    hwc2_layer_t*, int32_t*>);
+        case FunctionDescriptor::GetColorModes:
+            return asFP<HWC2_PFN_GET_COLOR_MODES>(
+                    displayHook<decltype(&Display::getColorModes),
+                    &Display::getColorModes, uint32_t*, int32_t*>);
+        case FunctionDescriptor::GetDisplayAttribute:
+            return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
+                    getDisplayAttributeHook);
+        case FunctionDescriptor::GetDisplayConfigs:
+            return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(
+                    displayHook<decltype(&Display::getConfigs),
+                    &Display::getConfigs, uint32_t*, hwc2_config_t*>);
+        case FunctionDescriptor::GetDisplayName:
+            return asFP<HWC2_PFN_GET_DISPLAY_NAME>(
+                    displayHook<decltype(&Display::getName),
+                    &Display::getName, uint32_t*, char*>);
+        case FunctionDescriptor::GetDisplayRequests:
+            return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(
+                    displayHook<decltype(&Display::getRequests),
+                    &Display::getRequests, int32_t*, uint32_t*, hwc2_layer_t*,
+                    int32_t*>);
+        case FunctionDescriptor::GetDisplayType:
+            return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(
+                    displayHook<decltype(&Display::getType),
+                    &Display::getType, int32_t*>);
+        case FunctionDescriptor::GetDozeSupport:
+            return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(
+                    displayHook<decltype(&Display::getDozeSupport),
+                    &Display::getDozeSupport, int32_t*>);
+        case FunctionDescriptor::GetHdrCapabilities:
+            return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(
+                    displayHook<decltype(&Display::getHdrCapabilities),
+                    &Display::getHdrCapabilities, uint32_t*, int32_t*, float*,
+                    float*, float*>);
+        case FunctionDescriptor::GetReleaseFences:
+            return asFP<HWC2_PFN_GET_RELEASE_FENCES>(
+                    displayHook<decltype(&Display::getReleaseFences),
+                    &Display::getReleaseFences, uint32_t*, hwc2_layer_t*,
+                    int32_t*>);
+        case FunctionDescriptor::PresentDisplay:
+            return asFP<HWC2_PFN_PRESENT_DISPLAY>(
+                    displayHook<decltype(&Display::present),
+                    &Display::present, int32_t*>);
+        case FunctionDescriptor::SetActiveConfig:
+            return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(
+                    displayHook<decltype(&Display::setActiveConfig),
+                    &Display::setActiveConfig, hwc2_config_t>);
+        case FunctionDescriptor::SetClientTarget:
+            return asFP<HWC2_PFN_SET_CLIENT_TARGET>(
+                    displayHook<decltype(&Display::setClientTarget),
+                    &Display::setClientTarget, buffer_handle_t, int32_t,
+                    int32_t, hwc_region_t>);
+        case FunctionDescriptor::SetColorMode:
+            return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
+        case FunctionDescriptor::SetColorTransform:
+            return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
+        case FunctionDescriptor::SetOutputBuffer:
+            return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(
+                    displayHook<decltype(&Display::setOutputBuffer),
+                    &Display::setOutputBuffer, buffer_handle_t, int32_t>);
+        case FunctionDescriptor::SetPowerMode:
+            return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook);
+        case FunctionDescriptor::SetVsyncEnabled:
+            return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook);
+        case FunctionDescriptor::ValidateDisplay:
+            return asFP<HWC2_PFN_VALIDATE_DISPLAY>(
+                    displayHook<decltype(&Display::validate),
+                    &Display::validate, uint32_t*, uint32_t*>);
+        case FunctionDescriptor::GetClientTargetSupport:
+            return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
+                    displayHook<decltype(&Display::getClientTargetSupport),
+                    &Display::getClientTargetSupport, uint32_t, uint32_t,
+                                                      int32_t, int32_t>);
+
+        // Layer functions
+        case FunctionDescriptor::SetCursorPosition:
+            return asFP<HWC2_PFN_SET_CURSOR_POSITION>(
+                    layerHook<decltype(&Layer::setCursorPosition),
+                    &Layer::setCursorPosition, int32_t, int32_t>);
+        case FunctionDescriptor::SetLayerBuffer:
+            return asFP<HWC2_PFN_SET_LAYER_BUFFER>(
+                    layerHook<decltype(&Layer::setBuffer), &Layer::setBuffer,
+                    buffer_handle_t, int32_t>);
+        case FunctionDescriptor::SetLayerSurfaceDamage:
+            return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
+                    layerHook<decltype(&Layer::setSurfaceDamage),
+                    &Layer::setSurfaceDamage, hwc_region_t>);
+
+        // Layer state functions
+        case FunctionDescriptor::SetLayerBlendMode:
+            return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(
+                    setLayerBlendModeHook);
+        case FunctionDescriptor::SetLayerColor:
+            return asFP<HWC2_PFN_SET_LAYER_COLOR>(
+                    layerHook<decltype(&Layer::setColor), &Layer::setColor,
+                    hwc_color_t>);
+        case FunctionDescriptor::SetLayerCompositionType:
+            return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
+                    setLayerCompositionTypeHook);
+        case FunctionDescriptor::SetLayerDataspace:
+            return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerDataspaceHook);
+        case FunctionDescriptor::SetLayerDisplayFrame:
+            return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
+                    layerHook<decltype(&Layer::setDisplayFrame),
+                    &Layer::setDisplayFrame, hwc_rect_t>);
+        case FunctionDescriptor::SetLayerPlaneAlpha:
+            return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
+                    layerHook<decltype(&Layer::setPlaneAlpha),
+                    &Layer::setPlaneAlpha, float>);
+        case FunctionDescriptor::SetLayerSidebandStream:
+            return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(
+                    layerHook<decltype(&Layer::setSidebandStream),
+                    &Layer::setSidebandStream, const native_handle_t*>);
+        case FunctionDescriptor::SetLayerSourceCrop:
+            return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
+                    layerHook<decltype(&Layer::setSourceCrop),
+                    &Layer::setSourceCrop, hwc_frect_t>);
+        case FunctionDescriptor::SetLayerTransform:
+            return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerTransformHook);
+        case FunctionDescriptor::SetLayerVisibleRegion:
+            return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
+                    layerHook<decltype(&Layer::setVisibleRegion),
+                    &Layer::setVisibleRegion, hwc_region_t>);
+        case FunctionDescriptor::SetLayerZOrder:
+            return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerZOrderHook);
+
+        default:
+            ALOGE("doGetFunction: Unknown function descriptor: %d (%s)",
+                    static_cast<int32_t>(descriptor),
+                    to_string(descriptor).c_str());
+            return nullptr;
+    }
+}
+
+// Device functions
+
+Error HWC2On1Adapter::createVirtualDisplay(uint32_t width,
+        uint32_t height, hwc2_display_t* outDisplay) {
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    if (mHwc1VirtualDisplay) {
+        // We have already allocated our only HWC1 virtual display
+        ALOGE("createVirtualDisplay: HWC1 virtual display already allocated");
+        return Error::NoResources;
+    }
+
+    mHwc1VirtualDisplay = std::make_shared<HWC2On1Adapter::Display>(*this,
+            HWC2::DisplayType::Virtual);
+    mHwc1VirtualDisplay->populateConfigs(width, height);
+    const auto displayId = mHwc1VirtualDisplay->getId();
+    mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL] = displayId;
+    mHwc1VirtualDisplay->setHwc1Id(HWC_DISPLAY_VIRTUAL);
+    mDisplays.emplace(displayId, mHwc1VirtualDisplay);
+    *outDisplay = displayId;
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId) {
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    if (!mHwc1VirtualDisplay || (mHwc1VirtualDisplay->getId() != displayId)) {
+        return Error::BadDisplay;
+    }
+
+    mHwc1VirtualDisplay.reset();
+    mHwc1DisplayMap.erase(HWC_DISPLAY_VIRTUAL);
+    mDisplays.erase(displayId);
+
+    return Error::None;
+}
+
+void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer) {
+    if (outBuffer != nullptr) {
+        auto copiedBytes = mDumpString.copy(outBuffer, *outSize);
+        *outSize = static_cast<uint32_t>(copiedBytes);
+        return;
+    }
+
+    std::stringstream output;
+
+    output << "-- HWC2On1Adapter --\n";
+
+    output << "Adapting to a HWC 1." << static_cast<int>(mHwc1MinorVersion) <<
+            " device\n";
+
+    // Attempt to acquire the lock for 1 second, but proceed without the lock
+    // after that, so we can still get some information if we're deadlocked
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex,
+            std::defer_lock);
+    lock.try_lock_for(1s);
+
+    if (mCapabilities.empty()) {
+        output << "Capabilities: None\n";
+    } else {
+        output << "Capabilities:\n";
+        for (auto capability : mCapabilities) {
+            output << "  " << to_string(capability) << '\n';
+        }
+    }
+
+    output << "Displays:\n";
+    for (const auto& element : mDisplays) {
+        const auto& display = element.second;
+        output << display->dump();
+    }
+    output << '\n';
+
+    // Release the lock before calling into HWC1, and since we no longer require
+    // mutual exclusion to access mCapabilities or mDisplays
+    lock.unlock();
+
+    if (mHwc1Device->dump) {
+        output << "HWC1 dump:\n";
+        std::vector<char> hwc1Dump(4096);
+        // Call with size - 1 to preserve a null character at the end
+        mHwc1Device->dump(mHwc1Device, hwc1Dump.data(),
+                static_cast<int>(hwc1Dump.size() - 1));
+        output << hwc1Dump.data();
+    }
+
+    mDumpString = output.str();
+    *outSize = static_cast<uint32_t>(mDumpString.size());
+}
+
+uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount() {
+    return mHwc1SupportsVirtualDisplays ? 1 : 0;
+}
+
+static bool isValid(Callback descriptor) {
+    switch (descriptor) {
+        case Callback::Hotplug: // Fall-through
+        case Callback::Refresh: // Fall-through
+        case Callback::Vsync: return true;
+        default: return false;
+    }
+}
+
+Error HWC2On1Adapter::registerCallback(Callback descriptor,
+        hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
+    if (!isValid(descriptor)) {
+        return Error::BadParameter;
+    }
+
+    ALOGV("registerCallback(%s, %p, %p)", to_string(descriptor).c_str(),
+            callbackData, pointer);
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    if (pointer != nullptr) {
+        mCallbacks[descriptor] = {callbackData, pointer};
+    } else {
+        ALOGI("unregisterCallback(%s)", to_string(descriptor).c_str());
+        mCallbacks.erase(descriptor);
+        return Error::None;
+    }
+
+    bool hasPendingInvalidate = false;
+    std::vector<hwc2_display_t> displayIds;
+    std::vector<std::pair<hwc2_display_t, int64_t>> pendingVsyncs;
+    std::vector<std::pair<hwc2_display_t, int>> pendingHotplugs;
+
+    if (descriptor == Callback::Refresh) {
+        hasPendingInvalidate = mHasPendingInvalidate;
+        if (hasPendingInvalidate) {
+            for (auto& displayPair : mDisplays) {
+                displayIds.emplace_back(displayPair.first);
+            }
+        }
+        mHasPendingInvalidate = false;
+    } else if (descriptor == Callback::Vsync) {
+        for (auto pending : mPendingVsyncs) {
+            auto hwc1DisplayId = pending.first;
+            if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+                ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d",
+                        hwc1DisplayId);
+                continue;
+            }
+            auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+            auto timestamp = pending.second;
+            pendingVsyncs.emplace_back(displayId, timestamp);
+        }
+        mPendingVsyncs.clear();
+    } else if (descriptor == Callback::Hotplug) {
+        // Hotplug the primary display
+        pendingHotplugs.emplace_back(mHwc1DisplayMap[HWC_DISPLAY_PRIMARY],
+                static_cast<int32_t>(Connection::Connected));
+
+        for (auto pending : mPendingHotplugs) {
+            auto hwc1DisplayId = pending.first;
+            if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+                ALOGE("hwc1Hotplug: Couldn't find display for HWC1 id %d",
+                        hwc1DisplayId);
+                continue;
+            }
+            auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+            auto connected = pending.second;
+            pendingHotplugs.emplace_back(displayId, connected);
+        }
+    }
+
+    // Call pending callbacks without the state lock held
+    lock.unlock();
+
+    if (hasPendingInvalidate) {
+        auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(pointer);
+        for (auto displayId : displayIds) {
+            refresh(callbackData, displayId);
+        }
+    }
+    if (!pendingVsyncs.empty()) {
+        auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
+        for (auto& pendingVsync : pendingVsyncs) {
+            vsync(callbackData, pendingVsync.first, pendingVsync.second);
+        }
+    }
+    if (!pendingHotplugs.empty()) {
+        auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer);
+        for (auto& pendingHotplug : pendingHotplugs) {
+            hotplug(callbackData, pendingHotplug.first, pendingHotplug.second);
+        }
+    }
+    return Error::None;
+}
+
+// Display functions
+
+std::atomic<hwc2_display_t> HWC2On1Adapter::Display::sNextId(1);
+
+HWC2On1Adapter::Display::Display(HWC2On1Adapter& device, HWC2::DisplayType type)
+  : mId(sNextId++),
+    mDevice(device),
+    mStateMutex(),
+    mHwc1RequestedContents(nullptr),
+    mRetireFence(),
+    mChanges(),
+    mHwc1Id(-1),
+    mConfigs(),
+    mActiveConfig(nullptr),
+    mActiveColorMode(static_cast<android_color_mode_t>(-1)),
+    mName(),
+    mType(type),
+    mPowerMode(PowerMode::Off),
+    mVsyncEnabled(Vsync::Invalid),
+    mClientTarget(),
+    mOutputBuffer(),
+    mHasColorTransform(false),
+    mLayers(),
+    mHwc1LayerMap(),
+    mNumAvailableRects(0),
+    mNextAvailableRect(nullptr),
+    mGeometryChanged(false)
+    {}
+
+Error HWC2On1Adapter::Display::acceptChanges() {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        ALOGV("[%" PRIu64 "] acceptChanges failed, not validated", mId);
+        return Error::NotValidated;
+    }
+
+    ALOGV("[%" PRIu64 "] acceptChanges", mId);
+
+    for (auto& change : mChanges->getTypeChanges()) {
+        auto layerId = change.first;
+        auto type = change.second;
+        if (mDevice.mLayers.count(layerId) == 0) {
+            // This should never happen but somehow does.
+            ALOGW("Cannot accept change for unknown layer (%" PRIu64 ")",
+                  layerId);
+            continue;
+        }
+        auto layer = mDevice.mLayers[layerId];
+        layer->setCompositionType(type);
+    }
+
+    mChanges->clearTypeChanges();
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    auto layer = *mLayers.emplace(std::make_shared<Layer>(*this));
+    mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer));
+    *outLayerId = layer->getId();
+    ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId);
+    markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    const auto mapLayer = mDevice.mLayers.find(layerId);
+    if (mapLayer == mDevice.mLayers.end()) {
+        ALOGV("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer",
+                mId, layerId);
+        return Error::BadLayer;
+    }
+    const auto layer = mapLayer->second;
+    mDevice.mLayers.erase(mapLayer);
+    const auto zRange = mLayers.equal_range(layer);
+    for (auto current = zRange.first; current != zRange.second; ++current) {
+        if (**current == *layer) {
+            current = mLayers.erase(current);
+            break;
+        }
+    }
+    ALOGV("[%" PRIu64 "] destroyed layer %" PRIu64, mId, layerId);
+    markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mActiveConfig) {
+        ALOGV("[%" PRIu64 "] getActiveConfig --> %s", mId,
+                to_string(Error::BadConfig).c_str());
+        return Error::BadConfig;
+    }
+    auto configId = mActiveConfig->getId();
+    ALOGV("[%" PRIu64 "] getActiveConfig --> %u", mId, configId);
+    *outConfig = configId;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getAttribute(hwc2_config_t configId,
+        Attribute attribute, int32_t* outValue) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+        ALOGV("[%" PRIu64 "] getAttribute failed: bad config (%u)", mId,
+                configId);
+        return Error::BadConfig;
+    }
+    *outValue = mConfigs[configId]->getAttribute(attribute);
+    ALOGV("[%" PRIu64 "] getAttribute(%u, %s) --> %d", mId, configId,
+            to_string(attribute).c_str(), *outValue);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getChangedCompositionTypes(
+        uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        ALOGE("[%" PRIu64 "] getChangedCompositionTypes failed: not validated",
+                mId);
+        return Error::NotValidated;
+    }
+
+    if ((outLayers == nullptr) || (outTypes == nullptr)) {
+        *outNumElements = mChanges->getTypeChanges().size();
+        return Error::None;
+    }
+
+    uint32_t numWritten = 0;
+    for (const auto& element : mChanges->getTypeChanges()) {
+        if (numWritten == *outNumElements) {
+            break;
+        }
+        auto layerId = element.first;
+        auto intType = static_cast<int32_t>(element.second);
+        ALOGV("Adding %" PRIu64 " %s", layerId,
+                to_string(element.second).c_str());
+        outLayers[numWritten] = layerId;
+        outTypes[numWritten] = intType;
+        ++numWritten;
+    }
+    *outNumElements = numWritten;
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes,
+        int32_t* outModes) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!outModes) {
+        *outNumModes = mColorModes.size();
+        return Error::None;
+    }
+    uint32_t numModes = std::min(*outNumModes,
+            static_cast<uint32_t>(mColorModes.size()));
+    std::copy_n(mColorModes.cbegin(), numModes, outModes);
+    *outNumModes = numModes;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs,
+        hwc2_config_t* outConfigs) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!outConfigs) {
+        *outNumConfigs = mConfigs.size();
+        return Error::None;
+    }
+    uint32_t numWritten = 0;
+    for (const auto& config : mConfigs) {
+        if (numWritten == *outNumConfigs) {
+            break;
+        }
+        outConfigs[numWritten] = config->getId();
+        ++numWritten;
+    }
+    *outNumConfigs = numWritten;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (mDevice.mHwc1MinorVersion < 4 || mHwc1Id != 0) {
+        *outSupport = 0;
+    } else {
+        *outSupport = 1;
+    }
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes,
+        int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+        float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
+    // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0
+    *outNumTypes = 0;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!outName) {
+        *outSize = mName.size();
+        return Error::None;
+    }
+    auto numCopied = mName.copy(outName, *outSize);
+    *outSize = numCopied;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getReleaseFences(uint32_t* outNumElements,
+        hwc2_layer_t* outLayers, int32_t* outFences) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    uint32_t numWritten = 0;
+    bool outputsNonNull = (outLayers != nullptr) && (outFences != nullptr);
+    for (const auto& layer : mLayers) {
+        if (outputsNonNull && (numWritten == *outNumElements)) {
+            break;
+        }
+
+        auto releaseFence = layer->getReleaseFence();
+        if (releaseFence != MiniFence::NO_FENCE) {
+            if (outputsNonNull) {
+                outLayers[numWritten] = layer->getId();
+                outFences[numWritten] = releaseFence->dup();
+            }
+            ++numWritten;
+        }
+    }
+    *outNumElements = numWritten;
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getRequests(int32_t* outDisplayRequests,
+        uint32_t* outNumElements, hwc2_layer_t* outLayers,
+        int32_t* outLayerRequests) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        return Error::NotValidated;
+    }
+
+    if (outLayers == nullptr || outLayerRequests == nullptr) {
+        *outNumElements = mChanges->getNumLayerRequests();
+        return Error::None;
+    }
+
+    // Display requests (HWC2::DisplayRequest) are not supported by hwc1:
+    // A hwc1 has always zero requests for the client.
+    *outDisplayRequests = 0;
+
+    uint32_t numWritten = 0;
+    for (const auto& request : mChanges->getLayerRequests()) {
+        if (numWritten == *outNumElements) {
+            break;
+        }
+        outLayers[numWritten] = request.first;
+        outLayerRequests[numWritten] = static_cast<int32_t>(request.second);
+        ++numWritten;
+    }
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getType(int32_t* outType) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    *outType = static_cast<int32_t>(mType);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::present(int32_t* outRetireFence) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (mChanges) {
+        Error error = mDevice.setAllDisplays();
+        if (error != Error::None) {
+            ALOGE("[%" PRIu64 "] present: setAllDisplaysFailed (%s)", mId,
+                    to_string(error).c_str());
+            return error;
+        }
+    }
+
+    *outRetireFence = mRetireFence.get()->dup();
+    ALOGV("[%" PRIu64 "] present returning retire fence %d", mId,
+            *outRetireFence);
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    auto config = getConfig(configId);
+    if (!config) {
+        return Error::BadConfig;
+    }
+    if (config == mActiveConfig) {
+        return Error::None;
+    }
+
+    if (mDevice.mHwc1MinorVersion >= 4) {
+        uint32_t hwc1Id = 0;
+        auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id);
+        if (error != Error::None) {
+            return error;
+        }
+
+        int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+                mHwc1Id, static_cast<int>(hwc1Id));
+        if (intError != 0) {
+            ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)",
+                intError);
+            return Error::BadConfig;
+        }
+        mActiveConfig = config;
+    }
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target,
+        int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("[%" PRIu64 "] setClientTarget(%p, %d)", mId, target, acquireFence);
+    mClientTarget.setBuffer(target);
+    mClientTarget.setFence(acquireFence);
+    // dataspace and damage can't be used by HWC1, so ignore them
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) {
+    std::unique_lock<std::recursive_mutex> lock (mStateMutex);
+
+    ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode);
+
+    if (mode == mActiveColorMode) {
+        return Error::None;
+    }
+    if (mColorModes.count(mode) == 0) {
+        ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode);
+        return Error::Unsupported;
+    }
+
+    uint32_t hwc1Config = 0;
+    auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config);
+    if (error != Error::None) {
+        return error;
+    }
+
+    ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config);
+    int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+            mHwc1Id, hwc1Config);
+    if (intError != 0) {
+        ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError);
+        return Error::Unsupported;
+    }
+
+    mActiveColorMode = mode;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("%" PRIu64 "] setColorTransform(%d)", mId,
+            static_cast<int32_t>(hint));
+    mHasColorTransform = (hint != HAL_COLOR_TRANSFORM_IDENTITY);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer,
+        int32_t releaseFence) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("[%" PRIu64 "] setOutputBuffer(%p, %d)", mId, buffer, releaseFence);
+    mOutputBuffer.setBuffer(buffer);
+    mOutputBuffer.setFence(releaseFence);
+    return Error::None;
+}
+
+static bool isValid(PowerMode mode) {
+    switch (mode) {
+        case PowerMode::Off: // Fall-through
+        case PowerMode::DozeSuspend: // Fall-through
+        case PowerMode::Doze: // Fall-through
+        case PowerMode::On: return true;
+    }
+}
+
+static int getHwc1PowerMode(PowerMode mode) {
+    switch (mode) {
+        case PowerMode::Off: return HWC_POWER_MODE_OFF;
+        case PowerMode::DozeSuspend: return HWC_POWER_MODE_DOZE_SUSPEND;
+        case PowerMode::Doze: return HWC_POWER_MODE_DOZE;
+        case PowerMode::On: return HWC_POWER_MODE_NORMAL;
+    }
+}
+
+Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode) {
+    if (!isValid(mode)) {
+        return Error::BadParameter;
+    }
+    if (mode == mPowerMode) {
+        return Error::None;
+    }
+
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    int error = 0;
+    if (mDevice.mHwc1MinorVersion < 4) {
+        error = mDevice.mHwc1Device->blank(mDevice.mHwc1Device, mHwc1Id,
+                mode == PowerMode::Off);
+    } else {
+        error = mDevice.mHwc1Device->setPowerMode(mDevice.mHwc1Device,
+                mHwc1Id, getHwc1PowerMode(mode));
+    }
+    ALOGE_IF(error != 0, "setPowerMode: Failed to set power mode on HWC1 (%d)",
+            error);
+
+    ALOGV("[%" PRIu64 "] setPowerMode(%s)", mId, to_string(mode).c_str());
+    mPowerMode = mode;
+    return Error::None;
+}
+
+static bool isValid(Vsync enable) {
+    switch (enable) {
+        case Vsync::Enable: // Fall-through
+        case Vsync::Disable: return true;
+        case Vsync::Invalid: return false;
+    }
+}
+
+Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable) {
+    if (!isValid(enable)) {
+        return Error::BadParameter;
+    }
+    if (enable == mVsyncEnabled) {
+        return Error::None;
+    }
+
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    int error = mDevice.mHwc1Device->eventControl(mDevice.mHwc1Device,
+            mHwc1Id, HWC_EVENT_VSYNC, enable == Vsync::Enable);
+    ALOGE_IF(error != 0, "setVsyncEnabled: Failed to set vsync on HWC1 (%d)",
+            error);
+
+    mVsyncEnabled = enable;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes,
+        uint32_t* outNumRequests) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        if (!mDevice.prepareAllDisplays()) {
+            return Error::BadDisplay;
+        }
+    } else {
+        ALOGE("Validate was called more than once!");
+    }
+
+    *outNumTypes = mChanges->getNumTypes();
+    *outNumRequests = mChanges->getNumLayerRequests();
+    ALOGV("[%" PRIu64 "] validate --> %u types, %u requests", mId, *outNumTypes,
+            *outNumRequests);
+    for (auto request : mChanges->getTypeChanges()) {
+        ALOGV("Layer %" PRIu64 " --> %s", request.first,
+                to_string(request.second).c_str());
+    }
+    return *outNumTypes > 0 ? Error::HasChanges : Error::None;
+}
+
+Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    const auto mapLayer = mDevice.mLayers.find(layerId);
+    if (mapLayer == mDevice.mLayers.end()) {
+        ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer", mId);
+        return Error::BadLayer;
+    }
+
+    const auto layer = mapLayer->second;
+    const auto zRange = mLayers.equal_range(layer);
+    bool layerOnDisplay = false;
+    for (auto current = zRange.first; current != zRange.second; ++current) {
+        if (**current == *layer) {
+            if ((*current)->getZ() == z) {
+                // Don't change anything if the Z hasn't changed
+                return Error::None;
+            }
+            current = mLayers.erase(current);
+            layerOnDisplay = true;
+            break;
+        }
+    }
+
+    if (!layerOnDisplay) {
+        ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display",
+                mId);
+        return Error::BadLayer;
+    }
+
+    layer->setZ(z);
+    mLayers.emplace(std::move(layer));
+    markGeometryChanged();
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getClientTargetSupport(uint32_t width, uint32_t height,
+                                      int32_t format, int32_t dataspace){
+    if (mActiveConfig == nullptr) {
+        return Error::Unsupported;
+    }
+
+    if (width == mActiveConfig->getAttribute(Attribute::Width) &&
+            height == mActiveConfig->getAttribute(Attribute::Height) &&
+            format == HAL_PIXEL_FORMAT_RGBA_8888 &&
+            dataspace == HAL_DATASPACE_UNKNOWN) {
+        return Error::None;
+    }
+
+    return Error::Unsupported;
+}
+
+static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = {
+    HWC_DISPLAY_VSYNC_PERIOD,
+    HWC_DISPLAY_WIDTH,
+    HWC_DISPLAY_HEIGHT,
+    HWC_DISPLAY_DPI_X,
+    HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_COLOR_TRANSFORM,
+    HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = {
+    HWC_DISPLAY_VSYNC_PERIOD,
+    HWC_DISPLAY_WIDTH,
+    HWC_DISPLAY_HEIGHT,
+    HWC_DISPLAY_DPI_X,
+    HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR =
+        sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t);
+static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR),
+        "Attribute tables have unexpected sizes");
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = {
+    6, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+    0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+    1, // HWC_DISPLAY_WIDTH = 2,
+    2, // HWC_DISPLAY_HEIGHT = 3,
+    3, // HWC_DISPLAY_DPI_X = 4,
+    4, // HWC_DISPLAY_DPI_Y = 5,
+    5, // HWC_DISPLAY_COLOR_TRANSFORM = 6,
+};
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = {
+    5, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+    0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+    1, // HWC_DISPLAY_WIDTH = 2,
+    2, // HWC_DISPLAY_HEIGHT = 3,
+    3, // HWC_DISPLAY_DPI_X = 4,
+    4, // HWC_DISPLAY_DPI_Y = 5,
+};
+
+template <uint32_t attribute>
+static constexpr bool attributesMatch()
+{
+    bool match = (attribute ==
+            ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]);
+    if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) {
+        return match;
+    }
+
+    return match && (attribute ==
+            ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]);
+}
+static_assert(attributesMatch<HWC_DISPLAY_VSYNC_PERIOD>(),
+        "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_WIDTH>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_HEIGHT>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_DPI_X>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(),
+        "Tables out of sync");
+
+void HWC2On1Adapter::Display::populateConfigs() {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("[%" PRIu64 "] populateConfigs", mId);
+
+    if (mHwc1Id == -1) {
+        ALOGE("populateConfigs: HWC1 ID not set");
+        return;
+    }
+
+    const size_t MAX_NUM_CONFIGS = 128;
+    uint32_t configs[MAX_NUM_CONFIGS] = {};
+    size_t numConfigs = MAX_NUM_CONFIGS;
+    mDevice.mHwc1Device->getDisplayConfigs(mDevice.mHwc1Device, mHwc1Id,
+            configs, &numConfigs);
+
+    for (size_t c = 0; c < numConfigs; ++c) {
+        uint32_t hwc1ConfigId = configs[c];
+        auto newConfig = std::make_shared<Config>(*this);
+
+        int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {};
+        bool hasColor = true;
+        auto result = mDevice.mHwc1Device->getDisplayAttributes(
+                mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId,
+                ATTRIBUTES_WITH_COLOR, values);
+        if (result != 0) {
+            mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device,
+                    mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values);
+            hasColor = false;
+        }
+
+        auto attributeMap = hasColor ?
+                ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR;
+
+        newConfig->setAttribute(Attribute::VsyncPeriod,
+                values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]);
+        newConfig->setAttribute(Attribute::Width,
+                values[attributeMap[HWC_DISPLAY_WIDTH]]);
+        newConfig->setAttribute(Attribute::Height,
+                values[attributeMap[HWC_DISPLAY_HEIGHT]]);
+        newConfig->setAttribute(Attribute::DpiX,
+                values[attributeMap[HWC_DISPLAY_DPI_X]]);
+        newConfig->setAttribute(Attribute::DpiY,
+                values[attributeMap[HWC_DISPLAY_DPI_Y]]);
+        if (hasColor) {
+            // In HWC1, color modes are referred to as color transforms. To avoid confusion with
+            // the HWC2 concept of color transforms, we internally refer to them as color modes for
+            // both HWC1 and 2.
+            newConfig->setAttribute(ColorMode,
+                    values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]);
+        }
+
+        // We can only do this after attempting to read the color mode
+        newConfig->setHwc1Id(hwc1ConfigId);
+
+        for (auto& existingConfig : mConfigs) {
+            if (existingConfig->merge(*newConfig)) {
+                ALOGV("Merged config %d with existing config %u: %s",
+                        hwc1ConfigId, existingConfig->getId(),
+                        existingConfig->toString().c_str());
+                newConfig.reset();
+                break;
+            }
+        }
+
+        // If it wasn't merged with any existing config, add it to the end
+        if (newConfig) {
+            newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size()));
+            ALOGV("Found new config %u: %s", newConfig->getId(),
+                    newConfig->toString().c_str());
+            mConfigs.emplace_back(std::move(newConfig));
+        }
+    }
+
+    initializeActiveConfig();
+    populateColorModes();
+}
+
+void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    mConfigs.emplace_back(std::make_shared<Config>(*this));
+    auto& config = mConfigs[0];
+
+    config->setAttribute(Attribute::Width, static_cast<int32_t>(width));
+    config->setAttribute(Attribute::Height, static_cast<int32_t>(height));
+    config->setHwc1Id(0);
+    config->setId(0);
+    mActiveConfig = config;
+}
+
+bool HWC2On1Adapter::Display::prepare() {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    // Only prepare display contents for displays HWC1 knows about
+    if (mHwc1Id == -1) {
+        return true;
+    }
+
+    // It doesn't make sense to prepare a display for which there is no active
+    // config, so return early
+    if (!mActiveConfig) {
+        ALOGE("[%" PRIu64 "] Attempted to prepare, but no config active", mId);
+        return false;
+    }
+
+    allocateRequestedContents();
+    assignHwc1LayerIds();
+
+    mHwc1RequestedContents->retireFenceFd = -1;
+    mHwc1RequestedContents->flags = 0;
+    if (mGeometryChanged) {
+        mHwc1RequestedContents->flags |= HWC_GEOMETRY_CHANGED;
+    }
+    mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer();
+    mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence();
+
+    // +1 is for framebuffer target layer.
+    mHwc1RequestedContents->numHwLayers = mLayers.size() + 1;
+    for (auto& layer : mLayers) {
+        auto& hwc1Layer = mHwc1RequestedContents->hwLayers[layer->getHwc1Id()];
+        hwc1Layer.releaseFenceFd = -1;
+        hwc1Layer.acquireFenceFd = -1;
+        ALOGV("Applying states for layer %" PRIu64 " ", layer->getId());
+        layer->applyState(hwc1Layer);
+    }
+
+    prepareFramebufferTarget();
+
+    resetGeometryMarker();
+
+    return true;
+}
+
+void HWC2On1Adapter::Display::generateChanges() {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    mChanges.reset(new Changes);
+
+    size_t numLayers = mHwc1RequestedContents->numHwLayers;
+    for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
+        const auto& receivedLayer = mHwc1RequestedContents->hwLayers[hwc1Id];
+        if (mHwc1LayerMap.count(hwc1Id) == 0) {
+            ALOGE_IF(receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET,
+                    "generateChanges: HWC1 layer %zd doesn't have a"
+                    " matching HWC2 layer, and isn't the framebuffer target",
+                    hwc1Id);
+            continue;
+        }
+
+        Layer& layer = *mHwc1LayerMap[hwc1Id];
+        updateTypeChanges(receivedLayer, layer);
+        updateLayerRequests(receivedLayer, layer);
+    }
+}
+
+bool HWC2On1Adapter::Display::hasChanges() const {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+    return mChanges != nullptr;
+}
+
+Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges || (mChanges->getNumTypes() > 0)) {
+        ALOGE("[%" PRIu64 "] set failed: not validated", mId);
+        return Error::NotValidated;
+    }
+
+    // Set up the client/framebuffer target
+    auto numLayers = hwcContents.numHwLayers;
+
+    // Close acquire fences on FRAMEBUFFER layers, since they will not be used
+    // by HWC
+    for (size_t l = 0; l < numLayers - 1; ++l) {
+        auto& layer = hwcContents.hwLayers[l];
+        if (layer.compositionType == HWC_FRAMEBUFFER) {
+            ALOGV("Closing fence %d for layer %zd", layer.acquireFenceFd, l);
+            close(layer.acquireFenceFd);
+            layer.acquireFenceFd = -1;
+        }
+    }
+
+    auto& clientTargetLayer = hwcContents.hwLayers[numLayers - 1];
+    if (clientTargetLayer.compositionType == HWC_FRAMEBUFFER_TARGET) {
+        clientTargetLayer.handle = mClientTarget.getBuffer();
+        clientTargetLayer.acquireFenceFd = mClientTarget.getFence();
+    } else {
+        ALOGE("[%" PRIu64 "] set: last HWC layer wasn't FRAMEBUFFER_TARGET",
+                mId);
+    }
+
+    mChanges.reset();
+
+    return Error::None;
+}
+
+void HWC2On1Adapter::Display::addRetireFence(int fenceFd) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+    mRetireFence.add(fenceFd);
+}
+
+void HWC2On1Adapter::Display::addReleaseFences(
+        const hwc_display_contents_1_t& hwcContents) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    size_t numLayers = hwcContents.numHwLayers;
+    for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
+        const auto& receivedLayer = hwcContents.hwLayers[hwc1Id];
+        if (mHwc1LayerMap.count(hwc1Id) == 0) {
+            if (receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+                ALOGE("addReleaseFences: HWC1 layer %zd doesn't have a"
+                        " matching HWC2 layer, and isn't the framebuffer"
+                        " target", hwc1Id);
+            }
+            // Close the framebuffer target release fence since we will use the
+            // display retire fence instead
+            if (receivedLayer.releaseFenceFd != -1) {
+                close(receivedLayer.releaseFenceFd);
+            }
+            continue;
+        }
+
+        Layer& layer = *mHwc1LayerMap[hwc1Id];
+        ALOGV("Adding release fence %d to layer %" PRIu64,
+                receivedLayer.releaseFenceFd, layer.getId());
+        layer.addReleaseFence(receivedLayer.releaseFenceFd);
+    }
+}
+
+bool HWC2On1Adapter::Display::hasColorTransform() const {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+    return mHasColorTransform;
+}
+
+static std::string hwc1CompositionString(int32_t type) {
+    switch (type) {
+        case HWC_FRAMEBUFFER: return "Framebuffer";
+        case HWC_OVERLAY: return "Overlay";
+        case HWC_BACKGROUND: return "Background";
+        case HWC_FRAMEBUFFER_TARGET: return "FramebufferTarget";
+        case HWC_SIDEBAND: return "Sideband";
+        case HWC_CURSOR_OVERLAY: return "CursorOverlay";
+        default:
+            return std::string("Unknown (") + std::to_string(type) + ")";
+    }
+}
+
+static std::string hwc1TransformString(int32_t transform) {
+    switch (transform) {
+        case 0: return "None";
+        case HWC_TRANSFORM_FLIP_H: return "FlipH";
+        case HWC_TRANSFORM_FLIP_V: return "FlipV";
+        case HWC_TRANSFORM_ROT_90: return "Rotate90";
+        case HWC_TRANSFORM_ROT_180: return "Rotate180";
+        case HWC_TRANSFORM_ROT_270: return "Rotate270";
+        case HWC_TRANSFORM_FLIP_H_ROT_90: return "FlipHRotate90";
+        case HWC_TRANSFORM_FLIP_V_ROT_90: return "FlipVRotate90";
+        default:
+            return std::string("Unknown (") + std::to_string(transform) + ")";
+    }
+}
+
+static std::string hwc1BlendModeString(int32_t mode) {
+    switch (mode) {
+        case HWC_BLENDING_NONE: return "None";
+        case HWC_BLENDING_PREMULT: return "Premultiplied";
+        case HWC_BLENDING_COVERAGE: return "Coverage";
+        default:
+            return std::string("Unknown (") + std::to_string(mode) + ")";
+    }
+}
+
+static std::string rectString(hwc_rect_t rect) {
+    std::stringstream output;
+    output << "[" << rect.left << ", " << rect.top << ", ";
+    output << rect.right << ", " << rect.bottom << "]";
+    return output.str();
+}
+
+static std::string approximateFloatString(float f) {
+    if (static_cast<int32_t>(f) == f) {
+        return std::to_string(static_cast<int32_t>(f));
+    }
+    int32_t truncated = static_cast<int32_t>(f * 10);
+    bool approximate = (static_cast<float>(truncated) != f * 10);
+    const size_t BUFFER_SIZE = 32;
+    char buffer[BUFFER_SIZE] = {};
+    auto bytesWritten = snprintf(buffer, BUFFER_SIZE,
+            "%s%.1f", approximate ? "~" : "", f);
+    return std::string(buffer, bytesWritten);
+}
+
+static std::string frectString(hwc_frect_t frect) {
+    std::stringstream output;
+    output << "[" << approximateFloatString(frect.left) << ", ";
+    output << approximateFloatString(frect.top) << ", ";
+    output << approximateFloatString(frect.right) << ", ";
+    output << approximateFloatString(frect.bottom) << "]";
+    return output.str();
+}
+
+static std::string colorString(hwc_color_t color) {
+    std::stringstream output;
+    output << "RGBA [";
+    output << static_cast<int32_t>(color.r) << ", ";
+    output << static_cast<int32_t>(color.g) << ", ";
+    output << static_cast<int32_t>(color.b) << ", ";
+    output << static_cast<int32_t>(color.a) << "]";
+    return output.str();
+}
+
+static std::string alphaString(float f) {
+    const size_t BUFFER_SIZE = 8;
+    char buffer[BUFFER_SIZE] = {};
+    auto bytesWritten = snprintf(buffer, BUFFER_SIZE, "%.3f", f);
+    return std::string(buffer, bytesWritten);
+}
+
+static std::string to_string(const hwc_layer_1_t& hwcLayer,
+        int32_t hwc1MinorVersion) {
+    const char* fill = "          ";
+
+    std::stringstream output;
+
+    output << "  Composition: " <<
+            hwc1CompositionString(hwcLayer.compositionType);
+
+    if (hwcLayer.compositionType == HWC_BACKGROUND) {
+        output << "  Color: " << colorString(hwcLayer.backgroundColor) << '\n';
+    } else if (hwcLayer.compositionType == HWC_SIDEBAND) {
+        output << "  Stream: " << hwcLayer.sidebandStream << '\n';
+    } else {
+        output << "  Buffer: " << hwcLayer.handle << "/" <<
+                hwcLayer.acquireFenceFd << '\n';
+    }
+
+    output << fill << "Display frame: " << rectString(hwcLayer.displayFrame) <<
+            '\n';
+
+    output << fill << "Source crop: ";
+    if (hwc1MinorVersion >= 3) {
+        output << frectString(hwcLayer.sourceCropf) << '\n';
+    } else {
+        output << rectString(hwcLayer.sourceCropi) << '\n';
+    }
+
+    output << fill << "Transform: " << hwc1TransformString(hwcLayer.transform);
+    output << "  Blend mode: " << hwc1BlendModeString(hwcLayer.blending);
+    if (hwcLayer.planeAlpha != 0xFF) {
+        output << "  Alpha: " << alphaString(hwcLayer.planeAlpha / 255.0f);
+    }
+    output << '\n';
+
+    if (hwcLayer.hints != 0) {
+        output << fill << "Hints:";
+        if ((hwcLayer.hints & HWC_HINT_TRIPLE_BUFFER) != 0) {
+            output << " TripleBuffer";
+        }
+        if ((hwcLayer.hints & HWC_HINT_CLEAR_FB) != 0) {
+            output << " ClearFB";
+        }
+        output << '\n';
+    }
+
+    if (hwcLayer.flags != 0) {
+        output << fill << "Flags:";
+        if ((hwcLayer.flags & HWC_SKIP_LAYER) != 0) {
+            output << " SkipLayer";
+        }
+        if ((hwcLayer.flags & HWC_IS_CURSOR_LAYER) != 0) {
+            output << " IsCursorLayer";
+        }
+        output << '\n';
+    }
+
+    return output.str();
+}
+
+static std::string to_string(const hwc_display_contents_1_t& hwcContents,
+        int32_t hwc1MinorVersion) {
+    const char* fill = "      ";
+
+    std::stringstream output;
+    output << fill << "Geometry changed: " <<
+            ((hwcContents.flags & HWC_GEOMETRY_CHANGED) != 0 ? "Y\n" : "N\n");
+
+    output << fill << hwcContents.numHwLayers << " Layer" <<
+            ((hwcContents.numHwLayers == 1) ? "\n" : "s\n");
+    for (size_t layer = 0; layer < hwcContents.numHwLayers; ++layer) {
+        output << fill << "  Layer " << layer;
+        output << to_string(hwcContents.hwLayers[layer], hwc1MinorVersion);
+    }
+
+    if (hwcContents.outbuf != nullptr) {
+        output << fill << "Output buffer: " << hwcContents.outbuf << "/" <<
+                hwcContents.outbufAcquireFenceFd << '\n';
+    }
+
+    return output.str();
+}
+
+std::string HWC2On1Adapter::Display::dump() const {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    std::stringstream output;
+
+    output << "  Display " << mId << ": ";
+    output << to_string(mType) << "  ";
+    output << "HWC1 ID: " << mHwc1Id << "  ";
+    output << "Power mode: " << to_string(mPowerMode) << "  ";
+    output << "Vsync: " << to_string(mVsyncEnabled) << '\n';
+
+    output << "    Color modes [active]:";
+    for (const auto& mode : mColorModes) {
+        if (mode == mActiveColorMode) {
+            output << " [" << mode << ']';
+        } else {
+            output << " " << mode;
+        }
+    }
+    output << '\n';
+
+    output << "    " << mConfigs.size() << " Config" <<
+            (mConfigs.size() == 1 ? "" : "s") << " (* active)\n";
+    for (const auto& config : mConfigs) {
+        output << (config == mActiveConfig ? "    * " : "      ");
+        output << config->toString(true) << '\n';
+    }
+
+    output << "    " << mLayers.size() << " Layer" <<
+            (mLayers.size() == 1 ? "" : "s") << '\n';
+    for (const auto& layer : mLayers) {
+        output << layer->dump();
+    }
+
+    output << "    Client target: " << mClientTarget.getBuffer() << '\n';
+
+    if (mOutputBuffer.getBuffer() != nullptr) {
+        output << "    Output buffer: " << mOutputBuffer.getBuffer() << '\n';
+    }
+
+    if (mHwc1RequestedContents) {
+        output << "    Last requested HWC1 state\n";
+        output << to_string(*mHwc1RequestedContents, mDevice.mHwc1MinorVersion);
+    }
+
+    return output.str();
+}
+
+hwc_rect_t* HWC2On1Adapter::Display::GetRects(size_t numRects) {
+    if (numRects == 0) {
+        return nullptr;
+    }
+
+    if (numRects > mNumAvailableRects) {
+        // This should NEVER happen since we calculated how many rects the
+        // display would need.
+        ALOGE("Rect allocation failure! SF is likely to crash soon!");
+        return nullptr;
+
+    }
+    hwc_rect_t* rects = mNextAvailableRect;
+    mNextAvailableRect += numRects;
+    mNumAvailableRects -= numRects;
+    return rects;
+}
+
+hwc_display_contents_1* HWC2On1Adapter::Display::getDisplayContents() {
+    return mHwc1RequestedContents.get();
+}
+
+void HWC2On1Adapter::Display::Config::setAttribute(HWC2::Attribute attribute,
+        int32_t value) {
+    mAttributes[attribute] = value;
+}
+
+int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const {
+    if (mAttributes.count(attribute) == 0) {
+        return -1;
+    }
+    return mAttributes.at(attribute);
+}
+
+void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) {
+    android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode));
+    mHwc1Ids.emplace(colorMode, id);
+}
+
+bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const {
+    for (const auto& idPair : mHwc1Ids) {
+        if (id == idPair.second) {
+            return true;
+        }
+    }
+    return false;
+}
+
+Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
+        uint32_t id, android_color_mode_t* outMode) const {
+    for (const auto& idPair : mHwc1Ids) {
+        if (id == idPair.second) {
+            *outMode = idPair.first;
+            return Error::None;
+        }
+    }
+    ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId);
+    return Error::BadParameter;
+}
+
+Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode,
+        uint32_t* outId) const {
+    for (const auto& idPair : mHwc1Ids) {
+        if (mode == idPair.first) {
+            *outId = idPair.second;
+            return Error::None;
+        }
+    }
+    ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId);
+    return Error::BadParameter;
+}
+
+bool HWC2On1Adapter::Display::Config::merge(const Config& other) {
+    auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height,
+            HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX,
+            HWC2::Attribute::DpiY};
+    for (auto attribute : attributes) {
+        if (getAttribute(attribute) != other.getAttribute(attribute)) {
+            return false;
+        }
+    }
+    android_color_mode_t otherColorMode =
+            static_cast<android_color_mode_t>(other.getAttribute(ColorMode));
+    if (mHwc1Ids.count(otherColorMode) != 0) {
+        ALOGE("Attempted to merge two configs (%u and %u) which appear to be "
+                "identical", mHwc1Ids.at(otherColorMode),
+                other.mHwc1Ids.at(otherColorMode));
+        return false;
+    }
+    mHwc1Ids.emplace(otherColorMode,
+            other.mHwc1Ids.at(otherColorMode));
+    return true;
+}
+
+std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const {
+    std::set<android_color_mode_t> colorModes;
+    for (const auto& idPair : mHwc1Ids) {
+        colorModes.emplace(idPair.first);
+    }
+    return colorModes;
+}
+
+std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const {
+    std::string output;
+
+    const size_t BUFFER_SIZE = 100;
+    char buffer[BUFFER_SIZE] = {};
+    auto writtenBytes = snprintf(buffer, BUFFER_SIZE,
+            "%u x %u", mAttributes.at(HWC2::Attribute::Width),
+            mAttributes.at(HWC2::Attribute::Height));
+    output.append(buffer, writtenBytes);
+
+    if (mAttributes.count(HWC2::Attribute::VsyncPeriod) != 0) {
+        std::memset(buffer, 0, BUFFER_SIZE);
+        writtenBytes = snprintf(buffer, BUFFER_SIZE, " @ %.1f Hz",
+                1e9 / mAttributes.at(HWC2::Attribute::VsyncPeriod));
+        output.append(buffer, writtenBytes);
+    }
+
+    if (mAttributes.count(HWC2::Attribute::DpiX) != 0 &&
+            mAttributes.at(HWC2::Attribute::DpiX) != -1) {
+        std::memset(buffer, 0, BUFFER_SIZE);
+        writtenBytes = snprintf(buffer, BUFFER_SIZE,
+                ", DPI: %.1f x %.1f",
+                mAttributes.at(HWC2::Attribute::DpiX) / 1000.0f,
+                mAttributes.at(HWC2::Attribute::DpiY) / 1000.0f);
+        output.append(buffer, writtenBytes);
+    }
+
+    std::memset(buffer, 0, BUFFER_SIZE);
+    if (splitLine) {
+        writtenBytes = snprintf(buffer, BUFFER_SIZE,
+                "\n        HWC1 ID/Color transform:");
+    } else {
+        writtenBytes = snprintf(buffer, BUFFER_SIZE,
+                ", HWC1 ID/Color transform:");
+    }
+    output.append(buffer, writtenBytes);
+
+
+    for (const auto& id : mHwc1Ids) {
+        android_color_mode_t colorMode = id.first;
+        uint32_t hwc1Id = id.second;
+        std::memset(buffer, 0, BUFFER_SIZE);
+        if (colorMode == mDisplay.mActiveColorMode) {
+            writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id,
+                    colorMode);
+        } else {
+            writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id,
+                    colorMode);
+        }
+        output.append(buffer, writtenBytes);
+    }
+
+    return output;
+}
+
+std::shared_ptr<const HWC2On1Adapter::Display::Config>
+        HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const {
+    if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+        return nullptr;
+    }
+    return mConfigs[configId];
+}
+
+void HWC2On1Adapter::Display::populateColorModes() {
+    mColorModes = mConfigs[0]->getColorModes();
+    for (const auto& config : mConfigs) {
+        std::set<android_color_mode_t> intersection;
+        auto configModes = config->getColorModes();
+        std::set_intersection(mColorModes.cbegin(), mColorModes.cend(),
+                configModes.cbegin(), configModes.cend(),
+                std::inserter(intersection, intersection.begin()));
+        std::swap(intersection, mColorModes);
+    }
+}
+
+void HWC2On1Adapter::Display::initializeActiveConfig() {
+    if (mDevice.mHwc1Device->getActiveConfig == nullptr) {
+        ALOGV("getActiveConfig is null, choosing config 0");
+        mActiveConfig = mConfigs[0];
+        mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+        return;
+    }
+
+    auto activeConfig = mDevice.mHwc1Device->getActiveConfig(
+            mDevice.mHwc1Device, mHwc1Id);
+
+    // Some devices startup without an activeConfig:
+    // We need to set one ourselves.
+    if (activeConfig == HWC_ERROR) {
+        ALOGV("There is no active configuration: Picking the first one: 0.");
+        const int defaultIndex = 0;
+        mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, defaultIndex);
+        activeConfig = defaultIndex;
+    }
+
+    for (const auto& config : mConfigs) {
+        if (config->hasHwc1Id(activeConfig)) {
+            ALOGE("Setting active config to %d for HWC1 config %u", config->getId(), activeConfig);
+            mActiveConfig = config;
+            if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) {
+                // This should never happen since we checked for the config's presence before
+                // setting it as active.
+                ALOGE("Unable to find color mode for active HWC1 config %d", config->getId());
+                mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+            }
+            break;
+        }
+    }
+    if (!mActiveConfig) {
+        ALOGV("Unable to find active HWC1 config %u, defaulting to "
+                "config 0", activeConfig);
+        mActiveConfig = mConfigs[0];
+        mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+    }
+
+
+
+
+}
+
+void HWC2On1Adapter::Display::allocateRequestedContents() {
+    // What needs to be allocated:
+    // 1 hwc_display_contents_1_t
+    // 1 hwc_layer_1_t for each layer
+    // 1 hwc_rect_t for each layer's surfaceDamage
+    // 1 hwc_rect_t for each layer's visibleRegion
+    // 1 hwc_layer_1_t for the framebuffer
+    // 1 hwc_rect_t for the framebuffer's visibleRegion
+
+    // Count # of surfaceDamage
+    size_t numSurfaceDamages = 0;
+    for (const auto& layer : mLayers) {
+        numSurfaceDamages += layer->getNumSurfaceDamages();
+    }
+
+    // Count # of visibleRegions (start at 1 for mandatory framebuffer target
+    // region)
+    size_t numVisibleRegion = 1;
+    for (const auto& layer : mLayers) {
+        numVisibleRegion += layer->getNumVisibleRegions();
+    }
+
+    size_t numRects = numVisibleRegion + numSurfaceDamages;
+    auto numLayers = mLayers.size() + 1;
+    size_t size = sizeof(hwc_display_contents_1_t) +
+            sizeof(hwc_layer_1_t) * numLayers +
+            sizeof(hwc_rect_t) * numRects;
+    auto contents = static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1));
+    mHwc1RequestedContents.reset(contents);
+    mNextAvailableRect = reinterpret_cast<hwc_rect_t*>(&contents->hwLayers[numLayers]);
+    mNumAvailableRects = numRects;
+}
+
+void HWC2On1Adapter::Display::assignHwc1LayerIds() {
+    mHwc1LayerMap.clear();
+    size_t nextHwc1Id = 0;
+    for (auto& layer : mLayers) {
+        mHwc1LayerMap[nextHwc1Id] = layer;
+        layer->setHwc1Id(nextHwc1Id++);
+    }
+}
+
+void HWC2On1Adapter::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer,
+        const Layer& layer) {
+    auto layerId = layer.getId();
+    switch (hwc1Layer.compositionType) {
+        case HWC_FRAMEBUFFER:
+            if (layer.getCompositionType() != Composition::Client) {
+                mChanges->addTypeChange(layerId, Composition::Client);
+            }
+            break;
+        case HWC_OVERLAY:
+            if (layer.getCompositionType() != Composition::Device) {
+                mChanges->addTypeChange(layerId, Composition::Device);
+            }
+            break;
+        case HWC_BACKGROUND:
+            ALOGE_IF(layer.getCompositionType() != Composition::SolidColor,
+                    "updateTypeChanges: HWC1 requested BACKGROUND, but HWC2"
+                    " wasn't expecting SolidColor");
+            break;
+        case HWC_FRAMEBUFFER_TARGET:
+            // Do nothing, since it shouldn't be modified by HWC1
+            break;
+        case HWC_SIDEBAND:
+            ALOGE_IF(layer.getCompositionType() != Composition::Sideband,
+                    "updateTypeChanges: HWC1 requested SIDEBAND, but HWC2"
+                    " wasn't expecting Sideband");
+            break;
+        case HWC_CURSOR_OVERLAY:
+            ALOGE_IF(layer.getCompositionType() != Composition::Cursor,
+                    "updateTypeChanges: HWC1 requested CURSOR_OVERLAY, but"
+                    " HWC2 wasn't expecting Cursor");
+            break;
+    }
+}
+
+void HWC2On1Adapter::Display::updateLayerRequests(
+        const hwc_layer_1_t& hwc1Layer, const Layer& layer) {
+    if ((hwc1Layer.hints & HWC_HINT_CLEAR_FB) != 0) {
+        mChanges->addLayerRequest(layer.getId(),
+                LayerRequest::ClearClientTarget);
+    }
+}
+
+void HWC2On1Adapter::Display::prepareFramebufferTarget() {
+    // We check that mActiveConfig is valid in Display::prepare
+    int32_t width = mActiveConfig->getAttribute(Attribute::Width);
+    int32_t height = mActiveConfig->getAttribute(Attribute::Height);
+
+    auto& hwc1Target = mHwc1RequestedContents->hwLayers[mLayers.size()];
+    hwc1Target.compositionType = HWC_FRAMEBUFFER_TARGET;
+    hwc1Target.releaseFenceFd = -1;
+    hwc1Target.hints = 0;
+    hwc1Target.flags = 0;
+    hwc1Target.transform = 0;
+    hwc1Target.blending = HWC_BLENDING_PREMULT;
+    if (mDevice.getHwc1MinorVersion() < 3) {
+        hwc1Target.sourceCropi = {0, 0, width, height};
+    } else {
+        hwc1Target.sourceCropf = {0.0f, 0.0f, static_cast<float>(width),
+                static_cast<float>(height)};
+    }
+    hwc1Target.displayFrame = {0, 0, width, height};
+    hwc1Target.planeAlpha = 255;
+
+    hwc1Target.visibleRegionScreen.numRects = 1;
+    hwc_rect_t* rects = GetRects(1);
+    rects[0].left = 0;
+    rects[0].top = 0;
+    rects[0].right = width;
+    rects[0].bottom = height;
+    hwc1Target.visibleRegionScreen.rects = rects;
+
+    // We will set this to the correct value in set
+    hwc1Target.acquireFenceFd = -1;
+}
+
+// Layer functions
+
+std::atomic<hwc2_layer_t> HWC2On1Adapter::Layer::sNextId(1);
+
+HWC2On1Adapter::Layer::Layer(Display& display)
+  : mId(sNextId++),
+    mDisplay(display),
+    mBuffer(),
+    mSurfaceDamage(),
+    mBlendMode(BlendMode::None),
+    mColor({0, 0, 0, 0}),
+    mCompositionType(Composition::Invalid),
+    mDisplayFrame({0, 0, -1, -1}),
+    mPlaneAlpha(0.0f),
+    mSidebandStream(nullptr),
+    mSourceCrop({0.0f, 0.0f, -1.0f, -1.0f}),
+    mTransform(Transform::None),
+    mVisibleRegion(),
+    mZ(0),
+    mReleaseFence(),
+    mHwc1Id(0),
+    mHasUnsupportedPlaneAlpha(false) {}
+
+bool HWC2On1Adapter::SortLayersByZ::operator()(
+        const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) {
+    return lhs->getZ() < rhs->getZ();
+}
+
+Error HWC2On1Adapter::Layer::setBuffer(buffer_handle_t buffer,
+        int32_t acquireFence) {
+    ALOGV("Setting acquireFence to %d for layer %" PRIu64, acquireFence, mId);
+    mBuffer.setBuffer(buffer);
+    mBuffer.setFence(acquireFence);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y) {
+    if (mCompositionType != Composition::Cursor) {
+        return Error::BadLayer;
+    }
+
+    if (mDisplay.hasChanges()) {
+        return Error::NotValidated;
+    }
+
+    auto displayId = mDisplay.getHwc1Id();
+    auto hwc1Device = mDisplay.getDevice().getHwc1Device();
+    hwc1Device->setCursorPositionAsync(hwc1Device, displayId, x, y);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage) {
+    // HWC1 supports surface damage starting only with version 1.5.
+    if (mDisplay.getDevice().mHwc1MinorVersion < 5) {
+        return Error::None;
+    }
+    mSurfaceDamage.resize(damage.numRects);
+    std::copy_n(damage.rects, damage.numRects, mSurfaceDamage.begin());
+    return Error::None;
+}
+
+// Layer state functions
+
+Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode) {
+    mBlendMode = mode;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setColor(hwc_color_t color) {
+    mColor = color;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setCompositionType(Composition type) {
+    mCompositionType = type;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t) {
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame) {
+    mDisplayFrame = frame;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha) {
+    mPlaneAlpha = alpha;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream) {
+    mSidebandStream = stream;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop) {
+    mSourceCrop = crop;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setTransform(Transform transform) {
+    mTransform = transform;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+static bool compareRects(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+    return rect1.left == rect2.left &&
+            rect1.right == rect2.right &&
+            rect1.top == rect2.top &&
+            rect1.bottom == rect2.bottom;
+}
+
+Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t visible) {
+    if ((getNumVisibleRegions() != visible.numRects) ||
+        !std::equal(mVisibleRegion.begin(), mVisibleRegion.end(), visible.rects,
+                    compareRects)) {
+        mVisibleRegion.resize(visible.numRects);
+        std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin());
+        mDisplay.markGeometryChanged();
+    }
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setZ(uint32_t z) {
+    mZ = z;
+    return Error::None;
+}
+
+void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd) {
+    ALOGV("addReleaseFence %d to layer %" PRIu64, fenceFd, mId);
+    mReleaseFence.add(fenceFd);
+}
+
+const sp<MiniFence>& HWC2On1Adapter::Layer::getReleaseFence() const {
+    return mReleaseFence.get();
+}
+
+void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer) {
+    applyCommonState(hwc1Layer);
+    applyCompositionType(hwc1Layer);
+    switch (mCompositionType) {
+        case Composition::SolidColor : applySolidColorState(hwc1Layer); break;
+        case Composition::Sideband : applySidebandState(hwc1Layer); break;
+        default: applyBufferState(hwc1Layer); break;
+    }
+}
+
+static std::string regionStrings(const std::vector<hwc_rect_t>& visibleRegion,
+        const std::vector<hwc_rect_t>& surfaceDamage) {
+    std::string regions;
+    regions += "        Visible Region";
+    regions.resize(40, ' ');
+    regions += "Surface Damage\n";
+
+    size_t numPrinted = 0;
+    size_t maxSize = std::max(visibleRegion.size(), surfaceDamage.size());
+    while (numPrinted < maxSize) {
+        std::string line("        ");
+        if (visibleRegion.empty() && numPrinted == 0) {
+            line += "None";
+        } else if (numPrinted < visibleRegion.size()) {
+            line += rectString(visibleRegion[numPrinted]);
+        }
+        line.resize(40, ' ');
+        if (surfaceDamage.empty() && numPrinted == 0) {
+            line += "None";
+        } else if (numPrinted < surfaceDamage.size()) {
+            line += rectString(surfaceDamage[numPrinted]);
+        }
+        line += '\n';
+        regions += line;
+        ++numPrinted;
+    }
+    return regions;
+}
+
+std::string HWC2On1Adapter::Layer::dump() const {
+    std::stringstream output;
+    const char* fill = "      ";
+
+    output << fill << to_string(mCompositionType);
+    output << " Layer  HWC2/1: " << mId << "/" << mHwc1Id << "  ";
+    output << "Z: " << mZ;
+    if (mCompositionType == HWC2::Composition::SolidColor) {
+        output << "  " << colorString(mColor);
+    } else if (mCompositionType == HWC2::Composition::Sideband) {
+        output << "  Handle: " << mSidebandStream << '\n';
+    } else {
+        output << "  Buffer: " << mBuffer.getBuffer() << "/" <<
+                mBuffer.getFence() << '\n';
+        output << fill << "  Display frame [LTRB]: " <<
+                rectString(mDisplayFrame) << '\n';
+        output << fill << "  Source crop: " <<
+                frectString(mSourceCrop) << '\n';
+        output << fill << "  Transform: " << to_string(mTransform);
+        output << "  Blend mode: " << to_string(mBlendMode);
+        if (mPlaneAlpha != 1.0f) {
+            output << "  Alpha: " <<
+                alphaString(mPlaneAlpha) << '\n';
+        } else {
+            output << '\n';
+        }
+        output << regionStrings(mVisibleRegion, mSurfaceDamage);
+    }
+    return output.str();
+}
+
+static int getHwc1Blending(HWC2::BlendMode blendMode) {
+    switch (blendMode) {
+        case BlendMode::Coverage: return HWC_BLENDING_COVERAGE;
+        case BlendMode::Premultiplied: return HWC_BLENDING_PREMULT;
+        default: return HWC_BLENDING_NONE;
+    }
+}
+
+void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer) {
+    auto minorVersion = mDisplay.getDevice().getHwc1MinorVersion();
+    hwc1Layer.blending = getHwc1Blending(mBlendMode);
+    hwc1Layer.displayFrame = mDisplayFrame;
+
+    auto pendingAlpha = mPlaneAlpha;
+    if (minorVersion < 2) {
+        mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f;
+    } else {
+        hwc1Layer.planeAlpha =
+                static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f);
+    }
+
+    if (minorVersion < 3) {
+        auto pending = mSourceCrop;
+        hwc1Layer.sourceCropi.left =
+                static_cast<int32_t>(std::ceil(pending.left));
+        hwc1Layer.sourceCropi.top =
+                static_cast<int32_t>(std::ceil(pending.top));
+        hwc1Layer.sourceCropi.right =
+                static_cast<int32_t>(std::floor(pending.right));
+        hwc1Layer.sourceCropi.bottom =
+                static_cast<int32_t>(std::floor(pending.bottom));
+    } else {
+        hwc1Layer.sourceCropf = mSourceCrop;
+    }
+
+    hwc1Layer.transform = static_cast<uint32_t>(mTransform);
+
+    auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen;
+    hwc1VisibleRegion.numRects = mVisibleRegion.size();
+    hwc_rect_t* rects = mDisplay.GetRects(hwc1VisibleRegion.numRects);
+    hwc1VisibleRegion.rects = rects;
+    for (size_t i = 0; i < mVisibleRegion.size(); i++) {
+        rects[i] = mVisibleRegion[i];
+    }
+}
+
+void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer) {
+    // If the device does not support background color it is likely to make
+    // assumption regarding backgroundColor and handle (both fields occupy
+    // the same location in hwc_layer_1_t union).
+    // To not confuse these devices we don't set background color and we
+    // make sure handle is a null pointer.
+    if (hasUnsupportedBackgroundColor()) {
+        hwc1Layer.handle = nullptr;
+    } else {
+        hwc1Layer.backgroundColor = mColor;
+    }
+}
+
+void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer) {
+    hwc1Layer.sidebandStream = mSidebandStream;
+}
+
+void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer) {
+    hwc1Layer.handle = mBuffer.getBuffer();
+    hwc1Layer.acquireFenceFd = mBuffer.getFence();
+}
+
+void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer) {
+    // HWC1 never supports color transforms or dataspaces and only sometimes
+    // supports plane alpha (depending on the version). These require us to drop
+    // some or all layers to client composition.
+    if (mHasUnsupportedPlaneAlpha || mDisplay.hasColorTransform() ||
+            hasUnsupportedBackgroundColor()) {
+        hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+        hwc1Layer.flags = HWC_SKIP_LAYER;
+        return;
+    }
+
+    hwc1Layer.flags = 0;
+    switch (mCompositionType) {
+        case Composition::Client:
+            hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+            hwc1Layer.flags |= HWC_SKIP_LAYER;
+            break;
+        case Composition::Device:
+            hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+            break;
+        case Composition::SolidColor:
+            // In theory the following line should work, but since the HWC1
+            // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1
+            // devices may not work correctly. To be on the safe side, we
+            // fall back to client composition.
+            //
+            // hwc1Layer.compositionType = HWC_BACKGROUND;
+            hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+            hwc1Layer.flags |= HWC_SKIP_LAYER;
+            break;
+        case Composition::Cursor:
+            hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+            if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) {
+                hwc1Layer.hints |= HWC_IS_CURSOR_LAYER;
+            }
+            break;
+        case Composition::Sideband:
+            if (mDisplay.getDevice().getHwc1MinorVersion() < 4) {
+                hwc1Layer.compositionType = HWC_SIDEBAND;
+            } else {
+                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+                hwc1Layer.flags |= HWC_SKIP_LAYER;
+            }
+            break;
+        default:
+            hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+            hwc1Layer.flags |= HWC_SKIP_LAYER;
+            break;
+    }
+    ALOGV("Layer %" PRIu64 " %s set to %d", mId,
+            to_string(mCompositionType).c_str(),
+            hwc1Layer.compositionType);
+    ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, "    and skipping");
+}
+
+// Adapter helpers
+
+void HWC2On1Adapter::populateCapabilities() {
+    if (mHwc1MinorVersion >= 3U) {
+        int supportedTypes = 0;
+        auto result = mHwc1Device->query(mHwc1Device,
+                HWC_DISPLAY_TYPES_SUPPORTED, &supportedTypes);
+        if ((result == 0) && ((supportedTypes & HWC_DISPLAY_VIRTUAL_BIT) != 0)) {
+            ALOGI("Found support for HWC virtual displays");
+            mHwc1SupportsVirtualDisplays = true;
+        }
+    }
+    if (mHwc1MinorVersion >= 4U) {
+        mCapabilities.insert(Capability::SidebandStream);
+    }
+
+    // Check for HWC background color layer support.
+    if (mHwc1MinorVersion >= 1U) {
+        int backgroundColorSupported = 0;
+        auto result = mHwc1Device->query(mHwc1Device,
+                                         HWC_BACKGROUND_LAYER_SUPPORTED,
+                                         &backgroundColorSupported);
+        if ((result == 0) && (backgroundColorSupported == 1)) {
+            ALOGV("Found support for HWC background color");
+            mHwc1SupportsBackgroundColor = true;
+        }
+    }
+
+    // Some devices might have HWC1 retire fences that accurately emulate
+    // HWC2 present fences when they are deferred, but it's not very reliable.
+    // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices.
+    mCapabilities.insert(Capability::PresentFenceIsNotReliable);
+}
+
+HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) {
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    auto display = mDisplays.find(id);
+    if (display == mDisplays.end()) {
+        return nullptr;
+    }
+
+    return display->second.get();
+}
+
+std::tuple<HWC2On1Adapter::Layer*, Error> HWC2On1Adapter::getLayer(
+        hwc2_display_t displayId, hwc2_layer_t layerId) {
+    auto display = getDisplay(displayId);
+    if (!display) {
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadDisplay);
+    }
+
+    auto layerEntry = mLayers.find(layerId);
+    if (layerEntry == mLayers.end()) {
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+    }
+
+    auto layer = layerEntry->second;
+    if (layer->getDisplay().getId() != displayId) {
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+    }
+    return std::make_tuple(layer.get(), Error::None);
+}
+
+void HWC2On1Adapter::populatePrimary() {
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical);
+    mHwc1DisplayMap[HWC_DISPLAY_PRIMARY] = display->getId();
+    display->setHwc1Id(HWC_DISPLAY_PRIMARY);
+    display->populateConfigs();
+    mDisplays.emplace(display->getId(), std::move(display));
+}
+
+bool HWC2On1Adapter::prepareAllDisplays() {
+    ATRACE_CALL();
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    for (const auto& displayPair : mDisplays) {
+        auto& display = displayPair.second;
+        if (!display->prepare()) {
+            return false;
+        }
+    }
+
+    if (mHwc1DisplayMap.count(HWC_DISPLAY_PRIMARY) == 0) {
+        ALOGE("prepareAllDisplays: Unable to find primary HWC1 display");
+        return false;
+    }
+
+    // Build an array of hwc_display_contents_1 to call prepare() on HWC1.
+    mHwc1Contents.clear();
+
+    // Always push the primary display
+    auto primaryDisplayId = mHwc1DisplayMap[HWC_DISPLAY_PRIMARY];
+    auto& primaryDisplay = mDisplays[primaryDisplayId];
+    mHwc1Contents.push_back(primaryDisplay->getDisplayContents());
+
+    // Push the external display, if present
+    if (mHwc1DisplayMap.count(HWC_DISPLAY_EXTERNAL) != 0) {
+        auto externalDisplayId = mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL];
+        auto& externalDisplay = mDisplays[externalDisplayId];
+        mHwc1Contents.push_back(externalDisplay->getDisplayContents());
+    } else {
+        // Even if an external display isn't present, we still need to send
+        // at least two displays down to HWC1
+        mHwc1Contents.push_back(nullptr);
+    }
+
+    // Push the hardware virtual display, if supported and present
+    if (mHwc1MinorVersion >= 3) {
+        if (mHwc1DisplayMap.count(HWC_DISPLAY_VIRTUAL) != 0) {
+            auto virtualDisplayId = mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL];
+            auto& virtualDisplay = mDisplays[virtualDisplayId];
+            mHwc1Contents.push_back(virtualDisplay->getDisplayContents());
+        } else {
+            mHwc1Contents.push_back(nullptr);
+        }
+    }
+
+    for (auto& displayContents : mHwc1Contents) {
+        if (!displayContents) {
+            continue;
+        }
+
+        ALOGV("Display %zd layers:", mHwc1Contents.size() - 1);
+        for (size_t l = 0; l < displayContents->numHwLayers; ++l) {
+            auto& layer = displayContents->hwLayers[l];
+            ALOGV("  %zd: %d", l, layer.compositionType);
+        }
+    }
+
+    ALOGV("Calling HWC1 prepare");
+    {
+        ATRACE_NAME("HWC1 prepare");
+        mHwc1Device->prepare(mHwc1Device, mHwc1Contents.size(),
+                mHwc1Contents.data());
+    }
+
+    for (size_t c = 0; c < mHwc1Contents.size(); ++c) {
+        auto& contents = mHwc1Contents[c];
+        if (!contents) {
+            continue;
+        }
+        ALOGV("Display %zd layers:", c);
+        for (size_t l = 0; l < contents->numHwLayers; ++l) {
+            ALOGV("  %zd: %d", l, contents->hwLayers[l].compositionType);
+        }
+    }
+
+    // Return the received contents to their respective displays
+    for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+        if (mHwc1Contents[hwc1Id] == nullptr) {
+            continue;
+        }
+
+        auto displayId = mHwc1DisplayMap[hwc1Id];
+        auto& display = mDisplays[displayId];
+        display->generateChanges();
+    }
+
+    return true;
+}
+
+void dumpHWC1Message(hwc_composer_device_1* device, size_t numDisplays,
+                     hwc_display_contents_1_t** displays) {
+    ALOGV("*****************************");
+    size_t displayId = 0;
+    while (displayId < numDisplays) {
+        hwc_display_contents_1_t* display = displays[displayId];
+
+        ALOGV("hwc_display_contents_1_t[%zu] @0x%p", displayId, display);
+        if (display == nullptr) {
+            displayId++;
+            continue;
+        }
+        ALOGV("  retirefd:0x%08x", display->retireFenceFd);
+        ALOGV("  outbuf  :0x%p", display->outbuf);
+        ALOGV("  outbuffd:0x%08x", display->outbufAcquireFenceFd);
+        ALOGV("  flags   :0x%08x", display->flags);
+        for(size_t layerId=0 ; layerId < display->numHwLayers ; layerId++) {
+            hwc_layer_1_t& layer = display->hwLayers[layerId];
+            ALOGV("    Layer[%zu]:", layerId);
+            ALOGV("      composition        : 0x%08x", layer.compositionType);
+            ALOGV("      hints              : 0x%08x", layer.hints);
+            ALOGV("      flags              : 0x%08x", layer.flags);
+            ALOGV("      handle             : 0x%p", layer.handle);
+            ALOGV("      transform          : 0x%08x", layer.transform);
+            ALOGV("      blending           : 0x%08x", layer.blending);
+            ALOGV("      sourceCropf        : %f, %f, %f, %f",
+                  layer.sourceCropf.left,
+                  layer.sourceCropf.top,
+                  layer.sourceCropf.right,
+                  layer.sourceCropf.bottom);
+            ALOGV("      displayFrame       : %d, %d, %d, %d",
+                  layer.displayFrame.left,
+                  layer.displayFrame.left,
+                  layer.displayFrame.left,
+                  layer.displayFrame.left);
+            hwc_region_t& visReg = layer.visibleRegionScreen;
+            ALOGV("      visibleRegionScreen: #0x%08zx[@0x%p]",
+                  visReg.numRects,
+                  visReg.rects);
+            for (size_t visRegId=0; visRegId < visReg.numRects ; visRegId++) {
+                if (layer.visibleRegionScreen.rects == nullptr) {
+                    ALOGV("        null");
+                } else {
+                    ALOGV("        visibleRegionScreen[%zu] %d, %d, %d, %d",
+                          visRegId,
+                          visReg.rects[visRegId].left,
+                          visReg.rects[visRegId].top,
+                          visReg.rects[visRegId].right,
+                          visReg.rects[visRegId].bottom);
+                }
+            }
+            ALOGV("      acquireFenceFd     : 0x%08x", layer.acquireFenceFd);
+            ALOGV("      releaseFenceFd     : 0x%08x", layer.releaseFenceFd);
+            ALOGV("      planeAlpha         : 0x%08x", layer.planeAlpha);
+            if (getMinorVersion(device) < 5)
+               continue;
+            ALOGV("      surfaceDamage      : #0x%08zx[@0x%p]",
+                  layer.surfaceDamage.numRects,
+                  layer.surfaceDamage.rects);
+            for (size_t sdId=0; sdId < layer.surfaceDamage.numRects ; sdId++) {
+                if (layer.surfaceDamage.rects == nullptr) {
+                    ALOGV("      null");
+                } else {
+                    ALOGV("      surfaceDamage[%zu] %d, %d, %d, %d",
+                          sdId,
+                          layer.surfaceDamage.rects[sdId].left,
+                          layer.surfaceDamage.rects[sdId].top,
+                          layer.surfaceDamage.rects[sdId].right,
+                          layer.surfaceDamage.rects[sdId].bottom);
+                }
+            }
+        }
+        displayId++;
+    }
+    ALOGV("-----------------------------");
+}
+
+Error HWC2On1Adapter::setAllDisplays() {
+    ATRACE_CALL();
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // Make sure we're ready to validate
+    for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+        if (mHwc1Contents[hwc1Id] == nullptr) {
+            continue;
+        }
+
+        auto displayId = mHwc1DisplayMap[hwc1Id];
+        auto& display = mDisplays[displayId];
+        Error error = display->set(*mHwc1Contents[hwc1Id]);
+        if (error != Error::None) {
+            ALOGE("setAllDisplays: Failed to set display %zd: %s", hwc1Id,
+                    to_string(error).c_str());
+            return error;
+        }
+    }
+
+    ALOGV("Calling HWC1 set");
+    {
+        ATRACE_NAME("HWC1 set");
+        //dumpHWC1Message(mHwc1Device, mHwc1Contents.size(), mHwc1Contents.data());
+        mHwc1Device->set(mHwc1Device, mHwc1Contents.size(),
+                mHwc1Contents.data());
+    }
+
+    // Add retire and release fences
+    for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+        if (mHwc1Contents[hwc1Id] == nullptr) {
+            continue;
+        }
+
+        auto displayId = mHwc1DisplayMap[hwc1Id];
+        auto& display = mDisplays[displayId];
+        auto retireFenceFd = mHwc1Contents[hwc1Id]->retireFenceFd;
+        ALOGV("setAllDisplays: Adding retire fence %d to display %zd",
+                retireFenceFd, hwc1Id);
+        display->addRetireFence(mHwc1Contents[hwc1Id]->retireFenceFd);
+        display->addReleaseFences(*mHwc1Contents[hwc1Id]);
+    }
+
+    return Error::None;
+}
+
+void HWC2On1Adapter::hwc1Invalidate() {
+    ALOGV("Received hwc1Invalidate");
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // If the HWC2-side callback hasn't been registered yet, buffer this until
+    // it is registered.
+    if (mCallbacks.count(Callback::Refresh) == 0) {
+        mHasPendingInvalidate = true;
+        return;
+    }
+
+    const auto& callbackInfo = mCallbacks[Callback::Refresh];
+    std::vector<hwc2_display_t> displays;
+    for (const auto& displayPair : mDisplays) {
+        displays.emplace_back(displayPair.first);
+    }
+
+    // Call back without the state lock held.
+    lock.unlock();
+
+    auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(callbackInfo.pointer);
+    for (auto display : displays) {
+        refresh(callbackInfo.data, display);
+    }
+}
+
+void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) {
+    ALOGV("Received hwc1Vsync(%d, %" PRId64 ")", hwc1DisplayId, timestamp);
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // If the HWC2-side callback hasn't been registered yet, buffer this until
+    // it is registered.
+    if (mCallbacks.count(Callback::Vsync) == 0) {
+        mPendingVsyncs.emplace_back(hwc1DisplayId, timestamp);
+        return;
+    }
+
+    if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+        ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", hwc1DisplayId);
+        return;
+    }
+
+    const auto& callbackInfo = mCallbacks[Callback::Vsync];
+    auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+
+    // Call back without the state lock held.
+    lock.unlock();
+
+    auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer);
+    vsync(callbackInfo.data, displayId, timestamp);
+}
+
+void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected) {
+    ALOGV("Received hwc1Hotplug(%d, %d)", hwc1DisplayId, connected);
+
+    if (hwc1DisplayId != HWC_DISPLAY_EXTERNAL) {
+        ALOGE("hwc1Hotplug: Received hotplug for non-external display");
+        return;
+    }
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // If the HWC2-side callback hasn't been registered yet, buffer this until
+    // it is registered
+    if (mCallbacks.count(Callback::Hotplug) == 0) {
+        mPendingHotplugs.emplace_back(hwc1DisplayId, connected);
+        return;
+    }
+
+    hwc2_display_t displayId = UINT64_MAX;
+    if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+        if (connected == 0) {
+            ALOGW("hwc1Hotplug: Received disconnect for unconnected display");
+            return;
+        }
+
+        // Create a new display on connect
+        auto display = std::make_shared<HWC2On1Adapter::Display>(*this,
+                HWC2::DisplayType::Physical);
+        display->setHwc1Id(HWC_DISPLAY_EXTERNAL);
+        display->populateConfigs();
+        displayId = display->getId();
+        mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL] = displayId;
+        mDisplays.emplace(displayId, std::move(display));
+    } else {
+        if (connected != 0) {
+            ALOGW("hwc1Hotplug: Received connect for previously connected "
+                    "display");
+            return;
+        }
+
+        // Disconnect an existing display
+        displayId = mHwc1DisplayMap[hwc1DisplayId];
+        mHwc1DisplayMap.erase(HWC_DISPLAY_EXTERNAL);
+        mDisplays.erase(displayId);
+    }
+
+    const auto& callbackInfo = mCallbacks[Callback::Hotplug];
+
+    // Call back without the state lock held
+    lock.unlock();
+
+    auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(callbackInfo.pointer);
+    auto hwc2Connected = (connected == 0) ?
+            HWC2::Connection::Disconnected : HWC2::Connection::Connected;
+    hotplug(callbackInfo.data, displayId, static_cast<int32_t>(hwc2Connected));
+}
+} // namespace android
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp
new file mode 100644
index 0000000..dfbe4d6
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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 "hwc2on1adapter/MiniFence.h"
+
+#include <unistd.h>
+
+namespace android {
+
+const sp<MiniFence> MiniFence::NO_FENCE = sp<MiniFence>(new MiniFence);
+
+MiniFence::MiniFence() :
+    mFenceFd(-1) {
+}
+
+MiniFence::MiniFence(int fenceFd) :
+    mFenceFd(fenceFd) {
+}
+
+MiniFence::~MiniFence() {
+    if (mFenceFd != -1) {
+        close(mFenceFd);
+    }
+}
+
+int MiniFence::dup() const {
+    return ::dup(mFenceFd);
+}
+}
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
new file mode 100644
index 0000000..3badfce
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
@@ -0,0 +1,738 @@
+/*
+ * Copyright 2015 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_SF_HWC2_ON_1_ADAPTER_H
+#define ANDROID_SF_HWC2_ON_1_ADAPTER_H
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "MiniFence.h"
+
+#include <atomic>
+#include <map>
+#include <mutex>
+#include <queue>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+struct hwc_composer_device_1;
+struct hwc_display_contents_1;
+struct hwc_layer_1;
+
+namespace android {
+
+// For devices unable to provide an implementation of HWC2 (see hwcomposer2.h),
+// we provide an adapter able to talk to HWC1 (see hwcomposer.h). It translates
+// streamed function calls ala HWC2 model to batched array of structs calls ala
+// HWC1 model.
+class HWC2On1Adapter : public hwc2_device_t
+{
+public:
+    explicit HWC2On1Adapter(struct hwc_composer_device_1* hwc1Device);
+    ~HWC2On1Adapter();
+
+    struct hwc_composer_device_1* getHwc1Device() const { return mHwc1Device; }
+    uint8_t getHwc1MinorVersion() const { return mHwc1MinorVersion; }
+
+private:
+    static inline HWC2On1Adapter* getAdapter(hwc2_device_t* device) {
+        return static_cast<HWC2On1Adapter*>(device);
+    }
+
+    // getCapabilities
+
+    void doGetCapabilities(uint32_t* outCount,
+            int32_t* /*hwc2_capability_t*/ outCapabilities);
+    static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount,
+            int32_t* /*hwc2_capability_t*/ outCapabilities) {
+        getAdapter(device)->doGetCapabilities(outCount, outCapabilities);
+    }
+
+    bool supportsBackgroundColor() {
+        return mHwc1SupportsBackgroundColor;
+    }
+
+    // getFunction
+
+    hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor);
+    static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device,
+            int32_t intDesc) {
+        auto descriptor = static_cast<HWC2::FunctionDescriptor>(intDesc);
+        return getAdapter(device)->doGetFunction(descriptor);
+    }
+
+    // Device functions
+
+    HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height,
+            hwc2_display_t* outDisplay);
+    static int32_t createVirtualDisplayHook(hwc2_device_t* device,
+            uint32_t width, uint32_t height, int32_t* /*format*/,
+            hwc2_display_t* outDisplay) {
+        // HWC1 implementations cannot override the buffer format requested by
+        // the consumer
+        auto error = getAdapter(device)->createVirtualDisplay(width, height,
+                outDisplay);
+        return static_cast<int32_t>(error);
+    }
+
+    HWC2::Error destroyVirtualDisplay(hwc2_display_t display);
+    static int32_t destroyVirtualDisplayHook(hwc2_device_t* device,
+            hwc2_display_t display) {
+        auto error = getAdapter(device)->destroyVirtualDisplay(display);
+        return static_cast<int32_t>(error);
+    }
+
+    std::string mDumpString;
+    void dump(uint32_t* outSize, char* outBuffer);
+    static void dumpHook(hwc2_device_t* device, uint32_t* outSize,
+            char* outBuffer) {
+        getAdapter(device)->dump(outSize, outBuffer);
+    }
+
+    uint32_t getMaxVirtualDisplayCount();
+    static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) {
+        return getAdapter(device)->getMaxVirtualDisplayCount();
+    }
+
+    HWC2::Error registerCallback(HWC2::Callback descriptor,
+            hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer);
+    static int32_t registerCallbackHook(hwc2_device_t* device,
+            int32_t intDesc, hwc2_callback_data_t callbackData,
+            hwc2_function_pointer_t pointer) {
+        auto descriptor = static_cast<HWC2::Callback>(intDesc);
+        auto error = getAdapter(device)->registerCallback(descriptor,
+                callbackData, pointer);
+        return static_cast<int32_t>(error);
+    }
+
+    // Display functions
+
+    class Layer;
+
+    class SortLayersByZ {
+        public:
+            bool operator()(const std::shared_ptr<Layer>& lhs,
+                    const std::shared_ptr<Layer>& rhs);
+    };
+
+    // The semantics of the fences returned by the device differ between
+    // hwc1.set() and hwc2.present(). Read hwcomposer.h and hwcomposer2.h
+    // for more information.
+    //
+    // Release fences in hwc1 are obtained on set() for a frame n and signaled
+    // when the layer buffer is not needed for read operations anymore
+    // (typically on frame n+1). In HWC2, release fences are obtained with a
+    // special call after present() for frame n. These fences signal
+    // on frame n: More specifically, the fence for a given buffer provided in
+    // frame n will signal when the prior buffer is no longer required.
+    //
+    // A retire fence (HWC1) is signaled when a composition is replaced
+    // on the panel whereas a present fence (HWC2) is signaled when a
+    // composition starts to be displayed on a panel.
+    //
+    // The HWC2to1Adapter emulates the new fence semantics for a frame
+    // n by returning the fence from frame n-1. For frame 0, the adapter
+    // returns NO_FENCE.
+    class DeferredFence {
+        public:
+            DeferredFence()
+              : mFences({MiniFence::NO_FENCE, MiniFence::NO_FENCE}) {}
+
+            void add(int32_t fenceFd) {
+                mFences.emplace(new MiniFence(fenceFd));
+                mFences.pop();
+            }
+
+            const sp<MiniFence>& get() const {
+                return mFences.front();
+            }
+
+        private:
+            // There are always two fences in this queue.
+            std::queue<sp<MiniFence>> mFences;
+    };
+
+    class FencedBuffer {
+        public:
+            FencedBuffer() : mBuffer(nullptr), mFence(MiniFence::NO_FENCE) {}
+
+            void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; }
+            void setFence(int fenceFd) { mFence = new MiniFence(fenceFd); }
+
+            buffer_handle_t getBuffer() const { return mBuffer; }
+            int getFence() const { return mFence->dup(); }
+
+        private:
+            buffer_handle_t mBuffer;
+            sp<MiniFence> mFence;
+    };
+
+    class Display {
+        public:
+            Display(HWC2On1Adapter& device, HWC2::DisplayType type);
+
+            hwc2_display_t getId() const { return mId; }
+            HWC2On1Adapter& getDevice() const { return mDevice; }
+
+            // Does not require locking because it is set before adding the
+            // Displays to the Adapter's list of displays
+            void setHwc1Id(int32_t id) { mHwc1Id = id; }
+            int32_t getHwc1Id() const { return mHwc1Id; }
+
+            // HWC2 Display functions
+            HWC2::Error acceptChanges();
+            HWC2::Error createLayer(hwc2_layer_t* outLayerId);
+            HWC2::Error destroyLayer(hwc2_layer_t layerId);
+            HWC2::Error getActiveConfig(hwc2_config_t* outConfigId);
+            HWC2::Error getAttribute(hwc2_config_t configId,
+                    HWC2::Attribute attribute, int32_t* outValue);
+            HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements,
+                    hwc2_layer_t* outLayers, int32_t* outTypes);
+            HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes);
+            HWC2::Error getConfigs(uint32_t* outNumConfigs,
+                    hwc2_config_t* outConfigIds);
+            HWC2::Error getDozeSupport(int32_t* outSupport);
+            HWC2::Error getHdrCapabilities(uint32_t* outNumTypes,
+                    int32_t* outTypes, float* outMaxLuminance,
+                    float* outMaxAverageLuminance, float* outMinLuminance);
+            HWC2::Error getName(uint32_t* outSize, char* outName);
+            HWC2::Error getReleaseFences(uint32_t* outNumElements,
+                    hwc2_layer_t* outLayers, int32_t* outFences);
+            HWC2::Error getRequests(int32_t* outDisplayRequests,
+                    uint32_t* outNumElements, hwc2_layer_t* outLayers,
+                    int32_t* outLayerRequests);
+            HWC2::Error getType(int32_t* outType);
+
+            // Since HWC1 "presents" (called "set" in HWC1) all Displays
+            // at once, the first call to any Display::present will trigger
+            // present() on all Displays in the Device. Subsequent calls without
+            // first calling validate() are noop (except for duping/returning
+            // the retire fence).
+            HWC2::Error present(int32_t* outRetireFence);
+
+            HWC2::Error setActiveConfig(hwc2_config_t configId);
+            HWC2::Error setClientTarget(buffer_handle_t target,
+                    int32_t acquireFence, int32_t dataspace,
+                    hwc_region_t damage);
+            HWC2::Error setColorMode(android_color_mode_t mode);
+            HWC2::Error setColorTransform(android_color_transform_t hint);
+            HWC2::Error setOutputBuffer(buffer_handle_t buffer,
+                    int32_t releaseFence);
+            HWC2::Error setPowerMode(HWC2::PowerMode mode);
+            HWC2::Error setVsyncEnabled(HWC2::Vsync enabled);
+
+            // Since HWC1 "validates" (called "prepare" in HWC1) all Displays
+            // at once, the first call to any Display::validate() will trigger
+            // validate() on all other Displays in the Device.
+            HWC2::Error validate(uint32_t* outNumTypes,
+                    uint32_t* outNumRequests);
+
+            HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
+
+            HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height,
+                     int32_t format, int32_t dataspace);
+
+            // Read configs from HWC1 device
+            void populateConfigs();
+
+            // Set configs for a virtual display
+            void populateConfigs(uint32_t width, uint32_t height);
+
+            bool prepare();
+
+            // Called after hwc.prepare() with responses from the device.
+            void generateChanges();
+
+            bool hasChanges() const;
+            HWC2::Error set(hwc_display_contents_1& hwcContents);
+            void addRetireFence(int fenceFd);
+            void addReleaseFences(const hwc_display_contents_1& hwcContents);
+
+            bool hasColorTransform() const;
+
+            std::string dump() const;
+
+            // Return a rect from the pool allocated during validate()
+            hwc_rect_t* GetRects(size_t numRects);
+
+            hwc_display_contents_1* getDisplayContents();
+
+            void markGeometryChanged() { mGeometryChanged = true; }
+            void resetGeometryMarker() { mGeometryChanged = false;}
+        private:
+            class Config {
+                public:
+                    Config(Display& display)
+                      : mDisplay(display),
+                        mId(0),
+                        mAttributes() {}
+
+                    bool isOnDisplay(const Display& display) const {
+                        return display.getId() == mDisplay.getId();
+                    }
+
+                    void setAttribute(HWC2::Attribute attribute, int32_t value);
+                    int32_t getAttribute(HWC2::Attribute attribute) const;
+
+                    void setHwc1Id(uint32_t id);
+                    bool hasHwc1Id(uint32_t id) const;
+                    HWC2::Error getColorModeForHwc1Id(uint32_t id,
+                            android_color_mode_t *outMode) const;
+                    HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode,
+                            uint32_t* outId) const;
+
+                    void setId(hwc2_config_t id) { mId = id; }
+                    hwc2_config_t getId() const { return mId; }
+
+                    // Attempts to merge two configs that differ only in color
+                    // mode. Returns whether the merge was successful
+                    bool merge(const Config& other);
+
+                    std::set<android_color_mode_t> getColorModes() const;
+
+                    // splitLine divides the output into two lines suitable for
+                    // dumpsys SurfaceFlinger
+                    std::string toString(bool splitLine = false) const;
+
+                private:
+                    Display& mDisplay;
+                    hwc2_config_t mId;
+                    std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
+
+                    // Maps from color transform to HWC1 config ID
+                    std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids;
+            };
+
+            // Stores changes requested from the device upon calling prepare().
+            // Handles change request to:
+            //   - Layer composition type.
+            //   - Layer hints.
+            class Changes {
+                public:
+                    uint32_t getNumTypes() const {
+                        return static_cast<uint32_t>(mTypeChanges.size());
+                    }
+
+                    uint32_t getNumLayerRequests() const {
+                        return static_cast<uint32_t>(mLayerRequests.size());
+                    }
+
+                    const std::unordered_map<hwc2_layer_t, HWC2::Composition>&
+                            getTypeChanges() const {
+                        return mTypeChanges;
+                    }
+
+                    const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>&
+                            getLayerRequests() const {
+                        return mLayerRequests;
+                    }
+
+                    void addTypeChange(hwc2_layer_t layerId,
+                            HWC2::Composition type) {
+                        mTypeChanges.insert({layerId, type});
+                    }
+
+                    void clearTypeChanges() { mTypeChanges.clear(); }
+
+                    void addLayerRequest(hwc2_layer_t layerId,
+                            HWC2::LayerRequest request) {
+                        mLayerRequests.insert({layerId, request});
+                    }
+
+                private:
+                    std::unordered_map<hwc2_layer_t, HWC2::Composition>
+                            mTypeChanges;
+                    std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>
+                            mLayerRequests;
+            };
+
+            std::shared_ptr<const Config>
+                    getConfig(hwc2_config_t configId) const;
+
+            void populateColorModes();
+            void initializeActiveConfig();
+
+            // Creates a bi-directional mapping between index in HWC1
+            // prepare/set array and Layer object. Stores mapping in
+            // mHwc1LayerMap and also updates Layer's attribute mHwc1Id.
+            void assignHwc1LayerIds();
+
+            // Called after a response to prepare() has been received:
+            // Ingest composition type changes requested by the device.
+            void updateTypeChanges(const struct hwc_layer_1& hwc1Layer,
+                    const Layer& layer);
+
+            // Called after a response to prepare() has been received:
+            // Ingest layer hint changes requested by the device.
+            void updateLayerRequests(const struct hwc_layer_1& hwc1Layer,
+                    const Layer& layer);
+
+            // Set all fields in HWC1 comm array for layer containing the
+            // HWC_FRAMEBUFFER_TARGET (always the last layer).
+            void prepareFramebufferTarget();
+
+            // Display ID generator.
+            static std::atomic<hwc2_display_t> sNextId;
+            const hwc2_display_t mId;
+
+
+            HWC2On1Adapter& mDevice;
+
+            // The state of this display should only be modified from
+            // SurfaceFlinger's main loop, with the exception of when dump is
+            // called. To prevent a bad state from crashing us during a dump
+            // call, all public calls into Display must acquire this mutex.
+            //
+            // It is recursive because we don't want to deadlock in validate
+            // (or present) when we call HWC2On1Adapter::prepareAllDisplays
+            // (or setAllDisplays), which calls back into Display functions
+            // which require locking.
+            mutable std::recursive_mutex mStateMutex;
+
+            // Allocate RAM able to store all layers and rects used for
+            // communication with HWC1. Place allocated RAM in variable
+            // mHwc1RequestedContents.
+            void allocateRequestedContents();
+
+            // Array of structs exchanged between client and hwc1 device.
+            // Sent to device upon calling prepare().
+            std::unique_ptr<hwc_display_contents_1> mHwc1RequestedContents;
+    private:
+            DeferredFence mRetireFence;
+
+            // Will only be non-null after the Display has been validated and
+            // before it has been presented
+            std::unique_ptr<Changes> mChanges;
+
+            int32_t mHwc1Id;
+
+            std::vector<std::shared_ptr<Config>> mConfigs;
+            std::shared_ptr<const Config> mActiveConfig;
+            std::set<android_color_mode_t> mColorModes;
+            android_color_mode_t mActiveColorMode;
+            std::string mName;
+            HWC2::DisplayType mType;
+            HWC2::PowerMode mPowerMode;
+            HWC2::Vsync mVsyncEnabled;
+
+            // Used to populate HWC1 HWC_FRAMEBUFFER_TARGET layer
+            FencedBuffer mClientTarget;
+
+
+            FencedBuffer mOutputBuffer;
+
+            bool mHasColorTransform;
+
+            // All layers this Display is aware of.
+            std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers;
+
+            // Mapping between layer index in array of hwc_display_contents_1*
+            // passed to HWC1 during validate/set and Layer object.
+            std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap;
+
+            // All communication with HWC1 via prepare/set is done with one
+            // alloc. This pointer is pointing to a pool of hwc_rect_t.
+            size_t mNumAvailableRects;
+            hwc_rect_t* mNextAvailableRect;
+
+            // True if any of the Layers contained in this Display have been
+            // updated with anything other than a buffer since last call to
+            // Display::set()
+            bool mGeometryChanged;
+    };
+
+    // Utility template calling a Display object method directly based on the
+    // hwc2_display_t displayId parameter.
+    template <typename ...Args>
+    static int32_t callDisplayFunction(hwc2_device_t* device,
+            hwc2_display_t displayId, HWC2::Error (Display::*member)(Args...),
+            Args... args) {
+        auto display = getAdapter(device)->getDisplay(displayId);
+        if (!display) {
+            return static_cast<int32_t>(HWC2::Error::BadDisplay);
+        }
+        auto error = ((*display).*member)(std::forward<Args>(args)...);
+        return static_cast<int32_t>(error);
+    }
+
+    template <typename MF, MF memFunc, typename ...Args>
+    static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId,
+            Args... args) {
+        return HWC2On1Adapter::callDisplayFunction(device, displayId, memFunc,
+                std::forward<Args>(args)...);
+    }
+
+    static int32_t getDisplayAttributeHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_config_t config,
+            int32_t intAttribute, int32_t* outValue) {
+        auto attribute = static_cast<HWC2::Attribute>(intAttribute);
+        return callDisplayFunction(device, display, &Display::getAttribute,
+                config, attribute, outValue);
+    }
+
+    static int32_t setColorTransformHook(hwc2_device_t* device,
+            hwc2_display_t display, const float* /*matrix*/,
+            int32_t /*android_color_transform_t*/ intHint) {
+        // We intentionally throw away the matrix, because if the hint is
+        // anything other than IDENTITY, we have to fall back to client
+        // composition anyway
+        auto hint = static_cast<android_color_transform_t>(intHint);
+        return callDisplayFunction(device, display, &Display::setColorTransform,
+                hint);
+    }
+
+    static int32_t setColorModeHook(hwc2_device_t* device,
+            hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) {
+        auto mode = static_cast<android_color_mode_t>(intMode);
+        return callDisplayFunction(device, display, &Display::setColorMode,
+                mode);
+    }
+
+    static int32_t setPowerModeHook(hwc2_device_t* device,
+            hwc2_display_t display, int32_t intMode) {
+        auto mode = static_cast<HWC2::PowerMode>(intMode);
+        return callDisplayFunction(device, display, &Display::setPowerMode,
+                mode);
+    }
+
+    static int32_t setVsyncEnabledHook(hwc2_device_t* device,
+            hwc2_display_t display, int32_t intEnabled) {
+        auto enabled = static_cast<HWC2::Vsync>(intEnabled);
+        return callDisplayFunction(device, display, &Display::setVsyncEnabled,
+                enabled);
+    }
+
+    class Layer {
+        public:
+            explicit Layer(Display& display);
+
+            bool operator==(const Layer& other) { return mId == other.mId; }
+            bool operator!=(const Layer& other) { return !(*this == other); }
+
+            hwc2_layer_t getId() const { return mId; }
+            Display& getDisplay() const { return mDisplay; }
+
+            // HWC2 Layer functions
+            HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence);
+            HWC2::Error setCursorPosition(int32_t x, int32_t y);
+            HWC2::Error setSurfaceDamage(hwc_region_t damage);
+
+            // HWC2 Layer state functions
+            HWC2::Error setBlendMode(HWC2::BlendMode mode);
+            HWC2::Error setColor(hwc_color_t color);
+            HWC2::Error setCompositionType(HWC2::Composition type);
+            HWC2::Error setDataspace(android_dataspace_t dataspace);
+            HWC2::Error setDisplayFrame(hwc_rect_t frame);
+            HWC2::Error setPlaneAlpha(float alpha);
+            HWC2::Error setSidebandStream(const native_handle_t* stream);
+            HWC2::Error setSourceCrop(hwc_frect_t crop);
+            HWC2::Error setTransform(HWC2::Transform transform);
+            HWC2::Error setVisibleRegion(hwc_region_t visible);
+            HWC2::Error setZ(uint32_t z);
+
+            HWC2::Composition getCompositionType() const {
+                return mCompositionType;
+            }
+            uint32_t getZ() const { return mZ; }
+
+            void addReleaseFence(int fenceFd);
+            const sp<MiniFence>& getReleaseFence() const;
+
+            void setHwc1Id(size_t id) { mHwc1Id = id; }
+            size_t getHwc1Id() const { return mHwc1Id; }
+
+            // Write state to HWC1 communication struct.
+            void applyState(struct hwc_layer_1& hwc1Layer);
+
+            std::string dump() const;
+
+            std::size_t getNumVisibleRegions() { return mVisibleRegion.size(); }
+
+            std::size_t getNumSurfaceDamages() { return mSurfaceDamage.size(); }
+
+            // True if a layer cannot be properly rendered by the device due
+            // to usage of SolidColor (a.k.a BackgroundColor in HWC1).
+            bool hasUnsupportedBackgroundColor() {
+                return (mCompositionType == HWC2::Composition::SolidColor &&
+                        !mDisplay.getDevice().supportsBackgroundColor());
+            }
+        private:
+            void applyCommonState(struct hwc_layer_1& hwc1Layer);
+            void applySolidColorState(struct hwc_layer_1& hwc1Layer);
+            void applySidebandState(struct hwc_layer_1& hwc1Layer);
+            void applyBufferState(struct hwc_layer_1& hwc1Layer);
+            void applyCompositionType(struct hwc_layer_1& hwc1Layer);
+
+            static std::atomic<hwc2_layer_t> sNextId;
+            const hwc2_layer_t mId;
+            Display& mDisplay;
+
+            FencedBuffer mBuffer;
+            std::vector<hwc_rect_t> mSurfaceDamage;
+
+            HWC2::BlendMode mBlendMode;
+            hwc_color_t mColor;
+            HWC2::Composition mCompositionType;
+            hwc_rect_t mDisplayFrame;
+            float mPlaneAlpha;
+            const native_handle_t* mSidebandStream;
+            hwc_frect_t mSourceCrop;
+            HWC2::Transform mTransform;
+            std::vector<hwc_rect_t> mVisibleRegion;
+
+            uint32_t mZ;
+
+            DeferredFence mReleaseFence;
+
+            size_t mHwc1Id;
+            bool mHasUnsupportedPlaneAlpha;
+    };
+
+    // Utility tempate calling a Layer object method based on ID parameters:
+    // hwc2_display_t displayId
+    // and
+    // hwc2_layer_t layerId
+    template <typename ...Args>
+    static int32_t callLayerFunction(hwc2_device_t* device,
+            hwc2_display_t displayId, hwc2_layer_t layerId,
+            HWC2::Error (Layer::*member)(Args...), Args... args) {
+        auto result = getAdapter(device)->getLayer(displayId, layerId);
+        auto error = std::get<HWC2::Error>(result);
+        if (error == HWC2::Error::None) {
+            auto layer = std::get<Layer*>(result);
+            error = ((*layer).*member)(std::forward<Args>(args)...);
+        }
+        return static_cast<int32_t>(error);
+    }
+
+    template <typename MF, MF memFunc, typename ...Args>
+    static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId,
+            hwc2_layer_t layerId, Args... args) {
+        return HWC2On1Adapter::callLayerFunction(device, displayId, layerId,
+                memFunc, std::forward<Args>(args)...);
+    }
+
+    // Layer state functions
+
+    static int32_t setLayerBlendModeHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intMode) {
+        auto mode = static_cast<HWC2::BlendMode>(intMode);
+        return callLayerFunction(device, display, layer,
+                &Layer::setBlendMode, mode);
+    }
+
+    static int32_t setLayerCompositionTypeHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intType) {
+        auto type = static_cast<HWC2::Composition>(intType);
+        return callLayerFunction(device, display, layer,
+                &Layer::setCompositionType, type);
+    }
+
+    static int32_t setLayerDataspaceHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intDataspace) {
+        auto dataspace = static_cast<android_dataspace_t>(intDataspace);
+        return callLayerFunction(device, display, layer, &Layer::setDataspace,
+                dataspace);
+    }
+
+    static int32_t setLayerTransformHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intTransform) {
+        auto transform = static_cast<HWC2::Transform>(intTransform);
+        return callLayerFunction(device, display, layer, &Layer::setTransform,
+                transform);
+    }
+
+    static int32_t setLayerZOrderHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, uint32_t z) {
+        return callDisplayFunction(device, display, &Display::updateLayerZ,
+                layer, z);
+    }
+
+    // Adapter internals
+
+    void populateCapabilities();
+    Display* getDisplay(hwc2_display_t id);
+    std::tuple<Layer*, HWC2::Error> getLayer(hwc2_display_t displayId,
+            hwc2_layer_t layerId);
+    void populatePrimary();
+
+    bool prepareAllDisplays();
+    std::vector<struct hwc_display_contents_1*> mHwc1Contents;
+    HWC2::Error setAllDisplays();
+
+    // Callbacks
+    void hwc1Invalidate();
+    void hwc1Vsync(int hwc1DisplayId, int64_t timestamp);
+    void hwc1Hotplug(int hwc1DisplayId, int connected);
+
+    // These are set in the constructor and before any asynchronous events are
+    // possible
+
+    struct hwc_composer_device_1* const mHwc1Device;
+    const uint8_t mHwc1MinorVersion;
+    bool mHwc1SupportsVirtualDisplays;
+    bool mHwc1SupportsBackgroundColor;
+
+    class Callbacks;
+    const std::unique_ptr<Callbacks> mHwc1Callbacks;
+
+    std::unordered_set<HWC2::Capability> mCapabilities;
+
+    // These are only accessed from the main SurfaceFlinger thread (not from
+    // callbacks or dump
+
+    std::map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers;
+
+    // A HWC1 supports only one virtual display.
+    std::shared_ptr<Display> mHwc1VirtualDisplay;
+
+    // These are potentially accessed from multiple threads, and are protected
+    // by this mutex. This needs to be recursive, since the HWC1 implementation
+    // can call back into the invalidate callback on the same thread that is
+    // calling prepare.
+    std::recursive_timed_mutex mStateMutex;
+
+    struct CallbackInfo {
+        hwc2_callback_data_t data;
+        hwc2_function_pointer_t pointer;
+    };
+    std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks;
+    bool mHasPendingInvalidate;
+
+    // There is a small gap between the time the HWC1 module is started and
+    // when the callbacks for vsync and hotplugs are registered by the
+    // HWC2on1Adapter. To prevent losing events they are stored in these arrays
+    // and fed to the callback as soon as possible.
+    std::vector<std::pair<int, int64_t>> mPendingVsyncs;
+    std::vector<std::pair<int, int>> mPendingHotplugs;
+
+    // Mapping between HWC1 display id and Display objects.
+    std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays;
+
+    // Map HWC1 display type (HWC_DISPLAY_PRIMARY, HWC_DISPLAY_EXTERNAL,
+    // HWC_DISPLAY_VIRTUAL) to Display IDs generated by HWC2on1Adapter objects.
+    std::unordered_map<int, hwc2_display_t> mHwc1DisplayMap;
+};
+
+} // namespace android
+
+#endif
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h
new file mode 100644
index 0000000..75de764
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MINIFENCE_H
+#define MINIFENCE_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+/* MiniFence is a minimal re-implementation of Fence from libui. It exists to
+ * avoid linking the HWC2on1Adapter to libui and satisfy Treble requirements.
+ */
+class MiniFence : public LightRefBase<MiniFence> {
+public:
+    static const sp<MiniFence> NO_FENCE;
+
+    // Construct a new MiniFence object with an invalid file descriptor.
+    MiniFence();
+
+    // Construct a new MiniFence object to manage a given fence file descriptor.
+    // When the new MiniFence object is destructed the file descriptor will be
+    // closed.
+    explicit MiniFence(int fenceFd);
+
+    // Not copyable or movable.
+    MiniFence(const MiniFence& rhs) = delete;
+    MiniFence& operator=(const MiniFence& rhs) = delete;
+    MiniFence(MiniFence&& rhs) = delete;
+    MiniFence& operator=(MiniFence&& rhs) = delete;
+
+    // Return a duplicate of the fence file descriptor. The caller is
+    // responsible for closing the returned file descriptor. On error, -1 will
+    // be returned and errno will indicate the problem.
+    int dup() const;
+
+private:
+    // Only allow instantiation using ref counting.
+    friend class LightRefBase<MiniFence>;
+    ~MiniFence();
+
+    int mFenceFd;
+
+};
+}
+#endif //MINIFENCE_H
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp b/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp
new file mode 100644
index 0000000..73a41f7
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp
@@ -0,0 +1,33 @@
+// Copyright 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+    name: "libhwc2onfbadapter",
+    vendor: true,
+
+    clang: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+
+    srcs: [
+        "HWC2OnFbAdapter.cpp",
+    ],
+
+    header_libs: ["libhardware_headers"],
+    shared_libs: ["liblog", "libsync"],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp b/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp
new file mode 100644
index 0000000..7c9e651
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp
@@ -0,0 +1,887 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "HWC2OnFbAdapter"
+
+//#define LOG_NDEBUG 0
+
+#include "hwc2onfbadapter/HWC2OnFbAdapter.h"
+
+#include <algorithm>
+#include <type_traits>
+
+#include <inttypes.h>
+#include <time.h>
+#include <sys/prctl.h>
+#include <unistd.h> // for close
+
+#include <hardware/fb.h>
+#include <log/log.h>
+#include <sync/sync.h>
+
+namespace android {
+
+namespace {
+
+void dumpHook(hwc2_device_t* device, uint32_t* outSize, char* outBuffer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (outBuffer) {
+        *outSize = adapter.getDebugString().copy(outBuffer, *outSize);
+    } else {
+        adapter.updateDebugString();
+        *outSize = adapter.getDebugString().size();
+    }
+}
+
+int32_t registerCallbackHook(hwc2_device_t* device, int32_t descriptor,
+                             hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    switch (descriptor) {
+        case HWC2_CALLBACK_HOTPLUG:
+            if (pointer) {
+                reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer)(callbackData, adapter.getDisplayId(),
+                                                            HWC2_CONNECTION_CONNECTED);
+            }
+            break;
+        case HWC2_CALLBACK_REFRESH:
+            break;
+        case HWC2_CALLBACK_VSYNC:
+            adapter.setVsyncCallback(reinterpret_cast<HWC2_PFN_VSYNC>(pointer), callbackData);
+            break;
+        default:
+            return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* /*device*/) {
+    return 0;
+}
+
+int32_t createVirtualDisplayHook(hwc2_device_t* /*device*/, uint32_t /*width*/, uint32_t /*height*/,
+                                 int32_t* /*format*/, hwc2_display_t* /*outDisplay*/) {
+    return HWC2_ERROR_NO_RESOURCES;
+}
+
+int32_t destroyVirtualDisplayHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/) {
+    return HWC2_ERROR_BAD_DISPLAY;
+}
+
+int32_t setOutputBufferHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/,
+                            buffer_handle_t /*buffer*/, int32_t /*releaseFence*/) {
+    return HWC2_ERROR_BAD_DISPLAY;
+}
+
+int32_t getDisplayNameHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outSize,
+                           char* outName) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    const auto& info = adapter.getInfo();
+    if (outName) {
+        *outSize = info.name.copy(outName, *outSize);
+    } else {
+        *outSize = info.name.size();
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayTypeHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outType) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outType = HWC2_DISPLAY_TYPE_PHYSICAL;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDozeSupportHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outSupport) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outSupport = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getHdrCapabilitiesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+                               int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+                               float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outNumTypes = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setPowerModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t /*mode*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    // pretend that it works
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setVsyncEnabledHook(hwc2_device_t* device, hwc2_display_t display, int32_t enabled) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    adapter.enableVsync(enabled == HWC2_VSYNC_ENABLE);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getColorModesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumModes,
+                          int32_t* outModes) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    if (outModes) {
+        if (*outNumModes > 0) {
+            outModes[0] = HAL_COLOR_MODE_NATIVE;
+            *outNumModes = 1;
+        }
+    } else {
+        *outNumModes = 1;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setColorModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t mode) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (mode != HAL_COLOR_MODE_NATIVE) {
+        return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setColorTransformHook(hwc2_device_t* device, hwc2_display_t display,
+                              const float* /*matrix*/, int32_t /*hint*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    // we always force client composition
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getClientTargetSupportHook(hwc2_device_t* device, hwc2_display_t display, uint32_t width,
+                                   uint32_t height, int32_t format, int32_t dataspace) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (dataspace != HAL_DATASPACE_UNKNOWN) {
+        return HWC2_ERROR_UNSUPPORTED;
+    }
+
+    const auto& info = adapter.getInfo();
+    return (info.width == width && info.height == height && info.format == format)
+            ? HWC2_ERROR_NONE
+            : HWC2_ERROR_UNSUPPORTED;
+}
+
+int32_t setClientTargetHook(hwc2_device_t* device, hwc2_display_t display, buffer_handle_t target,
+                            int32_t acquireFence, int32_t dataspace, hwc_region_t /*damage*/) {
+    if (acquireFence >= 0) {
+        sync_wait(acquireFence, -1);
+        close(acquireFence);
+    }
+
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (dataspace != HAL_DATASPACE_UNKNOWN) {
+        return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    // no state change
+    adapter.setBuffer(target);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayConfigsHook(hwc2_device_t* device, hwc2_display_t display,
+                              uint32_t* outNumConfigs, hwc2_config_t* outConfigs) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    if (outConfigs) {
+        if (*outNumConfigs > 0) {
+            outConfigs[0] = adapter.getConfigId();
+            *outNumConfigs = 1;
+        }
+    } else {
+        *outNumConfigs = 1;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayAttributeHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config,
+                                int32_t attribute, int32_t* outValue) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getConfigId() != config) {
+        return HWC2_ERROR_BAD_CONFIG;
+    }
+
+    const auto& info = adapter.getInfo();
+    switch (attribute) {
+        case HWC2_ATTRIBUTE_WIDTH:
+            *outValue = int32_t(info.width);
+            break;
+        case HWC2_ATTRIBUTE_HEIGHT:
+            *outValue = int32_t(info.height);
+            break;
+        case HWC2_ATTRIBUTE_VSYNC_PERIOD:
+            *outValue = int32_t(info.vsync_period_ns);
+            break;
+        case HWC2_ATTRIBUTE_DPI_X:
+            *outValue = int32_t(info.xdpi_scaled);
+            break;
+        case HWC2_ATTRIBUTE_DPI_Y:
+            *outValue = int32_t(info.ydpi_scaled);
+            break;
+        default:
+            return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getActiveConfigHook(hwc2_device_t* device, hwc2_display_t display,
+                            hwc2_config_t* outConfig) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outConfig = adapter.getConfigId();
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setActiveConfigHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getConfigId() != config) {
+        return HWC2_ERROR_BAD_CONFIG;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t validateDisplayHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+                            uint32_t* outNumRequests) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    const auto& dirtyLayers = adapter.getDirtyLayers();
+    *outNumTypes = dirtyLayers.size();
+    *outNumRequests = 0;
+
+    if (*outNumTypes > 0) {
+        adapter.setState(HWC2OnFbAdapter::State::VALIDATED_WITH_CHANGES);
+        return HWC2_ERROR_HAS_CHANGES;
+    } else {
+        adapter.setState(HWC2OnFbAdapter::State::VALIDATED);
+        return HWC2_ERROR_NONE;
+    }
+}
+
+int32_t getChangedCompositionTypesHook(hwc2_device_t* device, hwc2_display_t display,
+                                       uint32_t* outNumElements, hwc2_layer_t* outLayers,
+                                       int32_t* outTypes) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    // request client composition for all layers
+    const auto& dirtyLayers = adapter.getDirtyLayers();
+    if (outLayers && outTypes) {
+        *outNumElements = std::min(*outNumElements, uint32_t(dirtyLayers.size()));
+        auto iter = dirtyLayers.cbegin();
+        for (uint32_t i = 0; i < *outNumElements; i++) {
+            outLayers[i] = *iter++;
+            outTypes[i] = HWC2_COMPOSITION_CLIENT;
+        }
+    } else {
+        *outNumElements = dirtyLayers.size();
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayRequestsHook(hwc2_device_t* device, hwc2_display_t display,
+                               int32_t* outDisplayRequests, uint32_t* outNumElements,
+                               hwc2_layer_t* /*outLayers*/, int32_t* /*outLayerRequests*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    *outDisplayRequests = 0;
+    *outNumElements = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t acceptDisplayChangesHook(hwc2_device_t* device, hwc2_display_t display) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    adapter.clearDirtyLayers();
+    adapter.setState(HWC2OnFbAdapter::State::VALIDATED);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t presentDisplayHook(hwc2_device_t* device, hwc2_display_t display,
+                           int32_t* outPresentFence) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() != HWC2OnFbAdapter::State::VALIDATED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    adapter.postBuffer();
+    *outPresentFence = -1;
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getReleaseFencesHook(hwc2_device_t* device, hwc2_display_t display,
+                             uint32_t* outNumElements, hwc2_layer_t* /*outLayers*/,
+                             int32_t* /*outFences*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outNumElements = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t createLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t* outLayer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outLayer = adapter.addLayer();
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t destroyLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    if (adapter.removeLayer(layer)) {
+        adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+        return HWC2_ERROR_NONE;
+    } else {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+}
+
+int32_t setCursorPositionHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t /*layer*/,
+                              int32_t /*x*/, int32_t /*y*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    // always an error
+    return HWC2_ERROR_BAD_LAYER;
+}
+
+int32_t setLayerBufferHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+                           buffer_handle_t /*buffer*/, int32_t acquireFence) {
+    if (acquireFence >= 0) {
+        sync_wait(acquireFence, -1);
+        close(acquireFence);
+    }
+
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.hasLayer(layer)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    // no state change
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setLayerSurfaceDamageHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+                                  hwc_region_t /*damage*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.hasLayer(layer)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    // no state change
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setLayerCompositionTypeHook(hwc2_device_t* device, hwc2_display_t display,
+                                    hwc2_layer_t layer, int32_t type) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.markLayerDirty(layer, type != HWC2_COMPOSITION_CLIENT)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+template <typename... Args>
+int32_t setLayerStateHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+                          Args... /*args*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.hasLayer(layer)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function) {
+    static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+    return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+hwc2_function_pointer_t getFunctionHook(hwc2_device_t* /*device*/, int32_t descriptor) {
+    switch (descriptor) {
+        // global functions
+        case HWC2_FUNCTION_DUMP:
+            return asFP<HWC2_PFN_DUMP>(dumpHook);
+        case HWC2_FUNCTION_REGISTER_CALLBACK:
+            return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+        // virtual display functions
+        case HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT:
+            return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(getMaxVirtualDisplayCountHook);
+        case HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY:
+            return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(createVirtualDisplayHook);
+        case HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY:
+            return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(destroyVirtualDisplayHook);
+        case HWC2_FUNCTION_SET_OUTPUT_BUFFER:
+            return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(setOutputBufferHook);
+
+        // display functions
+        case HWC2_FUNCTION_GET_DISPLAY_NAME:
+            return asFP<HWC2_PFN_GET_DISPLAY_NAME>(getDisplayNameHook);
+        case HWC2_FUNCTION_GET_DISPLAY_TYPE:
+            return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(getDisplayTypeHook);
+        case HWC2_FUNCTION_GET_DOZE_SUPPORT:
+            return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(getDozeSupportHook);
+        case HWC2_FUNCTION_GET_HDR_CAPABILITIES:
+            return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(getHdrCapabilitiesHook);
+        case HWC2_FUNCTION_SET_POWER_MODE:
+            return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook);
+        case HWC2_FUNCTION_SET_VSYNC_ENABLED:
+            return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook);
+        case HWC2_FUNCTION_GET_COLOR_MODES:
+            return asFP<HWC2_PFN_GET_COLOR_MODES>(getColorModesHook);
+        case HWC2_FUNCTION_SET_COLOR_MODE:
+            return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
+        case HWC2_FUNCTION_SET_COLOR_TRANSFORM:
+            return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
+        case HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT:
+            return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(getClientTargetSupportHook);
+        case HWC2_FUNCTION_SET_CLIENT_TARGET:
+            return asFP<HWC2_PFN_SET_CLIENT_TARGET>(setClientTargetHook);
+
+        // config functions
+        case HWC2_FUNCTION_GET_DISPLAY_CONFIGS:
+            return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(getDisplayConfigsHook);
+        case HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE:
+            return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(getDisplayAttributeHook);
+        case HWC2_FUNCTION_GET_ACTIVE_CONFIG:
+            return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(getActiveConfigHook);
+        case HWC2_FUNCTION_SET_ACTIVE_CONFIG:
+            return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(setActiveConfigHook);
+
+        // validate/present functions
+        case HWC2_FUNCTION_VALIDATE_DISPLAY:
+            return asFP<HWC2_PFN_VALIDATE_DISPLAY>(validateDisplayHook);
+        case HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES:
+            return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(getChangedCompositionTypesHook);
+        case HWC2_FUNCTION_GET_DISPLAY_REQUESTS:
+            return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(getDisplayRequestsHook);
+        case HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES:
+            return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(acceptDisplayChangesHook);
+        case HWC2_FUNCTION_PRESENT_DISPLAY:
+            return asFP<HWC2_PFN_PRESENT_DISPLAY>(presentDisplayHook);
+        case HWC2_FUNCTION_GET_RELEASE_FENCES:
+            return asFP<HWC2_PFN_GET_RELEASE_FENCES>(getReleaseFencesHook);
+
+        // layer create/destroy
+        case HWC2_FUNCTION_CREATE_LAYER:
+            return asFP<HWC2_PFN_CREATE_LAYER>(createLayerHook);
+        case HWC2_FUNCTION_DESTROY_LAYER:
+            return asFP<HWC2_PFN_DESTROY_LAYER>(destroyLayerHook);
+
+        // layer functions; validateDisplay not required
+        case HWC2_FUNCTION_SET_CURSOR_POSITION:
+            return asFP<HWC2_PFN_SET_CURSOR_POSITION>(setCursorPositionHook);
+        case HWC2_FUNCTION_SET_LAYER_BUFFER:
+            return asFP<HWC2_PFN_SET_LAYER_BUFFER>(setLayerBufferHook);
+        case HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE:
+            return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(setLayerSurfaceDamageHook);
+
+        // layer state functions; validateDisplay required
+        case HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE:
+            return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(setLayerCompositionTypeHook);
+        case HWC2_FUNCTION_SET_LAYER_BLEND_MODE:
+            return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(setLayerStateHook<int32_t>);
+        case HWC2_FUNCTION_SET_LAYER_COLOR:
+            return asFP<HWC2_PFN_SET_LAYER_COLOR>(setLayerStateHook<hwc_color_t>);
+        case HWC2_FUNCTION_SET_LAYER_DATASPACE:
+            return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerStateHook<int32_t>);
+        case HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME:
+            return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(setLayerStateHook<hwc_rect_t>);
+        case HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA:
+            return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(setLayerStateHook<float>);
+        case HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM:
+            return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(setLayerStateHook<buffer_handle_t>);
+        case HWC2_FUNCTION_SET_LAYER_SOURCE_CROP:
+            return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(setLayerStateHook<hwc_frect_t>);
+        case HWC2_FUNCTION_SET_LAYER_TRANSFORM:
+            return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerStateHook<int32_t>);
+        case HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION:
+            return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(setLayerStateHook<hwc_region_t>);
+        case HWC2_FUNCTION_SET_LAYER_Z_ORDER:
+            return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerStateHook<uint32_t>);
+
+        default:
+            ALOGE("unknown function descriptor %d", descriptor);
+            return nullptr;
+    }
+}
+
+void getCapabilitiesHook(hwc2_device_t* /*device*/, uint32_t* outCount,
+                         int32_t* /*outCapabilities*/) {
+    *outCount = 0;
+}
+
+int closeHook(hw_device_t* device) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    adapter.close();
+    return 0;
+}
+
+} // anonymous namespace
+
+HWC2OnFbAdapter::HWC2OnFbAdapter(framebuffer_device_t* fbDevice)
+      : hwc2_device_t(), mFbDevice(fbDevice) {
+    common.close = closeHook;
+    hwc2_device::getCapabilities = getCapabilitiesHook;
+    hwc2_device::getFunction = getFunctionHook;
+
+    mFbInfo.name = "fbdev";
+    mFbInfo.width = mFbDevice->width;
+    mFbInfo.height = mFbDevice->height;
+    mFbInfo.format = mFbDevice->format;
+    mFbInfo.vsync_period_ns = int(1e9 / mFbDevice->fps);
+    mFbInfo.xdpi_scaled = int(mFbDevice->xdpi * 1000.0f);
+    mFbInfo.ydpi_scaled = int(mFbDevice->ydpi * 1000.0f);
+
+    mVsyncThread.start(0, mFbInfo.vsync_period_ns);
+}
+
+HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hw_device_t* device) {
+    return *reinterpret_cast<HWC2OnFbAdapter*>(device);
+}
+
+HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hwc2_device_t* device) {
+    return *reinterpret_cast<HWC2OnFbAdapter*>(device);
+}
+
+hwc2_display_t HWC2OnFbAdapter::getDisplayId() {
+    return 0;
+}
+
+hwc2_config_t HWC2OnFbAdapter::getConfigId() {
+    return 0;
+}
+
+void HWC2OnFbAdapter::close() {
+    mVsyncThread.stop();
+    framebuffer_close(mFbDevice);
+}
+
+const HWC2OnFbAdapter::Info& HWC2OnFbAdapter::getInfo() const {
+    return mFbInfo;
+}
+
+void HWC2OnFbAdapter::updateDebugString() {
+    if (mFbDevice->common.version >= 1 && mFbDevice->dump) {
+        char buffer[4096];
+        mFbDevice->dump(mFbDevice, buffer, sizeof(buffer));
+        buffer[sizeof(buffer) - 1] = '\0';
+
+        mDebugString = buffer;
+    }
+}
+
+const std::string& HWC2OnFbAdapter::getDebugString() const {
+    return mDebugString;
+}
+
+void HWC2OnFbAdapter::setState(State state) {
+    mState = state;
+}
+
+HWC2OnFbAdapter::State HWC2OnFbAdapter::getState() const {
+    return mState;
+}
+
+hwc2_layer_t HWC2OnFbAdapter::addLayer() {
+    hwc2_layer_t id = ++mNextLayerId;
+
+    mLayers.insert(id);
+    mDirtyLayers.insert(id);
+
+    return id;
+}
+
+bool HWC2OnFbAdapter::removeLayer(hwc2_layer_t layer) {
+    mDirtyLayers.erase(layer);
+    return mLayers.erase(layer);
+}
+
+bool HWC2OnFbAdapter::hasLayer(hwc2_layer_t layer) const {
+    return mLayers.count(layer) > 0;
+}
+
+bool HWC2OnFbAdapter::markLayerDirty(hwc2_layer_t layer, bool dirty) {
+    if (mLayers.count(layer) == 0) {
+        return false;
+    }
+
+    if (dirty) {
+        mDirtyLayers.insert(layer);
+    } else {
+        mDirtyLayers.erase(layer);
+    }
+
+    return true;
+}
+
+const std::unordered_set<hwc2_layer_t>& HWC2OnFbAdapter::getDirtyLayers() const {
+    return mDirtyLayers;
+}
+
+void HWC2OnFbAdapter::clearDirtyLayers() {
+    mDirtyLayers.clear();
+}
+
+/*
+ * For each frame, SurfaceFlinger
+ *
+ *  - peforms GLES composition
+ *  - calls eglSwapBuffers
+ *  - calls setClientTarget, which maps to setBuffer below
+ *  - calls presentDisplay, which maps to postBuffer below
+ *
+ * setBuffer should be a good place to call compositionComplete.
+ *
+ * As for post, it
+ *
+ *  - schedules the buffer for presentation on the next vsync
+ *  - locks the buffer and blocks all other users trying to lock it
+ *
+ * It does not give us a way to return a present fence, and we need to live
+ * with that.  The implication is that, when we are double-buffered,
+ * SurfaceFlinger assumes the front buffer is available for rendering again
+ * immediately after the back buffer is posted.  The locking semantics
+ * hopefully are strong enough that the rendering will be blocked.
+ */
+void HWC2OnFbAdapter::setBuffer(buffer_handle_t buffer) {
+    if (mFbDevice->compositionComplete) {
+        mFbDevice->compositionComplete(mFbDevice);
+    }
+    mBuffer = buffer;
+}
+
+bool HWC2OnFbAdapter::postBuffer() {
+    int error = 0;
+    if (mBuffer) {
+        error = mFbDevice->post(mFbDevice, mBuffer);
+    }
+
+    return error == 0;
+}
+
+void HWC2OnFbAdapter::setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) {
+    mVsyncThread.setCallback(callback, data);
+}
+
+void HWC2OnFbAdapter::enableVsync(bool enable) {
+    mVsyncThread.enableCallback(enable);
+}
+
+int64_t HWC2OnFbAdapter::VsyncThread::now() {
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+
+    return int64_t(ts.tv_sec) * 1'000'000'000 + ts.tv_nsec;
+}
+
+bool HWC2OnFbAdapter::VsyncThread::sleepUntil(int64_t t) {
+    struct timespec ts;
+    ts.tv_sec = t / 1'000'000'000;
+    ts.tv_nsec = t % 1'000'000'000;
+
+    while (true) {
+        int error = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr);
+        if (error) {
+            if (error == EINTR) {
+                continue;
+            }
+            return false;
+        } else {
+            return true;
+        }
+    }
+}
+
+void HWC2OnFbAdapter::VsyncThread::start(int64_t firstVsync, int64_t period) {
+    mNextVsync = firstVsync;
+    mPeriod = period;
+    mStarted = true;
+    mThread = std::thread(&VsyncThread::vsyncLoop, this);
+}
+
+void HWC2OnFbAdapter::VsyncThread::stop() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mStarted = false;
+    }
+    mCondition.notify_all();
+    mThread.join();
+}
+
+void HWC2OnFbAdapter::VsyncThread::setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mCallback = callback;
+    mCallbackData = data;
+}
+
+void HWC2OnFbAdapter::VsyncThread::enableCallback(bool enable) {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mCallbackEnabled = enable;
+    }
+    mCondition.notify_all();
+}
+
+void HWC2OnFbAdapter::VsyncThread::vsyncLoop() {
+    prctl(PR_SET_NAME, "VsyncThread", 0, 0, 0);
+
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (!mStarted) {
+        return;
+    }
+
+    while (true) {
+        if (!mCallbackEnabled) {
+            mCondition.wait(lock, [this] { return mCallbackEnabled || !mStarted; });
+            if (!mStarted) {
+                break;
+            }
+        }
+
+        lock.unlock();
+
+        // adjust mNextVsync if necessary
+        int64_t t = now();
+        if (mNextVsync < t) {
+            int64_t n = (t - mNextVsync + mPeriod - 1) / mPeriod;
+            mNextVsync += mPeriod * n;
+        }
+        bool fire = sleepUntil(mNextVsync);
+
+        lock.lock();
+
+        if (fire) {
+            ALOGV("VsyncThread(%" PRId64 ")", mNextVsync);
+            if (mCallback) {
+                mCallback(mCallbackData, getDisplayId(), mNextVsync);
+            }
+            mNextVsync += mPeriod;
+        }
+    }
+}
+
+} // namespace android
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h b/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h
new file mode 100644
index 0000000..d6272fd
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_HWC2_ON_FB_ADAPTER_H
+#define ANDROID_SF_HWC2_ON_FB_ADAPTER_H
+
+#include <condition_variable>
+#include <mutex>
+#include <string>
+#include <thread>
+#include <unordered_set>
+
+#include <hardware/hwcomposer2.h>
+
+struct framebuffer_device_t;
+
+namespace android {
+
+class HWC2OnFbAdapter : public hwc2_device_t {
+public:
+    HWC2OnFbAdapter(framebuffer_device_t* fbDevice);
+
+    static HWC2OnFbAdapter& cast(hw_device_t* device);
+    static HWC2OnFbAdapter& cast(hwc2_device_t* device);
+
+    static hwc2_display_t getDisplayId();
+    static hwc2_config_t getConfigId();
+
+    void close();
+
+    struct Info {
+        std::string name;
+        uint32_t width;
+        uint32_t height;
+        int format;
+        int vsync_period_ns;
+        int xdpi_scaled;
+        int ydpi_scaled;
+    };
+    const Info& getInfo() const;
+
+    void updateDebugString();
+    const std::string& getDebugString() const;
+
+    enum class State {
+        MODIFIED,
+        VALIDATED_WITH_CHANGES,
+        VALIDATED,
+    };
+    void setState(State state);
+    State getState() const;
+
+    hwc2_layer_t addLayer();
+    bool removeLayer(hwc2_layer_t layer);
+    bool hasLayer(hwc2_layer_t layer) const;
+    bool markLayerDirty(hwc2_layer_t layer, bool dirty);
+    const std::unordered_set<hwc2_layer_t>& getDirtyLayers() const;
+    void clearDirtyLayers();
+
+    void setBuffer(buffer_handle_t buffer);
+    bool postBuffer();
+
+    void setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data);
+    void enableVsync(bool enable);
+
+private:
+    framebuffer_device_t* mFbDevice{nullptr};
+    Info mFbInfo{};
+
+    std::string mDebugString;
+
+    State mState{State::MODIFIED};
+
+    uint64_t mNextLayerId{0};
+    std::unordered_set<hwc2_layer_t> mLayers;
+    std::unordered_set<hwc2_layer_t> mDirtyLayers;
+
+    buffer_handle_t mBuffer{nullptr};
+
+    class VsyncThread {
+    public:
+        static int64_t now();
+        static bool sleepUntil(int64_t t);
+
+        void start(int64_t first, int64_t period);
+        void stop();
+        void setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data);
+        void enableCallback(bool enable);
+
+    private:
+        void vsyncLoop();
+        bool waitUntilNextVsync();
+
+        std::thread mThread;
+        int64_t mNextVsync{0};
+        int64_t mPeriod{0};
+
+        std::mutex mMutex;
+        std::condition_variable mCondition;
+        bool mStarted{false};
+        HWC2_PFN_VSYNC mCallback{nullptr};
+        hwc2_callback_data_t mCallbackData{nullptr};
+        bool mCallbackEnabled{false};
+    };
+    VsyncThread mVsyncThread;
+};
+
+} // namespace android
+
+#endif // ANDROID_SF_HWC2_ON_FB_ADAPTER_H
diff --git a/graphics/composer/2.1/utils/passthrough/Android.bp b/graphics/composer/2.1/utils/passthrough/Android.bp
new file mode 100644
index 0000000..4d3c976
--- /dev/null
+++ b/graphics/composer/2.1/utils/passthrough/Android.bp
@@ -0,0 +1,22 @@
+cc_library_headers {
+    name: "android.hardware.graphics.composer@2.1-passthrough",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    shared_libs: [
+        "libhardware",
+        "libhwc2on1adapter",
+        "libhwc2onfbadapter",
+    ],
+    export_shared_lib_headers: [
+        "libhardware",
+        "libhwc2on1adapter",
+        "libhwc2onfbadapter",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-hal",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-hal",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
new file mode 100644
index 0000000..964e75b
--- /dev/null
+++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
@@ -0,0 +1,670 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "HwcHal.h included without LOG_TAG"
+#endif
+
+#include <atomic>
+#include <cstring>  // for strerror
+#include <type_traits>
+#include <unordered_set>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace passthrough {
+
+namespace detail {
+
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::ColorTransform;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Hdr;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::common::V1_0::Transform;
+
+// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
+template <typename Hal>
+class HwcHalImpl : public Hal {
+   public:
+    virtual ~HwcHalImpl() {
+        if (mDevice) {
+            hwc2_close(mDevice);
+        }
+    }
+
+    bool initWithModule(const hw_module_t* module) {
+        hwc2_device_t* device;
+        int result = hwc2_open(module, &device);
+        if (result) {
+            ALOGE("failed to open hwcomposer2 device: %s", strerror(-result));
+            return false;
+        }
+
+        return initWithDevice(std::move(device), true);
+    }
+
+    bool initWithDevice(hwc2_device_t* device, bool requireReliablePresentFence) {
+        // we own the device from this point on
+        mDevice = device;
+
+        initCapabilities();
+        if (requireReliablePresentFence &&
+            hasCapability(HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE)) {
+            ALOGE("present fence must be reliable");
+            mDevice->common.close(&mDevice->common);
+            mDevice = nullptr;
+            return false;
+        }
+
+        if (!initDispatch()) {
+            mDevice->common.close(&mDevice->common);
+            mDevice = nullptr;
+            return false;
+        }
+
+        return true;
+    }
+
+    bool hasCapability(hwc2_capability_t capability) override {
+        return (mCapabilities.count(capability) > 0);
+    }
+
+    std::string dumpDebugInfo() override {
+        uint32_t len = 0;
+        mDispatch.dump(mDevice, &len, nullptr);
+
+        std::vector<char> buf(len + 1);
+        mDispatch.dump(mDevice, &len, buf.data());
+        buf.resize(len + 1);
+        buf[len] = '\0';
+
+        return buf.data();
+    }
+
+    void registerEventCallback(hal::ComposerHal::EventCallback* callback) override {
+        mMustValidateDisplay = true;
+        mEventCallback = callback;
+
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
+    }
+
+    void unregisterEventCallback() override {
+        // we assume the callback functions
+        //
+        //  - can be unregistered
+        //  - can be in-flight
+        //  - will never be called afterward
+        //
+        // which is likely incorrect
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, nullptr);
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, nullptr);
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, nullptr);
+
+        mEventCallback = nullptr;
+    }
+
+    uint32_t getMaxVirtualDisplayCount() override {
+        return mDispatch.getMaxVirtualDisplayCount(mDevice);
+    }
+
+    Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
+                               Display* outDisplay) override {
+        int32_t hwc_format = static_cast<int32_t>(*format);
+        int32_t err =
+            mDispatch.createVirtualDisplay(mDevice, width, height, &hwc_format, outDisplay);
+        *format = static_cast<PixelFormat>(hwc_format);
+
+        return static_cast<Error>(err);
+    }
+
+    Error destroyVirtualDisplay(Display display) override {
+        int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display);
+        return static_cast<Error>(err);
+    }
+
+    Error createLayer(Display display, Layer* outLayer) override {
+        int32_t err = mDispatch.createLayer(mDevice, display, outLayer);
+        return static_cast<Error>(err);
+    }
+
+    Error destroyLayer(Display display, Layer layer) override {
+        int32_t err = mDispatch.destroyLayer(mDevice, display, layer);
+        return static_cast<Error>(err);
+    }
+
+    Error getActiveConfig(Display display, Config* outConfig) override {
+        int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig);
+        return static_cast<Error>(err);
+    }
+
+    Error getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                 PixelFormat format, Dataspace dataspace) override {
+        int32_t err = mDispatch.getClientTargetSupport(mDevice, display, width, height,
+                                                       static_cast<int32_t>(format),
+                                                       static_cast<int32_t>(dataspace));
+        return static_cast<Error>(err);
+    }
+
+    Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) override {
+        uint32_t count = 0;
+        int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        outModes->resize(count);
+        err = mDispatch.getColorModes(
+            mDevice, display, &count,
+            reinterpret_cast<std::underlying_type<ColorMode>::type*>(outModes->data()));
+        if (err != HWC2_ERROR_NONE) {
+            *outModes = hidl_vec<ColorMode>();
+            return static_cast<Error>(err);
+        }
+
+        return Error::NONE;
+    }
+
+    Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute,
+                              int32_t* outValue) override {
+        int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config,
+                                                    static_cast<int32_t>(attribute), outValue);
+        return static_cast<Error>(err);
+    }
+
+    Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) override {
+        uint32_t count = 0;
+        int32_t err = mDispatch.getDisplayConfigs(mDevice, display, &count, nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        outConfigs->resize(count);
+        err = mDispatch.getDisplayConfigs(mDevice, display, &count, outConfigs->data());
+        if (err != HWC2_ERROR_NONE) {
+            *outConfigs = hidl_vec<Config>();
+            return static_cast<Error>(err);
+        }
+
+        return Error::NONE;
+    }
+
+    Error getDisplayName(Display display, hidl_string* outName) override {
+        uint32_t count = 0;
+        int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        std::vector<char> buf(count + 1);
+        err = mDispatch.getDisplayName(mDevice, display, &count, buf.data());
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+        buf.resize(count + 1);
+        buf[count] = '\0';
+
+        *outName = buf.data();
+
+        return Error::NONE;
+    }
+
+    Error getDisplayType(Display display, IComposerClient::DisplayType* outType) override {
+        int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID;
+        int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type);
+        *outType = static_cast<IComposerClient::DisplayType>(hwc_type);
+
+        return static_cast<Error>(err);
+    }
+
+    Error getDozeSupport(Display display, bool* outSupport) override {
+        int32_t hwc_support = 0;
+        int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support);
+        *outSupport = hwc_support;
+
+        return static_cast<Error>(err);
+    }
+
+    Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes, float* outMaxLuminance,
+                             float* outMaxAverageLuminance, float* outMinLuminance) override {
+        uint32_t count = 0;
+        int32_t err =
+            mDispatch.getHdrCapabilities(mDevice, display, &count, nullptr, outMaxLuminance,
+                                         outMaxAverageLuminance, outMinLuminance);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        outTypes->resize(count);
+        err = mDispatch.getHdrCapabilities(
+            mDevice, display, &count,
+            reinterpret_cast<std::underlying_type<Hdr>::type*>(outTypes->data()), outMaxLuminance,
+            outMaxAverageLuminance, outMinLuminance);
+        if (err != HWC2_ERROR_NONE) {
+            *outTypes = hidl_vec<Hdr>();
+            return static_cast<Error>(err);
+        }
+
+        return Error::NONE;
+    }
+
+    Error setActiveConfig(Display display, Config config) override {
+        int32_t err = mDispatch.setActiveConfig(mDevice, display, config);
+        return static_cast<Error>(err);
+    }
+
+    Error setColorMode(Display display, ColorMode mode) override {
+        int32_t err = mDispatch.setColorMode(mDevice, display, static_cast<int32_t>(mode));
+        return static_cast<Error>(err);
+    }
+
+    Error setPowerMode(Display display, IComposerClient::PowerMode mode) override {
+        int32_t err = mDispatch.setPowerMode(mDevice, display, static_cast<int32_t>(mode));
+        return static_cast<Error>(err);
+    }
+
+    Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override {
+        int32_t err = mDispatch.setVsyncEnabled(mDevice, display, static_cast<int32_t>(enabled));
+        return static_cast<Error>(err);
+    }
+
+    Error setColorTransform(Display display, const float* matrix, int32_t hint) override {
+        int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint);
+        return static_cast<Error>(err);
+    }
+
+    Error setClientTarget(Display display, buffer_handle_t target, int32_t acquireFence,
+                          int32_t dataspace, const std::vector<hwc_rect_t>& damage) override {
+        hwc_region region = {damage.size(), damage.data()};
+        int32_t err =
+            mDispatch.setClientTarget(mDevice, display, target, acquireFence, dataspace, region);
+        return static_cast<Error>(err);
+    }
+
+    Error setOutputBuffer(Display display, buffer_handle_t buffer, int32_t releaseFence) override {
+        int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer, releaseFence);
+        // unlike in setClientTarget, releaseFence is owned by us
+        if (err == HWC2_ERROR_NONE && releaseFence >= 0) {
+            close(releaseFence);
+        }
+
+        return static_cast<Error>(err);
+    }
+
+    Error validateDisplay(Display display, std::vector<Layer>* outChangedLayers,
+                          std::vector<IComposerClient::Composition>* outCompositionTypes,
+                          uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers,
+                          std::vector<uint32_t>* outRequestMasks) override {
+        uint32_t typesCount = 0;
+        uint32_t reqsCount = 0;
+        int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount);
+        mMustValidateDisplay = false;
+
+        if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
+            return static_cast<Error>(err);
+        }
+
+        err = mDispatch.getChangedCompositionTypes(mDevice, display, &typesCount, nullptr, nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        std::vector<Layer> changedLayers(typesCount);
+        std::vector<IComposerClient::Composition> compositionTypes(typesCount);
+        err = mDispatch.getChangedCompositionTypes(
+            mDevice, display, &typesCount, changedLayers.data(),
+            reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>(
+                compositionTypes.data()));
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        int32_t displayReqs = 0;
+        err = mDispatch.getDisplayRequests(mDevice, display, &displayReqs, &reqsCount, nullptr,
+                                           nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        std::vector<Layer> requestedLayers(reqsCount);
+        std::vector<uint32_t> requestMasks(reqsCount);
+        err = mDispatch.getDisplayRequests(mDevice, display, &displayReqs, &reqsCount,
+                                           requestedLayers.data(),
+                                           reinterpret_cast<int32_t*>(requestMasks.data()));
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        *outChangedLayers = std::move(changedLayers);
+        *outCompositionTypes = std::move(compositionTypes);
+        *outDisplayRequestMask = displayReqs;
+        *outRequestedLayers = std::move(requestedLayers);
+        *outRequestMasks = std::move(requestMasks);
+
+        return static_cast<Error>(err);
+    }
+
+    Error acceptDisplayChanges(Display display) override {
+        int32_t err = mDispatch.acceptDisplayChanges(mDevice, display);
+        return static_cast<Error>(err);
+    }
+
+    Error presentDisplay(Display display, int32_t* outPresentFence, std::vector<Layer>* outLayers,
+                         std::vector<int32_t>* outReleaseFences) override {
+        if (mMustValidateDisplay) {
+            return Error::NOT_VALIDATED;
+        }
+
+        *outPresentFence = -1;
+        int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        uint32_t count = 0;
+        err = mDispatch.getReleaseFences(mDevice, display, &count, nullptr, nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            ALOGW("failed to get release fences");
+            return Error::NONE;
+        }
+
+        outLayers->resize(count);
+        outReleaseFences->resize(count);
+        err = mDispatch.getReleaseFences(mDevice, display, &count, outLayers->data(),
+                                         outReleaseFences->data());
+        if (err != HWC2_ERROR_NONE) {
+            ALOGW("failed to get release fences");
+            outLayers->clear();
+            outReleaseFences->clear();
+            return Error::NONE;
+        }
+
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerCursorPosition(Display display, Layer layer, int32_t x, int32_t y) override {
+        int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer,
+                         int32_t acquireFence) override {
+        int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer, buffer, acquireFence);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerSurfaceDamage(Display display, Layer layer,
+                                const std::vector<hwc_rect_t>& damage) override {
+        hwc_region region = {damage.size(), damage.data()};
+        int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer, region);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerBlendMode(Display display, Layer layer, int32_t mode) override {
+        int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerColor(Display display, Layer layer, IComposerClient::Color color) override {
+        hwc_color_t hwc_color{color.r, color.g, color.b, color.a};
+        int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerCompositionType(Display display, Layer layer, int32_t type) override {
+        int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer, type);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerDataspace(Display display, Layer layer, int32_t dataspace) override {
+        int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer, dataspace);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerDisplayFrame(Display display, Layer layer, const hwc_rect_t& frame) override {
+        int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer, frame);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) override {
+        int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer, alpha);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerSidebandStream(Display display, Layer layer, buffer_handle_t stream) override {
+        int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer, stream);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerSourceCrop(Display display, Layer layer, const hwc_frect_t& crop) override {
+        int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerTransform(Display display, Layer layer, int32_t transform) override {
+        int32_t err = mDispatch.setLayerTransform(mDevice, display, layer, transform);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerVisibleRegion(Display display, Layer layer,
+                                const std::vector<hwc_rect_t>& visible) override {
+        hwc_region_t region = {visible.size(), visible.data()};
+        int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer, region);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerZOrder(Display display, Layer layer, uint32_t z) override {
+        int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z);
+        return static_cast<Error>(err);
+    }
+
+   protected:
+    virtual void initCapabilities() {
+        uint32_t count = 0;
+        mDevice->getCapabilities(mDevice, &count, nullptr);
+
+        std::vector<int32_t> caps(count);
+        mDevice->getCapabilities(mDevice, &count, caps.data());
+        caps.resize(count);
+
+        mCapabilities.reserve(count);
+        for (auto cap : caps) {
+            mCapabilities.insert(static_cast<hwc2_capability_t>(cap));
+        }
+    }
+
+    template <typename T>
+    bool initDispatch(hwc2_function_descriptor_t desc, T* outPfn) {
+        auto pfn = mDevice->getFunction(mDevice, desc);
+        if (pfn) {
+            *outPfn = reinterpret_cast<T>(pfn);
+            return true;
+        } else {
+            ALOGE("failed to get hwcomposer2 function %d", desc);
+            return false;
+        }
+    }
+
+    virtual bool initDispatch() {
+        if (!initDispatch(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, &mDispatch.acceptDisplayChanges) ||
+            !initDispatch(HWC2_FUNCTION_CREATE_LAYER, &mDispatch.createLayer) ||
+            !initDispatch(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY, &mDispatch.createVirtualDisplay) ||
+            !initDispatch(HWC2_FUNCTION_DESTROY_LAYER, &mDispatch.destroyLayer) ||
+            !initDispatch(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
+                          &mDispatch.destroyVirtualDisplay) ||
+            !initDispatch(HWC2_FUNCTION_DUMP, &mDispatch.dump) ||
+            !initDispatch(HWC2_FUNCTION_GET_ACTIVE_CONFIG, &mDispatch.getActiveConfig) ||
+            !initDispatch(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
+                          &mDispatch.getChangedCompositionTypes) ||
+            !initDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
+                          &mDispatch.getClientTargetSupport) ||
+            !initDispatch(HWC2_FUNCTION_GET_COLOR_MODES, &mDispatch.getColorModes) ||
+            !initDispatch(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE, &mDispatch.getDisplayAttribute) ||
+            !initDispatch(HWC2_FUNCTION_GET_DISPLAY_CONFIGS, &mDispatch.getDisplayConfigs) ||
+            !initDispatch(HWC2_FUNCTION_GET_DISPLAY_NAME, &mDispatch.getDisplayName) ||
+            !initDispatch(HWC2_FUNCTION_GET_DISPLAY_REQUESTS, &mDispatch.getDisplayRequests) ||
+            !initDispatch(HWC2_FUNCTION_GET_DISPLAY_TYPE, &mDispatch.getDisplayType) ||
+            !initDispatch(HWC2_FUNCTION_GET_DOZE_SUPPORT, &mDispatch.getDozeSupport) ||
+            !initDispatch(HWC2_FUNCTION_GET_HDR_CAPABILITIES, &mDispatch.getHdrCapabilities) ||
+            !initDispatch(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
+                          &mDispatch.getMaxVirtualDisplayCount) ||
+            !initDispatch(HWC2_FUNCTION_GET_RELEASE_FENCES, &mDispatch.getReleaseFences) ||
+            !initDispatch(HWC2_FUNCTION_PRESENT_DISPLAY, &mDispatch.presentDisplay) ||
+            !initDispatch(HWC2_FUNCTION_REGISTER_CALLBACK, &mDispatch.registerCallback) ||
+            !initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG, &mDispatch.setActiveConfig) ||
+            !initDispatch(HWC2_FUNCTION_SET_CLIENT_TARGET, &mDispatch.setClientTarget) ||
+            !initDispatch(HWC2_FUNCTION_SET_COLOR_MODE, &mDispatch.setColorMode) ||
+            !initDispatch(HWC2_FUNCTION_SET_COLOR_TRANSFORM, &mDispatch.setColorTransform) ||
+            !initDispatch(HWC2_FUNCTION_SET_CURSOR_POSITION, &mDispatch.setCursorPosition) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_BLEND_MODE, &mDispatch.setLayerBlendMode) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_BUFFER, &mDispatch.setLayerBuffer) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_COLOR, &mDispatch.setLayerColor) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
+                          &mDispatch.setLayerCompositionType) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_DATASPACE, &mDispatch.setLayerDataspace) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME, &mDispatch.setLayerDisplayFrame) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA, &mDispatch.setLayerPlaneAlpha)) {
+            return false;
+        }
+
+        if (hasCapability(HWC2_CAPABILITY_SIDEBAND_STREAM)) {
+            if (!initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM,
+                              &mDispatch.setLayerSidebandStream)) {
+                return false;
+            }
+        }
+
+        if (!initDispatch(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP, &mDispatch.setLayerSourceCrop) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
+                          &mDispatch.setLayerSurfaceDamage) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_TRANSFORM, &mDispatch.setLayerTransform) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
+                          &mDispatch.setLayerVisibleRegion) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_Z_ORDER, &mDispatch.setLayerZOrder) ||
+            !initDispatch(HWC2_FUNCTION_SET_OUTPUT_BUFFER, &mDispatch.setOutputBuffer) ||
+            !initDispatch(HWC2_FUNCTION_SET_POWER_MODE, &mDispatch.setPowerMode) ||
+            !initDispatch(HWC2_FUNCTION_SET_VSYNC_ENABLED, &mDispatch.setVsyncEnabled) ||
+            !initDispatch(HWC2_FUNCTION_VALIDATE_DISPLAY, &mDispatch.validateDisplay)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                            int32_t connected) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        hal->mEventCallback->onHotplug(display,
+                                       static_cast<IComposerCallback::Connection>(connected));
+    }
+
+    static void refreshHook(hwc2_callback_data_t callbackData, hwc2_display_t display) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        hal->mMustValidateDisplay = true;
+        hal->mEventCallback->onRefresh(display);
+    }
+
+    static void vsyncHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                          int64_t timestamp) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        hal->mEventCallback->onVsync(display, timestamp);
+    }
+
+    hwc2_device_t* mDevice = nullptr;
+
+    std::unordered_set<hwc2_capability_t> mCapabilities;
+
+    struct {
+        HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges;
+        HWC2_PFN_CREATE_LAYER createLayer;
+        HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay;
+        HWC2_PFN_DESTROY_LAYER destroyLayer;
+        HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay;
+        HWC2_PFN_DUMP dump;
+        HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig;
+        HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes;
+        HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport;
+        HWC2_PFN_GET_COLOR_MODES getColorModes;
+        HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute;
+        HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs;
+        HWC2_PFN_GET_DISPLAY_NAME getDisplayName;
+        HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests;
+        HWC2_PFN_GET_DISPLAY_TYPE getDisplayType;
+        HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport;
+        HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities;
+        HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount;
+        HWC2_PFN_GET_RELEASE_FENCES getReleaseFences;
+        HWC2_PFN_PRESENT_DISPLAY presentDisplay;
+        HWC2_PFN_REGISTER_CALLBACK registerCallback;
+        HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig;
+        HWC2_PFN_SET_CLIENT_TARGET setClientTarget;
+        HWC2_PFN_SET_COLOR_MODE setColorMode;
+        HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform;
+        HWC2_PFN_SET_CURSOR_POSITION setCursorPosition;
+        HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode;
+        HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer;
+        HWC2_PFN_SET_LAYER_COLOR setLayerColor;
+        HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType;
+        HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace;
+        HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame;
+        HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha;
+        HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream;
+        HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop;
+        HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage;
+        HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform;
+        HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion;
+        HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder;
+        HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer;
+        HWC2_PFN_SET_POWER_MODE setPowerMode;
+        HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled;
+        HWC2_PFN_VALIDATE_DISPLAY validateDisplay;
+    } mDispatch = {};
+
+    hal::ComposerHal::EventCallback* mEventCallback = nullptr;
+
+    std::atomic<bool> mMustValidateDisplay{true};
+};
+
+}  // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+}  // namespace passthrough
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h
new file mode 100644
index 0000000..33c914d
--- /dev/null
+++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "HwcLoader.h included without LOG_TAG"
+#endif
+
+#include <memory>
+
+#include <composer-hal/2.1/Composer.h>
+#include <composer-passthrough/2.1/HwcHal.h>
+#include <hardware/fb.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer2.h>
+#include <hwc2on1adapter/HWC2On1Adapter.h>
+#include <hwc2onfbadapter/HWC2OnFbAdapter.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace passthrough {
+
+class HwcLoader {
+   public:
+    static IComposer* load() {
+        const hw_module_t* module = loadModule();
+        if (!module) {
+            return nullptr;
+        }
+
+        auto hal = createHalWithAdapter(module);
+        if (!hal) {
+            return nullptr;
+        }
+
+        return createComposer(std::move(hal));
+    }
+
+    // load hwcomposer2 module
+    static const hw_module_t* loadModule() {
+        const hw_module_t* module;
+        int error = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
+        if (error) {
+            ALOGI("falling back to gralloc module");
+            error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+        }
+
+        if (error) {
+            ALOGE("failed to get hwcomposer or gralloc module");
+            return nullptr;
+        }
+
+        return module;
+    }
+
+    // create a ComposerHal instance
+    static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) {
+        auto hal = std::make_unique<HwcHal>();
+        return hal->initWithModule(module) ? std::move(hal) : nullptr;
+    }
+
+    // create a ComposerHal instance, insert an adapter if necessary
+    static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) {
+        bool adapted;
+        hwc2_device_t* device = openDeviceWithAdapter(module, &adapted);
+        if (!device) {
+            return nullptr;
+        }
+        auto hal = std::make_unique<HwcHal>();
+        return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr;
+    }
+
+    // create an IComposer instance
+    static IComposer* createComposer(std::unique_ptr<hal::ComposerHal> hal) {
+        return hal::Composer::create(std::move(hal)).release();
+    }
+
+   protected:
+    // open hwcomposer2 device, install an adapter if necessary
+    static hwc2_device_t* openDeviceWithAdapter(const hw_module_t* module, bool* outAdapted) {
+        if (module->id && std::string(module->id) == GRALLOC_HARDWARE_MODULE_ID) {
+            *outAdapted = true;
+            return adaptGrallocModule(module);
+        }
+
+        hw_device_t* device;
+        int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
+        if (error) {
+            ALOGE("failed to open hwcomposer device: %s", strerror(-error));
+            return nullptr;
+        }
+
+        int major = (device->version >> 24) & 0xf;
+        if (major != 2) {
+            *outAdapted = true;
+            return adaptHwc1Device(std::move(reinterpret_cast<hwc_composer_device_1*>(device)));
+        }
+
+        *outAdapted = false;
+        return reinterpret_cast<hwc2_device_t*>(device);
+    }
+
+   private:
+    static hwc2_device_t* adaptGrallocModule(const hw_module_t* module) {
+        framebuffer_device_t* device;
+        int error = framebuffer_open(module, &device);
+        if (error) {
+            ALOGE("failed to open framebuffer device: %s", strerror(-error));
+            return nullptr;
+        }
+
+        return new HWC2OnFbAdapter(device);
+    }
+
+    static hwc2_device_t* adaptHwc1Device(hwc_composer_device_1* device) {
+        int minor = (device->common.version >> 16) & 0xf;
+        if (minor < 1) {
+            ALOGE("hwcomposer 1.0 is not supported");
+            device->common.close(&device->common);
+            return nullptr;
+        }
+
+        return new HWC2On1Adapter(device);
+    }
+};
+
+}  // namespace passthrough
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/Android.bp b/graphics/composer/2.1/utils/vts/Android.bp
new file mode 100644
index 0000000..846cfdf
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "android.hardware.graphics.composer@2.1-vts",
+    defaults: ["hidl_defaults"],
+    srcs: [
+        "ComposerVts.cpp",
+        "GraphicsComposerCallback.cpp",
+        "TestCommandReader.cpp",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "android.hardware.graphics.composer@2.1",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+        "-DLOG_TAG=\"ComposerVts\"",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
new file mode 100644
index 0000000..2f531b4
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -0,0 +1,324 @@
+/*
+ * 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 <composer-vts/2.1/ComposerVts.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+Composer::Composer() {
+    mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>();
+    init();
+}
+
+Composer::Composer(const std::string& name) {
+    mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name);
+    init();
+}
+
+void Composer::init() {
+    ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
+
+    std::vector<IComposer::Capability> capabilities = getCapabilities();
+    mCapabilities.insert(capabilities.begin(), capabilities.end());
+}
+
+sp<IComposer> Composer::getRaw() const {
+    return mComposer;
+}
+
+bool Composer::hasCapability(IComposer::Capability capability) const {
+    return mCapabilities.count(capability) > 0;
+}
+
+std::vector<IComposer::Capability> Composer::getCapabilities() {
+    std::vector<IComposer::Capability> capabilities;
+    mComposer->getCapabilities(
+        [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
+
+    return capabilities;
+}
+
+std::string Composer::dumpDebugInfo() {
+    std::string debugInfo;
+    mComposer->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+
+    return debugInfo;
+}
+
+std::unique_ptr<ComposerClient> Composer::createClient() {
+    std::unique_ptr<ComposerClient> client;
+    mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
+        client = std::make_unique<ComposerClient>(tmpClient);
+    });
+
+    return client;
+}
+
+ComposerClient::ComposerClient(const sp<IComposerClient>& client) : mClient(client) {}
+
+ComposerClient::~ComposerClient() {
+    for (auto it : mDisplayResources) {
+        Display display = it.first;
+        DisplayResource& resource = it.second;
+
+        for (auto layer : resource.layers) {
+            EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer))
+                << "failed to destroy layer " << layer;
+        }
+
+        if (resource.isVirtual) {
+            EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display))
+                << "failed to destroy virtual display " << display;
+        }
+    }
+    mDisplayResources.clear();
+}
+
+sp<IComposerClient> ComposerClient::getRaw() const {
+    return mClient;
+}
+
+void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) {
+    mClient->registerCallback(callback);
+}
+
+uint32_t ComposerClient::getMaxVirtualDisplayCount() {
+    return mClient->getMaxVirtualDisplayCount();
+}
+
+Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
+                                             PixelFormat formatHint, uint32_t outputBufferSlotCount,
+                                             PixelFormat* outFormat) {
+    Display display = 0;
+    mClient->createVirtualDisplay(
+        width, height, formatHint, outputBufferSlotCount,
+        [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
+            display = tmpDisplay;
+            *outFormat = tmpFormat;
+
+            ASSERT_TRUE(mDisplayResources.insert({display, DisplayResource(true)}).second)
+                << "duplicated virtual display id " << display;
+        });
+
+    return display;
+}
+
+void ComposerClient::destroyVirtualDisplay(Display display) {
+    Error error = mClient->destroyVirtualDisplay(display);
+    ASSERT_EQ(Error::NONE, error) << "failed to destroy virtual display " << display;
+
+    mDisplayResources.erase(display);
+}
+
+Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) {
+    Layer layer = 0;
+    mClient->createLayer(display, bufferSlotCount, [&](const auto& tmpError, const auto& tmpLayer) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer";
+        layer = tmpLayer;
+
+        auto resourceIt = mDisplayResources.find(display);
+        if (resourceIt == mDisplayResources.end()) {
+            resourceIt = mDisplayResources.insert({display, DisplayResource(false)}).first;
+        }
+
+        ASSERT_TRUE(resourceIt->second.layers.insert(layer).second)
+            << "duplicated layer id " << layer;
+    });
+
+    return layer;
+}
+
+void ComposerClient::destroyLayer(Display display, Layer layer) {
+    Error error = mClient->destroyLayer(display, layer);
+    ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer;
+
+    auto resourceIt = mDisplayResources.find(display);
+    ASSERT_NE(mDisplayResources.end(), resourceIt);
+    resourceIt->second.layers.erase(layer);
+}
+
+Config ComposerClient::getActiveConfig(Display display) {
+    Config config = 0;
+    mClient->getActiveConfig(display, [&](const auto& tmpError, const auto& tmpConfig) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config";
+        config = tmpConfig;
+    });
+
+    return config;
+}
+
+bool ComposerClient::getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                            PixelFormat format, Dataspace dataspace) {
+    Error error = mClient->getClientTargetSupport(display, width, height, format, dataspace);
+    return error == Error::NONE;
+}
+
+std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
+    std::vector<ColorMode> modes;
+    mClient->getColorModes(display, [&](const auto& tmpError, const auto& tmpMode) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode";
+        modes = tmpMode;
+    });
+
+    return modes;
+}
+
+int32_t ComposerClient::getDisplayAttribute(Display display, Config config,
+                                            IComposerClient::Attribute attribute) {
+    int32_t value = 0;
+    mClient->getDisplayAttribute(
+        display, config, attribute, [&](const auto& tmpError, const auto& tmpValue) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get display attribute";
+            value = tmpValue;
+        });
+
+    return value;
+}
+
+std::vector<Config> ComposerClient::getDisplayConfigs(Display display) {
+    std::vector<Config> configs;
+    mClient->getDisplayConfigs(display, [&](const auto& tmpError, const auto& tmpConfigs) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs";
+        configs = tmpConfigs;
+    });
+
+    return configs;
+}
+
+std::string ComposerClient::getDisplayName(Display display) {
+    std::string name;
+    mClient->getDisplayName(display, [&](const auto& tmpError, const auto& tmpName) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name";
+        name = tmpName.c_str();
+    });
+
+    return name;
+}
+
+IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) {
+    IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
+    mClient->getDisplayType(display, [&](const auto& tmpError, const auto& tmpType) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type";
+        type = tmpType;
+    });
+
+    return type;
+}
+
+bool ComposerClient::getDozeSupport(Display display) {
+    bool support = false;
+    mClient->getDozeSupport(display, [&](const auto& tmpError, const auto& tmpSupport) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support";
+        support = tmpSupport;
+    });
+
+    return support;
+}
+
+std::vector<Hdr> ComposerClient::getHdrCapabilities(Display display, float* outMaxLuminance,
+                                                    float* outMaxAverageLuminance,
+                                                    float* outMinLuminance) {
+    std::vector<Hdr> types;
+    mClient->getHdrCapabilities(
+        display, [&](const auto& tmpError, const auto& tmpTypes, const auto& tmpMaxLuminance,
+                     const auto& tmpMaxAverageLuminance, const auto& tmpMinLuminance) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities";
+            types = tmpTypes;
+            *outMaxLuminance = tmpMaxLuminance;
+            *outMaxAverageLuminance = tmpMaxAverageLuminance;
+            *outMinLuminance = tmpMinLuminance;
+        });
+
+    return types;
+}
+
+void ComposerClient::setClientTargetSlotCount(Display display, uint32_t clientTargetSlotCount) {
+    Error error = mClient->setClientTargetSlotCount(display, clientTargetSlotCount);
+    ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count";
+}
+
+void ComposerClient::setActiveConfig(Display display, Config config) {
+    Error error = mClient->setActiveConfig(display, config);
+    ASSERT_EQ(Error::NONE, error) << "failed to set active config";
+}
+
+void ComposerClient::setColorMode(Display display, ColorMode mode) {
+    Error error = mClient->setColorMode(display, mode);
+    ASSERT_EQ(Error::NONE, error) << "failed to set color mode";
+}
+
+void ComposerClient::setPowerMode(Display display, IComposerClient::PowerMode mode) {
+    Error error = mClient->setPowerMode(display, mode);
+    ASSERT_EQ(Error::NONE, error) << "failed to set power mode";
+}
+
+void ComposerClient::setVsyncEnabled(Display display, bool enabled) {
+    IComposerClient::Vsync vsync =
+        (enabled) ? IComposerClient::Vsync::ENABLE : IComposerClient::Vsync::DISABLE;
+    Error error = mClient->setVsyncEnabled(display, vsync);
+    ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode";
+
+    // give the hwbinder thread some time to handle any pending vsync callback
+    if (!enabled) {
+        usleep(5 * 1000);
+    }
+}
+
+void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* writer) {
+    bool queueChanged = false;
+    uint32_t commandLength = 0;
+    hidl_vec<hidl_handle> commandHandles;
+    ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
+
+    if (queueChanged) {
+        auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
+        ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
+        return;
+    }
+
+    mClient->executeCommands(commandLength, commandHandles,
+                             [&](const auto& tmpError, const auto& tmpOutQueueChanged,
+                                 const auto& tmpOutLength, const auto& tmpOutHandles) {
+                                 ASSERT_EQ(Error::NONE, tmpError);
+
+                                 if (tmpOutQueueChanged) {
+                                     mClient->getOutputCommandQueue(
+                                         [&](const auto& tmpError, const auto& tmpDescriptor) {
+                                             ASSERT_EQ(Error::NONE, tmpError);
+                                             reader->setMQDescriptor(tmpDescriptor);
+                                         });
+                                 }
+
+                                 ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
+                                 reader->parse();
+                             });
+}
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
new file mode 100644
index 0000000..1ead138
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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 <composer-vts/2.1/GraphicsComposerCallback.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+void GraphicsComposerCallback::setVsyncAllowed(bool allowed) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mVsyncAllowed = allowed;
+}
+
+std::vector<Display> GraphicsComposerCallback::getDisplays() const {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return std::vector<Display>(mDisplays.begin(), mDisplays.end());
+}
+
+int GraphicsComposerCallback::getInvalidHotplugCount() const {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mInvalidHotplugCount;
+}
+
+int GraphicsComposerCallback::getInvalidRefreshCount() const {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mInvalidRefreshCount;
+}
+
+int GraphicsComposerCallback::getInvalidVsyncCount() const {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mInvalidVsyncCount;
+}
+
+Return<void> GraphicsComposerCallback::onHotplug(Display display, Connection connection) {
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    if (connection == Connection::CONNECTED) {
+        if (!mDisplays.insert(display).second) {
+            mInvalidHotplugCount++;
+        }
+    } else if (connection == Connection::DISCONNECTED) {
+        if (!mDisplays.erase(display)) {
+            mInvalidHotplugCount++;
+        }
+    }
+
+    return Void();
+}
+
+Return<void> GraphicsComposerCallback::onRefresh(Display display) {
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    if (mDisplays.count(display) == 0) {
+        mInvalidRefreshCount++;
+    }
+
+    return Void();
+}
+
+Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    if (!mVsyncAllowed || mDisplays.count(display) == 0) {
+        mInvalidVsyncCount++;
+    }
+
+    return Void();
+}
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
new file mode 100644
index 0000000..6f8f1ad
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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 <composer-vts/2.1/TestCommandReader.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+void TestCommandReader::parse() {
+    while (!isEmpty()) {
+        IComposerClient::Command command;
+        uint16_t length;
+        ASSERT_TRUE(beginCommand(&command, &length));
+
+        switch (command) {
+            case IComposerClient::Command::SET_ERROR: {
+                ASSERT_EQ(2, length);
+                auto loc = read();
+                auto err = readSigned();
+                GTEST_FAIL() << "unexpected error " << err << " at location " << loc;
+            } break;
+            case IComposerClient::Command::SELECT_DISPLAY:
+            case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
+            case IComposerClient::Command::SET_DISPLAY_REQUESTS:
+            case IComposerClient::Command::SET_PRESENT_FENCE:
+            case IComposerClient::Command::SET_RELEASE_FENCES:
+                break;
+            default:
+                GTEST_FAIL() << "unexpected return command " << std::hex
+                             << static_cast<int>(command);
+                break;
+        }
+
+        endCommand();
+    }
+}
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
new file mode 100644
index 0000000..0d883e4
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/TestCommandReader.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Hdr;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+class ComposerClient;
+
+// A wrapper to IComposer.
+class Composer {
+   public:
+    Composer();
+    explicit Composer(const std::string& name);
+
+    sp<IComposer> getRaw() const;
+
+    // Returns true when the composer supports the specified capability.
+    bool hasCapability(IComposer::Capability capability) const;
+
+    std::vector<IComposer::Capability> getCapabilities();
+    std::string dumpDebugInfo();
+    std::unique_ptr<ComposerClient> createClient();
+
+   protected:
+    sp<IComposer> mComposer;
+
+   private:
+    void init();
+
+    std::unordered_set<IComposer::Capability> mCapabilities;
+};
+
+// A wrapper to IComposerClient.
+class ComposerClient {
+   public:
+    ComposerClient(const sp<IComposerClient>& client);
+    ~ComposerClient();
+
+    sp<IComposerClient> getRaw() const;
+
+    void registerCallback(const sp<IComposerCallback>& callback);
+    uint32_t getMaxVirtualDisplayCount();
+
+    Display createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint,
+                                 uint32_t outputBufferSlotCount, PixelFormat* outFormat);
+    void destroyVirtualDisplay(Display display);
+
+    Layer createLayer(Display display, uint32_t bufferSlotCount);
+    void destroyLayer(Display display, Layer layer);
+
+    Config getActiveConfig(Display display);
+    bool getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                PixelFormat format, Dataspace dataspace);
+    std::vector<ColorMode> getColorModes(Display display);
+    int32_t getDisplayAttribute(Display display, Config config,
+                                IComposerClient::Attribute attribute);
+    std::vector<Config> getDisplayConfigs(Display display);
+    std::string getDisplayName(Display display);
+    IComposerClient::DisplayType getDisplayType(Display display);
+    bool getDozeSupport(Display display);
+    std::vector<Hdr> getHdrCapabilities(Display display, float* outMaxLuminance,
+                                        float* outMaxAverageLuminance, float* outMinLuminance);
+
+    void setClientTargetSlotCount(Display display, uint32_t clientTargetSlotCount);
+    void setActiveConfig(Display display, Config config);
+    void setColorMode(Display display, ColorMode mode);
+    void setPowerMode(Display display, IComposerClient::PowerMode mode);
+    void setVsyncEnabled(Display display, bool enabled);
+
+    void execute(TestCommandReader* reader, CommandWriterBase* writer);
+
+   private:
+    sp<IComposerClient> mClient;
+
+    // Keep track of all virtual displays and layers.  When a test fails with
+    // ASSERT_*, the destructor will clean up the resources for the test.
+    struct DisplayResource {
+        DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
+
+        bool isVirtual;
+        std::unordered_set<Layer> layers;
+    };
+    std::unordered_map<Display, DisplayResource> mDisplayResources;
+};
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
new file mode 100644
index 0000000..e3c348f
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/graphics/composer/2.1/IComposerCallback.h>
+
+#include <mutex>
+#include <unordered_set>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+// IComposerCallback to be installed with IComposerClient::registerCallback.
+class GraphicsComposerCallback : public IComposerCallback {
+   public:
+    void setVsyncAllowed(bool allowed);
+
+    std::vector<Display> getDisplays() const;
+
+    int getInvalidHotplugCount() const;
+
+    int getInvalidRefreshCount() const;
+
+    int getInvalidVsyncCount() const;
+
+   private:
+    Return<void> onHotplug(Display display, Connection connection) override;
+    Return<void> onRefresh(Display display) override;
+    Return<void> onVsync(Display display, int64_t) override;
+
+    mutable std::mutex mMutex;
+    // the set of all currently connected displays
+    std::unordered_set<Display> mDisplays;
+    // true only when vsync is enabled
+    bool mVsyncAllowed = true;
+
+    // track invalid callbacks
+    int mInvalidHotplugCount = 0;
+    int mInvalidRefreshCount = 0;
+    int mInvalidVsyncCount = 0;
+};
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/vts/functional/TestCommandReader.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
similarity index 79%
rename from graphics/composer/2.1/vts/functional/TestCommandReader.h
rename to graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
index ae25d2d..3888eeb 100644
--- a/graphics/composer/2.1/vts/functional/TestCommandReader.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef TEST_COMMAND_READER_H
-#define TEST_COMMAND_READER_H
+#pragma once
 
 #include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
 
@@ -24,22 +23,20 @@
 namespace graphics {
 namespace composer {
 namespace V2_1 {
-namespace tests {
+namespace vts {
 
 // A command parser that checks that no error nor unexpected commands are
 // returned.
 class TestCommandReader : public CommandReaderBase {
- public:
-  // Parse all commands in the return command queue.  Call GTEST_FAIL() for
-  // unexpected errors or commands.
-  void parse();
+   public:
+    // Parse all commands in the return command queue.  Call GTEST_FAIL() for
+    // unexpected errors or commands.
+    void parse();
 };
 
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_1
 }  // namespace composer
 }  // namespace graphics
 }  // namespace hardware
 }  // namespace android
-
-#endif  // TEST_COMMAND_READER_H
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 92b65a3..8e346df 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -14,36 +14,6 @@
 // limitations under the License.
 //
 
-cc_library_static {
-    name: "libVtsHalGraphicsComposerTestUtils",
-    defaults: ["hidl_defaults"],
-    srcs: [
-        "GraphicsComposerCallback.cpp",
-        "TestCommandReader.cpp",
-        "VtsHalGraphicsComposerTestUtils.cpp",
-    ],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "libfmq",
-        "libsync",
-    ],
-    static_libs: [
-        "VtsHalHidlTargetTestBase",
-    ],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-        "-DLOG_TAG=\"GraphicsComposerTestUtils\"",
-    ],
-    export_include_dirs: ["."],
-}
-
 cc_test {
     name: "VtsHalGraphicsComposerV2_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
@@ -57,10 +27,9 @@
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
-        "libVtsHalGraphicsComposerTestUtils",
-        "libnativehelper",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp b/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp
deleted file mode 100644
index 0ad440c..0000000
--- a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "GraphicsComposerCallback.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-void GraphicsComposerCallback::setVsyncAllowed(bool allowed) {
-  std::lock_guard<std::mutex> lock(mMutex);
-  mVsyncAllowed = allowed;
-}
-
-std::vector<Display> GraphicsComposerCallback::getDisplays() const {
-  std::lock_guard<std::mutex> lock(mMutex);
-  return std::vector<Display>(mDisplays.begin(), mDisplays.end());
-}
-
-int GraphicsComposerCallback::getInvalidHotplugCount() const {
-  std::lock_guard<std::mutex> lock(mMutex);
-  return mInvalidHotplugCount;
-}
-
-int GraphicsComposerCallback::getInvalidRefreshCount() const {
-  std::lock_guard<std::mutex> lock(mMutex);
-  return mInvalidRefreshCount;
-}
-
-int GraphicsComposerCallback::getInvalidVsyncCount() const {
-  std::lock_guard<std::mutex> lock(mMutex);
-  return mInvalidVsyncCount;
-}
-
-Return<void> GraphicsComposerCallback::onHotplug(Display display,
-                                                 Connection connection) {
-  std::lock_guard<std::mutex> lock(mMutex);
-
-  if (connection == Connection::CONNECTED) {
-    if (!mDisplays.insert(display).second) {
-      mInvalidHotplugCount++;
-    }
-  } else if (connection == Connection::DISCONNECTED) {
-    if (!mDisplays.erase(display)) {
-      mInvalidHotplugCount++;
-    }
-  }
-
-  return Void();
-}
-
-Return<void> GraphicsComposerCallback::onRefresh(Display display) {
-  std::lock_guard<std::mutex> lock(mMutex);
-
-  if (mDisplays.count(display) == 0) {
-    mInvalidRefreshCount++;
-  }
-
-  return Void();
-}
-
-Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
-  std::lock_guard<std::mutex> lock(mMutex);
-
-  if (!mVsyncAllowed || mDisplays.count(display) == 0) {
-    mInvalidVsyncCount++;
-  }
-
-  return Void();
-}
-
-}  // namespace tests
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h b/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h
deleted file mode 100644
index e332086..0000000
--- a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef GRAPHICS_COMPOSER_CALLBACK_H
-#define GRAPHICS_COMPOSER_CALLBACK_H
-
-#include <android/hardware/graphics/composer/2.1/IComposerCallback.h>
-
-#include <mutex>
-#include <unordered_set>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-// IComposerCallback to be installed with IComposerClient::registerCallback.
-class GraphicsComposerCallback : public IComposerCallback {
- public:
-  void setVsyncAllowed(bool allowed);
-
-  std::vector<Display> getDisplays() const;
-
-  int getInvalidHotplugCount() const;
-
-  int getInvalidRefreshCount() const;
-
-  int getInvalidVsyncCount() const;
-
- private:
-  Return<void> onHotplug(Display display, Connection connection) override;
-  Return<void> onRefresh(Display display) override;
-  Return<void> onVsync(Display display, int64_t) override;
-
-  mutable std::mutex mMutex;
-  // the set of all currently connected displays
-  std::unordered_set<Display> mDisplays;
-  // true only when vsync is enabled
-  bool mVsyncAllowed = true;
-
-  // track invalid callbacks
-  int mInvalidHotplugCount = 0;
-  int mInvalidRefreshCount = 0;
-  int mInvalidVsyncCount = 0;
-};
-
-}  // namespace tests
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // GRAPHICS_COMPOSER_CALLBACK_H
diff --git a/graphics/composer/2.1/vts/functional/TestCommandReader.cpp b/graphics/composer/2.1/vts/functional/TestCommandReader.cpp
deleted file mode 100644
index b1f9aca..0000000
--- a/graphics/composer/2.1/vts/functional/TestCommandReader.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "TestCommandReader.h"
-
-#include <gtest/gtest.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-void TestCommandReader::parse() {
-  while (!isEmpty()) {
-    IComposerClient::Command command;
-    uint16_t length;
-    ASSERT_TRUE(beginCommand(&command, &length));
-
-    switch (command) {
-      case IComposerClient::Command::SET_ERROR: {
-        ASSERT_EQ(2, length);
-        auto loc = read();
-        auto err = readSigned();
-        GTEST_FAIL() << "unexpected error " << err << " at location " << loc;
-      } break;
-      case IComposerClient::Command::SELECT_DISPLAY:
-      case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
-      case IComposerClient::Command::SET_DISPLAY_REQUESTS:
-      case IComposerClient::Command::SET_PRESENT_FENCE:
-      case IComposerClient::Command::SET_RELEASE_FENCES:
-        break;
-      default:
-        GTEST_FAIL() << "unexpected return command " << std::hex
-                     << static_cast<int>(command);
-        break;
-    }
-
-    endCommand();
-  }
-}
-
-}  // namespace tests
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
deleted file mode 100644
index c66cdd0..0000000
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <VtsHalHidlTargetTestBase.h>
-
-#include "VtsHalGraphicsComposerTestUtils.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-Composer::Composer() {
-  mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>();
-  init();
-}
-
-Composer::Composer(const std::string& name) {
-  mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name);
-  init();
-}
-
-void Composer::init() {
-  ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
-
-  std::vector<IComposer::Capability> capabilities = getCapabilities();
-  mCapabilities.insert(capabilities.begin(), capabilities.end());
-}
-
-sp<IComposer> Composer::getRaw() const { return mComposer; }
-
-bool Composer::hasCapability(IComposer::Capability capability) const {
-  return mCapabilities.count(capability) > 0;
-}
-
-std::vector<IComposer::Capability> Composer::getCapabilities() {
-  std::vector<IComposer::Capability> capabilities;
-  mComposer->getCapabilities(
-      [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
-
-  return capabilities;
-}
-
-std::string Composer::dumpDebugInfo() {
-  std::string debugInfo;
-  mComposer->dumpDebugInfo(
-      [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
-  return debugInfo;
-}
-
-std::unique_ptr<ComposerClient> Composer::createClient() {
-  std::unique_ptr<ComposerClient> client;
-  mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
-    ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
-    client = std::make_unique<ComposerClient>(tmpClient);
-  });
-
-  return client;
-}
-
-ComposerClient::ComposerClient(const sp<IComposerClient>& client)
-    : mClient(client) {}
-
-ComposerClient::~ComposerClient() {
-  for (auto it : mDisplayResources) {
-    Display display = it.first;
-    DisplayResource& resource = it.second;
-
-    for (auto layer : resource.layers) {
-      EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer))
-          << "failed to destroy layer " << layer;
-    }
-
-    if (resource.isVirtual) {
-      EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display))
-          << "failed to destroy virtual display " << display;
-    }
-  }
-  mDisplayResources.clear();
-}
-
-sp<IComposerClient> ComposerClient::getRaw() const { return mClient; }
-
-void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) {
-  mClient->registerCallback(callback);
-}
-
-uint32_t ComposerClient::getMaxVirtualDisplayCount() {
-  return mClient->getMaxVirtualDisplayCount();
-}
-
-Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
-                                             PixelFormat formatHint,
-                                             uint32_t outputBufferSlotCount,
-                                             PixelFormat* outFormat) {
-  Display display = 0;
-  mClient->createVirtualDisplay(
-      width, height, formatHint, outputBufferSlotCount,
-      [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
-        display = tmpDisplay;
-        *outFormat = tmpFormat;
-
-        ASSERT_TRUE(
-            mDisplayResources.insert({display, DisplayResource(true)}).second)
-            << "duplicated virtual display id " << display;
-      });
-
-  return display;
-}
-
-void ComposerClient::destroyVirtualDisplay(Display display) {
-  Error error = mClient->destroyVirtualDisplay(display);
-  ASSERT_EQ(Error::NONE, error)
-      << "failed to destroy virtual display " << display;
-
-  mDisplayResources.erase(display);
-}
-
-Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) {
-  Layer layer = 0;
-  mClient->createLayer(
-      display, bufferSlotCount,
-      [&](const auto& tmpError, const auto& tmpLayer) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer";
-        layer = tmpLayer;
-
-        auto resourceIt = mDisplayResources.find(display);
-        if (resourceIt == mDisplayResources.end()) {
-          resourceIt =
-              mDisplayResources.insert({display, DisplayResource(false)}).first;
-        }
-
-        ASSERT_TRUE(resourceIt->second.layers.insert(layer).second)
-            << "duplicated layer id " << layer;
-      });
-
-  return layer;
-}
-
-void ComposerClient::destroyLayer(Display display, Layer layer) {
-  Error error = mClient->destroyLayer(display, layer);
-  ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer;
-
-  auto resourceIt = mDisplayResources.find(display);
-  ASSERT_NE(mDisplayResources.end(), resourceIt);
-  resourceIt->second.layers.erase(layer);
-}
-
-Config ComposerClient::getActiveConfig(Display display) {
-  Config config = 0;
-  mClient->getActiveConfig(
-      display, [&](const auto& tmpError, const auto& tmpConfig) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config";
-        config = tmpConfig;
-      });
-
-  return config;
-}
-
-bool ComposerClient::getClientTargetSupport(Display display, uint32_t width,
-                                            uint32_t height, PixelFormat format,
-                                            Dataspace dataspace) {
-  Error error = mClient->getClientTargetSupport(display, width, height, format,
-                                                dataspace);
-  return error == Error::NONE;
-}
-
-std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
-  std::vector<ColorMode> modes;
-  mClient->getColorModes(
-      display, [&](const auto& tmpError, const auto& tmpMode) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode";
-        modes = tmpMode;
-      });
-
-  return modes;
-}
-
-int32_t ComposerClient::getDisplayAttribute(
-    Display display, Config config, IComposerClient::Attribute attribute) {
-  int32_t value = 0;
-  mClient->getDisplayAttribute(display, config, attribute,
-                               [&](const auto& tmpError, const auto& tmpValue) {
-                                 ASSERT_EQ(Error::NONE, tmpError)
-                                     << "failed to get display attribute";
-                                 value = tmpValue;
-                               });
-
-  return value;
-}
-
-std::vector<Config> ComposerClient::getDisplayConfigs(Display display) {
-  std::vector<Config> configs;
-  mClient->getDisplayConfigs(
-      display, [&](const auto& tmpError, const auto& tmpConfigs) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs";
-        configs = tmpConfigs;
-      });
-
-  return configs;
-}
-
-std::string ComposerClient::getDisplayName(Display display) {
-  std::string name;
-  mClient->getDisplayName(
-      display, [&](const auto& tmpError, const auto& tmpName) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name";
-        name = tmpName.c_str();
-      });
-
-  return name;
-}
-
-IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) {
-  IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
-  mClient->getDisplayType(
-      display, [&](const auto& tmpError, const auto& tmpType) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type";
-        type = tmpType;
-      });
-
-  return type;
-}
-
-bool ComposerClient::getDozeSupport(Display display) {
-  bool support = false;
-  mClient->getDozeSupport(
-      display, [&](const auto& tmpError, const auto& tmpSupport) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support";
-        support = tmpSupport;
-      });
-
-  return support;
-}
-
-std::vector<Hdr> ComposerClient::getHdrCapabilities(
-    Display display, float* outMaxLuminance, float* outMaxAverageLuminance,
-    float* outMinLuminance) {
-  std::vector<Hdr> types;
-  mClient->getHdrCapabilities(
-      display,
-      [&](const auto& tmpError, const auto& tmpTypes,
-          const auto& tmpMaxLuminance, const auto& tmpMaxAverageLuminance,
-          const auto& tmpMinLuminance) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities";
-        types = tmpTypes;
-        *outMaxLuminance = tmpMaxLuminance;
-        *outMaxAverageLuminance = tmpMaxAverageLuminance;
-        *outMinLuminance = tmpMinLuminance;
-      });
-
-  return types;
-}
-
-void ComposerClient::setClientTargetSlotCount(Display display,
-                                              uint32_t clientTargetSlotCount) {
-  Error error =
-      mClient->setClientTargetSlotCount(display, clientTargetSlotCount);
-  ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count";
-}
-
-void ComposerClient::setActiveConfig(Display display, Config config) {
-  Error error = mClient->setActiveConfig(display, config);
-  ASSERT_EQ(Error::NONE, error) << "failed to set active config";
-}
-
-void ComposerClient::setColorMode(Display display, ColorMode mode) {
-  Error error = mClient->setColorMode(display, mode);
-  ASSERT_EQ(Error::NONE, error) << "failed to set color mode";
-}
-
-void ComposerClient::setPowerMode(Display display,
-                                  IComposerClient::PowerMode mode) {
-  Error error = mClient->setPowerMode(display, mode);
-  ASSERT_EQ(Error::NONE, error) << "failed to set power mode";
-}
-
-void ComposerClient::setVsyncEnabled(Display display, bool enabled) {
-  IComposerClient::Vsync vsync = (enabled) ? IComposerClient::Vsync::ENABLE
-                                           : IComposerClient::Vsync::DISABLE;
-  Error error = mClient->setVsyncEnabled(display, vsync);
-  ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode";
-
-  // give the hwbinder thread some time to handle any pending vsync callback
-  if (!enabled) {
-      usleep(5 * 1000);
-  }
-}
-
-void ComposerClient::execute(TestCommandReader* reader,
-                             CommandWriterBase* writer) {
-  bool queueChanged = false;
-  uint32_t commandLength = 0;
-  hidl_vec<hidl_handle> commandHandles;
-  ASSERT_TRUE(
-      writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
-
-  if (queueChanged) {
-    auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
-    ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
-    return;
-  }
-
-  mClient->executeCommands(
-      commandLength, commandHandles,
-      [&](const auto& tmpError, const auto& tmpOutQueueChanged,
-          const auto& tmpOutLength, const auto& tmpOutHandles) {
-        ASSERT_EQ(Error::NONE, tmpError);
-
-        if (tmpOutQueueChanged) {
-          mClient->getOutputCommandQueue(
-              [&](const auto& tmpError, const auto& tmpDescriptor) {
-                ASSERT_EQ(Error::NONE, tmpError);
-                reader->setMQDescriptor(tmpDescriptor);
-              });
-        }
-
-        ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
-        reader->parse();
-      });
-}
-
-}  // namespace tests
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
deleted file mode 100644
index 00d9d8c..0000000
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VTS_HAL_GRAPHICS_COMPOSER_UTILS
-#define VTS_HAL_GRAPHICS_COMPOSER_UTILS
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
-#include <utils/StrongPointer.h>
-
-#include "TestCommandReader.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::Hdr;
-using android::hardware::graphics::common::V1_0::PixelFormat;
-
-class ComposerClient;
-
-// A wrapper to IComposer.
-class Composer {
- public:
-  Composer();
-  explicit Composer(const std::string& name);
-
-  sp<IComposer> getRaw() const;
-
-  // Returns true when the composer supports the specified capability.
-  bool hasCapability(IComposer::Capability capability) const;
-
-  std::vector<IComposer::Capability> getCapabilities();
-  std::string dumpDebugInfo();
-  std::unique_ptr<ComposerClient> createClient();
-
- protected:
-  sp<IComposer> mComposer;
-
- private:
-  void init();
-
-  std::unordered_set<IComposer::Capability> mCapabilities;
-};
-
-// A wrapper to IComposerClient.
-class ComposerClient {
- public:
-  ComposerClient(const sp<IComposerClient>& client);
-  ~ComposerClient();
-
-  sp<IComposerClient> getRaw() const;
-
-  void registerCallback(const sp<IComposerCallback>& callback);
-  uint32_t getMaxVirtualDisplayCount();
-
-  Display createVirtualDisplay(uint32_t width, uint32_t height,
-                               PixelFormat formatHint,
-                               uint32_t outputBufferSlotCount,
-                               PixelFormat* outFormat);
-  void destroyVirtualDisplay(Display display);
-
-  Layer createLayer(Display display, uint32_t bufferSlotCount);
-  void destroyLayer(Display display, Layer layer);
-
-  Config getActiveConfig(Display display);
-  bool getClientTargetSupport(Display display, uint32_t width, uint32_t height,
-                              PixelFormat format, Dataspace dataspace);
-  std::vector<ColorMode> getColorModes(Display display);
-  int32_t getDisplayAttribute(Display display, Config config,
-                              IComposerClient::Attribute attribute);
-  std::vector<Config> getDisplayConfigs(Display display);
-  std::string getDisplayName(Display display);
-  IComposerClient::DisplayType getDisplayType(Display display);
-  bool getDozeSupport(Display display);
-  std::vector<Hdr> getHdrCapabilities(Display display, float* outMaxLuminance,
-                                      float* outMaxAverageLuminance,
-                                      float* outMinLuminance);
-
-  void setClientTargetSlotCount(Display display,
-                                uint32_t clientTargetSlotCount);
-  void setActiveConfig(Display display, Config config);
-  void setColorMode(Display display, ColorMode mode);
-  void setPowerMode(Display display, IComposerClient::PowerMode mode);
-  void setVsyncEnabled(Display display, bool enabled);
-
-  void execute(TestCommandReader* reader, CommandWriterBase* writer);
-
- private:
-  sp<IComposerClient> mClient;
-
-  // Keep track of all virtual displays and layers.  When a test fails with
-  // ASSERT_*, the destructor will clean up the resources for the test.
-  struct DisplayResource {
-    DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
-
-    bool isVirtual;
-    std::unordered_set<Layer> layers;
-  };
-  std::unordered_map<Display, DisplayResource> mDisplayResources;
-};
-
-}  // namespace tests
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // VTS_HAL_GRAPHICS_COMPOSER_UTILS
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 376ee37..8b8b530 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -17,10 +17,10 @@
 #define LOG_TAG "graphics_composer_hidl_hal_test"
 
 #include <android-base/logging.h>
+#include <composer-vts/2.1/ComposerVts.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.h>
 #include <mapper-vts/2.0/MapperVts.h>
-#include "GraphicsComposerCallback.h"
-#include "TestCommandReader.h"
-#include "VtsHalGraphicsComposerTestUtils.h"
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
@@ -38,7 +38,7 @@
 namespace graphics {
 namespace composer {
 namespace V2_1 {
-namespace tests {
+namespace vts {
 namespace {
 
 using android::hardware::graphics::common::V1_0::BufferUsage;
@@ -69,53 +69,53 @@
 };
 
 class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- protected:
-  void SetUp() override {
-      ASSERT_NO_FATAL_FAILURE(
-          mComposer = std::make_unique<Composer>(
-              GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
-      ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
+   protected:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(
+            mComposer = std::make_unique<Composer>(
+                GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+        ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
 
-      mComposerCallback = new GraphicsComposerCallback;
-      mComposerClient->registerCallback(mComposerCallback);
+        mComposerCallback = new GraphicsComposerCallback;
+        mComposerClient->registerCallback(mComposerCallback);
 
-      // assume the first display is primary and is never removed
-      mPrimaryDisplay = waitForFirstDisplay();
+        // assume the first display is primary and is never removed
+        mPrimaryDisplay = waitForFirstDisplay();
 
-      // explicitly disable vsync
-      mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
-      mComposerCallback->setVsyncAllowed(false);
-  }
-
-  void TearDown() override {
-    if (mComposerCallback != nullptr) {
-      EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
-      EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
-      EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+        // explicitly disable vsync
+        mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+        mComposerCallback->setVsyncAllowed(false);
     }
-  }
 
-  // use the slot count usually set by SF
-  static constexpr uint32_t kBufferSlotCount = 64;
-
-  std::unique_ptr<Composer> mComposer;
-  std::unique_ptr<ComposerClient> mComposerClient;
-  sp<GraphicsComposerCallback> mComposerCallback;
-  // the first display and is assumed never to be removed
-  Display mPrimaryDisplay;
-
- private:
-  Display waitForFirstDisplay() {
-    while (true) {
-      std::vector<Display> displays = mComposerCallback->getDisplays();
-      if (displays.empty()) {
-        usleep(5 * 1000);
-        continue;
-      }
-
-      return displays[0];
+    void TearDown() override {
+        if (mComposerCallback != nullptr) {
+            EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+        }
     }
-  }
+
+    // use the slot count usually set by SF
+    static constexpr uint32_t kBufferSlotCount = 64;
+
+    std::unique_ptr<Composer> mComposer;
+    std::unique_ptr<ComposerClient> mComposerClient;
+    sp<GraphicsComposerCallback> mComposerCallback;
+    // the first display and is assumed never to be removed
+    Display mPrimaryDisplay;
+
+   private:
+    Display waitForFirstDisplay() {
+        while (true) {
+            std::vector<Display> displays = mComposerCallback->getDisplays();
+            if (displays.empty()) {
+                usleep(5 * 1000);
+                continue;
+            }
+
+            return displays[0];
+        }
+    }
 };
 
 /**
@@ -124,16 +124,17 @@
  * Test that IComposer::getCapabilities returns no invalid capabilities.
  */
 TEST_F(GraphicsComposerHidlTest, GetCapabilities) {
-  auto capabilities = mComposer->getCapabilities();
-  ASSERT_EQ(capabilities.end(),
-            std::find(capabilities.begin(), capabilities.end(),
-                      IComposer::Capability::INVALID));
+    auto capabilities = mComposer->getCapabilities();
+    ASSERT_EQ(capabilities.end(),
+              std::find(capabilities.begin(), capabilities.end(), IComposer::Capability::INVALID));
 }
 
 /**
  * Test IComposer::dumpDebugInfo.
  */
-TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) { mComposer->dumpDebugInfo(); }
+TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) {
+    mComposer->dumpDebugInfo();
+}
 
 /**
  * Test IComposer::createClient.
@@ -141,9 +142,8 @@
  * Test that IComposerClient is a singleton.
  */
 TEST_F(GraphicsComposerHidlTest, CreateClientSingleton) {
-  mComposer->getRaw()->createClient([&](const auto& tmpError, const auto&) {
-    EXPECT_EQ(Error::NO_RESOURCES, tmpError);
-  });
+    mComposer->getRaw()->createClient(
+        [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::NO_RESOURCES, tmpError); });
 }
 
 /**
@@ -153,22 +153,22 @@
  * Test that virtual displays can be created and has the correct display type.
  */
 TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay) {
-  if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
-    GTEST_SUCCEED() << "no virtual display support";
-    return;
-  }
+    if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
+        GTEST_SUCCEED() << "no virtual display support";
+        return;
+    }
 
-  Display display;
-  PixelFormat format;
-  ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay(
-                              64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
-                              kBufferSlotCount, &format));
+    Display display;
+    PixelFormat format;
+    ASSERT_NO_FATAL_FAILURE(
+        display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
+                                                        kBufferSlotCount, &format));
 
-  // test display type
-  IComposerClient::DisplayType type = mComposerClient->getDisplayType(display);
-  EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type);
+    // test display type
+    IComposerClient::DisplayType type = mComposerClient->getDisplayType(display);
+    EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type);
 
-  mComposerClient->destroyVirtualDisplay(display);
+    mComposerClient->destroyVirtualDisplay(display);
 }
 
 /**
@@ -177,18 +177,18 @@
  * Test that layers can be created and destroyed.
  */
 TEST_F(GraphicsComposerHidlTest, CreateLayer) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mComposerClient->destroyLayer(mPrimaryDisplay, layer);
+    mComposerClient->destroyLayer(mPrimaryDisplay, layer);
 }
 
 /**
  * Test IComposerClient::getDisplayName.
  */
 TEST_F(GraphicsComposerHidlTest, GetDisplayName) {
-  mComposerClient->getDisplayName(mPrimaryDisplay);
+    mComposerClient->getDisplayName(mPrimaryDisplay);
 }
 
 /**
@@ -198,8 +198,8 @@
  * for the primary display.
  */
 TEST_F(GraphicsComposerHidlTest, GetDisplayType) {
-  ASSERT_EQ(IComposerClient::DisplayType::PHYSICAL,
-            mComposerClient->getDisplayType(mPrimaryDisplay));
+    ASSERT_EQ(IComposerClient::DisplayType::PHYSICAL,
+              mComposerClient->getDisplayType(mPrimaryDisplay));
 }
 
 /**
@@ -209,22 +209,20 @@
  * required client targets.
  */
 TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport) {
-  std::vector<Config> configs =
-      mComposerClient->getDisplayConfigs(mPrimaryDisplay);
-  for (auto config : configs) {
-    int32_t width = mComposerClient->getDisplayAttribute(
-        mPrimaryDisplay, config, IComposerClient::Attribute::WIDTH);
-    int32_t height = mComposerClient->getDisplayAttribute(
-        mPrimaryDisplay, config, IComposerClient::Attribute::HEIGHT);
-    ASSERT_LT(0, width);
-    ASSERT_LT(0, height);
+    std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+    for (auto config : configs) {
+        int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                             IComposerClient::Attribute::WIDTH);
+        int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                              IComposerClient::Attribute::HEIGHT);
+        ASSERT_LT(0, width);
+        ASSERT_LT(0, height);
 
-    mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+        mComposerClient->setActiveConfig(mPrimaryDisplay, config);
 
-    ASSERT_TRUE(mComposerClient->getClientTargetSupport(
-        mPrimaryDisplay, width, height, PixelFormat::RGBA_8888,
-        Dataspace::UNKNOWN));
-  }
+        ASSERT_TRUE(mComposerClient->getClientTargetSupport(
+            mPrimaryDisplay, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN));
+    }
 }
 
 /**
@@ -234,47 +232,44 @@
  * formats, and succeeds or fails correctly for optional attributes.
  */
 TEST_F(GraphicsComposerHidlTest, GetDisplayAttribute) {
-  std::vector<Config> configs =
-      mComposerClient->getDisplayConfigs(mPrimaryDisplay);
-  for (auto config : configs) {
-    const std::array<IComposerClient::Attribute, 3> requiredAttributes = {{
-        IComposerClient::Attribute::WIDTH, IComposerClient::Attribute::HEIGHT,
-        IComposerClient::Attribute::VSYNC_PERIOD,
-    }};
-    for (auto attribute : requiredAttributes) {
-      mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, attribute);
-    }
+    std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+    for (auto config : configs) {
+        const std::array<IComposerClient::Attribute, 3> requiredAttributes = {{
+            IComposerClient::Attribute::WIDTH, IComposerClient::Attribute::HEIGHT,
+            IComposerClient::Attribute::VSYNC_PERIOD,
+        }};
+        for (auto attribute : requiredAttributes) {
+            mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, attribute);
+        }
 
-    const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
-        IComposerClient::Attribute::DPI_X, IComposerClient::Attribute::DPI_Y,
-    }};
-    for (auto attribute : optionalAttributes) {
-      mComposerClient->getRaw()->getDisplayAttribute(
-          mPrimaryDisplay, config, attribute,
-          [&](const auto& tmpError, const auto&) {
-            EXPECT_TRUE(tmpError == Error::NONE ||
-                        tmpError == Error::UNSUPPORTED);
-          });
+        const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
+            IComposerClient::Attribute::DPI_X, IComposerClient::Attribute::DPI_Y,
+        }};
+        for (auto attribute : optionalAttributes) {
+            mComposerClient->getRaw()->getDisplayAttribute(
+                mPrimaryDisplay, config, attribute, [&](const auto& tmpError, const auto&) {
+                    EXPECT_TRUE(tmpError == Error::NONE || tmpError == Error::UNSUPPORTED);
+                });
+        }
     }
-  }
 }
 
 /**
  * Test IComposerClient::getHdrCapabilities.
  */
 TEST_F(GraphicsComposerHidlTest, GetHdrCapabilities) {
-  float maxLuminance;
-  float maxAverageLuminance;
-  float minLuminance;
-  mComposerClient->getHdrCapabilities(mPrimaryDisplay, &maxLuminance,
-                                      &maxAverageLuminance, &minLuminance);
+    float maxLuminance;
+    float maxAverageLuminance;
+    float minLuminance;
+    mComposerClient->getHdrCapabilities(mPrimaryDisplay, &maxLuminance, &maxAverageLuminance,
+                                        &minLuminance);
 }
 
 /**
  * Test IComposerClient::setClientTargetSlotCount.
  */
 TEST_F(GraphicsComposerHidlTest, SetClientTargetSlotCount) {
-  mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
+    mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
 }
 
 /**
@@ -284,12 +279,11 @@
  * configs.
  */
 TEST_F(GraphicsComposerHidlTest, SetActiveConfig) {
-  std::vector<Config> configs =
-      mComposerClient->getDisplayConfigs(mPrimaryDisplay);
-  for (auto config : configs) {
-    mComposerClient->setActiveConfig(mPrimaryDisplay, config);
-    ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay));
-  }
+    std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+    for (auto config : configs) {
+        mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+        ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay));
+    }
 }
 
 /**
@@ -298,11 +292,10 @@
  * Test that IComposerClient::setColorMode succeeds for all color modes.
  */
 TEST_F(GraphicsComposerHidlTest, SetColorMode) {
-  std::vector<ColorMode> modes =
-      mComposerClient->getColorModes(mPrimaryDisplay);
-  for (auto mode : modes) {
-    mComposerClient->setColorMode(mPrimaryDisplay, mode);
-  }
+    std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+    for (auto mode : modes) {
+        mComposerClient->setColorMode(mPrimaryDisplay, mode);
+    }
 }
 
 /**
@@ -311,20 +304,20 @@
  * Test that IComposerClient::setPowerMode succeeds for all power modes.
  */
 TEST_F(GraphicsComposerHidlTest, SetPowerMode) {
-  std::vector<IComposerClient::PowerMode> modes;
-  modes.push_back(IComposerClient::PowerMode::OFF);
+    std::vector<IComposerClient::PowerMode> modes;
+    modes.push_back(IComposerClient::PowerMode::OFF);
 
-  if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
-    modes.push_back(IComposerClient::PowerMode::DOZE);
-    modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
-  }
+    if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
+        modes.push_back(IComposerClient::PowerMode::DOZE);
+        modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
+    }
 
-  // push ON last
-  modes.push_back(IComposerClient::PowerMode::ON);
+    // push ON last
+    modes.push_back(IComposerClient::PowerMode::ON);
 
-  for (auto mode : modes) {
-    mComposerClient->setPowerMode(mPrimaryDisplay, mode);
-  }
+    for (auto mode : modes) {
+        mComposerClient->setPowerMode(mPrimaryDisplay, mode);
+    }
 }
 
 /**
@@ -334,369 +327,365 @@
  * spurious vsync events.
  */
 TEST_F(GraphicsComposerHidlTest, SetVsyncEnabled) {
-  mComposerCallback->setVsyncAllowed(true);
+    mComposerCallback->setVsyncAllowed(true);
 
-  mComposerClient->setVsyncEnabled(mPrimaryDisplay, true);
-  usleep(60 * 1000);
-  mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+    mComposerClient->setVsyncEnabled(mPrimaryDisplay, true);
+    usleep(60 * 1000);
+    mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
 
-  mComposerCallback->setVsyncAllowed(false);
+    mComposerCallback->setVsyncAllowed(false);
 }
 
 // Tests for IComposerClient::Command.
 class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
- protected:
-  void SetUp() override {
-    ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
+   protected:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
 
-    ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
 
-    mWriter = std::make_unique<CommandWriterBase>(1024);
-    mReader = std::make_unique<TestCommandReader>();
-  }
+        mWriter = std::make_unique<CommandWriterBase>(1024);
+        mReader = std::make_unique<TestCommandReader>();
+    }
 
-  void TearDown() override {
-    ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
-  }
+    void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); }
 
-  const native_handle_t* allocate() {
-      IMapper::BufferDescriptorInfo info{};
-      info.width = 64;
-      info.height = 64;
-      info.layerCount = 1;
-      info.format = PixelFormat::RGBA_8888;
-      info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN |
-                                         BufferUsage::CPU_READ_OFTEN);
+    const native_handle_t* allocate() {
+        IMapper::BufferDescriptorInfo info{};
+        info.width = 64;
+        info.height = 64;
+        info.layerCount = 1;
+        info.format = PixelFormat::RGBA_8888;
+        info.usage =
+            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
 
-      return mGralloc->allocate(info);
-  }
+        return mGralloc->allocate(info);
+    }
 
-  void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
+    void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
-  std::unique_ptr<CommandWriterBase> mWriter;
-  std::unique_ptr<TestCommandReader> mReader;
+    std::unique_ptr<CommandWriterBase> mWriter;
+    std::unique_ptr<TestCommandReader> mReader;
 
- private:
-  std::unique_ptr<Gralloc> mGralloc;
+   private:
+    std::unique_ptr<Gralloc> mGralloc;
 };
 
 /**
  * Test IComposerClient::Command::SET_COLOR_TRANSFORM.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_COLOR_TRANSFORM) {
-  const std::array<float, 16> identity = {{
-      1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-      0.0f, 0.0f, 0.0f, 1.0f,
-  }};
+    const std::array<float, 16> identity = {{
+        1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+        1.0f,
+    }};
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->setColorTransform(identity.data(), ColorTransform::IDENTITY);
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->setColorTransform(identity.data(), ColorTransform::IDENTITY);
 
-  execute();
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_CLIENT_TARGET.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_CLIENT_TARGET) {
-  mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
+    mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN,
-                           std::vector<IComposerClient::Rect>());
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN,
+                             std::vector<IComposerClient::Rect>());
 
-  execute();
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_OUTPUT_BUFFER.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_OUTPUT_BUFFER) {
-  if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
-    GTEST_SUCCEED() << "no virtual display support";
-    return;
-  }
+    if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
+        GTEST_SUCCEED() << "no virtual display support";
+        return;
+    }
 
-  Display display;
-  PixelFormat format;
-  ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay(
-                              64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
-                              kBufferSlotCount, &format));
+    Display display;
+    PixelFormat format;
+    ASSERT_NO_FATAL_FAILURE(
+        display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
+                                                        kBufferSlotCount, &format));
 
-  const native_handle_t* handle;
-  ASSERT_NO_FATAL_FAILURE(handle = allocate());
+    const native_handle_t* handle;
+    ASSERT_NO_FATAL_FAILURE(handle = allocate());
 
-  mWriter->selectDisplay(display);
-  mWriter->setOutputBuffer(0, handle, -1);
-  execute();
+    mWriter->selectDisplay(display);
+    mWriter->setOutputBuffer(0, handle, -1);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::VALIDATE_DISPLAY.
  */
 TEST_F(GraphicsComposerHidlCommandTest, VALIDATE_DISPLAY) {
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->validateDisplay();
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->validateDisplay();
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::ACCEPT_DISPLAY_CHANGES.
  */
 TEST_F(GraphicsComposerHidlCommandTest, ACCEPT_DISPLAY_CHANGES) {
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->validateDisplay();
-  mWriter->acceptDisplayChanges();
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->validateDisplay();
+    mWriter->acceptDisplayChanges();
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::PRESENT_DISPLAY.
  */
 TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY) {
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->validateDisplay();
-  mWriter->presentDisplay();
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->validateDisplay();
+    mWriter->presentDisplay();
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerCursorPosition(1, 1);
-  mWriter->setLayerCursorPosition(0, 0);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerCursorPosition(1, 1);
+    mWriter->setLayerCursorPosition(0, 0);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_BUFFER.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) {
-  auto handle = allocate();
-  ASSERT_NE(nullptr, handle);
+    auto handle = allocate();
+    ASSERT_NE(nullptr, handle);
 
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerBuffer(0, handle, -1);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerBuffer(0, handle, -1);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SURFACE_DAMAGE) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  IComposerClient::Rect empty{0, 0, 0, 0};
-  IComposerClient::Rect unit{0, 0, 1, 1};
+    IComposerClient::Rect empty{0, 0, 0, 0};
+    IComposerClient::Rect unit{0, 0, 1, 1};
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, empty));
-  mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, unit));
-  mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>());
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, empty));
+    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, unit));
+    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>());
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_BLEND_MODE.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BLEND_MODE) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
-  mWriter->setLayerBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
-  mWriter->setLayerBlendMode(IComposerClient::BlendMode::COVERAGE);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
+    mWriter->setLayerBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
+    mWriter->setLayerBlendMode(IComposerClient::BlendMode::COVERAGE);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_COLOR.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COLOR) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerColor(IComposerClient::Color{0xff, 0xff, 0xff, 0xff});
-  mWriter->setLayerColor(IComposerClient::Color{0, 0, 0, 0});
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerColor(IComposerClient::Color{0xff, 0xff, 0xff, 0xff});
+    mWriter->setLayerColor(IComposerClient::Color{0, 0, 0, 0});
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COMPOSITION_TYPE) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT);
-  mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
-  mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
-  mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_DATASPACE.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DATASPACE) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerDataspace(Dataspace::UNKNOWN);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_DISPLAY_FRAME.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DISPLAY_FRAME) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerDisplayFrame(IComposerClient::Rect{0, 0, 1, 1});
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerDisplayFrame(IComposerClient::Rect{0, 0, 1, 1});
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_PLANE_ALPHA.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PLANE_ALPHA) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerPlaneAlpha(0.0f);
-  mWriter->setLayerPlaneAlpha(1.0f);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerPlaneAlpha(0.0f);
+    mWriter->setLayerPlaneAlpha(1.0f);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SIDEBAND_STREAM) {
-  if (!mComposer->hasCapability(IComposer::Capability::SIDEBAND_STREAM)) {
-    GTEST_SUCCEED() << "no sideband stream support";
-    return;
-  }
+    if (!mComposer->hasCapability(IComposer::Capability::SIDEBAND_STREAM)) {
+        GTEST_SUCCEED() << "no sideband stream support";
+        return;
+    }
 
-  auto handle = allocate();
-  ASSERT_NE(nullptr, handle);
+    auto handle = allocate();
+    ASSERT_NE(nullptr, handle);
 
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerSidebandStream(handle);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerSidebandStream(handle);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_SOURCE_CROP.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SOURCE_CROP) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerSourceCrop(IComposerClient::FRect{0.0f, 0.0f, 1.0f, 1.0f});
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerSourceCrop(IComposerClient::FRect{0.0f, 0.0f, 1.0f, 1.0f});
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_TRANSFORM.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_TRANSFORM) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerTransform(static_cast<Transform>(0));
-  mWriter->setLayerTransform(Transform::FLIP_H);
-  mWriter->setLayerTransform(Transform::FLIP_V);
-  mWriter->setLayerTransform(Transform::ROT_90);
-  mWriter->setLayerTransform(Transform::ROT_180);
-  mWriter->setLayerTransform(Transform::ROT_270);
-  mWriter->setLayerTransform(
-      static_cast<Transform>(Transform::FLIP_H | Transform::ROT_90));
-  mWriter->setLayerTransform(
-      static_cast<Transform>(Transform::FLIP_V | Transform::ROT_90));
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerTransform(static_cast<Transform>(0));
+    mWriter->setLayerTransform(Transform::FLIP_H);
+    mWriter->setLayerTransform(Transform::FLIP_V);
+    mWriter->setLayerTransform(Transform::ROT_90);
+    mWriter->setLayerTransform(Transform::ROT_180);
+    mWriter->setLayerTransform(Transform::ROT_270);
+    mWriter->setLayerTransform(static_cast<Transform>(Transform::FLIP_H | Transform::ROT_90));
+    mWriter->setLayerTransform(static_cast<Transform>(Transform::FLIP_V | Transform::ROT_90));
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_VISIBLE_REGION.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_VISIBLE_REGION) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  IComposerClient::Rect empty{0, 0, 0, 0};
-  IComposerClient::Rect unit{0, 0, 1, 1};
+    IComposerClient::Rect empty{0, 0, 0, 0};
+    IComposerClient::Rect unit{0, 0, 1, 1};
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, empty));
-  mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, unit));
-  mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>());
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, empty));
+    mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, unit));
+    mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>());
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_Z_ORDER.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_Z_ORDER) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerZOrder(10);
-  mWriter->setLayerZOrder(0);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerZOrder(10);
+    mWriter->setLayerZOrder(0);
+    execute();
 }
 
-}  // namespace anonymous
-}  // namespace tests
+}  // namespace
+}  // namespace vts
 }  // namespace V2_1
 }  // namespace composer
 }  // namespace graphics
@@ -704,7 +693,7 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-    using android::hardware::graphics::composer::V2_1::tests::GraphicsComposerHidlEnvironment;
+    using android::hardware::graphics::composer::V2_1::vts::GraphicsComposerHidlEnvironment;
     ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
     GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
diff --git a/graphics/composer/2.2/default/Android.bp b/graphics/composer/2.2/default/Android.bp
new file mode 100644
index 0000000..906479e
--- /dev/null
+++ b/graphics/composer/2.2/default/Android.bp
@@ -0,0 +1,31 @@
+cc_binary {
+    name: "android.hardware.graphics.composer@2.2-service",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: ["service.cpp"],
+    init_rc: ["android.hardware.graphics.composer@2.2-service.rc"],
+    header_libs: [
+        "android.hardware.graphics.composer@2.2-passthrough",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.2",
+        "android.hardware.graphics.mapper@2.0",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libfmq",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwc2on1adapter",
+        "libhwc2onfbadapter",
+        "liblog",
+        "libsync",
+        "libutils",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"ComposerHal\""
+    ],
+}
diff --git a/graphics/composer/2.2/default/OWNERS b/graphics/composer/2.2/default/OWNERS
new file mode 100644
index 0000000..4714be2
--- /dev/null
+++ b/graphics/composer/2.2/default/OWNERS
@@ -0,0 +1,5 @@
+# Graphics team
+courtneygo@google.com
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
new file mode 100644
index 0000000..a41d902
--- /dev/null
+++ b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
@@ -0,0 +1,6 @@
+service vendor.hwcomposer-2-2 /vendor/bin/hw/android.hardware.graphics.composer@2.2-service
+    class hal animation
+    user system
+    group graphics drmrpc
+    capabilities SYS_NICE
+    onrestart restart surfaceflinger
diff --git a/graphics/composer/2.2/default/service.cpp b/graphics/composer/2.2/default/service.cpp
new file mode 100644
index 0000000..8c5ef18
--- /dev/null
+++ b/graphics/composer/2.2/default/service.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 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 <sched.h>
+
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <binder/ProcessState.h>
+#include <composer-passthrough/2.2/HwcLoader.h>
+#include <hidl/HidlTransportSupport.h>
+
+using android::hardware::graphics::composer::V2_2::IComposer;
+using android::hardware::graphics::composer::V2_2::passthrough::HwcLoader;
+
+int main() {
+    // the conventional HAL might start binder services
+    android::ProcessState::initWithDriver("/dev/vndbinder");
+    android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
+    android::ProcessState::self()->startThreadPool();
+
+    // same as SF main thread
+    struct sched_param param = {0};
+    param.sched_priority = 2;
+    if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO: %d", errno);
+    }
+
+    android::hardware::configureRpcThreadpool(4, true /* will join */);
+
+    android::sp<IComposer> composer = HwcLoader::load();
+    if (composer == nullptr) {
+        return 1;
+    }
+    if (composer->registerAsService() != android::NO_ERROR) {
+        ALOGE("failed to register service");
+        return 1;
+    }
+
+    android::hardware::joinRpcThreadpool();
+
+    ALOGE("service is terminating");
+    return 1;
+}
diff --git a/graphics/composer/2.2/utils/hal/Android.bp b/graphics/composer/2.2/utils/hal/Android.bp
new file mode 100644
index 0000000..10dcae4
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_headers {
+    name: "android.hardware.graphics.composer@2.2-hal",
+    defaults: ["hidl_defaults"],
+    vendor_available: true,
+    shared_libs: [
+        "android.hardware.graphics.composer@2.2",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.composer@2.2",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.2-command-buffer",
+        "android.hardware.graphics.composer@2.1-hal",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.2-command-buffer",
+        "android.hardware.graphics.composer@2.1-hal",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h
new file mode 100644
index 0000000..58bbaa5
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "Composer.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <composer-hal/2.1/Composer.h>
+#include <composer-hal/2.2/ComposerClient.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+namespace detail {
+
+// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerImpl : public V2_1::hal::detail::ComposerImpl<Interface, Hal> {
+   public:
+    static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) {
+        return std::make_unique<ComposerImpl>(std::move(hal));
+    }
+
+    ComposerImpl(std::unique_ptr<Hal> hal) : BaseType2_1(std::move(hal)) {}
+
+   protected:
+    V2_1::IComposerClient* createClient() override {
+        auto client = ComposerClient::create(mHal.get());
+        if (!client) {
+            return nullptr;
+        }
+
+        auto clientDestroyed = [this]() { onClientDestroyed(); };
+        client->setOnClientDestroyed(clientDestroyed);
+
+        return client.release();
+    }
+
+   private:
+    using BaseType2_1 = V2_1::hal::detail::ComposerImpl<Interface, Hal>;
+    using BaseType2_1::mHal;
+    using BaseType2_1::onClientDestroyed;
+};
+
+}  // namespace detail
+
+using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
+
+}  // namespace hal
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
new file mode 100644
index 0000000..d550f83
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerClient.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-hal/2.1/ComposerClient.h>
+#include <composer-hal/2.2/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-hal/2.2/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+namespace detail {
+
+// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerClientImpl : public V2_1::hal::detail::ComposerClientImpl<Interface, Hal> {
+   public:
+    static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
+        auto client = std::make_unique<ComposerClientImpl>(hal);
+        return client->init() ? std::move(client) : nullptr;
+    }
+
+    ComposerClientImpl(Hal* hal) : BaseType2_1(hal) {}
+
+    // IComposerClient 2.2 interface
+
+    Return<void> getPerFrameMetadataKeys(
+        Display display, IComposerClient::getPerFrameMetadataKeys_cb hidl_cb) override {
+        std::vector<IComposerClient::PerFrameMetadataKey> keys;
+        Error error = mHal->getPerFrameMetadataKeys(display, &keys);
+        hidl_cb(error, keys);
+        return Void();
+    }
+
+    Return<void> getReadbackBufferAttributes(
+        Display display, IComposerClient::getReadbackBufferAttributes_cb hidl_cb) override {
+        PixelFormat format = static_cast<PixelFormat>(0);
+        Dataspace dataspace = Dataspace::UNKNOWN;
+        Error error = mHal->getReadbackBufferAttributes(display, &format, &dataspace);
+        hidl_cb(error, format, dataspace);
+        return Void();
+    }
+
+    Return<void> getReadbackBufferFence(
+        Display display, IComposerClient::getReadbackBufferFence_cb hidl_cb) override {
+        base::unique_fd fenceFd;
+        Error error = mHal->getReadbackBufferFence(display, &fenceFd);
+        if (error != Error::NONE) {
+            hidl_cb(error, nullptr);
+            return Void();
+        }
+
+        NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+        hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
+        return Void();
+    }
+
+    Return<Error> setReadbackBuffer(Display display, const hidl_handle& buffer,
+                                    const hidl_handle& releaseFence) override {
+        base::unique_fd fenceFd;
+        Error error = getFenceFd(releaseFence, &fenceFd);
+        if (error != Error::NONE) {
+            return error;
+        }
+
+        auto resources = static_cast<ComposerResources*>(mResources.get());
+        const native_handle_t* readbackBuffer;
+        ComposerResources::ReplacedBufferHandle replacedReadbackBuffer;
+        error = resources->getDisplayReadbackBuffer(display, buffer.getNativeHandle(),
+                                                    &readbackBuffer, &replacedReadbackBuffer);
+        if (error != Error::NONE) {
+            return error;
+        }
+
+        return mHal->setReadbackBuffer(display, readbackBuffer, std::move(fenceFd));
+    }
+
+    Return<Error> setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
+        return mHal->setPowerMode_2_2(display, mode);
+    }
+
+   protected:
+    std::unique_ptr<V2_1::hal::ComposerResources> createResources() override {
+        return ComposerResources::create();
+    }
+
+    std::unique_ptr<V2_1::hal::ComposerCommandEngine> createCommandEngine() override {
+        return std::make_unique<ComposerCommandEngine>(
+            mHal, static_cast<ComposerResources*>(mResources.get()));
+    }
+
+    // convert fenceFd to or from hidl_handle
+    static Error getFenceFd(const hidl_handle& fenceHandle, base::unique_fd* outFenceFd) {
+        auto handle = fenceHandle.getNativeHandle();
+        if (handle && handle->numFds > 1) {
+            ALOGE("invalid fence handle with %d fds", handle->numFds);
+            return Error::BAD_PARAMETER;
+        }
+
+        int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+        if (fenceFd >= 0) {
+            fenceFd = dup(fenceFd);
+            if (fenceFd < 0) {
+                return Error::NO_RESOURCES;
+            }
+        }
+
+        outFenceFd->reset(fenceFd);
+
+        return Error::NONE;
+    }
+
+    static hidl_handle getFenceHandle(const base::unique_fd& fenceFd, char* handleStorage) {
+        native_handle_t* handle = nullptr;
+        if (fenceFd >= 0) {
+            handle = native_handle_init(handleStorage, 1, 0);
+            handle->data[0] = fenceFd;
+        }
+
+        return hidl_handle(handle);
+    }
+
+   private:
+    using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
+    using BaseType2_1::mHal;
+    using BaseType2_1::mResources;
+};
+
+}  // namespace detail
+
+using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
+
+}  // namespace hal
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
new file mode 100644
index 0000000..adcac46
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerCommandEngine.h included without LOG_TAG"
+#endif
+
+#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-hal/2.2/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+class ComposerCommandEngine : public V2_1::hal::ComposerCommandEngine {
+   public:
+    ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
+        : BaseType2_1(hal, resources), mHal(hal) {}
+
+   protected:
+    bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override {
+        switch (static_cast<IComposerClient::Command>(command)) {
+            case IComposerClient::Command::SET_PER_FRAME_METADATA:
+                return executeSetPerFrameMetadata(length);
+            case IComposerClient::Command::SET_LAYER_FLOAT_COLOR:
+                return executeSetLayerFloatColor(length);
+            default:
+                return BaseType2_1::executeCommand(command, length);
+        }
+    }
+
+    bool executeSetPerFrameMetadata(uint16_t length) {
+        // (key, value) pairs
+        if (length % 2 != 0) {
+            return false;
+        }
+
+        std::vector<IComposerClient::PerFrameMetadata> metadata;
+        metadata.reserve(length / 2);
+        while (length > 0) {
+            metadata.emplace_back(IComposerClient::PerFrameMetadata{
+                static_cast<IComposerClient::PerFrameMetadataKey>(readSigned()), readFloat()});
+            length -= 2;
+        }
+
+        auto err = mHal->setPerFrameMetadata(mCurrentDisplay, metadata);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerFloatColor(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerFloatColorLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerFloatColor(mCurrentDisplay, mCurrentLayer, readFloatColor());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    IComposerClient::FloatColor readFloatColor() {
+        return IComposerClient::FloatColor{readFloat(), readFloat(), readFloat(), readFloat()};
+    }
+
+   private:
+    using BaseType2_1 = V2_1::hal::ComposerCommandEngine;
+    using BaseType2_1::mWriter;
+
+    ComposerHal* mHal;
+};
+
+}  // namespace hal
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
new file mode 100644
index 0000000..30b3643
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 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/IComposer.h>
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-hal/2.1/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+using common::V1_0::Dataspace;
+using common::V1_0::PixelFormat;
+using V2_1::Display;
+using V2_1::Error;
+using V2_1::Layer;
+
+class ComposerHal : public V2_1::hal::ComposerHal {
+   public:
+    // superceded by setPowerMode_2_2
+    Error setPowerMode(Display display, V2_1::IComposerClient::PowerMode mode) override {
+        return setPowerMode_2_2(display, static_cast<IComposerClient::PowerMode>(mode));
+    }
+
+    virtual Error getPerFrameMetadataKeys(
+        Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) = 0;
+    virtual Error setPerFrameMetadata(
+        Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) = 0;
+
+    virtual Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat,
+                                              Dataspace* outDataspace) = 0;
+    virtual Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle,
+                                    base::unique_fd fenceFd) = 0;
+    virtual Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) = 0;
+
+    virtual Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) = 0;
+
+    virtual Error setLayerFloatColor(Display display, Layer layer,
+                                     IComposerClient::FloatColor color) = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h
new file mode 100644
index 0000000..85b6651
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerResources.h included without LOG_TAG"
+#endif
+
+#include <composer-hal/2.1/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+using V2_1::hal::ComposerHandleCache;
+using V2_1::hal::ComposerHandleImporter;
+
+class ComposerDisplayResource : public V2_1::hal::ComposerDisplayResource {
+   public:
+    ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+                            uint32_t outputBufferCacheSize)
+        : V2_1::hal::ComposerDisplayResource(type, importer, outputBufferCacheSize),
+          mReadbackBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, 1) {}
+
+    Error getReadbackBuffer(const native_handle_t* inHandle, const native_handle_t** outHandle,
+                            const native_handle** outReplacedHandle) {
+        const uint32_t slot = 0;
+        const bool fromCache = false;
+        return mReadbackBufferCache.getHandle(slot, fromCache, inHandle, outHandle,
+                                              outReplacedHandle);
+    }
+
+   protected:
+    ComposerHandleCache mReadbackBufferCache;
+};
+
+class ComposerResources : public V2_1::hal::ComposerResources {
+   public:
+    static std::unique_ptr<ComposerResources> create() {
+        auto resources = std::make_unique<ComposerResources>();
+        return resources->init() ? std::move(resources) : nullptr;
+    }
+
+    Error getDisplayReadbackBuffer(Display display, const native_handle_t* rawHandle,
+                                   const native_handle_t** outHandle,
+                                   ReplacedBufferHandle* outReplacedHandle) {
+        // import buffer
+        const native_handle_t* importedHandle;
+        Error error = mImporter.importBuffer(rawHandle, &importedHandle);
+        if (error != Error::NONE) {
+            return error;
+        }
+
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+
+        auto iter = mDisplayResources.find(display);
+        if (iter == mDisplayResources.end()) {
+            mImporter.freeBuffer(importedHandle);
+            return Error::BAD_DISPLAY;
+        }
+        ComposerDisplayResource& displayResource =
+            *static_cast<ComposerDisplayResource*>(iter->second.get());
+
+        // update cache
+        const native_handle_t* replacedHandle;
+        error = displayResource.getReadbackBuffer(importedHandle, outHandle, &replacedHandle);
+        if (error != Error::NONE) {
+            mImporter.freeBuffer(importedHandle);
+            return error;
+        }
+
+        outReplacedHandle->reset(&mImporter, replacedHandle);
+        return Error::NONE;
+    }
+
+   protected:
+    std::unique_ptr<V2_1::hal::ComposerDisplayResource> createDisplayResource(
+        ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) override {
+        return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
+    }
+};
+
+}  // namespace hal
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/passthrough/Android.bp b/graphics/composer/2.2/utils/passthrough/Android.bp
new file mode 100644
index 0000000..318ce91
--- /dev/null
+++ b/graphics/composer/2.2/utils/passthrough/Android.bp
@@ -0,0 +1,14 @@
+cc_library_headers {
+    name: "android.hardware.graphics.composer@2.2-passthrough",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-passthrough",
+        "android.hardware.graphics.composer@2.2-hal",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-passthrough",
+        "android.hardware.graphics.composer@2.2-hal",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
new file mode 100644
index 0000000..b251351
--- /dev/null
+++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "HwcHal.h included without LOG_TAG"
+#endif
+
+#include <type_traits>
+
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-passthrough/2.1/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace passthrough {
+
+namespace detail {
+
+using common::V1_0::Dataspace;
+using common::V1_0::PixelFormat;
+using V2_1::Display;
+using V2_1::Error;
+using V2_1::Layer;
+
+// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
+template <typename Hal>
+class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> {
+   public:
+    // XXX when can we return Error::UNSUPPORTED?
+
+    Error getPerFrameMetadataKeys(
+        Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) override {
+        if (!mDispatch.getPerFrameMetadataKeys) {
+            return Error::UNSUPPORTED;
+        }
+
+        uint32_t count = 0;
+        int32_t error = mDispatch.getPerFrameMetadataKeys(mDevice, display, &count, nullptr);
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+
+        std::vector<IComposerClient::PerFrameMetadataKey> keys(count);
+        error = mDispatch.getPerFrameMetadataKeys(
+            mDevice, display, &count,
+            reinterpret_cast<std::underlying_type<IComposerClient::PerFrameMetadataKey>::type*>(
+                keys.data()));
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+
+        keys.resize(count);
+        *outKeys = std::move(keys);
+        return Error::NONE;
+    }
+
+    Error setPerFrameMetadata(
+        Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) override {
+        if (!mDispatch.setPerFrameMetadata) {
+            return Error::UNSUPPORTED;
+        }
+
+        std::vector<int32_t> keys;
+        std::vector<float> values;
+        keys.reserve(metadata.size());
+        values.reserve(metadata.size());
+        for (const auto& m : metadata) {
+            keys.push_back(static_cast<int32_t>(m.key));
+            values.push_back(m.value);
+        }
+
+        int32_t error = mDispatch.setPerFrameMetadata(mDevice, display, metadata.size(),
+                                                      keys.data(), values.data());
+        return static_cast<Error>(error);
+    }
+
+    Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat,
+                                      Dataspace* outDataspace) override {
+        if (!mDispatch.getReadbackBufferAttributes) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t format = 0;
+        int32_t dataspace = 0;
+        int32_t error =
+            mDispatch.getReadbackBufferAttributes(mDevice, display, &format, &dataspace);
+        if (error == HWC2_ERROR_NONE) {
+            *outFormat = static_cast<PixelFormat>(format);
+            *outDataspace = static_cast<Dataspace>(dataspace);
+        }
+        return static_cast<Error>(error);
+    }
+
+    Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle,
+                            base::unique_fd fenceFd) override {
+        if (!mDispatch.setReadbackBuffer) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t error =
+            mDispatch.setReadbackBuffer(mDevice, display, bufferHandle, fenceFd.release());
+        return static_cast<Error>(error);
+    }
+
+    Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) override {
+        if (!mDispatch.getReadbackBufferFence) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t fenceFd = -1;
+        int32_t error = mDispatch.getReadbackBufferFence(mDevice, display, &fenceFd);
+        outFenceFd->reset(fenceFd);
+        return static_cast<Error>(error);
+    }
+
+    Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
+        if (mode == IComposerClient::PowerMode::ON_SUSPEND) {
+            return Error::UNSUPPORTED;
+        }
+        return setPowerMode(display, static_cast<V2_1::IComposerClient::PowerMode>(mode));
+    }
+
+    Error setLayerFloatColor(Display display, Layer layer,
+                             IComposerClient::FloatColor color) override {
+        if (!mDispatch.setLayerFloatColor) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t error = mDispatch.setLayerFloatColor(
+            mDevice, display, layer, hwc_float_color{color.r, color.g, color.b, color.a});
+        return static_cast<Error>(error);
+    }
+
+   protected:
+    template <typename T>
+    bool initOptionalDispatch(hwc2_function_descriptor_t desc, T* outPfn) {
+        auto pfn = mDevice->getFunction(mDevice, desc);
+        if (pfn) {
+            *outPfn = reinterpret_cast<T>(pfn);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    bool initDispatch() override {
+        if (!BaseType2_1::initDispatch()) {
+            return false;
+        }
+
+        initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_FLOAT_COLOR, &mDispatch.setLayerFloatColor);
+
+        initOptionalDispatch(HWC2_FUNCTION_SET_PER_FRAME_METADATA, &mDispatch.setPerFrameMetadata);
+        initOptionalDispatch(HWC2_FUNCTION_GET_PER_FRAME_METADATA_KEYS,
+                             &mDispatch.getPerFrameMetadataKeys);
+
+        initOptionalDispatch(HWC2_FUNCTION_SET_READBACK_BUFFER, &mDispatch.setReadbackBuffer);
+        initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_ATTRIBUTES,
+                             &mDispatch.getReadbackBufferAttributes);
+        initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_FENCE,
+                             &mDispatch.getReadbackBufferFence);
+
+        return true;
+    }
+
+    struct {
+        HWC2_PFN_SET_LAYER_FLOAT_COLOR setLayerFloatColor;
+        HWC2_PFN_SET_PER_FRAME_METADATA setPerFrameMetadata;
+        HWC2_PFN_GET_PER_FRAME_METADATA_KEYS getPerFrameMetadataKeys;
+        HWC2_PFN_SET_READBACK_BUFFER setReadbackBuffer;
+        HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES getReadbackBufferAttributes;
+        HWC2_PFN_GET_READBACK_BUFFER_FENCE getReadbackBufferFence;
+    } mDispatch = {};
+
+   private:
+    using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+    using BaseType2_1::mDevice;
+    using BaseType2_1::setPowerMode;
+};
+
+}  // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+}  // namespace passthrough
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h
new file mode 100644
index 0000000..cb4a238
--- /dev/null
+++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "HwcLoader.h included without LOG_TAG"
+#endif
+
+#include <composer-hal/2.2/Composer.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-passthrough/2.1/HwcLoader.h>
+#include <composer-passthrough/2.2/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace passthrough {
+
+class HwcLoader : public V2_1::passthrough::HwcLoader {
+   public:
+    static IComposer* load() {
+        const hw_module_t* module = loadModule();
+        if (!module) {
+            return nullptr;
+        }
+
+        auto hal = createHalWithAdapter(module);
+        if (!hal) {
+            return nullptr;
+        }
+
+        return createComposer(std::move(hal)).release();
+    }
+
+    // create a ComposerHal instance
+    static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) {
+        auto hal = std::make_unique<HwcHal>();
+        return hal->initWithModule(module) ? std::move(hal) : nullptr;
+    }
+
+    // create a ComposerHal instance, insert an adapter if necessary
+    static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) {
+        bool adapted;
+        hwc2_device_t* device = openDeviceWithAdapter(module, &adapted);
+        if (!device) {
+            return nullptr;
+        }
+        auto hal = std::make_unique<HwcHal>();
+        return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr;
+    }
+
+    // create an IComposer instance
+    static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) {
+        return hal::Composer::create(std::move(hal));
+    }
+};
+
+}  // namespace passthrough
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
new file mode 100644
index 0000000..641fdcb
--- /dev/null
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "android.hardware.graphics.composer@2.2-vts",
+    defaults: ["hidl_defaults"],
+    srcs: [
+        "ComposerVts.cpp",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.1-vts",
+        "android.hardware.graphics.composer@2.2",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+        "android.hardware.graphics.composer@2.2-command-buffer",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+        "-DLOG_TAG=\"ComposerVts\"",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
similarity index 96%
rename from graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
rename to graphics/composer/2.2/utils/vts/ComposerVts.cpp
index 00946ce..b536f67 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <hidl/HidlTransportUtils.h>
+#include <composer-vts/2.2/ComposerVts.h>
 
+#include <VtsHalHidlTargetTestBase.h>
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
-#include "2.2/VtsHalGraphicsComposerTestUtils.h"
+#include <hidl/HidlTransportUtils.h>
 
 namespace android {
 namespace hardware {
 namespace graphics {
 namespace composer {
 namespace V2_2 {
-namespace tests {
+namespace vts {
 
-using android::hardware::graphics::composer::V2_2::IComposerClient;
-using android::hardware::details::getDescriptor;
 using android::hardware::details::canCastInterface;
+using android::hardware::details::getDescriptor;
+using android::hardware::graphics::composer::V2_2::IComposerClient;
 
 std::unique_ptr<ComposerClient_v2_2> Composer_v2_2::createClient_v2_2() {
     std::unique_ptr<ComposerClient_v2_2> client;
@@ -56,7 +56,7 @@
     return keys;
 }
 
-void ComposerClient_v2_2::execute_v2_2(V2_1::tests::TestCommandReader* reader,
+void ComposerClient_v2_2::execute_v2_2(V2_1::vts::TestCommandReader* reader,
                                        V2_2::CommandWriterBase* writer) {
     bool queueChanged = false;
     uint32_t commandLength = 0;
@@ -119,7 +119,7 @@
     *outFence = 0;
 }
 
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
 }  // namespace graphics
diff --git a/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
similarity index 82%
rename from graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h
rename to graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index c5756ed..eced69f 100644
--- a/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -22,11 +22,11 @@
 #include <unordered_set>
 #include <vector>
 
-#include <VtsHalGraphicsComposerTestUtils.h>
 #include <VtsHalHidlTargetTestBase.h>
 #include <android/hardware/graphics/composer/2.2/IComposer.h>
 #include <android/hardware/graphics/composer/2.2/IComposerClient.h>
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/ComposerVts.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
@@ -34,7 +34,7 @@
 namespace graphics {
 namespace composer {
 namespace V2_2 {
-namespace tests {
+namespace vts {
 
 using android::hardware::graphics::common::V1_0::ColorMode;
 using android::hardware::graphics::common::V1_0::Dataspace;
@@ -47,22 +47,22 @@
 
 // Only thing I need for Composer_v2_2 is to create a v2_2 ComposerClient
 // Everything else is the same
-class Composer_v2_2 : public V2_1::tests::Composer {
+class Composer_v2_2 : public V2_1::vts::Composer {
    public:
-    Composer_v2_2() : V2_1::tests::Composer(){};
-    explicit Composer_v2_2(const std::string& name) : V2_1::tests::Composer(name){};
+    Composer_v2_2() : V2_1::vts::Composer(){};
+    explicit Composer_v2_2(const std::string& name) : V2_1::vts::Composer(name){};
 
     std::unique_ptr<ComposerClient_v2_2> createClient_v2_2();
 };
 
 // A wrapper to IComposerClient.
 class ComposerClient_v2_2
-    : public android::hardware::graphics::composer::V2_1::tests::ComposerClient {
+    : public android::hardware::graphics::composer::V2_1::vts::ComposerClient {
    public:
     ComposerClient_v2_2(const sp<IComposerClient>& client)
-        : V2_1::tests::ComposerClient(client), mClient_v2_2(client){};
+        : V2_1::vts::ComposerClient(client), mClient_v2_2(client){};
 
-    void execute_v2_2(V2_1::tests::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
+    void execute_v2_2(V2_1::vts::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
 
     std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display);
 
@@ -76,7 +76,7 @@
     sp<V2_2::IComposerClient> mClient_v2_2;
 };
 
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
 }  // namespace graphics
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 78322a1..7747900 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -14,37 +14,6 @@
 // limitations under the License.
 //
 
-cc_library_static {
-    name: "libVtsHalGraphicsComposerTestUtils@2.2",
-    defaults: ["hidl_defaults"],
-    srcs: [
-        "VtsHalGraphicsComposerTestUtils.cpp",
-    ],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.composer@2.2",
-        "libfmq",
-        "libsync",
-    ],
-    static_libs: [
-        "libVtsHalGraphicsComposerTestUtils",
-        "VtsHalHidlTargetTestBase",
-    ],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
-        "android.hardware.graphics.composer@2.2-command-buffer",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-        "-DLOG_TAG=\"GraphicsComposerTestUtils@2.2\"",
-    ],
-    export_include_dirs: ["include"],
-}
-
 cc_test {
     name: "VtsHalGraphicsComposerV2_2TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
@@ -58,14 +27,13 @@
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.composer@2.2",
         "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.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
         "android.hardware.graphics.mapper@2.1",
-        "libVtsHalGraphicsComposerTestUtils",
-        "libVtsHalGraphicsComposerTestUtils@2.2",
-        "libnativehelper",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 6fbdd3c..c494329 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -16,23 +16,20 @@
 
 #define LOG_TAG "graphics_composer_hidl_hal_test@2.2"
 
+#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/graphics/mapper/2.1/IMapper.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.0/MapperVts.h>
-#include <sync/sync.h>
-#include "2.2/VtsHalGraphicsComposerTestUtils.h"
-#include "GraphicsComposerCallback.h"
-#include "TestCommandReader.h"
-#include "VtsHalGraphicsComposerTestUtils.h"
-
-#include <VtsHalHidlTargetTestBase.h>
 
 namespace android {
 namespace hardware {
 namespace graphics {
 namespace composer {
 namespace V2_2 {
-namespace tests {
+namespace vts {
 namespace {
 
 using android::hardware::graphics::common::V1_0::BufferUsage;
@@ -71,7 +68,7 @@
                 GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
         ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient_v2_2());
 
-        mComposerCallback = new V2_1::tests::GraphicsComposerCallback;
+        mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
         mComposerClient->registerCallback(mComposerCallback);
 
         // assume the first display is primary and is never removed
@@ -95,7 +92,7 @@
 
     std::unique_ptr<Composer_v2_2> mComposer;
     std::unique_ptr<ComposerClient_v2_2> mComposerClient;
-    sp<V2_1::tests::GraphicsComposerCallback> mComposerCallback;
+    sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
     // the first display and is assumed never to be removed
     Display mPrimaryDisplay;
 
@@ -122,7 +119,7 @@
         ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
 
         mWriter = std::make_unique<V2_2::CommandWriterBase>(1024);
-        mReader = std::make_unique<V2_1::tests::TestCommandReader>();
+        mReader = std::make_unique<V2_1::vts::TestCommandReader>();
     }
 
     void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); }
@@ -142,7 +139,7 @@
     void execute() { mComposerClient->execute_v2_2(mReader.get(), mWriter.get()); }
 
     std::unique_ptr<V2_2::CommandWriterBase> mWriter;
-    std::unique_ptr<V2_1::tests::TestCommandReader> mReader;
+    std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
 
    private:
     std::unique_ptr<Gralloc> mGralloc;
@@ -239,7 +236,7 @@
 }
 
 }  // namespace
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
 }  // namespace graphics
@@ -247,7 +244,7 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-    using android::hardware::graphics::composer::V2_2::tests::GraphicsComposerHidlEnvironment;
+    using android::hardware::graphics::composer::V2_2::vts::GraphicsComposerHidlEnvironment;
     ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
     GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);