Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b29fdf1d authored by Kenny Guy's avatar Kenny Guy
Browse files

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
parent e6a18182
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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);
  }
+7 −0
Original line number Diff line number Diff line
@@ -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);
  }

+182 −3
Original line number Diff line number Diff line
@@ -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) {
+37 −3
Original line number Diff line number Diff line
@@ -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) {
+8 −31

File changed.

Preview size limit exceeded, changes collapsed.

Loading