diff options
| author | 2024-03-21 23:44:28 +0000 | |
|---|---|---|
| committer | 2024-03-22 23:24:03 +0000 | |
| commit | 53a504dfaeea2c34bccded0d518b34b83af13bc2 (patch) | |
| tree | d03cbe781eefff9125c7e81af8f4fe2a406b608f | |
| parent | 960937f0d480b1fa80dc766527910fc20409b6b6 (diff) | |
Add transition point to low lux modifier
- Add transition point to brightness low lux modifier
- Pass in nits -> brightness splines from ddc.
- Only activate even dimmer if autobrightness is on.
Bug: 179428400
Test: atest DisplayServiceTests
Change-Id: I37c2ddca6c111c11b90525222d22a77ccfd3665f
12 files changed, 337 insertions, 63 deletions
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index 851d1978dd98..1ff285e16aa2 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -1097,13 +1097,34 @@ public class DisplayDeviceConfig { return mBrightnessToBacklightSpline.interpolate(brightness); } - private float getBrightnessFromBacklight(float brightness) { + /** + * Calculates the screen brightness value - as used among the system from the HAL backlight + * level + * @param backlight value from 0-1 HAL scale + * @return brightness value from 0-1 framework scale + */ + public float getBrightnessFromBacklight(float backlight) { if (mLowBrightnessData != null) { - return mLowBrightnessData.mBacklightToBrightness.interpolate(brightness); + return mLowBrightnessData.mBacklightToBrightness.interpolate(backlight); } - return mBacklightToBrightnessSpline.interpolate(brightness); + return mBacklightToBrightnessSpline.interpolate(backlight); } + /** + * + * @return low brightness mode transition point + */ + public float getLowBrightnessTransitionPoint() { + if (mLowBrightnessData == null) { + return PowerManager.BRIGHTNESS_MIN; + } + return mLowBrightnessData.mTransitionPoint; + } + + /** + * + * @return HAL backlight mapping to framework brightness + */ private Spline getBacklightToBrightnessSpline() { if (mLowBrightnessData != null) { return mLowBrightnessData.mBacklightToBrightness; @@ -1133,7 +1154,12 @@ public class DisplayDeviceConfig { return mBacklightToNitsSpline.interpolate(backlight); } - private float getBacklightFromNits(float nits) { + /** + * + * @param nits - display brightness + * @return corresponding HAL backlight value + */ + public float getBacklightFromNits(float nits) { if (mLowBrightnessData != null) { return mLowBrightnessData.mNitsToBacklight.interpolate(nits); } @@ -1148,6 +1174,18 @@ public class DisplayDeviceConfig { } /** + * + * @param lux - ambient brightness + * @return minimum allowed nits, given the lux. + */ + public float getMinNitsFromLux(float lux) { + if (mLowBrightnessData == null) { + return INVALID_NITS; + } + return mLowBrightnessData.mMinLuxToNits.interpolate(lux); + } + + /** * @return true if there is sdrHdrRatioMap, false otherwise. */ public boolean hasSdrToHdrRatioSpline() { diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 90ad8c02c29c..cb07cf47413a 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -1426,12 +1426,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call && (mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged() || userSetBrightnessChanged); - mBrightnessRangeController.setAutoBrightnessEnabled( - mAutomaticBrightnessStrategy.isAutoBrightnessEnabled() + final int autoBrightnessState = mAutomaticBrightnessStrategy.isAutoBrightnessEnabled() ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED : mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff() ? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE - : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED); + : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED; + + mBrightnessRangeController.setAutoBrightnessEnabled(autoBrightnessState); + mBrightnessClamperController.setAutoBrightnessState(autoBrightnessState); boolean updateScreenBrightnessSetting = displayBrightnessState.shouldUpdateScreenBrightnessSetting(); diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java index d8a45009f236..9c7504db0cf0 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java @@ -66,6 +66,7 @@ public class BrightnessClamperController { private float mCustomAnimationRate = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; @Nullable private Type mClamperType = null; + private int mAutoBrightnessState = -1; private boolean mClamperApplied = false; @@ -94,7 +95,8 @@ public class BrightnessClamperController { mClampers = injector.getClampers(handler, clamperChangeListenerInternal, data, flags, context); - mModifiers = injector.getModifiers(flags, context, handler, clamperChangeListener); + mModifiers = injector.getModifiers(flags, context, handler, clamperChangeListener, + data.mDisplayDeviceConfig); mOnPropertiesChangedListener = properties -> mClampers.forEach(BrightnessClamper::onDeviceConfigChanged); start(); @@ -197,6 +199,19 @@ public class BrightnessClamperController { mModifiers.forEach(modifier -> modifier.onAmbientLuxChange(ambientLux)); } + /** + * Sets the autobrightness state for clampers that need to be aware of the state. + * @param state autobrightness state + */ + public void setAutoBrightnessState(int state) { + if (state == mAutoBrightnessState) { + return; + } + mModifiers.forEach(modifier -> modifier.setAutoBrightnessState(state)); + mAutoBrightnessState = state; + recalculateBrightnessCap(); + } + // Called in DisplayControllerHandler private void recalculateBrightnessCap() { float brightnessCap = PowerManager.BRIGHTNESS_MAX; @@ -265,12 +280,14 @@ public class BrightnessClamperController { } List<BrightnessStateModifier> getModifiers(DisplayManagerFlags flags, Context context, - Handler handler, ClamperChangeListener listener) { + Handler handler, ClamperChangeListener listener, + DisplayDeviceConfig displayDeviceConfig) { List<BrightnessStateModifier> modifiers = new ArrayList<>(); modifiers.add(new DisplayDimModifier(context)); modifiers.add(new BrightnessLowPowerModeModifier()); if (flags.isEvenDimmerEnabled()) { - modifiers.add(new BrightnessLowLuxModifier(handler, listener, context)); + modifiers.add(new BrightnessLowLuxModifier(handler, listener, context, + displayDeviceConfig)); } return modifiers; } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java index a91bb59b0bc0..7f88c3029820 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java @@ -16,13 +16,14 @@ package com.android.server.display.brightness.clamper; +import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED; + import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.hardware.display.DisplayManagerInternal; import android.net.Uri; import android.os.Handler; -import android.os.PowerManager; import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; @@ -30,6 +31,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.display.BrightnessSynchronizer; import com.android.server.display.DisplayBrightnessState; +import com.android.server.display.DisplayDeviceConfig; import com.android.server.display.brightness.BrightnessReason; import com.android.server.display.utils.DebugUtils; @@ -45,19 +47,23 @@ public class BrightnessLowLuxModifier extends BrightnessModifier { // 'adb shell setprop persist.log.tag.BrightnessLowLuxModifier DEBUG && adb reboot' private static final String TAG = "BrightnessLowLuxModifier"; private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); - private static final float MIN_NITS = 2.0f; + private static final float MIN_NITS_DEFAULT = 0.2f; private final SettingsObserver mSettingsObserver; private final ContentResolver mContentResolver; private final Handler mHandler; private final BrightnessClamperController.ClamperChangeListener mChangeListener; private int mReason; private float mBrightnessLowerBound; + private float mMinNitsAllowed; private boolean mIsActive; + private boolean mAutoBrightnessEnabled; private float mAmbientLux; + private final DisplayDeviceConfig mDisplayDeviceConfig; @VisibleForTesting BrightnessLowLuxModifier(Handler handler, - BrightnessClamperController.ClamperChangeListener listener, Context context) { + BrightnessClamperController.ClamperChangeListener listener, Context context, + DisplayDeviceConfig displayDeviceConfig) { super(); mChangeListener = listener; @@ -67,6 +73,8 @@ public class BrightnessLowLuxModifier extends BrightnessModifier { mHandler.post(() -> { start(); }); + + mDisplayDeviceConfig = displayDeviceConfig; } /** @@ -78,41 +86,45 @@ public class BrightnessLowLuxModifier extends BrightnessModifier { int userId = UserHandle.USER_CURRENT; float settingNitsLowerBound = Settings.Secure.getFloatForUser( mContentResolver, Settings.Secure.EVEN_DIMMER_MIN_NITS, - /* def= */ MIN_NITS, userId); + /* def= */ MIN_NITS_DEFAULT, userId); boolean isActive = Settings.Secure.getFloatForUser(mContentResolver, Settings.Secure.EVEN_DIMMER_ACTIVATED, - /* def= */ 0, userId) == 1.0f; - - // TODO: luxBasedNitsLowerBound = mMinLuxToNitsSpline(currentLux); - float luxBasedNitsLowerBound = 2.0f; - - final float nitsLowerBound = isActive ? Math.max(settingNitsLowerBound, - luxBasedNitsLowerBound) : MIN_NITS; - - final int reason = settingNitsLowerBound > luxBasedNitsLowerBound - ? BrightnessReason.MODIFIER_MIN_USER_SET_LOWER_BOUND - : BrightnessReason.MODIFIER_MIN_LUX; - - // TODO: brightnessLowerBound = nitsToBrightnessSpline(nitsLowerBound); - final float brightnessLowerBound = PowerManager.BRIGHTNESS_MIN; + /* def= */ 0, userId) == 1.0f && mAutoBrightnessEnabled; + + float luxBasedNitsLowerBound = mDisplayDeviceConfig.getMinNitsFromLux(mAmbientLux); + + final int reason; + float minNitsAllowed = -1f; // undefined, if setting is off. + final float minBrightnessAllowed; + + if (isActive) { + minNitsAllowed = Math.max(settingNitsLowerBound, + luxBasedNitsLowerBound); + minBrightnessAllowed = getBrightnessFromNits(minNitsAllowed); + reason = settingNitsLowerBound > luxBasedNitsLowerBound + ? BrightnessReason.MODIFIER_MIN_USER_SET_LOWER_BOUND + : BrightnessReason.MODIFIER_MIN_LUX; + } else { + minBrightnessAllowed = mDisplayDeviceConfig.getLowBrightnessTransitionPoint(); + reason = 0; + } - if (mBrightnessLowerBound != brightnessLowerBound + if (mBrightnessLowerBound != minBrightnessAllowed || mReason != reason || mIsActive != isActive) { mIsActive = isActive; mReason = reason; if (DEBUG) { Slog.i(TAG, "isActive: " + isActive - + ", brightnessLowerBound: " + brightnessLowerBound + + ", minBrightnessAllowed: " + minBrightnessAllowed + ", mAmbientLux: " + mAmbientLux - + ", mReason: " + ( - mReason == BrightnessReason.MODIFIER_MIN_USER_SET_LOWER_BOUND ? "minSetting" - : "lux") - + ", nitsLowerBound: " + nitsLowerBound + + ", mReason: " + (mReason) + + ", minNitsAllowed: " + minNitsAllowed ); } - mBrightnessLowerBound = brightnessLowerBound; + mMinNitsAllowed = minNitsAllowed; + mBrightnessLowerBound = minBrightnessAllowed; mChangeListener.onChanged(); } } @@ -177,11 +189,23 @@ public class BrightnessLowLuxModifier extends BrightnessModifier { } @Override + public void setAutoBrightnessState(int state) { + mAutoBrightnessEnabled = state == AUTO_BRIGHTNESS_ENABLED; + } + + @Override public void dump(PrintWriter pw) { pw.println("BrightnessLowLuxModifier:"); pw.println(" mIsActive=" + mIsActive); pw.println(" mBrightnessLowerBound=" + mBrightnessLowerBound); pw.println(" mReason=" + mReason); + pw.println(" mAmbientLux=" + mAmbientLux); + pw.println(" mMinNitsAllowed=" + mMinNitsAllowed); + } + + private float getBrightnessFromNits(float nits) { + return mDisplayDeviceConfig.getBrightnessFromBacklight( + mDisplayDeviceConfig.getBacklightFromNits(nits)); } private final class SettingsObserver extends ContentObserver { diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessModifier.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessModifier.java index 2a3dd8752615..db5a524da71d 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessModifier.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessModifier.java @@ -73,4 +73,9 @@ abstract class BrightnessModifier implements BrightnessStateModifier { public void onAmbientLuxChange(float ambientLux) { // do nothing } + + @Override + public void setAutoBrightnessState(int state) { + // do nothing + } } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessStateModifier.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessStateModifier.java index 22342581fa8b..1606159cb247 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessStateModifier.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessStateModifier.java @@ -48,4 +48,10 @@ public interface BrightnessStateModifier { * @param ambientLux current debounced lux. */ void onAmbientLuxChange(float ambientLux); + + /** + * Sets the autobrightness state for clampers that need to be aware of the state. + * @param state autobrightness state + */ + void setAutoBrightnessState(int state); } diff --git a/services/core/java/com/android/server/display/config/LowBrightnessData.java b/services/core/java/com/android/server/display/config/LowBrightnessData.java index aa82533bf6a7..1a4e807fece6 100644 --- a/services/core/java/com/android/server/display/config/LowBrightnessData.java +++ b/services/core/java/com/android/server/display/config/LowBrightnessData.java @@ -66,11 +66,13 @@ public class LowBrightnessData { * Spline, mapping between backlight and brightness */ public final Spline mBacklightToBrightness; + public final Spline mMinLuxToNits; @VisibleForTesting public LowBrightnessData(float transitionPoint, float[] nits, float[] backlight, float[] brightness, Spline backlightToNits, - Spline nitsToBacklight, Spline brightnessToBacklight, Spline backlightToBrightness) { + Spline nitsToBacklight, Spline brightnessToBacklight, Spline backlightToBrightness, + Spline minLuxToNits) { mTransitionPoint = transitionPoint; mNits = nits; mBacklight = backlight; @@ -79,6 +81,7 @@ public class LowBrightnessData { mNitsToBacklight = nitsToBacklight; mBrightnessToBacklight = brightnessToBacklight; mBacklightToBrightness = backlightToBrightness; + mMinLuxToNits = minLuxToNits; } @Override @@ -92,6 +95,7 @@ public class LowBrightnessData { + ", mNitsToBacklight: " + mNitsToBacklight + ", mBrightnessToBacklight: " + mBrightnessToBacklight + ", mBacklightToBrightness: " + mBacklightToBrightness + + ", mMinLuxToNits: " + mMinLuxToNits + "} "; } @@ -132,11 +136,40 @@ public class LowBrightnessData { brightness[i] = brightnessList.get(i); } + final NitsMap map = lbm.getLuxToMinimumNitsMap(); + if (map == null) { + Slog.e(TAG, "Invalid min lux to nits mapping"); + return null; + } + final List<Point> points = map.getPoint(); + final int size = points.size(); + + float[] minLux = new float[size]; + float[] minNits = new float[size]; + + int i = 0; + for (Point point : points) { + minLux[i] = point.getValue().floatValue(); + minNits[i] = point.getNits().floatValue(); + if (i > 0) { + if (minLux[i] < minLux[i - 1]) { + Slog.e(TAG, "minLuxToNitsSpline must be non-decreasing, ignoring rest " + + " of configuration. Value: " + minLux[i] + " < " + minLux[i - 1]); + } + if (minNits[i] < minNits[i - 1]) { + Slog.e(TAG, "minLuxToNitsSpline must be non-decreasing, ignoring rest " + + " of configuration. Nits: " + minNits[i] + " < " + minNits[i - 1]); + } + } + ++i; + } + return new LowBrightnessData(transitionPoints, nits, backlight, brightness, Spline.createSpline(backlight, nits), Spline.createSpline(nits, backlight), Spline.createSpline(brightness, backlight), - Spline.createSpline(backlight, brightness) - ); + Spline.createSpline(backlight, brightness), + Spline.createSpline(minLux, minNits) + ); } } diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd index 1f5451813dae..912ff4ae2022 100644 --- a/services/core/xsd/display-device-config/display-device-config.xsd +++ b/services/core/xsd/display-device-config/display-device-config.xsd @@ -232,6 +232,9 @@ </xs:element> <xs:element name="brightness" type="xs:float" maxOccurs="unbounded"> </xs:element> + <!-- Mapping of current lux to minimum allowed nits values. --> + <xs:element name="luxToMinimumNitsMap" type="nitsMap" maxOccurs="1"> + </xs:element> </xs:sequence> <xs:attribute name="enabled" type="xs:boolean" use="optional"/> </xs:complexType> diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt index c39c3d7ee7c6..3c708900c64e 100644 --- a/services/core/xsd/display-device-config/schema/current.txt +++ b/services/core/xsd/display-device-config/schema/current.txt @@ -255,9 +255,11 @@ package com.android.server.display.config { method public java.util.List<java.lang.Float> getBacklight(); method public java.util.List<java.lang.Float> getBrightness(); method public boolean getEnabled(); + method public com.android.server.display.config.NitsMap getLuxToMinimumNitsMap(); method public java.util.List<java.lang.Float> getNits(); method public java.math.BigDecimal getTransitionPoint(); method public void setEnabled(boolean); + method public void setLuxToMinimumNitsMap(com.android.server.display.config.NitsMap); method public void setTransitionPoint(java.math.BigDecimal); } diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java index 73a2f655da8d..5a022c0f5d27 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java @@ -1651,6 +1651,17 @@ public final class DisplayDeviceConfigTest { + " <brightness>0.1</brightness>\n" + " <brightness>0.5</brightness>\n" + " <brightness>1.0</brightness>\n" + + " <luxToMinimumNitsMap>\n" + + " <point>\n" + + " <value>10</value> <nits>0.3</nits>\n" + + " </point>\n" + + " <point>\n" + + " <value>50</value> <nits>0.7</nits>\n" + + " </point>\n" + + " <point>\n" + + " <value>100</value> <nits>1.0</nits>\n" + + " </point>\n" + + " </luxToMinimumNitsMap>\n" + "</lowBrightness>"; } diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java index 5294943fa387..5487bc53ffce 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java @@ -35,6 +35,7 @@ import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.server.display.DisplayBrightnessState; +import com.android.server.display.DisplayDeviceConfig; import com.android.server.display.brightness.BrightnessReason; import com.android.server.display.feature.DeviceConfigParameterProvider; import com.android.server.display.feature.DisplayManagerFlags; @@ -280,7 +281,8 @@ public class BrightnessClamperControllerTest { @Override List<BrightnessStateModifier> getModifiers(DisplayManagerFlags flags, Context context, - Handler handler, BrightnessClamperController.ClamperChangeListener listener) { + Handler handler, BrightnessClamperController.ClamperChangeListener listener, + DisplayDeviceConfig displayDeviceConfig) { return mModifiers; } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt index e4a7d982514f..749c400f819e 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt @@ -15,13 +15,18 @@ */ package com.android.server.display.brightness.clamper -import android.os.PowerManager import android.os.UserHandle +import android.platform.test.annotations.RequiresFlagsEnabled import android.provider.Settings import android.testing.TestableContext import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED +import com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED +import com.android.server.display.DisplayDeviceConfig import com.android.server.display.brightness.BrightnessReason +import com.android.server.display.feature.flags.Flags import com.android.server.testutils.TestHandler +import com.android.server.testutils.whenever import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -32,71 +37,197 @@ private const val userId = UserHandle.USER_CURRENT class BrightnessLowLuxModifierTest { private var mockClamperChangeListener = - mock<BrightnessClamperController.ClamperChangeListener>() + mock<BrightnessClamperController.ClamperChangeListener>() val context = TestableContext( - InstrumentationRegistry.getInstrumentation().getContext()) + InstrumentationRegistry.getInstrumentation().getContext()) private val testHandler = TestHandler(null) private lateinit var modifier: BrightnessLowLuxModifier + private var mockDisplayDeviceConfig = mock<DisplayDeviceConfig>() + + private val LOW_LUX_BRIGHTNESS = 0.1f + private val TRANSITION_POINT = 0.25f + private val NORMAL_RANGE_BRIGHTNESS = 0.3f + @Before fun setUp() { - modifier = BrightnessLowLuxModifier(testHandler, mockClamperChangeListener, context) + modifier = + BrightnessLowLuxModifier(testHandler, + mockClamperChangeListener, + context, + mockDisplayDeviceConfig) + + // values below transition point (even dimmer range) + // nits: 0.1 -> backlight 0.02 -> brightness -> 0.1 + whenever(mockDisplayDeviceConfig.getBacklightFromNits(/* nits= */ 1.0f)) + .thenReturn(0.02f) + whenever(mockDisplayDeviceConfig.getBrightnessFromBacklight(/* backlight = */ 0.02f)) + .thenReturn(LOW_LUX_BRIGHTNESS) + + // values above transition point (noraml range) + // nits: 10 -> backlight 0.2 -> brightness -> 0.3 + whenever(mockDisplayDeviceConfig.getBacklightFromNits(/* nits= */ 2f)) + .thenReturn(0.15f) + whenever(mockDisplayDeviceConfig.getBrightnessFromBacklight(/* backlight = */ 0.15f)) + .thenReturn(0.24f) + + // values above transition point (normal range) + // nits: 10 -> backlight 0.2 -> brightness -> 0.3 + whenever(mockDisplayDeviceConfig.getBacklightFromNits(/* nits= */ 10f)) + .thenReturn(0.2f) + whenever(mockDisplayDeviceConfig.getBrightnessFromBacklight(/* backlight = */ 0.2f)) + .thenReturn(NORMAL_RANGE_BRIGHTNESS) + + // min nits when lux of 400 + whenever(mockDisplayDeviceConfig.getMinNitsFromLux(/* lux= */ 400f)) + .thenReturn(1.0f) + + + whenever(mockDisplayDeviceConfig.lowBrightnessTransitionPoint).thenReturn(TRANSITION_POINT) + testHandler.flush() } @Test - fun testThrottlingBounds() { + fun testSettingOffDisablesModifier() { + // test transition point ensures brightness doesn't drop when setting is off. Settings.Secure.putIntForUser(context.contentResolver, - Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, userId) // true - Settings.Secure.putFloatForUser(context.contentResolver, - Settings.Secure.EVEN_DIMMER_MIN_NITS, 0.7f, userId) + Settings.Secure.EVEN_DIMMER_ACTIVATED, 0, userId) + modifier.setAutoBrightnessState(AUTO_BRIGHTNESS_ENABLED) modifier.recalculateLowerBound() testHandler.flush() - assertThat(modifier.isActive).isTrue() + assertThat(modifier.brightnessLowerBound).isEqualTo(TRANSITION_POINT) + assertThat(modifier.brightnessReason).isEqualTo(0) // no reason - ie off + modifier.onAmbientLuxChange(3000.0f) + testHandler.flush() + assertThat(modifier.isActive).isFalse() + assertThat(modifier.brightnessLowerBound).isEqualTo(TRANSITION_POINT) + assertThat(modifier.brightnessReason).isEqualTo(0) // no reason - ie off + } - // TODO: code currently returns MIN/MAX; update with lux values - assertThat(modifier.brightnessLowerBound).isEqualTo(PowerManager.BRIGHTNESS_MIN) + @Test + @RequiresFlagsEnabled(Flags.FLAG_EVEN_DIMMER) + fun testLuxRestrictsBrightnessRange() { + // test that high lux prevents low brightness range. + Settings.Secure.putIntForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, userId) + Settings.Secure.putFloatForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_MIN_NITS, 0.1f, userId) + modifier.setAutoBrightnessState(AUTO_BRIGHTNESS_ENABLED) + modifier.onAmbientLuxChange(400.0f) + testHandler.flush() + + assertThat(modifier.isActive).isTrue() + // Test restriction from lux setting + assertThat(modifier.brightnessReason).isEqualTo(BrightnessReason.MODIFIER_MIN_LUX) + assertThat(modifier.brightnessLowerBound).isEqualTo(LOW_LUX_BRIGHTNESS) } @Test - fun testGetReason_UserSet() { + @RequiresFlagsEnabled(Flags.FLAG_EVEN_DIMMER) + fun testUserRestrictsBrightnessRange() { + // test that user minimum nits setting prevents low brightness range. Settings.Secure.putIntForUser(context.contentResolver, - Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, userId) + Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, userId) Settings.Secure.putFloatForUser(context.contentResolver, - Settings.Secure.EVEN_DIMMER_MIN_NITS, 30.0f, userId) + Settings.Secure.EVEN_DIMMER_MIN_NITS, 10.0f, userId) + modifier.setAutoBrightnessState(AUTO_BRIGHTNESS_ENABLED) modifier.recalculateLowerBound() testHandler.flush() - assertThat(modifier.isActive).isTrue() // Test restriction from user setting + assertThat(modifier.isActive).isTrue() assertThat(modifier.brightnessReason) .isEqualTo(BrightnessReason.MODIFIER_MIN_USER_SET_LOWER_BOUND) + assertThat(modifier.brightnessLowerBound).isEqualTo(NORMAL_RANGE_BRIGHTNESS) } @Test - fun testGetReason_Lux() { + @RequiresFlagsEnabled(Flags.FLAG_EVEN_DIMMER) + fun testOnToOff() { + // test that high lux prevents low brightness range. Settings.Secure.putIntForUser(context.contentResolver, - Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, userId) + Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, userId) // on Settings.Secure.putFloatForUser(context.contentResolver, - Settings.Secure.EVEN_DIMMER_MIN_NITS, 0.0f, userId) - modifier.onAmbientLuxChange(3000.0f) + Settings.Secure.EVEN_DIMMER_MIN_NITS, 1.0f, userId) + modifier.setAutoBrightnessState(AUTO_BRIGHTNESS_ENABLED) + modifier.onAmbientLuxChange(400.0f) testHandler.flush() + assertThat(modifier.isActive).isTrue() + // Test restriction from lux setting + assertThat(modifier.brightnessReason).isEqualTo(BrightnessReason.MODIFIER_MIN_LUX) + assertThat(modifier.brightnessLowerBound).isEqualTo(LOW_LUX_BRIGHTNESS) + + Settings.Secure.putIntForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_ACTIVATED, 0, userId) // off + + modifier.recalculateLowerBound() + testHandler.flush() + + assertThat(modifier.isActive).isFalse() + assertThat(modifier.brightnessLowerBound).isEqualTo(TRANSITION_POINT) + assertThat(modifier.brightnessReason).isEqualTo(0) // no reason - ie off + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_EVEN_DIMMER) + fun testOffToOn() { + // test that high lux prevents low brightness range. + Settings.Secure.putIntForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_ACTIVATED, 0, userId) // off + Settings.Secure.putFloatForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_MIN_NITS, 1.0f, userId) + modifier.setAutoBrightnessState(AUTO_BRIGHTNESS_ENABLED) + modifier.onAmbientLuxChange(400.0f) + testHandler.flush() + + assertThat(modifier.isActive).isFalse() + assertThat(modifier.brightnessLowerBound).isEqualTo(TRANSITION_POINT) + assertThat(modifier.brightnessReason).isEqualTo(0) // no reason - ie off + + + + Settings.Secure.putIntForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, userId) // on + modifier.recalculateLowerBound() + testHandler.flush() + assertThat(modifier.isActive).isTrue() // Test restriction from lux setting assertThat(modifier.brightnessReason).isEqualTo(BrightnessReason.MODIFIER_MIN_LUX) + assertThat(modifier.brightnessLowerBound).isEqualTo(LOW_LUX_BRIGHTNESS) } @Test - fun testSettingOffDisablesModifier() { + @RequiresFlagsEnabled(Flags.FLAG_EVEN_DIMMER) + fun testDisabledWhenAutobrightnessIsOff() { + // test that high lux prevents low brightness range. Settings.Secure.putIntForUser(context.contentResolver, - Settings.Secure.EVEN_DIMMER_ACTIVATED, 0, userId) - assertThat(modifier.brightnessLowerBound).isEqualTo(PowerManager.BRIGHTNESS_MIN) - modifier.onAmbientLuxChange(3000.0f) + Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, userId) // on + Settings.Secure.putFloatForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_MIN_NITS, 1.0f, userId) + + modifier.setAutoBrightnessState(AUTO_BRIGHTNESS_ENABLED) + modifier.onAmbientLuxChange(400.0f) testHandler.flush() + + assertThat(modifier.isActive).isTrue() + // Test restriction from lux setting + assertThat(modifier.brightnessReason).isEqualTo(BrightnessReason.MODIFIER_MIN_LUX) + assertThat(modifier.brightnessLowerBound).isEqualTo(LOW_LUX_BRIGHTNESS) + + + modifier.setAutoBrightnessState(AUTO_BRIGHTNESS_DISABLED) + modifier.onAmbientLuxChange(400.0f) + testHandler.flush() + assertThat(modifier.isActive).isFalse() - assertThat(modifier.brightnessLowerBound).isEqualTo(PowerManager.BRIGHTNESS_MIN) + // Test restriction from lux setting + assertThat(modifier.brightnessReason).isEqualTo(0) + assertThat(modifier.brightnessLowerBound).isEqualTo(TRANSITION_POINT) } } + |