Switch SurfaceFlinger to HWC 2.0

Enables SurfaceFlinger to speak to version 2.0 of the Hardware Composer
HAL instead of version 1.x (also removing support for the framebuffer
HAL). By default, however, this functionality is disabled. In order to
enable it, USE_HWC2 must be set to true in Android.mk.

Change-Id: I4589e02ac2165236b10ff2f7cb772f87e0d3daab
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index 2f743c1..d819f83 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -49,11 +49,13 @@
     };
     virtual status_t prepareFrame(CompositionType compositionType) = 0;
 
+#ifndef USE_HWC2
     // Should be called when composition rendering is complete for a frame (but
     // eglSwapBuffers hasn't necessarily been called). Required by certain
     // older drivers for synchronization.
     // TODO: Remove this when we drop support for HWC 1.0.
     virtual status_t compositionComplete() = 0;
+#endif
 
     // Inform the surface that GLES composition is complete for this frame, and
     // the surface should make sure that HWComposer has the correct buffer for
@@ -74,6 +76,10 @@
 
     virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
 
+#ifdef USE_HWC2
+    virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
+#endif
+
 protected:
     DisplaySurface() {}
     virtual ~DisplaySurface() {}
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index a6bc158..29e0766 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -15,6 +15,10 @@
  ** limitations under the License.
  */
 
+// #define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "FramebufferSurface"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -56,16 +60,35 @@
     ConsumerBase(consumer),
     mDisplayType(disp),
     mCurrentBufferSlot(-1),
+#ifdef USE_HWC2
+    mCurrentBuffer(),
+    mCurrentFence(Fence::NO_FENCE),
+    mHwc(hwc),
+    mHasPendingRelease(false),
+    mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
+    mPreviousBuffer()
+#else
     mCurrentBuffer(0),
     mHwc(hwc)
+#endif
 {
+#ifdef USE_HWC2
+    ALOGV("Creating for display %d", disp);
+#endif
+
     mName = "FramebufferSurface";
     mConsumer->setConsumerName(mName);
     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
                                        GRALLOC_USAGE_HW_RENDER |
                                        GRALLOC_USAGE_HW_COMPOSER);
+#ifdef USE_HWC2
+    const auto& activeConfig = mHwc.getActiveConfig(disp);
+    mConsumer->setDefaultBufferSize(activeConfig->getWidth(),
+            activeConfig->getHeight());
+#else
     mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
-    mConsumer->setDefaultBufferSize(mHwc.getWidth(disp),  mHwc.getHeight(disp));
+    mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
+#endif
     mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1);
 }
 
@@ -78,13 +101,35 @@
 }
 
 status_t FramebufferSurface::advanceFrame() {
+#ifdef USE_HWC2
+    sp<GraphicBuffer> buf;
+    sp<Fence> acquireFence(Fence::NO_FENCE);
+    android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
+    status_t result = nextBuffer(buf, acquireFence, dataspace);
+    if (result != NO_ERROR) {
+        ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
+                strerror(-result), result);
+        return result;
+    }
+    result = mHwc.setClientTarget(mDisplayType, acquireFence, buf, dataspace);
+    if (result != NO_ERROR) {
+        ALOGE("error posting framebuffer: %d", result);
+    }
+    return result;
+#else
     // Once we remove FB HAL support, we can call nextBuffer() from here
     // instead of using onFrameAvailable(). No real benefit, except it'll be
     // more like VirtualDisplaySurface.
     return NO_ERROR;
+#endif
 }
 
+#ifdef USE_HWC2
+status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer,
+        sp<Fence>& outFence, android_dataspace_t& outDataspace) {
+#else
 status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
+#endif
     Mutex::Autolock lock(mMutex);
 
     BufferItem item;
@@ -107,6 +152,11 @@
     // had released the old buffer first.
     if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
         item.mSlot != mCurrentBufferSlot) {
+#ifdef USE_HWC2
+        mHasPendingRelease = true;
+        mPreviousBufferSlot = mCurrentBufferSlot;
+        mPreviousBuffer = mCurrentBuffer;
+#else
         // Release the previous buffer.
         err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
@@ -114,14 +164,23 @@
             ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
             return err;
         }
+#endif
     }
     mCurrentBufferSlot = item.mSlot;
     mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
+#ifdef USE_HWC2
+    mCurrentFence = item.mFence;
+#endif
+
     outFence = item.mFence;
     outBuffer = mCurrentBuffer;
+#ifdef USE_HWC2
+    outDataspace = item.mDataSpace;
+#endif
     return NO_ERROR;
 }
 
+#ifndef USE_HWC2
 // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
 void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
     sp<GraphicBuffer> buf;
@@ -137,6 +196,7 @@
         ALOGE("error posting framebuffer: %d", err);
     }
 }
+#endif
 
 void FramebufferSurface::freeBufferLocked(int slotIndex) {
     ConsumerBase::freeBufferLocked(slotIndex);
@@ -146,6 +206,24 @@
 }
 
 void FramebufferSurface::onFrameCommitted() {
+#ifdef USE_HWC2
+    if (mHasPendingRelease) {
+        sp<Fence> fence = mHwc.getRetireFence(mDisplayType);
+        if (fence->isValid()) {
+            status_t result = addReleaseFence(mPreviousBufferSlot,
+                    mPreviousBuffer, fence);
+            ALOGE_IF(result != NO_ERROR, "onFrameCommitted: failed to add the"
+                    " fence: %s (%d)", strerror(-result), result);
+        }
+        status_t result = releaseBufferLocked(mPreviousBufferSlot,
+                mPreviousBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+        ALOGE_IF(result != NO_ERROR, "onFrameCommitted: error releasing buffer:"
+                " %s (%d)", strerror(-result), result);
+
+        mPreviousBuffer.clear();
+        mHasPendingRelease = false;
+    }
+#else
     sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
     if (fence->isValid() &&
             mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
@@ -154,12 +232,15 @@
         ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
                 strerror(-err), err);
     }
+#endif
 }
 
+#ifndef USE_HWC2
 status_t FramebufferSurface::compositionComplete()
 {
     return mHwc.fbCompositionComplete();
 }
+#endif
 
 void FramebufferSurface::dumpAsString(String8& result) const {
     ConsumerBase::dump(result);
@@ -167,10 +248,18 @@
 
 void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
 {
+#ifndef USE_HWC2
     mHwc.fbDump(result);
+#endif
     ConsumerBase::dumpLocked(result, prefix);
 }
 
+#ifdef USE_HWC2
+const sp<Fence>& FramebufferSurface::getClientTargetAcquireFence() const {
+    return mCurrentFence;
+}
+#endif
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 3d17840..0605602 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -41,7 +41,9 @@
 
     virtual status_t beginFrame(bool mustRecompose);
     virtual status_t prepareFrame(CompositionType compositionType);
+#ifndef USE_HWC2
     virtual status_t compositionComplete();
+#endif
     virtual status_t advanceFrame();
     virtual void onFrameCommitted();
     virtual void dumpAsString(String8& result) const;
@@ -50,10 +52,16 @@
     // displays.
     virtual void resizeBuffers(const uint32_t /*w*/, const uint32_t /*h*/) { };
 
+#ifdef USE_HWC2
+    virtual const sp<Fence>& getClientTargetAcquireFence() const override;
+#endif
+
 private:
     virtual ~FramebufferSurface() { }; // this class cannot be overloaded
 
+#ifndef USE_HWC2
     virtual void onFrameAvailable(const BufferItem& item);
+#endif
     virtual void freeBufferLocked(int slotIndex);
 
     virtual void dumpLocked(String8& result, const char* prefix) const;
@@ -61,7 +69,12 @@
     // nextBuffer waits for and then latches the next buffer from the
     // BufferQueue and releases the previously latched buffer to the
     // BufferQueue.  The new buffer is returned in the 'buffer' argument.
+#ifdef USE_HWC2
+    status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,
+            android_dataspace_t& outDataspace);
+#else
     status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence);
+#endif
 
     // mDisplayType must match one of the HWC display types
     int mDisplayType;
@@ -75,8 +88,20 @@
     // no current buffer.
     sp<GraphicBuffer> mCurrentBuffer;
 
+#ifdef USE_HWC2
+    // mCurrentFence is the current buffer's acquire fence
+    sp<Fence> mCurrentFence;
+#endif
+
     // Hardware composer, owned by SurfaceFlinger.
     HWComposer& mHwc;
+
+#ifdef USE_HWC2
+    // Previous buffer to release after getting an updated retire fence
+    bool mHasPendingRelease;
+    int mPreviousBufferSlot;
+    sp<GraphicBuffer> mPreviousBuffer;
+#endif
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index d37fcb2..26f9519 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+// #define LOG_NDEBUG 0
+
+#undef LOG_TAG
+#define LOG_TAG "HWComposer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <inttypes.h>
@@ -43,6 +47,8 @@
 #include <cutils/properties.h>
 
 #include "HWComposer.h"
+#include "HWC2On1Adapter.h"
+#include "HWC2.h"
 
 #include "../Layer.h"           // needed only for debugging
 #include "../SurfaceFlinger.h"
@@ -51,1088 +57,688 @@
 
 #define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
 
-static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
-    uint32_t hwcVersion = hwc->common.version;
-    return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
-}
-
-static uint32_t hwcHeaderVersion(const hwc_composer_device_1_t* hwc) {
-    uint32_t hwcVersion = hwc->common.version;
-    return hwcVersion & HARDWARE_API_VERSION_2_HEADER_MASK;
-}
-
-static bool hwcHasApiVersion(const hwc_composer_device_1_t* hwc,
-        uint32_t version) {
-    return hwcApiVersion(hwc) >= (version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK);
-}
-
 // ---------------------------------------------------------------------------
 
-struct HWComposer::cb_context {
-    struct callbacks : public hwc_procs_t {
-        // these are here to facilitate the transition when adding
-        // new callbacks (an implementation can check for NULL before
-        // calling a new callback).
-        void (*zero[4])(void);
-    };
-    callbacks procs;
-    HWComposer* hwc;
-};
-
-// ---------------------------------------------------------------------------
-
-HWComposer::HWComposer(
-        const sp<SurfaceFlinger>& flinger,
-        EventHandler& handler)
+HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger)
     : mFlinger(flinger),
-      mFbDev(0), mHwc(0), mNumDisplays(1),
-      mCBContext(new cb_context),
-      mEventHandler(handler),
-      mDebugForceFakeVSync(false)
+      mAdapter(),
+      mHwcDevice(),
+      mDisplayData(2),
+      mFreeDisplaySlots(),
+      mHwcDisplaySlots(),
+      mCBContext(),
+      mEventHandler(nullptr),
+      mVSyncCounts(),
+      mRemainingHwcVirtualDisplays(0)
 {
-    for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
-        mLists[i] = 0;
-    }
-
     for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
         mLastHwVSync[i] = 0;
         mVSyncCounts[i] = 0;
     }
 
-    char value[PROPERTY_VALUE_MAX];
-    property_get("debug.sf.no_hw_vsync", value, "0");
-    mDebugForceFakeVSync = atoi(value);
-
-    bool needVSyncThread = true;
-
-    // Note: some devices may insist that the FB HAL be opened before HWC.
-    int fberr = loadFbHalModule();
     loadHwcModule();
-
-    if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        // close FB HAL if we don't needed it.
-        // FIXME: this is temporary until we're not forced to open FB HAL
-        // before HWC.
-        framebuffer_close(mFbDev);
-        mFbDev = NULL;
-    }
-
-    // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
-    if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
-            && !mFbDev) {
-        ALOGE("ERROR: failed to open framebuffer (%s), aborting",
-                strerror(-fberr));
-        abort();
-    }
-
-    // these display IDs are always reserved
-    for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
-        mAllocatedDisplayIDs.markBit(i);
-    }
-
-    if (mHwc) {
-        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
-              (hwcApiVersion(mHwc) >> 24) & 0xff,
-              (hwcApiVersion(mHwc) >> 16) & 0xff);
-        if (mHwc->registerProcs) {
-            mCBContext->hwc = this;
-            mCBContext->procs.invalidate = &hook_invalidate;
-            mCBContext->procs.vsync = &hook_vsync;
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
-                mCBContext->procs.hotplug = &hook_hotplug;
-            else
-                mCBContext->procs.hotplug = NULL;
-            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
-            mHwc->registerProcs(mHwc, &mCBContext->procs);
-        }
-
-        // don't need a vsync thread if we have a hardware composer
-        needVSyncThread = false;
-        // always turn vsync off when we start
-        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
-
-        // the number of displays we actually have depends on the
-        // hw composer version
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-            // 1.3 adds support for virtual displays
-            mNumDisplays = MAX_HWC_DISPLAYS;
-        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            // 1.1 adds support for multiple displays
-            mNumDisplays = NUM_BUILTIN_DISPLAYS;
-        } else {
-            mNumDisplays = 1;
-        }
-    }
-
-    if (mFbDev) {
-        ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
-                "should only have fbdev if no hwc or hwc is 1.0");
-
-        DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
-        disp.connected = true;
-        disp.format = mFbDev->format;
-        DisplayConfig config = DisplayConfig();
-        config.width = mFbDev->width;
-        config.height = mFbDev->height;
-        config.xdpi = mFbDev->xdpi;
-        config.ydpi = mFbDev->ydpi;
-        config.refresh = nsecs_t(1e9 / mFbDev->fps);
-        disp.configs.push_back(config);
-        disp.currentConfig = 0;
-    } else if (mHwc) {
-        // here we're guaranteed to have at least HWC 1.1
-        for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
-            queryDisplayProperties(i);
-        }
-    }
-
-    if (needVSyncThread) {
-        // we don't have VSYNC support, we need to fake it
-        mVSyncThread = new VSyncThread(*this);
-    }
 }
 
