Emulator HWC2 HAL implementation

Test: go/emu-hwc2

Bug: 78773713
Change-Id: I4023803c8c91d18c658a751c2cc48c244af1c75d
diff --git a/Android.mk b/Android.mk
index 39b8144..c9eae70 100644
--- a/Android.mk
+++ b/Android.mk
@@ -137,4 +137,9 @@
 
 include $(GOLDFISH_OPENGL_PATH)/system/vulkan/Android.mk
 
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -gt 28 -o $(IS_AT_LEAST_QPR1) = true && echo isApi29OrHigher),isApi29OrHigher)
+    # HWC2 enabled after P
+    include $(GOLDFISH_OPENGL_PATH)/system/hwc2/Android.mk
+endif
+
 endif
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index b3788fa..790994e 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -226,6 +226,7 @@
         queryAndSetDmaImpl(m_rcEnc);
         queryAndSetGLESMaxVersion(m_rcEnc);
         queryAndSetNoErrorState(m_rcEnc);
+        queryAndSetHostCompositionImpl(m_rcEnc);
         if (m_processPipe) {
             m_processPipe->processPipeInit(m_rcEnc);
         }
@@ -279,6 +280,17 @@
     return m_glExtensions;
 }
 
+void HostConnection::queryAndSetHostCompositionImpl(ExtendedRCEncoderContext *rcEnc) {
+    const std::string& glExtensions = queryGLExtensions(rcEnc);
+    ALOGD("HostComposition ext %s", glExtensions.c_str());
+    if (glExtensions.find(kHostCompositionV1) != std::string::npos) {
+        rcEnc->setHostComposition(HOST_COMPOSITION_V1);
+    }
+    else {
+        rcEnc->setHostComposition(HOST_COMPOSITION_NONE);
+    }
+}
+
 void HostConnection::setChecksumHelper(ExtendedRCEncoderContext *rcEnc) {
     const std::string& glExtensions = queryGLExtensions(rcEnc);
     // check the host supported version
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index 9c0d2b0..c19693c 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -72,6 +72,12 @@
 static const char kGLESMaxVersion_3_1[] = "ANDROID_EMU_gles_max_version_3_1";
 static const char kGLESMaxVersion_3_2[] = "ANDROID_EMU_gles_max_version_3_2";
 
+enum HostComposition {
+    HOST_COMPOSITION_NONE = 0,
+    HOST_COMPOSITION_V1,
+};
+static const char kHostCompositionV1[] = "ANDROID_EMU_host_composition_v1";
+
 // No querying errors from host extension
 static const char kGLESNoHostError[] = "ANDROID_EMU_gles_no_host_error";
 
@@ -85,8 +91,12 @@
         }
     void setSyncImpl(SyncImpl syncImpl) { m_syncImpl = syncImpl; }
     void setDmaImpl(DmaImpl dmaImpl) { m_dmaImpl = dmaImpl; }
+    void setHostComposition(HostComposition hostComposition) {
+        m_hostComposition = hostComposition; }
     bool hasNativeSync() const { return m_syncImpl >= SYNC_IMPL_NATIVE_SYNC_V2; }
     bool hasNativeSyncV3() const { return m_syncImpl >= SYNC_IMPL_NATIVE_SYNC_V3; }
+    bool hasHostCompositionV1() const {
+        return m_hostComposition == HOST_COMPOSITION_V1; }
     DmaImpl getDmaVersion() const { return m_dmaImpl; }
     void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
     virtual uint64_t lockAndWriteDma(void* data, uint32_t size) {
@@ -107,6 +117,7 @@
 private:
     SyncImpl m_syncImpl;
     DmaImpl m_dmaImpl;
+    HostComposition m_hostComposition;
     struct goldfish_dma_context* m_dmaCxt;
     GLESMaxVersion m_glesMaxVersion;
 };
