[SurfaceFlinger] Extend HDR support.

Previously we stored HDR10 support in DisplayDevice. This patch extends and
generalizes the support to HLG and Dolby Vision.

Minor: Adapt Hdr type from HAL.

BUG: 73825729
BUG: 77156734
Test: Build, flash, watch Youtube HDR
Change-Id: Id642bc9482523b4646814dca9ecfb1f043987dc5
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
index 755e60c..50f9bf1 100644
--- a/libs/ui/HdrCapabilities.cpp
+++ b/libs/ui/HdrCapabilities.cpp
@@ -33,7 +33,7 @@
             sizeof(mMaxAverageLuminance) +
             sizeof(mMinLuminance) +
             sizeof(int32_t) +
-            mSupportedHdrTypes.size() * sizeof(int32_t);
+            mSupportedHdrTypes.size() * sizeof(ui::Hdr);
 }
 
 status_t HdrCapabilities::flatten(void* buffer, size_t size) const {
@@ -48,7 +48,7 @@
     reinterpret_cast<float&>(buf[2]) = mMinLuminance;
     buf[3] = static_cast<int32_t>(mSupportedHdrTypes.size());
     for (size_t i = 0, c = mSupportedHdrTypes.size(); i < c; ++i) {
-        buf[4 + i] = mSupportedHdrTypes[i];
+        buf[4 + i] = static_cast<int32_t>(mSupportedHdrTypes[i]);
     }
     return NO_ERROR;
 }
@@ -78,7 +78,7 @@
     if (itemCount) {
         mSupportedHdrTypes.resize(itemCount);
         for (size_t i = 0; i < itemCount; ++i) {
-            mSupportedHdrTypes[i] = buf[4 + i];
+            mSupportedHdrTypes[i] = static_cast<ui::Hdr>(buf[4 + i]);
         }
     }
     return NO_ERROR;
diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h
index bd5722f..0fa819d 100644
--- a/libs/ui/include/ui/GraphicTypes.h
+++ b/libs/ui/include/ui/GraphicTypes.h
@@ -24,6 +24,7 @@
 namespace android {
 namespace ui {
 
+using android::hardware::graphics::common::V1_0::Hdr;
 using android::hardware::graphics::common::V1_1::ColorMode;
 using android::hardware::graphics::common::V1_1::Dataspace;
 using android::hardware::graphics::common::V1_1::PixelFormat;
diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h
index 925aa1b..4e98c28 100644
--- a/libs/ui/include/ui/HdrCapabilities.h
+++ b/libs/ui/include/ui/HdrCapabilities.h
@@ -21,6 +21,7 @@
 
 #include <vector>
 
+#include <ui/GraphicTypes.h>
 #include <utils/Flattenable.h>
 
 namespace android {
@@ -28,7 +29,7 @@
 class HdrCapabilities : public LightFlattenable<HdrCapabilities>
 {
 public:
-    HdrCapabilities(const std::vector<int32_t /*android_hdr_t*/>& types,
+    HdrCapabilities(const std::vector<ui::Hdr>& types,
             float maxLuminance, float maxAverageLuminance, float minLuminance)
       : mSupportedHdrTypes(types),
         mMaxLuminance(maxLuminance),
@@ -47,7 +48,7 @@
 
     ~HdrCapabilities();
 
-    const std::vector<int32_t /*android_hdr_t*/>& getSupportedHdrTypes() const {
+    const std::vector<ui::Hdr>& getSupportedHdrTypes() const {
         return mSupportedHdrTypes;
     }
     float getDesiredMaxLuminance() const { return mMaxLuminance; }
@@ -61,7 +62,7 @@
     status_t unflatten(void const* buffer, size_t size);
 
 private:
-    std::vector<int32_t /*android_hdr_t*/> mSupportedHdrTypes;
+    std::vector<ui::Hdr> mSupportedHdrTypes;
     float mMaxLuminance;
     float mMaxAverageLuminance;
     float mMinLuminance;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index d90ab1d..cd41662 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -55,6 +55,7 @@
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 using android::ui::ColorMode;
+using android::ui::Hdr;
 using android::ui::RenderIntent;
 
 /*
@@ -77,7 +78,7 @@
         int displayWidth,
         int displayHeight,
         bool hasWideColorGamut,
-        bool hasHdr10,
+        const HdrCapabilities& hdrCapabilities,
         int initialPowerMode)
     : lastCompositionHadVisibleLayers(false),
       mFlinger(flinger),
@@ -100,9 +101,26 @@
       mActiveColorMode(ColorMode::NATIVE),
       mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY),
       mHasWideColorGamut(hasWideColorGamut),
-      mHasHdr10(hasHdr10)
+      mHasHdr10(false),
+      mHasHLG(false),
+      mHasDolbyVision(false)
 {
     // clang-format on
+    for (Hdr hdrType : hdrCapabilities.getSupportedHdrTypes()) {
+        switch (hdrType) {
+            case Hdr::HDR10:
+                mHasHdr10 = true;
+                break;
+            case Hdr::HLG:
+                mHasHLG = true;
+                break;
+            case Hdr::DOLBY_VISION:
+                mHasDolbyVision = true;
+                break;
+            default:
+                ALOGE("UNKNOWN HDR capability: %d", static_cast<int32_t>(hdrType));
+        }
+    }
 
     // initialize the display orientation transform.
     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index b8a8906..cd0bed6 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -85,7 +85,7 @@
             int displayWidth,
             int displayHeight,
             bool hasWideColorGamut,
-            bool hasHdr10,
+            const HdrCapabilities& hdrCapabilities,
             int initialPowerMode);
     // clang-format on
 
@@ -136,7 +136,9 @@
     status_t beginFrame(bool mustRecompose) const;
     status_t prepareFrame(HWComposer& hwc);
     bool hasWideColorGamut() const { return mHasWideColorGamut; }
-    bool hasHdr10() const { return mHasHdr10; }
+    bool hasHDR10Support() const { return mHasHdr10; }
+    bool hasHLGSupport() const { return mHasHLG; }
+    bool hasDolbyVisionSupport() const { return mHasDolbyVision; }
 
     void swapBuffers(HWComposer& hwc) const;
 
@@ -255,6 +257,8 @@
     // Fed to RenderEngine during composition.
     bool mHasWideColorGamut;
     bool mHasHdr10;
+    bool mHasHLG;
+    bool mHasDolbyVision;
 };
 
 struct DisplayDeviceState {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 5f94bb4..0667f8d 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -448,26 +448,21 @@
     return Error::None;
 }
 
-Error Display::getHdrCapabilities(
-        std::unique_ptr<HdrCapabilities>* outCapabilities) const
+Error Display::getHdrCapabilities(HdrCapabilities* outCapabilities) const
 {
     float maxLuminance = -1.0f;
     float maxAverageLuminance = -1.0f;
     float minLuminance = -1.0f;
-    std::vector<Hwc2::Hdr> intTypes;
-    auto intError = mComposer.getHdrCapabilities(mId, &intTypes,
+    std::vector<Hwc2::Hdr> types;
+    auto intError = mComposer.getHdrCapabilities(mId, &types,
             &maxLuminance, &maxAverageLuminance, &minLuminance);
     auto error = static_cast<HWC2::Error>(intError);
 
-    std::vector<int32_t> types;
-    for (auto type : intTypes) {
-        types.push_back(static_cast<int32_t>(type));
-    }
     if (error != Error::None) {
         return error;
     }
 
-    *outCapabilities = std::make_unique<HdrCapabilities>(std::move(types),
+    *outCapabilities = HdrCapabilities(std::move(types),
             maxLuminance, maxAverageLuminance, minLuminance);
     return Error::None;
 }
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index e5779d4..aa907ea 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -228,7 +228,7 @@
     [[clang::warn_unused_result]] Error getType(DisplayType* outType) const;
     [[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const;
     [[clang::warn_unused_result]] Error getHdrCapabilities(
-            std::unique_ptr<android::HdrCapabilities>* outCapabilities) const;
+            android::HdrCapabilities* outCapabilities) const;
     [[clang::warn_unused_result]] Error getReleaseFences(
             std::unordered_map<Layer*,
                     android::sp<android::Fence>>* outFences) const;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 8db8aa6..0a3ac84 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -824,24 +824,22 @@
     mDisplayData[displayId].releaseFences.clear();
 }
 
-std::unique_ptr<HdrCapabilities> HWComposer::getHdrCapabilities(
-        int32_t displayId) {
+status_t HWComposer::getHdrCapabilities(
+        int32_t displayId, HdrCapabilities* outCapabilities) {
     if (!isValidDisplay(displayId)) {
         ALOGE("getHdrCapabilities: Display %d is not valid", displayId);
-        return nullptr;
+        return BAD_INDEX;
     }
 
     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
-    std::unique_ptr<HdrCapabilities> capabilities;
-    auto error = hwcDisplay->getHdrCapabilities(&capabilities);
+    auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
     if (error != HWC2::Error::None) {
         ALOGE("getOutputCapabilities: Failed to get capabilities on display %d:"
-                " %s (%d)", displayId, to_string(error).c_str(),
-                static_cast<int32_t>(error));
-        return nullptr;
+              " %s (%d)", displayId, to_string(error).c_str(),
+              static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
     }
-
-    return capabilities;
+    return NO_ERROR;
 }
 
 std::vector<ui::RenderIntent> HWComposer::getRenderIntents(int32_t displayId,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index e86d621..138e1f1 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -134,8 +134,8 @@
     // it can call this to clear the shared pointers in the release fence map
     void clearReleaseFences(int32_t displayId);
 
-    // Returns the HDR capabilities of the given display
-    std::unique_ptr<HdrCapabilities> getHdrCapabilities(int32_t displayId);
+    // Fetches the HDR capabilities of the given display
+    status_t getHdrCapabilities(int32_t displayId, HdrCapabilities* outCapabilities);
 
     // Returns the available RenderIntent of the given display.
     std::vector<ui::RenderIntent> getRenderIntents(int32_t displayId, ui::ColorMode colorMode) const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 57f729b..58e4fbe 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -106,6 +106,7 @@
 using namespace android::hardware::configstore::V1_0;
 using ui::ColorMode;
 using ui::Dataspace;
+using ui::Hdr;
 using ui::RenderIntent;
 
 namespace {
@@ -1118,21 +1119,23 @@
         return BAD_VALUE;
     }
 
-    std::unique_ptr<HdrCapabilities> capabilities =
-            getBE().mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId());
-    if (capabilities) {
-        if (displayDevice->hasWideColorGamut() && !displayDevice->hasHdr10()) {
+    HdrCapabilities capabilities;
+    int status = getBE().mHwc->getHdrCapabilities(
+        displayDevice->getHwcDisplayId(), &capabilities);
+    if (status == NO_ERROR) {
+        if (displayDevice->hasWideColorGamut() &&
+            !displayDevice->hasHDR10Support()) {
             // insert HDR10 as we will force client composition for HDR10
             // layers
-            std::vector<int32_t> types = capabilities->getSupportedHdrTypes();
-            types.push_back(HAL_HDR_HDR10);
+            std::vector<Hdr> types = capabilities.getSupportedHdrTypes();
+            types.push_back(Hdr::HDR10);
 
             *outCapabilities = HdrCapabilities(types,
-                    capabilities->getDesiredMaxLuminance(),
-                    capabilities->getDesiredMaxAverageLuminance(),
-                    capabilities->getDesiredMinLuminance());
+                    capabilities.getDesiredMaxLuminance(),
+                    capabilities.getDesiredMaxAverageLuminance(),
+                    capabilities.getDesiredMinLuminance());
         } else {
-            *outCapabilities = std::move(*capabilities);
+            *outCapabilities = std::move(capabilities);
         }
     } else {
         return BAD_VALUE;
@@ -1906,7 +1909,7 @@
                 // Historically, HDR dataspaces are ignored by SurfaceFlinger. But
                 // since SurfaceFlinger simulates HDR support now, it should honor
                 // them unless there is also native support.
-                if (!displayDevice->hasHdr10()) {
+                if (!displayDevice->hasHDR10Support()) {
                     return Dataspace::V0_SCRGB_LINEAR;
                 }
                 break;
@@ -2024,7 +2027,7 @@
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
                  layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
-                    !displayDevice->hasHdr10()) {
+                    !displayDevice->hasHDR10Support()) {
                 layer->forceClientComposition(hwcId);
             }
 
@@ -2277,13 +2280,8 @@
         }
     }
 
-    bool hasHdr10 = false;
-    std::unique_ptr<HdrCapabilities> hdrCapabilities = getHwComposer().getHdrCapabilities(hwcId);
-    if (hdrCapabilities) {
-        const std::vector<int32_t> types = hdrCapabilities->getSupportedHdrTypes();
-        auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10);
-        hasHdr10 = iter != types.cend();
-    }
+    HdrCapabilities hdrCapabilities;
+    getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities);
 
     auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
     auto nativeWindow = nativeWindowSurface->getNativeWindow();
@@ -2316,7 +2314,7 @@
     sp<DisplayDevice> hw =
             new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
                               dispSurface, std::move(renderSurface), displayWidth, displayHeight,
-                              hasWideColorGamut, hasHdr10, initialPowerMode);
+                              hasWideColorGamut, hdrCapabilities, initialPowerMode);
 
     if (maxFrameBufferAcquiredBuffers >= 3) {
         nativeWindowSurface->preallocateBuffers();
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 0705b5c..2551a9c 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -81,7 +81,7 @@
         sp<DisplayDevice> build() {
             return new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, false, mDisplayToken,
                                      mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0,
-                                     0, false, false, HWC_POWER_MODE_NORMAL);
+                                     0, false, {}, HWC_POWER_MODE_NORMAL);
         }
 
         FakeDisplayDeviceFactory& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {