Loading services/core/java/com/android/server/display/DisplayDeviceConfig.java +7 −4 Original line number Diff line number Diff line Loading @@ -99,6 +99,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Function; import javax.xml.datatype.DatatypeConfigurationException; Loading Loading @@ -1798,15 +1799,17 @@ public class DisplayDeviceConfig { loadThermalThrottlingConfig(config); loadPowerThrottlingConfigData(config); // Backlight and evenDimmer data should be loaded for HbmData mHbmData = HighBrightnessModeData.loadHighBrightnessModeData(config, (hbm) -> { Function<HighBrightnessMode, Float> transitionPointProvider = (hbm) -> { float transitionPointBacklightScale = hbm.getTransitionPoint_all().floatValue(); if (transitionPointBacklightScale >= mBacklightMaximum) { throw new IllegalArgumentException("HBM transition point invalid. " + mHbmData.transitionPoint + " is not less than " + transitionPointBacklightScale + " is not less than " + mBacklightMaximum); } return getBrightnessFromBacklight(transitionPointBacklightScale); }); }; mHbmData = HighBrightnessModeData.loadHighBrightnessModeData(config, transitionPointProvider); if (mHbmData.isHighBrightnessModeEnabled && mHbmData.refreshRateLimit != null) { // TODO(b/331650248): cleanup, DMD can use mHbmData.refreshRateLimit mRefreshRateLimitations.add(new RefreshRateLimitation( Loading @@ -1830,7 +1833,7 @@ public class DisplayDeviceConfig { loadRefreshRateSetting(config); loadScreenOffBrightnessSensorValueToLuxFromDdc(config); loadUsiVersion(config); mHdrBrightnessData = HdrBrightnessData.loadConfig(config); mHdrBrightnessData = HdrBrightnessData.loadConfig(config, transitionPointProvider); loadBrightnessCapForWearBedtimeMode(config); loadIdleScreenRefreshRateTimeoutConfigs(config); mVrrSupportEnabled = config.getSupportsVrr(); Loading services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +4 −3 Original line number Diff line number Diff line Loading @@ -271,8 +271,9 @@ public class BrightnessClamperController { ModifiersAggregatedState state2) { return !BrightnessSynchronizer.floatEquals(state1.mMaxDesiredHdrRatio, state2.mMaxDesiredHdrRatio) || state1.mSdrHdrRatioSpline != state2.mSdrHdrRatioSpline || state1.mHdrHbmEnabled != state2.mHdrHbmEnabled; || !BrightnessSynchronizer.floatEquals(state1.mMaxHdrBrightness, state2.mMaxHdrBrightness) || state1.mSdrHdrRatioSpline != state2.mSdrHdrRatioSpline; } private void start() { Loading Loading @@ -470,8 +471,8 @@ public class BrightnessClamperController { */ public static class ModifiersAggregatedState { float mMaxDesiredHdrRatio = HdrBrightnessModifier.DEFAULT_MAX_HDR_SDR_RATIO; float mMaxHdrBrightness = PowerManager.BRIGHTNESS_MAX; @Nullable Spline mSdrHdrRatioSpline = null; boolean mHdrHbmEnabled = false; } } services/core/java/com/android/server/display/brightness/clamper/HdrBrightnessModifier.java +119 −13 Original line number Diff line number Diff line Loading @@ -16,11 +16,15 @@ package com.android.server.display.brightness.clamper; import static com.android.server.display.DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; import static com.android.server.display.brightness.clamper.LightSensorController.INVALID_LUX; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.hardware.display.DisplayManagerInternal; import android.os.Handler; import android.os.IBinder; import android.os.PowerManager; import android.view.SurfaceControlHdrLayerInfoListener; import com.android.internal.annotations.VisibleForTesting; Loading @@ -30,6 +34,7 @@ import com.android.server.display.DisplayDeviceConfig; import com.android.server.display.config.HdrBrightnessData; import java.io.PrintWriter; import java.util.Map; public class HdrBrightnessModifier implements BrightnessStateModifier, BrightnessClamperController.DisplayDeviceDataListener, Loading @@ -53,20 +58,32 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, private final Handler mHandler; private final BrightnessClamperController.ClamperChangeListener mClamperChangeListener; private final Injector mInjector; private final Runnable mDebouncer; private IBinder mRegisteredDisplayToken; private float mScreenSize; private float mHdrLayerSize = DEFAULT_HDR_LAYER_SIZE; private HdrBrightnessData mHdrBrightnessData; private DisplayDeviceConfig mDisplayDeviceConfig; @Nullable private HdrBrightnessData mHdrBrightnessData; private float mScreenSize; private float mMaxDesiredHdrRatio = DEFAULT_MAX_HDR_SDR_RATIO; private float mHdrLayerSize = DEFAULT_HDR_LAYER_SIZE; private float mAmbientLux = INVALID_LUX; private Mode mMode = Mode.NO_HDR; // The maximum brightness allowed for current lux private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX; private float mPendingMaxBrightness = PowerManager.BRIGHTNESS_MAX; // brightness change speed, in units per seconds. Applied only on ambient lux changes private float mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET; private float mPendingTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET; HdrBrightnessModifier(Handler handler, BrightnessClamperController.ClamperChangeListener clamperChangeListener, BrightnessClamperController.DisplayDeviceData displayData) { this(handler, clamperChangeListener, new Injector(), displayData); this(new Handler(handler.getLooper()), clamperChangeListener, new Injector(), displayData); } @VisibleForTesting Loading @@ -77,6 +94,11 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, mHandler = handler; mClamperChangeListener = clamperChangeListener; mInjector = injector; mDebouncer = () -> { mTransitionRate = mPendingTransitionRate; mMaxBrightness = mPendingMaxBrightness; mClamperChangeListener.onChanged(); }; onDisplayChanged(displayData); } Loading @@ -90,33 +112,60 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, if (mMode == Mode.NO_HDR) { return; } float hdrBrightness = mDisplayDeviceConfig.getHdrBrightnessFromSdr( stateBuilder.getBrightness(), mMaxDesiredHdrRatio, mHdrBrightnessData.sdrToHdrRatioSpline); float maxBrightness = getMaxBrightness(mMode, mMaxBrightness, mHdrBrightnessData); hdrBrightness = Math.min(hdrBrightness, maxBrightness); stateBuilder.setHdrBrightness(hdrBrightness); stateBuilder.setCustomAnimationRate(mTransitionRate); // transition rate applied, reset mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET; } @Override public void dump(PrintWriter printWriter) { // noop public void dump(PrintWriter pw) { pw.println("HdrBrightnessModifier:"); pw.println(" mHdrBrightnessData=" + mHdrBrightnessData); pw.println(" mScreenSize=" + mScreenSize); pw.println(" mMaxDesiredHdrRatio=" + mMaxDesiredHdrRatio); pw.println(" mHdrLayerSize=" + mHdrLayerSize); pw.println(" mAmbientLux=" + mAmbientLux); pw.println(" mMode=" + mMode); pw.println(" mMaxBrightness=" + mMaxBrightness); pw.println(" mPendingMaxBrightness=" + mPendingMaxBrightness); pw.println(" mTransitionRate=" + mTransitionRate); pw.println(" mPendingTransitionRate=" + mPendingTransitionRate); pw.println(" mHdrListener registered=" + (mRegisteredDisplayToken != null)); } // Called in DisplayControllerHandler @Override public void stop() { unregisterHdrListener(); mHandler.removeCallbacksAndMessages(null); } // Called in DisplayControllerHandler @Override public boolean shouldListenToLightSensor() { return false; return hasBrightnessLimits(); } // Called in DisplayControllerHandler @Override public void setAmbientLux(float lux) { // noop mAmbientLux = lux; if (!hasBrightnessLimits()) { return; } float desiredMaxBrightness = findBrightnessLimit(mHdrBrightnessData, lux); if (mMode == Mode.NO_HDR) { mMaxBrightness = desiredMaxBrightness; } else { scheduleMaxBrightnessUpdate(desiredMaxBrightness, mHdrBrightnessData); } } @Override Loading @@ -125,15 +174,44 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, displayData.mHeight, displayData.mDisplayDeviceConfig)); } // Called in DisplayControllerHandler // Called in DisplayControllerHandler, when any modifier state changes @Override public void applyStateChange( BrightnessClamperController.ModifiersAggregatedState aggregatedState) { if (mMode != Mode.NO_HDR) { if (mMode != Mode.NO_HDR && mHdrBrightnessData != null) { aggregatedState.mMaxDesiredHdrRatio = mMaxDesiredHdrRatio; aggregatedState.mSdrHdrRatioSpline = mHdrBrightnessData.sdrToHdrRatioSpline; aggregatedState.mHdrHbmEnabled = (mMode == Mode.HBM_HDR); aggregatedState.mMaxHdrBrightness = getMaxBrightness( mMode, mMaxBrightness, mHdrBrightnessData); } } private boolean hasBrightnessLimits() { return mHdrBrightnessData != null && !mHdrBrightnessData.maxBrightnessLimits.isEmpty(); } private void scheduleMaxBrightnessUpdate(float desiredMaxBrightness, HdrBrightnessData data) { if (mMaxBrightness == desiredMaxBrightness) { mPendingMaxBrightness = mMaxBrightness; mPendingTransitionRate = -1f; mTransitionRate = -1f; mHandler.removeCallbacks(mDebouncer); } else if (mPendingMaxBrightness != desiredMaxBrightness) { mPendingMaxBrightness = desiredMaxBrightness; long debounceTime; if (mPendingMaxBrightness > mMaxBrightness) { debounceTime = data.brightnessIncreaseDebounceMillis; mPendingTransitionRate = data.screenBrightnessRampIncrease; } else { debounceTime = data.brightnessDecreaseDebounceMillis; mPendingTransitionRate = data.screenBrightnessRampDecrease; } mHandler.removeCallbacks(mDebouncer); mHandler.postDelayed(mDebouncer, debounceTime); } // do nothing if expectedMaxBrightness == mDesiredMaxBrightness // && expectedMaxBrightness != mMaxBrightness } // Called in DisplayControllerHandler Loading Loading @@ -168,6 +246,8 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, mMaxDesiredHdrRatio = maxDesiredHdrRatio; if (needToNotifyChange) { // data or hdr layer changed, reset custom transition rate mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET; mClamperChangeListener.onChanged(); } } Loading @@ -190,6 +270,32 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, return Mode.HBM_HDR; } private float getMaxBrightness(Mode mode, float maxBrightness, HdrBrightnessData data) { if (mode == Mode.NBM_HDR) { return Math.min(data.hbmTransitionPoint, maxBrightness); } else if (mode == Mode.HBM_HDR) { return maxBrightness; } else { return PowerManager.BRIGHTNESS_MAX; } } // Called in DisplayControllerHandler private float findBrightnessLimit(HdrBrightnessData data, float ambientLux) { float foundAmbientBoundary = Float.MAX_VALUE; float foundMaxBrightness = PowerManager.BRIGHTNESS_MAX; for (Map.Entry<Float, Float> brightnessPoint : data.maxBrightnessLimits.entrySet()) { float ambientBoundary = brightnessPoint.getKey(); // find ambient lux upper boundary closest to current ambient lux if (ambientBoundary > ambientLux && ambientBoundary < foundAmbientBoundary) { foundMaxBrightness = brightnessPoint.getValue(); foundAmbientBoundary = ambientBoundary; } } return foundMaxBrightness; } // Called in DisplayControllerHandler private void onHdrInfoChanged(float hdrLayerSize, float maxDesiredHdrSdrRatio) { mHdrLayerSize = hdrLayerSize; Loading services/core/java/com/android/server/display/config/HdrBrightnessData.java +35 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.display.config; import static com.android.server.display.config.HighBrightnessModeData.HDR_PERCENT_OF_SCREEN_REQUIRED_DEFAULT; import android.annotation.Nullable; import android.os.PowerManager; import android.util.Spline; import com.android.internal.annotations.VisibleForTesting; Loading @@ -29,6 +30,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; /** * Brightness config for HDR content Loading @@ -48,9 +50,9 @@ import java.util.Map; * </point> * </brightnessMap> * <brightnessIncreaseDebounceMillis>1000</brightnessIncreaseDebounceMillis> * <brightnessIncreaseDurationMillis>10000</brightnessIncreaseDurationMillis> * <screenBrightnessRampIncrease>0.04</brightnessIncreaseDurationMillis> * <brightnessDecreaseDebounceMillis>13000</brightnessDecreaseDebounceMillis> * <brightnessDecreaseDurationMillis>10000</brightnessDecreaseDurationMillis> * <screenBrightnessRampDecrease>0.03</brightnessDecreaseDurationMillis> * <minimumHdrPercentOfScreenForNbm>0.2</minimumHdrPercentOfScreenForNbm> * <minimumHdrPercentOfScreenForHbm>0.5</minimumHdrPercentOfScreenForHbm> * <allowInLowPowerMode>true</allowInLowPowerMode> Loading Loading @@ -98,6 +100,11 @@ public class HdrBrightnessData { */ public final float screenBrightnessRampDecrease; /** * Brightness level at which we transition from normal to high-brightness */ public final float hbmTransitionPoint; /** * Min Hdr layer size to start hdr brightness boost up to high brightness mode transition point */ Loading @@ -123,6 +130,7 @@ public class HdrBrightnessData { public HdrBrightnessData(Map<Float, Float> maxBrightnessLimits, long brightnessIncreaseDebounceMillis, float screenBrightnessRampIncrease, long brightnessDecreaseDebounceMillis, float screenBrightnessRampDecrease, float hbmTransitionPoint, float minimumHdrPercentOfScreenForNbm, float minimumHdrPercentOfScreenForHbm, boolean allowInLowPowerMode, @Nullable Spline sdrToHdrRatioSpline) { this.maxBrightnessLimits = maxBrightnessLimits; Loading @@ -130,6 +138,7 @@ public class HdrBrightnessData { this.screenBrightnessRampIncrease = screenBrightnessRampIncrease; this.brightnessDecreaseDebounceMillis = brightnessDecreaseDebounceMillis; this.screenBrightnessRampDecrease = screenBrightnessRampDecrease; this.hbmTransitionPoint = hbmTransitionPoint; this.minimumHdrPercentOfScreenForNbm = minimumHdrPercentOfScreenForNbm; this.minimumHdrPercentOfScreenForHbm = minimumHdrPercentOfScreenForHbm; this.allowInLowPowerMode = allowInLowPowerMode; Loading @@ -144,6 +153,7 @@ public class HdrBrightnessData { + ", mScreenBrightnessRampIncrease: " + screenBrightnessRampIncrease + ", mBrightnessDecreaseDebounceMillis: " + brightnessDecreaseDebounceMillis + ", mScreenBrightnessRampDecrease: " + screenBrightnessRampDecrease + ", transitionPoint: " + hbmTransitionPoint + ", minimumHdrPercentOfScreenForNbm: " + minimumHdrPercentOfScreenForNbm + ", minimumHdrPercentOfScreenForHbm: " + minimumHdrPercentOfScreenForHbm + ", allowInLowPowerMode: " + allowInLowPowerMode Loading @@ -155,10 +165,12 @@ public class HdrBrightnessData { * Loads HdrBrightnessData from DisplayConfiguration */ @Nullable public static HdrBrightnessData loadConfig(DisplayConfiguration config) { public static HdrBrightnessData loadConfig(DisplayConfiguration config, Function<HighBrightnessMode, Float> transitionPointProvider) { HighBrightnessMode hbmConfig = config.getHighBrightnessMode(); HdrBrightnessConfig hdrConfig = config.getHdrBrightnessConfig(); if (hdrConfig == null) { return getFallbackData(config.getHighBrightnessMode()); return getFallbackData(hbmConfig, transitionPointProvider); } List<NonNegativeFloatToFloatPoint> points = hdrConfig.getBrightnessMap().getPoint(); Loading @@ -169,22 +181,38 @@ public class HdrBrightnessData { float minHdrPercentForHbm = hdrConfig.getMinimumHdrPercentOfScreenForHbm() != null ? hdrConfig.getMinimumHdrPercentOfScreenForHbm().floatValue() : getFallbackHdrPercent(config.getHighBrightnessMode()); : getFallbackHdrPercent(hbmConfig); float minHdrPercentForNbm = hdrConfig.getMinimumHdrPercentOfScreenForNbm() != null ? hdrConfig.getMinimumHdrPercentOfScreenForNbm().floatValue() : minHdrPercentForHbm; if (minHdrPercentForNbm > minHdrPercentForHbm) { throw new IllegalArgumentException( "minHdrPercentForHbm should be >= minHdrPercentForNbm"); } return new HdrBrightnessData(brightnessLimits, hdrConfig.getBrightnessIncreaseDebounceMillis().longValue(), hdrConfig.getScreenBrightnessRampIncrease().floatValue(), hdrConfig.getBrightnessDecreaseDebounceMillis().longValue(), hdrConfig.getScreenBrightnessRampDecrease().floatValue(), getTransitionPoint(hbmConfig, transitionPointProvider), minHdrPercentForNbm, minHdrPercentForHbm, hdrConfig.getAllowInLowPowerMode(), getSdrHdrRatioSpline(hdrConfig, config.getHighBrightnessMode())); } private static float getTransitionPoint(@Nullable HighBrightnessMode hbm, Function<HighBrightnessMode, Float> transitionPointProvider) { if (hbm == null) { return PowerManager.BRIGHTNESS_MAX; } else { return transitionPointProvider.apply(hbm); } } @Nullable private static HdrBrightnessData getFallbackData(HighBrightnessMode hbm) { private static HdrBrightnessData getFallbackData(@Nullable HighBrightnessMode hbm, Function<HighBrightnessMode, Float> transitionPointProvider) { if (hbm == null) { return null; } Loading @@ -193,6 +221,7 @@ public class HdrBrightnessData { return new HdrBrightnessData(Collections.emptyMap(), 0, DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET, 0, DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET, getTransitionPoint(hbm, transitionPointProvider), fallbackPercent, fallbackPercent, false, fallbackSpline); } Loading services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -353,7 +353,8 @@ public class BrightnessClamperControllerTest { public void test_notifiesExternalListener_aggregatedStateChanged() { doAnswer((invocation) -> { ModifiersAggregatedState argument = invocation.getArgument(0); argument.mHdrHbmEnabled = true; // we need to do changes in AggregatedState to trigger onChange argument.mMaxHdrBrightness = 0.5f; return null; }).when(mMockStatefulModifier).applyStateChange(any()); mTestInjector.mCapturedChangeListener.onChanged(); Loading Loading
services/core/java/com/android/server/display/DisplayDeviceConfig.java +7 −4 Original line number Diff line number Diff line Loading @@ -99,6 +99,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Function; import javax.xml.datatype.DatatypeConfigurationException; Loading Loading @@ -1798,15 +1799,17 @@ public class DisplayDeviceConfig { loadThermalThrottlingConfig(config); loadPowerThrottlingConfigData(config); // Backlight and evenDimmer data should be loaded for HbmData mHbmData = HighBrightnessModeData.loadHighBrightnessModeData(config, (hbm) -> { Function<HighBrightnessMode, Float> transitionPointProvider = (hbm) -> { float transitionPointBacklightScale = hbm.getTransitionPoint_all().floatValue(); if (transitionPointBacklightScale >= mBacklightMaximum) { throw new IllegalArgumentException("HBM transition point invalid. " + mHbmData.transitionPoint + " is not less than " + transitionPointBacklightScale + " is not less than " + mBacklightMaximum); } return getBrightnessFromBacklight(transitionPointBacklightScale); }); }; mHbmData = HighBrightnessModeData.loadHighBrightnessModeData(config, transitionPointProvider); if (mHbmData.isHighBrightnessModeEnabled && mHbmData.refreshRateLimit != null) { // TODO(b/331650248): cleanup, DMD can use mHbmData.refreshRateLimit mRefreshRateLimitations.add(new RefreshRateLimitation( Loading @@ -1830,7 +1833,7 @@ public class DisplayDeviceConfig { loadRefreshRateSetting(config); loadScreenOffBrightnessSensorValueToLuxFromDdc(config); loadUsiVersion(config); mHdrBrightnessData = HdrBrightnessData.loadConfig(config); mHdrBrightnessData = HdrBrightnessData.loadConfig(config, transitionPointProvider); loadBrightnessCapForWearBedtimeMode(config); loadIdleScreenRefreshRateTimeoutConfigs(config); mVrrSupportEnabled = config.getSupportsVrr(); Loading
services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +4 −3 Original line number Diff line number Diff line Loading @@ -271,8 +271,9 @@ public class BrightnessClamperController { ModifiersAggregatedState state2) { return !BrightnessSynchronizer.floatEquals(state1.mMaxDesiredHdrRatio, state2.mMaxDesiredHdrRatio) || state1.mSdrHdrRatioSpline != state2.mSdrHdrRatioSpline || state1.mHdrHbmEnabled != state2.mHdrHbmEnabled; || !BrightnessSynchronizer.floatEquals(state1.mMaxHdrBrightness, state2.mMaxHdrBrightness) || state1.mSdrHdrRatioSpline != state2.mSdrHdrRatioSpline; } private void start() { Loading Loading @@ -470,8 +471,8 @@ public class BrightnessClamperController { */ public static class ModifiersAggregatedState { float mMaxDesiredHdrRatio = HdrBrightnessModifier.DEFAULT_MAX_HDR_SDR_RATIO; float mMaxHdrBrightness = PowerManager.BRIGHTNESS_MAX; @Nullable Spline mSdrHdrRatioSpline = null; boolean mHdrHbmEnabled = false; } }
services/core/java/com/android/server/display/brightness/clamper/HdrBrightnessModifier.java +119 −13 Original line number Diff line number Diff line Loading @@ -16,11 +16,15 @@ package com.android.server.display.brightness.clamper; import static com.android.server.display.DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; import static com.android.server.display.brightness.clamper.LightSensorController.INVALID_LUX; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.hardware.display.DisplayManagerInternal; import android.os.Handler; import android.os.IBinder; import android.os.PowerManager; import android.view.SurfaceControlHdrLayerInfoListener; import com.android.internal.annotations.VisibleForTesting; Loading @@ -30,6 +34,7 @@ import com.android.server.display.DisplayDeviceConfig; import com.android.server.display.config.HdrBrightnessData; import java.io.PrintWriter; import java.util.Map; public class HdrBrightnessModifier implements BrightnessStateModifier, BrightnessClamperController.DisplayDeviceDataListener, Loading @@ -53,20 +58,32 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, private final Handler mHandler; private final BrightnessClamperController.ClamperChangeListener mClamperChangeListener; private final Injector mInjector; private final Runnable mDebouncer; private IBinder mRegisteredDisplayToken; private float mScreenSize; private float mHdrLayerSize = DEFAULT_HDR_LAYER_SIZE; private HdrBrightnessData mHdrBrightnessData; private DisplayDeviceConfig mDisplayDeviceConfig; @Nullable private HdrBrightnessData mHdrBrightnessData; private float mScreenSize; private float mMaxDesiredHdrRatio = DEFAULT_MAX_HDR_SDR_RATIO; private float mHdrLayerSize = DEFAULT_HDR_LAYER_SIZE; private float mAmbientLux = INVALID_LUX; private Mode mMode = Mode.NO_HDR; // The maximum brightness allowed for current lux private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX; private float mPendingMaxBrightness = PowerManager.BRIGHTNESS_MAX; // brightness change speed, in units per seconds. Applied only on ambient lux changes private float mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET; private float mPendingTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET; HdrBrightnessModifier(Handler handler, BrightnessClamperController.ClamperChangeListener clamperChangeListener, BrightnessClamperController.DisplayDeviceData displayData) { this(handler, clamperChangeListener, new Injector(), displayData); this(new Handler(handler.getLooper()), clamperChangeListener, new Injector(), displayData); } @VisibleForTesting Loading @@ -77,6 +94,11 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, mHandler = handler; mClamperChangeListener = clamperChangeListener; mInjector = injector; mDebouncer = () -> { mTransitionRate = mPendingTransitionRate; mMaxBrightness = mPendingMaxBrightness; mClamperChangeListener.onChanged(); }; onDisplayChanged(displayData); } Loading @@ -90,33 +112,60 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, if (mMode == Mode.NO_HDR) { return; } float hdrBrightness = mDisplayDeviceConfig.getHdrBrightnessFromSdr( stateBuilder.getBrightness(), mMaxDesiredHdrRatio, mHdrBrightnessData.sdrToHdrRatioSpline); float maxBrightness = getMaxBrightness(mMode, mMaxBrightness, mHdrBrightnessData); hdrBrightness = Math.min(hdrBrightness, maxBrightness); stateBuilder.setHdrBrightness(hdrBrightness); stateBuilder.setCustomAnimationRate(mTransitionRate); // transition rate applied, reset mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET; } @Override public void dump(PrintWriter printWriter) { // noop public void dump(PrintWriter pw) { pw.println("HdrBrightnessModifier:"); pw.println(" mHdrBrightnessData=" + mHdrBrightnessData); pw.println(" mScreenSize=" + mScreenSize); pw.println(" mMaxDesiredHdrRatio=" + mMaxDesiredHdrRatio); pw.println(" mHdrLayerSize=" + mHdrLayerSize); pw.println(" mAmbientLux=" + mAmbientLux); pw.println(" mMode=" + mMode); pw.println(" mMaxBrightness=" + mMaxBrightness); pw.println(" mPendingMaxBrightness=" + mPendingMaxBrightness); pw.println(" mTransitionRate=" + mTransitionRate); pw.println(" mPendingTransitionRate=" + mPendingTransitionRate); pw.println(" mHdrListener registered=" + (mRegisteredDisplayToken != null)); } // Called in DisplayControllerHandler @Override public void stop() { unregisterHdrListener(); mHandler.removeCallbacksAndMessages(null); } // Called in DisplayControllerHandler @Override public boolean shouldListenToLightSensor() { return false; return hasBrightnessLimits(); } // Called in DisplayControllerHandler @Override public void setAmbientLux(float lux) { // noop mAmbientLux = lux; if (!hasBrightnessLimits()) { return; } float desiredMaxBrightness = findBrightnessLimit(mHdrBrightnessData, lux); if (mMode == Mode.NO_HDR) { mMaxBrightness = desiredMaxBrightness; } else { scheduleMaxBrightnessUpdate(desiredMaxBrightness, mHdrBrightnessData); } } @Override Loading @@ -125,15 +174,44 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, displayData.mHeight, displayData.mDisplayDeviceConfig)); } // Called in DisplayControllerHandler // Called in DisplayControllerHandler, when any modifier state changes @Override public void applyStateChange( BrightnessClamperController.ModifiersAggregatedState aggregatedState) { if (mMode != Mode.NO_HDR) { if (mMode != Mode.NO_HDR && mHdrBrightnessData != null) { aggregatedState.mMaxDesiredHdrRatio = mMaxDesiredHdrRatio; aggregatedState.mSdrHdrRatioSpline = mHdrBrightnessData.sdrToHdrRatioSpline; aggregatedState.mHdrHbmEnabled = (mMode == Mode.HBM_HDR); aggregatedState.mMaxHdrBrightness = getMaxBrightness( mMode, mMaxBrightness, mHdrBrightnessData); } } private boolean hasBrightnessLimits() { return mHdrBrightnessData != null && !mHdrBrightnessData.maxBrightnessLimits.isEmpty(); } private void scheduleMaxBrightnessUpdate(float desiredMaxBrightness, HdrBrightnessData data) { if (mMaxBrightness == desiredMaxBrightness) { mPendingMaxBrightness = mMaxBrightness; mPendingTransitionRate = -1f; mTransitionRate = -1f; mHandler.removeCallbacks(mDebouncer); } else if (mPendingMaxBrightness != desiredMaxBrightness) { mPendingMaxBrightness = desiredMaxBrightness; long debounceTime; if (mPendingMaxBrightness > mMaxBrightness) { debounceTime = data.brightnessIncreaseDebounceMillis; mPendingTransitionRate = data.screenBrightnessRampIncrease; } else { debounceTime = data.brightnessDecreaseDebounceMillis; mPendingTransitionRate = data.screenBrightnessRampDecrease; } mHandler.removeCallbacks(mDebouncer); mHandler.postDelayed(mDebouncer, debounceTime); } // do nothing if expectedMaxBrightness == mDesiredMaxBrightness // && expectedMaxBrightness != mMaxBrightness } // Called in DisplayControllerHandler Loading Loading @@ -168,6 +246,8 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, mMaxDesiredHdrRatio = maxDesiredHdrRatio; if (needToNotifyChange) { // data or hdr layer changed, reset custom transition rate mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET; mClamperChangeListener.onChanged(); } } Loading @@ -190,6 +270,32 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, return Mode.HBM_HDR; } private float getMaxBrightness(Mode mode, float maxBrightness, HdrBrightnessData data) { if (mode == Mode.NBM_HDR) { return Math.min(data.hbmTransitionPoint, maxBrightness); } else if (mode == Mode.HBM_HDR) { return maxBrightness; } else { return PowerManager.BRIGHTNESS_MAX; } } // Called in DisplayControllerHandler private float findBrightnessLimit(HdrBrightnessData data, float ambientLux) { float foundAmbientBoundary = Float.MAX_VALUE; float foundMaxBrightness = PowerManager.BRIGHTNESS_MAX; for (Map.Entry<Float, Float> brightnessPoint : data.maxBrightnessLimits.entrySet()) { float ambientBoundary = brightnessPoint.getKey(); // find ambient lux upper boundary closest to current ambient lux if (ambientBoundary > ambientLux && ambientBoundary < foundAmbientBoundary) { foundMaxBrightness = brightnessPoint.getValue(); foundAmbientBoundary = ambientBoundary; } } return foundMaxBrightness; } // Called in DisplayControllerHandler private void onHdrInfoChanged(float hdrLayerSize, float maxDesiredHdrSdrRatio) { mHdrLayerSize = hdrLayerSize; Loading
services/core/java/com/android/server/display/config/HdrBrightnessData.java +35 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.display.config; import static com.android.server.display.config.HighBrightnessModeData.HDR_PERCENT_OF_SCREEN_REQUIRED_DEFAULT; import android.annotation.Nullable; import android.os.PowerManager; import android.util.Spline; import com.android.internal.annotations.VisibleForTesting; Loading @@ -29,6 +30,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; /** * Brightness config for HDR content Loading @@ -48,9 +50,9 @@ import java.util.Map; * </point> * </brightnessMap> * <brightnessIncreaseDebounceMillis>1000</brightnessIncreaseDebounceMillis> * <brightnessIncreaseDurationMillis>10000</brightnessIncreaseDurationMillis> * <screenBrightnessRampIncrease>0.04</brightnessIncreaseDurationMillis> * <brightnessDecreaseDebounceMillis>13000</brightnessDecreaseDebounceMillis> * <brightnessDecreaseDurationMillis>10000</brightnessDecreaseDurationMillis> * <screenBrightnessRampDecrease>0.03</brightnessDecreaseDurationMillis> * <minimumHdrPercentOfScreenForNbm>0.2</minimumHdrPercentOfScreenForNbm> * <minimumHdrPercentOfScreenForHbm>0.5</minimumHdrPercentOfScreenForHbm> * <allowInLowPowerMode>true</allowInLowPowerMode> Loading Loading @@ -98,6 +100,11 @@ public class HdrBrightnessData { */ public final float screenBrightnessRampDecrease; /** * Brightness level at which we transition from normal to high-brightness */ public final float hbmTransitionPoint; /** * Min Hdr layer size to start hdr brightness boost up to high brightness mode transition point */ Loading @@ -123,6 +130,7 @@ public class HdrBrightnessData { public HdrBrightnessData(Map<Float, Float> maxBrightnessLimits, long brightnessIncreaseDebounceMillis, float screenBrightnessRampIncrease, long brightnessDecreaseDebounceMillis, float screenBrightnessRampDecrease, float hbmTransitionPoint, float minimumHdrPercentOfScreenForNbm, float minimumHdrPercentOfScreenForHbm, boolean allowInLowPowerMode, @Nullable Spline sdrToHdrRatioSpline) { this.maxBrightnessLimits = maxBrightnessLimits; Loading @@ -130,6 +138,7 @@ public class HdrBrightnessData { this.screenBrightnessRampIncrease = screenBrightnessRampIncrease; this.brightnessDecreaseDebounceMillis = brightnessDecreaseDebounceMillis; this.screenBrightnessRampDecrease = screenBrightnessRampDecrease; this.hbmTransitionPoint = hbmTransitionPoint; this.minimumHdrPercentOfScreenForNbm = minimumHdrPercentOfScreenForNbm; this.minimumHdrPercentOfScreenForHbm = minimumHdrPercentOfScreenForHbm; this.allowInLowPowerMode = allowInLowPowerMode; Loading @@ -144,6 +153,7 @@ public class HdrBrightnessData { + ", mScreenBrightnessRampIncrease: " + screenBrightnessRampIncrease + ", mBrightnessDecreaseDebounceMillis: " + brightnessDecreaseDebounceMillis + ", mScreenBrightnessRampDecrease: " + screenBrightnessRampDecrease + ", transitionPoint: " + hbmTransitionPoint + ", minimumHdrPercentOfScreenForNbm: " + minimumHdrPercentOfScreenForNbm + ", minimumHdrPercentOfScreenForHbm: " + minimumHdrPercentOfScreenForHbm + ", allowInLowPowerMode: " + allowInLowPowerMode Loading @@ -155,10 +165,12 @@ public class HdrBrightnessData { * Loads HdrBrightnessData from DisplayConfiguration */ @Nullable public static HdrBrightnessData loadConfig(DisplayConfiguration config) { public static HdrBrightnessData loadConfig(DisplayConfiguration config, Function<HighBrightnessMode, Float> transitionPointProvider) { HighBrightnessMode hbmConfig = config.getHighBrightnessMode(); HdrBrightnessConfig hdrConfig = config.getHdrBrightnessConfig(); if (hdrConfig == null) { return getFallbackData(config.getHighBrightnessMode()); return getFallbackData(hbmConfig, transitionPointProvider); } List<NonNegativeFloatToFloatPoint> points = hdrConfig.getBrightnessMap().getPoint(); Loading @@ -169,22 +181,38 @@ public class HdrBrightnessData { float minHdrPercentForHbm = hdrConfig.getMinimumHdrPercentOfScreenForHbm() != null ? hdrConfig.getMinimumHdrPercentOfScreenForHbm().floatValue() : getFallbackHdrPercent(config.getHighBrightnessMode()); : getFallbackHdrPercent(hbmConfig); float minHdrPercentForNbm = hdrConfig.getMinimumHdrPercentOfScreenForNbm() != null ? hdrConfig.getMinimumHdrPercentOfScreenForNbm().floatValue() : minHdrPercentForHbm; if (minHdrPercentForNbm > minHdrPercentForHbm) { throw new IllegalArgumentException( "minHdrPercentForHbm should be >= minHdrPercentForNbm"); } return new HdrBrightnessData(brightnessLimits, hdrConfig.getBrightnessIncreaseDebounceMillis().longValue(), hdrConfig.getScreenBrightnessRampIncrease().floatValue(), hdrConfig.getBrightnessDecreaseDebounceMillis().longValue(), hdrConfig.getScreenBrightnessRampDecrease().floatValue(), getTransitionPoint(hbmConfig, transitionPointProvider), minHdrPercentForNbm, minHdrPercentForHbm, hdrConfig.getAllowInLowPowerMode(), getSdrHdrRatioSpline(hdrConfig, config.getHighBrightnessMode())); } private static float getTransitionPoint(@Nullable HighBrightnessMode hbm, Function<HighBrightnessMode, Float> transitionPointProvider) { if (hbm == null) { return PowerManager.BRIGHTNESS_MAX; } else { return transitionPointProvider.apply(hbm); } } @Nullable private static HdrBrightnessData getFallbackData(HighBrightnessMode hbm) { private static HdrBrightnessData getFallbackData(@Nullable HighBrightnessMode hbm, Function<HighBrightnessMode, Float> transitionPointProvider) { if (hbm == null) { return null; } Loading @@ -193,6 +221,7 @@ public class HdrBrightnessData { return new HdrBrightnessData(Collections.emptyMap(), 0, DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET, 0, DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET, getTransitionPoint(hbm, transitionPointProvider), fallbackPercent, fallbackPercent, false, fallbackSpline); } Loading
services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -353,7 +353,8 @@ public class BrightnessClamperControllerTest { public void test_notifiesExternalListener_aggregatedStateChanged() { doAnswer((invocation) -> { ModifiersAggregatedState argument = invocation.getArgument(0); argument.mHdrHbmEnabled = true; // we need to do changes in AggregatedState to trigger onChange argument.mMaxHdrBrightness = 0.5f; return null; }).when(mMockStatefulModifier).applyStateChange(any()); mTestInjector.mCapturedChangeListener.onChanged(); Loading