@@ -167,6 +178,7 @@
     void queryAndSetDmaImpl(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetGLESMaxVersion(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetNoErrorState(ExtendedRCEncoderContext *rcEnc);
+    void queryAndSetHostCompositionImpl(ExtendedRCEncoderContext *rcEnc);
 
 private:
     IOStream *m_stream;
diff --git a/system/hwc2/Android.mk b/system/hwc2/Android.mk
new file mode 100644
index 0000000..a3bf20f
--- /dev/null
+++ b/system/hwc2/Android.mk
@@ -0,0 +1,61 @@
+#
+# Copyright 2015 The Android Open-Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
+emulator_hwcomposer_shared_libraries := \
+    liblog \
+    libutils \
+    libcutils \
+    libEGL \
+    libutils \
+    libhardware \
+    libsync \
+    libui \
+
+emulator_hwcomposer_cflags += \
+    -DLOG_TAG=\"hwc2\"
+
+emulator_hwcomposer_c_includes += \
+    system/core/libsync \
+    system/core/libsync/include \
+    device/generic/goldfish-opengl/system/include \
+    device/generic/goldfish-opengl/system/OpenglSystemCommon \
+    device/generic/goldfish-opengl/host/include/libOpenglRender \
+    device/generic/goldfish-opengl/shared/OpenglCodecCommon \
+    device/generic/goldfish-opengl/system/renderControl_enc
+
+emulator_hwcomposer_relative_path := hw
+
+emulator_hwcomposer2_src_files := \
+    EmuHWC2.cpp \
+    MiniFence.cpp
+
+include $(CLEAR_VARS)
+
+LOCAL_VENDOR_MODULE := true
+LOCAL_SHARED_LIBRARIES := $(emulator_hwcomposer_shared_libraries)
+LOCAL_SHARED_LIBRARIES += libOpenglSystemCommon lib_renderControl_enc
+LOCAL_SRC_FILES := $(emulator_hwcomposer2_src_files)
+LOCAL_C_INCLUDES := $(emulator_hwcomposer_c_includes)
+LOCAL_MODULE_RELATIVE_PATH := $(emulator_hwcomposer_relative_path)
+
+LOCAL_MODULE := hwcomposer.ranchu
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/system/hwc2/EmuHWC2.cpp b/system/hwc2/EmuHWC2.cpp
new file mode 100644
index 0000000..37466a1
--- /dev/null
+++ b/system/hwc2/EmuHWC2.cpp
@@ -0,0 +1,1336 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EmuHWC2.h"
+#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "EmuHWC2"
+
+#include <errno.h>
+#include <log/log.h>
+#include <sync/sync.h>
+
+#if defined(LOG_NNDEBUG) && LOG_NNDEBUG == 0
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function)
+{
+    static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+    return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+#define DEFINE_AND_VALIDATE_HOST_CONNECTION \
+    HostConnection *hostCon = HostConnection::get(); \
+    if (!hostCon) { \
+        ALOGE("EmuHWC2: Failed to get host connection\n"); \
+        return Error::NoResources; \
+    } \
+    ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
+    if (!rcEnc) { \
+        ALOGE("EmuHWC2: Failed to get renderControl encoder context\n"); \
+        return Error::NoResources; \
+    }
+
+
+using namespace HWC2;
+
+namespace android {
+
+EmuHWC2::EmuHWC2()
+  : mStateMutex()
+{
+    common.tag = HARDWARE_DEVICE_TAG;
+    common.version = HWC_DEVICE_API_VERSION_2_0;
+    common.close = closeHook;
+    getCapabilities = getCapabilitiesHook;
+    getFunction = getFunctionHook;
+    populateCapabilities();
+}
+
+void EmuHWC2::doGetCapabilities(uint32_t* outCount, int32_t* outCapabilities) {
+    if (outCapabilities == nullptr) {
+        *outCount = mCapabilities.size();
+        return;
+    }
+
+    auto capabilityIter = mCapabilities.cbegin();
+    for (size_t i = 0; i < *outCount; ++i) {
+        if (capabilityIter == mCapabilities.cend()) {
+            return;
+        }
+        outCapabilities[i] = static_cast<int32_t>(*capabilityIter);
+        ++capabilityIter;
+    }
+}
+
+hwc2_function_pointer_t EmuHWC2::doGetFunction(
+        FunctionDescriptor descriptor) {
+    switch(descriptor) {
+        case FunctionDescriptor::CreateVirtualDisplay:
+            return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
+                    createVirtualDisplayHook);
+        case FunctionDescriptor::DestroyVirtualDisplay:
+            return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
+                    destroyVirtualDisplayHook);
+        case FunctionDescriptor::Dump:
+            return asFP<HWC2_PFN_DUMP>(dumpHook);
+        case FunctionDescriptor::GetMaxVirtualDisplayCount:
+            return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
+                    getMaxVirtualDisplayCountHook);
+        case FunctionDescriptor::RegisterCallback:
+            return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+            // Display functions
+        case FunctionDescriptor::AcceptDisplayChanges:
+            return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
+                    displayHook<decltype(&Display::acceptChanges),
+                    &Display::acceptChanges>);
+        case FunctionDescriptor::CreateLayer:
+            return asFP<HWC2_PFN_CREATE_LAYER>(
+                    displayHook<decltype(&Display::createLayer),
+                    &Display::createLayer, hwc2_layer_t*>);
+        case FunctionDescriptor::DestroyLayer:
+            return asFP<HWC2_PFN_DESTROY_LAYER>(
+                    displayHook<decltype(&Display::destroyLayer),
+                    &Display::destroyLayer, hwc2_layer_t>);
+        case FunctionDescriptor::GetActiveConfig:
+            return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(
+                    displayHook<decltype(&Display::getActiveConfig),
+                    &Display::getActiveConfig, hwc2_config_t*>);
+        case FunctionDescriptor::GetChangedCompositionTypes:
+            return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
+                    displayHook<decltype(&Display::getChangedCompositionTypes),
+                    &Display::getChangedCompositionTypes, uint32_t*,
+                    hwc2_layer_t*, int32_t*>);
+        case FunctionDescriptor::GetColorModes:
+            return asFP<HWC2_PFN_GET_COLOR_MODES>(
+                    displayHook<decltype(&Display::getColorModes),
+                    &Display::getColorModes, uint32_t*, int32_t*>);
+        case FunctionDescriptor::GetDisplayAttribute:
+            return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
+                    displayHook<decltype(&Display::getDisplayAttribute),
+                    &Display::getDisplayAttribute, hwc2_config_t,
+                    int32_t, int32_t*>);
+        case FunctionDescriptor::GetDisplayConfigs:
+            return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(
+                    displayHook<decltype(&Display::getConfigs),
+                    &Display::getConfigs, uint32_t*, hwc2_config_t*>);
+        case FunctionDescriptor::GetDisplayName:
+            return asFP<HWC2_PFN_GET_DISPLAY_NAME>(
+                    displayHook<decltype(&Display::getName),
+                    &Display::getName, uint32_t*, char*>);
+        case FunctionDescriptor::GetDisplayRequests:
+            return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(
+                    displayHook<decltype(&Display::getRequests),
+                    &Display::getRequests, int32_t*, uint32_t*, hwc2_layer_t*,
+                    int32_t*>);
+        case FunctionDescriptor::GetDisplayType:
+            return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(
+                    displayHook<decltype(&Display::getType),
+                    &Display::getType, int32_t*>);
+        case FunctionDescriptor::GetDozeSupport:
+            return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(
+                    displayHook<decltype(&Display::getDozeSupport),
+                    &Display::getDozeSupport, int32_t*>);
+        case FunctionDescriptor::GetHdrCapabilities:
+            return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(
+                    displayHook<decltype(&Display::getHdrCapabilities),
+                    &Display::getHdrCapabilities, uint32_t*, int32_t*, float*,
+                    float*, float*>);
+        case FunctionDescriptor::GetReleaseFences:
+            return asFP<HWC2_PFN_GET_RELEASE_FENCES>(
+                    displayHook<decltype(&Display::getReleaseFences),
+                    &Display::getReleaseFences, uint32_t*, hwc2_layer_t*,
+                    int32_t*>);
+        case FunctionDescriptor::PresentDisplay:
+            return asFP<HWC2_PFN_PRESENT_DISPLAY>(
+                    displayHook<decltype(&Display::present),
+                    &Display::present, int32_t*>);
+        case FunctionDescriptor::SetActiveConfig:
+            return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(
+                    displayHook<decltype(&Display::setActiveConfig),
+                    &Display::setActiveConfig, hwc2_config_t>);
+        case FunctionDescriptor::SetClientTarget:
+            return asFP<HWC2_PFN_SET_CLIENT_TARGET>(
+                    displayHook<decltype(&Display::setClientTarget),
+                    &Display::setClientTarget, buffer_handle_t, int32_t,
+                    int32_t, hwc_region_t>);
+        case FunctionDescriptor::SetColorMode:
+            return asFP<HWC2_PFN_SET_COLOR_MODE>(
+                    displayHook<decltype(&Display::setColorMode),
+                    &Display::setColorMode, int32_t>);
+        case FunctionDescriptor::SetColorTransform:
+            return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(
+                    displayHook<decltype(&Display::setColorTransform),
+                    &Display::setColorTransform, const float*, int32_t>);
+        case FunctionDescriptor::SetOutputBuffer:
+            return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(
+                    displayHook<decltype(&Display::setOutputBuffer),
+                    &Display::setOutputBuffer, buffer_handle_t, int32_t>);
+        case FunctionDescriptor::SetPowerMode:
+            return asFP<HWC2_PFN_SET_POWER_MODE>(
+                    displayHook<decltype(&Display::setPowerMode),
+                    &Display::setPowerMode, int32_t>);
+        case FunctionDescriptor::SetVsyncEnabled:
+            return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(
+                    displayHook<decltype(&Display::setVsyncEnabled),
+                    &Display::setVsyncEnabled, int32_t>);
+        case FunctionDescriptor::ValidateDisplay:
+            return asFP<HWC2_PFN_VALIDATE_DISPLAY>(
+                    displayHook<decltype(&Display::validate),
+                    &Display::validate, uint32_t*, uint32_t*>);
+        case FunctionDescriptor::GetClientTargetSupport:
+            return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
+                    displayHook<decltype(&Display::getClientTargetSupport),
+                    &Display::getClientTargetSupport, uint32_t, uint32_t,
+                                                      int32_t, int32_t>);
+        // Layer functions
+        case FunctionDescriptor::SetCursorPosition:
+            return asFP<HWC2_PFN_SET_CURSOR_POSITION>(
+                    layerHook<decltype(&Layer::setCursorPosition),
+                    &Layer::setCursorPosition, int32_t, int32_t>);
+        case FunctionDescriptor::SetLayerBuffer:
+            return asFP<HWC2_PFN_SET_LAYER_BUFFER>(
+                    layerHook<decltype(&Layer::setBuffer), &Layer::setBuffer,
+                    buffer_handle_t, int32_t>);
+        case FunctionDescriptor::SetLayerSurfaceDamage:
+            return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
+                    layerHook<decltype(&Layer::setSurfaceDamage),
+                    &Layer::setSurfaceDamage, hwc_region_t>);
+
+        // Layer state functions
+        case FunctionDescriptor::SetLayerBlendMode:
+            return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(
+                    layerHook<decltype(&Layer::setBlendMode),
+                    &Layer::setBlendMode, int32_t>);
+        case FunctionDescriptor::SetLayerColor:
+            return asFP<HWC2_PFN_SET_LAYER_COLOR>(
+                    layerHook<decltype(&Layer::setColor), &Layer::setColor,
+                    hwc_color_t>);
+        case FunctionDescriptor::SetLayerCompositionType:
+            return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
+                    layerHook<decltype(&Layer::setCompositionType),
+                    &Layer::setCompositionType, int32_t>);
+        case FunctionDescriptor::SetLayerDataspace:
+            return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(
+                    layerHook<decltype(&Layer::setDataspace),
+                    &Layer::setDataspace, int32_t>);
+        case FunctionDescriptor::SetLayerDisplayFrame:
+            return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
+                    layerHook<decltype(&Layer::setDisplayFrame),
+                    &Layer::setDisplayFrame, hwc_rect_t>);
+        case FunctionDescriptor::SetLayerPlaneAlpha:
+            return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
+                    layerHook<decltype(&Layer::setPlaneAlpha),
+                    &Layer::setPlaneAlpha, float>);
+        case FunctionDescriptor::SetLayerSidebandStream:
+            return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(
+                    layerHook<decltype(&Layer::setSidebandStream),
+                    &Layer::setSidebandStream, const native_handle_t*>);
+        case FunctionDescriptor::SetLayerSourceCrop:
+            return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
+                    layerHook<decltype(&Layer::setSourceCrop),
+                    &Layer::setSourceCrop, hwc_frect_t>);
+        case FunctionDescriptor::SetLayerTransform:
+            return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(
+                    layerHook<decltype(&Layer::setTransform),
+                    &Layer::setTransform, int32_t>);
+        case FunctionDescriptor::SetLayerVisibleRegion:
+            return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
+                    layerHook<decltype(&Layer::setVisibleRegion),
+                    &Layer::setVisibleRegion, hwc_region_t>);
+        case FunctionDescriptor::SetLayerZOrder:
+            return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(
+                    displayHook<decltype(&Display::updateLayerZ),
+                    &Display::updateLayerZ, hwc2_layer_t, uint32_t>);
+
+        default:
+            ALOGE("doGetFunction: Unknown function descriptor: %d (%s)",
+                    static_cast<int32_t>(descriptor),
+                    to_string(descriptor).c_str());
+            return nullptr;
+    }
+}
+
+
+// Device functions
+
+Error EmuHWC2::createVirtualDisplay(uint32_t /*width*/, uint32_t /*height*/,
+        int32_t* /*format*/, hwc2_display_t* /*outDisplay*/) {
+    ALOGVV("%s", __FUNCTION__);
+    //TODO: VirtualDisplay support
+    return Error::None;
+}
+
+Error EmuHWC2::destroyVirtualDisplay(hwc2_display_t /*displayId*/) {
+    ALOGVV("%s", __FUNCTION__);
+    //TODO: VirtualDisplay support
+    return Error::None;
+}
+
+void EmuHWC2::dump(uint32_t* /*outSize*/, char* /*outBuffer*/) {
+    ALOGVV("%s", __FUNCTION__);
+    //TODO:
+    return;
+}
+
+uint32_t EmuHWC2::getMaxVirtualDisplayCount() {
+    ALOGVV("%s", __FUNCTION__);
+    //TODO: VirtualDisplay support
+    return 0;
+}
+
+static bool isValid(Callback descriptor) {
+    switch (descriptor) {
+        case Callback::Hotplug: // Fall-through
+        case Callback::Refresh: // Fall-through
+        case Callback::Vsync: return true;
+        default: return false;
+    }
+}
+
+Error EmuHWC2::registerCallback(Callback descriptor,
+        hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
+    ALOGVV("%s", __FUNCTION__);
+    if (!isValid(descriptor)) {
+        ALOGE("registerCallback: Unkown function descriptor: %d",
+                static_cast<int32_t>(descriptor));
+        return Error::BadParameter;
+    }
+    ALOGV("registerCallback(%s, %p, %p)", to_string(descriptor).c_str(),
+            callbackData, pointer);
+
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (pointer != nullptr) {
+        mCallbacks[descriptor] = {callbackData, pointer};
+    }
+    else {
+        ALOGV("unregisterCallback(%s)", to_string(descriptor).c_str());
+        mCallbacks.erase(descriptor);
+        return Error::None;
+    }
+
+    // Callback without the state lock held
+    if (descriptor == Callback::Hotplug) {
+        lock.unlock();
+        auto hotplug = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
+        hotplug(callbackData, 0, static_cast<int32_t>(Connection::Connected));
+    }
+
+    return Error::None;
+}
+
+//Gralloc Functions
+EmuHWC2::GrallocModule::GrallocModule() {
+    int ret;
+
+    ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mHw);
+    assert(ret == 0 && "Gralloc moudle not found");
+    mGralloc = reinterpret_cast<const gralloc_module_t*>(mHw);
+
+    ret = framebuffer_open(mHw, &mFbDev);
+    assert(ret == 0 && "Fail to open FrameBuffer device");
+}
+
+EmuHWC2::GrallocModule::~GrallocModule() {
+    if (mHandle != nullptr) {
+        mGralloc->unregisterBuffer(mGralloc, mHandle);
+        mAllocDev->free(mAllocDev, mHandle);
+        ALOGI("free targetCb %d", ((cb_handle_t*)(mHandle))->hostHandle);
+    }
+}
+
+uint32_t EmuHWC2::GrallocModule::getTargetCb() {
+    if (mHandle == nullptr) {
+        int ret, stride;
+        ret = gralloc_open(mHw, &mAllocDev);
+        assert(ret == 0 && "Fail to open GPU device");
+        ret = mAllocDev->alloc(mAllocDev,
+                               mFbDev->width, mFbDev->height, mFbDev->format,
+                               GRALLOC_USAGE_HW_COMPOSER|GRALLOC_USAGE_HW_RENDER,
+                               &mHandle, &stride);
+        assert(ret == 0 && "Fail to allocate target ColorBuffer");
+        mGralloc->registerBuffer(mGralloc, mHandle);
+        ALOGI("targetCb %d", reinterpret_cast<const cb_handle_t*>(mHandle)
+              ->hostHandle);
+    }
+    return reinterpret_cast<const cb_handle_t*>(mHandle)->hostHandle;
+}
+
+// Display functions
+
+std::atomic<hwc2_display_t> EmuHWC2::Display::sNextId(0);
+
+EmuHWC2::Display::Display(EmuHWC2& device, DisplayType type)
+  : mDevice(device),
+    mId(sNextId++),
+    mName(),
+    mType(type),
+    mPowerMode(PowerMode::Off),
+    mVsyncEnabled(Vsync::Invalid),
+    mVsyncPeriod(1000*1000*1000/60), // vsync is 60 hz
+    mVsyncThread(*this),
+    mClientTarget(),
+    mChanges(),
+    mLayers(),
+    mConfigs(),
+    mActiveConfig(nullptr),
+    mColorModes(),
+    mSetColorTransform(false),
+    mStateMutex()
+    {
+        mVsyncThread.run("", HAL_PRIORITY_URGENT_DISPLAY);
+    }
+
+Error EmuHWC2::Display::acceptChanges() {
+    ALOGVV("%s: displayId %u", __FUNCTION__, (uint32_t)mId);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        ALOGW("%s: displayId %u acceptChanges failed, not validated",
+              __FUNCTION__, (uint32_t)mId);
+        return Error::NotValidated;
+    }
+
+
+    for (auto& change : mChanges->getTypeChanges()) {
+        auto layerId = change.first;
+        auto type = change.second;
+        if (mDevice.mLayers.count(layerId) == 0) {
+            // This should never happen but somehow does.
+            ALOGW("Cannot accept change for unknown layer %u",
+                  (uint32_t)layerId);
+            continue;
+        }
+        auto layer = mDevice.mLayers[layerId];
+        layer->setCompositionType((int32_t)type);
+    }
+
+    mChanges->clearTypeChanges();
+    return Error::None;
+}
+
+Error EmuHWC2::Display::createLayer(hwc2_layer_t* outLayerId) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    auto layer = *mLayers.emplace(std::make_shared<Layer>(*this));
+    mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer));
+    *outLayerId = layer->getId();
+    ALOGV("%s: Display %u created layer %u", __FUNCTION__, (uint32_t)mId,
+         (uint32_t)(*outLayerId));
+    return Error::None;
+}
+
+Error EmuHWC2::Display::destroyLayer(hwc2_layer_t layerId) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    const auto mapLayer = mDevice.mLayers.find(layerId);
+    if (mapLayer == mDevice.mLayers.end()) {
+        ALOGW("%s failed: no such layer, displayId %u layerId %u",
+             __FUNCTION__, (uint32_t)mId, (uint32_t)layerId);
+        return Error::BadLayer;
+    }
+    const auto layer = mapLayer->second;
+    mDevice.mLayers.erase(mapLayer);
+    const auto zRange = mLayers.equal_range(layer);
+    for (auto current = zRange.first; current != zRange.second; ++current) {
+        if (**current == *layer) {
+            current = mLayers.erase(current);
+            break;
+        }
+    }
+    ALOGV("%s: displayId %d layerId %d", __FUNCTION__, (uint32_t)mId,
+         (uint32_t)layerId);
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getActiveConfig(hwc2_config_t* outConfig) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (!mActiveConfig) {
+        ALOGW("%s: displayId %d %s", __FUNCTION__, (uint32_t)mId,
+                to_string(Error::BadConfig).c_str());
+        return Error::BadConfig;
+    }
+    auto configId = mActiveConfig->getId();
+    ALOGV("%s: displayId %d configId %d", __FUNCTION__,
+          (uint32_t)mId, (uint32_t)configId);
+    *outConfig = configId;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getDisplayAttribute(hwc2_config_t configId,
+        int32_t attribute, int32_t* outValue) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+        ALOGW("%s: bad config (%u %u)", __FUNCTION__, (uint32_t)mId, configId);
+        return Error::BadConfig;
+    }
+    *outValue = mConfigs[configId]->getAttribute((Attribute)attribute);
+    ALOGV("%s: (%d %d) %s --> %d", __FUNCTION__,
+          (uint32_t)mId, (uint32_t)configId,
+          to_string((Attribute)attribute).c_str(), *outValue);
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getChangedCompositionTypes(
+        uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        ALOGW("display %u getChangedCompositionTypes failed: not validated",
+                (uint32_t)mId);
+        return Error::NotValidated;
+    }
+
+    if ((outLayers == nullptr) || (outTypes == nullptr)) {
+        *outNumElements = mChanges->getTypeChanges().size();
+        return Error::None;
+    }
+
+    uint32_t numWritten = 0;
+    for (const auto& element : mChanges->getTypeChanges()) {
+        if (numWritten == *outNumElements) {
+            break;
+        }
+        auto layerId = element.first;
+        auto intType = static_cast<int32_t>(element.second);
+        ALOGV("%s: Adding layer %u %s", __FUNCTION__, (uint32_t)layerId,
+                to_string(element.second).c_str());
+        outLayers[numWritten] = layerId;
+        outTypes[numWritten] = intType;
+        ++numWritten;
+    }
+    *outNumElements = numWritten;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getColorModes(uint32_t* outNumModes,
+        int32_t* outModes) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (!outModes) {
+        *outNumModes = mColorModes.size();
+        return Error::None;
+    }
+
+    // we only support HAL_COLOR_MODE_NATIVE so far
+    uint32_t numModes = std::min(*outNumModes,
+            static_cast<uint32_t>(mColorModes.size()));
+    std::copy_n(mColorModes.cbegin(), numModes, outModes);
+    *outNumModes = numModes;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getConfigs(uint32_t* outNumConfigs,
+        hwc2_config_t* outConfigs) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (!outConfigs) {
+        *outNumConfigs = mConfigs.size();
+        return Error::None;
+    }
+    uint32_t numWritten = 0;
+    for (const auto config : mConfigs) {
+        if (numWritten == *outNumConfigs) {
+            break;
+        }
+        outConfigs[numWritten] = config->getId();
+        ++numWritten;
+    }
+    *outNumConfigs = numWritten;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getDozeSupport(int32_t* outSupport) {
+    ALOGVV("%s", __FUNCTION__);
+    // We don't support so far
+    *outSupport = 0;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getHdrCapabilities(uint32_t* outNumTypes,
+        int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+        float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
+    ALOGVV("%s", __FUNCTION__);
+    // We don't support so far
+    *outNumTypes = 0;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getName(uint32_t* outSize, char* outName) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (!outName) {
+        *outSize = mName.size();
+        return Error::None;
+    }
+    auto numCopied = mName.copy(outName, *outSize);
+    *outSize = numCopied;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getReleaseFences(uint32_t* outNumElements,
+        hwc2_layer_t* /*outLayers*/, int32_t* /*outFences*/) {
+    ALOGVV("%s", __FUNCTION__);
+
+    *outNumElements = 0;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getRequests(int32_t* outDisplayRequests,
+        uint32_t* outNumElements, hwc2_layer_t* outLayers,
+        int32_t* outLayerRequests) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        return Error::NotValidated;
+    }
+
+    if (outLayers == nullptr || outLayerRequests == nullptr) {
+        *outNumElements = mChanges->getNumLayerRequests();
+        return Error::None;
+    }
+
+    //TODO
+    // Display requests (HWC2::DisplayRequest) are not supported so far:
+    *outDisplayRequests = 0;
+
+    uint32_t numWritten = 0;
+    for (const auto& request : mChanges->getLayerRequests()) {
+        if (numWritten == *outNumElements) {
+            break;
+        }
+        outLayers[numWritten] = request.first;
+        outLayerRequests[numWritten] = static_cast<int32_t>(request.second);
+        ++numWritten;
+    }
+
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getType(int32_t* outType) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    *outType = (int32_t)mType;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::present(int32_t* outRetireFence) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (!mChanges || (mChanges->getNumTypes() > 0)) {
+        ALOGE("%s display(%u) set failed: not validated", __FUNCTION__,
+              (uint32_t)mId);
+        return Error::NotValidated;
+    }
+    mChanges.reset();
+
+    DEFINE_AND_VALIDATE_HOST_CONNECTION
+    if (rcEnc->hasHostCompositionV1()) {
+        uint32_t numLayer = 0;
+        for (auto layer: mLayers) {
+            if (layer->getCompositionType() == Composition::Device ||
+                layer->getCompositionType() == Composition::SolidColor) {
+                numLayer++;
+            }
+        }
+        ALOGV("present %d layers total %u layers", numLayer,
+              (uint32_t)mLayers.size());
+        if (numLayer == 0) {
+            mGralloc->getFb()->post(mGralloc->getFb(), mClientTarget.getBuffer());
+            *outRetireFence = mClientTarget.getFence();
+            return Error::None;
+        }
+
+        if (mComposeMsg == nullptr || mComposeMsg->getLayerCnt() < numLayer) {
+            mComposeMsg.reset(new ComposeMsg(numLayer));
+        }
+
+        // Handle the composition
+        ComposeDevice* p = mComposeMsg->get();
+        ComposeLayer* l = p->layer;
+        for (auto layer: mLayers) {
+            if (layer->getCompositionType() != Composition::Device &&
+                layer->getCompositionType() != Composition::SolidColor) {
+                ALOGE("%s: Unsupported composition types %d",
+                      __FUNCTION__, layer->getCompositionType());
+                continue;
+            }
+            // send layer composition command to host
+            if (layer->getCompositionType() == Composition::Device) {
+                int fence = layer->getLayerBuffer().getFence();
+                if (fence != -1) {
+                    int err = sync_wait(fence, 3000);
+                    if (err < 0 && errno == ETIME) {
+                        ALOGE("%s waited on fence %d for 3000 ms",
+                            __FUNCTION__, fence);
+                    }
+                }
+                else {
+                    ALOGV("%s: aquiredFence not set for layer %u",
+                          __FUNCTION__, (uint32_t)layer->getId());
+                }
+                cb_handle_t *cb =
+                    (cb_handle_t *)layer->getLayerBuffer().getBuffer();
+                if (cb != nullptr) {
+                    l->cbHandle = cb->hostHandle;
+                }
+                else {
+                    ALOGE("%s null buffer for layer %d", __FUNCTION__,
+                          (uint32_t)layer->getId());
+                }
+            }
+            else {
+                // solidcolor has no buffer
+                l->cbHandle = 0;
+            }
+            l->composeMode = (hwc2_composition_t)layer->getCompositionType();
+            l->displayFrame = layer->getDisplayFrame();
+            l->crop = layer->getSourceCrop();
+            l->blendMode = layer->getBlendMode();
+            l->alpha = layer->getPlaneAlpha();
+            l->color = layer->getColor();
+            l->transform = layer->getTransform();
+            ALOGV("   cb %d blendmode %d alpha %f %d %d %d %d z %d"
+                  " composeMode %d, transform %d",
+                  l->cbHandle, l->blendMode, l->alpha,
+                  l->displayFrame.left, l->displayFrame.top,
+                  l->displayFrame.right, l->displayFrame.bottom,
+                  layer->getZ(), l->composeMode, l->transform);
+            l++;
+        }
+        p->version = 1;
+        p->targetHandle = mGralloc->getTargetCb();
+        p->numLayers = numLayer;
+
+        rcEnc->rcCompose(rcEnc,
+                         sizeof(ComposeDevice) + numLayer * sizeof(ComposeLayer),
+                         (void *)p);
+        // not set retireFence should be fine, because the rcCompose is a
+        // sync call, it returns until the host call eglswapbuffers
+        *outRetireFence = -1;
+    }
+    else {
+        // we set all layers Composition::Client, so do nothing.
+        mGralloc->getFb()->post(mGralloc->getFb(), mClientTarget.getBuffer());
+        *outRetireFence = mClientTarget.getFence();
+        ALOGV("%s fallback to post, returns outRetireFence %d",
+              __FUNCTION__, *outRetireFence);
+    }
+
+    return Error::None;
+}
+
+Error EmuHWC2::Display::setActiveConfig(hwc2_config_t configId) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+        ALOGW("%s: bad config (%u %u)", __FUNCTION__, (uint32_t)mId,
+              (uint32_t)configId);
+        return Error::BadConfig;
+    }
+    auto config = mConfigs[configId];
+    if (config == mActiveConfig) {
+        return Error::None;
+    }
+
+    mActiveConfig = config;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::setClientTarget(buffer_handle_t target,
+        int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) {
+    ALOGVV("%s", __FUNCTION__);
+
+    cb_handle_t *cb =
+            (cb_handle_t *)target;
+    ALOGV("%s: display(%u) buffer handle %p cb %d, acquireFence %d", __FUNCTION__,
+          (uint32_t)mId, target, cb->hostHandle, acquireFence);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+    mClientTarget.setBuffer(target);
+    mClientTarget.setFence(acquireFence);
+    return Error::None;
+}
+
+Error EmuHWC2::Display::setColorMode(int32_t intMode) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    auto mode = static_cast<android_color_mode_t>(intMode);
+    ALOGV("%s: (display %u mode %d)", __FUNCTION__, (uint32_t)mId, intMode);
+    if (mode == mActiveColorMode) {
+        return Error::None;
+    }
+    if (mColorModes.count(mode) == 0) {
+        ALOGE("%s: display %d Mode %d not found in mColorModes",
+             __FUNCTION__, (uint32_t)mId, intMode);
+        return Error::Unsupported;
+    }
+    mActiveColorMode = mode;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::setColorTransform(const float* /*matrix*/,
+                                          int32_t hint) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+    //we force client composition if this is set
+    if (hint == 0 ) {
+        mSetColorTransform = false;
+    }
+    else {
+        mSetColorTransform = true;
+    }
+    return Error::None;
+}
+
+Error EmuHWC2::Display::setOutputBuffer(buffer_handle_t /*buffer*/,
+        int32_t /*releaseFence*/) {
+    ALOGVV("%s", __FUNCTION__);
+    //TODO: for virtual display
+    return Error::None;
+}
+
+static bool isValid(PowerMode mode) {
+    switch (mode) {
+        case PowerMode::Off: // Fall-through
+        case PowerMode::DozeSuspend: // Fall-through
+        case PowerMode::Doze: // Fall-through
+        case PowerMode::On: return true;
+        default: return false;
+    }
+}
+
+Error EmuHWC2::Display::setPowerMode(int32_t intMode) {
+    ALOGVV("%s", __FUNCTION__);
+    // Emulator always set screen ON
+    PowerMode mode = static_cast<PowerMode>(intMode);
+    if (!isValid(mode)) {
+        return Error::BadParameter;
+    }
+    if (mode == mPowerMode) {
+        return Error::None;
+    }
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    ALOGV("%s: (display %u mode %s)", __FUNCTION__,
+          (uint32_t)mId, to_string(mode).c_str());
+    mPowerMode = mode;
+    return Error::None;
+}
+
+static bool isValid(Vsync enable) {
+    switch (enable) {
+        case Vsync::Enable: // Fall-through
+        case Vsync::Disable: return true;
+        case Vsync::Invalid: return false;
+    }
+}
+
+Error EmuHWC2::Display::setVsyncEnabled(int32_t intEnable) {
+    ALOGVV("%s", __FUNCTION__);
+    Vsync enable = static_cast<Vsync>(intEnable);
+    if (!isValid(enable)) {
+        return Error::BadParameter;
+    }
+    if (enable == mVsyncEnabled) {
+        return Error::None;
+    }
+
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    mVsyncEnabled = enable;
+    return Error::None;
+}
+
+Error EmuHWC2::Display::validate(uint32_t* outNumTypes,
+        uint32_t* outNumRequests) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        mChanges.reset(new Changes);
+        DEFINE_AND_VALIDATE_HOST_CONNECTION
+        if (rcEnc->hasHostCompositionV1()) {
+            // Support Device and SolidColor, otherwise, fallback all layers
+            // to Client
+            bool fallBack = false;
+            for (auto& layer : mLayers) {
+                if (layer->getCompositionType() == Composition::Client ||
+                    layer->getCompositionType() == Composition::Cursor ||
+                    layer->getCompositionType() == Composition::Sideband) {
+                    ALOGV("%s: layer %u CompositionType %d\n", __FUNCTION__,
+                         (uint32_t)layer->getId(), layer->getCompositionType());
+                    fallBack = true;
+                    break;
+                }
+            }
+            if (mSetColorTransform) {
+                fallBack = true;
+            }
+            if (fallBack) {
+                for (auto& layer : mLayers) {
+                    if (layer->getCompositionType() != Composition::Client) {
+                        mChanges->addTypeChange(layer->getId(),
+                                                Composition::Client);
+                    }
+                }
+            }
+       }
+       else {
+            for (auto& layer : mLayers) {
+                if (layer->getCompositionType() != Composition::Client) {
+                    mChanges->addTypeChange(layer->getId(),
+                                            Composition::Client);
+                }
+            }
+        }
+    }
+    else {
+        ALOGE("Validate was called more than once!");
+    }
+
+    *outNumTypes = mChanges->getNumTypes();
+    *outNumRequests = mChanges->getNumLayerRequests();
+    ALOGV("%s: displayId %u types %u, requests %u", __FUNCTION__,
+          (uint32_t)mId, *outNumTypes, *outNumRequests);
+    return *outNumTypes > 0 ? Error::HasChanges : Error::None;
+}
+
+Error EmuHWC2::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) {
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    const auto mapLayer = mDevice.mLayers.find(layerId);
+    if (mapLayer == mDevice.mLayers.end()) {
+        ALOGE("%s failed to find layer %u", __FUNCTION__, (uint32_t)mId);
+        return Error::BadLayer;
+    }
+
+    const auto layer = mapLayer->second;
+    const auto zRange = mLayers.equal_range(layer);
+    bool layerOnDisplay = false;
+    for (auto current = zRange.first; current != zRange.second; ++current) {
+        if (**current == *layer) {
+            if ((*current)->getZ() == z) {
+                // Don't change anything if the Z hasn't changed
+                return Error::None;
+            }
+            current = mLayers.erase(current);
+            layerOnDisplay = true;
+            break;
+        }
+    }
+
+    if (!layerOnDisplay) {
+        ALOGE("%s failed to find layer %u on display", __FUNCTION__,
+              (uint32_t)mId);
+        return Error::BadLayer;
+    }
+
+    layer->setZ(z);
+    mLayers.emplace(std::move(layer));
+    return Error::None;
+}
+
+Error EmuHWC2::Display::getClientTargetSupport(uint32_t width, uint32_t height,
+                                      int32_t format, int32_t dataspace){
+    ALOGVV("%s", __FUNCTION__);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (mActiveConfig == nullptr) {
+        return Error::Unsupported;
+    }
+
+    if (width == (uint32_t)mActiveConfig->getAttribute(Attribute::Width) &&
+        height == (uint32_t)mActiveConfig->getAttribute(Attribute::Height) &&
+        format == HAL_PIXEL_FORMAT_RGBA_8888 &&
+        dataspace == HAL_DATASPACE_UNKNOWN) {
+        return Error::None;
+    }
+
+    return Error::None;
+}
+
+
+int EmuHWC2::Display::populatePrimaryConfigs() {
+    ALOGVV("%s DisplayId %u", __FUNCTION__, (uint32_t)mId);
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    mGralloc.reset(new GrallocModule());
+    auto newConfig = std::make_shared<Config>(*this);
+    // vsync is 60 hz;
+    newConfig->setAttribute(Attribute::VsyncPeriod, mVsyncPeriod);
+    newConfig->setAttribute(Attribute::Width, mGralloc->getFb()->width);
+    newConfig->setAttribute(Attribute::Height, mGralloc->getFb()->height);
+    newConfig->setAttribute(Attribute::DpiX, mGralloc->getFb()->xdpi*1000);
+    newConfig->setAttribute(Attribute::DpiY, mGralloc->getFb()->ydpi*1000);
+
+    newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size()));
+    ALOGV("Found new config %d: %s", (uint32_t)newConfig->getId(),
+            newConfig->toString().c_str());
+    mConfigs.emplace_back(std::move(newConfig));
+
+    // Only have single config so far, it is activeConfig
+    mActiveConfig = mConfigs[0];
+    mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+    mColorModes.emplace((android_color_mode_t)HAL_COLOR_MODE_NATIVE);
+
+    return 0;
+}
+
+
+// Config functions
+
+void EmuHWC2::Display::Config::setAttribute(Attribute attribute,
+       int32_t value) {
+    mAttributes[attribute] = value;
+}
+
+int32_t EmuHWC2::Display::Config::getAttribute(Attribute attribute) const {
+    if (mAttributes.count(attribute) == 0) {
+        return -1;
+    }
+    return mAttributes.at(attribute);
+}
+
+std::string EmuHWC2::Display::Config::toString() const {
+    std::string output;
+
+    const size_t BUFFER_SIZE = 100;
+    char buffer[BUFFER_SIZE] = {};
+    auto writtenBytes = snprintf(buffer, BUFFER_SIZE,
+            "%u x %u", mAttributes.at(HWC2::Attribute::Width),
+            mAttributes.at(HWC2::Attribute::Height));
+    output.append(buffer, writtenBytes);
+
+    if (mAttributes.count(HWC2::Attribute::VsyncPeriod) != 0) {
+        std::memset(buffer, 0, BUFFER_SIZE);
+        writtenBytes = snprintf(buffer, BUFFER_SIZE, " @ %.1f Hz",
+                1e9 / mAttributes.at(HWC2::Attribute::VsyncPeriod));
+        output.append(buffer, writtenBytes);
+    }
+
+    if (mAttributes.count(HWC2::Attribute::DpiX) != 0 &&
+            mAttributes.at(HWC2::Attribute::DpiX) != -1) {
+        std::memset(buffer, 0, BUFFER_SIZE);
+        writtenBytes = snprintf(buffer, BUFFER_SIZE,
+                ", DPI: %.1f x %.1f",
+                mAttributes.at(HWC2::Attribute::DpiX) / 1000.0f,
+                mAttributes.at(HWC2::Attribute::DpiY) / 1000.0f);
+        output.append(buffer, writtenBytes);
+    }
+
+    return output;
+}
+
+
+// VsyncThread function
+bool EmuHWC2::Display::VsyncThread::threadLoop() {
+    struct timespec rt;
+    if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
+        ALOGE("%s: error in vsync thread clock_gettime: %s",
+              __FUNCTION__, strerror(errno));
+        return true;
+    }
+    const int logInterval = 60;
+    int64_t lastLogged = rt.tv_sec;
+    int sent = 0;
+    int lastSent = 0;
+    bool vsyncEnabled = false;
+    struct timespec wait_time;
+    wait_time.tv_sec = 0;
+    wait_time.tv_nsec = mDisplay.mVsyncPeriod;
+
+    while (true) {
+        int err = nanosleep(&wait_time, NULL);
+        if (err == -1) {
+            if (errno == EINTR) {
+                break;
+            }
+            ALOGE("%s: error in vsync thread: %s", __FUNCTION__, strerror(errno));
+        }
+
+        std::unique_lock<std::mutex> lock(mDisplay.mStateMutex);
+        vsyncEnabled = (mDisplay.mVsyncEnabled == Vsync::Enable);
+        lock.unlock();
+
+        if (!vsyncEnabled) {
+            continue;
+        }
+
+        if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
+            ALOGE("%s: error in vsync thread clock_gettime: %s",
+                 __FUNCTION__, strerror(errno));
+        }
+
+        int64_t timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec;
+
+        lock.lock();
+        const auto& callbackInfo = mDisplay.mDevice.mCallbacks[Callback::Vsync];
+        auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer);
+        lock.unlock();
+
+        if (vsync) {
+            vsync(callbackInfo.data, mDisplay.mId, timestamp);
+        }
+
+        if (rt.tv_sec - lastLogged >= logInterval) {
+            ALOGVV("sent %d syncs in %ds", sent - lastSent, rt.tv_sec - lastLogged);
+            lastLogged = rt.tv_sec;
+            lastSent = sent;
+        }
+        ++sent;
+    }
+    return false;
+}
+
+
+// Layer functions
+bool EmuHWC2::SortLayersByZ::operator()(
+        const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) {
+    return lhs->getZ() < rhs->getZ();
+}
+
+std::atomic<hwc2_layer_t> EmuHWC2::Layer::sNextId(1);
+
+EmuHWC2::Layer::Layer(Display& display)
+  : mId(sNextId++),
+    mDisplay(display),
+    mBuffer(),
+    mSurfaceDamage(),
+    mBlendMode(BlendMode::None),
+    mColor({0, 0, 0, 0}),
+    mCompositionType(Composition::Invalid),
+    mDisplayFrame({0, 0, -1, -1}),
+    mPlaneAlpha(0.0f),
+    mSidebandStream(nullptr),
+    mSourceCrop({0.0f, 0.0f, -1.0f, -1.0f}),
+    mTransform(Transform::None),
+    mVisibleRegion(),
+    mZ(0)
+    {}
+
+Error EmuHWC2::Layer::setBuffer(buffer_handle_t buffer,
+        int32_t acquireFence) {
+    ALOGVV("%s: Setting acquireFence %d for layer %u", __FUNCTION__,
+          acquireFence, (uint32_t)mId);
+    mBuffer.setBuffer(buffer);
+    mBuffer.setFence(acquireFence);
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setCursorPosition(int32_t /*x*/,
+                                        int32_t /*y*/) {
+    ALOGVV("%s", __FUNCTION__);
+    if (mCompositionType != Composition::Cursor) {
+        return Error::BadLayer;
+    }
+   //TODO
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setSurfaceDamage(hwc_region_t /*damage*/) {
+    // Emulator redraw whole layer per frame, so ignore this.
+    return Error::None;
+}
+
+// Layer state functions
+
+Error EmuHWC2::Layer::setBlendMode(int32_t mode) {
+    ALOGVV("%s %d for layer %u", __FUNCTION__, mode, (uint32_t)mId);
+    mBlendMode = static_cast<BlendMode>(mode);
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setColor(hwc_color_t color) {
+    ALOGVV("%s", __FUNCTION__);
+    mColor = color;
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setCompositionType(int32_t type) {
+    ALOGVV("%s", __FUNCTION__);
+    mCompositionType = static_cast<Composition>(type);
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setDataspace(int32_t) {
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setDisplayFrame(hwc_rect_t frame) {
+    mDisplayFrame = frame;
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setPlaneAlpha(float alpha) {
+    mPlaneAlpha = alpha;
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setSidebandStream(const native_handle_t* stream) {
+    mSidebandStream = stream;
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setSourceCrop(hwc_frect_t crop) {
+    mSourceCrop = crop;
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setTransform(int32_t transform) {
+    mTransform = static_cast<Transform>(transform);
+    return Error::None;
+}
+
+static bool compareRects(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+    return rect1.left == rect2.left &&
+            rect1.right == rect2.right &&
+            rect1.top == rect2.top &&
+            rect1.bottom == rect2.bottom;
+}
+
+Error EmuHWC2::Layer::setVisibleRegion(hwc_region_t visible) {
+    ALOGVV("%s", __FUNCTION__);
+    if ((getNumVisibleRegions() != visible.numRects) ||
+        !std::equal(mVisibleRegion.begin(), mVisibleRegion.end(), visible.rects,
+                    compareRects)) {
+        mVisibleRegion.resize(visible.numRects);
+        std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin());
+    }
+    return Error::None;
+}
+
+Error EmuHWC2::Layer::setZ(uint32_t z) {
+    ALOGVV("%s %d", __FUNCTION__, z);
+    mZ = z;
+    return Error::None;
+}
+
+// Adaptor Helpers
+
+void EmuHWC2::populateCapabilities() {
+    //TODO: add Capabilities
+    // support virtualDisplay
+    // support sideBandStream
+    // support backGroundColor
+    // we should not set this for HWC2, TODO: remove
+    // mCapabilities.insert(Capability::PresentFenceIsNotReliable);
+}
+
+int EmuHWC2::populatePrimary() {
+    int ret = 0;
+    auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical);
+    ret = display->populatePrimaryConfigs();
+    if (ret != 0) {
+        return ret;
+    }
+    mDisplays.emplace(display->getId(), std::move(display));
+    return ret;
+}
+
+EmuHWC2::Display* EmuHWC2::getDisplay(hwc2_display_t id) {
+    auto display = mDisplays.find(id);
+    if (display == mDisplays.end()) {
+        return nullptr;
+    }
+    return display->second.get();
+}
+
+std::tuple<EmuHWC2::Layer*, Error> EmuHWC2::getLayer(
+        hwc2_display_t displayId, hwc2_layer_t layerId) {
+    auto display = getDisplay(displayId);
+    if (!display) {
+        ALOGE("%s: Fail to find display %d", __FUNCTION__, (uint32_t)displayId);
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadDisplay);
+    }
+
+    auto layerEntry = mLayers.find(layerId);
+    if (layerEntry == mLayers.end()) {
+        ALOGE("%s: Fail to find layer %d", __FUNCTION__, (uint32_t)layerId);
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+    }
+
+    auto layer = layerEntry->second;
+    if (layer->getDisplay().getId() != displayId) {
+        ALOGE("%s: layer %d not belongs to display %d", __FUNCTION__,
+              (uint32_t)layerId, (uint32_t)displayId);
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+    }
+    return std::make_tuple(layer.get(), Error::None);
+}
+
+static int hwc2DevOpen(const struct hw_module_t *module, const char *name,
+        struct hw_device_t **dev) {
+    ALOGV("%s ", __FUNCTION__);
+    if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
+        ALOGE("Invalid module name- %s", name);
+        return -EINVAL;
+    }
+
+    EmuHWC2* ctx = new EmuHWC2();
+    if (!ctx) {
+        ALOGE("Failed to allocate EmuHWC2");
+        return -ENOMEM;
+    }
+    int ret = ctx->populatePrimary();
+    if (ret != 0) {
+        ALOGE("Failed to populate primary display");
+        return ret;
+    }
+
+    ctx->common.module = const_cast<hw_module_t *>(module);
+    *dev = &ctx->common;
+    return 0;
+}
+}
+
+static struct hw_module_methods_t hwc2_module_methods = {
+    .open = android::hwc2DevOpen
+};
+
+hw_module_t HAL_MODULE_INFO_SYM = {
+    .tag = HARDWARE_MODULE_TAG,
+    .version_major = 2,
+    .version_minor = 0,
+    .id = HWC_HARDWARE_MODULE_ID,
+    .name = "goldfish HWC2 module",
+    .author = "The Android Open Source Project",
+    .methods = &hwc2_module_methods,
+    .dso = NULL,
+    .reserved = {0},
+};
diff --git a/system/hwc2/EmuHWC2.h b/system/hwc2/EmuHWC2.h
new file mode 100644
index 0000000..0d768dd
--- /dev/null
+++ b/system/hwc2/EmuHWC2.h
@@ -0,0 +1,448 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HW_EMU_HWC2_H
+#define ANDROID_HW_EMU_HWC2_H
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+#include <utils/Thread.h>
+
+#include <atomic>
+#include <map>
+#include <mutex>
+#include <vector>
+#include <unordered_set>
+#include <unordered_map>
+#include <set>
+
+#include "gralloc_cb.h"
+#include "MiniFence.h"
+#include "HostConnection.h"
+
+namespace android {
+
+class EmuHWC2 : public hwc2_device_t {
+public:
+    EmuHWC2();
+    int populatePrimary();
+
+private:
+    static inline EmuHWC2* getHWC2(hwc2_device_t* device) {
+        return static_cast<EmuHWC2*>(device);
+    }
+
+    static int closeHook(hw_device_t* device) {
+        EmuHWC2 *ctx = reinterpret_cast<EmuHWC2*>(device);
+        delete ctx;
+        return 0;
+    }
+
+    // getCapabilities
+    void doGetCapabilities(uint32_t* outCount, int32_t* outCapabilities);
+    static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount,
+                                int32_t* outCapabilities) {
+        getHWC2(device)->doGetCapabilities(outCount, outCapabilities);
+    }
+
+    // getFunction
+    hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor);
+    static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device,
+            int32_t desc) {
+        auto descriptor = static_cast<HWC2::FunctionDescriptor>(desc);
+        return getHWC2(device)->doGetFunction(descriptor);
+    }
+
+    // Device functions
+    HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height,
+            int32_t* format, hwc2_display_t* outDisplay);
+    static int32_t createVirtualDisplayHook(hwc2_device_t* device,
+            uint32_t width, uint32_t height, int32_t* format,
+            hwc2_display_t* outDisplay) {
+        auto error = getHWC2(device)->createVirtualDisplay(width, height,
+                format, outDisplay);
+        return static_cast<int32_t>(error);
+    }
+
+    HWC2::Error destroyVirtualDisplay(hwc2_display_t display);
+    static int32_t destroyVirtualDisplayHook(hwc2_device_t* device,
+            hwc2_display_t display) {
+        auto error = getHWC2(device)->destroyVirtualDisplay(display);
+        return static_cast<int32_t>(error);
+    }
+
+    std::string mDumpString;
+    void dump(uint32_t* outSize, char* outBuffer);
+    static void dumpHook(hwc2_device_t* device, uint32_t* outSize,
+            char* outBuffer) {
+        getHWC2(device)->dump(outSize, outBuffer);
+    }
+
+    uint32_t getMaxVirtualDisplayCount();
+    static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) {
+        return getHWC2(device)->getMaxVirtualDisplayCount();
+    }
+
+    HWC2::Error registerCallback(HWC2::Callback descriptor,
+            hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer);
+    static int32_t registerCallbackHook(hwc2_device_t* device,
+            int32_t intDesc, hwc2_callback_data_t callbackData,
+            hwc2_function_pointer_t pointer) {
+        auto descriptor = static_cast<HWC2::Callback>(intDesc);
+        auto error = getHWC2(device)->registerCallback(descriptor,
+                callbackData, pointer);
+        return static_cast<int32_t>(error);
+    }
+
+    class Layer;
+    class SortLayersByZ {
+    public:
+        bool operator()(const std::shared_ptr<Layer>& lhs,
+                    const std::shared_ptr<Layer>& rhs);
+    };
+
+    // SurfaceFlinger sets the ColorBuffer and its Fence handler for each
+    // layer. This class is a container for these two.
+    class FencedBuffer {
+        public:
+            FencedBuffer() : mBuffer(nullptr), mFence(MiniFence::NO_FENCE) {}
+
+            void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; }
+            void setFence(int fenceFd) { mFence = new MiniFence(fenceFd); }
+
+            buffer_handle_t getBuffer() const { return mBuffer; }
+            int getFence() const { return mFence->dup(); }
+
+        private:
+            buffer_handle_t mBuffer;
+            sp<MiniFence> mFence;
+    };
+
+    class GrallocModule {
+    public:
+        GrallocModule();
+        ~GrallocModule();
+        framebuffer_device_t* getFb() { return mFbDev; }
+        uint32_t getTargetCb();
+    private:
+        const hw_module_t* mHw = nullptr;
+        const gralloc_module_t* mGralloc = nullptr;
+        alloc_device_t* mAllocDev = nullptr;
+        framebuffer_device_t* mFbDev = nullptr;
+        buffer_handle_t mHandle = nullptr;
+    };
+
+    typedef struct compose_layer {
+        uint32_t cbHandle;
+        hwc2_composition_t composeMode;
+        hwc_rect_t displayFrame;
+        hwc_frect_t crop;
+        int32_t blendMode;
+        float alpha;
+        hwc_color_t color;
+        hwc_transform_t transform;
+    } ComposeLayer;
+    typedef struct compose_device {
+        uint32_t version;
+        uint32_t targetHandle;
+        uint32_t numLayers;
+        struct compose_layer layer[0];
+    } ComposeDevice;
+
+    class ComposeMsg {
+    public:
+        ComposeMsg(uint32_t layerCnt = 0) :
+          mData(sizeof(ComposeDevice) + layerCnt * sizeof(ComposeLayer))
+        {
+            mComposeDevice = reinterpret_cast<ComposeDevice*>(mData.data());
+            mLayerCnt = layerCnt;
+        }
+
+        ComposeDevice* get() { return mComposeDevice; }
+
+        uint32_t getLayerCnt() { return mLayerCnt; }
+
+    private:
+        std::vector<uint8_t> mData;
+        uint32_t mLayerCnt;
+        ComposeDevice* mComposeDevice;
+    };
+
+    class Display {
+    public:
+        Display(EmuHWC2& device, HWC2::DisplayType type);
+        hwc2_display_t getId() const {return mId;}
+
+        // HWC2 Display functions
+        HWC2::Error acceptChanges();
+        HWC2::Error createLayer(hwc2_layer_t* outLayerId);
+        HWC2::Error destroyLayer(hwc2_layer_t layerId);
+        HWC2::Error getActiveConfig(hwc2_config_t* outConfigId);
+        HWC2::Error getDisplayAttribute(hwc2_config_t configId,
+                int32_t attribute, int32_t* outValue);
+        HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements,
+                hwc2_layer_t* outLayers, int32_t* outTypes);
+        HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes);
+        HWC2::Error getConfigs(uint32_t* outNumConfigs,
+                hwc2_config_t* outConfigIds);
+        HWC2::Error getDozeSupport(int32_t* outSupport);
+        HWC2::Error getHdrCapabilities(uint32_t* outNumTypes,
+                int32_t* outTypes, float* outMaxLuminance,
+                float* outMaxAverageLuminance, float* outMinLuminance);
+        HWC2::Error getName(uint32_t* outSize, char* outName);
+        HWC2::Error getReleaseFences(uint32_t* outNumElements,
+                hwc2_layer_t* outLayers, int32_t* outFences);
+        HWC2::Error getRequests(int32_t* outDisplayRequests,
+                uint32_t* outNumElements, hwc2_layer_t* outLayers,
+                int32_t* outLayerRequests);
+        HWC2::Error getType(int32_t* outType);
+        HWC2::Error present(int32_t* outRetireFence);
+        HWC2::Error setActiveConfig(hwc2_config_t configId);
+        HWC2::Error setClientTarget(buffer_handle_t target,
+                int32_t acquireFence, int32_t dataspace,
+                hwc_region_t damage);
+        HWC2::Error setColorMode(int32_t mode);
+        HWC2::Error setColorTransform(const float* matrix,
+                int32_t hint);
+        HWC2::Error setOutputBuffer(buffer_handle_t buffer,
+                int32_t releaseFence);
+        HWC2::Error setPowerMode(int32_t mode);
+        HWC2::Error setVsyncEnabled(int32_t enabled);
+        HWC2::Error validate(uint32_t* outNumTypes,
+                uint32_t* outNumRequests);
+        HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
+        HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height,
+                 int32_t format, int32_t dataspace);
+
+        // Read configs from PRIMARY Display
+        int populatePrimaryConfigs();
+
+    private:
+        class Config {
+        public:
+            Config(Display& display)
+              : mDisplay(display),
+                mId(0),
+                mAttributes() {}
+
+            bool isOnDisplay(const Display& display) const {
+                return display.getId() == mDisplay.getId();
+            }
+            void setAttribute(HWC2::Attribute attribute, int32_t value);
+            int32_t getAttribute(HWC2::Attribute attribute) const;
+            void setId(hwc2_config_t id) {mId = id; }
+            hwc2_config_t getId() const {return mId; }
+            std::string toString() const;
+
+        private:
+            Display& mDisplay;
+            hwc2_config_t mId;
+            std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
+        };
+
+        // Stores changes requested from the device upon calling prepare().
+        // Handles change request to:
+        //   - Layer composition type.
+        //   - Layer hints.
+        class Changes {
+            public:
+                uint32_t getNumTypes() const {
+                    return static_cast<uint32_t>(mTypeChanges.size());
+                }
+
+                uint32_t getNumLayerRequests() const {
+                    return static_cast<uint32_t>(mLayerRequests.size());
+                }
+
+                const std::unordered_map<hwc2_layer_t, HWC2::Composition>&
+                        getTypeChanges() const {
+                    return mTypeChanges;
+                }
+
+                const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>&
+                        getLayerRequests() const {
+                    return mLayerRequests;
+                }
+
+                void addTypeChange(hwc2_layer_t layerId,
+                        HWC2::Composition type) {
+                    mTypeChanges.insert({layerId, type});
+                }
+
+                void clearTypeChanges() { mTypeChanges.clear(); }
+
+                void addLayerRequest(hwc2_layer_t layerId,
+                        HWC2::LayerRequest request) {
+                    mLayerRequests.insert({layerId, request});
+                }
+
+            private:
+                std::unordered_map<hwc2_layer_t, HWC2::Composition>
+                        mTypeChanges;
+                std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>
+                        mLayerRequests;
+        };
+
+        // Generate sw vsync signal
+        class VsyncThread : public Thread {
+        public:
+            VsyncThread(Display& display)
+              : mDisplay(display) {}
+            virtual ~VsyncThread() {}
+        private:
+            Display& mDisplay;
+            bool threadLoop() final;
+        };
+
+    private:
+        EmuHWC2& mDevice;
+        // Display ID generator.
+        static std::atomic<hwc2_display_t> sNextId;
+        const hwc2_display_t mId;
+        std::string mName;
+        HWC2::DisplayType mType;
+        HWC2::PowerMode mPowerMode;
+        HWC2::Vsync mVsyncEnabled;
+        uint32_t mVsyncPeriod;
+        VsyncThread mVsyncThread;
+        FencedBuffer mClientTarget;
+        // Will only be non-null after the Display has been validated and
+        // before it has been presented
+        std::unique_ptr<Changes> mChanges;
+        // All layers this Display is aware of.
+        std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers;
+        std::vector<std::shared_ptr<Config>> mConfigs;
+        std::shared_ptr<const Config> mActiveConfig;
+        std::set<android_color_mode_t> mColorModes;
+        android_color_mode_t mActiveColorMode;
+        bool mSetColorTransform;
+        // The state of this display should only be modified from
+        // SurfaceFlinger's main loop, with the exception of when dump is
+        // called. To prevent a bad state from crashing us during a dump
+        // call, all public calls into Display must acquire this mutex.
+        mutable std::mutex mStateMutex;
+        std::unique_ptr<GrallocModule> mGralloc;
+        std::unique_ptr<ComposeMsg> mComposeMsg;
+   };
+
+    template<typename MF, MF memFunc, typename ...Args>
+    static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId,
+            Args... args) {
+        auto display = getHWC2(device)->getDisplay(displayId);
+        if (!display) {
+            return static_cast<int32_t>(HWC2::Error::BadDisplay);
+        }
+        auto error = ((*display).*memFunc)(std::forward<Args>(args)...);
+        return static_cast<int32_t>(error);
+    }
+
+    class Layer {
+    public:
+        explicit Layer(Display& display);
+        Display& getDisplay() const {return mDisplay;}
+        hwc2_layer_t getId() const {return mId;}
+        bool operator==(const Layer& other) { return mId == other.mId; }
+        bool operator!=(const Layer& other) { return !(*this == other); }
+
+        // HWC2 Layer functions
+        HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence);
+        HWC2::Error setCursorPosition(int32_t x, int32_t y);
+        HWC2::Error setSurfaceDamage(hwc_region_t damage);
+
+        // HWC2 Layer state functions
+        HWC2::Error setBlendMode(int32_t mode);
+        HWC2::Error setColor(hwc_color_t color);
+        HWC2::Error setCompositionType(int32_t type);
+        HWC2::Error setDataspace(int32_t dataspace);
+        HWC2::Error setDisplayFrame(hwc_rect_t frame);
+        HWC2::Error setPlaneAlpha(float alpha);
+        HWC2::Error setSidebandStream(const native_handle_t* stream);
+        HWC2::Error setSourceCrop(hwc_frect_t crop);
+        HWC2::Error setTransform(int32_t transform);
+        HWC2::Error setVisibleRegion(hwc_region_t visible);
+        HWC2::Error setZ(uint32_t z);
+
+        HWC2::Composition getCompositionType() const {
+            return mCompositionType;
+        }
+        hwc_color_t getColor() {return mColor; }
+        uint32_t getZ() {return mZ; }
+        std::size_t getNumVisibleRegions() {return mVisibleRegion.size(); }
+        FencedBuffer& getLayerBuffer() {return mBuffer; }
+        int32_t getBlendMode() {return (int32_t)mBlendMode; }
+        float getPlaneAlpha() {return mPlaneAlpha; }
+        hwc_frect_t getSourceCrop() {return mSourceCrop; }
+        hwc_rect_t getDisplayFrame() {return mDisplayFrame; }
+        hwc_transform_t getTransform() {return (hwc_transform_t)mTransform; }
+    private:
+        static std::atomic<hwc2_layer_t> sNextId;
+        const hwc2_layer_t mId;
+        Display& mDisplay;
+        FencedBuffer mBuffer;
+        std::vector<hwc_rect_t> mSurfaceDamage;
+
+        HWC2::BlendMode mBlendMode;
+        hwc_color_t mColor;
+        HWC2::Composition mCompositionType;
+        hwc_rect_t mDisplayFrame;
+        float mPlaneAlpha;
+        const native_handle_t* mSidebandStream;
+        hwc_frect_t mSourceCrop;
+        HWC2::Transform mTransform;
+        std::vector<hwc_rect_t> mVisibleRegion;
+        uint32_t mZ;
+    };
+
+    template <typename MF, MF memFunc, typename ...Args>
+    static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId,
+            hwc2_layer_t layerId, Args... args) {
+        auto result = getHWC2(device)->getLayer(displayId, layerId);
+        auto error = std::get<HWC2::Error>(result);
+        if (error == HWC2::Error::None) {
+            auto layer = std::get<Layer*>(result);
+            error = ((*layer).*memFunc)(std::forward<Args>(args)...);
+        }
+        return static_cast<int32_t>(error);
+    }
+
+    // helpers
+    void populateCapabilities();
+    Display* getDisplay(hwc2_display_t id);
+    std::tuple<Layer*, HWC2::Error> getLayer(hwc2_display_t displayId,
+            hwc2_layer_t layerId);
+
+    std::unordered_set<HWC2::Capability> mCapabilities;
+
+    // These are potentially accessed from multiple threads, and are protected
+    // by this mutex.
+    std::mutex mStateMutex;
+
+    struct CallbackInfo {
+        hwc2_callback_data_t data;
+        hwc2_function_pointer_t pointer;
+    };
+    std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks;
+
+    std::unordered_map<hwc2_display_t, std::shared_ptr<Display>> mDisplays;
+    std::unordered_map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers;
+
+};
+
+}
+#endif
diff --git a/system/hwc2/MiniFence.cpp b/system/hwc2/MiniFence.cpp
new file mode 100644
index 0000000..ecfb063
--- /dev/null
+++ b/system/hwc2/MiniFence.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MiniFence.h"
+
+#include <unistd.h>
+
+namespace android {
+
+const sp<MiniFence> MiniFence::NO_FENCE = sp<MiniFence>(new MiniFence);
+
+MiniFence::MiniFence() :
+    mFenceFd(-1) {
+}
+
+MiniFence::MiniFence(int fenceFd) :
+    mFenceFd(fenceFd) {
+}
+
+MiniFence::~MiniFence() {
+    if (mFenceFd != -1) {
+        close(mFenceFd);
+    }
+}
+
+int MiniFence::dup() const {
+    return ::dup(mFenceFd);
+}
+}
diff --git a/system/hwc2/MiniFence.h b/system/hwc2/MiniFence.h
new file mode 100644
index 0000000..31c9536
--- /dev/null
+++ b/system/hwc2/MiniFence.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EMU_HWC2_MINIFENCE_H
+#define EMU_HWC2_MINIFENCE_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+/* MiniFence is a minimal re-implementation of Fence from libui. It exists to
+ * avoid linking the HWC2on1Adapter to libui and satisfy Treble requirements.
+ */
+class MiniFence : public LightRefBase<MiniFence> {
+public:
+    static const sp<MiniFence> NO_FENCE;
+
+    // Construct a new MiniFence object with an invalid file descriptor.
+    MiniFence();
+
+    // Construct a new MiniFence object to manage a given fence file descriptor.
+    // When the new MiniFence object is destructed the file descriptor will be
+    // closed.
+    explicit MiniFence(int fenceFd);
+
+    // Not copyable or movable.
+    MiniFence(const MiniFence& rhs) = delete;
+    MiniFence& operator=(const MiniFence& rhs) = delete;
+    MiniFence(MiniFence&& rhs) = delete;
+    MiniFence& operator=(MiniFence&& rhs) = delete;
+
+    // Return a duplicate of the fence file descriptor. The caller is
+    // responsible for closing the returned file descriptor. On error, -1 will
+    // be returned and errno will indicate the problem.
+    int dup() const;
+
+private:
+    // Only allow instantiation using ref counting.
+    friend class LightRefBase<MiniFence>;
+    ~MiniFence();
+
+    int mFenceFd;
+
+};
+}
+#endif //EMU_HWC2_MINIFENCE_H
diff --git a/system/renderControl_enc/renderControl_client_context.cpp b/system/renderControl_enc/renderControl_client_context.cpp
index 4a86244..fb5ead1 100644
--- a/system/renderControl_enc/renderControl_client_context.cpp
+++ b/system/renderControl_enc/renderControl_client_context.cpp
@@ -47,6 +47,7 @@
 	rcUpdateColorBufferDMA = (rcUpdateColorBufferDMA_client_proc_t) getProc("rcUpdateColorBufferDMA", userData);
 	rcCreateColorBufferDMA = (rcCreateColorBufferDMA_client_proc_t) getProc("rcCreateColorBufferDMA", userData);
 	rcWaitSyncKHR = (rcWaitSyncKHR_client_proc_t) getProc("rcWaitSyncKHR", userData);
