Merge "Add idle screen brightness mapping to DPC"

This commit is contained in:
Fiona Campbell
2021-11-25 10:51:01 +00:00
committed by Android (Google) Code Review
5 changed files with 205 additions and 19 deletions

View File

@@ -1483,6 +1483,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,
@@ -1506,6 +1530,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
@@ -1522,6 +1550,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.

View File

@@ -1902,6 +1902,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" />
@@ -3788,7 +3789,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" />

View File

@@ -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);
}
// Display independent values
float[] luxLevels = getLuxLevels(resources.getIntArray(
com.android.internal.R.array.config_autoBrightnessLevels));
/**
* 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, 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 {

View File

@@ -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;
@@ -386,8 +387,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
@@ -408,7 +418,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.
@@ -600,7 +610,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;
}
@@ -609,7 +619,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;
@@ -867,9 +878,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);
@@ -920,7 +939,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,
@@ -2143,8 +2162,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;
}
@@ -2296,6 +2315,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());

View File

@@ -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))