diff options
| author | 2023-05-17 16:45:44 +0000 | |
|---|---|---|
| committer | 2023-05-17 16:45:44 +0000 | |
| commit | 79e56488dea7dde88c913a341e55a5fbec0ee423 (patch) | |
| tree | 0a8c1cf76fd5852d0a655077abf33fd9c7690d5a | |
| parent | 4adfb70d9a3c46fab02781a330fcb115826f2819 (diff) | |
| parent | dd39ff9d91977577f222ee9706492f6c1f803a3c (diff) | |
Merge "Handle interaction between minimal post processing and HDR output control" into udc-dev
4 files changed, 130 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/display/DisplayControl.java b/services/core/java/com/android/server/display/DisplayControl.java index b30c05cfda31..22f3bbd80a77 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 @@ public class DisplayControl { 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 @@ public class DisplayControl { } /** + * 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 34ad91c4c808..38445295b0f1 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.GuardedBy; 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 @@ public final class DisplayManagerService extends SystemService { 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 @@ public final class DisplayManagerService extends SystemService { } 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 @@ public final class DisplayManagerService extends SystemService { 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 @@ public final class DisplayManagerService extends SystemService { return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM); } - private HdrConversionMode getHdrConversionModeInternal() { + HdrConversionMode getHdrConversionModeInternal() { if (!mInjector.getHdrOutputConversionSupport()) { return HDR_CONVERSION_MODE_UNSUPPORTED; } @@ -2400,7 +2427,7 @@ public final class DisplayManagerService extends SystemService { } } - 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 @@ public final class DisplayManagerService extends SystemService { // 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 @@ public final class DisplayManagerService extends SystemService { 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 @@ public final class DisplayManagerService extends SystemService { 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 5f95c28e6d09..e65b9030195a 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 @@ static jintArray nativeGetSupportedHdrOutputTypes(JNIEnv* env, jclass clazz) { 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 @@ static const JNINativeMethod sDisplayMethods[] = { (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 54387507f4c2..a6c57371803b 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 @@ public class DisplayManagerServiceTest { return new int[]{}; } + @Override + int[] getHdrOutputTypesWithLatency() { + return new int[]{Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION}; + } + boolean getHdrOutputConversionSupport() { return true; } @@ -1862,6 +1867,44 @@ public class DisplayManagerServiceTest { 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 = |