diff options
| author | 2021-11-10 16:48:04 +0000 | |
|---|---|---|
| committer | 2021-11-24 17:45:26 +0000 | |
| commit | f0c4a778b098b4128a679b76b3ec2b9bc94f3e53 (patch) | |
| tree | cf584e12d88ddd80b7e11502f7eeda932d0aaa0e | |
| parent | 2f9d26218e83806ae877fb1b5ff64fbadb245801 (diff) | |
Add idle screen brightness mapping to DPC
Add idle screen brightness nits mapping to config.xml.
Also add flag to enable idle screen brightness mode.
Add idle screen brightness mapping to DPC dumpsys.
Bug: 205685949
Test: adb shell dumpsys display | grep -A10 Idle
Test: atest BrightnessMappingStrategyTest
Change-Id: Ifa18b835c05c28c060c46c77aeaeca457a2b12e3
5 files changed, 205 insertions, 19 deletions
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index fceb951a7923..bbc9cdeb7a7f 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1464,6 +1464,30 @@ <integer-array name="config_autoBrightnessLevels"> </integer-array> + <!-- Array of light sensor lux values to define our levels for auto backlight brightness + support whilst in idle mode. + The N entries of this array define N + 1 control points as follows: + (1-based arrays) + + Point 1: (0, value[1]): lux <= 0 + Point 2: (level[1], value[2]): 0 < lux <= level[1] + Point 3: (level[2], value[3]): level[2] < lux <= level[3] + ... + Point N+1: (level[N], value[N+1]): level[N] < lux + + The control points must be strictly increasing. Each control point + corresponds to an entry in the brightness backlight values arrays. + For example, if lux == level[1] (first element of the levels array) + then the brightness will be determined by value[2] (second element + of the brightness values array). + + Spline interpolation is used to determine the auto-brightness + backlight values for lux levels between these control points. + + Must be overridden in platform specific overlays --> + <integer-array name="config_autoBrightnessLevelsIdle"> + </integer-array> + <!-- Timeout (in milliseconds) after which we remove the effects any user interactions might've had on the brightness mapping. This timeout doesn't start until we transition to a non-interactive display policy so that we don't reset while users are using their devices, @@ -1487,6 +1511,10 @@ <integer-array name="config_autoBrightnessLcdBacklightValues_doze"> </integer-array> + <!-- Enables idle screen brightness mode on this device. + If this is true, config_autoBrightnessDisplayValuesNitsIdle must be defined. --> + <bool name="config_enableIdleScreenBrightnessMode">false</bool> + <!-- Array of desired screen brightness in nits corresponding to the lux values in the config_autoBrightnessLevels array. As with config_screenBrightnessMinimumNits and config_screenBrightnessMaximumNits, the display brightness is defined as the measured @@ -1503,6 +1531,13 @@ <array name="config_autoBrightnessDisplayValuesNits"> </array> + <!-- Array of desired screen brightness in nits for idle screen brightness mode. + This array should meet the same requirements as config_autoBrightnessDisplayValuesNits. + This array also corresponds to the lux values given in config_autoBrightnessLevelsIdle. + In order to activate this mode, config_enableIdleScreenBrightnessMode must be true. --> + <array name="config_autoBrightnessDisplayValuesNitsIdle"> + </array> + <!-- Array of output values for button backlight corresponding to the luX values in the config_autoBrightnessLevels array. This array should have size one greater than the size of the config_autoBrightnessLevels array. diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f166b733042f..168e0f135260 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1897,6 +1897,7 @@ <java-symbol type="array" name="config_autoBrightnessLcdBacklightValues" /> <java-symbol type="array" name="config_autoBrightnessLcdBacklightValues_doze" /> <java-symbol type="array" name="config_autoBrightnessLevels" /> + <java-symbol type="array" name="config_autoBrightnessLevelsIdle" /> <java-symbol type="array" name="config_ambientThresholdLevels" /> <java-symbol type="array" name="config_ambientBrighteningThresholds" /> <java-symbol type="array" name="config_ambientDarkeningThresholds" /> @@ -3782,7 +3783,9 @@ <java-symbol type="bool" name="config_fillMainBuiltInDisplayCutout" /> <java-symbol type="drawable" name="ic_logout" /> + <java-symbol type="bool" name="config_enableIdleScreenBrightnessMode" /> <java-symbol type="array" name="config_autoBrightnessDisplayValuesNits" /> + <java-symbol type="array" name="config_autoBrightnessDisplayValuesNitsIdle" /> <java-symbol type="array" name="config_screenBrightnessBacklight" /> <java-symbol type="array" name="config_screenBrightnessNits" /> diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java index 74a21a733fb9..beb4d5b28d5c 100644 --- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java +++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java @@ -60,17 +60,62 @@ public abstract class BrightnessMappingStrategy { private static final Plog PLOG = Plog.createSystemPlog(TAG); + /** + * Creates a BrightnessMappingStrategy for active (normal) mode. + * @param resources + * @param displayDeviceConfig + * @return the BrightnessMappingStrategy + */ @Nullable public static BrightnessMappingStrategy create(Resources resources, DisplayDeviceConfig displayDeviceConfig) { + return create(resources, displayDeviceConfig, /* isForIdleMode= */ false); + } + + /** + * Creates a BrightnessMappingStrategy for idle screen brightness mode. + * @param resources + * @param displayDeviceConfig + * @return the BrightnessMappingStrategy + */ + @Nullable + public static BrightnessMappingStrategy createForIdleMode(Resources resources, + DisplayDeviceConfig displayDeviceConfig) { + return create(resources, displayDeviceConfig, /* isForIdleMode= */ true); + } + + /** + * Creates a BrightnessMapping strategy for either active or idle screen brightness mode. + * We do not create a simple mapping strategy for idle mode. + * + * @param resources + * @param displayDeviceConfig + * @param isForIdleMode determines whether the configurations loaded are for idle screen + * brightness mode or active screen brightness mode. + * @return the BrightnessMappingStrategy + */ + @Nullable + private static BrightnessMappingStrategy create(Resources resources, + DisplayDeviceConfig displayDeviceConfig, boolean isForIdleMode) { + + // Display independent, mode dependent values + float[] brightnessLevelsNits; + float[] luxLevels; + if (isForIdleMode) { + brightnessLevelsNits = getFloatArray(resources.obtainTypedArray( + com.android.internal.R.array.config_autoBrightnessDisplayValuesNitsIdle)); + luxLevels = getLuxLevels(resources.getIntArray( + com.android.internal.R.array.config_autoBrightnessLevelsIdle)); + } else { + brightnessLevelsNits = getFloatArray(resources.obtainTypedArray( + com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)); + luxLevels = getLuxLevels(resources.getIntArray( + com.android.internal.R.array.config_autoBrightnessLevels)); + } - // Display independent values - float[] luxLevels = getLuxLevels(resources.getIntArray( - com.android.internal.R.array.config_autoBrightnessLevels)); + // Display independent, mode independent values int[] brightnessLevelsBacklight = resources.getIntArray( com.android.internal.R.array.config_autoBrightnessLcdBacklightValues); - float[] brightnessLevelsNits = getFloatArray(resources.obtainTypedArray( - com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)); float autoBrightnessAdjustmentMaxGamma = resources.getFraction( com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma, 1, 1); @@ -91,7 +136,7 @@ public abstract class BrightnessMappingStrategy { builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO); return new PhysicalMappingStrategy(builder.build(), nitsRange, brightnessRange, autoBrightnessAdjustmentMaxGamma); - } else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) { + } else if (isValidMapping(luxLevels, brightnessLevelsBacklight) && !isForIdleMode) { return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight, autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout); } else { diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 2f3342f20fcb..8f6d20dfcf96 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -54,6 +54,7 @@ import android.util.Slog; import android.util.TimeUtils; import android.view.Display; +import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.display.BrightnessSynchronizer; @@ -384,8 +385,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private Sensor mLightSensor; // The mapper between ambient lux, display backlight values, and display brightness. + // This mapper holds the current one that is being used. We will switch between the idle + // mapper and active mapper here. @Nullable - private BrightnessMappingStrategy mBrightnessMapper; + private BrightnessMappingStrategy mCurrentBrightnessMapper; + + // Mapper used for active (normal) screen brightness mode + @Nullable + private BrightnessMappingStrategy mInteractiveModeBrightnessMapper; + // Mapper used for idle screen brightness mode + @Nullable + private BrightnessMappingStrategy mIdleModeBrightnessMapper; // The current brightness configuration. @Nullable @@ -406,7 +416,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // The temporary screen brightness. Typically set when a user is interacting with the // brightness slider but hasn't settled on a choice yet. Set to - // PowerManager.BRIGHNTESS_INVALID_FLOAT when there's no temporary brightness set. + // PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary brightness set. private float mTemporaryScreenBrightness; // The current screen brightness while in VR mode. @@ -595,7 +605,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } private void handleRbcChanged(boolean strengthChanged, boolean justActivated) { - if (mBrightnessMapper == null) { + if (mCurrentBrightnessMapper == null) { Log.w(TAG, "No brightness mapping available to recalculate splines"); return; } @@ -604,7 +614,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call for (int i = 0; i < mNitsRange.length; i++) { adjustedNits[i] = mCdsi.getReduceBrightColorsAdjustedBrightnessNits(mNitsRange[i]); } - mBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), adjustedNits); + mCurrentBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), + adjustedNits); mPendingRbcOnOrChanged = strengthChanged || justActivated; @@ -862,9 +873,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call return; } - mBrightnessMapper = BrightnessMappingStrategy.create(resources, mDisplayDeviceConfig); + final boolean isIdleScreenBrightnessEnabled = resources.getBoolean( + R.bool.config_enableIdleScreenBrightnessMode); + mInteractiveModeBrightnessMapper = BrightnessMappingStrategy.create(resources, + mDisplayDeviceConfig); + if (isIdleScreenBrightnessEnabled) { + mIdleModeBrightnessMapper = BrightnessMappingStrategy.createForIdleMode(resources, + mDisplayDeviceConfig); + } + mCurrentBrightnessMapper = mInteractiveModeBrightnessMapper; - if (mBrightnessMapper != null) { + if (mCurrentBrightnessMapper != null) { final float dozeScaleFactor = resources.getFraction( com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor, 1, 1); @@ -915,7 +934,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mAutomaticBrightnessController.stop(); } mAutomaticBrightnessController = new AutomaticBrightnessController(this, - handler.getLooper(), mSensorManager, mLightSensor, mBrightnessMapper, + handler.getLooper(), mSensorManager, mLightSensor, mCurrentBrightnessMapper, lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate, initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce, @@ -2138,8 +2157,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } private float convertToNits(float brightness) { - if (mBrightnessMapper != null) { - return mBrightnessMapper.convertToNits(brightness); + if (mCurrentBrightnessMapper != null) { + return mCurrentBrightnessMapper.convertToNits(brightness); } else { return -1.0f; } @@ -2291,6 +2310,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pw.println(" mReportedToPolicy=" + reportedToPolicyToString(mReportedScreenStateToPolicy)); + if (mIdleModeBrightnessMapper != null) { + pw.println(" mIdleModeBrightnessMapper= "); + mIdleModeBrightnessMapper.dump(pw); + } + if (mScreenBrightnessRampAnimator != null) { pw.println(" mScreenBrightnessRampAnimator.isAnimating()=" + mScreenBrightnessRampAnimator.isAnimating()); diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java index 285806b5dcd7..c6757261ce42 100644 --- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java +++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java @@ -59,6 +59,20 @@ public class BrightnessMappingStrategyTest { 5000 }; + private static final int[] LUX_LEVELS_IDLE = { + 0, + 10, + 40, + 80, + 200, + 655, + 1200, + 2500, + 4400, + 8000, + 10000 + }; + private static final float[] DISPLAY_LEVELS_NITS = { 13.25f, 54.0f, @@ -73,6 +87,20 @@ public class BrightnessMappingStrategyTest { 478.5f, }; + private static final float[] DISPLAY_LEVELS_NITS_IDLE = { + 23.25f, + 64.0f, + 88.85f, + 115.02f, + 142.7f, + 180.12f, + 222.1f, + 275.2f, + 345.8f, + 425.2f, + 468.5f, + }; + private static final int[] DISPLAY_LEVELS_BACKLIGHT = { 9, 30, @@ -88,7 +116,6 @@ public class BrightnessMappingStrategyTest { }; private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f }; - private static final float[] DISPLAY_LEVELS_RANGE_NITS = { 13.25f, 478.5f }; private static final float[] BACKLIGHT_RANGE_ZERO_TO_ONE = { 0.0f, 1.0f }; private static final float[] DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT = { 0.03149606299f, 1.0f }; @@ -118,6 +145,8 @@ public class BrightnessMappingStrategyTest { new float[] { 0.0f, 100.0f, 1000.0f, 2500.0f, 4000.0f, 4900.0f, 5000.0f }, new float[] { 0.0475f, 0.0475f, 0.2225f, 0.5140f, 0.8056f, 0.9805f, 1.0f }); + private static final float TOLERANCE = 0.0001f; + @Test public void testSimpleStrategyMappingAtControlPoints() { Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT); @@ -357,6 +386,27 @@ public class BrightnessMappingStrategyTest { assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res, ddc)); } + @Test + public void testIdleModeConfigLoadsCorrectly() { + Resources res = createResourcesIdle(LUX_LEVELS_IDLE, DISPLAY_LEVELS_NITS_IDLE); + DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE); + + // Create an idle mode bms + // This will fail if it tries to fetch the wrong configuration. + BrightnessMappingStrategy bms = BrightnessMappingStrategy.createForIdleMode(res, ddc); + assertNotNull("BrightnessMappingStrategy should not be null", bms); + + // Ensure that the config is the one we set + // Ensure that the lux -> brightness -> nits path works. () + for (int i = 0; i < DISPLAY_LEVELS_NITS_IDLE.length; i++) { + assertEquals(LUX_LEVELS_IDLE[i], bms.getDefaultConfig().getCurve().first[i], TOLERANCE); + assertEquals(DISPLAY_LEVELS_NITS_IDLE[i], bms.getDefaultConfig().getCurve().second[i], + TOLERANCE); + assertEquals(bms.convertToNits(bms.getBrightness(LUX_LEVELS_IDLE[i])), + DISPLAY_LEVELS_NITS_IDLE[i], TOLERANCE); + } + } + private static void assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy strategy) { // Save out all of the initial brightness data for comparison after reset. float[] initialBrightnessLevels = new float[LUX_LEVELS.length]; @@ -421,14 +471,39 @@ public class BrightnessMappingStrategyTest { brightnessLevelsNits); } + private Resources createResourcesIdle(int[] luxLevels, float[] brightnessLevelsNits) { + return createResources(EMPTY_INT_ARRAY, EMPTY_INT_ARRAY, EMPTY_FLOAT_ARRAY, + luxLevels, brightnessLevelsNits); + } + private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight, float[] brightnessLevelsNits) { + return createResources(luxLevels, brightnessLevelsBacklight, brightnessLevelsNits, + EMPTY_INT_ARRAY, EMPTY_FLOAT_ARRAY); + + } + + private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight, + float[] brightnessLevelsNits, int[] luxLevelsIdle, float[] brightnessLevelsNitsIdle) { + Resources mockResources = mock(Resources.class); + // For historical reasons, the lux levels resource implicitly defines the first point as 0, // so we need to chop it off of the array the mock resource object returns. - int[] luxLevelsResource = Arrays.copyOfRange(luxLevels, 1, luxLevels.length); - when(mockResources.getIntArray(com.android.internal.R.array.config_autoBrightnessLevels)) - .thenReturn(luxLevelsResource); + // Don't mock if these values are not set. If we try to use them, we will fail. + if (luxLevels.length > 0) { + int[] luxLevelsResource = Arrays.copyOfRange(luxLevels, 1, luxLevels.length); + when(mockResources.getIntArray( + com.android.internal.R.array.config_autoBrightnessLevels)) + .thenReturn(luxLevelsResource); + } + if (luxLevelsIdle.length > 0) { + int[] luxLevelsIdleResource = Arrays.copyOfRange(luxLevelsIdle, 1, + luxLevelsIdle.length); + when(mockResources.getIntArray( + com.android.internal.R.array.config_autoBrightnessLevelsIdle)) + .thenReturn(luxLevelsIdleResource); + } when(mockResources.getIntArray( com.android.internal.R.array.config_autoBrightnessLcdBacklightValues)) @@ -438,6 +513,10 @@ public class BrightnessMappingStrategyTest { when(mockResources.obtainTypedArray( com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)) .thenReturn(mockBrightnessLevelNits); + TypedArray mockBrightnessLevelNitsIdle = createFloatTypedArray(brightnessLevelsNitsIdle); + when(mockResources.obtainTypedArray( + com.android.internal.R.array.config_autoBrightnessDisplayValuesNitsIdle)) + .thenReturn(mockBrightnessLevelNitsIdle); when(mockResources.getInteger( com.android.internal.R.integer.config_screenBrightnessSettingMinimum)) |