diff options
7 files changed, 142 insertions, 57 deletions
diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java index 21273e0f2785..13ee47eb91c8 100644 --- a/services/core/java/com/android/server/display/BrightnessRangeController.java +++ b/services/core/java/com/android/server/display/BrightnessRangeController.java @@ -19,6 +19,7 @@ package com.android.server.display; import android.hardware.display.BrightnessInfo; import android.os.Handler; import android.os.IBinder; +import android.os.PowerManager; import com.android.server.display.brightness.clamper.HdrClamper; import com.android.server.display.feature.DisplayManagerFlags; @@ -52,17 +53,26 @@ class BrightnessRangeController { HdrClamper hdrClamper, DisplayManagerFlags flags) { mHbmController = hbmController; mModeChangeCallback = modeChangeCallback; - mUseHdrClamper = false; - mUseNbmController = flags.isNbmControllerEnabled(); - mNormalBrightnessModeController.resetNbmData(displayDeviceConfig.getLuxThrottlingData()); mHdrClamper = hdrClamper; + mUseHdrClamper = flags.isHdrClamperEnabled(); + mUseNbmController = flags.isNbmControllerEnabled(); + if (mUseNbmController) { + mNormalBrightnessModeController.resetNbmData( + displayDeviceConfig.getLuxThrottlingData()); + } + if (mUseHdrClamper) { + mHdrClamper.resetHdrConfig(displayDeviceConfig.getHdrBrightnessData()); + } + } void dump(PrintWriter pw) { pw.println("BrightnessRangeController:"); pw.println(" mUseNormalBrightnessController=" + mUseNbmController); + pw.println(" mUseHdrClamper=" + mUseHdrClamper); mHbmController.dump(pw); mNormalBrightnessModeController.dump(pw); + mHdrClamper.dump(pw); } void onAmbientLuxChange(float ambientLux) { @@ -91,6 +101,9 @@ class BrightnessRangeController { displayDeviceConfig::getHdrBrightnessFromSdr); } ); + if (mUseHdrClamper) { + mHdrClamper.resetHdrConfig(displayDeviceConfig.getHdrBrightnessData()); + } } void stop() { @@ -128,8 +141,10 @@ class BrightnessRangeController { } float getHdrBrightnessValue() { - float hdrBrightness = mHbmController.getHdrBrightnessValue(); - return Math.min(hdrBrightness, mHdrClamper.getMaxBrightness()); + float hdrBrightness = mHbmController.getHdrBrightnessValue(); + float brightnessMax = mUseHdrClamper ? mHdrClamper.getMaxBrightness() + : PowerManager.BRIGHTNESS_MAX; + return Math.min(hdrBrightness, brightnessMax); } float getTransitionPoint() { @@ -151,6 +166,6 @@ class BrightnessRangeController { } public float getHdrTransitionRate() { - return mHdrClamper.getTransitionRate(); + return mUseHdrClamper ? mHdrClamper.getTransitionRate() : -1; } } diff --git a/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java b/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java index 079a196234a8..a514136e62a2 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java +++ b/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java @@ -16,40 +16,41 @@ package com.android.server.display.brightness.clamper; +import android.annotation.Nullable; import android.os.Handler; import android.os.PowerManager; -import com.android.internal.annotations.VisibleForTesting; +import com.android.server.display.config.HdrBrightnessData; -import java.util.HashMap; +import java.io.PrintWriter; import java.util.Map; public class HdrClamper { - private final Configuration mConfiguration = new Configuration(); - private final BrightnessClamperController.ClamperChangeListener mClamperChangeListener; private final Handler mHandler; private final Runnable mDebouncer; - private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX; + @Nullable + private HdrBrightnessData mHdrBrightnessData = null; - // brightness change speed, in units per seconds, - private float mTransitionRate = -1f; + private float mAmbientLux = Float.MAX_VALUE; + private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX; private float mDesiredMaxBrightness = PowerManager.BRIGHTNESS_MAX; - private float mDesiredTransitionDuration = -1; // in seconds + // brightness change speed, in units per seconds, + private float mTransitionRate = -1f; + private float mDesiredTransitionRate = -1f; public HdrClamper(BrightnessClamperController.ClamperChangeListener clamperChangeListener, Handler handler) { mClamperChangeListener = clamperChangeListener; mHandler = handler; mDebouncer = () -> { - mTransitionRate = Math.abs((mMaxBrightness - mDesiredMaxBrightness) - / mDesiredTransitionDuration); + mTransitionRate = mDesiredTransitionRate; mMaxBrightness = mDesiredMaxBrightness; mClamperChangeListener.onChanged(); }; @@ -65,46 +66,74 @@ public class HdrClamper { return mTransitionRate; } - /** * Updates brightness cap in response to ambient lux change. * Called by ABC in same looper: mHandler.getLooper() */ public void onAmbientLuxChange(float ambientLux) { - float expectedMaxBrightness = findBrightnessLimit(ambientLux); + mAmbientLux = ambientLux; + recalculateBrightnessCap(mHdrBrightnessData, ambientLux); + } + + /** + * Updates brightness cap config. + * Called in same looper: mHandler.getLooper() + */ + public void resetHdrConfig(HdrBrightnessData data) { + mHdrBrightnessData = data; + recalculateBrightnessCap(data, mAmbientLux); + } + + /** + * Dumps the state of HdrClamper. + */ + public void dump(PrintWriter pw) { + pw.println("HdrClamper:"); + pw.println(" mMaxBrightness=" + mMaxBrightness); + pw.println(" mDesiredMaxBrightness=" + mDesiredMaxBrightness); + pw.println(" mTransitionRate=" + mTransitionRate); + pw.println(" mDesiredTransitionRate=" + mDesiredTransitionRate); + pw.println(" mHdrBrightnessData=" + (mHdrBrightnessData == null ? "null" + : mHdrBrightnessData.toString())); + pw.println(" mAmbientLux=" + mAmbientLux); + } + + private void recalculateBrightnessCap(HdrBrightnessData data, float ambientLux) { + if (data == null) { + mHandler.removeCallbacks(mDebouncer); + return; + } + float expectedMaxBrightness = findBrightnessLimit(data, ambientLux); + if (mMaxBrightness == expectedMaxBrightness) { mDesiredMaxBrightness = mMaxBrightness; - mDesiredTransitionDuration = -1; + mDesiredTransitionRate = -1f; mTransitionRate = -1f; mHandler.removeCallbacks(mDebouncer); } else if (mDesiredMaxBrightness != expectedMaxBrightness) { mDesiredMaxBrightness = expectedMaxBrightness; long debounceTime; + long transitionDuration; if (mDesiredMaxBrightness > mMaxBrightness) { - debounceTime = mConfiguration.mIncreaseConfig.mDebounceTimeMillis; - mDesiredTransitionDuration = - (float) mConfiguration.mIncreaseConfig.mTransitionTimeMillis / 1000; + debounceTime = mHdrBrightnessData.mBrightnessIncreaseDebounceMillis; + transitionDuration = mHdrBrightnessData.mBrightnessIncreaseDurationMillis; } else { - debounceTime = mConfiguration.mDecreaseConfig.mDebounceTimeMillis; - mDesiredTransitionDuration = - (float) mConfiguration.mDecreaseConfig.mTransitionTimeMillis / 1000; + debounceTime = mHdrBrightnessData.mBrightnessDecreaseDebounceMillis; + transitionDuration = mHdrBrightnessData.mBrightnessDecreaseDurationMillis; } + mDesiredTransitionRate = Math.abs( + (mMaxBrightness - mDesiredMaxBrightness) * 1000f / transitionDuration); mHandler.removeCallbacks(mDebouncer); mHandler.postDelayed(mDebouncer, debounceTime); } } - @VisibleForTesting - Configuration getConfiguration() { - return mConfiguration; - } - - private float findBrightnessLimit(float ambientLux) { + private float findBrightnessLimit(HdrBrightnessData data, float ambientLux) { float foundAmbientBoundary = Float.MAX_VALUE; float foundMaxBrightness = PowerManager.BRIGHTNESS_MAX; for (Map.Entry<Float, Float> brightnessPoint : - mConfiguration.mMaxBrightnessLimits.entrySet()) { + data.mMaxBrightnessLimits.entrySet()) { float ambientBoundary = brightnessPoint.getKey(); // find ambient lux upper boundary closest to current ambient lux if (ambientBoundary > ambientLux && ambientBoundary < foundAmbientBoundary) { @@ -114,19 +143,4 @@ public class HdrClamper { } return foundMaxBrightness; } - - @VisibleForTesting - static class Configuration { - final Map<Float, Float> mMaxBrightnessLimits = new HashMap<>(); - final TransitionConfiguration mIncreaseConfig = new TransitionConfiguration(); - - final TransitionConfiguration mDecreaseConfig = new TransitionConfiguration(); - } - - @VisibleForTesting - static class TransitionConfiguration { - long mDebounceTimeMillis; - - long mTransitionTimeMillis; - } } diff --git a/services/core/java/com/android/server/display/config/HdrBrightnessData.java b/services/core/java/com/android/server/display/config/HdrBrightnessData.java index 06d3c5b87520..48d671d356f7 100644 --- a/services/core/java/com/android/server/display/config/HdrBrightnessData.java +++ b/services/core/java/com/android/server/display/config/HdrBrightnessData.java @@ -18,6 +18,8 @@ package com.android.server.display.config; import android.annotation.Nullable; +import com.android.internal.annotations.VisibleForTesting; + import java.util.HashMap; import java.util.List; import java.util.Map; @@ -52,7 +54,8 @@ public class HdrBrightnessData { */ public final long mBrightnessDecreaseDurationMillis; - private HdrBrightnessData(Map<Float, Float> maxBrightnessLimits, + @VisibleForTesting + public HdrBrightnessData(Map<Float, Float> maxBrightnessLimits, long brightnessIncreaseDebounceMillis, long brightnessIncreaseDurationMillis, long brightnessDecreaseDebounceMillis, long brightnessDecreaseDurationMillis) { mMaxBrightnessLimits = maxBrightnessLimits; diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java index aebd8a08ee3f..d23c4fe91c84 100644 --- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java @@ -39,6 +39,10 @@ public class DisplayManagerFlags { Flags.FLAG_ENABLE_NBM_CONTROLLER, Flags::enableNbmController); + private final FlagState mHdrClamperFlagState = new FlagState( + Flags.FLAG_ENABLE_HDR_CLAMPER, + Flags::enableHdrClamper); + /** Returns whether connected display management is enabled or not. */ public boolean isConnectedDisplayManagementEnabled() { return mConnectedDisplayManagementFlagState.isEnabled(); @@ -49,6 +53,10 @@ public class DisplayManagerFlags { return mNbmControllerFlagState.isEnabled(); } + public boolean isHdrClamperEnabled() { + return mHdrClamperFlagState.isEnabled(); + } + private static class FlagState { private final String mName; diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig index 12306b039225..ce64bd389839 100644 --- a/services/core/java/com/android/server/display/feature/display_flags.aconfig +++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig @@ -14,6 +14,14 @@ flag { name: "enable_nbm_controller" namespace: "display_manager" description: "Feature flag for Normal Brightness Mode Controller" - bug: "277877297" + bug: "299527549" + is_fixed_read_only: true +} + +flag { + name: "enable_hdr_clamper" + namespace: "display_manager" + description: "Feature flag for HDR Clamper" + bug: "295100043" is_fixed_read_only: true } diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java index d6b2c8732e50..85406b5d12dd 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java @@ -1256,9 +1256,35 @@ public final class DisplayPowerController2Test { } @Test - public void testRampRateForHdrContent() { + public void testRampRateForHdrContent_HdrClamperOff() { + float hdrBrightness = 0.8f; float clampedBrightness = 0.6f; - float transitionRate = 35.5f; + float transitionRate = 1.5f; + + DisplayPowerRequest dpr = new DisplayPowerRequest(); + when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f); + when(mHolder.displayPowerState.getScreenBrightness()).thenReturn(.2f); + when(mHolder.displayPowerState.getSdrScreenBrightness()).thenReturn(.1f); + when(mHolder.hbmController.getHighBrightnessMode()).thenReturn( + BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR); + when(mHolder.hbmController.getHdrBrightnessValue()).thenReturn(hdrBrightness); + when(mHolder.hdrClamper.getMaxBrightness()).thenReturn(clampedBrightness); + when(mHolder.hdrClamper.getTransitionRate()).thenReturn(transitionRate); + + mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + advanceTime(1); // Run updatePowerState + + verify(mHolder.animator, atLeastOnce()).animateTo(eq(hdrBrightness), anyFloat(), + eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE), eq(false)); + } + + @Test + public void testRampRateForHdrContent_HdrClamperOn() { + float clampedBrightness = 0.6f; + float transitionRate = 1.5f; + DisplayManagerFlags flags = mock(DisplayManagerFlags.class); + when(flags.isHdrClamperEnabled()).thenReturn(true); + mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID, /* isEnabled= */ true, flags); DisplayPowerRequest dpr = new DisplayPowerRequest(); when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f); @@ -1361,6 +1387,12 @@ public final class DisplayPowerController2Test { private DisplayPowerControllerHolder createDisplayPowerController(int displayId, String uniqueId, boolean isEnabled) { + return createDisplayPowerController(displayId, uniqueId, isEnabled, + mock(DisplayManagerFlags.class)); + } + + private DisplayPowerControllerHolder createDisplayPowerController(int displayId, + String uniqueId, boolean isEnabled, DisplayManagerFlags flags) { final DisplayPowerState displayPowerState = mock(DisplayPowerState.class); final DualRampAnimator<DisplayPowerState> animator = mock(DualRampAnimator.class); final AutomaticBrightnessController automaticBrightnessController = @@ -1373,7 +1405,6 @@ public final class DisplayPowerController2Test { mock(ScreenOffBrightnessSensorController.class); final HighBrightnessModeController hbmController = mock(HighBrightnessModeController.class); final HdrClamper hdrClamper = mock(HdrClamper.class); - final DisplayManagerFlags flags = mock(DisplayManagerFlags.class); when(hbmController.getCurrentBrightnessMax()).thenReturn(PowerManager.BRIGHTNESS_MAX); diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java index 0ebe46ac0c88..37d966d044c5 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java @@ -24,6 +24,7 @@ import android.os.PowerManager; import androidx.test.filters.SmallTest; +import com.android.server.display.config.HdrBrightnessData; import com.android.server.testutils.OffsettableClock; import com.android.server.testutils.TestHandler; @@ -34,6 +35,8 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import java.util.Map; + @SmallTest public class HdrClamperTest { @@ -108,10 +111,13 @@ public class HdrClamperTest { } private void configureClamper() { - mHdrClamper.getConfiguration().mMaxBrightnessLimits.put(500f, 0.6f); - mHdrClamper.getConfiguration().mIncreaseConfig.mDebounceTimeMillis = 1000; - mHdrClamper.getConfiguration().mIncreaseConfig.mTransitionTimeMillis = 1500; - mHdrClamper.getConfiguration().mDecreaseConfig.mDebounceTimeMillis = 2000; - mHdrClamper.getConfiguration().mDecreaseConfig.mTransitionTimeMillis = 2500; + HdrBrightnessData data = new HdrBrightnessData( + Map.of(500f, 0.6f), + /* brightnessIncreaseDebounceMillis= */ 1000, + /* brightnessIncreaseDurationMillis= */ 1500, + /* brightnessDecreaseDebounceMillis= */ 2000, + /* brightnessDecreaseDurationMillis= */2500 + ); + mHdrClamper.resetHdrConfig(data); } } |