-HWComposer::~HWComposer() {
-    if (mHwc) {
-        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
+HWComposer::~HWComposer() {}
+
+void HWComposer::setEventHandler(EventHandler* handler)
+{
+    if (handler == nullptr) {
+        ALOGE("setEventHandler: Rejected attempt to clear handler");
+        return;
     }
-    if (mVSyncThread != NULL) {
-        mVSyncThread->requestExitAndWait();
+
+    bool wasNull = (mEventHandler == nullptr);
+    mEventHandler = handler;
+
+    if (wasNull) {
+        auto hotplugHook = std::bind(&HWComposer::hotplug, this,
+                std::placeholders::_1, std::placeholders::_2);
+        mHwcDevice->registerHotplugCallback(hotplugHook);
+        auto invalidateHook = std::bind(&HWComposer::invalidate, this,
+                std::placeholders::_1);
+        mHwcDevice->registerRefreshCallback(invalidateHook);
+        auto vsyncHook = std::bind(&HWComposer::vsync, this,
+                std::placeholders::_1, std::placeholders::_2);
+        mHwcDevice->registerVsyncCallback(vsyncHook);
     }
-    if (mHwc) {
-        hwc_close_1(mHwc);
-    }
-    if (mFbDev) {
-        framebuffer_close(mFbDev);
-    }
-    delete mCBContext;
 }
 
 // Load and prepare the hardware composer module.  Sets mHwc.
 void HWComposer::loadHwcModule()
 {
+    ALOGV("loadHwcModule");
+
     hw_module_t const* module;
 
     if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
-        ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
-        return;
+        ALOGE("%s module not found, aborting", HWC_HARDWARE_MODULE_ID);
+        abort();
     }
 
-    int err = hwc_open_1(module, &mHwc);
-    if (err) {
-        ALOGE("%s device failed to initialize (%s)",
-              HWC_HARDWARE_COMPOSER, strerror(-err));
-        return;
+    if (module->module_api_version >= 0x0200) {
+        hwc2_device_t* hwc2device = nullptr;
+        int error = hwc2_open(module, &hwc2device);
+        if (error != 0) {
+            ALOGE("Failed to open HWC2 device (%s), aborting", strerror(-error));
+            abort();
+        }
+        mHwcDevice = std::make_unique<HWC2::Device>(hwc2device);
+    } else {
+        hwc_composer_device_1_t* hwc1device = nullptr;
+        int error = hwc_open_1(module, &hwc1device);
+        if (error) {
+            ALOGE("Failed to open HWC1 device (%s), aborting", strerror(-error));
+            abort();
+        }
+        mAdapter = std::make_unique<HWC2On1Adapter>(hwc1device);
+        uint8_t minorVersion = mAdapter->getHwc1MinorVersion();
+        if (minorVersion < 1) {
+            ALOGE("Cannot adapt to HWC version %d.%d",
+                    static_cast<int32_t>((minorVersion >> 8) & 0xF),
+                    static_cast<int32_t>(minorVersion & 0xF));
+            abort();
+        }
+        mHwcDevice = std::make_unique<HWC2::Device>(
+                static_cast<hwc2_device_t*>(mAdapter.get()));
     }
 
-    if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
-            hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
-            hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
-        ALOGE("%s device version %#x unsupported, will not be used",
-              HWC_HARDWARE_COMPOSER, mHwc->common.version);
-        hwc_close_1(mHwc);
-        mHwc = NULL;
-        return;
+    mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
+}
+
+bool HWComposer::isValidDisplay(int32_t displayId) const {
+    return static_cast<size_t>(displayId) < mDisplayData.size() &&
+            mDisplayData[displayId].hwcDisplay;
+}
+
+void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) {
+    bool valid = true;
+    switch (from) {
+        case HWC2::Composition::Client:
+            valid = false;
+            break;
+        case HWC2::Composition::Device:
+        case HWC2::Composition::SolidColor:
+            valid = (to == HWC2::Composition::Client);
+            break;
+        case HWC2::Composition::Cursor:
+        case HWC2::Composition::Sideband:
+            valid = (to == HWC2::Composition::Client ||
+                    to == HWC2::Composition::Device);
+            break;
+        default:
+            break;
+    }
+
+    if (!valid) {
+        ALOGE("Invalid layer type change: %s --> %s", to_string(from).c_str(),
+                to_string(to).c_str());
     }
 }
 
-// Load and prepare the FB HAL, which uses the gralloc module.  Sets mFbDev.
-int HWComposer::loadFbHalModule()
-{
-    hw_module_t const* module;
-
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    if (err != 0) {
-        ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
-        return err;
+void HWComposer::hotplug(const std::shared_ptr<HWC2::Display>& display,
+        HWC2::Connection connected) {
+    ALOGV("hotplug: %" PRIu64 ", %s", display->getId(),
+            to_string(connected).c_str());
+    int32_t disp = 0;
+    if (!mDisplayData[0].hwcDisplay) {
+        ALOGE_IF(connected != HWC2::Connection::Connected, "Assumed primary"
+                " display would be connected");
+        mDisplayData[0].hwcDisplay = display;
+        mHwcDisplaySlots[display->getId()] = 0;
+        disp = DisplayDevice::DISPLAY_PRIMARY;
+    } else {
+        // Disconnect is handled through HWComposer::disconnectDisplay via
+        // SurfaceFlinger's onHotplugReceived callback handling
+        if (connected == HWC2::Connection::Connected) {
+            mDisplayData[1].hwcDisplay = display;
+            mHwcDisplaySlots[display->getId()] = 1;
+        }
+        disp = DisplayDevice::DISPLAY_EXTERNAL;
     }
-
-    return framebuffer_open(module, &mFbDev);
+    mEventHandler->onHotplugReceived(disp,
+            connected == HWC2::Connection::Connected);
 }
 
-status_t HWComposer::initCheck() const {
-    return mHwc ? NO_ERROR : NO_INIT;
-}
-
-void HWComposer::hook_invalidate(const struct hwc_procs* procs) {
-    cb_context* ctx = reinterpret_cast<cb_context*>(
-            const_cast<hwc_procs_t*>(procs));
-    ctx->hwc->invalidate();
-}
-
-void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
-        int64_t timestamp) {
-    cb_context* ctx = reinterpret_cast<cb_context*>(
-            const_cast<hwc_procs_t*>(procs));
-    ctx->hwc->vsync(disp, timestamp);
-}
-
-void HWComposer::hook_hotplug(const struct hwc_procs* procs, int disp,
-        int connected) {
-    cb_context* ctx = reinterpret_cast<cb_context*>(
-            const_cast<hwc_procs_t*>(procs));
-    ctx->hwc->hotplug(disp, connected);
-}
-
-void HWComposer::invalidate() {
+void HWComposer::invalidate(const std::shared_ptr<HWC2::Display>& /*display*/) {
     mFlinger->repaintEverything();
 }
 
-void HWComposer::vsync(int disp, int64_t timestamp) {
-    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
-        {
-            Mutex::Autolock _l(mLock);
-
-            // There have been reports of HWCs that signal several vsync events
-            // with the same timestamp when turning the display off and on. This
-            // is a bug in the HWC implementation, but filter the extra events
-            // out here so they don't cause havoc downstream.
-            if (timestamp == mLastHwVSync[disp]) {
-                ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
-                        timestamp);
-                return;
-            }
-
-            mLastHwVSync[disp] = timestamp;
-        }
-
-        char tag[16];
-        snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
-        ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
-
-        mEventHandler.onVSyncReceived(disp, timestamp);
-    }
-}
-
-void HWComposer::hotplug(int disp, int connected) {
-    if (disp >= VIRTUAL_DISPLAY_ID_BASE) {
-        ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
-                disp, connected);
+void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display,
+        int64_t timestamp) {
+    auto displayType = HWC2::DisplayType::Invalid;
+    auto error = display->getType(&displayType);
+    if (error != HWC2::Error::None) {
+        ALOGE("vsync: Failed to determine type of display %" PRIu64,
+                display->getId());
         return;
     }
-    queryDisplayProperties(disp);
-    // Do not teardown or recreate the primary display
-    if (disp != HWC_DISPLAY_PRIMARY) {
-        mEventHandler.onHotplugReceived(disp, bool(connected));
-    }
-}
 
-static float getDefaultDensity(uint32_t width, uint32_t height) {
-    // Default density is based on TVs: 1080p displays get XHIGH density,
-    // lower-resolution displays get TV density. Maybe eventually we'll need
-    // to update it for 4K displays, though hopefully those just report
-    // accurate DPI information to begin with. This is also used for virtual
-    // displays and even primary displays with older hwcomposers, so be
-    // careful about orientation.
-
-    uint32_t h = width < height ? width : height;
-    if (h >= 1080) return ACONFIGURATION_DENSITY_XHIGH;
-    else           return ACONFIGURATION_DENSITY_TV;
-}
-
-static const uint32_t DISPLAY_ATTRIBUTES[] = {
-    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,
-};
-#define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
-
-static const uint32_t PRE_HWC15_DISPLAY_ATTRIBUTES[] = {
-    HWC_DISPLAY_VSYNC_PERIOD,
-    HWC_DISPLAY_WIDTH,
-    HWC_DISPLAY_HEIGHT,
-    HWC_DISPLAY_DPI_X,
-    HWC_DISPLAY_DPI_Y,
-    HWC_DISPLAY_NO_ATTRIBUTE,
-};
-
-status_t HWComposer::queryDisplayProperties(int disp) {
-
-    LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
-
-    // use zero as default value for unspecified attributes
-    int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
-    memset(values, 0, sizeof(values));
-
-    const size_t MAX_NUM_CONFIGS = 128;
-    uint32_t configs[MAX_NUM_CONFIGS] = {0};
-    size_t numConfigs = MAX_NUM_CONFIGS;
-    status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs);
-    if (err != NO_ERROR) {
-        // this can happen if an unpluggable display is not connected
-        mDisplayData[disp].connected = false;
-        return err;
+    if (displayType == HWC2::DisplayType::Virtual) {
+        ALOGE("Virtual display %" PRIu64 " passed to vsync callback",
+                display->getId());
+        return;
     }
 
-    mDisplayData[disp].currentConfig = 0;
-    for (size_t c = 0; c < numConfigs; ++c) {
-        err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
-                DISPLAY_ATTRIBUTES, values);
-        // If this is a pre-1.5 HWC, it may not know about color transform, so
-        // try again with a smaller set of attributes
-        if (err != NO_ERROR) {
-            err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
-                    PRE_HWC15_DISPLAY_ATTRIBUTES, values);
-        }
-        if (err != NO_ERROR) {
-            // we can't get this display's info. turn it off.
-            mDisplayData[disp].connected = false;
-            return err;
-        }
-
-        DisplayConfig config = DisplayConfig();
-        for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
-            switch (DISPLAY_ATTRIBUTES[i]) {
-                case HWC_DISPLAY_VSYNC_PERIOD:
-                    config.refresh = nsecs_t(values[i]);
-                    break;
-                case HWC_DISPLAY_WIDTH:
-                    config.width = values[i];
-                    break;
-                case HWC_DISPLAY_HEIGHT:
-                    config.height = values[i];
-                    break;
-                case HWC_DISPLAY_DPI_X:
-                    config.xdpi = values[i] / 1000.0f;
-                    break;
-                case HWC_DISPLAY_DPI_Y:
-                    config.ydpi = values[i] / 1000.0f;
-                    break;
-                case HWC_DISPLAY_COLOR_TRANSFORM:
-                    config.colorTransform = values[i];
-                    break;
-                default:
-                    ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
-                            i, DISPLAY_ATTRIBUTES[i]);
-                    break;
-            }
-        }
-
-        if (config.xdpi == 0.0f || config.ydpi == 0.0f) {
-            float dpi = getDefaultDensity(config.width, config.height);
-            config.xdpi = dpi;
-            config.ydpi = dpi;
-        }
-
-        mDisplayData[disp].configs.push_back(config);
+    if (mHwcDisplaySlots.count(display->getId()) == 0) {
+        ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback",
+                display->getId());
+        return;
     }
 
-    // FIXME: what should we set the format to?
-    mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
-    mDisplayData[disp].connected = true;
-    return NO_ERROR;
-}
+    int32_t disp = mHwcDisplaySlots[display->getId()];
+    {
+        Mutex::Autolock _l(mLock);
 
-status_t HWComposer::setVirtualDisplayProperties(int32_t id,
-        uint32_t w, uint32_t h, uint32_t format) {
-    if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) ||
-            !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
+        // There have been reports of HWCs that signal several vsync events
+        // with the same timestamp when turning the display off and on. This
+        // is a bug in the HWC implementation, but filter the extra events
+        // out here so they don't cause havoc downstream.
+        if (timestamp == mLastHwVSync[disp]) {
+            ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
+                    timestamp);
+            return;
+        }
+
+        mLastHwVSync[disp] = timestamp;
     }
-    size_t configId = mDisplayData[id].currentConfig;
-    mDisplayData[id].format = format;
-    DisplayConfig& config = mDisplayData[id].configs.editItemAt(configId);
-    config.width = w;
-    config.height = h;
-    config.xdpi = config.ydpi = getDefaultDensity(w, h);
-    return NO_ERROR;
+
+    char tag[16];
+    snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
+    ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
+
+    mEventHandler->onVSyncReceived(disp, timestamp);
 }
 
