/*
 * 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 <cutils/properties.h>
#include <log/log.h>
#include <sync/sync.h>

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicBufferAllocator.h>

#include "../egl/goldfish_sync.h"

#include "ThreadInfo.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);
}

static std::unique_ptr<HostConnection> sHostCon;

static HostConnection* createOrGetHostConnection() {
    if (!sHostCon) {
        sHostCon = HostConnection::createUnique();
    }
    return sHostCon.get();
}

#define DEFINE_AND_VALIDATE_HOST_CONNECTION \
    HostConnection *hostCon = createOrGetHostConnection(); \
    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();
    initDisplayParameters();
}

Error EmuHWC2::initDisplayParameters() {
    DEFINE_AND_VALIDATE_HOST_CONNECTION
    hostCon->lock();

    mDisplayWidth = rcEnc->rcGetFBParam(rcEnc, FB_WIDTH);
    mDisplayHeight = rcEnc->rcGetFBParam(rcEnc, FB_HEIGHT);
    mDisplayDpiX = rcEnc->rcGetFBParam(rcEnc, FB_XDPI);
    mDisplayDpiY = rcEnc->rcGetFBParam(rcEnc, FB_YDPI);

    hostCon->unlock();

    return HWC2::Error::None;
}

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>);
        // 2.3 required functions
        case FunctionDescriptor::GetDisplayIdentificationData:
            return asFP<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>(
                    displayHook<decltype(&Display::getDisplayIdentificationData),
                    &Display::getDisplayIdentificationData, uint8_t*, uint32_t*, uint8_t*>);
        case FunctionDescriptor::GetDisplayCapabilities:
            return asFP<HWC2_PFN_GET_DISPLAY_CAPABILITIES>(
                    displayHook<decltype(&Display::getDisplayCapabilities),
                    &Display::getDisplayCapabilities, uint32_t*, uint32_t*>);
        case FunctionDescriptor::GetDisplayBrightnessSupport:
            return asFP<HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT>(
                    displayHook<decltype(&Display::getDisplayBrightnessSupport),
                    &Display::getDisplayBrightnessSupport, bool*>);
        case FunctionDescriptor::SetDisplayBrightness:
            return asFP<HWC2_PFN_SET_DISPLAY_BRIGHTNESS>(
                    displayHook<decltype(&Display::setDisplayBrightness),
                    &Display::setDisplayBrightness, float>);
        // 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_HOTPLUG>(pointer);
        for (const auto& iter : mDisplays) {
            hotplug(callbackData, iter.first, static_cast<int32_t>(Connection::Connected));
        }
    }

    return Error::None;
}

const native_handle_t* EmuHWC2::allocateDisplayColorBuffer(int width, int height) {
    const uint32_t layerCount = 1;
    const uint64_t graphicBufferId = 0; // not used

    buffer_handle_t h;
    uint32_t stride;

    if (GraphicBufferAllocator::get().allocate(
        width, height,
        PIXEL_FORMAT_RGBA_8888,
        layerCount,
        (GraphicBuffer::USAGE_HW_COMPOSER | GraphicBuffer::USAGE_HW_RENDER),
        &h, &stride,
        graphicBufferId, "EmuHWC2") == OK) {
        return static_cast<const native_handle_t*>(h);
    } else {
        return nullptr;
    }
}

void EmuHWC2::freeDisplayColorBuffer(const native_handle_t* h) {
    GraphicBufferAllocator::get().free(h);
}

// Display functions

#define VSYNC_PERIOD_PROP "ro.kernel.qemu.vsync"

static int getVsyncPeriodFromProperty() {
    char displaysValue[PROPERTY_VALUE_MAX] = "";
    property_get(VSYNC_PERIOD_PROP, displaysValue, "");
    bool isValid = displaysValue[0] != '\0';

    if (!isValid) return 60;

    long vsyncPeriodParsed = strtol(displaysValue, 0, 10);

    // On failure, strtol returns 0. Also, there's no reason to have 0
    // as the vsync period.
    if (!vsyncPeriodParsed) return 60;

    return static_cast<int>(vsyncPeriodParsed);
}

std::atomic<hwc2_display_t> EmuHWC2::Display::sNextId(0);

EmuHWC2::Display::Display(EmuHWC2& device, DisplayType type, int width, int height)
  : mDevice(device),
    mId(sNextId++),
    mHostDisplayId(0),
    mName(),
    mType(type),
    mPowerMode(PowerMode::Off),
    mVsyncEnabled(Vsync::Invalid),
    mVsyncPeriod(1000*1000*1000/getVsyncPeriodFromProperty()), // vsync is 60 hz
    mVsyncThread(*this),
    mClientTarget(),
    mChanges(),
    mLayers(),
    mReleaseLayerIds(),
    mReleaseFences(),
    mConfigs(),
    mActiveConfig(nullptr),
    mColorModes(),
    mSetColorTransform(false),
    mStateMutex() {
        mVsyncThread.run("", ANDROID_PRIORITY_URGENT_DISPLAY);
        mTargetCb = device.allocateDisplayColorBuffer(width, height);
}

EmuHWC2::Display::~Display() {
    mDevice.freeDisplayColorBuffer(mTargetCb);
}

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 = mReleaseLayerIds.size();

    ALOGVV("%s. Got %u elements", __FUNCTION__, *outNumElements);

    if (*outNumElements && outLayers) {
        ALOGVV("%s. export release layers", __FUNCTION__);
        memcpy(outLayers, mReleaseLayerIds.data(),
               sizeof(hwc2_layer_t) * (*outNumElements));
    }

    if (*outNumElements && outFences) {
        ALOGVV("%s. export release fences", __FUNCTION__);
        memcpy(outFences, mReleaseFences.data(),
               sizeof(int32_t) * (*outNumElements));
    }

    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__);

    *outRetireFence = -1;

    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
    hostCon->lock();
    bool hostCompositionV1 = rcEnc->hasHostCompositionV1();
    bool hostCompositionV2 = rcEnc->hasHostCompositionV2();
    hostCon->unlock();

    // if we supports v2, then discard v1
    if (hostCompositionV2) {
        hostCompositionV1 = false;
    }

    if (hostCompositionV2 || hostCompositionV1) {
        uint32_t numLayer = 0;
        for (auto layer: mLayers) {
            if (layer->getCompositionType() == Composition::Device ||
                layer->getCompositionType() == Composition::SolidColor) {
                numLayer++;
            }
        }

        ALOGVV("present %d layers total %u layers",
              numLayer, (uint32_t)mLayers.size());

        mReleaseLayerIds.clear();
        mReleaseFences.clear();

        if (numLayer == 0) {
            ALOGW("No layers, exit, buffer %p", mClientTarget.getBuffer());
            if (mClientTarget.getBuffer()) {
                post(hostCon, rcEnc, mClientTarget.getBuffer());
                *outRetireFence = mClientTarget.getFence();
            }
            return Error::None;
        }

        if (hostCompositionV1) {
            if (mComposeMsg == nullptr || mComposeMsg->getLayerCnt() < numLayer) {
                mComposeMsg.reset(new ComposeMsg(numLayer));
            }
        } else {
            if (mComposeMsg_v2 == nullptr || mComposeMsg_v2->getLayerCnt() < numLayer) {
                mComposeMsg_v2.reset(new ComposeMsg_v2(numLayer));
            }
        }

        // Handle the composition
        ComposeDevice* p;
        ComposeDevice_v2* p2;
        ComposeLayer* l;

        if (hostCompositionV1) {
            p = mComposeMsg->get();
            l = p->layer;
        } else {
            p2 = mComposeMsg_v2->get();
            l = p2->layer;
        }

        for (auto layer: mLayers) {
            if (layer->getCompositionType() != Composition::Device &&
                layer->getCompositionType() != Composition::SolidColor) {
                ALOGE("%s: Unsupported composition types %d layer %u",
                      __FUNCTION__, layer->getCompositionType(),
                      (uint32_t)layer->getId());
                continue;
            }
            // send layer composition command to host
            if (layer->getCompositionType() == Composition::Device) {
                int fence = layer->getLayerBuffer().getFence();
                mReleaseLayerIds.push_back(layer->getId());
                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);
                    }
                    close(fence);
                }
                else {
                    ALOGV("%s: acquire fence not set for layer %u",
                          __FUNCTION__, (uint32_t)layer->getId());
                }
                const native_handle_t *cb =
                    layer->getLayerBuffer().getBuffer();
                if (cb != nullptr) {
                    l->cbHandle = hostCon->grallocHelper()->getHostHandle(cb);
                }
                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++;
        }
        if (hostCompositionV1) {
            p->version = 1;
            p->targetHandle = hostCon->grallocHelper()->getHostHandle(mTargetCb);
            p->numLayers = numLayer;
        } else {
            p2->version = 2;
            p2->displayId = mHostDisplayId;
            p2->targetHandle = hostCon->grallocHelper()->getHostHandle(mTargetCb);
            p2->numLayers = numLayer;
        }

        hostCon->lock();
        if (rcEnc->hasAsyncFrameCommands()) {
            if (hostCompositionV1) {
                rcEnc->rcComposeAsync(rcEnc,
                        sizeof(ComposeDevice) + numLayer * sizeof(ComposeLayer),
                        (void *)p);
            } else {
                rcEnc->rcComposeAsync(rcEnc,
                        sizeof(ComposeDevice_v2) + numLayer * sizeof(ComposeLayer),
                        (void *)p2);
            }
        } else {
            if (hostCompositionV1) {
                rcEnc->rcCompose(rcEnc,
                        sizeof(ComposeDevice) + numLayer * sizeof(ComposeLayer),
                        (void *)p);
            } else {
                rcEnc->rcCompose(rcEnc,
                        sizeof(ComposeDevice_v2) + numLayer * sizeof(ComposeLayer),
                        (void *)p2);
            }
        }

        hostCon->unlock();

        // Send a retire fence and use it as the release fence for all layers,
        // since media expects it
        EGLint attribs[] = { EGL_SYNC_NATIVE_FENCE_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID };

        uint64_t sync_handle, thread_handle;
        int retire_fd;

        hostCon->lock();
        rcEnc->rcCreateSyncKHR(rcEnc, EGL_SYNC_NATIVE_FENCE_ANDROID,
                attribs, 2 * sizeof(EGLint), true /* destroy when signaled */,
                &sync_handle, &thread_handle);
        hostCon->unlock();

        goldfish_sync_queue_work(mSyncDeviceFd,
                sync_handle, thread_handle, &retire_fd);

        for (size_t i = 0; i < mReleaseLayerIds.size(); ++i) {
            mReleaseFences.push_back(dup(retire_fd));
        }

        *outRetireFence = dup(retire_fd);
        close(retire_fd);
        hostCon->lock();
        if (rcEnc->hasAsyncFrameCommands()) {
            rcEnc->rcDestroySyncKHRAsync(rcEnc, sync_handle);
        } else {
            rcEnc->rcDestroySyncKHR(rcEnc, sync_handle);
        }
        hostCon->unlock();
    } else {
        // we set all layers Composition::Client, so do nothing.
        post(hostCon, rcEnc, 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 %u", __FUNCTION__, (uint32_t)configId);
    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__);

    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 %d", __FUNCTION__, intMode);
    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 hint %d", __FUNCTION__, hint);
    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 %d", __FUNCTION__, intEnable);
    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
        hostCon->lock();
        bool hostCompositionV1 = rcEnc->hasHostCompositionV1();
        bool hostCompositionV2 = rcEnc->hasHostCompositionV2();
        hostCon->unlock();

        if (hostCompositionV1 || hostCompositionV2) {
            // Support Device and SolidColor, otherwise, fallback all layers
            // to Client
            bool fallBack = false;
            for (auto& layer : mLayers) {
                if (layer->getCompositionType() == Composition::Invalid) {
                    // Log error for unused layers, layer leak?
                    ALOGE("%s layer %u CompositionType(%d) not set",
                          __FUNCTION__, (uint32_t)layer->getId(),
                          layer->getCompositionType());
                    continue;
                }
                if (layer->getCompositionType() == Composition::Client ||
                    layer->getCompositionType() == Composition::Cursor ||
                    layer->getCompositionType() == Composition::Sideband) {
                    ALOGW("%s: layer %u CompositionType %d, fallback", __FUNCTION__,
                         (uint32_t)layer->getId(), layer->getCompositionType());
                    fallBack = true;
                    break;
                }
            }
            if (mSetColorTransform) {
                fallBack = true;
            }
            if (fallBack) {
                for (auto& layer : mLayers) {
                    if (layer->getCompositionType() == Composition::Invalid) {
                        continue;
                    }
                    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;
}

// thess EDIDs are carefully generated according to the EDID spec version 1.3, more info
// can be found from the following file:
//   frameworks/native/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
// approved pnp ids can be found here: https://uefi.org/pnp_id_list
// pnp id: GGL, name: EMU_display_0, last byte is checksum
// display id is local:8141603649153536
static const uint8_t sEDID0[] = {
    0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27,
    0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
    0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
    0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x30, 0x00, 0x4b
};

// pnp id: GGL, name: EMU_display_1
// display id is local:8140900251843329
static const uint8_t sEDID1[] = {
    0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27,
    0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
    0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
    0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x31, 0x00, 0x3b
};

// pnp id: GGL, name: EMU_display_2
// display id is local:8140940453066754
static const uint8_t sEDID2[] = {
    0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27,
    0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
    0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
    0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x32, 0x00, 0x49
};

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))

Error EmuHWC2::Display::getDisplayIdentificationData(uint8_t* outPort,
        uint32_t* outDataSize, uint8_t* outData) {
    ALOGVV("%s DisplayId %u", __FUNCTION__, (uint32_t)mId);
    if (outPort == nullptr || outDataSize == nullptr)
        return Error::BadParameter;

    uint32_t len = std::min(*outDataSize, (uint32_t)ARRAY_SIZE(sEDID0));
    if (outData != nullptr && len < (uint32_t)ARRAY_SIZE(sEDID0)) {
        ALOGW("%s DisplayId %u, small buffer size: %u is specified",
                __FUNCTION__, (uint32_t)mId, len);
    }
    *outDataSize = ARRAY_SIZE(sEDID0);
    switch (mId) {
        case 0:
            *outPort = 0;
            if (outData)
                memcpy(outData, sEDID0, len);
            break;

        case 1:
            *outPort = 1;
            if (outData)
                memcpy(outData, sEDID1, len);
            break;

        case 2:
            *outPort = 2;
            if (outData)
                memcpy(outData, sEDID2, len);
            break;

        default:
            *outPort = (uint8_t)mId;
            if (outData) {
                memcpy(outData, sEDID2, len);
                uint32_t size = ARRAY_SIZE(sEDID0);
                // change the name to EMU_display_<mID>
                // note the 3rd char from back is the number, _0, _1, _2, etc.
                if (len >= size - 2)
                    outData[size-3] = '0' + (uint8_t)mId;
                if (len >= size) {
                    // update the last byte, which is checksum byte
                    uint8_t checksum = -(uint8_t)std::accumulate(
                            outData, outData + size - 1, static_cast<uint8_t>(0));
                    outData[size - 1] = checksum;
                }
            }
            break;
    }

    return Error::None;
}

Error EmuHWC2::Display::getDisplayCapabilities(uint32_t* outNumCapabilities,
        uint32_t* outCapabilities) {
    if (outNumCapabilities == nullptr) {
        return Error::None;
    }

    bool brightness_support = true;
    bool doze_support = true;

    uint32_t count = 1  + static_cast<uint32_t>(doze_support) + (brightness_support ? 1 : 0);
    int index = 0;
    if (outCapabilities != nullptr && (*outNumCapabilities >= count)) {
        outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
        if (doze_support) {
            outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE;
        }
        if (brightness_support) {
            outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_BRIGHTNESS;
       }
    }

    *outNumCapabilities = count;
    return Error::None;
}

Error EmuHWC2::Display::getDisplayBrightnessSupport(bool *out_support) {
    *out_support = false;
    return Error::None;
}

Error EmuHWC2::Display::setDisplayBrightness(float brightness) {
    ALOGW("TODO: setDisplayBrightness() is not implemented yet: brightness=%f", brightness);
    return Error::None;
}

int EmuHWC2::Display::populatePrimaryConfigs(int width, int height, int dpiX, int dpiY) {
    ALOGVV("%s DisplayId %u", __FUNCTION__, (uint32_t)mId);
    std::unique_lock<std::mutex> lock(mStateMutex);

    auto newConfig = std::make_shared<Config>(*this);
    // vsync is 60 hz;
    newConfig->setAttribute(Attribute::VsyncPeriod, mVsyncPeriod);
    newConfig->setAttribute(Attribute::Width, width);
    newConfig->setAttribute(Attribute::Height, height);
    newConfig->setAttribute(Attribute::DpiX, dpiX * 1000);
    newConfig->setAttribute(Attribute::DpiY, dpiY * 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);

    mSyncDeviceFd = goldfish_sync_open();

    return 0;
}

void EmuHWC2::Display::post(HostConnection *hostCon,
                            ExtendedRCEncoderContext *rcEnc,
                            buffer_handle_t h) {
    assert(cb && "native_handle_t::from(h) failed");

    hostCon->lock();
    rcEnc->rcFBPost(rcEnc, hostCon->grallocHelper()->getHostHandle(h));
    hostCon->flush();
    hostCon->unlock();
}

HWC2::Error EmuHWC2::Display::populateSecondaryConfigs(uint32_t width, uint32_t height,
        uint32_t dpi, uint32_t idx) {
    ALOGVV("%s DisplayId %u, width %u, height %u, dpi %u",
            __FUNCTION__, (uint32_t)mId, width, height, dpi);
    std::unique_lock<std::mutex> lock(mStateMutex);

    auto newConfig = std::make_shared<Config>(*this);
    // vsync is 60 hz;
    newConfig->setAttribute(Attribute::VsyncPeriod, mVsyncPeriod);
    newConfig->setAttribute(Attribute::Width, width);
    newConfig->setAttribute(Attribute::Height, height);
    newConfig->setAttribute(Attribute::DpiX, dpi*1000);
    newConfig->setAttribute(Attribute::DpiY, dpi*1000);

    int configId = mConfigs.size();
    newConfig->setId(static_cast<hwc2_config_t>(configId));
    ALOGV("Found new secondary config %d: %s", (uint32_t)newConfig->getId(),
            newConfig->toString().c_str());
    mConfigs.emplace_back(std::move(newConfig));

    mActiveConfig = mConfigs[configId];
    mActiveColorMode = HAL_COLOR_MODE_NATIVE;
    mColorModes.emplace((android_color_mode_t)HAL_COLOR_MODE_NATIVE);

    uint32_t displayId = hostDisplayIdStart + idx;
    DEFINE_AND_VALIDATE_HOST_CONNECTION

    hostCon->lock();
    rcEnc->rcDestroyDisplay(rcEnc, displayId);
    rcEnc->rcCreateDisplay(rcEnc, &displayId);
    rcEnc->rcSetDisplayPose(rcEnc, displayId, -1, -1, width, height);
    hostCon->unlock();

    if (displayId != hostDisplayIdStart + idx) {
        ALOGE("Something wrong with host displayId allocation, want %d "
              "allocated %d", hostDisplayIdStart + idx, displayId);
    }
    mHostDisplayId = displayId;
    ALOGVV("%s: mHostDisplayId=%d", __FUNCTION__, mHostDisplayId);

    return HWC2::Error::None;
}


// 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;
    const int64_t kOneRefreshNs = mDisplay.mVsyncPeriod;
    const int64_t kOneSecondNs = 1000ULL * 1000ULL * 1000ULL;
    int64_t lastTimeNs = -1;
    int64_t phasedWaitNs = 0;
    int64_t currentNs = 0;

    while (true) {
        clock_gettime(CLOCK_MONOTONIC, &rt);
        currentNs = rt.tv_nsec + rt.tv_sec * kOneSecondNs;

        if (lastTimeNs < 0) {
            phasedWaitNs = currentNs + kOneRefreshNs;
        } else {
            phasedWaitNs = kOneRefreshNs *
                (( currentNs - lastTimeNs) / kOneRefreshNs + 1) +
                lastTimeNs;
        }

        wait_time.tv_sec = phasedWaitNs / kOneSecondNs;
        wait_time.tv_nsec = phasedWaitNs - wait_time.tv_sec * kOneSecondNs;

        int ret;
        do {
            ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wait_time, NULL);
        } while (ret == -1 && errno == EINTR);

        lastTimeNs = phasedWaitNs;

        std::unique_lock<std::mutex> lock(mDisplay.mStateMutex);
        vsyncEnabled = (mDisplay.mVsyncEnabled == Vsync::Enable);
        lock.unlock();

        if (!vsyncEnabled) {
            continue;
        }

        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, lastTimeNs);
        }

        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) const {
    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 layer %u", __FUNCTION__, (uint32_t)mId);
    if (mCompositionType != Composition::Cursor) {
        ALOGE("%s: CompositionType not Cursor type", __FUNCTION__);
        return Error::BadLayer;
    }
   //TODO
    return Error::None;
}