+	rcCompose = (rcCompose_client_proc_t) getProc("rcCompose", userData);
 	return 0;
 }
 
diff --git a/system/renderControl_enc/renderControl_client_context.h b/system/renderControl_enc/renderControl_client_context.h
index 1e5594b..5d3878c 100644
--- a/system/renderControl_enc/renderControl_client_context.h
+++ b/system/renderControl_enc/renderControl_client_context.h
@@ -47,6 +47,7 @@
 	rcUpdateColorBufferDMA_client_proc_t rcUpdateColorBufferDMA;
 	rcCreateColorBufferDMA_client_proc_t rcCreateColorBufferDMA;
 	rcWaitSyncKHR_client_proc_t rcWaitSyncKHR;
+	rcCompose_client_proc_t rcCompose;
 	virtual ~renderControl_client_context_t() {}
 
 	typedef renderControl_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/system/renderControl_enc/renderControl_client_proc.h b/system/renderControl_enc/renderControl_client_proc.h
index 3f1e5bb..24708dd 100644
--- a/system/renderControl_enc/renderControl_client_proc.h
+++ b/system/renderControl_enc/renderControl_client_proc.h
@@ -46,6 +46,7 @@
 typedef int (renderControl_APIENTRY *rcUpdateColorBufferDMA_client_proc_t) (void * ctx, uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*, uint32_t);
 typedef uint32_t (renderControl_APIENTRY *rcCreateColorBufferDMA_client_proc_t) (void * ctx, uint32_t, uint32_t, GLenum, int);
 typedef void (renderControl_APIENTRY *rcWaitSyncKHR_client_proc_t) (void * ctx, uint64_t, EGLint);
