diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index a317ea2..89779af 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -25,8 +25,6 @@
     DisplayHardware/ComposerHal.cpp \
     DisplayHardware/FramebufferSurface.cpp \
     DisplayHardware/HWC2.cpp \
-    DisplayHardware/HWC2On1Adapter.cpp \
-    DisplayHardware/MiniFence.cpp \
     DisplayHardware/PowerHAL.cpp \
     DisplayHardware/VirtualDisplaySurface.cpp \
     Effects/Daltonizer.cpp \
@@ -152,6 +150,7 @@
     libdl \
     libfmq \
     libhardware \
+    libhwc2on1adapter \
     libhidlbase \
     libhidltransport \
     libhwbinder \
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
deleted file mode 100644
index 13bf0b5..0000000
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ /dev/null
@@ -1,2596 +0,0 @@
-/*
- * 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.
- */
-
-//#define LOG_NDEBUG 0
-
-#undef LOG_TAG
-#define LOG_TAG "HWC2On1Adapter"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "HWC2On1Adapter.h"
-
-#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*>);
-
-        // 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;
-    }
-
-    if (MAX_VIRTUAL_DISPLAY_DIMENSION != 0 &&
-            (width > MAX_VIRTUAL_DISPLAY_DIMENSION ||
-            height > MAX_VIRTUAL_DISPLAY_DIMENSION)) {
-        ALOGE("createVirtualDisplay: Can't create a virtual display with"
-                " a dimension > %u (tried %u x %u)",
-                MAX_VIRTUAL_DISPLAY_DIMENSION, width, height);
-        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);
-
-    mCallbacks[descriptor] = {callbackData, pointer};
-
-    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;
-        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;
-}
-
-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;
-}
-
-Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t visible) {
-    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;
-        }
-    }
-}
-
-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/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
deleted file mode 100644
index a1d2c88..0000000
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- * 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);
-
-            // 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/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index f03491f..e1138af 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -47,7 +47,7 @@
 #include <log/log.h>
 
 #include "HWComposer.h"
-#include "HWC2On1Adapter.h"
+#include "hwc2on1adapter/HWC2On1Adapter.h"
 #include "HWC2.h"
 #include "ComposerHal.h"
 
@@ -267,6 +267,15 @@
         return NO_MEMORY;
     }
 
+    if (MAX_VIRTUAL_DISPLAY_DIMENSION != 0 &&
+        (width > MAX_VIRTUAL_DISPLAY_DIMENSION ||
+         height > MAX_VIRTUAL_DISPLAY_DIMENSION)) {
+        ALOGE("createVirtualDisplay: Can't create a virtual display with"
+                      " a dimension > %u (tried %u x %u)",
+              MAX_VIRTUAL_DISPLAY_DIMENSION, width, height);
+        return INVALID_OPERATION;
+    }
+
     std::shared_ptr<HWC2::Display> display;
     auto error = mHwcDevice->createVirtualDisplay(width, height, format,
             &display);
diff --git a/services/surfaceflinger/DisplayHardware/MiniFence.cpp b/services/surfaceflinger/DisplayHardware/MiniFence.cpp
deleted file mode 100644
index ecfb063..0000000
--- a/services/surfaceflinger/DisplayHardware/MiniFence.cpp
+++ /dev/null
@@ -1,42 +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 "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/services/surfaceflinger/DisplayHardware/MiniFence.h b/services/surfaceflinger/DisplayHardware/MiniFence.h
deleted file mode 100644
index 75de764..0000000
--- a/services/surfaceflinger/DisplayHardware/MiniFence.h
+++ /dev/null
@@ -1,59 +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 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
