Make the short term brightness model configurable.
Bug: 146141793 Test: atest BrightnessConfigurationTest Test: atest AutomaticBrightnessControllerTest Test: manual - use reflection to configure the new parameters from turbo app and check dumpsys Change-Id: I78af8009f15400f2f91e55363066d97f008a7922
This commit is contained in:
@@ -2353,9 +2353,13 @@ package android.hardware.display {
|
||||
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
|
||||
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
|
||||
method public android.util.Pair<float[],float[]> getCurve();
|
||||
method public float getShortTermModelLowerLuxMultiplier();
|
||||
method public long getShortTermModelTimeout();
|
||||
method public float getShortTermModelUpperLuxMultiplier();
|
||||
method public boolean shouldCollectColorSamples();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
|
||||
field public static final long SHORT_TERM_TIMEOUT_UNSET = -1L; // 0xffffffffffffffffL
|
||||
}
|
||||
|
||||
public static class BrightnessConfiguration.Builder {
|
||||
@@ -2366,6 +2370,9 @@ package android.hardware.display {
|
||||
method public int getMaxCorrectionsByCategory();
|
||||
method public int getMaxCorrectionsByPackageName();
|
||||
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
|
||||
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelLowerLuxMultiplier(@FloatRange(from=0.0f) float);
|
||||
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeout(long);
|
||||
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelUpperLuxMultiplier(@FloatRange(from=0.0f) float);
|
||||
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
|
||||
}
|
||||
|
||||
|
||||
@@ -1023,9 +1023,13 @@ package android.hardware.display {
|
||||
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
|
||||
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
|
||||
method public android.util.Pair<float[],float[]> getCurve();
|
||||
method public float getShortTermModelLowerLuxMultiplier();
|
||||
method public long getShortTermModelTimeout();
|
||||
method public float getShortTermModelUpperLuxMultiplier();
|
||||
method public boolean shouldCollectColorSamples();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
|
||||
field public static final long SHORT_TERM_TIMEOUT_UNSET = -1L; // 0xffffffffffffffffL
|
||||
}
|
||||
|
||||
public static class BrightnessConfiguration.Builder {
|
||||
@@ -1036,6 +1040,9 @@ package android.hardware.display {
|
||||
method public int getMaxCorrectionsByCategory();
|
||||
method public int getMaxCorrectionsByPackageName();
|
||||
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
|
||||
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelLowerLuxMultiplier(@FloatRange(from=0.0f) float);
|
||||
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeout(long);
|
||||
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelUpperLuxMultiplier(@FloatRange(from=0.0f) float);
|
||||
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.hardware.display;
|
||||
|
||||
import android.annotation.FloatRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
@@ -56,6 +57,16 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
private static final String ATTR_PACKAGE_NAME = "package-name";
|
||||
private static final String ATTR_CATEGORY = "category";
|
||||
private static final String ATTR_COLLECT_COLOR = "collect-color";
|
||||
private static final String ATTR_MODEL_TIMEOUT = "model-timeout";
|
||||
private static final String ATTR_MODEL_LOWER_BOUND = "model-lower-bound";
|
||||
private static final String ATTR_MODEL_UPPER_BOUND = "model-upper-bound";
|
||||
/**
|
||||
* Returned from {@link #getShortTermModelTimeout()} if no timeout has been set.
|
||||
* In this case the device will use the default timeout available in the
|
||||
* {@link BrightnessConfiguration} returned from
|
||||
* {@link DisplayManager#getDefaultBrightnessConfiguration()}.
|
||||
*/
|
||||
public static final long SHORT_TERM_TIMEOUT_UNSET = -1;
|
||||
|
||||
private final float[] mLux;
|
||||
private final float[] mNits;
|
||||
@@ -63,17 +74,26 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
private final Map<Integer, BrightnessCorrection> mCorrectionsByCategory;
|
||||
private final String mDescription;
|
||||
private final boolean mShouldCollectColorSamples;
|
||||
private final long mShortTermModelTimeout;
|
||||
private final float mShortTermModelLowerLuxMultiplier;
|
||||
private final float mShortTermModelUpperLuxMultiplier;
|
||||
|
||||
private BrightnessConfiguration(float[] lux, float[] nits,
|
||||
Map<String, BrightnessCorrection> correctionsByPackageName,
|
||||
Map<Integer, BrightnessCorrection> correctionsByCategory, String description,
|
||||
boolean shouldCollectColorSamples) {
|
||||
boolean shouldCollectColorSamples,
|
||||
long shortTermModelTimeout,
|
||||
float shortTermModelLowerLuxMultiplier,
|
||||
float shortTermModelUpperLuxMultiplier) {
|
||||
mLux = lux;
|
||||
mNits = nits;
|
||||
mCorrectionsByPackageName = correctionsByPackageName;
|
||||
mCorrectionsByCategory = correctionsByCategory;
|
||||
mDescription = description;
|
||||
mShouldCollectColorSamples = shouldCollectColorSamples;
|
||||
mShortTermModelTimeout = shortTermModelTimeout;
|
||||
mShortTermModelLowerLuxMultiplier = shortTermModelLowerLuxMultiplier;
|
||||
mShortTermModelUpperLuxMultiplier = shortTermModelUpperLuxMultiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,6 +152,42 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
return mShouldCollectColorSamples;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timeout for the short term model in milliseconds.
|
||||
*
|
||||
* If the screen is inactive for this timeout then the short term model
|
||||
* will check the lux range defined by {@link #getShortTermModelLowerLuxMultiplier()} and
|
||||
* {@link #getShortTermModelUpperLuxMultiplier()} to decide whether to keep any adjustment
|
||||
* the user has made to adaptive brightness.
|
||||
*/
|
||||
public long getShortTermModelTimeout() {
|
||||
return mShortTermModelTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the multiplier used to calculate the upper bound for which
|
||||
* a users adaptive brightness is considered valid.
|
||||
*
|
||||
* For example if a user changes the brightness when the ambient light level
|
||||
* is 100 lux, the adjustment will be kept if the current ambient light level
|
||||
* is {@code <= 100 + (100 * getShortTermModelUpperLuxMultiplier())}.
|
||||
*/
|
||||
public float getShortTermModelUpperLuxMultiplier() {
|
||||
return mShortTermModelUpperLuxMultiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the multiplier used to calculate the lower bound for which
|
||||
* a users adaptive brightness is considered valid.
|
||||
*
|
||||
* For example if a user changes the brightness when the ambient light level
|
||||
* is 100 lux, the adjustment will be kept if the current ambient light level
|
||||
* is {@code >= 100 - (100 * getShortTermModelLowerLuxMultiplier())}.
|
||||
*/
|
||||
public float getShortTermModelLowerLuxMultiplier() {
|
||||
return mShortTermModelLowerLuxMultiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeFloatArray(mLux);
|
||||
@@ -152,6 +208,9 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
}
|
||||
dest.writeString(mDescription);
|
||||
dest.writeBoolean(mShouldCollectColorSamples);
|
||||
dest.writeLong(mShortTermModelTimeout);
|
||||
dest.writeFloat(mShortTermModelLowerLuxMultiplier);
|
||||
dest.writeFloat(mShortTermModelUpperLuxMultiplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -182,6 +241,15 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
sb.append(mDescription);
|
||||
}
|
||||
sb.append(", shouldCollectColorSamples = " + mShouldCollectColorSamples);
|
||||
if (mShortTermModelTimeout >= 0) {
|
||||
sb.append(", shortTermModelTimeout = " + mShortTermModelTimeout);
|
||||
}
|
||||
if (!Float.isNaN(mShortTermModelLowerLuxMultiplier)) {
|
||||
sb.append(", shortTermModelLowerLuxMultiplier = " + mShortTermModelLowerLuxMultiplier);
|
||||
}
|
||||
if (!Float.isNaN(mShortTermModelLowerLuxMultiplier)) {
|
||||
sb.append(", shortTermModelUpperLuxMultiplier = " + mShortTermModelUpperLuxMultiplier);
|
||||
}
|
||||
sb.append("'}");
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -197,6 +265,9 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
result = result * 31 + mDescription.hashCode();
|
||||
}
|
||||
result = result * 31 + Boolean.hashCode(mShouldCollectColorSamples);
|
||||
result = result * 31 + Long.hashCode(mShortTermModelTimeout);
|
||||
result = result * 31 + Float.hashCode(mShortTermModelLowerLuxMultiplier);
|
||||
result = result * 31 + Float.hashCode(mShortTermModelUpperLuxMultiplier);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -213,7 +284,19 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
&& mCorrectionsByPackageName.equals(other.mCorrectionsByPackageName)
|
||||
&& mCorrectionsByCategory.equals(other.mCorrectionsByCategory)
|
||||
&& Objects.equals(mDescription, other.mDescription)
|
||||
&& mShouldCollectColorSamples == other.mShouldCollectColorSamples;
|
||||
&& mShouldCollectColorSamples == other.mShouldCollectColorSamples
|
||||
&& mShortTermModelTimeout == other.mShortTermModelTimeout
|
||||
&& checkFloatEquals(mShortTermModelLowerLuxMultiplier,
|
||||
other.mShortTermModelLowerLuxMultiplier)
|
||||
&& checkFloatEquals(mShortTermModelUpperLuxMultiplier,
|
||||
other.mShortTermModelUpperLuxMultiplier);
|
||||
}
|
||||
|
||||
private boolean checkFloatEquals(float one, float two) {
|
||||
if (Float.isNaN(one) && Float.isNaN(two)) {
|
||||
return true;
|
||||
}
|
||||
return one == two;
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Creator<BrightnessConfiguration> CREATOR =
|
||||
@@ -243,6 +326,9 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
builder.setDescription(description);
|
||||
final boolean shouldCollectColorSamples = in.readBoolean();
|
||||
builder.setShouldCollectColorSamples(shouldCollectColorSamples);
|
||||
builder.setShortTermModelTimeout(in.readLong());
|
||||
builder.setShortTermModelLowerLuxMultiplier(in.readFloat());
|
||||
builder.setShortTermModelUpperLuxMultiplier(in.readFloat());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -296,6 +382,18 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
if (mShouldCollectColorSamples) {
|
||||
serializer.attribute(null, ATTR_COLLECT_COLOR, Boolean.toString(true));
|
||||
}
|
||||
if (mShortTermModelTimeout >= 0) {
|
||||
serializer.attribute(null, ATTR_MODEL_TIMEOUT,
|
||||
Long.toString(mShortTermModelTimeout));
|
||||
}
|
||||
if (!Float.isNaN(mShortTermModelLowerLuxMultiplier)) {
|
||||
serializer.attribute(null, ATTR_MODEL_LOWER_BOUND,
|
||||
Float.toString(mShortTermModelLowerLuxMultiplier));
|
||||
}
|
||||
if (!Float.isNaN(mShortTermModelUpperLuxMultiplier)) {
|
||||
serializer.attribute(null, ATTR_MODEL_UPPER_BOUND,
|
||||
Float.toString(mShortTermModelUpperLuxMultiplier));
|
||||
}
|
||||
serializer.endTag(null, TAG_BRIGHTNESS_PARAMS);
|
||||
}
|
||||
|
||||
@@ -320,6 +418,9 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
Map<String, BrightnessCorrection> correctionsByPackageName = new HashMap<>();
|
||||
Map<Integer, BrightnessCorrection> correctionsByCategory = new HashMap<>();
|
||||
boolean shouldCollectColorSamples = false;
|
||||
long shortTermModelTimeout = SHORT_TERM_TIMEOUT_UNSET;
|
||||
float shortTermModelLowerLuxMultiplier = Float.NaN;
|
||||
float shortTermModelUpperLuxMultiplier = Float.NaN;
|
||||
final int configDepth = parser.getDepth();
|
||||
while (XmlUtils.nextElementWithin(parser, configDepth)) {
|
||||
if (TAG_BRIGHTNESS_CURVE.equals(parser.getName())) {
|
||||
@@ -357,6 +458,12 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
} else if (TAG_BRIGHTNESS_PARAMS.equals(parser.getName())) {
|
||||
shouldCollectColorSamples =
|
||||
Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_COLLECT_COLOR));
|
||||
Long timeout = loadLongFromXml(parser, ATTR_MODEL_TIMEOUT);
|
||||
if (timeout != null) {
|
||||
shortTermModelTimeout = timeout;
|
||||
}
|
||||
shortTermModelLowerLuxMultiplier = loadFloatFromXml(parser, ATTR_MODEL_LOWER_BOUND);
|
||||
shortTermModelUpperLuxMultiplier = loadFloatFromXml(parser, ATTR_MODEL_UPPER_BOUND);
|
||||
}
|
||||
}
|
||||
final int n = luxList.size();
|
||||
@@ -380,6 +487,9 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
builder.addCorrectionByCategory(category, correction);
|
||||
}
|
||||
builder.setShouldCollectColorSamples(shouldCollectColorSamples);
|
||||
builder.setShortTermModelTimeout(shortTermModelTimeout);
|
||||
builder.setShortTermModelLowerLuxMultiplier(shortTermModelLowerLuxMultiplier);
|
||||
builder.setShortTermModelUpperLuxMultiplier(shortTermModelUpperLuxMultiplier);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -392,6 +502,16 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
private static Long loadLongFromXml(XmlPullParser parser, String attribute) {
|
||||
final String string = parser.getAttributeValue(null, attribute);
|
||||
try {
|
||||
return Long.parseLong(string);
|
||||
} catch (NullPointerException | NumberFormatException e) {
|
||||
// Ignoring
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder class for {@link BrightnessConfiguration}s.
|
||||
*/
|
||||
@@ -405,6 +525,9 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
private Map<Integer, BrightnessCorrection> mCorrectionsByCategory;
|
||||
private String mDescription;
|
||||
private boolean mShouldCollectColorSamples;
|
||||
private long mShortTermModelTimeout = SHORT_TERM_TIMEOUT_UNSET;
|
||||
private float mShortTermModelLowerLuxMultiplier = Float.NaN;
|
||||
private float mShortTermModelUpperLuxMultiplier = Float.NaN;
|
||||
|
||||
/**
|
||||
* Constructs the builder with the control points for the brightness curve.
|
||||
@@ -541,6 +664,60 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timeout for the short term model in milliseconds.
|
||||
*
|
||||
* If the screen is inactive for this timeout then the short term model
|
||||
* will check the lux range defined by {@link #setShortTermModelLowerLuxMultiplier(float))}
|
||||
* and {@link #setShortTermModelUpperLuxMultiplier(float)} to decide whether to keep any
|
||||
* adjustment the user has made to adaptive brightness.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setShortTermModelTimeout(long shortTermModelTimeout) {
|
||||
mShortTermModelTimeout = shortTermModelTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the multiplier used to calculate the upper bound for which
|
||||
* a users adaptive brightness is considered valid.
|
||||
*
|
||||
* For example if a user changes the brightness when the ambient light level
|
||||
* is 100 lux, the adjustment will be kept if the current ambient light level
|
||||
* is {@code <= 100 + (100 * shortTermModelUpperLuxMultiplier)}.
|
||||
*
|
||||
* @throws IllegalArgumentException if shortTermModelUpperLuxMultiplier is negative.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setShortTermModelUpperLuxMultiplier(
|
||||
@FloatRange(from = 0.0f) float shortTermModelUpperLuxMultiplier) {
|
||||
if (shortTermModelUpperLuxMultiplier < 0.0f) {
|
||||
throw new IllegalArgumentException("Negative lux multiplier");
|
||||
}
|
||||
mShortTermModelUpperLuxMultiplier = shortTermModelUpperLuxMultiplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the multiplier used to calculate the lower bound for which
|
||||
* a users adaptive brightness is considered valid.
|
||||
*
|
||||
* For example if a user changes the brightness when the ambient light level
|
||||
* is 100 lux, the adjustment will be kept if the current ambient light level
|
||||
* is {@code >= 100 - (100 * shortTermModelLowerLuxMultiplier)}.
|
||||
*
|
||||
* @throws IllegalArgumentException if shortTermModelUpperLuxMultiplier is negative.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setShortTermModelLowerLuxMultiplier(
|
||||
@FloatRange(from = 0.0f) float shortTermModelLowerLuxMultiplier) {
|
||||
if (shortTermModelLowerLuxMultiplier < 0.0f) {
|
||||
throw new IllegalArgumentException("Negative lux multiplier");
|
||||
}
|
||||
mShortTermModelLowerLuxMultiplier = shortTermModelLowerLuxMultiplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the {@link BrightnessConfiguration}.
|
||||
*/
|
||||
@@ -550,7 +727,9 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
throw new IllegalStateException("A curve must be set!");
|
||||
}
|
||||
return new BrightnessConfiguration(mCurveLux, mCurveNits, mCorrectionsByPackageName,
|
||||
mCorrectionsByCategory, mDescription, mShouldCollectColorSamples);
|
||||
mCorrectionsByCategory, mDescription, mShouldCollectColorSamples,
|
||||
mShortTermModelTimeout, mShortTermModelLowerLuxMultiplier,
|
||||
mShortTermModelUpperLuxMultiplier);
|
||||
}
|
||||
|
||||
private static void checkMonotonic(float[] vals, boolean strictlyIncreasing, String name) {
|
||||
|
||||
@@ -114,11 +114,27 @@ public class BrightnessConfigurationTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLuxMultipliersMustBePositive() {
|
||||
BrightnessConfiguration.Builder config = new BrightnessConfiguration.Builder(
|
||||
LUX_LEVELS, NITS_LEVELS);
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
config.setShortTermModelUpperLuxMultiplier(-1f);
|
||||
});
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
config.setShortTermModelLowerLuxMultiplier(-1f);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParceledConfigIsEquivalent() {
|
||||
BrightnessConfiguration.Builder builder =
|
||||
new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
|
||||
builder.setShouldCollectColorSamples(true);
|
||||
builder.setShortTermModelTimeout(1234L);
|
||||
builder.setShortTermModelLowerLuxMultiplier(0.9f);
|
||||
builder.setShortTermModelUpperLuxMultiplier(0.2f);
|
||||
builder.addCorrectionByCategory(3,
|
||||
BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
|
||||
builder.addCorrectionByPackageName("a.package.name",
|
||||
@@ -137,6 +153,9 @@ public class BrightnessConfigurationTest {
|
||||
BrightnessConfiguration.Builder builder =
|
||||
new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
|
||||
builder.setShouldCollectColorSamples(true);
|
||||
builder.setShortTermModelTimeout(123L);
|
||||
builder.setShortTermModelLowerLuxMultiplier(0.4f);
|
||||
builder.setShortTermModelUpperLuxMultiplier(0.8f);
|
||||
builder.addCorrectionByCategory(3,
|
||||
BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
|
||||
builder.addCorrectionByPackageName("a.package.name",
|
||||
@@ -208,13 +227,28 @@ public class BrightnessConfigurationTest {
|
||||
BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
|
||||
builder.addCorrectionByPackageName("a.package.name",
|
||||
BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
|
||||
BrightnessConfiguration correctionsDiffer = builder.build();
|
||||
assertNotEquals(baseConfig, correctionsDiffer);
|
||||
|
||||
builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
|
||||
builder.setShouldCollectColorSamples(true);
|
||||
BrightnessConfiguration colorCollectionDiffers = builder.build();
|
||||
assertNotEquals(baseConfig, colorCollectionDiffers);
|
||||
|
||||
builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
|
||||
builder.setShouldCollectColorSamples(true);
|
||||
BrightnessConfiguration correctionsDiffer = builder.build();
|
||||
assertNotEquals(baseConfig, correctionsDiffer);
|
||||
builder.setShortTermModelTimeout(300L);
|
||||
BrightnessConfiguration timeoutDiffers = builder.build();
|
||||
assertNotEquals(baseConfig, timeoutDiffers);
|
||||
|
||||
builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
|
||||
builder.setShortTermModelLowerLuxMultiplier(0.7f);
|
||||
BrightnessConfiguration lowerLuxDiffers = builder.build();
|
||||
assertNotEquals(baseConfig, lowerLuxDiffers);
|
||||
|
||||
builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
|
||||
builder.setShortTermModelUpperLuxMultiplier(0.6f);
|
||||
BrightnessConfiguration upperLuxDiffers = builder.build();
|
||||
assertNotEquals(baseConfig, upperLuxDiffers);
|
||||
}
|
||||
|
||||
private static void assertArrayEquals(float[] expected, float[] actual, String name) {
|
||||
|
||||
@@ -52,9 +52,6 @@ class AutomaticBrightnessController {
|
||||
|
||||
private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false;
|
||||
|
||||
// If true, enables the use of the screen auto-brightness adjustment setting.
|
||||
private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT = true;
|
||||
|
||||
// How long the current sensor reading is assumed to be valid beyond the current time.
|
||||
// This provides a bit of prediction, as well as ensures that the weight for the last sample is
|
||||
// non-zero, which in turn ensures that the total weight is non-zero.
|
||||
@@ -131,13 +128,6 @@ class AutomaticBrightnessController {
|
||||
|
||||
private boolean mLoggingEnabled;
|
||||
|
||||
// Timeout 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, but also so that
|
||||
// we don't erroneously keep the short-term model if the device is dozing but the display is
|
||||
// fully on.
|
||||
private long mShortTermModelTimeout;
|
||||
|
||||
// Amount of time to delay auto-brightness after screen on while waiting for
|
||||
// the light sensor to warm-up in milliseconds.
|
||||
// May be 0 if no warm-up is required.
|
||||
@@ -202,7 +192,6 @@ class AutomaticBrightnessController {
|
||||
// we use a relative threshold to determine when to revert to the OEM curve.
|
||||
private boolean mShortTermModelValid;
|
||||
private float mShortTermModelAnchor;
|
||||
private float SHORT_TERM_MODEL_THRESHOLD_RATIO = 0.6f;
|
||||
|
||||
// Context-sensitive brightness configurations require keeping track of the foreground app's
|
||||
// package name and category, which is done by registering a TaskStackListener to call back to
|
||||
@@ -224,14 +213,13 @@ class AutomaticBrightnessController {
|
||||
int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
|
||||
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
|
||||
HysteresisLevels ambientBrightnessThresholds,
|
||||
HysteresisLevels screenBrightnessThresholds, long shortTermModelTimeout,
|
||||
HysteresisLevels screenBrightnessThresholds,
|
||||
PackageManager packageManager) {
|
||||
this(new Injector(), callbacks, looper, sensorManager, lightSensor, mapper,
|
||||
lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor,
|
||||
lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig,
|
||||
darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig,
|
||||
ambientBrightnessThresholds, screenBrightnessThresholds, shortTermModelTimeout,
|
||||
packageManager);
|
||||
ambientBrightnessThresholds, screenBrightnessThresholds, packageManager);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -241,7 +229,7 @@ class AutomaticBrightnessController {
|
||||
int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
|
||||
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
|
||||
HysteresisLevels ambientBrightnessThresholds,
|
||||
HysteresisLevels screenBrightnessThresholds, long shortTermModelTimeout,
|
||||
HysteresisLevels screenBrightnessThresholds,
|
||||
PackageManager packageManager) {
|
||||
mInjector = injector;
|
||||
mCallbacks = callbacks;
|
||||
@@ -261,7 +249,6 @@ class AutomaticBrightnessController {
|
||||
mWeightingIntercept = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
|
||||
mAmbientBrightnessThresholds = ambientBrightnessThresholds;
|
||||
mScreenBrightnessThresholds = screenBrightnessThresholds;
|
||||
mShortTermModelTimeout = shortTermModelTimeout;
|
||||
mShortTermModelValid = true;
|
||||
mShortTermModelAnchor = -1;
|
||||
|
||||
@@ -370,7 +357,7 @@ class AutomaticBrightnessController {
|
||||
}
|
||||
if (!isInteractivePolicy(policy) && isInteractivePolicy(oldPolicy)) {
|
||||
mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE_SHORT_TERM_MODEL,
|
||||
mShortTermModelTimeout);
|
||||
mBrightnessMapper.getShortTermModelTimeout());
|
||||
} else if (isInteractivePolicy(policy) && !isInteractivePolicy(oldPolicy)) {
|
||||
mHandler.removeMessages(MSG_INVALIDATE_SHORT_TERM_MODEL);
|
||||
}
|
||||
@@ -452,7 +439,7 @@ class AutomaticBrightnessController {
|
||||
pw.println(" mAmbientLightRingBuffer=" + mAmbientLightRingBuffer);
|
||||
pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
|
||||
pw.println(" mDisplayPolicy=" + DisplayPowerRequest.policyToString(mDisplayPolicy));
|
||||
pw.println(" mShortTermModelTimeout=" + mShortTermModelTimeout);
|
||||
pw.println(" mShortTermModelTimeout=" + mBrightnessMapper.getShortTermModelTimeout());
|
||||
pw.println(" mShortTermModelAnchor=" + mShortTermModelAnchor);
|
||||
pw.println(" mShortTermModelValid=" + mShortTermModelValid);
|
||||
pw.println(" mBrightnessAdjustmentSamplePending=" + mBrightnessAdjustmentSamplePending);
|
||||
@@ -552,20 +539,10 @@ class AutomaticBrightnessController {
|
||||
|
||||
// If the short term model was invalidated and the change is drastic enough, reset it.
|
||||
if (!mShortTermModelValid && mShortTermModelAnchor != -1) {
|
||||
final float minAmbientLux =
|
||||
mShortTermModelAnchor - mShortTermModelAnchor * SHORT_TERM_MODEL_THRESHOLD_RATIO;
|
||||
final float maxAmbientLux =
|
||||
mShortTermModelAnchor + mShortTermModelAnchor * SHORT_TERM_MODEL_THRESHOLD_RATIO;
|
||||
if (minAmbientLux < mAmbientLux && mAmbientLux < maxAmbientLux) {
|
||||
if (mLoggingEnabled) {
|
||||
Slog.d(TAG, "ShortTermModel: re-validate user data, ambient lux is " +
|
||||
minAmbientLux + " < " + mAmbientLux + " < " + maxAmbientLux);
|
||||
}
|
||||
mShortTermModelValid = true;
|
||||
} else {
|
||||
Slog.d(TAG, "ShortTermModel: reset data, ambient lux is " + mAmbientLux +
|
||||
"(" + minAmbientLux + ", " + maxAmbientLux + ")");
|
||||
if (mBrightnessMapper.shouldResetShortTermModel(mAmbientLux, mShortTermModelAnchor)) {
|
||||
resetShortTermModel();
|
||||
} else {
|
||||
mShortTermModelValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public abstract class BrightnessMappingStrategy {
|
||||
|
||||
private static final float LUX_GRAD_SMOOTHING = 0.25f;
|
||||
private static final float MAX_GRAD = 1.0f;
|
||||
private static final float SHORT_TERM_MODEL_THRESHOLD_RATIO = 0.6f;
|
||||
|
||||
protected boolean mLoggingEnabled;
|
||||
|
||||
@@ -69,6 +70,9 @@ public abstract class BrightnessMappingStrategy {
|
||||
int[] backlightRange = resources.getIntArray(
|
||||
com.android.internal.R.array.config_screenBrightnessBacklight);
|
||||
|
||||
long shortTermModelTimeout = resources.getInteger(
|
||||
com.android.internal.R.integer.config_autoBrightnessShortTermModelTimeout);
|
||||
|
||||
if (isValidMapping(nitsRange, backlightRange)
|
||||
&& isValidMapping(luxLevels, brightnessLevelsNits)) {
|
||||
int minimumBacklight = resources.getInteger(
|
||||
@@ -82,11 +86,14 @@ public abstract class BrightnessMappingStrategy {
|
||||
}
|
||||
BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
|
||||
luxLevels, brightnessLevelsNits);
|
||||
builder.setShortTermModelTimeout(shortTermModelTimeout);
|
||||
builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
|
||||
builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
|
||||
return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
|
||||
autoBrightnessAdjustmentMaxGamma);
|
||||
} else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
|
||||
return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight,
|
||||
autoBrightnessAdjustmentMaxGamma);
|
||||
autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -188,6 +195,12 @@ public abstract class BrightnessMappingStrategy {
|
||||
*/
|
||||
public abstract boolean setBrightnessConfiguration(@Nullable BrightnessConfiguration config);
|
||||
|
||||
/**
|
||||
* Gets the current {@link BrightnessConfiguration}.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract BrightnessConfiguration getBrightnessConfiguration();
|
||||
|
||||
/**
|
||||
* Returns the desired brightness of the display based on the current ambient lux, including
|
||||
* any context-related corrections.
|
||||
@@ -274,8 +287,53 @@ public abstract class BrightnessMappingStrategy {
|
||||
/** @return The default brightness configuration. */
|
||||
public abstract BrightnessConfiguration getDefaultConfig();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the timeout for the short term model
|
||||
*
|
||||
* Timeout 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, but also so that
|
||||
* we don't erroneously keep the short-term model if the device is dozing but the
|
||||
* display is fully on.
|
||||
*/
|
||||
public abstract long getShortTermModelTimeout();
|
||||
|
||||
public abstract void dump(PrintWriter pw);
|
||||
|
||||
/**
|
||||
* Check if the short term model should be reset given the anchor lux the last
|
||||
* brightness change was made at and the current ambient lux.
|
||||
*/
|
||||
public boolean shouldResetShortTermModel(float ambientLux, float shortTermModelAnchor) {
|
||||
BrightnessConfiguration config = getBrightnessConfiguration();
|
||||
float minThresholdRatio = SHORT_TERM_MODEL_THRESHOLD_RATIO;
|
||||
float maxThresholdRatio = SHORT_TERM_MODEL_THRESHOLD_RATIO;
|
||||
if (config != null) {
|
||||
if (!Float.isNaN(config.getShortTermModelLowerLuxMultiplier())) {
|
||||
minThresholdRatio = config.getShortTermModelLowerLuxMultiplier();
|
||||
}
|
||||
if (!Float.isNaN(config.getShortTermModelUpperLuxMultiplier())) {
|
||||
maxThresholdRatio = config.getShortTermModelUpperLuxMultiplier();
|
||||
}
|
||||
}
|
||||
final float minAmbientLux =
|
||||
shortTermModelAnchor - shortTermModelAnchor * minThresholdRatio;
|
||||
final float maxAmbientLux =
|
||||
shortTermModelAnchor + shortTermModelAnchor * maxThresholdRatio;
|
||||
if (minAmbientLux < ambientLux && ambientLux <= maxAmbientLux) {
|
||||
if (mLoggingEnabled) {
|
||||
Slog.d(TAG, "ShortTermModel: re-validate user data, ambient lux is "
|
||||
+ minAmbientLux + " < " + ambientLux + " < " + maxAmbientLux);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
Slog.d(TAG, "ShortTermModel: reset data, ambient lux is " + ambientLux
|
||||
+ "(" + minAmbientLux + ", " + maxAmbientLux + ")");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected float normalizeAbsoluteBrightness(int brightness) {
|
||||
brightness = MathUtils.constrain(brightness,
|
||||
PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
|
||||
@@ -455,8 +513,10 @@ public abstract class BrightnessMappingStrategy {
|
||||
private float mAutoBrightnessAdjustment;
|
||||
private float mUserLux;
|
||||
private float mUserBrightness;
|
||||
private long mShortTermModelTimeout;
|
||||
|
||||
public SimpleMappingStrategy(float[] lux, int[] brightness, float maxGamma) {
|
||||
private SimpleMappingStrategy(float[] lux, int[] brightness, float maxGamma,
|
||||
long timeout) {
|
||||
Preconditions.checkArgument(lux.length != 0 && brightness.length != 0,
|
||||
"Lux and brightness arrays must not be empty!");
|
||||
Preconditions.checkArgument(lux.length == brightness.length,
|
||||
@@ -481,6 +541,12 @@ public abstract class BrightnessMappingStrategy {
|
||||
PLOG.start("simple mapping strategy");
|
||||
}
|
||||
computeSpline();
|
||||
mShortTermModelTimeout = timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getShortTermModelTimeout() {
|
||||
return mShortTermModelTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -488,6 +554,11 @@ public abstract class BrightnessMappingStrategy {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrightnessConfiguration getBrightnessConfiguration() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBrightness(float lux, String packageName,
|
||||
@ApplicationInfo.Category int category) {
|
||||
@@ -659,6 +730,15 @@ public abstract class BrightnessMappingStrategy {
|
||||
computeSpline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getShortTermModelTimeout() {
|
||||
if (mConfig.getShortTermModelTimeout() >= 0) {
|
||||
return mConfig.getShortTermModelTimeout();
|
||||
} else {
|
||||
return mDefaultConfig.getShortTermModelTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBrightnessConfiguration(@Nullable BrightnessConfiguration config) {
|
||||
if (config == null) {
|
||||
@@ -675,6 +755,11 @@ public abstract class BrightnessMappingStrategy {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrightnessConfiguration getBrightnessConfiguration() {
|
||||
return mConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBrightness(float lux, String packageName,
|
||||
@ApplicationInfo.Category int category) {
|
||||
|
||||
@@ -483,8 +483,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
+ initialLightSensorRate + ") to be less than or equal to "
|
||||
+ "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");
|
||||
}
|
||||
int shortTermModelTimeout = resources.getInteger(
|
||||
com.android.internal.R.integer.config_autoBrightnessShortTermModelTimeout);
|
||||
|
||||
String lightSensorType = resources.getString(
|
||||
com.android.internal.R.string.config_displayLightSensorType);
|
||||
@@ -498,8 +496,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
|
||||
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
|
||||
autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
|
||||
screenBrightnessThresholds, shortTermModelTimeout,
|
||||
context.getPackageManager());
|
||||
screenBrightnessThresholds, context.getPackageManager());
|
||||
} else {
|
||||
mUseSoftwareAutoBrightnessConfig = false;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ public class AutomaticBrightnessControllerTest {
|
||||
private static final int INITIAL_LIGHT_SENSOR_RATE = 20;
|
||||
private static final int BRIGHTENING_LIGHT_DEBOUNCE_CONFIG = 0;
|
||||
private static final int DARKENING_LIGHT_DEBOUNCE_CONFIG = 0;
|
||||
private static final int SHORT_TERM_MODEL_TIMEOUT = 0;
|
||||
private static final float DOZE_SCALE_FACTOR = 0.0f;
|
||||
private static final boolean RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG = false;
|
||||
|
||||
@@ -86,7 +85,7 @@ public class AutomaticBrightnessControllerTest {
|
||||
BRIGHTNESS_MAX, DOZE_SCALE_FACTOR, LIGHT_SENSOR_RATE, INITIAL_LIGHT_SENSOR_RATE,
|
||||
BRIGHTENING_LIGHT_DEBOUNCE_CONFIG, DARKENING_LIGHT_DEBOUNCE_CONFIG,
|
||||
RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG, mAmbientBrightnessThresholds,
|
||||
mScreenBrightnessThresholds, SHORT_TERM_MODEL_TIMEOUT, mPackageManager);
|
||||
mScreenBrightnessThresholds, mPackageManager);
|
||||
controller.setLoggingEnabled(true);
|
||||
|
||||
// Configure the brightness controller and grab an instance of the sensor listener,
|
||||
@@ -189,4 +188,27 @@ public class AutomaticBrightnessControllerTest {
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, (int) lux2));
|
||||
assertEquals(255, controller.getAutomaticScreenBrightness());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserAddUserDataPoint() throws Exception {
|
||||
Sensor lightSensor = TestUtils.createSensor(Sensor.TYPE_LIGHT, "Light Sensor");
|
||||
AutomaticBrightnessController controller = setupController(lightSensor);
|
||||
|
||||
ArgumentCaptor<SensorEventListener> listenerCaptor =
|
||||
ArgumentCaptor.forClass(SensorEventListener.class);
|
||||
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(lightSensor),
|
||||
eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
|
||||
SensorEventListener listener = listenerCaptor.getValue();
|
||||
|
||||
// Sensor reads 1000 lux,
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000));
|
||||
|
||||
// User sets brightness to 100
|
||||
controller.configure(true /* enable */, null /* configuration */,
|
||||
100 /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */,
|
||||
false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
|
||||
|
||||
// There should be a user data point added to the mapper.
|
||||
verify(mBrightnessMappingStrategy).addUserDataPoint(1000f, 100);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user