+typedef GLint (renderControl_APIENTRY *rcCompose_client_proc_t) (void * ctx, uint32_t, void*);
 
 
 #endif
diff --git a/system/renderControl_enc/renderControl_enc.cpp b/system/renderControl_enc/renderControl_enc.cpp
index f250926..905b6a9 100644
--- a/system/renderControl_enc/renderControl_enc.cpp
+++ b/system/renderControl_enc/renderControl_enc.cpp
@@ -1393,6 +1393,49 @@
 
 }
 
+GLint rcCompose_enc(void *self , uint32_t bufferSize, void* buffer)
+{
+
+	renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
+	IOStream *stream = ctx->m_stream;
+	ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+	bool useChecksum = checksumCalculator->getVersion() > 0;
+
+	const unsigned int __size_buffer =  bufferSize;
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 4 + __size_buffer + 1*4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_rcCompose;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &bufferSize, 4); ptr += 4;
+	*(unsigned int *)(ptr) = __size_buffer; ptr += 4;
+	memcpy(ptr, buffer, __size_buffer);ptr += __size_buffer;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+
+	GLint retval;
+	stream->readback(&retval, 4);
+	if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
+	if (useChecksum) {
+		unsigned char *checksumBufPtr = NULL;
+		unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+		if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+		stream->readback(checksumBufPtr, checksumSize);
+		if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+			ALOGE("rcCompose: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+	return retval;
+}
+
 }  // namespace
 
 renderControl_encoder_context_t::renderControl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -1437,5 +1480,6 @@
 	this->rcUpdateColorBufferDMA = &rcUpdateColorBufferDMA_enc;
 	this->rcCreateColorBufferDMA = &rcCreateColorBufferDMA_enc;
 	this->rcWaitSyncKHR = &rcWaitSyncKHR_enc;