-int32_t HWComposer::allocateDisplayId() {
-    if (mAllocatedDisplayIDs.count() >= mNumDisplays) {
+status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
+        int32_t *outId) {
+    if (mRemainingHwcVirtualDisplays == 0) {
+        ALOGE("allocateVirtualDisplay: No remaining virtual displays");
         return NO_MEMORY;
     }
-    int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit();
-    mAllocatedDisplayIDs.markBit(id);
-    mDisplayData[id].connected = true;
-    mDisplayData[id].configs.resize(1);
-    mDisplayData[id].currentConfig = 0;
-    return id;
-}
 
-status_t HWComposer::freeDisplayId(int32_t id) {
-    if (id < NUM_BUILTIN_DISPLAYS) {
-        // cannot free the reserved IDs
-        return BAD_VALUE;
+    std::shared_ptr<HWC2::Display> display;
+    auto error = mHwcDevice->createVirtualDisplay(width, height, &display);
+    if (error != HWC2::Error::None) {
+        ALOGE("allocateVirtualDisplay: Failed to create HWC virtual display");
+        return NO_MEMORY;
     }
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
+
+    size_t displaySlot = 0;
+    if (!mFreeDisplaySlots.empty()) {
+        displaySlot = *mFreeDisplaySlots.begin();
+        mFreeDisplaySlots.erase(displaySlot);
+    } else if (mDisplayData.size() < INT32_MAX) {
+        // Don't bother allocating a slot larger than we can return
+        displaySlot = mDisplayData.size();
+        mDisplayData.resize(displaySlot + 1);
+    } else {
+        ALOGE("allocateVirtualDisplay: Unable to allocate a display slot");
+        return NO_MEMORY;
     }
-    mAllocatedDisplayIDs.clearBit(id);
-    mDisplayData[id].connected = false;
+
+    mDisplayData[displaySlot].hwcDisplay = display;
+
+    --mRemainingHwcVirtualDisplays;
+    *outId = static_cast<int32_t>(displaySlot);
+
     return NO_ERROR;
 }
 
-nsecs_t HWComposer::getRefreshTimestamp(int disp) const {
+std::shared_ptr<HWC2::Layer> HWComposer::createLayer(int32_t displayId) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("Failed to create layer on invalid display %d", displayId);
+        return nullptr;
+    }
+    auto display = mDisplayData[displayId].hwcDisplay;
+    std::shared_ptr<HWC2::Layer> layer;
+    auto error = display->createLayer(&layer);
+    if (error != HWC2::Error::None) {
+        ALOGE("Failed to create layer on display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return nullptr;
+    }
+    return layer;
+}
+
+nsecs_t HWComposer::getRefreshTimestamp(int32_t disp) const {
     // this returns the last refresh timestamp.
     // if the last one is not available, we estimate it based on
     // the refresh period and whatever closest timestamp we have.
     Mutex::Autolock _l(mLock);
     nsecs_t now = systemTime(CLOCK_MONOTONIC);
-    size_t configId = mDisplayData[disp].currentConfig;
-    return now - ((now - mLastHwVSync[disp]) %
-            mDisplayData[disp].configs[configId].refresh);
+    auto vsyncPeriod = getActiveConfig(disp)->getVsyncPeriod();
+    return now - ((now - mLastHwVSync[disp]) % vsyncPeriod);
 }
 
-sp<Fence> HWComposer::getDisplayFence(int disp) const {
-    return mDisplayData[disp].lastDisplayFence;
-}
-
-uint32_t HWComposer::getFormat(int disp) const {
-    if (static_cast<uint32_t>(disp) >= MAX_HWC_DISPLAYS || !mAllocatedDisplayIDs.hasBit(disp)) {
-        return HAL_PIXEL_FORMAT_RGBA_8888;
-    } else {
-        return mDisplayData[disp].format;
-    }
-}
-
-bool HWComposer::isConnected(int disp) const {
-    return mDisplayData[disp].connected;
-}
-
-uint32_t HWComposer::getWidth(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].width;
-}
-
-uint32_t HWComposer::getHeight(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].height;
-}
-
-float HWComposer::getDpiX(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].xdpi;
-}
-
-float HWComposer::getDpiY(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].ydpi;
-}
-
-nsecs_t HWComposer::getRefreshPeriod(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].refresh;
-}
-
-const Vector<HWComposer::DisplayConfig>& HWComposer::getConfigs(int disp) const {
-    return mDisplayData[disp].configs;
-}
-
-size_t HWComposer::getCurrentConfig(int disp) const {
-    return mDisplayData[disp].currentConfig;
-}
-
-void HWComposer::eventControl(int disp, int event, int enabled) {
-    if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
-        ALOGD("eventControl ignoring event %d on unallocated disp %d (en=%d)",
-              event, disp, enabled);
-        return;
-    }
-    if (event != EVENT_VSYNC) {
-        ALOGW("eventControl got unexpected event %d (disp=%d en=%d)",
-              event, disp, enabled);
-        return;
-    }
-    status_t err = NO_ERROR;
-    if (mHwc && !mDebugForceFakeVSync) {
-        // NOTE: we use our own internal lock here because we have to call
-        // into the HWC with the lock held, and we want to make sure
-        // that even if HWC blocks (which it shouldn't), it won't
-        // affect other threads.
-        Mutex::Autolock _l(mEventControlLock);
-        const int32_t eventBit = 1UL << event;
-        const int32_t newValue = enabled ? eventBit : 0;
-        const int32_t oldValue = mDisplayData[disp].events & eventBit;
-        if (newValue != oldValue) {
-            ATRACE_CALL();
-            err = mHwc->eventControl(mHwc, disp, event, enabled);
-            if (!err) {
-                int32_t& events(mDisplayData[disp].events);
-                events = (events & ~eventBit) | newValue;
-
-                char tag[16];
-                snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", disp);
-                ATRACE_INT(tag, enabled);
-            }
-        }
-        // error here should not happen -- not sure what we should
-        // do if it does.
-        ALOGE_IF(err, "eventControl(%d, %d) failed %s",
-                event, enabled, strerror(-err));
-    }
-
-    if (err == NO_ERROR && mVSyncThread != NULL) {
-        mVSyncThread->setEnabled(enabled);
-    }
-}
-
-status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
-    }
-
-    if (mHwc) {
-        DisplayData& disp(mDisplayData[id]);
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            // we need space for the HWC_FRAMEBUFFER_TARGET
-            numLayers++;
-        }
-        if (disp.capacity < numLayers || disp.list == NULL) {
-            size_t size = sizeof(hwc_display_contents_1_t)
-                    + numLayers * sizeof(hwc_layer_1_t);
-            free(disp.list);
-            disp.list = (hwc_display_contents_1_t*)malloc(size);
-            disp.capacity = numLayers;
-        }
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
-            memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
-            const DisplayConfig& currentConfig =
-                    disp.configs[disp.currentConfig];
-            const hwc_rect_t r = { 0, 0,
-                    (int) currentConfig.width, (int) currentConfig.height };
-            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
-            disp.framebufferTarget->hints = 0;
-            disp.framebufferTarget->flags = 0;
-            disp.framebufferTarget->handle = disp.fbTargetHandle;
-            disp.framebufferTarget->transform = 0;
-            disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-                disp.framebufferTarget->sourceCropf.left = 0;
-                disp.framebufferTarget->sourceCropf.top = 0;
-                disp.framebufferTarget->sourceCropf.right =
-                        currentConfig.width;
-                disp.framebufferTarget->sourceCropf.bottom =
-                        currentConfig.height;
-            } else {
-                disp.framebufferTarget->sourceCrop = r;
-            }
-            disp.framebufferTarget->displayFrame = r;
-            disp.framebufferTarget->visibleRegionScreen.numRects = 1;
-            disp.framebufferTarget->visibleRegionScreen.rects =
-                &disp.framebufferTarget->displayFrame;
-            disp.framebufferTarget->acquireFenceFd = -1;
-            disp.framebufferTarget->releaseFenceFd = -1;
-            disp.framebufferTarget->planeAlpha = 0xFF;
-        }
-        disp.list->retireFenceFd = -1;
-        disp.list->flags = HWC_GEOMETRY_CHANGED;
-        disp.list->numHwLayers = numLayers;
-    }
-    return NO_ERROR;
-}
-
-status_t HWComposer::setFramebufferTarget(int32_t id,
-        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
-    }
-    DisplayData& disp(mDisplayData[id]);
-    if (!disp.framebufferTarget) {
-        // this should never happen, but apparently eglCreateWindowSurface()
-        // triggers a Surface::queueBuffer()  on some
-        // devices (!?) -- log and ignore.
-        ALOGE("HWComposer: framebufferTarget is null");
-        return NO_ERROR;
-    }
-
-    int acquireFenceFd = -1;
-    if (acquireFence->isValid()) {
-        acquireFenceFd = acquireFence->dup();
-    }
-
-    // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);
-    disp.fbTargetHandle = buf->handle;
-    disp.framebufferTarget->handle = disp.fbTargetHandle;
-    disp.framebufferTarget->acquireFenceFd = acquireFenceFd;
-    return NO_ERROR;
-}
-
-status_t HWComposer::prepare() {
-    Mutex::Autolock _l(mDisplayLock);
-    for (size_t i=0 ; i<mNumDisplays ; i++) {
-        DisplayData& disp(mDisplayData[i]);
-        if (disp.framebufferTarget) {
-            // make sure to reset the type to HWC_FRAMEBUFFER_TARGET
-            // DO NOT reset the handle field to NULL, because it's possible
-            // that we have nothing to redraw (eg: eglSwapBuffers() not called)
-            // in which case, we should continue to use the same buffer.
-            LOG_FATAL_IF(disp.list == NULL);
-            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
-        }
-        if (!disp.connected && disp.list != NULL) {
-            ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",
-                  i, disp.list->numHwLayers);
-        }
-        mLists[i] = disp.list;
-        if (mLists[i]) {
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-                mLists[i]->outbuf = disp.outbufHandle;
-                mLists[i]->outbufAcquireFenceFd = -1;
-            } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-                // garbage data to catch improper use
-                mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
-                mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
-            } else {
-                mLists[i]->dpy = EGL_NO_DISPLAY;
-                mLists[i]->sur = EGL_NO_SURFACE;
-            }
-        }
-    }
-
-    int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
-    ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
-
-    if (err == NO_ERROR) {
-        // here we're just making sure that "skip" layers are set
-        // to HWC_FRAMEBUFFER and we're also counting how many layers
-        // we have of each type.
-        //
-        // If there are no window layers, we treat the display has having FB
-        // composition, because SurfaceFlinger will use GLES to draw the
-        // wormhole region.
-        for (size_t i=0 ; i<mNumDisplays ; i++) {
-            DisplayData& disp(mDisplayData[i]);
-            disp.hasFbComp = false;
-            disp.hasOvComp = false;
-            if (disp.list) {
-                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
-                    hwc_layer_1_t& l = disp.list->hwLayers[i];
-
-                    //ALOGD("prepare: %d, type=%d, handle=%p",
-                    //        i, l.compositionType, l.handle);
-
-                    if (l.flags & HWC_SKIP_LAYER) {
-                        l.compositionType = HWC_FRAMEBUFFER;
-                    }
-                    if (l.compositionType == HWC_FRAMEBUFFER) {
-                        disp.hasFbComp = true;
-                    }
-                    if (l.compositionType == HWC_OVERLAY) {
-                        disp.hasOvComp = true;
-                    }
-                    if (l.compositionType == HWC_CURSOR_OVERLAY) {
-                        disp.hasOvComp = true;
-                    }
-                }
-                if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
-                    disp.hasFbComp = true;
-                }
-            } else {
-                disp.hasFbComp = true;
-            }
-        }
-    }
-    return (status_t)err;
-}
-
-bool HWComposer::hasHwcComposition(int32_t id) const {
-    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+bool HWComposer::isConnected(int32_t disp) const {
+    if (!isValidDisplay(disp)) {
+        ALOGE("isConnected: Attempted to access invalid display %d", disp);
         return false;
-    return mDisplayData[id].hasOvComp;
+    }
+    return mDisplayData[disp].hwcDisplay->isConnected();
 }
 
-bool HWComposer::hasGlesComposition(int32_t id) const {
-    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return true;
-    return mDisplayData[id].hasFbComp;
-}
-
-sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return Fence::NO_FENCE;
-
-    int fd = INVALID_OPERATION;
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        const DisplayData& disp(mDisplayData[id]);
-        if (disp.framebufferTarget) {
-            fd = disp.framebufferTarget->releaseFenceFd;
-            disp.framebufferTarget->acquireFenceFd = -1;
-            disp.framebufferTarget->releaseFenceFd = -1;
+std::vector<std::shared_ptr<const HWC2::Display::Config>>
+        HWComposer::getConfigs(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("getConfigs: Attempted to access invalid display %d", displayId);
+        return {};
+    }
+    auto& displayData = mDisplayData[displayId];
+    auto configs = mDisplayData[displayId].hwcDisplay->getConfigs();
+    if (displayData.configMap.empty()) {
+        for (size_t i = 0; i < configs.size(); ++i) {
+            displayData.configMap[i] = configs[i];
         }
     }
-    return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
+    return configs;
 }
 
-status_t HWComposer::commit() {
-    int err = NO_ERROR;
-    if (mHwc) {
-        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            // On version 1.0, the OpenGL ES target surface is communicated
-            // by the (dpy, sur) fields and we are guaranteed to have only
-            // a single display.
-            mLists[0]->dpy = eglGetCurrentDisplay();
-            mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
-        }
-
-        for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
-            DisplayData& disp(mDisplayData[i]);
-            if (disp.outbufHandle) {
-                mLists[i]->outbuf = disp.outbufHandle;
-                mLists[i]->outbufAcquireFenceFd =
-                        disp.outbufAcquireFence->dup();
-            }
-        }
-
-        err = mHwc->set(mHwc, mNumDisplays, mLists);
-
-        for (size_t i=0 ; i<mNumDisplays ; i++) {
-            DisplayData& disp(mDisplayData[i]);
-            disp.lastDisplayFence = disp.lastRetireFence;
-            disp.lastRetireFence = Fence::NO_FENCE;
-            if (disp.list) {
-                if (disp.list->retireFenceFd != -1) {
-                    disp.lastRetireFence = new Fence(disp.list->retireFenceFd);
-                    disp.list->retireFenceFd = -1;
-                }
-                disp.list->flags &= ~HWC_GEOMETRY_CHANGED;
-            }
-        }
+std::shared_ptr<const HWC2::Display::Config>
+        HWComposer::getActiveConfig(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("getActiveConfigs: Attempted to access invalid display %d",
+                displayId);
+        return nullptr;
     }
-    return (status_t)err;
+    std::shared_ptr<const HWC2::Display::Config> config;
+    auto error = mDisplayData[displayId].hwcDisplay->getActiveConfig(&config);
+    if (error == HWC2::Error::BadConfig) {
+        ALOGV("getActiveConfig: No config active, returning null");
+        return nullptr;
+    } else if (error != HWC2::Error::None) {
+        ALOGE("getActiveConfig failed for display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return nullptr;
+    } else if (!config) {
+        ALOGE("getActiveConfig returned an unknown config for display %d",
+                displayId);
+        return nullptr;
+    }
+
+    return config;
 }
 
-status_t HWComposer::setPowerMode(int disp, int mode) {
-    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
-    if (mHwc) {
-        if (mode == HWC_POWER_MODE_OFF) {
-            eventControl(disp, HWC_EVENT_VSYNC, 0);
-        }
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
-            return (status_t)mHwc->setPowerMode(mHwc, disp, mode);
+void HWComposer::setVsyncEnabled(int32_t disp, HWC2::Vsync enabled) {
+    if (disp < 0 || disp >= HWC_DISPLAY_VIRTUAL) {
+        ALOGD("setVsyncEnabled: Ignoring for virtual display %d", disp);
+        return;
+    }
+
+    if (!isValidDisplay(disp)) {
+        ALOGE("setVsyncEnabled: Attempted to access invalid display %d", disp);
+        return;
+    }
+
+    // NOTE: we use our own internal lock here because we have to call
+    // into the HWC with the lock held, and we want to make sure
+    // that even if HWC blocks (which it shouldn't), it won't
+    // affect other threads.
+    Mutex::Autolock _l(mVsyncLock);
+    auto& displayData = mDisplayData[disp];
+    if (enabled != displayData.vsyncEnabled) {
+        ATRACE_CALL();
+        auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
+        if (error == HWC2::Error::None) {
+            displayData.vsyncEnabled = enabled;
+
+            char tag[16];
+            snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", disp);
+            ATRACE_INT(tag, enabled == HWC2::Vsync::Enable ? 1 : 0);
         } else {
-            return (status_t)mHwc->blank(mHwc, disp,
-                    mode == HWC_POWER_MODE_OFF ? 1 : 0);
+            ALOGE("setVsyncEnabled: Failed to set vsync to %s on %d/%" PRIu64
+                    ": %s (%d)", to_string(enabled).c_str(), disp,
+                    mDisplayData[disp].hwcDisplay->getId(),
+                    to_string(error).c_str(), static_cast<int32_t>(error));
         }
     }
-    return NO_ERROR;
 }
 
-status_t HWComposer::setActiveConfig(int disp, int mode) {
-    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
-    DisplayData& dd(mDisplayData[disp]);
-    dd.currentConfig = mode;
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
-        return (status_t)mHwc->setActiveConfig(mHwc, disp, mode);
-    } else {
-        LOG_FATAL_IF(mode != 0);
-    }
-    return NO_ERROR;
-}
-
-void HWComposer::disconnectDisplay(int disp) {
-    LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY);
-    DisplayData& dd(mDisplayData[disp]);
-    free(dd.list);
-    dd.list = NULL;
-    dd.framebufferTarget = NULL;    // points into dd.list
-    dd.fbTargetHandle = NULL;
-    dd.outbufHandle = NULL;
-    dd.lastRetireFence = Fence::NO_FENCE;
-    dd.lastDisplayFence = Fence::NO_FENCE;
-    dd.outbufAcquireFence = Fence::NO_FENCE;
-    // clear all the previous configs and repopulate when a new
-    // device is added
-    dd.configs.clear();
-}
-
-int HWComposer::getVisualID() const {
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
-        // is supported by the implementation. we can only be in this case
-        // if we have HWC 1.1
-        return HAL_PIXEL_FORMAT_RGBA_8888;
-        //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-    } else {
-        return mFbDev->format;
-    }
-}
-
-bool HWComposer::supportsFramebufferTarget() const {
-    return (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
-}
-
-int HWComposer::fbPost(int32_t id,
-        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        return setFramebufferTarget(id, acquireFence, buffer);
-    } else {
-        acquireFence->waitForever("HWComposer::fbPost");
-        return mFbDev->post(mFbDev, buffer->handle);
-    }
-}
-
-int HWComposer::fbCompositionComplete() {
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
-        return NO_ERROR;
-
-    if (mFbDev->compositionComplete) {
-        return mFbDev->compositionComplete(mFbDev);
-    } else {
-        return INVALID_OPERATION;
-    }
-}
-
-void HWComposer::fbDump(String8& result) {
-    if (mFbDev && mFbDev->common.version >= 1 && mFbDev->dump) {
-        const size_t SIZE = 4096;
-        char buffer[SIZE];
-        mFbDev->dump(mFbDev, buffer, SIZE);
-        result.append(buffer);
-    }
-}
-
-status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
-        const sp<GraphicBuffer>& buf) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+status_t HWComposer::setClientTarget(int32_t displayId,
+        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
+        android_dataspace_t dataspace) {
+    if (!isValidDisplay(displayId)) {
         return BAD_INDEX;
-    if (id < VIRTUAL_DISPLAY_ID_BASE)
-        return INVALID_OPERATION;
+    }
 
-    DisplayData& disp(mDisplayData[id]);
-    disp.outbufHandle = buf->handle;
-    disp.outbufAcquireFence = acquireFence;
+    ALOGV("setClientTarget for display %d", displayId);
+    auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+    buffer_handle_t handle = nullptr;
+    if ((target != nullptr) && target->getNativeBuffer()) {
+        handle = target->getNativeBuffer()->handle;
+    }
+    auto error = hwcDisplay->setClientTarget(handle, acquireFence, dataspace);
+    if (error != HWC2::Error::None) {
+        ALOGE("Failed to set client target for display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return BAD_VALUE;
+    }
+
     return NO_ERROR;
 }
 
-sp<Fence> HWComposer::getLastRetireFence(int32_t id) const {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+status_t HWComposer::prepare(DisplayDevice& displayDevice) {
+    ATRACE_CALL();
+
+    Mutex::Autolock _l(mDisplayLock);
+    auto displayId = displayDevice.getHwcDisplayId();
+    if (!isValidDisplay(displayId)) {
+        return BAD_INDEX;
+    }
+
+    auto& displayData = mDisplayData[displayId];
+    auto& hwcDisplay = displayData.hwcDisplay;
+    if (!hwcDisplay->isConnected()) {
+        return NO_ERROR;
+    }
+
+    uint32_t numTypes = 0;
+    uint32_t numRequests = 0;
+    auto error = hwcDisplay->validate(&numTypes, &numRequests);
+    if (error != HWC2::Error::None && error != HWC2::Error::HasChanges) {
+        ALOGE("prepare: validate failed for display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return BAD_INDEX;
+    }
+
+    std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::Composition>
+        changedTypes;
+    changedTypes.reserve(numTypes);
+    error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
+    if (error != HWC2::Error::None) {
+        ALOGE("prepare: getChangedCompositionTypes failed on display %d: "
+                "%s (%d)", displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return BAD_INDEX;
+    }
+
+
+    displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
+    std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::LayerRequest>
+        layerRequests;
+    layerRequests.reserve(numRequests);
+    error = hwcDisplay->getRequests(&displayData.displayRequests,
+            &layerRequests);
+    if (error != HWC2::Error::None) {
+        ALOGE("prepare: getRequests failed on display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return BAD_INDEX;
+    }
+
+    displayData.hasClientComposition = false;
+    displayData.hasDeviceComposition = false;
+    for (auto& layer : displayDevice.getVisibleLayersSortedByZ()) {
+        auto hwcLayer = layer->getHwcLayer(displayId);
+
+        if (changedTypes.count(hwcLayer) != 0) {
+            // We pass false so we only update our state and don't call back
+            // into the HWC device
+            validateChange(layer->getCompositionType(displayId),
+                    changedTypes[hwcLayer]);
+            layer->setCompositionType(displayId, changedTypes[hwcLayer], false);
+        }
+
+        switch (layer->getCompositionType(displayId)) {
+            case HWC2::Composition::Client:
+                displayData.hasClientComposition = true;
+                break;
+            case HWC2::Composition::Device:
+            case HWC2::Composition::SolidColor:
+            case HWC2::Composition::Cursor:
+            case HWC2::Composition::Sideband:
+                displayData.hasDeviceComposition = true;
+                break;
+            default:
+                break;
+        }
+
+        if (layerRequests.count(hwcLayer) != 0 &&
+                layerRequests[hwcLayer] ==
+                        HWC2::LayerRequest::ClearClientTarget) {
+            layer->setClearClientTarget(displayId, true);
+        } else {
+            if (layerRequests.count(hwcLayer) != 0) {
+                ALOGE("prepare: Unknown layer request: %s",
+                        to_string(layerRequests[hwcLayer]).c_str());
+            }
+            layer->setClearClientTarget(displayId, false);
+        }
+    }
+
+    error = hwcDisplay->acceptChanges();
+    if (error != HWC2::Error::None) {
+        ALOGE("prepare: acceptChanges failed: %s", to_string(error).c_str());
+        return BAD_INDEX;
+    }
+
+    return NO_ERROR;
+}
+
+bool HWComposer::hasDeviceComposition(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("hasDeviceComposition: Invalid display %d", displayId);
+        return false;
+    }
+    return mDisplayData[displayId].hasDeviceComposition;
+}
+
+bool HWComposer::hasClientComposition(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("hasClientComposition: Invalid display %d", displayId);
+        return true;
+    }
+    return mDisplayData[displayId].hasClientComposition;
+}
+
+sp<Fence> HWComposer::getRetireFence(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("getRetireFence failed for invalid display %d", displayId);
         return Fence::NO_FENCE;
-    return mDisplayData[id].lastRetireFence;
+    }
+    return mDisplayData[displayId].lastRetireFence;
 }
 
-status_t HWComposer::setCursorPositionAsync(int32_t id, const Rect& pos)
-{
-    if (mHwc->setCursorPositionAsync) {
-        return (status_t)mHwc->setCursorPositionAsync(mHwc, id, pos.left, pos.top);
+sp<Fence> HWComposer::getLayerReleaseFence(int32_t displayId,
+        const std::shared_ptr<HWC2::Layer>& layer) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("getLayerReleaseFence: Invalid display");
+        return Fence::NO_FENCE;
     }
-    else {
-        return NO_ERROR;
+    auto displayFences = mDisplayData[displayId].releaseFences;
+    if (displayFences.count(layer) == 0) {
+        ALOGV("getLayerReleaseFence: Release fence not found");
+        return Fence::NO_FENCE;
     }
+    return displayFences[layer];
 }
 
-/*
- * Helper template to implement a concrete HWCLayer
- * This holds the pointer to the concrete hwc layer type
- * and implements the "iterable" side of HWCLayer.
- */
-template<typename CONCRETE, typename HWCTYPE>
-class Iterable : public HWComposer::HWCLayer {
-protected:
-    HWCTYPE* const mLayerList;
-    HWCTYPE* mCurrentLayer;
-    Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer) { }
-    inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
-    inline HWCTYPE* getLayer() { return mCurrentLayer; }
-    virtual ~Iterable() { }
-private:
-    // returns a copy of ourselves
-    virtual HWComposer::HWCLayer* dup() {
-        return new CONCRETE( static_cast<const CONCRETE&>(*this) );
-    }
-    virtual status_t setLayer(size_t index) {
-        mCurrentLayer = &mLayerList[index];
-        return NO_ERROR;
-    }
-};
+status_t HWComposer::commit(int32_t displayId) {
+    ATRACE_CALL();
 
-/*
- * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_1_0.
- * This implements the HWCLayer side of HWCIterableLayer.
- */
-class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
-    struct hwc_composer_device_1* mHwc;
-public:
-    HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer)
-        : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc) { }
-
-    virtual int32_t getCompositionType() const {
-        return getLayer()->compositionType;
-    }
-    virtual uint32_t getHints() const {
-        return getLayer()->hints;
-    }
-    virtual sp<Fence> getAndResetReleaseFence() {
-        int fd = getLayer()->releaseFenceFd;
-        getLayer()->releaseFenceFd = -1;
-        return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
-    }
-    virtual void setAcquireFenceFd(int fenceFd) {
-        getLayer()->acquireFenceFd = fenceFd;
-    }
-    virtual void setPerFrameDefaultState() {
-        //getLayer()->compositionType = HWC_FRAMEBUFFER;
-    }
-    virtual void setPlaneAlpha(uint8_t alpha) {
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
-            getLayer()->planeAlpha = alpha;
-        } else {
-            if (alpha < 0xFF) {
-                getLayer()->flags |= HWC_SKIP_LAYER;
-            }
-        }
-    }
-    virtual void setDefaultState() {
-        hwc_layer_1_t* const l = getLayer();
-        l->compositionType = HWC_FRAMEBUFFER;
-        l->hints = 0;
-        l->flags = HWC_SKIP_LAYER;
-        l->handle = 0;
-        l->transform = 0;
-        l->blending = HWC_BLENDING_NONE;
-        l->visibleRegionScreen.numRects = 0;
-        l->visibleRegionScreen.rects = NULL;
-        l->acquireFenceFd = -1;
-        l->releaseFenceFd = -1;
-        l->planeAlpha = 0xFF;
-    }
-    virtual void setSkip(bool skip) {
-        if (skip) {
-            getLayer()->flags |= HWC_SKIP_LAYER;
-        } else {
-            getLayer()->flags &= ~HWC_SKIP_LAYER;
-        }
-    }
-    virtual void setIsCursorLayerHint(bool isCursor) {
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
-            if (isCursor) {
-                getLayer()->flags |= HWC_IS_CURSOR_LAYER;
-            }
-            else {
-                getLayer()->flags &= ~HWC_IS_CURSOR_LAYER;
-            }
-        }
-    }
-    virtual void setBlending(uint32_t blending) {
-        getLayer()->blending = blending;
-    }
-    virtual void setTransform(uint32_t transform) {
-        getLayer()->transform = transform;
-    }
-    virtual void setFrame(const Rect& frame) {
-        getLayer()->displayFrame = reinterpret_cast<hwc_rect_t const&>(frame);
-    }
-    virtual void setCrop(const FloatRect& crop) {
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-            getLayer()->sourceCropf = reinterpret_cast<hwc_frect_t const&>(crop);
-        } else {
-            /*
-             * Since h/w composer didn't support a flot crop rect before version 1.3,
-             * using integer coordinates instead produces a different output from the GL code in
-             * Layer::drawWithOpenGL(). The difference can be large if the buffer crop to
-             * window size ratio is large and a window crop is defined
-             * (i.e.: if we scale the buffer a lot and we also crop it with a window crop).
-             */
-            hwc_rect_t& r = getLayer()->sourceCrop;
-            r.left  = int(ceilf(crop.left));
-            r.top   = int(ceilf(crop.top));
-            r.right = int(floorf(crop.right));
-            r.bottom= int(floorf(crop.bottom));
-        }
-    }
-    virtual void setVisibleRegionScreen(const Region& reg) {
-        hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
-        mVisibleRegion = reg;
-        visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(
-                mVisibleRegion.getArray(&visibleRegion.numRects));
-    }
-    virtual void setSurfaceDamage(const Region& reg) {
-        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
-            return;
-        }
-        hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
-        // We encode default full-screen damage as INVALID_RECT upstream, but as
-        // 0 rects for HWComposer
-        if (reg.isRect() && reg.getBounds() == Rect::INVALID_RECT) {
-            surfaceDamage.numRects = 0;
-            surfaceDamage.rects = NULL;
-            return;
-        }
-        mSurfaceDamage = reg;
-        surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(
-                mSurfaceDamage.getArray(&surfaceDamage.numRects));
-    }
-    virtual void setSidebandStream(const sp<NativeHandle>& stream) {
-        ALOG_ASSERT(stream->handle() != NULL);
-        getLayer()->compositionType = HWC_SIDEBAND;
-        getLayer()->sidebandStream = stream->handle();
-    }
-    virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
-        if (buffer == 0 || buffer->handle == 0) {
-            getLayer()->compositionType = HWC_FRAMEBUFFER;
-            getLayer()->flags |= HWC_SKIP_LAYER;
-            getLayer()->handle = 0;
-        } else {
-            if (getLayer()->compositionType == HWC_SIDEBAND) {
-                // If this was a sideband layer but the stream was removed, reset
-                // it to FRAMEBUFFER. The HWC can change it to OVERLAY in prepare.
-                getLayer()->compositionType = HWC_FRAMEBUFFER;
-            }
-            getLayer()->handle = buffer->handle;
-        }
-    }
-    virtual void onDisplayed() {
-        getLayer()->acquireFenceFd = -1;
+    if (!isValidDisplay(displayId)) {
+        return BAD_INDEX;
     }
 
-protected:
-    // We need to hold "copies" of these for memory management purposes. The
-    // actual hwc_layer_1_t holds pointers to the memory within. Vector<>
-    // internally doesn't copy the memory unless one of the copies is modified.
-    Region mVisibleRegion;
-    Region mSurfaceDamage;
-};
+    auto& displayData = mDisplayData[displayId];
+    auto& hwcDisplay = displayData.hwcDisplay;
+    auto error = hwcDisplay->present(&displayData.lastRetireFence);
+    if (error != HWC2::Error::None) {
+        ALOGE("commit: present failed for display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
+    }
 
-/*
- * returns an iterator initialized at a given index in the layer list
- */
-HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return LayerListIterator();
+    std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+    error = hwcDisplay->getReleaseFences(&releaseFences);
+    if (error != HWC2::Error::None) {
+        ALOGE("commit: Failed to get release fences for display %d: %s (%d)",
+                displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
     }
-    const DisplayData& disp(mDisplayData[id]);
-    if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
-        return LayerListIterator();
-    }
-    return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index);
+
+    displayData.releaseFences = std::move(releaseFences);
+
+    return NO_ERROR;
 }
 
