Merge "Select GL transport and draw call flush interval based on prop"
diff --git a/system/hwc2/EmuHWC2.cpp b/system/hwc2/EmuHWC2.cpp
index 921d848..db23c46 100644
--- a/system/hwc2/EmuHWC2.cpp
+++ b/system/hwc2/EmuHWC2.cpp
@@ -219,6 +219,23 @@
                     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>(
@@ -1130,6 +1147,136 @@
     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 std::vector<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 std::vector<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 std::vector<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
+};
+
+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)(sEDID0.size()));
+    if (outData != nullptr && len < (uint32_t)(sEDID0.size())) {
+        ALOGW("%s DisplayId %u, small buffer size: %u is specified",
+                __FUNCTION__, (uint32_t)mId, len);
+    }
+    *outDataSize = (int32_t)(sEDID0.size());
+    switch (mId) {
+        case 0:
+            *outPort = 0;
+            if (outData)
+                memcpy(outData, sEDID0.data(), len);
+            break;
+
+        case 1:
+            *outPort = 1;
+            if (outData)
+                memcpy(outData, sEDID1.data(), len);
+            break;
+
+        case 2:
+            *outPort = 2;
+            if (outData)
+                memcpy(outData, sEDID2.data(), len);
+            break;
+
+        default:
+            *outPort = (uint8_t)mId;
+            if (outData) {
+                memcpy(outData, sEDID2.data(), len);
+                uint32_t size = sEDID0.size();
+                // 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() {
     ALOGVV("%s DisplayId %u", __FUNCTION__, (uint32_t)mId);
@@ -1524,6 +1671,7 @@
 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();
diff --git a/system/hwc2/EmuHWC2.h b/system/hwc2/EmuHWC2.h
index d4615a7..765a649 100644
--- a/system/hwc2/EmuHWC2.h
+++ b/system/hwc2/EmuHWC2.h
@@ -27,6 +27,7 @@
 #include <atomic>
 #include <map>
 #include <mutex>
+#include <numeric>
 #include <sstream>
 #include <vector>
 #include <unordered_set>
@@ -257,6 +258,13 @@
         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);
+        // 2.3 required functions
+        HWC2::Error getDisplayIdentificationData(uint8_t* outPort,
+                 uint32_t* outDataSize, uint8_t* outData);
+        HWC2::Error getDisplayCapabilities(uint32_t* outNumCapabilities,
+                 uint32_t* outCapabilities);
+        HWC2::Error getDisplayBrightnessSupport(bool *out_support);
+        HWC2::Error setDisplayBrightness(float brightness);
 
         // Read configs from PRIMARY Display
         int populatePrimaryConfigs();