+	this->rcCompose = &rcCompose_enc;
 }
 
diff --git a/system/renderControl_enc/renderControl_entry.cpp b/system/renderControl_enc/renderControl_entry.cpp
index 9a47dd3..4296940 100644
--- a/system/renderControl_enc/renderControl_entry.cpp
+++ b/system/renderControl_enc/renderControl_entry.cpp
@@ -42,6 +42,7 @@
 	int rcUpdateColorBufferDMA(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size);
 	uint32_t rcCreateColorBufferDMA(uint32_t width, uint32_t height, GLenum internalFormat, int frameworkFormat);
 	void rcWaitSyncKHR(uint64_t sync, EGLint flags);
+	GLint rcCompose(uint32_t bufferSize, void* buffer);
 };
 
 #ifndef GET_CONTEXT
@@ -272,3 +273,9 @@
 	ctx->rcWaitSyncKHR(ctx, sync, flags);
 }
 
+GLint rcCompose(uint32_t bufferSize, void* buffer)
+{
+	GET_CONTEXT;
+	return ctx->rcCompose(ctx, bufferSize, buffer);
+}
+
diff --git a/system/renderControl_enc/renderControl_ftable.h b/system/renderControl_enc/renderControl_ftable.h
index 7bfc7c5..ab75bb0 100644
--- a/system/renderControl_enc/renderControl_ftable.h
+++ b/system/renderControl_enc/renderControl_ftable.h
@@ -45,6 +45,7 @@
 	{"rcUpdateColorBufferDMA", (void*)rcUpdateColorBufferDMA},
 	{"rcCreateColorBufferDMA", (void*)rcCreateColorBufferDMA},
 	{"rcWaitSyncKHR", (void*)rcWaitSyncKHR},
+	{"rcCompose", (void*)rcCompose},
 };
 static const int renderControl_num_funcs = sizeof(renderControl_funcs_by_name) / sizeof(struct _renderControl_funcs_by_name);
 
diff --git a/system/renderControl_enc/renderControl_opcodes.h b/system/renderControl_enc/renderControl_opcodes.h
index 146164f..100faaa 100644
--- a/system/renderControl_enc/renderControl_opcodes.h
+++ b/system/renderControl_enc/renderControl_opcodes.h
@@ -40,7 +40,8 @@
 #define OP_rcUpdateColorBufferDMA 					10034
 #define OP_rcCreateColorBufferDMA 					10035
 #define OP_rcWaitSyncKHR 					10036
-#define OP_last 					10037
+#define OP_rcCompose 					10037
+#define OP_last 					10038
 
 
 #endif