-/*
- * returns an iterator on the beginning of the layer list
- */
-HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
-    return getLayerIterator(id, 0);
-}
+status_t HWComposer::setPowerMode(int32_t displayId, int32_t intMode) {
+    ALOGV("setPowerMode(%d, %d)", displayId, intMode);
+    if (!isValidDisplay(displayId)) {
+        ALOGE("setPowerMode: Bad display");
+        return BAD_INDEX;
+    }
+    if (displayId >= VIRTUAL_DISPLAY_ID_BASE) {
+        ALOGE("setPowerMode: Virtual display %d passed in, returning",
+                displayId);
+        return BAD_INDEX;
+    }
 
-/*
- * returns an iterator on the end of the layer list
- */
-HWComposer::LayerListIterator HWComposer::end(int32_t id) {
-    size_t numLayers = 0;
-    if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
-        const DisplayData& disp(mDisplayData[id]);
-        if (mHwc && disp.list) {
-            numLayers = disp.list->numHwLayers;
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-                // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
-                // which we ignore when iterating through the layer list.
-                ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
-                if (numLayers) {
-                    numLayers--;
+    auto mode = static_cast<HWC2::PowerMode>(intMode);
+    if (mode == HWC2::PowerMode::Off) {
+        setVsyncEnabled(displayId, HWC2::Vsync::Disable);
+    }
+
+    auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+    switch (mode) {
+        case HWC2::PowerMode::Off:
+        case HWC2::PowerMode::On:
+            ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
+            {
+                auto error = hwcDisplay->setPowerMode(mode);
+                if (error != HWC2::Error::None) {
+                    ALOGE("setPowerMode: Unable to set power mode %s for "
+                            "display %d: %s (%d)", to_string(mode).c_str(),
+                            displayId, to_string(error).c_str(),
+                            static_cast<int32_t>(error));
                 }
             }
-        }
+            break;
+        case HWC2::PowerMode::Doze:
+        case HWC2::PowerMode::DozeSuspend:
+            ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
+            {
+                bool supportsDoze = false;
+                auto error = hwcDisplay->supportsDoze(&supportsDoze);
+                if (error != HWC2::Error::None) {
+                    ALOGE("setPowerMode: Unable to query doze support for "
+                            "display %d: %s (%d)", displayId,
+                            to_string(error).c_str(),
+                            static_cast<int32_t>(error));
+                }
+                if (!supportsDoze) {
+                    mode = HWC2::PowerMode::On;
+                }
+
+                error = hwcDisplay->setPowerMode(mode);
+                if (error != HWC2::Error::None) {
+                    ALOGE("setPowerMode: Unable to set power mode %s for "
+                            "display %d: %s (%d)", to_string(mode).c_str(),
+                            displayId, to_string(error).c_str(),
+                            static_cast<int32_t>(error));
+                }
+            }
+            break;
+        default:
+            ALOGV("setPowerMode: Not calling HWC");
+            break;
     }
-    return getLayerIterator(id, numLayers);
+
+    return NO_ERROR;
+}
+
+status_t HWComposer::setActiveConfig(int32_t displayId, size_t configId) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("setActiveConfig: Display %d is not valid", displayId);
+        return BAD_INDEX;
+    }
+
+    auto& displayData = mDisplayData[displayId];
+    if (displayData.configMap.count(configId) == 0) {
+        ALOGE("setActiveConfig: Invalid config %zd", configId);
+        return BAD_INDEX;
+    }
+
+    auto error = displayData.hwcDisplay->setActiveConfig(
+            displayData.configMap[configId]);
+    if (error != HWC2::Error::None) {
+        ALOGE("setActiveConfig: Failed to set config %zu on display %d: "
+                "%s (%d)", configId, displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
+    }
+
+    return NO_ERROR;
+}
+
+void HWComposer::disconnectDisplay(int displayId) {
+    LOG_ALWAYS_FATAL_IF(displayId < 0);
+    auto& displayData = mDisplayData[displayId];
+
+    auto displayType = HWC2::DisplayType::Invalid;
+    auto error = displayData.hwcDisplay->getType(&displayType);
+    if (error != HWC2::Error::None) {
+        ALOGE("disconnectDisplay: Failed to determine type of display %d",
+                displayId);
+        return;
+    }
+
+    // If this was a virtual display, add its slot back for reuse by future
+    // virtual displays
+    if (displayType == HWC2::DisplayType::Virtual) {
+        mFreeDisplaySlots.insert(displayId);
+        ++mRemainingHwcVirtualDisplays;
+    }
+
+    auto hwcId = displayData.hwcDisplay->getId();
+    mHwcDisplaySlots.erase(hwcId);
+    displayData.reset();
+}
+
+status_t HWComposer::setOutputBuffer(int32_t displayId,
+        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("setOutputBuffer: Display %d is not valid", displayId);
+        return BAD_INDEX;
+    }
+
+    auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+    auto displayType = HWC2::DisplayType::Invalid;
+    auto error = hwcDisplay->getType(&displayType);
+    if (error != HWC2::Error::None) {
+        ALOGE("setOutputBuffer: Failed to determine type of display %d",
+                displayId);
+        return NAME_NOT_FOUND;
+    }
+
+    if (displayType != HWC2::DisplayType::Virtual) {
+        ALOGE("setOutputBuffer: Display %d is not virtual", displayId);
+        return INVALID_OPERATION;
+    }
+
+    error = hwcDisplay->setOutputBuffer(buffer, acquireFence);
+    if (error != HWC2::Error::None) {
+        ALOGE("setOutputBuffer: Failed to set buffer on display %d: %s (%d)",
+                displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
+    }
+
+    return NO_ERROR;
+}
+
+void HWComposer::clearReleaseFences(int32_t displayId) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("clearReleaseFences: Display %d is not valid", displayId);
+        return;
+    }
+    mDisplayData[displayId].releaseFences.clear();
 }
 
 // Converts a PixelFormat to a human-readable string.  Max 11 chars.
 // (Could use a table of prefab String8 objects.)
+/*
 static String8 getFormatStr(PixelFormat format) {
     switch (format) {
     case PIXEL_FORMAT_RGBA_8888:    return String8("RGBA_8888");
@@ -1148,174 +754,34 @@
         return result;
     }
 }
+*/
 
 void HWComposer::dump(String8& result) const {
-    Mutex::Autolock _l(mDisplayLock);
-    if (mHwc) {
-        result.appendFormat("Hardware Composer state (version %08x):\n", hwcApiVersion(mHwc));
-        result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
-        for (size_t i=0 ; i<mNumDisplays ; i++) {
-            const DisplayData& disp(mDisplayData[i]);
-            if (!disp.connected)
-                continue;
-
-            const Vector< sp<Layer> >& visibleLayersSortedByZ =
-                    mFlinger->getLayerSortedByZForHwcDisplay(i);
-
-
-            result.appendFormat("  Display[%zd] configurations (* current):\n", i);
-            for (size_t c = 0; c < disp.configs.size(); ++c) {
-                const DisplayConfig& config(disp.configs[c]);
-                result.appendFormat("    %s%zd: %ux%u, xdpi=%f, ydpi=%f"
-                        ", refresh=%" PRId64 ", colorTransform=%d\n",
-                        c == disp.currentConfig ? "* " : "", c,
-                        config.width, config.height, config.xdpi, config.ydpi,
-                        config.refresh, config.colorTransform);
-            }
-
-            if (disp.list) {
-                result.appendFormat(
-                        "  numHwLayers=%zu, flags=%08x\n",
-                        disp.list->numHwLayers, disp.list->flags);
-
-                result.append(
-                        "    type   |  handle  | hint | flag | tr | blnd |   format    |     source crop (l,t,r,b)      |          frame         | name \n"
-                        "-----------+----------+------+------+----+------+-------------+--------------------------------+------------------------+------\n");
-                //      " _________ | ________ | ____ | ____ | __ | ____ | ___________ |_____._,_____._,_____._,_____._ |_____,_____,_____,_____ | ___...
-                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
-                    const hwc_layer_1_t&l = disp.list->hwLayers[i];
-                    int32_t format = -1;
-                    String8 name("unknown");
-
-                    if (i < visibleLayersSortedByZ.size()) {
-                        const sp<Layer>& layer(visibleLayersSortedByZ[i]);
-                        const sp<GraphicBuffer>& buffer(
-                                layer->getActiveBuffer());
-                        if (buffer != NULL) {
-                            format = buffer->getPixelFormat();
-                        }
-                        name = layer->getName();
-                    }
-
-                    int type = l.compositionType;
-                    if (type == HWC_FRAMEBUFFER_TARGET) {
-                        name = "HWC_FRAMEBUFFER_TARGET";
-                        format = disp.format;
-                    }
-
-                    static char const* compositionTypeName[] = {
-                            "GLES",
-                            "HWC",
-                            "BKGND",
-                            "FB TARGET",
-                            "SIDEBAND",
-                            "HWC_CURSOR",
-                            "UNKNOWN"};
-                    if (type >= NELEM(compositionTypeName))
-                        type = NELEM(compositionTypeName) - 1;
-
-                    String8 formatStr = getFormatStr(format);
-                    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-                        result.appendFormat(
-                                " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d | %s\n",
-                                        compositionTypeName[type],
-                                        intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
-                                        l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom,
-                                        l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
-                                        name.string());
-                    } else {
-                        result.appendFormat(
-                                " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7d,%7d,%7d,%7d |%5d,%5d,%5d,%5d | %s\n",
-                                        compositionTypeName[type],
-                                        intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
-                                        l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
-                                        l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
-                                        name.string());
-                    }
-                }
-            }
-        }
-    }
-
-    if (mHwc && mHwc->dump) {
-        const size_t SIZE = 4096;
-        char buffer[SIZE];
-        mHwc->dump(mHwc, buffer, SIZE);
-        result.append(buffer);
-    }
+    // TODO: In order to provide a dump equivalent to HWC1, we need to shadow
+    // all the state going into the layers. This is probably better done in
+    // Layer itself, but it's going to take a bit of work to get there.
+    result.append(mHwcDevice->dump().c_str());
 }
 
 // ---------------------------------------------------------------------------
 
-HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
-    : mHwc(hwc), mEnabled(false),
-      mNextFakeVSync(0),
-      mRefreshPeriod(hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY))
-{
-}
-
-void HWComposer::VSyncThread::setEnabled(bool enabled) {
-    Mutex::Autolock _l(mLock);
-    if (mEnabled != enabled) {
-        mEnabled = enabled;
-        mCondition.signal();
-    }
-}
-
-void HWComposer::VSyncThread::onFirstRef() {
-    run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
-}
-
-bool HWComposer::VSyncThread::threadLoop() {
-    { // scope for lock
-        Mutex::Autolock _l(mLock);
-        while (!mEnabled) {
-            mCondition.wait(mLock);
-        }
-    }
-
-    const nsecs_t period = mRefreshPeriod;
-    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
-    nsecs_t next_vsync = mNextFakeVSync;
-    nsecs_t sleep = next_vsync - now;
-    if (sleep < 0) {
-        // we missed, find where the next vsync should be
-        sleep = (period - ((now - next_vsync) % period));
-        next_vsync = now + sleep;
-    }
-    mNextFakeVSync = next_vsync + period;
-
-    struct timespec spec;
-    spec.tv_sec  = next_vsync / 1000000000;
-    spec.tv_nsec = next_vsync % 1000000000;
-
-    int err;
-    do {
-        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
-    } while (err<0 && errno == EINTR);
-
-    if (err == 0) {
-        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
-    }
-
-    return true;
-}
-
 HWComposer::DisplayData::DisplayData()
-:   configs(),
-    currentConfig(0),
-    format(HAL_PIXEL_FORMAT_RGBA_8888),
-    connected(false),
-    hasFbComp(false), hasOvComp(false),
-    capacity(0), list(NULL),
-    framebufferTarget(NULL), fbTargetHandle(0),
-    lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE),
-    outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE),
-    events(0)
-{}
+  : hasClientComposition(false),
+    hasDeviceComposition(false),
+    hwcDisplay(),
+    lastRetireFence(Fence::NO_FENCE),
+    outbufHandle(nullptr),
+    outbufAcquireFence(Fence::NO_FENCE),
+    vsyncEnabled(HWC2::Vsync::Disable) {
+    ALOGV("Created new DisplayData");
+}
 
 HWComposer::DisplayData::~DisplayData() {
-    free(list);
+}
+
+void HWComposer::DisplayData::reset() {
+    ALOGV("DisplayData reset");
+    *this = DisplayData();
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 5e0b3d8..30c8f67 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -14,14 +14,18 @@
  * limitations under the License.
  */
 
+#ifndef USE_HWC2
+#include "HWComposer_hwc1.h"
+#else
+
 #ifndef ANDROID_SF_HWCOMPOSER_H
 #define ANDROID_SF_HWCOMPOSER_H
 
+#include "HWC2.h"
+
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <hardware/hwcomposer_defs.h>
-
 #include <ui/Fence.h>
 
 #include <utils/BitSet.h>
@@ -32,22 +36,29 @@
 #include <utils/Timers.h>
 #include <utils/Vector.h>
 
+#include <memory>
+#include <set>
+#include <vector>
+
 extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
                            const struct timespec *request,
                            struct timespec *remain);
 
