Loading services/core/java/com/android/server/display/DisplayControl.java +9 −0 Original line number Diff line number Diff line Loading @@ -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(); /** Loading Loading @@ -127,6 +128,14 @@ public class DisplayControl { return nativeGetSupportedHdrOutputTypes(); } /** * 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 Loading services/core/java/com/android/server/display/DisplayManagerService.java +49 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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() { Loading Loading @@ -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) { Loading Loading @@ -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; } Loading Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -3044,6 +3082,10 @@ public final class DisplayManagerService extends SystemService { return DisplayControl.getSupportedHdrOutputTypes(); } int[] getHdrOutputTypesWithLatency() { return DisplayControl.getHdrOutputTypesWithLatency(); } boolean getHdrOutputConversionSupport() { return DisplayControl.getHdrOutputConversionSupport(); } Loading services/core/jni/com_android_server_display_DisplayControl.cpp +29 −2 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -167,6 +192,8 @@ static const JNINativeMethod sDisplayMethods[] = { (void*)nativeSetHdrConversionMode }, {"nativeGetSupportedHdrOutputTypes", "()[I", (void*)nativeGetSupportedHdrOutputTypes }, {"nativeGetHdrOutputTypesWithLatency", "()[I", (void*)nativeGetHdrOutputTypesWithLatency }, {"nativeGetHdrOutputConversionSupport", "()Z", (void*) nativeGetHdrOutputConversionSupport }, // clang-format on Loading services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java +43 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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 = Loading Loading
services/core/java/com/android/server/display/DisplayControl.java +9 −0 Original line number Diff line number Diff line Loading @@ -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(); /** Loading Loading @@ -127,6 +128,14 @@ public class DisplayControl { return nativeGetSupportedHdrOutputTypes(); } /** * 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 Loading
services/core/java/com/android/server/display/DisplayManagerService.java +49 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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() { Loading Loading @@ -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) { Loading Loading @@ -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; } Loading Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -3044,6 +3082,10 @@ public final class DisplayManagerService extends SystemService { return DisplayControl.getSupportedHdrOutputTypes(); } int[] getHdrOutputTypesWithLatency() { return DisplayControl.getHdrOutputTypesWithLatency(); } boolean getHdrOutputConversionSupport() { return DisplayControl.getHdrOutputConversionSupport(); } Loading
services/core/jni/com_android_server_display_DisplayControl.cpp +29 −2 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -167,6 +192,8 @@ static const JNINativeMethod sDisplayMethods[] = { (void*)nativeSetHdrConversionMode }, {"nativeGetSupportedHdrOutputTypes", "()[I", (void*)nativeGetSupportedHdrOutputTypes }, {"nativeGetHdrOutputTypesWithLatency", "()[I", (void*)nativeGetHdrOutputTypesWithLatency }, {"nativeGetHdrOutputConversionSupport", "()Z", (void*) nativeGetHdrOutputConversionSupport }, // clang-format on Loading
services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java +43 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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 = Loading