Hdr format settings [Backend]
Added new API to SurfaceControl to override the HDR formats supported by
device in SurfaceFlinger. This API is used in the CTS Tests to verify
HDR capabilities and enabling/disabling of HDR formats.
Bug: 172905874
Test: atest CtsDisplayTestCases
Change-Id: Icb13cdd638d315c0e23ece8aa61242470404a428
Merged-In: Icb13cdd638d315c0e23ece8aa61242470404a428
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index ceab6ec..97f8f47 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -477,6 +477,26 @@
return reply.readInt32();
}
+ virtual status_t overrideHdrTypes(const sp<IBinder>& display,
+ const std::vector<ui::Hdr>& hdrTypes) {
+ Parcel data, reply;
+ SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
+ SAFE_PARCEL(data.writeStrongBinder, display);
+
+ std::vector<int32_t> hdrTypesVector;
+ for (ui::Hdr i : hdrTypes) {
+ hdrTypesVector.push_back(static_cast<int32_t>(i));
+ }
+ SAFE_PARCEL(data.writeInt32Vector, hdrTypesVector);
+
+ status_t result = remote()->transact(BnSurfaceComposer::OVERRIDE_HDR_TYPES, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("overrideHdrTypes failed to transact: %d", result);
+ return result;
+ }
+ return result;
+ }
+
status_t enableVSyncInjections(bool enable) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -1963,6 +1983,20 @@
SAFE_PARCEL(reply->writeInt32, extraBuffers);
return NO_ERROR;
}
+ case OVERRIDE_HDR_TYPES: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> display = nullptr;
+ SAFE_PARCEL(data.readStrongBinder, &display);
+
+ std::vector<int32_t> hdrTypes;
+ SAFE_PARCEL(data.readInt32Vector, &hdrTypes);
+
+ std::vector<ui::Hdr> hdrTypesVector;
+ for (int i : hdrTypes) {
+ hdrTypesVector.push_back(static_cast<ui::Hdr>(i));
+ }
+ return overrideHdrTypes(display, hdrTypesVector);
+ }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index d7b2c2e..0b01084 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1985,6 +1985,11 @@
return ComposerService::getComposerService()->getAnimationFrameStats(outStats);
}
+status_t SurfaceComposerClient::overrideHdrTypes(const sp<IBinder>& display,
+ const std::vector<ui::Hdr>& hdrTypes) {
+ return ComposerService::getComposerService()->overrideHdrTypes(display, hdrTypes);
+}
+
status_t SurfaceComposerClient::getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 35990d1..9f9ca74 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -267,6 +267,13 @@
*/
virtual status_t getAnimationFrameStats(FrameStats* outStats) const = 0;
+ /* Overrides the supported HDR modes for the given display device.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ virtual status_t overrideHdrTypes(const sp<IBinder>& display,
+ const std::vector<ui::Hdr>& hdrTypes) = 0;
+
virtual status_t enableVSyncInjections(bool enable) = 0;
virtual status_t injectVSync(nsecs_t when) = 0;
@@ -570,6 +577,7 @@
GET_DYNAMIC_DISPLAY_INFO,
ADD_FPS_LISTENER,
REMOVE_FPS_LISTENER,
+ OVERRIDE_HDR_TYPES,
// Always append new enum to the end.
};
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index a643e9e..c38375c 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -572,6 +572,9 @@
static status_t clearAnimationFrameStats();
static status_t getAnimationFrameStats(FrameStats* outStats);
+ static status_t overrideHdrTypes(const sp<IBinder>& display,
+ const std::vector<ui::Hdr>& hdrTypes);
+
static void setDisplayProjection(const sp<IBinder>& token, ui::Rotation orientation,
const Rect& layerStackRect, const Rect& displayRect);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 8d7f8c9..5ac3f19 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -772,6 +772,10 @@
status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override {
return NO_ERROR;
}
+ status_t overrideHdrTypes(const sp<IBinder>& /*display*/,
+ const std::vector<ui::Hdr>& /*hdrTypes*/) override {
+ return NO_ERROR;
+ }
status_t enableVSyncInjections(bool /*enable*/) override {
return NO_ERROR;
}
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index f4a2a3f..b7b2cc6 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -354,8 +354,20 @@
return mCompositionDisplay->getDisplayColorProfile()->getSupportedPerFrameMetadata();
}
-const HdrCapabilities& DisplayDevice::getHdrCapabilities() const {
- return mCompositionDisplay->getDisplayColorProfile()->getHdrCapabilities();
+void DisplayDevice::overrideHdrTypes(const std::vector<ui::Hdr>& hdrTypes) {
+ mOverrideHdrTypes = hdrTypes;
+}
+
+HdrCapabilities DisplayDevice::getHdrCapabilities() const {
+ const HdrCapabilities& capabilities =
+ mCompositionDisplay->getDisplayColorProfile()->getHdrCapabilities();
+ std::vector<ui::Hdr> hdrTypes = capabilities.getSupportedHdrTypes();
+ if (!mOverrideHdrTypes.empty()) {
+ hdrTypes = mOverrideHdrTypes;
+ }
+ return HdrCapabilities(hdrTypes, capabilities.getDesiredMaxLuminance(),
+ capabilities.getDesiredMaxAverageLuminance(),
+ capabilities.getDesiredMinLuminance());
}
std::atomic<int32_t> DisplayDeviceState::sNextSequenceId(1);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 7156613..68846d3 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -126,13 +126,15 @@
bool hasHLGSupport() const;
bool hasDolbyVisionSupport() const;
+ void overrideHdrTypes(const std::vector<ui::Hdr>& hdrTypes);
+
// The returned HdrCapabilities is the combination of HDR capabilities from
// hardware composer and RenderEngine. When the DisplayDevice supports wide
// color gamut, RenderEngine is able to simulate HDR support in Display P3
// color space for both PQ and HLG HDR contents. The minimum and maximum
// luminance will be set to sDefaultMinLumiance and sDefaultMaxLumiance
// respectively if hardware composer doesn't return meaningful values.
- const HdrCapabilities& getHdrCapabilities() const;
+ HdrCapabilities getHdrCapabilities() const;
// Return true if intent is supported by the display.
bool hasRenderIntent(ui::RenderIntent intent) const;
@@ -217,6 +219,8 @@
const bool mIsPrimary;
std::optional<DeviceProductInfo> mDeviceProductInfo;
+
+ std::vector<ui::Hdr> mOverrideHdrTypes;
};
struct DisplayDeviceState {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 31097aa..f9636ca 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1287,6 +1287,21 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::overrideHdrTypes(const sp<IBinder>& displayToken,
+ const std::vector<ui::Hdr>& hdrTypes) {
+ Mutex::Autolock lock(mStateLock);
+
+ auto display = getDisplayDeviceLocked(displayToken);
+ if (!display) {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ return NAME_NOT_FOUND;
+ }
+
+ display->overrideHdrTypes(hdrTypes);
+ dispatchDisplayHotplugEvent(display->getPhysicalId(), true /* connected */);
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::getDisplayedContentSamplingAttributes(const sp<IBinder>& displayToken,
ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
@@ -5013,6 +5028,7 @@
case DESTROY_DISPLAY:
case ENABLE_VSYNC_INJECTIONS:
case GET_ANIMATION_FRAME_STATS:
+ case OVERRIDE_HDR_TYPES:
case GET_HDR_CAPABILITIES:
case SET_DESIRED_DISPLAY_MODE_SPECS:
case GET_DESIRED_DISPLAY_MODE_SPECS:
@@ -5029,9 +5045,11 @@
case NOTIFY_POWER_BOOST:
case SET_GLOBAL_SHADOW_SETTINGS:
case ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN: {
- // ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN is used by CTS tests, which acquire the
- // necessary permission dynamically. Don't use the permission cache for this check.
- bool usePermissionCache = code != ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN;
+ // ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN and OVERRIDE_HDR_TYPES are used by CTS tests,
+ // which acquire the necessary permission dynamically. Don't use the permission cache
+ // for this check.
+ bool usePermissionCache =
+ code != ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN && code != OVERRIDE_HDR_TYPES;
if (!callingThreadHasUnscopedSurfaceFlingerAccess(usePermissionCache)) {
IPCThreadState* ipc = IPCThreadState::self();
ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d",
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8d2f66d..e4ff6c9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -642,6 +642,8 @@
void setPowerMode(const sp<IBinder>& displayToken, int mode) override;
status_t clearAnimationFrameStats() override;
status_t getAnimationFrameStats(FrameStats* outStats) const override;
+ status_t overrideHdrTypes(const sp<IBinder>& displayToken,
+ const std::vector<ui::Hdr>& hdrTypes) override;
status_t enableVSyncInjections(bool enable) override;
status_t injectVSync(nsecs_t when) override;
status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) override;