-struct hwc_composer_device_1;
-struct hwc_display_contents_1;
-struct hwc_layer_1;
-struct hwc_procs;
 struct framebuffer_device_t;
 
+namespace HWC2 {
+    class Device;
+    class Display;
+}
+
 namespace android {
 // ---------------------------------------------------------------------------
 
+class DisplayDevice;
 class Fence;
 class FloatRect;
 class GraphicBuffer;
+class HWC2On1Adapter;
 class NativeHandle;
 class Region;
 class String8;
@@ -58,198 +69,70 @@
 public:
     class EventHandler {
         friend class HWComposer;
-        virtual void onVSyncReceived(int disp, nsecs_t timestamp) = 0;
-        virtual void onHotplugReceived(int disp, bool connected) = 0;
+        virtual void onVSyncReceived(int32_t disp, nsecs_t timestamp) = 0;
+        virtual void onHotplugReceived(int32_t disp, bool connected) = 0;
     protected:
         virtual ~EventHandler() {}
     };
 
-    enum {
-        NUM_BUILTIN_DISPLAYS = HWC_NUM_PHYSICAL_DISPLAY_TYPES,
-        MAX_HWC_DISPLAYS = HWC_NUM_DISPLAY_TYPES,
-        VIRTUAL_DISPLAY_ID_BASE = HWC_DISPLAY_VIRTUAL,
-    };
-
-    HWComposer(
-            const sp<SurfaceFlinger>& flinger,
-            EventHandler& handler);
+    HWComposer(const sp<SurfaceFlinger>& flinger);
 
     ~HWComposer();
 
-    status_t initCheck() const;
+    void setEventHandler(EventHandler* handler);
 
-    // Returns a display ID starting at VIRTUAL_DISPLAY_ID_BASE, this ID is to
-    // be used with createWorkList (and all other methods requiring an ID
-    // below).
-    // IDs below NUM_BUILTIN_DISPLAYS are pre-defined and therefore are
-    // always valid.
-    // Returns -1 if an ID cannot be allocated
-    int32_t allocateDisplayId();
+    // Attempts to allocate a virtual display. If the virtual display is created
+    // on the HWC device, outId will contain its HWC ID.
+    status_t allocateVirtualDisplay(uint32_t width, uint32_t height,
+            int32_t* outId);
 
-    // Recycles the given virtual display ID and frees the associated worklist.
-    // IDs below NUM_BUILTIN_DISPLAYS are not recycled.
-    status_t freeDisplayId(int32_t id);
-
+    // Attempts to create a new layer on this display
+    std::shared_ptr<HWC2::Layer> createLayer(int32_t displayId);
 
     // Asks the HAL what it can do
-    status_t prepare();
+    status_t prepare(DisplayDevice& displayDevice);
 
-    // commits the list
-    status_t commit();
+    status_t setClientTarget(int32_t displayId, const sp<Fence>& acquireFence,
+            const sp<GraphicBuffer>& target, android_dataspace_t dataspace);
+
+    // Finalize the layers and present them
+    status_t commit(int32_t displayId);
 
     // set power mode
-    status_t setPowerMode(int disp, int mode);
+    status_t setPowerMode(int32_t displayId, int mode);
 
     // set active config
-    status_t setActiveConfig(int disp, int mode);
+    status_t setActiveConfig(int32_t displayId, size_t configId);
 
     // reset state when an external, non-virtual display is disconnected
-    void disconnectDisplay(int disp);
-
-    // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
-    status_t createWorkList(int32_t id, size_t numLayers);
-
-    bool supportsFramebufferTarget() const;
+    void disconnectDisplay(int32_t displayId);
 
     // does this display have layers handled by HWC
-    bool hasHwcComposition(int32_t id) const;
+    bool hasDeviceComposition(int32_t displayId) const;
 
     // does this display have layers handled by GLES
-    bool hasGlesComposition(int32_t id) const;
+    bool hasClientComposition(int32_t displayId) const;
 
-    // get the releaseFence file descriptor for a display's framebuffer layer.
-    // the release fence is only valid after commit()
-    sp<Fence> getAndResetReleaseFence(int32_t id);
+    // get the retire fence for the previous frame (i.e., corresponding to the
+    // last call to presentDisplay
+    sp<Fence> getRetireFence(int32_t displayId) const;
 
-    // needed forward declarations
-    class LayerListIterator;
-
-    // return the visual id to be used to find a suitable EGLConfig for
-    // *ALL* displays.
-    int getVisualID() const;
-
-    // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
-    int fbPost(int32_t id, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
-    int fbCompositionComplete();
-    void fbDump(String8& result);
+    // Get last release fence for the given layer
+    sp<Fence> getLayerReleaseFence(int32_t displayId,
+            const std::shared_ptr<HWC2::Layer>& layer) const;
 
     // Set the output buffer and acquire fence for a virtual display.
-    // Returns INVALID_OPERATION if id is not a virtual display.
-    status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+    // Returns INVALID_OPERATION if displayId is not a virtual display.
+    status_t setOutputBuffer(int32_t displayId, const sp<Fence>& acquireFence,
             const sp<GraphicBuffer>& buf);
 
-    // Get the retire fence for the last committed frame. This fence will
-    // signal when the h/w composer is completely finished with the frame.
-    // For physical displays, it is no longer being displayed. For virtual
-    // displays, writes to the output buffer are complete.
-    sp<Fence> getLastRetireFence(int32_t id) const;
-
-    status_t setCursorPositionAsync(int32_t id, const Rect &pos);
-
-    /*
-     * Interface to hardware composer's layers functionality.
-     * This abstracts the HAL interface to layers which can evolve in
-     * incompatible ways from one release to another.
-     * The idea is that we could extend this interface as we add
-     * features to h/w composer.
-     */
-    class HWCLayerInterface {
-    protected:
-        virtual ~HWCLayerInterface() { }
-    public:
-        virtual int32_t getCompositionType() const = 0;
-        virtual uint32_t getHints() const = 0;
-        virtual sp<Fence> getAndResetReleaseFence() = 0;
-        virtual void setDefaultState() = 0;
-        virtual void setSkip(bool skip) = 0;
-        virtual void setIsCursorLayerHint(bool isCursor = true) = 0;
-        virtual void setBlending(uint32_t blending) = 0;
-        virtual void setTransform(uint32_t transform) = 0;
-        virtual void setFrame(const Rect& frame) = 0;
-        virtual void setCrop(const FloatRect& crop) = 0;
-        virtual void setVisibleRegionScreen(const Region& reg) = 0;
-        virtual void setSurfaceDamage(const Region& reg) = 0;
-        virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
-        virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
-        virtual void setAcquireFenceFd(int fenceFd) = 0;
-        virtual void setPlaneAlpha(uint8_t alpha) = 0;
-        virtual void onDisplayed() = 0;
-    };
-
-    /*
-     * Interface used to implement an iterator to a list
-     * of HWCLayer.
-     */
-    class HWCLayer : public HWCLayerInterface {
-        friend class LayerListIterator;
-        // select the layer at the given index
-        virtual status_t setLayer(size_t index) = 0;
-        virtual HWCLayer* dup() = 0;
-        static HWCLayer* copy(HWCLayer *rhs) {
-            return rhs ? rhs->dup() : NULL;
-        }
-    protected:
-        virtual ~HWCLayer() { }
-    };
-
-    /*
-     * Iterator through a HWCLayer list.
-     * This behaves more or less like a forward iterator.
-     */
-    class LayerListIterator {
-        friend class HWComposer;
-        HWCLayer* const mLayerList;
-        size_t mIndex;
-
-        LayerListIterator() : mLayerList(NULL), mIndex(0) { }
-
-        LayerListIterator(HWCLayer* layer, size_t index)
-            : mLayerList(layer), mIndex(index) { }
-
-        // we don't allow assignment, because we don't need it for now
-        LayerListIterator& operator = (const LayerListIterator& rhs);
-
-    public:
-        // copy operators
-        LayerListIterator(const LayerListIterator& rhs)
-            : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) {
-        }
-
-        ~LayerListIterator() { delete mLayerList; }
-
-        // pre-increment
-        LayerListIterator& operator++() {
-            mLayerList->setLayer(++mIndex);
-            return *this;
-        }
-
-        // dereference
-        HWCLayerInterface& operator * () { return *mLayerList; }
-        HWCLayerInterface* operator -> () { return mLayerList; }
-
-        // comparison
-        bool operator == (const LayerListIterator& rhs) const {
-            return mIndex == rhs.mIndex;
-        }
-        bool operator != (const LayerListIterator& rhs) const {
-            return !operator==(rhs);
-        }
-    };
-
-    // Returns an iterator to the beginning of the layer list
-    LayerListIterator begin(int32_t id);
-
-    // Returns an iterator to the end of the layer list
-    LayerListIterator end(int32_t id);
-
+    // After SurfaceFlinger has retrieved the release fences for all the frames,
+    // it can call this to clear the shared pointers in the release fence map
+    void clearReleaseFences(int32_t displayId);
 
     // Events handling ---------------------------------------------------------
 
-    enum {
-        EVENT_VSYNC = HWC_EVENT_VSYNC
-    };
-
-    void eventControl(int disp, int event, int enabled);
+    void setVsyncEnabled(int32_t disp, HWC2::Vsync enabled);
 
     struct DisplayConfig {
         uint32_t width;
@@ -262,119 +145,81 @@
 
     // Query display parameters.  Pass in a display index (e.g.
     // HWC_DISPLAY_PRIMARY).
-    nsecs_t getRefreshTimestamp(int disp) const;
-    sp<Fence> getDisplayFence(int disp) const;
-    uint32_t getFormat(int disp) const;
-    bool isConnected(int disp) const;
+    nsecs_t getRefreshTimestamp(int32_t disp) const;
+    bool isConnected(int32_t disp) const;
 
-    // These return the values for the current config of a given display index.
-    // To get the values for all configs, use getConfigs below.
-    uint32_t getWidth(int disp) const;
-    uint32_t getHeight(int disp) const;
-    float getDpiX(int disp) const;
-    float getDpiY(int disp) const;
-    nsecs_t getRefreshPeriod(int disp) const;
+    // Non-const because it can update configMap inside of mDisplayData
+    std::vector<std::shared_ptr<const HWC2::Display::Config>>
+            getConfigs(int32_t displayId) const;
 
-    const Vector<DisplayConfig>& getConfigs(int disp) const;
-    size_t getCurrentConfig(int disp) const;
-
-    status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h,
-            uint32_t format);
-
-    // this class is only used to fake the VSync event on systems that don't
-    // have it.
-    class VSyncThread : public Thread {
-        HWComposer& mHwc;
-        mutable Mutex mLock;
-        Condition mCondition;
-        bool mEnabled;
-        mutable nsecs_t mNextFakeVSync;
-        nsecs_t mRefreshPeriod;
-        virtual void onFirstRef();
-        virtual bool threadLoop();
-    public:
-        VSyncThread(HWComposer& hwc);
-        void setEnabled(bool enabled);
-    };
-
-    friend class VSyncThread;
+    std::shared_ptr<const HWC2::Display::Config>
+            getActiveConfig(int32_t displayId) const;
 
     // for debugging ----------------------------------------------------------
     void dump(String8& out) const;
 
 private:
-    void loadHwcModule();
-    int loadFbHalModule();
+    static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
 
-    LayerListIterator getLayerIterator(int32_t id, size_t index);
+    void loadHwcModule();
+
+    bool isValidDisplay(int32_t displayId) const;
+    static void validateChange(HWC2::Composition from, HWC2::Composition to);
 
     struct cb_context;
 
-    static void hook_invalidate(const struct hwc_procs* procs);
-    static void hook_vsync(const struct hwc_procs* procs, int disp,
+    void invalidate(const std::shared_ptr<HWC2::Display>& display);
+    void vsync(const std::shared_ptr<HWC2::Display>& display,
             int64_t timestamp);
-    static void hook_hotplug(const struct hwc_procs* procs, int disp,
-            int connected);
-
-    inline void invalidate();
-    inline void vsync(int disp, int64_t timestamp);
-    inline void hotplug(int disp, int connected);
-
-    status_t queryDisplayProperties(int disp);
-
-    status_t setFramebufferTarget(int32_t id,
-            const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
+    void hotplug(const std::shared_ptr<HWC2::Display>& display,
+            HWC2::Connection connected);
 
     struct DisplayData {
         DisplayData();
         ~DisplayData();
-        Vector<DisplayConfig> configs;
-        size_t currentConfig;
-        uint32_t format;    // pixel format from FB hal, for pre-hwc-1.1
-        bool connected;
-        bool hasFbComp;
-        bool hasOvComp;
-        size_t capacity;
-        hwc_display_contents_1* list;
-        hwc_layer_1* framebufferTarget;
-        buffer_handle_t fbTargetHandle;
+        void reset();
+
+        bool hasClientComposition;
+        bool hasDeviceComposition;
+        std::shared_ptr<HWC2::Display> hwcDisplay;
+        HWC2::DisplayRequest displayRequests;
         sp<Fence> lastRetireFence;  // signals when the last set op retires
-        sp<Fence> lastDisplayFence; // signals when the last set op takes
-                                    // effect on screen
+        std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>>
+                releaseFences;
         buffer_handle_t outbufHandle;
         sp<Fence> outbufAcquireFence;
+        mutable std::unordered_map<int32_t,
+                std::shared_ptr<const HWC2::Display::Config>> configMap;
 
-        // protected by mEventControlLock
-        int32_t events;
+        // protected by mVsyncLock
+        HWC2::Vsync vsyncEnabled;
     };
 
     sp<SurfaceFlinger>              mFlinger;
-    framebuffer_device_t*           mFbDev;
-    struct hwc_composer_device_1*   mHwc;
-    // invariant: mLists[0] != NULL iff mHwc != NULL
-    // mLists[i>0] can be NULL. that display is to be ignored
-    struct hwc_display_contents_1*  mLists[MAX_HWC_DISPLAYS];
-    DisplayData                     mDisplayData[MAX_HWC_DISPLAYS];
+    std::unique_ptr<HWC2On1Adapter> mAdapter;
+    std::unique_ptr<HWC2::Device>   mHwcDevice;
+    std::vector<DisplayData>        mDisplayData;
+    std::set<size_t>                mFreeDisplaySlots;
+    std::unordered_map<hwc2_display_t, int32_t> mHwcDisplaySlots;
     // protect mDisplayData from races between prepare and dump
     mutable Mutex mDisplayLock;
-    size_t                          mNumDisplays;
 
     cb_context*                     mCBContext;
-    EventHandler&                   mEventHandler;
+    EventHandler*                   mEventHandler;
     size_t                          mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
-    sp<VSyncThread>                 mVSyncThread;
-    bool                            mDebugForceFakeVSync;
-    BitSet32                        mAllocatedDisplayIDs;
+    uint32_t                        mRemainingHwcVirtualDisplays;
 
     // protected by mLock
     mutable Mutex mLock;
-    mutable nsecs_t mLastHwVSync[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
+    mutable std::unordered_map<int32_t, nsecs_t> mLastHwVSync;
 
     // thread-safe
-    mutable Mutex mEventControlLock;
+    mutable Mutex mVsyncLock;
 };
 
 // ---------------------------------------------------------------------------
 }; // namespace android
 
 #endif // ANDROID_SF_HWCOMPOSER_H
+
+#endif // #ifdef USE_HWC2
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
new file mode 100644
index 0000000..d37fcb2
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -0,0 +1,1322 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <inttypes.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/misc.h>
+#include <utils/NativeHandle.h>
+#include <utils/String8.h>
+#include <utils/Thread.h>
+#include <utils/Trace.h>
+#include <utils/Vector.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+
+#include <android/configuration.h>
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include "HWComposer.h"
+
+#include "../Layer.h"           // needed only for debugging
+#include "../SurfaceFlinger.h"
+
+namespace android {
+
+#define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
+
+static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
+    uint32_t hwcVersion = hwc->common.version;
+    return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+}
+
+static uint32_t hwcHeaderVersion(const hwc_composer_device_1_t* hwc) {
+    uint32_t hwcVersion = hwc->common.version;
+    return hwcVersion & HARDWARE_API_VERSION_2_HEADER_MASK;
+}
+
+static bool hwcHasApiVersion(const hwc_composer_device_1_t* hwc,
+        uint32_t version) {
+    return hwcApiVersion(hwc) >= (version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK);
+}
+
+// ---------------------------------------------------------------------------
+
+struct HWComposer::cb_context {
+    struct callbacks : public hwc_procs_t {
+        // these are here to facilitate the transition when adding
+        // new callbacks (an implementation can check for NULL before
+        // calling a new callback).
+        void (*zero[4])(void);
+    };
+    callbacks procs;
+    HWComposer* hwc;
+};
+
+// ---------------------------------------------------------------------------
+
+HWComposer::HWComposer(
+        const sp<SurfaceFlinger>& flinger,
+        EventHandler& handler)
+    : mFlinger(flinger),
+      mFbDev(0), mHwc(0), mNumDisplays(1),
+      mCBContext(new cb_context),
+      mEventHandler(handler),
+      mDebugForceFakeVSync(false)
+{
+    for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
+        mLists[i] = 0;
+    }
+
+    for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
+        mLastHwVSync[i] = 0;
+        mVSyncCounts[i] = 0;
+    }
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.sf.no_hw_vsync", value, "0");
+    mDebugForceFakeVSync = atoi(value);
+
+    bool needVSyncThread = true;
+
+    // Note: some devices may insist that the FB HAL be opened before HWC.
+    int fberr = loadFbHalModule();
+    loadHwcModule();
+
+    if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        // close FB HAL if we don't needed it.
+        // FIXME: this is temporary until we're not forced to open FB HAL
+        // before HWC.
+        framebuffer_close(mFbDev);
+        mFbDev = NULL;
+    }
+
+    // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
+    if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
+            && !mFbDev) {
+        ALOGE("ERROR: failed to open framebuffer (%s), aborting",
+                strerror(-fberr));
+        abort();
+    }
+
+    // these display IDs are always reserved
+    for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
+        mAllocatedDisplayIDs.markBit(i);
+    }
+
+    if (mHwc) {
+        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
+              (hwcApiVersion(mHwc) >> 24) & 0xff,
+              (hwcApiVersion(mHwc) >> 16) & 0xff);
+        if (mHwc->registerProcs) {
+            mCBContext->hwc = this;
+            mCBContext->procs.invalidate = &hook_invalidate;
+            mCBContext->procs.vsync = &hook_vsync;
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
+                mCBContext->procs.hotplug = &hook_hotplug;
+            else
+                mCBContext->procs.hotplug = NULL;
+            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
+            mHwc->registerProcs(mHwc, &mCBContext->procs);
+        }
+
+        // don't need a vsync thread if we have a hardware composer
+        needVSyncThread = false;
+        // always turn vsync off when we start
+        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
+
+        // the number of displays we actually have depends on the
+        // hw composer version
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+            // 1.3 adds support for virtual displays
+            mNumDisplays = MAX_HWC_DISPLAYS;
+        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            // 1.1 adds support for multiple displays
+            mNumDisplays = NUM_BUILTIN_DISPLAYS;
+        } else {
+            mNumDisplays = 1;
+        }
+    }
+
+    if (mFbDev) {
+        ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
+                "should only have fbdev if no hwc or hwc is 1.0");
+
+        DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
+        disp.connected = true;
+        disp.format = mFbDev->format;
+        DisplayConfig config = DisplayConfig();
+        config.width = mFbDev->width;
+        config.height = mFbDev->height;
+        config.xdpi = mFbDev->xdpi;
+        config.ydpi = mFbDev->ydpi;
+        config.refresh = nsecs_t(1e9 / mFbDev->fps);
+        disp.configs.push_back(config);
+        disp.currentConfig = 0;
+    } else if (mHwc) {
+        // here we're guaranteed to have at least HWC 1.1
+        for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
+            queryDisplayProperties(i);
+        }
+    }
+
+    if (needVSyncThread) {
+        // we don't have VSYNC support, we need to fake it
+        mVSyncThread = new VSyncThread(*this);
+    }
+}
+
+HWComposer::~HWComposer() {
+    if (mHwc) {
+        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
+    }
+    if (mVSyncThread != NULL) {
+        mVSyncThread->requestExitAndWait();
+    }
+    if (mHwc) {
+        hwc_close_1(mHwc);
+    }
+    if (mFbDev) {
+        framebuffer_close(mFbDev);
+    }
+    delete mCBContext;
+}
+
+// Load and prepare the hardware composer module.  Sets mHwc.
+void HWComposer::loadHwcModule()
+{
+    hw_module_t const* module;
+
+    if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
+        ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
+        return;
+    }
+
+    int err = hwc_open_1(module, &mHwc);
+    if (err) {
+        ALOGE("%s device failed to initialize (%s)",
+              HWC_HARDWARE_COMPOSER, strerror(-err));
+        return;
+    }
+
+    if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
+            hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
+            hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
+        ALOGE("%s device version %#x unsupported, will not be used",
+              HWC_HARDWARE_COMPOSER, mHwc->common.version);
+        hwc_close_1(mHwc);
+        mHwc = NULL;
+        return;
+    }
+}
+
+// Load and prepare the FB HAL, which uses the gralloc module.  Sets mFbDev.
+int HWComposer::loadFbHalModule()
+{
+    hw_module_t const* module;
+
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    if (err != 0) {
+        ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
+        return err;
+    }
+
+    return framebuffer_open(module, &mFbDev);
+}
+
+status_t HWComposer::initCheck() const {
+    return mHwc ? NO_ERROR : NO_INIT;
+}
+
+void HWComposer::hook_invalidate(const struct hwc_procs* procs) {
+    cb_context* ctx = reinterpret_cast<cb_context*>(
+            const_cast<hwc_procs_t*>(procs));
+    ctx->hwc->invalidate();
+}
+
+void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
+        int64_t timestamp) {
+    cb_context* ctx = reinterpret_cast<cb_context*>(
+            const_cast<hwc_procs_t*>(procs));
+    ctx->hwc->vsync(disp, timestamp);
+}
+
+void HWComposer::hook_hotplug(const struct hwc_procs* procs, int disp,
+        int connected) {
+    cb_context* ctx = reinterpret_cast<cb_context*>(
+            const_cast<hwc_procs_t*>(procs));
+    ctx->hwc->hotplug(disp, connected);
+}
+
+void HWComposer::invalidate() {
+    mFlinger->repaintEverything();
+}
+
+void HWComposer::vsync(int disp, int64_t timestamp) {
+    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+        {
+            Mutex::Autolock _l(mLock);
+
+            // There have been reports of HWCs that signal several vsync events
+            // with the same timestamp when turning the display off and on. This
+            // is a bug in the HWC implementation, but filter the extra events
+            // out here so they don't cause havoc downstream.
+            if (timestamp == mLastHwVSync[disp]) {
+                ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
+                        timestamp);
+                return;
+            }
+
+            mLastHwVSync[disp] = timestamp;
+        }
+
+        char tag[16];
+        snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
+        ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
+
+        mEventHandler.onVSyncReceived(disp, timestamp);
+    }
+}
+
+void HWComposer::hotplug(int disp, int connected) {
+    if (disp >= VIRTUAL_DISPLAY_ID_BASE) {
+        ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
+                disp, connected);
+        return;
+    }
+    queryDisplayProperties(disp);
+    // Do not teardown or recreate the primary display
+    if (disp != HWC_DISPLAY_PRIMARY) {
+        mEventHandler.onHotplugReceived(disp, bool(connected));
+    }
+}
+
+static float getDefaultDensity(uint32_t width, uint32_t height) {
+    // Default density is based on TVs: 1080p displays get XHIGH density,
+    // lower-resolution displays get TV density. Maybe eventually we'll need
+    // to update it for 4K displays, though hopefully those just report
+    // accurate DPI information to begin with. This is also used for virtual
+    // displays and even primary displays with older hwcomposers, so be
+    // careful about orientation.
+
+    uint32_t h = width < height ? width : height;
+    if (h >= 1080) return ACONFIGURATION_DENSITY_XHIGH;
+    else           return ACONFIGURATION_DENSITY_TV;
+}
+
+static const uint32_t DISPLAY_ATTRIBUTES[] = {
+    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,
+};
+#define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
+
+static const uint32_t PRE_HWC15_DISPLAY_ATTRIBUTES[] = {
+    HWC_DISPLAY_VSYNC_PERIOD,
+    HWC_DISPLAY_WIDTH,
+    HWC_DISPLAY_HEIGHT,
+    HWC_DISPLAY_DPI_X,
+    HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+status_t HWComposer::queryDisplayProperties(int disp) {
+
+    LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
+
+    // use zero as default value for unspecified attributes
+    int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
+    memset(values, 0, sizeof(values));
+
+    const size_t MAX_NUM_CONFIGS = 128;
+    uint32_t configs[MAX_NUM_CONFIGS] = {0};
+    size_t numConfigs = MAX_NUM_CONFIGS;
+    status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs);
+    if (err != NO_ERROR) {
+        // this can happen if an unpluggable display is not connected
+        mDisplayData[disp].connected = false;
+        return err;
+    }
+
+    mDisplayData[disp].currentConfig = 0;
+    for (size_t c = 0; c < numConfigs; ++c) {
+        err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
+                DISPLAY_ATTRIBUTES, values);
+        // If this is a pre-1.5 HWC, it may not know about color transform, so
+        // try again with a smaller set of attributes
+        if (err != NO_ERROR) {
+            err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
+                    PRE_HWC15_DISPLAY_ATTRIBUTES, values);
+        }
+        if (err != NO_ERROR) {
+            // we can't get this display's info. turn it off.
+            mDisplayData[disp].connected = false;
+            return err;
+        }
+
+        DisplayConfig config = DisplayConfig();
+        for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
+            switch (DISPLAY_ATTRIBUTES[i]) {
+                case HWC_DISPLAY_VSYNC_PERIOD:
+                    config.refresh = nsecs_t(values[i]);
+                    break;
+                case HWC_DISPLAY_WIDTH:
+                    config.width = values[i];
+                    break;
+                case HWC_DISPLAY_HEIGHT:
+                    config.height = values[i];
+                    break;
+                case HWC_DISPLAY_DPI_X:
+                    config.xdpi = values[i] / 1000.0f;
+                    break;
+                case HWC_DISPLAY_DPI_Y:
+                    config.ydpi = values[i] / 1000.0f;
+                    break;
+                case HWC_DISPLAY_COLOR_TRANSFORM:
+                    config.colorTransform = values[i];
+                    break;
+                default:
+                    ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
+                            i, DISPLAY_ATTRIBUTES[i]);
+                    break;
+            }
+        }
+
+        if (config.xdpi == 0.0f || config.ydpi == 0.0f) {
+            float dpi = getDefaultDensity(config.width, config.height);
+            config.xdpi = dpi;
+            config.ydpi = dpi;
+        }
+
+        mDisplayData[disp].configs.push_back(config);
+    }
+
+    // FIXME: what should we set the format to?
+    mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
+    mDisplayData[disp].connected = true;
+    return NO_ERROR;
+}
+
+status_t HWComposer::setVirtualDisplayProperties(int32_t id,
+        uint32_t w, uint32_t h, uint32_t format) {
+    if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) ||
+            !mAllocatedDisplayIDs.hasBit(id)) {
+        return BAD_INDEX;
+    }
+    size_t configId = mDisplayData[id].currentConfig;
+    mDisplayData[id].format = format;
+    DisplayConfig& config = mDisplayData[id].configs.editItemAt(configId);
+    config.width = w;
+    config.height = h;
+    config.xdpi = config.ydpi = getDefaultDensity(w, h);
+    return NO_ERROR;
+}
+
+int32_t HWComposer::allocateDisplayId() {
+    if (mAllocatedDisplayIDs.count() >= mNumDisplays) {
+        return NO_MEMORY;
+    }
+    int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit();
+    mAllocatedDisplayIDs.markBit(id);
+    mDisplayData[id].connected = true;
+    mDisplayData[id].configs.resize(1);
+    mDisplayData[id].currentConfig = 0;
+    return id;
+}
+
+status_t HWComposer::freeDisplayId(int32_t id) {
+    if (id < NUM_BUILTIN_DISPLAYS) {
+        // cannot free the reserved IDs
+        return BAD_VALUE;
+    }
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
+        return BAD_INDEX;
+    }
+    mAllocatedDisplayIDs.clearBit(id);
+    mDisplayData[id].connected = false;
+    return NO_ERROR;
+}
+
+nsecs_t HWComposer::getRefreshTimestamp(int disp) const {
+    // this returns the last refresh timestamp.
+    // if the last one is not available, we estimate it based on
+    // the refresh period and whatever closest timestamp we have.
+    Mutex::Autolock _l(mLock);
+    nsecs_t now = systemTime(CLOCK_MONOTONIC);
+    size_t configId = mDisplayData[disp].currentConfig;
+    return now - ((now - mLastHwVSync[disp]) %
+            mDisplayData[disp].configs[configId].refresh);
+}
+
+sp<Fence> HWComposer::getDisplayFence(int disp) const {
+    return mDisplayData[disp].lastDisplayFence;
+}
+
+uint32_t HWComposer::getFormat(int disp) const {
+    if (static_cast<uint32_t>(disp) >= MAX_HWC_DISPLAYS || !mAllocatedDisplayIDs.hasBit(disp)) {
+        return HAL_PIXEL_FORMAT_RGBA_8888;
+    } else {
+        return mDisplayData[disp].format;
+    }
+}
+
+bool HWComposer::isConnected(int disp) const {
+    return mDisplayData[disp].connected;
+}
+
+uint32_t HWComposer::getWidth(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].width;
+}
+
+uint32_t HWComposer::getHeight(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].height;
+}
+
+float HWComposer::getDpiX(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].xdpi;
+}
+
+float HWComposer::getDpiY(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].ydpi;
+}
+
+nsecs_t HWComposer::getRefreshPeriod(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].refresh;
+}
+
+const Vector<HWComposer::DisplayConfig>& HWComposer::getConfigs(int disp) const {
+    return mDisplayData[disp].configs;
+}
+
+size_t HWComposer::getCurrentConfig(int disp) const {
+    return mDisplayData[disp].currentConfig;
+}
+
+void HWComposer::eventControl(int disp, int event, int enabled) {
+    if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
+        ALOGD("eventControl ignoring event %d on unallocated disp %d (en=%d)",
+              event, disp, enabled);
+        return;
+    }
+    if (event != EVENT_VSYNC) {
+        ALOGW("eventControl got unexpected event %d (disp=%d en=%d)",
+              event, disp, enabled);
+        return;
+    }
+    status_t err = NO_ERROR;
+    if (mHwc && !mDebugForceFakeVSync) {
+        // NOTE: we use our own internal lock here because we have to call
+        // into the HWC with the lock held, and we want to make sure
+        // that even if HWC blocks (which it shouldn't), it won't
+        // affect other threads.
+        Mutex::Autolock _l(mEventControlLock);
+        const int32_t eventBit = 1UL << event;
+        const int32_t newValue = enabled ? eventBit : 0;
+        const int32_t oldValue = mDisplayData[disp].events & eventBit;
+        if (newValue != oldValue) {
+            ATRACE_CALL();
+            err = mHwc->eventControl(mHwc, disp, event, enabled);
+            if (!err) {
+                int32_t& events(mDisplayData[disp].events);
+                events = (events & ~eventBit) | newValue;
+
+                char tag[16];
+                snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", disp);
+                ATRACE_INT(tag, enabled);
+            }
+        }
+        // error here should not happen -- not sure what we should
+        // do if it does.
+        ALOGE_IF(err, "eventControl(%d, %d) failed %s",
+                event, enabled, strerror(-err));
+    }
+
+    if (err == NO_ERROR && mVSyncThread != NULL) {
+        mVSyncThread->setEnabled(enabled);
+    }
+}
+
+status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
+        return BAD_INDEX;
+    }
+
+    if (mHwc) {
+        DisplayData& disp(mDisplayData[id]);
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            // we need space for the HWC_FRAMEBUFFER_TARGET
+            numLayers++;
+        }
+        if (disp.capacity < numLayers || disp.list == NULL) {
+            size_t size = sizeof(hwc_display_contents_1_t)
+                    + numLayers * sizeof(hwc_layer_1_t);
+            free(disp.list);
+            disp.list = (hwc_display_contents_1_t*)malloc(size);
+            disp.capacity = numLayers;
+        }
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
+            memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
+            const DisplayConfig& currentConfig =
+                    disp.configs[disp.currentConfig];
+            const hwc_rect_t r = { 0, 0,
+                    (int) currentConfig.width, (int) currentConfig.height };
+            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
+            disp.framebufferTarget->hints = 0;
+            disp.framebufferTarget->flags = 0;
+            disp.framebufferTarget->handle = disp.fbTargetHandle;
+            disp.framebufferTarget->transform = 0;
+            disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+                disp.framebufferTarget->sourceCropf.left = 0;
+                disp.framebufferTarget->sourceCropf.top = 0;
+                disp.framebufferTarget->sourceCropf.right =
+                        currentConfig.width;
+                disp.framebufferTarget->sourceCropf.bottom =
+                        currentConfig.height;
+            } else {
+                disp.framebufferTarget->sourceCrop = r;
+            }
+            disp.framebufferTarget->displayFrame = r;
+            disp.framebufferTarget->visibleRegionScreen.numRects = 1;
+            disp.framebufferTarget->visibleRegionScreen.rects =
+                &disp.framebufferTarget->displayFrame;
+            disp.framebufferTarget->acquireFenceFd = -1;
+            disp.framebufferTarget->releaseFenceFd = -1;
+            disp.framebufferTarget->planeAlpha = 0xFF;
+        }
+        disp.list->retireFenceFd = -1;
+        disp.list->flags = HWC_GEOMETRY_CHANGED;
+        disp.list->numHwLayers = numLayers;
+    }
+    return NO_ERROR;
+}
+
+status_t HWComposer::setFramebufferTarget(int32_t id,
+        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
+        return BAD_INDEX;
+    }
+    DisplayData& disp(mDisplayData[id]);
+    if (!disp.framebufferTarget) {
+        // this should never happen, but apparently eglCreateWindowSurface()
+        // triggers a Surface::queueBuffer()  on some
+        // devices (!?) -- log and ignore.
+        ALOGE("HWComposer: framebufferTarget is null");
+        return NO_ERROR;
+    }
+
+    int acquireFenceFd = -1;
+    if (acquireFence->isValid()) {
+        acquireFenceFd = acquireFence->dup();
+    }
+
+    // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);
+    disp.fbTargetHandle = buf->handle;
+    disp.framebufferTarget->handle = disp.fbTargetHandle;
+    disp.framebufferTarget->acquireFenceFd = acquireFenceFd;
+    return NO_ERROR;
+}
+
+status_t HWComposer::prepare() {
+    Mutex::Autolock _l(mDisplayLock);
+    for (size_t i=0 ; i<mNumDisplays ; i++) {
+        DisplayData& disp(mDisplayData[i]);
+        if (disp.framebufferTarget) {
+            // make sure to reset the type to HWC_FRAMEBUFFER_TARGET
+            // DO NOT reset the handle field to NULL, because it's possible
+            // that we have nothing to redraw (eg: eglSwapBuffers() not called)
+            // in which case, we should continue to use the same buffer.
+            LOG_FATAL_IF(disp.list == NULL);
+            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
+        }
+        if (!disp.connected && disp.list != NULL) {
+            ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",
+                  i, disp.list->numHwLayers);
+        }
+        mLists[i] = disp.list;
+        if (mLists[i]) {
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+                mLists[i]->outbuf = disp.outbufHandle;
+                mLists[i]->outbufAcquireFenceFd = -1;
+            } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+                // garbage data to catch improper use
+                mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
+                mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
+            } else {
+                mLists[i]->dpy = EGL_NO_DISPLAY;
+                mLists[i]->sur = EGL_NO_SURFACE;
+            }
+        }
+    }
+
+    int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
+    ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
+
+    if (err == NO_ERROR) {
+        // here we're just making sure that "skip" layers are set
+        // to HWC_FRAMEBUFFER and we're also counting how many layers
+        // we have of each type.
+        //
+        // If there are no window layers, we treat the display has having FB
+        // composition, because SurfaceFlinger will use GLES to draw the
+        // wormhole region.
+        for (size_t i=0 ; i<mNumDisplays ; i++) {
+            DisplayData& disp(mDisplayData[i]);
+            disp.hasFbComp = false;
+            disp.hasOvComp = false;
+            if (disp.list) {
+                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
+                    hwc_layer_1_t& l = disp.list->hwLayers[i];
+
+                    //ALOGD("prepare: %d, type=%d, handle=%p",
+                    //        i, l.compositionType, l.handle);
+
+                    if (l.flags & HWC_SKIP_LAYER) {
+                        l.compositionType = HWC_FRAMEBUFFER;
+                    }
+                    if (l.compositionType == HWC_FRAMEBUFFER) {
+                        disp.hasFbComp = true;
+                    }
+                    if (l.compositionType == HWC_OVERLAY) {
+                        disp.hasOvComp = true;
+                    }
+                    if (l.compositionType == HWC_CURSOR_OVERLAY) {
+                        disp.hasOvComp = true;
+                    }
+                }
+                if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
+                    disp.hasFbComp = true;
+                }
+            } else {
+                disp.hasFbComp = true;
+            }
+        }
+    }
+    return (status_t)err;
+}
+
+bool HWComposer::hasHwcComposition(int32_t id) const {
+    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return false;
+    return mDisplayData[id].hasOvComp;
+}
+
+bool HWComposer::hasGlesComposition(int32_t id) const {
+    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return true;
+    return mDisplayData[id].hasFbComp;
+}
+
+sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return Fence::NO_FENCE;
+
+    int fd = INVALID_OPERATION;
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        const DisplayData& disp(mDisplayData[id]);
+        if (disp.framebufferTarget) {
+            fd = disp.framebufferTarget->releaseFenceFd;
+            disp.framebufferTarget->acquireFenceFd = -1;
+            disp.framebufferTarget->releaseFenceFd = -1;
+        }
+    }
+    return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
+}
+
+status_t HWComposer::commit() {
+    int err = NO_ERROR;
+    if (mHwc) {
+        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            // On version 1.0, the OpenGL ES target surface is communicated
+            // by the (dpy, sur) fields and we are guaranteed to have only
+            // a single display.
+            mLists[0]->dpy = eglGetCurrentDisplay();
+            mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
+        }
+
+        for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
+            DisplayData& disp(mDisplayData[i]);
+            if (disp.outbufHandle) {
+                mLists[i]->outbuf = disp.outbufHandle;
+                mLists[i]->outbufAcquireFenceFd =
+                        disp.outbufAcquireFence->dup();
+            }
+        }
+
+        err = mHwc->set(mHwc, mNumDisplays, mLists);
+
+        for (size_t i=0 ; i<mNumDisplays ; i++) {
+            DisplayData& disp(mDisplayData[i]);
+            disp.lastDisplayFence = disp.lastRetireFence;
+            disp.lastRetireFence = Fence::NO_FENCE;
+            if (disp.list) {
+                if (disp.list->retireFenceFd != -1) {
+                    disp.lastRetireFence = new Fence(disp.list->retireFenceFd);
+                    disp.list->retireFenceFd = -1;
+                }
+                disp.list->flags &= ~HWC_GEOMETRY_CHANGED;
+            }
+        }
+    }
+    return (status_t)err;
+}
+
+status_t HWComposer::setPowerMode(int disp, int mode) {
+    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
+    if (mHwc) {
+        if (mode == HWC_POWER_MODE_OFF) {
+            eventControl(disp, HWC_EVENT_VSYNC, 0);
+        }
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
+            return (status_t)mHwc->setPowerMode(mHwc, disp, mode);
+        } else {
+            return (status_t)mHwc->blank(mHwc, disp,
+                    mode == HWC_POWER_MODE_OFF ? 1 : 0);
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t HWComposer::setActiveConfig(int disp, int mode) {
+    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
+    DisplayData& dd(mDisplayData[disp]);
+    dd.currentConfig = mode;
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
+        return (status_t)mHwc->setActiveConfig(mHwc, disp, mode);
+    } else {
+        LOG_FATAL_IF(mode != 0);
+    }
+    return NO_ERROR;
+}
+
+void HWComposer::disconnectDisplay(int disp) {
+    LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY);
+    DisplayData& dd(mDisplayData[disp]);
+    free(dd.list);
+    dd.list = NULL;
+    dd.framebufferTarget = NULL;    // points into dd.list
+    dd.fbTargetHandle = NULL;
+    dd.outbufHandle = NULL;
+    dd.lastRetireFence = Fence::NO_FENCE;
+    dd.lastDisplayFence = Fence::NO_FENCE;
+    dd.outbufAcquireFence = Fence::NO_FENCE;
+    // clear all the previous configs and repopulate when a new
+    // device is added
+    dd.configs.clear();
+}
+
+int HWComposer::getVisualID() const {
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
+        // is supported by the implementation. we can only be in this case
+        // if we have HWC 1.1
+        return HAL_PIXEL_FORMAT_RGBA_8888;
+        //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+    } else {
+        return mFbDev->format;
+    }
+}
+
+bool HWComposer::supportsFramebufferTarget() const {
+    return (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
+}
+
+int HWComposer::fbPost(int32_t id,
+        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        return setFramebufferTarget(id, acquireFence, buffer);
+    } else {
+        acquireFence->waitForever("HWComposer::fbPost");
+        return mFbDev->post(mFbDev, buffer->handle);
+    }
+}
+
+int HWComposer::fbCompositionComplete() {
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
+        return NO_ERROR;
+
+    if (mFbDev->compositionComplete) {
+        return mFbDev->compositionComplete(mFbDev);
+    } else {
+        return INVALID_OPERATION;
+    }
+}
+
+void HWComposer::fbDump(String8& result) {
+    if (mFbDev && mFbDev->common.version >= 1 && mFbDev->dump) {
+        const size_t SIZE = 4096;
+        char buffer[SIZE];
+        mFbDev->dump(mFbDev, buffer, SIZE);
+        result.append(buffer);
+    }
+}
+
+status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+        const sp<GraphicBuffer>& buf) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return BAD_INDEX;
+    if (id < VIRTUAL_DISPLAY_ID_BASE)
+        return INVALID_OPERATION;
+
+    DisplayData& disp(mDisplayData[id]);
+    disp.outbufHandle = buf->handle;
+    disp.outbufAcquireFence = acquireFence;
+    return NO_ERROR;
+}
+
+sp<Fence> HWComposer::getLastRetireFence(int32_t id) const {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return Fence::NO_FENCE;
+    return mDisplayData[id].lastRetireFence;
+}
+
+status_t HWComposer::setCursorPositionAsync(int32_t id, const Rect& pos)
+{
+    if (mHwc->setCursorPositionAsync) {
+        return (status_t)mHwc->setCursorPositionAsync(mHwc, id, pos.left, pos.top);
+    }
+    else {
+        return NO_ERROR;
+    }
+}
+
+/*
+ * Helper template to implement a concrete HWCLayer
+ * This holds the pointer to the concrete hwc layer type
+ * and implements the "iterable" side of HWCLayer.
+ */
+template<typename CONCRETE, typename HWCTYPE>
+class Iterable : public HWComposer::HWCLayer {
+protected:
+    HWCTYPE* const mLayerList;
+    HWCTYPE* mCurrentLayer;
+    Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer) { }
+    inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
+    inline HWCTYPE* getLayer() { return mCurrentLayer; }
+    virtual ~Iterable() { }
+private:
+    // returns a copy of ourselves
+    virtual HWComposer::HWCLayer* dup() {
+        return new CONCRETE( static_cast<const CONCRETE&>(*this) );
+    }
+    virtual status_t setLayer(size_t index) {
+        mCurrentLayer = &mLayerList[index];
+        return NO_ERROR;
+    }
+};
+
+/*
+ * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_1_0.
+ * This implements the HWCLayer side of HWCIterableLayer.
+ */
+class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
+    struct hwc_composer_device_1* mHwc;
+public:
+    HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer)
+        : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc) { }
+
+    virtual int32_t getCompositionType() const {
+        return getLayer()->compositionType;
+    }
+    virtual uint32_t getHints() const {
+        return getLayer()->hints;
+    }
+    virtual sp<Fence> getAndResetReleaseFence() {
+        int fd = getLayer()->releaseFenceFd;
+        getLayer()->releaseFenceFd = -1;
+        return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
+    }
+    virtual void setAcquireFenceFd(int fenceFd) {
+        getLayer()->acquireFenceFd = fenceFd;
+    }
+    virtual void setPerFrameDefaultState() {
+        //getLayer()->compositionType = HWC_FRAMEBUFFER;
+    }
+    virtual void setPlaneAlpha(uint8_t alpha) {
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
+            getLayer()->planeAlpha = alpha;
+        } else {
+            if (alpha < 0xFF) {
+                getLayer()->flags |= HWC_SKIP_LAYER;
+            }
+        }
+    }
+    virtual void setDefaultState() {
+        hwc_layer_1_t* const l = getLayer();
+        l->compositionType = HWC_FRAMEBUFFER;
+        l->hints = 0;
+        l->flags = HWC_SKIP_LAYER;
+        l->handle = 0;
+        l->transform = 0;
+        l->blending = HWC_BLENDING_NONE;
+        l->visibleRegionScreen.numRects = 0;
+        l->visibleRegionScreen.rects = NULL;
+        l->acquireFenceFd = -1;
+        l->releaseFenceFd = -1;
+        l->planeAlpha = 0xFF;
+    }
+    virtual void setSkip(bool skip) {
+        if (skip) {
+            getLayer()->flags |= HWC_SKIP_LAYER;
+        } else {
+            getLayer()->flags &= ~HWC_SKIP_LAYER;
+        }
+    }
+    virtual void setIsCursorLayerHint(bool isCursor) {
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
+            if (isCursor) {
+                getLayer()->flags |= HWC_IS_CURSOR_LAYER;
+            }
+            else {
+                getLayer()->flags &= ~HWC_IS_CURSOR_LAYER;
+            }
+        }
+    }
+    virtual void setBlending(uint32_t blending) {
+        getLayer()->blending = blending;
+    }
+    virtual void setTransform(uint32_t transform) {
+        getLayer()->transform = transform;
+    }
+    virtual void setFrame(const Rect& frame) {
+        getLayer()->displayFrame = reinterpret_cast<hwc_rect_t const&>(frame);
+    }
+    virtual void setCrop(const FloatRect& crop) {
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+            getLayer()->sourceCropf = reinterpret_cast<hwc_frect_t const&>(crop);
+        } else {
+            /*
+             * Since h/w composer didn't support a flot crop rect before version 1.3,
+             * using integer coordinates instead produces a different output from the GL code in
+             * Layer::drawWithOpenGL(). The difference can be large if the buffer crop to
+             * window size ratio is large and a window crop is defined
+             * (i.e.: if we scale the buffer a lot and we also crop it with a window crop).
+             */
+            hwc_rect_t& r = getLayer()->sourceCrop;
+            r.left  = int(ceilf(crop.left));
+            r.top   = int(ceilf(crop.top));
+            r.right = int(floorf(crop.right));
+            r.bottom= int(floorf(crop.bottom));
+        }
+    }
+    virtual void setVisibleRegionScreen(const Region& reg) {
+        hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
+        mVisibleRegion = reg;
+        visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(
+                mVisibleRegion.getArray(&visibleRegion.numRects));
+    }
+    virtual void setSurfaceDamage(const Region& reg) {
+        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
+            return;
+        }
+        hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
+        // We encode default full-screen damage as INVALID_RECT upstream, but as
+        // 0 rects for HWComposer
+        if (reg.isRect() && reg.getBounds() == Rect::INVALID_RECT) {
+            surfaceDamage.numRects = 0;
+            surfaceDamage.rects = NULL;
+            return;
+        }
+        mSurfaceDamage = reg;
+        surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(
+                mSurfaceDamage.getArray(&surfaceDamage.numRects));
+    }
+    virtual void setSidebandStream(const sp<NativeHandle>& stream) {
+        ALOG_ASSERT(stream->handle() != NULL);
+        getLayer()->compositionType = HWC_SIDEBAND;
+        getLayer()->sidebandStream = stream->handle();
+    }
+    virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
+        if (buffer == 0 || buffer->handle == 0) {
+            getLayer()->compositionType = HWC_FRAMEBUFFER;
+            getLayer()->flags |= HWC_SKIP_LAYER;
+            getLayer()->handle = 0;
+        } else {
+            if (getLayer()->compositionType == HWC_SIDEBAND) {
+                // If this was a sideband layer but the stream was removed, reset
+                // it to FRAMEBUFFER. The HWC can change it to OVERLAY in prepare.
+                getLayer()->compositionType = HWC_FRAMEBUFFER;
+            }
+            getLayer()->handle = buffer->handle;
+        }
+    }
+    virtual void onDisplayed() {
+        getLayer()->acquireFenceFd = -1;
+    }
+
+protected:
+    // We need to hold "copies" of these for memory management purposes. The
+    // actual hwc_layer_1_t holds pointers to the memory within. Vector<>
+    // internally doesn't copy the memory unless one of the copies is modified.
+    Region mVisibleRegion;
+    Region mSurfaceDamage;
+};
+
+/*
+ * returns an iterator initialized at a given index in the layer list
+ */
+HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
+        return LayerListIterator();
+    }
+    const DisplayData& disp(mDisplayData[id]);
+    if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
+        return LayerListIterator();
+    }
+    return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index);
+}
+
+/*
+ * returns an iterator on the beginning of the layer list
+ */
+HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
+    return getLayerIterator(id, 0);
+}
+
+/*
+ * returns an iterator on the end of the layer list
+ */
+HWComposer::LayerListIterator HWComposer::end(int32_t id) {
+    size_t numLayers = 0;
+    if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
+        const DisplayData& disp(mDisplayData[id]);
+        if (mHwc && disp.list) {
+            numLayers = disp.list->numHwLayers;
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+                // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
+                // which we ignore when iterating through the layer list.
+                ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
+                if (numLayers) {
+                    numLayers--;
+                }
+            }
+        }
+    }
+    return getLayerIterator(id, numLayers);
+}
+
+// Converts a PixelFormat to a human-readable string.  Max 11 chars.
+// (Could use a table of prefab String8 objects.)
+static String8 getFormatStr(PixelFormat format) {
+    switch (format) {
+    case PIXEL_FORMAT_RGBA_8888:    return String8("RGBA_8888");
+    case PIXEL_FORMAT_RGBX_8888:    return String8("RGBx_8888");
+    case PIXEL_FORMAT_RGB_888:      return String8("RGB_888");
+    case PIXEL_FORMAT_RGB_565:      return String8("RGB_565");
+    case PIXEL_FORMAT_BGRA_8888:    return String8("BGRA_8888");
+    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+                                    return String8("ImplDef");
+    default:
+        String8 result;
+        result.appendFormat("? %08x", format);
+        return result;
+    }
+}
+
+void HWComposer::dump(String8& result) const {
+    Mutex::Autolock _l(mDisplayLock);
+    if (mHwc) {
+        result.appendFormat("Hardware Composer state (version %08x):\n", hwcApiVersion(mHwc));
+        result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
+        for (size_t i=0 ; i<mNumDisplays ; i++) {
+            const DisplayData& disp(mDisplayData[i]);
+            if (!disp.connected)
+                continue;
+
+            const Vector< sp<Layer> >& visibleLayersSortedByZ =
+                    mFlinger->getLayerSortedByZForHwcDisplay(i);
+
+
+            result.appendFormat("  Display[%zd] configurations (* current):\n", i);
+            for (size_t c = 0; c < disp.configs.size(); ++c) {
+                const DisplayConfig& config(disp.configs[c]);
+                result.appendFormat("    %s%zd: %ux%u, xdpi=%f, ydpi=%f"
+                        ", refresh=%" PRId64 ", colorTransform=%d\n",
+                        c == disp.currentConfig ? "* " : "", c,
+                        config.width, config.height, config.xdpi, config.ydpi,
+                        config.refresh, config.colorTransform);
+            }
+
+            if (disp.list) {
+                result.appendFormat(
+                        "  numHwLayers=%zu, flags=%08x\n",
+                        disp.list->numHwLayers, disp.list->flags);
+
+                result.append(
+                        "    type   |  handle  | hint | flag | tr | blnd |   format    |     source crop (l,t,r,b)      |          frame         | name \n"
+                        "-----------+----------+------+------+----+------+-------------+--------------------------------+------------------------+------\n");
+                //      " _________ | ________ | ____ | ____ | __ | ____ | ___________ |_____._,_____._,_____._,_____._ |_____,_____,_____,_____ | ___...
+                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
+                    const hwc_layer_1_t&l = disp.list->hwLayers[i];
+                    int32_t format = -1;
+                    String8 name("unknown");
+
+                    if (i < visibleLayersSortedByZ.size()) {
+                        const sp<Layer>& layer(visibleLayersSortedByZ[i]);
+                        const sp<GraphicBuffer>& buffer(
+                                layer->getActiveBuffer());
+                        if (buffer != NULL) {
+                            format = buffer->getPixelFormat();
+                        }
+                        name = layer->getName();
+                    }
+
+                    int type = l.compositionType;
+                    if (type == HWC_FRAMEBUFFER_TARGET) {
+                        name = "HWC_FRAMEBUFFER_TARGET";
+                        format = disp.format;
+                    }
+
+                    static char const* compositionTypeName[] = {
+                            "GLES",
+                            "HWC",
+                            "BKGND",
+                            "FB TARGET",
+                            "SIDEBAND",
+                            "HWC_CURSOR",
+                            "UNKNOWN"};
+                    if (type >= NELEM(compositionTypeName))
+                        type = NELEM(compositionTypeName) - 1;
+
+                    String8 formatStr = getFormatStr(format);
+                    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+                        result.appendFormat(
+                                " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d | %s\n",
+                                        compositionTypeName[type],
+                                        intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
+                                        l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom,
+                                        l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
+                                        name.string());
+                    } else {
+                        result.appendFormat(
+                                " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7d,%7d,%7d,%7d |%5d,%5d,%5d,%5d | %s\n",
+                                        compositionTypeName[type],
+                                        intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
+                                        l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
+                                        l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
+                                        name.string());
+                    }
+                }
+            }
+        }
+    }
+
+    if (mHwc && mHwc->dump) {
+        const size_t SIZE = 4096;
+        char buffer[SIZE];
+        mHwc->dump(mHwc, buffer, SIZE);
+        result.append(buffer);
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
+    : mHwc(hwc), mEnabled(false),
+      mNextFakeVSync(0),
+      mRefreshPeriod(hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY))
+{
+}
+
+void HWComposer::VSyncThread::setEnabled(bool enabled) {
+    Mutex::Autolock _l(mLock);
+    if (mEnabled != enabled) {
+        mEnabled = enabled;
+        mCondition.signal();
+    }
+}
+
+void HWComposer::VSyncThread::onFirstRef() {
+    run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
+}
+
+bool HWComposer::VSyncThread::threadLoop() {
+    { // scope for lock
+        Mutex::Autolock _l(mLock);
+        while (!mEnabled) {
+            mCondition.wait(mLock);
+        }
+    }
+
+    const nsecs_t period = mRefreshPeriod;
+    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+    nsecs_t next_vsync = mNextFakeVSync;
+    nsecs_t sleep = next_vsync - now;
+    if (sleep < 0) {
+        // we missed, find where the next vsync should be
+        sleep = (period - ((now - next_vsync) % period));
+        next_vsync = now + sleep;
+    }
+    mNextFakeVSync = next_vsync + period;
+
+    struct timespec spec;
+    spec.tv_sec  = next_vsync / 1000000000;
+    spec.tv_nsec = next_vsync % 1000000000;
+
+    int err;
+    do {
+        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
+    } while (err<0 && errno == EINTR);
+
+    if (err == 0) {
+        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
+    }
+
+    return true;
+}
+
+HWComposer::DisplayData::DisplayData()
+:   configs(),
+    currentConfig(0),
+    format(HAL_PIXEL_FORMAT_RGBA_8888),
+    connected(false),
+    hasFbComp(false), hasOvComp(false),
+    capacity(0), list(NULL),
+    framebufferTarget(NULL), fbTargetHandle(0),
+    lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE),
+    outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE),
+    events(0)
+{}
+
+HWComposer::DisplayData::~DisplayData() {
+    free(list);
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
new file mode 100644
index 0000000..f5f7d77
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_HWCOMPOSER_HWC1_H
+#define ANDROID_SF_HWCOMPOSER_HWC1_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <hardware/hwcomposer_defs.h>
+
+#include <ui/Fence.h>
+
+#include <utils/BitSet.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
+#include <utils/Thread.h>
+#include <utils/Timers.h>
+#include <utils/Vector.h>
+
+extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
+                           const struct timespec *request,
+                           struct timespec *remain);
+
+struct hwc_composer_device_1;
+struct hwc_display_contents_1;
+struct hwc_layer_1;
+struct hwc_procs;
+struct framebuffer_device_t;
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Fence;
+class FloatRect;
+class GraphicBuffer;
+class NativeHandle;
+class Region;
+class String8;
+class SurfaceFlinger;
+
+class HWComposer
+{
+public:
+    class EventHandler {
+        friend class HWComposer;
+        virtual void onVSyncReceived(int disp, nsecs_t timestamp) = 0;
+        virtual void onHotplugReceived(int disp, bool connected) = 0;
+    protected:
+        virtual ~EventHandler() {}
+    };
+
+    enum {
+        NUM_BUILTIN_DISPLAYS = HWC_NUM_PHYSICAL_DISPLAY_TYPES,
+        MAX_HWC_DISPLAYS = HWC_NUM_DISPLAY_TYPES,
+        VIRTUAL_DISPLAY_ID_BASE = HWC_DISPLAY_VIRTUAL,
+    };
+
+    HWComposer(
+            const sp<SurfaceFlinger>& flinger,
+            EventHandler& handler);
+
+    ~HWComposer();
+
+    status_t initCheck() const;
+
+    // Returns a display ID starting at VIRTUAL_DISPLAY_ID_BASE, this ID is to
+    // be used with createWorkList (and all other methods requiring an ID
+    // below).
+    // IDs below NUM_BUILTIN_DISPLAYS are pre-defined and therefore are
+    // always valid.
+    // Returns -1 if an ID cannot be allocated
+    int32_t allocateDisplayId();
+
+    // Recycles the given virtual display ID and frees the associated worklist.
+    // IDs below NUM_BUILTIN_DISPLAYS are not recycled.
+    status_t freeDisplayId(int32_t id);
+
+
+    // Asks the HAL what it can do
+    status_t prepare();
+
+    // commits the list
+    status_t commit();
+
+    // set power mode
+    status_t setPowerMode(int disp, int mode);
+
+    // set active config
+    status_t setActiveConfig(int disp, int mode);
+
+    // reset state when an external, non-virtual display is disconnected
+    void disconnectDisplay(int disp);
+
+    // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
+    status_t createWorkList(int32_t id, size_t numLayers);
+
+    bool supportsFramebufferTarget() const;
+
+    // does this display have layers handled by HWC
+    bool hasHwcComposition(int32_t id) const;
+
+    // does this display have layers handled by GLES
+    bool hasGlesComposition(int32_t id) const;
+
+    // get the releaseFence file descriptor for a display's framebuffer layer.
+    // the release fence is only valid after commit()
+    sp<Fence> getAndResetReleaseFence(int32_t id);
+
+    // needed forward declarations
+    class LayerListIterator;
+
+    // return the visual id to be used to find a suitable EGLConfig for
+    // *ALL* displays.
+    int getVisualID() const;
+
+    // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
+    int fbPost(int32_t id, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
+    int fbCompositionComplete();
+    void fbDump(String8& result);
+
+    // Set the output buffer and acquire fence for a virtual display.
+    // Returns INVALID_OPERATION if id is not a virtual display.
+    status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+            const sp<GraphicBuffer>& buf);
+
+    // Get the retire fence for the last committed frame. This fence will
+    // signal when the h/w composer is completely finished with the frame.
+    // For physical displays, it is no longer being displayed. For virtual
+    // displays, writes to the output buffer are complete.
+    sp<Fence> getLastRetireFence(int32_t id) const;
+
+    status_t setCursorPositionAsync(int32_t id, const Rect &pos);
+
+    /*
+     * Interface to hardware composer's layers functionality.
+     * This abstracts the HAL interface to layers which can evolve in
+     * incompatible ways from one release to another.
+     * The idea is that we could extend this interface as we add
+     * features to h/w composer.
+     */
+    class HWCLayerInterface {
+    protected:
+        virtual ~HWCLayerInterface() { }
+    public:
+        virtual int32_t getCompositionType() const = 0;
+        virtual uint32_t getHints() const = 0;
+        virtual sp<Fence> getAndResetReleaseFence() = 0;
+        virtual void setDefaultState() = 0;
+        virtual void setSkip(bool skip) = 0;
+        virtual void setIsCursorLayerHint(bool isCursor = true) = 0;
+        virtual void setBlending(uint32_t blending) = 0;
+        virtual void setTransform(uint32_t transform) = 0;
+        virtual void setFrame(const Rect& frame) = 0;
+        virtual void setCrop(const FloatRect& crop) = 0;
+        virtual void setVisibleRegionScreen(const Region& reg) = 0;
+        virtual void setSurfaceDamage(const Region& reg) = 0;
+        virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
+        virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
+        virtual void setAcquireFenceFd(int fenceFd) = 0;
+        virtual void setPlaneAlpha(uint8_t alpha) = 0;
+        virtual void onDisplayed() = 0;
+    };
+
+    /*
+     * Interface used to implement an iterator to a list
+     * of HWCLayer.
+     */
+    class HWCLayer : public HWCLayerInterface {
+        friend class LayerListIterator;
+        // select the layer at the given index
+        virtual status_t setLayer(size_t index) = 0;
+        virtual HWCLayer* dup() = 0;
+        static HWCLayer* copy(HWCLayer *rhs) {
+            return rhs ? rhs->dup() : NULL;
+        }
+    protected:
+        virtual ~HWCLayer() { }
+    };
+
+    /*
+     * Iterator through a HWCLayer list.
+     * This behaves more or less like a forward iterator.
+     */
+    class LayerListIterator {
+        friend class HWComposer;
+        HWCLayer* const mLayerList;
+        size_t mIndex;
+
+        LayerListIterator() : mLayerList(NULL), mIndex(0) { }
+
+        LayerListIterator(HWCLayer* layer, size_t index)
+            : mLayerList(layer), mIndex(index) { }
+
+        // we don't allow assignment, because we don't need it for now
+        LayerListIterator& operator = (const LayerListIterator& rhs);
+
+    public:
+        // copy operators
+        LayerListIterator(const LayerListIterator& rhs)
+            : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) {
+        }
+
+        ~LayerListIterator() { delete mLayerList; }
+
+        // pre-increment
+        LayerListIterator& operator++() {
+            mLayerList->setLayer(++mIndex);
+            return *this;
+        }
+
+        // dereference
+        HWCLayerInterface& operator * () { return *mLayerList; }
+        HWCLayerInterface* operator -> () { return mLayerList; }
+
+        // comparison
+        bool operator == (const LayerListIterator& rhs) const {
+            return mIndex == rhs.mIndex;
+        }
+        bool operator != (const LayerListIterator& rhs) const {
+            return !operator==(rhs);
+        }
+    };
+
+    // Returns an iterator to the beginning of the layer list
+    LayerListIterator begin(int32_t id);
+
+    // Returns an iterator to the end of the layer list
+    LayerListIterator end(int32_t id);
+
+
+    // Events handling ---------------------------------------------------------
+
+    enum {
+        EVENT_VSYNC = HWC_EVENT_VSYNC
+    };
+
+    void eventControl(int disp, int event, int enabled);
+
+    struct DisplayConfig {
+        uint32_t width;
+        uint32_t height;
+        float xdpi;
+        float ydpi;
+        nsecs_t refresh;
+        int colorTransform;
+    };
+
+    // Query display parameters.  Pass in a display index (e.g.
+    // HWC_DISPLAY_PRIMARY).
+    nsecs_t getRefreshTimestamp(int disp) const;
+    sp<Fence> getDisplayFence(int disp) const;
+    uint32_t getFormat(int disp) const;
+    bool isConnected(int disp) const;
+
+    // These return the values for the current config of a given display index.
+    // To get the values for all configs, use getConfigs below.
+    uint32_t getWidth(int disp) const;
+    uint32_t getHeight(int disp) const;
+    float getDpiX(int disp) const;
+    float getDpiY(int disp) const;
+    nsecs_t getRefreshPeriod(int disp) const;
+
+    const Vector<DisplayConfig>& getConfigs(int disp) const;
+    size_t getCurrentConfig(int disp) const;
+
+    status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h,
+            uint32_t format);
+
+    // this class is only used to fake the VSync event on systems that don't
+    // have it.
+    class VSyncThread : public Thread {
+        HWComposer& mHwc;
+        mutable Mutex mLock;
+        Condition mCondition;
+        bool mEnabled;
+        mutable nsecs_t mNextFakeVSync;
+        nsecs_t mRefreshPeriod;
+        virtual void onFirstRef();
+        virtual bool threadLoop();
+    public:
+        VSyncThread(HWComposer& hwc);
+        void setEnabled(bool enabled);
+    };
+
+    friend class VSyncThread;
+
+    // for debugging ----------------------------------------------------------
+    void dump(String8& out) const;
+
+private:
+    void loadHwcModule();
+    int loadFbHalModule();
+
+    LayerListIterator getLayerIterator(int32_t id, size_t index);
+
+    struct cb_context;
+
+    static void hook_invalidate(const struct hwc_procs* procs);
+    static void hook_vsync(const struct hwc_procs* procs, int disp,
+            int64_t timestamp);
+    static void hook_hotplug(const struct hwc_procs* procs, int disp,
+            int connected);
+
+    inline void invalidate();
+    inline void vsync(int disp, int64_t timestamp);
+    inline void hotplug(int disp, int connected);
+
+    status_t queryDisplayProperties(int disp);
+
+    status_t setFramebufferTarget(int32_t id,
+            const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
+
+    struct DisplayData {
+        DisplayData();
+        ~DisplayData();
+        Vector<DisplayConfig> configs;
+        size_t currentConfig;
+        uint32_t format;    // pixel format from FB hal, for pre-hwc-1.1
+        bool connected;
+        bool hasFbComp;
+        bool hasOvComp;
+        size_t capacity;
+        hwc_display_contents_1* list;
+        hwc_layer_1* framebufferTarget;
+        buffer_handle_t fbTargetHandle;
+        sp<Fence> lastRetireFence;  // signals when the last set op retires
+        sp<Fence> lastDisplayFence; // signals when the last set op takes
+                                    // effect on screen
+        buffer_handle_t outbufHandle;
+        sp<Fence> outbufAcquireFence;
+
+        // protected by mEventControlLock
+        int32_t events;
+    };
+
+    sp<SurfaceFlinger>              mFlinger;
+    framebuffer_device_t*           mFbDev;
+    struct hwc_composer_device_1*   mHwc;
+    // invariant: mLists[0] != NULL iff mHwc != NULL
+    // mLists[i>0] can be NULL. that display is to be ignored
+    struct hwc_display_contents_1*  mLists[MAX_HWC_DISPLAYS];
+    DisplayData                     mDisplayData[MAX_HWC_DISPLAYS];
+    // protect mDisplayData from races between prepare and dump
+    mutable Mutex mDisplayLock;
+    size_t                          mNumDisplays;
+
+    cb_context*                     mCBContext;
+    EventHandler&                   mEventHandler;
+    size_t                          mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
+    sp<VSyncThread>                 mVSyncThread;
+    bool                            mDebugForceFakeVSync;
+    BitSet32                        mAllocatedDisplayIDs;
+
+    // protected by mLock
+    mutable Mutex mLock;
+    mutable nsecs_t mLastHwVSync[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
+
+    // thread-safe
+    mutable Mutex mEventControlLock;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SF_HWCOMPOSER_H
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 1a0d689..1afed36 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -57,8 +57,20 @@
     mHwc(hwc),
     mDisplayId(dispId),
     mDisplayName(name),
+    mSource{},
+    mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
+    mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
     mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
     mProducerSlotSource(0),
+    mProducerBuffers(),
+    mQueueBufferOutput(),
+    mSinkBufferWidth(0),
+    mSinkBufferHeight(0),
+    mCompositionType(COMPOSITION_UNKNOWN),
+    mFbFence(Fence::NO_FENCE),
+    mOutputFence(Fence::NO_FENCE),
+    mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
+    mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
     mDbgState(DBG_STATE_IDLE),
     mDbgLastCompositionType(COMPOSITION_UNKNOWN),
     mMustRecompose(false)
@@ -163,9 +175,11 @@
     return NO_ERROR;
 }
 
+#ifndef USE_HWC2
 status_t VirtualDisplaySurface::compositionComplete() {
     return NO_ERROR;
 }
+#endif
 
 status_t VirtualDisplaySurface::advanceFrame() {
     if (mDisplayId < 0)
@@ -206,7 +220,13 @@
 
     status_t result = NO_ERROR;
     if (fbBuffer != NULL) {
+#ifdef USE_HWC2
+        // TODO: Correctly propagate the dataspace from GL composition
+        result = mHwc.setClientTarget(mDisplayId, mFbFence, fbBuffer,
+                HAL_DATASPACE_UNKNOWN);
+#else
         result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
+#endif
     }
 
     return result;
@@ -220,13 +240,22 @@
             "Unexpected onFrameCommitted() in %s state", dbgStateStr());
     mDbgState = DBG_STATE_IDLE;
 
+#ifdef USE_HWC2
+    sp<Fence> retireFence = mHwc.getRetireFence(mDisplayId);
+#else
     sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
+#endif
     if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
         // release the scratch buffer back to the pool
         Mutex::Autolock lock(mMutex);
         int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
         VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot);
+#ifdef USE_HWC2
+        addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot],
+                retireFence);
+#else
         addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], fbFence);
+#endif
         releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot],
                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
     }
@@ -234,7 +263,9 @@
     if (mOutputProducerSlot >= 0) {
         int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
         QueueBufferOutput qbo;
+#ifndef USE_HWC2
         sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
+#endif
         VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
         if (mMustRecompose) {
             status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
@@ -243,7 +274,11 @@
                         HAL_DATASPACE_UNKNOWN,
                         Rect(mSinkBufferWidth, mSinkBufferHeight),
                         NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
+#ifdef USE_HWC2
+                        retireFence),
+#else
                         outFence),
+#endif
                     &qbo);
             if (result == NO_ERROR) {
                 updateQueueBufferOutput(qbo);
@@ -253,7 +288,11 @@
             // through the motions of updating the display to keep our state
             // machine happy. We cancel the buffer to avoid triggering another
             // re-composition and causing an infinite loop.
+#ifdef USE_HWC2
+            mSource[SOURCE_SINK]->cancelBuffer(sslot, retireFence);
+#else
             mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence);
+#endif
         }
     }
 
@@ -272,6 +311,12 @@
     mSinkBufferHeight = h;
 }
 
+#ifdef USE_HWC2
+const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
+    return mFbFence;
+}
+#endif
+
 status_t VirtualDisplaySurface::requestBuffer(int pslot,
         sp<GraphicBuffer>* outBuf) {
     if (mDisplayId < 0)
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index ede204c..fe187c2 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -83,11 +83,16 @@
     //
     virtual status_t beginFrame(bool mustRecompose);
     virtual status_t prepareFrame(CompositionType compositionType);
+#ifndef USE_HWC2
     virtual status_t compositionComplete();
+#endif
     virtual status_t advanceFrame();
     virtual void onFrameCommitted();
     virtual void dumpAsString(String8& result) const;
     virtual void resizeBuffers(const uint32_t w, const uint32_t h);
+#ifdef USE_HWC2
+    virtual const sp<Fence>& getClientTargetAcquireFence() const override;
+#endif
 
 private:
     enum Source {SOURCE_SINK = 0, SOURCE_SCRATCH = 1};