Each Display Mode now has a list of supported HDR types.
SurfaceFlinger removes Dolby Vision as a supported HDR type when a certain mode does not support it
Bug: 241349060
Test: atest ExcludeDolbyVisionTest
Change-Id: I481cc13417f65cbcb1f4658be410adb6e99c760b
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 3782c6c..800e36d 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -535,7 +535,7 @@
return static_cast<Error>(status.getServiceSpecificError());
}
- *outTypes = translate<Hdr>(capabilities.types);
+ *outTypes = capabilities.types;
*outMaxLuminance = capabilities.maxLuminance;
*outMaxAverageLuminance = capabilities.maxAverageLuminance;
*outMinLuminance = capabilities.minLuminance;
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index d84efe7..2a043fd 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -104,7 +104,7 @@
Error getDozeSupport(Display display, bool* outSupport) override;
Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) override;
- Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance,
+ Error getHdrCapabilities(Display display, std::vector<Hdr>* outHdrTypes, float* outMaxLuminance,
float* outMaxAverageLuminance, float* outMinLuminance) override;
Error getOverlaySupport(OverlayProperties* outProperties) override;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index a9bf282..ec23935 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -66,7 +66,6 @@
using types::V1_1::RenderIntent;
using types::V1_2::ColorMode;
using types::V1_2::Dataspace;
-using types::V1_2::Hdr;
using types::V1_2::PixelFormat;
using V2_1::Config;
@@ -84,6 +83,7 @@
using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey;
using PerFrameMetadataBlob = IComposerClient::PerFrameMetadataBlob;
using AidlTransform = ::aidl::android::hardware::graphics::common::Transform;
+using aidl::android::hardware::graphics::common::Hdr;
class Composer {
public:
@@ -140,7 +140,7 @@
virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
virtual Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) = 0;
- virtual Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
+ virtual Error getHdrCapabilities(Display display, std::vector<Hdr>* outHdrTypes,
float* outMaxLuminance, float* outMaxAverageLuminance,
float* outMinLuminance) = 0;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index e264570..d0126d0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -320,17 +320,17 @@
float maxLuminance = -1.0f;
float maxAverageLuminance = -1.0f;
float minLuminance = -1.0f;
- std::vector<Hwc2::Hdr> types;
- auto intError = mComposer.getHdrCapabilities(mId, &types,
- &maxLuminance, &maxAverageLuminance, &minLuminance);
+ std::vector<Hwc2::Hdr> hdrTypes;
+ auto intError = mComposer.getHdrCapabilities(mId, &hdrTypes, &maxLuminance,
+ &maxAverageLuminance, &minLuminance);
auto error = static_cast<HWC2::Error>(intError);
if (error != Error::NONE) {
return error;
}
- *outCapabilities = HdrCapabilities(std::move(types),
- maxLuminance, maxAverageLuminance, minLuminance);
+ *outCapabilities =
+ HdrCapabilities(std::move(hdrTypes), maxLuminance, maxAverageLuminance, minLuminance);
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
index 8238828..537d545 100644
--- a/services/surfaceflinger/DisplayHardware/Hal.h
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -20,6 +20,7 @@
#include <android/hardware/graphics/composer/2.4/IComposer.h>
#include <android/hardware/graphics/composer/2.4/IComposerClient.h>
+#include <aidl/android/hardware/graphics/common/Hdr.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
@@ -39,7 +40,6 @@
using types::V1_1::RenderIntent;
using types::V1_2::ColorMode;
using types::V1_2::Dataspace;
-using types::V1_2::Hdr;
using types::V1_2::PixelFormat;
using V2_1::Error;
@@ -69,6 +69,7 @@
using PowerMode = IComposerClient::PowerMode;
using Vsync = IComposerClient::Vsync;
using VsyncPeriodChangeConstraints = IComposerClient::VsyncPeriodChangeConstraints;
+using Hdr = aidl::android::hardware::graphics::common::Hdr;
} // namespace hardware::graphics::composer::hal
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index f8522e2..b607df0 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -496,13 +496,13 @@
"OptionalFeature::KernelIdleTimer is not supported on HIDL");
}
-Error HidlComposer::getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
+Error HidlComposer::getHdrCapabilities(Display display, std::vector<Hdr>* outHdrTypes,
float* outMaxLuminance, float* outMaxAverageLuminance,
float* outMinLuminance) {
Error error = kDefaultError;
if (mClient_2_3) {
mClient_2_3->getHdrCapabilities_2_3(display,
- [&](const auto& tmpError, const auto& tmpTypes,
+ [&](const auto& tmpError, const auto& tmpHdrTypes,
const auto& tmpMaxLuminance,
const auto& tmpMaxAverageLuminance,
const auto& tmpMinLuminance) {
@@ -510,15 +510,15 @@
if (error != Error::NONE) {
return;
}
+ *outHdrTypes = translate<ui::Hdr>(tmpHdrTypes);
- *outTypes = tmpTypes;
*outMaxLuminance = tmpMaxLuminance;
*outMaxAverageLuminance = tmpMaxAverageLuminance;
*outMinLuminance = tmpMinLuminance;
});
} else {
mClient->getHdrCapabilities(display,
- [&](const auto& tmpError, const auto& tmpTypes,
+ [&](const auto& tmpError, const auto& tmpHdrTypes,
const auto& tmpMaxLuminance,
const auto& tmpMaxAverageLuminance,
const auto& tmpMinLuminance) {
@@ -526,11 +526,7 @@
if (error != Error::NONE) {
return;
}
-
- outTypes->clear();
- for (auto type : tmpTypes) {
- outTypes->push_back(static_cast<Hdr>(type));
- }
+ *outHdrTypes = translate<ui::Hdr>(tmpHdrTypes);
*outMaxLuminance = tmpMaxLuminance;
*outMaxAverageLuminance = tmpMaxAverageLuminance;
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 48b720c..3602bbb 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -56,7 +56,6 @@
using types::V1_1::RenderIntent;
using types::V1_2::ColorMode;
using types::V1_2::Dataspace;
-using types::V1_2::Hdr;
using types::V1_2::PixelFormat;
using V2_1::Config;
@@ -209,7 +208,7 @@
Error getDozeSupport(Display display, bool* outSupport) override;
Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) override;
- Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance,
+ Error getHdrCapabilities(Display display, std::vector<Hdr>* outHdrTypes, float* outMaxLuminance,
float* outMaxAverageLuminance, float* outMinLuminance) override;
Error getOverlaySupport(aidl::android::hardware::graphics::composer3::OverlayProperties*
outProperties) override;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9af8ca9..bd3c0f1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -198,6 +198,9 @@
namespace {
+static constexpr int FOUR_K_WIDTH = 3840;
+static constexpr int FOUR_K_HEIGHT = 2160;
+
// TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity.
constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;
@@ -245,6 +248,44 @@
return displaySupportKernelIdleTimer || sysprop::support_kernel_idle_timer(false);
}
+bool isAbove4k30(const ui::DisplayMode& outMode) {
+ using fps_approx_ops::operator>;
+ Fps refreshRate = Fps::fromValue(outMode.refreshRate);
+ return outMode.resolution.getWidth() >= FOUR_K_WIDTH &&
+ outMode.resolution.getHeight() >= FOUR_K_HEIGHT && refreshRate > 30_Hz;
+}
+
+void excludeDolbyVisionIf4k30Present(const std::vector<ui::Hdr>& displayHdrTypes,
+ ui::DisplayMode& outMode) {
+ if (isAbove4k30(outMode) &&
+ std::any_of(displayHdrTypes.begin(), displayHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::DOLBY_VISION_4K30; })) {
+ for (ui::Hdr type : displayHdrTypes) {
+ if (type != ui::Hdr::DOLBY_VISION_4K30 && type != ui::Hdr::DOLBY_VISION) {
+ outMode.supportedHdrTypes.push_back(type);
+ }
+ }
+ } else {
+ for (ui::Hdr type : displayHdrTypes) {
+ if (type != ui::Hdr::DOLBY_VISION_4K30) {
+ outMode.supportedHdrTypes.push_back(type);
+ }
+ }
+ }
+}
+
+HdrCapabilities filterOut4k30(const HdrCapabilities& displayHdrCapabilities) {
+ std::vector<ui::Hdr> hdrTypes;
+ for (ui::Hdr type : displayHdrCapabilities.getSupportedHdrTypes()) {
+ if (type != ui::Hdr::DOLBY_VISION_4K30) {
+ hdrTypes.push_back(type);
+ }
+ }
+ return {hdrTypes, displayHdrCapabilities.getDesiredMaxLuminance(),
+ displayHdrCapabilities.getDesiredMaxAverageLuminance(),
+ displayHdrCapabilities.getDesiredMinLuminance()};
+}
+
} // namespace anonymous
// ---------------------------------------------------------------------------
@@ -1033,7 +1074,8 @@
// We add an additional 1ms to allow for processing time and
// differences between the ideal and actual refresh rate.
outMode.presentationDeadline = period - outMode.sfVsyncOffset + 1000000;
-
+ excludeDolbyVisionIf4k30Present(display->getHdrCapabilities().getSupportedHdrTypes(),
+ outMode);
info->supportedDisplayModes.push_back(outMode);
}
@@ -1044,7 +1086,7 @@
info->activeDisplayModeId =
display->refreshRateSelector().getActiveMode().modePtr->getId().value();
info->activeColorMode = display->getCompositionDisplay()->getState().colorMode;
- info->hdrCapabilities = display->getHdrCapabilities();
+ info->hdrCapabilities = filterOut4k30(display->getHdrCapabilities());
info->autoLowLatencyModeSupported =
getHwComposer().hasDisplayCapability(displayId,
@@ -7355,6 +7397,10 @@
outMode.sfVsyncOffset = mode.sfVsyncOffset;
outMode.presentationDeadline = mode.presentationDeadline;
outMode.group = mode.group;
+ std::transform(mode.supportedHdrTypes.begin(), mode.supportedHdrTypes.end(),
+ std::back_inserter(outMode.supportedHdrTypes),
+ [](const ui::Hdr& value) { return static_cast<int32_t>(value); });
+
outInfo->supportedDisplayModes.push_back(outMode);
}
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index dbfce78..c0a6bdb 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -81,7 +81,6 @@
using types::V1_1::RenderIntent;
using types::V1_2::ColorMode;
using types::V1_2::Dataspace;
-using types::V1_2::Hdr;
using types::V1_2::PixelFormat;
using V2_1::Config;
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 0114577..8b0cd78 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -111,6 +111,7 @@
"SurfaceFlinger_SetPowerModeInternalTest.cpp",
"SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp",
"SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp",
+ "SurfaceFlinger_ExcludeDolbyVisionTest.cpp",
"SchedulerTest.cpp",
"SetFrameRateTest.cpp",
"RefreshRateSelectorTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_ExcludeDolbyVisionTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_ExcludeDolbyVisionTest.cpp
new file mode 100644
index 0000000..11e734a
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_ExcludeDolbyVisionTest.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include "DisplayTransactionTestHelpers.h"
+
+namespace android {
+namespace {
+
+using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
+
+class ExcludeDolbyVisionTest : public DisplayTransactionTest {
+public:
+ void injectDisplayModes(std::vector<DisplayModePtr> displayModePtrs) {
+ DisplayModes modes;
+ for (DisplayModePtr displayMode : displayModePtrs) {
+ modes.try_emplace(displayMode->getId(), displayMode);
+ }
+
+ mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
+ .setDisplayModes(std::move(modes), displayModePtrs[0]->getId())
+ .inject();
+ mDisplay->overrideHdrTypes(types);
+ }
+
+protected:
+ sp<DisplayDevice> mDisplay;
+
+ static constexpr DisplayModeId modeId1080p60{0};
+ static constexpr DisplayModeId modeId4k30{1};
+ static constexpr DisplayModeId modeId4k60{2};
+
+ static inline const DisplayModePtr mode1080p60 =
+ createDisplayMode(modeId1080p60, 60_Hz, 0, ui::Size(1920, 1080));
+ static inline const DisplayModePtr mode4k30 =
+ createDisplayMode(modeId4k30, 30_Hz, 1, ui::Size(3840, 2160));
+ static inline const DisplayModePtr mode4k30NonStandard =
+ createDisplayMode(modeId4k30, 30.1_Hz, 1, ui::Size(3840, 2160));
+ static inline const DisplayModePtr mode4k60 =
+ createDisplayMode(modeId4k60, 60_Hz, 2, ui::Size(3840, 2160));
+
+ const std::vector<ui::Hdr> types = {ui::Hdr::DOLBY_VISION, ui::Hdr::DOLBY_VISION_4K30,
+ ui::Hdr::HDR10_PLUS};
+};
+
+TEST_F(ExcludeDolbyVisionTest, excludesDolbyVisionOnModesHigherThan4k30) {
+ injectDisplayModes({mode4k60});
+ ui::DynamicDisplayInfo info;
+ mFlinger.getDynamicDisplayInfo(mDisplay->getDisplayToken().promote(), &info);
+
+ std::vector<ui::DisplayMode> displayModes = info.supportedDisplayModes;
+
+ ASSERT_EQ(1, displayModes.size());
+ ASSERT_TRUE(std::any_of(displayModes[0].supportedHdrTypes.begin(),
+ displayModes[0].supportedHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::HDR10_PLUS; }));
+ ASSERT_TRUE(displayModes[0].supportedHdrTypes.size() == 1);
+}
+
+TEST_F(ExcludeDolbyVisionTest, includesDolbyVisionOnModesLowerThanOrEqualTo4k30) {
+ injectDisplayModes({mode1080p60, mode4k30, mode4k30NonStandard});
+ ui::DynamicDisplayInfo info;
+ mFlinger.getDynamicDisplayInfo(mDisplay->getDisplayToken().promote(), &info);
+
+ std::vector<ui::DisplayMode> displayModes = info.supportedDisplayModes;
+
+ ASSERT_EQ(2, displayModes.size());
+ for (size_t i = 0; i < displayModes.size(); i++) {
+ ASSERT_TRUE(std::any_of(displayModes[i].supportedHdrTypes.begin(),
+ displayModes[i].supportedHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::HDR10_PLUS; }));
+ ASSERT_TRUE(std::any_of(displayModes[i].supportedHdrTypes.begin(),
+ displayModes[i].supportedHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::DOLBY_VISION; }));
+ ASSERT_TRUE(displayModes[i].supportedHdrTypes.size() == 2);
+ }
+}
+
+TEST_F(ExcludeDolbyVisionTest, 4k30IsNotReportedAsAValidHdrType) {
+ injectDisplayModes({mode4k60});
+ ui::DynamicDisplayInfo info;
+ mFlinger.getDynamicDisplayInfo(mDisplay->getDisplayToken().promote(), &info);
+
+ std::vector<ui::Hdr> displayHdrTypes = info.hdrCapabilities.getSupportedHdrTypes();
+
+ ASSERT_EQ(2, displayHdrTypes.size());
+ ASSERT_TRUE(std::any_of(displayHdrTypes.begin(), displayHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::HDR10_PLUS; }));
+ ASSERT_TRUE(std::any_of(displayHdrTypes.begin(), displayHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::DOLBY_VISION; }));
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index e29dd67..c8362ee 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -30,6 +30,7 @@
#include <ftl/fake_guard.h>
#include <gui/ScreenCaptureResults.h>
+#include <ui/DynamicDisplayInfo.h>
#include "DisplayDevice.h"
#include "FakeVsyncConfiguration.h"
#include "FrameTracer/FrameTracer.h"
@@ -486,6 +487,11 @@
void updateLayerMetadataSnapshot() { mFlinger->updateLayerMetadataSnapshot(); }
+ void getDynamicDisplayInfo(const sp<IBinder>& displayToken,
+ ui::DynamicDisplayInfo* dynamicDisplayInfo) {
+ mFlinger->getDynamicDisplayInfo(displayToken, dynamicDisplayInfo);
+ }
+
/* ------------------------------------------------------------------------
* Read-only access to private data to assert post-conditions.
*/
@@ -643,7 +649,6 @@
// is much longer lived.
auto display = std::make_unique<HWC2Display>(*composer, *mCapabilities, mHwcDisplayId,
mHwcDisplayType);
-
display->mutableIsConnected() = true;
display->setPowerMode(mPowerMode);
flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = std::move(display);
@@ -652,7 +657,6 @@
.WillRepeatedly(
DoAll(SetArgPointee<1>(std::vector<hal::HWConfigId>{mActiveConfig}),
Return(hal::Error::NONE)));
-
EXPECT_CALL(*composer,
getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::WIDTH, _))
.WillRepeatedly(DoAll(SetArgPointee<3>(mResolution.getWidth()),
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 5ee38ec..836e3a4 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -32,7 +32,6 @@
using android::hardware::graphics::common::V1_1::RenderIntent;
using android::hardware::graphics::common::V1_2::ColorMode;
using android::hardware::graphics::common::V1_2::Dataspace;
-using android::hardware::graphics::common::V1_2::Hdr;
using android::hardware::graphics::common::V1_2::PixelFormat;
using android::hardware::graphics::composer::V2_1::Config;