Error EmuHWC2::Layer::setSurfaceDamage(hwc_region_t /*damage*/) {
    // Emulator redraw whole layer per frame, so ignore this.
    ALOGVV("%s", __FUNCTION__);
    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 layer %u %d", __FUNCTION__, (uint32_t)mId, color);
    mColor = color;
    return Error::None;
}

Error EmuHWC2::Layer::setCompositionType(int32_t type) {
    ALOGVV("%s layer %u %u", __FUNCTION__, (uint32_t)mId, type);
    mCompositionType = static_cast<Composition>(type);
    return Error::None;
}

Error EmuHWC2::Layer::setDataspace(int32_t) {
    ALOGVV("%s", __FUNCTION__);
    return Error::None;
}

Error EmuHWC2::Layer::setDisplayFrame(hwc_rect_t frame) {
    ALOGVV("%s layer %u", __FUNCTION__, (uint32_t)mId);
    mDisplayFrame = frame;
    return Error::None;
}

Error EmuHWC2::Layer::setPlaneAlpha(float alpha) {
    ALOGVV("%s layer %u %f", __FUNCTION__, (uint32_t)mId, alpha);
    mPlaneAlpha = alpha;
    return Error::None;
}

Error EmuHWC2::Layer::setSidebandStream(const native_handle_t* stream) {
    ALOGVV("%s layer %u", __FUNCTION__, (uint32_t)mId);
    mSidebandStream = stream;
    return Error::None;
}

Error EmuHWC2::Layer::setSourceCrop(hwc_frect_t crop) {
    ALOGVV("%s layer %u", __FUNCTION__, (uint32_t)mId);
    mSourceCrop = crop;
    return Error::None;
}

Error EmuHWC2::Layer::setTransform(int32_t transform) {
    ALOGVV("%s layer %u", __FUNCTION__, (uint32_t)mId);
    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 layer %u %d", __FUNCTION__, (uint32_t)mId, 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,
            mDisplayWidth, mDisplayHeight);
    ret = display->populatePrimaryConfigs(mDisplayWidth, mDisplayHeight,
                                          mDisplayDpiX, mDisplayDpiY);
    if (ret != 0) {
        return ret;
    }
    mDisplays.emplace(display->getId(), std::move(display));
    return ret;
}

// Note "hwservicemanager." is used to avoid selinux issue
#define EXTERANL_DISPLAY_PROP "hwservicemanager.external.displays"

// return 0 for successful, 1 if no external displays are specified
// return < 0 if failed
int EmuHWC2::populateSecondaryDisplays() {
    // this guest property, hwservicemanager.external.displays,
    // specifies multi-display info, with comma (,) as separator
    // each display has the following info:
    //   physicalId,width,height,dpi,flags
    // serveral displays can be provided, e.g., following has 2 displays:
    // setprop hwservicemanager.external.displays 1,1200,800,120,0,2,1200,800,120,0
    std::vector<uint64_t> values;
    char displaysValue[PROPERTY_VALUE_MAX] = "";
    property_get(EXTERANL_DISPLAY_PROP, displaysValue, "");
    bool isValid = displaysValue[0] != '\0';
    if (isValid) {
        char *p = displaysValue;
        while (*p) {
            if (!isdigit(*p) && *p != ',' && *p != ' ') {
                isValid = false;
                break;
            }
            p ++;
        }
        if (!isValid) {
            ALOGE("Invalid syntax for the value of system prop: %s", EXTERANL_DISPLAY_PROP);
        }
    }
    if (!isValid) {
        // no external displays are specified
        return 1;
    }
    // parse all int values to a vector
    std::istringstream stream(displaysValue);
    for (uint64_t id; stream >> id;) {
        values.push_back(id);
        if (stream.peek() == ',')
            stream.ignore();
    }
    // each display has 5 values
    if ((values.size() % 5) != 0) {
        ALOGE("%s: invalid value for system property: %s", __FUNCTION__, EXTERANL_DISPLAY_PROP);
        return -1;
    }
    uint32_t idx = 0;
    while (!values.empty()) {
        // uint64_t physicalId = values[0];
        uint32_t width = values[1];
        uint32_t height = values[2];
        uint32_t dpi = values[3];
        // uint32_t flags = values[4];
        values.erase(values.begin(), values.begin() + 5);

        Error ret = Error::None;
        auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical, width, height);
        ret = display->populateSecondaryConfigs(width, height, dpi, idx++);
        if (ret != Error::None) {
            return -2;
        }
        mDisplays.emplace(display->getId(), std::move(display));
    }
    return 0;
}

EmuHWC2::Display* EmuHWC2::getDisplay(hwc2_display_t id) {
    auto display = mDisplays.find(id);
    if (display == mDisplays.end()) {
        ALOGE("Failed to get display for id=%d", (uint32_t)id);
        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) {
    ALOGVV("%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;
    }

    ret = ctx->populateSecondaryDisplays();
    if (ret < 0) {
        ALOGE("Failed to populate secondary displays");
        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},
};
