Merge "Handle interaction between minimal post processing and HDR output control" into udc-dev am: 79e56488de
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22224783
Change-Id: I5840f87e9c0ed256fcd5c6c22289cac2fb122fe0
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/services/core/java/com/android/server/display/DisplayControl.java b/services/core/java/com/android/server/display/DisplayControl.java
index b30c05c..22f3bbd 100644
--- a/services/core/java/com/android/server/display/DisplayControl.java
+++ b/services/core/java/com/android/server/display/DisplayControl.java
@@ -37,6 +37,7 @@
private static native int nativeSetHdrConversionMode(int conversionMode,
int preferredHdrOutputType, int[] autoHdrTypes, int autoHdrTypesLength);
private static native int[] nativeGetSupportedHdrOutputTypes();
+ private static native int[] nativeGetHdrOutputTypesWithLatency();
private static native boolean nativeGetHdrOutputConversionSupport();
/**
@@ -128,6 +129,14 @@
}
/**
+ * Returns the HDR output types which introduces latency on conversion to them.
+ * @hide
+ */
+ public static @Display.HdrCapabilities.HdrType int[] getHdrOutputTypesWithLatency() {
+ return nativeGetHdrOutputTypesWithLatency();
+ }
+
+ /**
* Returns whether the HDR output conversion is supported by the device.
* @hide
*/
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 34ad91c4..3844529 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -141,6 +141,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
@@ -737,6 +738,20 @@
return mDisplayDeviceRepo;
}
+ @VisibleForTesting
+ boolean isMinimalPostProcessingAllowed() {
+ synchronized (mSyncRoot) {
+ return mMinimalPostProcessingAllowed;
+ }
+ }
+
+ @VisibleForTesting
+ void setMinimalPostProcessingAllowed(boolean allowed) {
+ synchronized (mSyncRoot) {
+ mMinimalPostProcessingAllowed = allowed;
+ }
+ }
+
private void loadStableDisplayValuesLocked() {
final Point size = mPersistentDataStore.getStableDisplaySize();
if (size.x > 0 && size.y > 0) {
@@ -937,8 +952,9 @@
}
private void updateSettingsLocked() {
- mMinimalPostProcessingAllowed = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED, 1, UserHandle.USER_CURRENT) != 0;
+ setMinimalPostProcessingAllowed(Settings.Secure.getIntForUser(
+ mContext.getContentResolver(), Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED,
+ 1, UserHandle.USER_CURRENT) != 0);
}
private void updateUserDisabledHdrTypesFromSettingsLocked() {
@@ -2166,6 +2182,17 @@
return autoHdrOutputTypesArray.toArray();
}
+ @GuardedBy("mSyncRoot")
+ private boolean hdrConversionIntroducesLatencyLocked() {
+ final int preferredHdrOutputType =
+ getHdrConversionModeSettingInternal().getPreferredHdrOutputType();
+ if (preferredHdrOutputType != Display.HdrCapabilities.HDR_TYPE_INVALID) {
+ int[] hdrTypesWithLatency = mInjector.getHdrOutputTypesWithLatency();
+ return ArrayUtils.contains(hdrTypesWithLatency, preferredHdrOutputType);
+ }
+ return false;
+ }
+
Display.Mode getUserPreferredDisplayModeInternal(int displayId) {
synchronized (mSyncRoot) {
if (displayId == Display.INVALID_DISPLAY) {
@@ -2243,7 +2270,7 @@
return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM);
}
- private HdrConversionMode getHdrConversionModeInternal() {
+ HdrConversionMode getHdrConversionModeInternal() {
if (!mInjector.getHdrOutputConversionSupport()) {
return HDR_CONVERSION_MODE_UNSUPPORTED;
}
@@ -2400,7 +2427,7 @@
}
}
- private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
+ void setDisplayPropertiesInternal(int displayId, boolean hasContent,
float requestedRefreshRate, int requestedModeId, float requestedMinRefreshRate,
float requestedMaxRefreshRate, boolean preferMinimalPostProcessing,
boolean disableHdrConversion, boolean inTraversal) {
@@ -2438,11 +2465,17 @@
// TODO(b/202378408) set minimal post-processing only if it's supported once we have a
// separate API for disabling on-device processing.
- boolean mppRequest = mMinimalPostProcessingAllowed && preferMinimalPostProcessing;
+ boolean mppRequest = isMinimalPostProcessingAllowed() && preferMinimalPostProcessing;
+ boolean disableHdrConversionForLatency = false;
if (display.getRequestedMinimalPostProcessingLocked() != mppRequest) {
display.setRequestedMinimalPostProcessingLocked(mppRequest);
shouldScheduleTraversal = true;
+ // If HDR conversion introduces latency, disable that in case minimal
+ // post-processing is requested
+ if (mppRequest) {
+ disableHdrConversionForLatency = hdrConversionIntroducesLatencyLocked();
+ }
}
if (shouldScheduleTraversal) {
@@ -2452,12 +2485,17 @@
if (mHdrConversionMode == null) {
return;
}
- if (mOverrideHdrConversionMode == null && disableHdrConversion) {
+ // HDR conversion is disabled in two cases:
+ // - HDR conversion introduces latency and minimal post-processing is requested
+ // - app requests to disable HDR conversion
+ if (mOverrideHdrConversionMode == null && (disableHdrConversion
+ || disableHdrConversionForLatency)) {
mOverrideHdrConversionMode =
new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH);
setHdrConversionModeInternal(mHdrConversionMode);
handleLogicalDisplayChangedLocked(display);
- } else if (mOverrideHdrConversionMode != null && !disableHdrConversion) {
+ } else if (mOverrideHdrConversionMode != null && !disableHdrConversion
+ && !disableHdrConversionForLatency) {
mOverrideHdrConversionMode = null;
setHdrConversionModeInternal(mHdrConversionMode);
handleLogicalDisplayChangedLocked(display);
@@ -3044,6 +3082,10 @@
return DisplayControl.getSupportedHdrOutputTypes();
}
+ int[] getHdrOutputTypesWithLatency() {
+ return DisplayControl.getHdrOutputTypesWithLatency();
+ }
+
boolean getHdrOutputConversionSupport() {
return DisplayControl.getHdrOutputConversionSupport();
}
diff --git a/services/core/jni/com_android_server_display_DisplayControl.cpp b/services/core/jni/com_android_server_display_DisplayControl.cpp
index 5f95c28..e65b903 100644
--- a/services/core/jni/com_android_server_display_DisplayControl.cpp
+++ b/services/core/jni/com_android_server_display_DisplayControl.cpp
@@ -110,7 +110,32 @@
return nullptr;
}
jint* arrayValues = env->GetIntArrayElements(array, 0);
- int index = 0;
+ size_t index = 0;
+ for (auto hdrOutputType : hdrOutputTypes) {
+ arrayValues[index++] = static_cast<jint>(hdrOutputType);
+ }
+ env->ReleaseIntArrayElements(array, arrayValues, 0);
+ return array;
+}
+
+static jintArray nativeGetHdrOutputTypesWithLatency(JNIEnv* env, jclass clazz) {
+ std::vector<gui::HdrConversionCapability> hdrConversionCapabilities;
+ SurfaceComposerClient::getHdrConversionCapabilities(&hdrConversionCapabilities);
+
+ // Extract unique HDR output types with latency.
+ std::set<int> hdrOutputTypes;
+ for (const auto& hdrConversionCapability : hdrConversionCapabilities) {
+ if (hdrConversionCapability.outputType > 0 && hdrConversionCapability.addsLatency) {
+ hdrOutputTypes.insert(hdrConversionCapability.outputType);
+ }
+ }
+ jintArray array = env->NewIntArray(hdrOutputTypes.size());
+ if (array == nullptr) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", nullptr);
+ return nullptr;
+ }
+ jint* arrayValues = env->GetIntArrayElements(array, 0);
+ size_t index = 0;
for (auto hdrOutputType : hdrOutputTypes) {
arrayValues[index++] = static_cast<jint>(hdrOutputType);
}
@@ -167,7 +192,9 @@
(void*)nativeSetHdrConversionMode },
{"nativeGetSupportedHdrOutputTypes", "()[I",
(void*)nativeGetSupportedHdrOutputTypes },
- {"nativeGetHdrOutputConversionSupport", "()Z",
+ {"nativeGetHdrOutputTypesWithLatency", "()[I",
+ (void*)nativeGetHdrOutputTypesWithLatency },
+ {"nativeGetHdrOutputConversionSupport", "()Z",
(void*) nativeGetHdrOutputConversionSupport },
// clang-format on
};
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 5438750..a6c5737 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -220,6 +220,11 @@
return new int[]{};
}
+ @Override
+ int[] getHdrOutputTypesWithLatency() {
+ return new int[]{Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION};
+ }
+
boolean getHdrOutputConversionSupport() {
return true;
}
@@ -1862,6 +1867,44 @@
assertEquals(mode.getPreferredHdrOutputType(), mPreferredHdrOutputType);
}
+ @Test
+ public void testHdrConversionMode_withMinimalPostProcessing() {
+ DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+ registerDefaultDisplays(displayManager);
+ displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
+ FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
+ new float[]{60f, 30f, 20f});
+ int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
+ displayDevice);
+
+ final HdrConversionMode mode = new HdrConversionMode(
+ HdrConversionMode.HDR_CONVERSION_FORCE,
+ Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION);
+ displayManager.setHdrConversionModeInternal(mode);
+ assertEquals(mode, displayManager.getHdrConversionModeSettingInternal());
+
+ displayManager.setMinimalPostProcessingAllowed(true);
+ displayManager.setDisplayPropertiesInternal(displayId, false /* hasContent */,
+ 30.0f /* requestedRefreshRate */,
+ displayDevice.getDisplayDeviceInfoLocked().modeId /* requestedModeId */,
+ 30.0f /* requestedMinRefreshRate */, 120.0f /* requestedMaxRefreshRate */,
+ true /* preferMinimalPostProcessing */, false /* disableHdrConversion */,
+ true /* inTraversal */);
+
+ assertEquals(new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH),
+ displayManager.getHdrConversionModeInternal());
+
+ displayManager.setDisplayPropertiesInternal(displayId, false /* hasContent */,
+ 30.0f /* requestedRefreshRate */,
+ displayDevice.getDisplayDeviceInfoLocked().modeId /* requestedModeId */,
+ 30.0f /* requestedMinRefreshRate */, 120.0f /* requestedMaxRefreshRate */,
+ false /* preferMinimalPostProcessing */, false /* disableHdrConversion */,
+ true /* inTraversal */);
+ assertEquals(mode, displayManager.getHdrConversionModeInternal());
+ }
+
private void testDisplayInfoFrameRateOverrideModeCompat(boolean compatChangeEnabled)
throws Exception {
DisplayManagerService displayManager =