diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java index 0bfc8e5d554b9..fea521f15b849 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java +++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java @@ -72,8 +72,6 @@ public class BrightnessController implements ToggleSlider.Listener { private static final Uri BRIGHTNESS_FOR_VR_FLOAT_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT); - private final float mMinimumBacklight; - private final float mMaximumBacklight; private final float mDefaultBacklight; private final float mMinimumBacklightForVr; private final float mMaximumBacklightForVr; @@ -314,10 +312,6 @@ public class BrightnessController implements ToggleSlider.Listener { mDisplayId = mContext.getDisplayId(); PowerManager pm = context.getSystemService(PowerManager.class); - mMinimumBacklight = pm.getBrightnessConstraint( - PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM); - mMaximumBacklight = pm.getBrightnessConstraint( - PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM); mDefaultBacklight = mContext.getDisplay().getBrightnessDefault(); mMinimumBacklightForVr = pm.getBrightnessConstraint( PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR); @@ -375,8 +369,8 @@ public class BrightnessController implements ToggleSlider.Listener { metric = mAutomatic ? MetricsEvent.ACTION_BRIGHTNESS_AUTO : MetricsEvent.ACTION_BRIGHTNESS; - minBacklight = mMinimumBacklight; - maxBacklight = mMaximumBacklight; + minBacklight = PowerManager.BRIGHTNESS_MIN; + maxBacklight = PowerManager.BRIGHTNESS_MAX; settingToChange = Settings.System.SCREEN_BRIGHTNESS_FLOAT; } final float valFloat = MathUtils.min(convertGammaToLinearFloat(value, @@ -439,8 +433,8 @@ public class BrightnessController implements ToggleSlider.Listener { min = mMinimumBacklightForVr; max = mMaximumBacklightForVr; } else { - min = mMinimumBacklight; - max = mMaximumBacklight; + min = PowerManager.BRIGHTNESS_MIN; + max = PowerManager.BRIGHTNESS_MAX; } // convertGammaToLinearFloat returns 0-1 if (BrightnessSynchronizer.floatEquals(brightnessValue, diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java index a62f67a743adf..30cbf27456387 100644 --- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java +++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java @@ -61,7 +61,10 @@ public abstract class BrightnessMappingStrategy { private static final Plog PLOG = Plog.createSystemPlog(TAG); @Nullable - public static BrightnessMappingStrategy create(Resources resources) { + public static BrightnessMappingStrategy create(Resources resources, + DisplayDeviceConfig displayDeviceConfig) { + + // Display independent values float[] luxLevels = getLuxLevels(resources.getIntArray( com.android.internal.R.array.config_autoBrightnessLevels)); int[] brightnessLevelsBacklight = resources.getIntArray( @@ -71,32 +74,22 @@ public abstract class BrightnessMappingStrategy { float autoBrightnessAdjustmentMaxGamma = resources.getFraction( com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma, 1, 1); - - float[] nitsRange = getFloatArray(resources.obtainTypedArray( - com.android.internal.R.array.config_screenBrightnessNits)); - 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) + // Display dependent values - used for physical mapping strategy nits -> brightness + final float[] nitsRange = displayDeviceConfig.getNits(); + final float[] brightnessRange = displayDeviceConfig.getBrightness(); + + if (isValidMapping(nitsRange, brightnessRange) && isValidMapping(luxLevels, brightnessLevelsNits)) { - int minimumBacklight = resources.getInteger( - com.android.internal.R.integer.config_screenBrightnessSettingMinimum); - int maximumBacklight = resources.getInteger( - com.android.internal.R.integer.config_screenBrightnessSettingMaximum); - if (backlightRange[0] > minimumBacklight - || backlightRange[backlightRange.length - 1] < maximumBacklight) { - Slog.w(TAG, "Screen brightness mapping does not cover whole range of available " + - "backlight values, autobrightness functionality may be impaired."); - } + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder( luxLevels, brightnessLevelsNits); builder.setShortTermModelTimeoutMillis(shortTermModelTimeout); builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO); builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO); - return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange, + return new PhysicalMappingStrategy(builder.build(), nitsRange, brightnessRange, autoBrightnessAdjustmentMaxGamma); } else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) { return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight, @@ -264,11 +257,11 @@ public abstract class BrightnessMappingStrategy { public abstract boolean setAutoBrightnessAdjustment(float adjustment); /** - * Converts the provided backlight value to nits if possible. + * Converts the provided brightness value to nits if possible. * - * Returns -1.0f if there's no available mapping for the backlight to nits. + * Returns -1.0f if there's no available mapping for the brightness to nits. */ - public abstract float convertToNits(int backlight); + public abstract float convertToNits(float brightness); /** * Adds a user interaction data point to the brightness mapping. @@ -603,7 +596,7 @@ public abstract class BrightnessMappingStrategy { } @Override - public float convertToNits(int backlight) { + public float convertToNits(float brightness) { return -1.0f; } @@ -701,37 +694,39 @@ public abstract class BrightnessMappingStrategy { // in nits. private Spline mBrightnessSpline; - // A spline mapping from nits to the corresponding backlight value, normalized to the range + // A spline mapping from nits to the corresponding brightness value, normalized to the range // [0, 1.0]. - private Spline mNitsToBacklightSpline; + private Spline mNitsToBrightnessSpline; + + // A spline mapping from the system brightness value, normalized to the range [0, 1.0], to + // a brightness in nits. + private Spline mBrightnessToNitsSpline; // The default brightness configuration. private final BrightnessConfiguration mDefaultConfig; - // A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to - // a brightness in nits. - private Spline mBacklightToNitsSpline; - - private float[] mNits; - private int[] mBacklight; + private final float[] mNits; + private final float[] mBrightness; private boolean mBrightnessRangeAdjustmentApplied; - private float mMaxGamma; + private final float mMaxGamma; private float mAutoBrightnessAdjustment; private float mUserLux; private float mUserBrightness; public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits, - int[] backlight, float maxGamma) { - Preconditions.checkArgument(nits.length != 0 && backlight.length != 0, - "Nits and backlight arrays must not be empty!"); - Preconditions.checkArgument(nits.length == backlight.length, - "Nits and backlight arrays must be the same length!"); + float[] brightness, float maxGamma) { + + Preconditions.checkArgument(nits.length != 0 && brightness.length != 0, + "Nits and brightness arrays must not be empty!"); + + Preconditions.checkArgument(nits.length == brightness.length, + "Nits and brightness arrays must be the same length!"); Objects.requireNonNull(config); Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits"); - Preconditions.checkArrayElementsInRange(backlight, - PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON, "backlight"); + Preconditions.checkArrayElementsInRange(brightness, + PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, "brightness"); mMaxGamma = maxGamma; mAutoBrightnessAdjustment = 0; @@ -739,7 +734,7 @@ public abstract class BrightnessMappingStrategy { mUserBrightness = -1; mNits = nits; - mBacklight = backlight; + mBrightness = brightness; computeNitsBrightnessSplines(mNits); mDefaultConfig = config; @@ -784,15 +779,15 @@ public abstract class BrightnessMappingStrategy { public float getBrightness(float lux, String packageName, @ApplicationInfo.Category int category) { float nits = mBrightnessSpline.interpolate(lux); - float backlight = mNitsToBacklightSpline.interpolate(nits); + float brightness = mNitsToBrightnessSpline.interpolate(nits); // Correct the brightness according to the current application and its category, but - // only if no user data point is set (as this will oevrride the user setting). + // only if no user data point is set (as this will override the user setting). if (mUserLux == -1) { - backlight = correctBrightness(backlight, packageName, category); + brightness = correctBrightness(brightness, packageName, category); } else if (mLoggingEnabled) { Slog.d(TAG, "user point set, correction not applied"); } - return backlight; + return brightness; } @Override @@ -817,8 +812,8 @@ public abstract class BrightnessMappingStrategy { } @Override - public float convertToNits(int backlight) { - return mBacklightToNitsSpline.interpolate(normalizeAbsoluteBrightness(backlight)); + public float convertToNits(float brightness) { + return mBrightnessToNitsSpline.interpolate(brightness); } @Override @@ -884,7 +879,8 @@ public abstract class BrightnessMappingStrategy { pw.println("PhysicalMappingStrategy"); pw.println(" mConfig=" + mConfig); pw.println(" mBrightnessSpline=" + mBrightnessSpline); - pw.println(" mNitsToBacklightSpline=" + mNitsToBacklightSpline); + pw.println(" mNitsToBrightnessSpline=" + mNitsToBrightnessSpline); + pw.println(" mBrightnessToNitsSpline=" + mBrightnessToNitsSpline); pw.println(" mMaxGamma=" + mMaxGamma); pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment); pw.println(" mUserLux=" + mUserLux); @@ -894,31 +890,25 @@ public abstract class BrightnessMappingStrategy { } private void computeNitsBrightnessSplines(float[] nits) { - final int len = nits.length; - float[] normalizedBacklight = new float[len]; - for (int i = 0; i < len; i++) { - normalizedBacklight[i] = normalizeAbsoluteBrightness(mBacklight[i]); - } - - mNitsToBacklightSpline = Spline.createSpline(nits, normalizedBacklight); - mBacklightToNitsSpline = Spline.createSpline(normalizedBacklight, nits); + mNitsToBrightnessSpline = Spline.createSpline(nits, mBrightness); + mBrightnessToNitsSpline = Spline.createSpline(mBrightness, nits); } private void computeSpline() { Pair defaultCurve = mConfig.getCurve(); float[] defaultLux = defaultCurve.first; float[] defaultNits = defaultCurve.second; - float[] defaultBacklight = new float[defaultNits.length]; - for (int i = 0; i < defaultBacklight.length; i++) { - defaultBacklight[i] = mNitsToBacklightSpline.interpolate(defaultNits[i]); + float[] defaultBrightness = new float[defaultNits.length]; + for (int i = 0; i < defaultBrightness.length; i++) { + defaultBrightness[i] = mNitsToBrightnessSpline.interpolate(defaultNits[i]); } - Pair curve = getAdjustedCurve(defaultLux, defaultBacklight, mUserLux, + Pair curve = getAdjustedCurve(defaultLux, defaultBrightness, mUserLux, mUserBrightness, mAutoBrightnessAdjustment, mMaxGamma); float[] lux = curve.first; - float[] backlight = curve.second; - float[] nits = new float[backlight.length]; + float[] brightness = curve.second; + float[] nits = new float[brightness.length]; for (int i = 0; i < nits.length; i++) { - nits[i] = mBacklightToNitsSpline.interpolate(backlight[i]); + nits[i] = mBrightnessToNitsSpline.interpolate(brightness[i]); } mBrightnessSpline = Spline.createSpline(lux, nits); } @@ -926,7 +916,7 @@ public abstract class BrightnessMappingStrategy { private float getUnadjustedBrightness(float lux) { Pair curve = mConfig.getCurve(); Spline spline = Spline.createSpline(curve.first, curve.second); - return mNitsToBacklightSpline.interpolate(spline.interpolate(lux)); + return mNitsToBrightnessSpline.interpolate(spline.interpolate(lux)); } private float correctBrightness(float brightness, String packageName, int category) { diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index 49328f1019c3f..0071b2f558c4b 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -18,9 +18,12 @@ package com.android.server.display; import android.annotation.NonNull; import android.content.Context; +import android.content.res.Resources; import android.os.Environment; import android.os.PowerManager; +import android.util.MathUtils; import android.util.Slog; +import android.util.Spline; import android.view.DisplayAddress; import com.android.internal.R; @@ -72,15 +75,31 @@ public class DisplayDeviceConfig { private final Context mContext; + // Nits and backlight values that are loaded from either the display device config file, or + // config.xml. These are the raw values and just used for the dumpsys + private float[] mRawNits; + private float[] mRawBacklight; + + // These arrays are calculated from the raw arrays, but clamped to contain values equal to and + // between mBacklightMinimum and mBacklightMaximum. These three arrays should all be the same + // length + // Nits array that is used to store the entire range of nits values that the device supports private float[] mNits; + // Backlight array holds the values that the HAL uses to display the corresponding nits values + private float[] mBacklight; + // Purely an array that covers the ranges of values 0.0 - 1.0, indicating the system brightness + // for the corresponding values above private float[] mBrightness; - private float mBrightnessMinimum = Float.NaN; - private float mBrightnessMaximum = Float.NaN; + + private float mBacklightMinimum = Float.NaN; + private float mBacklightMaximum = Float.NaN; private float mBrightnessDefault = Float.NaN; private float mBrightnessRampFastDecrease = Float.NaN; private float mBrightnessRampFastIncrease = Float.NaN; private float mBrightnessRampSlowDecrease = Float.NaN; private float mBrightnessRampSlowIncrease = Float.NaN; + private Spline mBrightnessToBacklightSpline; + private Spline mBacklightToBrightnessSpline; private List mQuirks; private boolean mIsHighBrightnessModeEnabled = false; private HighBrightnessModeData mHbmData; @@ -167,7 +186,7 @@ public class DisplayDeviceConfig { } /** - * Return the brightness mapping nits array if one is defined in the configuration file. + * Return the brightness mapping nits array. * * @return The brightness mapping nits array. */ @@ -176,22 +195,40 @@ public class DisplayDeviceConfig { } /** - * Return the brightness mapping value array if one is defined in the configuration file. + * Return the brightness mapping backlight array. * - * @return The brightness mapping value array. + * @return The backlight mapping value array. + */ + public float[] getBacklight() { + return mBacklight; + } + + /** + * Calculates the backlight value, as recognised by the HAL, from the brightness value + * given that the rest of the system deals with. + * + * @param brightness value on the framework scale of 0-1 + * @return backlight value on the HAL scale of 0-1 + */ + public float getBacklightFromBrightness(float brightness) { + return mBrightnessToBacklightSpline.interpolate(brightness); + } + + /** + * Return an array of equal length to backlight and nits, that covers the entire system + * brightness range of 0.0-1.0. + * + * @return brightness array */ public float[] getBrightness() { return mBrightness; } - public float getBrightnessMinimum() { - return mBrightnessMinimum; - } - - public float getBrightnessMaximum() { - return mBrightnessMaximum; - } - + /** + * Return the default brightness on a scale of 0.0f - 1.0f + * + * @return default brightness + */ public float getBrightnessDefault() { return mBrightnessDefault; } @@ -237,10 +274,15 @@ public class DisplayDeviceConfig { @Override public String toString() { String str = "DisplayDeviceConfig{" - + "mBrightness=" + Arrays.toString(mBrightness) + + "mBacklight=" + Arrays.toString(mBacklight) + ", mNits=" + Arrays.toString(mNits) - + ", mBrightnessMinimum=" + mBrightnessMinimum - + ", mBrightnessMaximum=" + mBrightnessMaximum + + ", mRawBacklight=" + Arrays.toString(mRawBacklight) + + ", mRawNits=" + Arrays.toString(mRawNits) + + ", mBrightness=" + Arrays.toString(mBrightness) + + ", mBrightnessToBacklightSpline=" + mBrightnessToBacklightSpline + + ", mBacklightToBrightnessSpline=" + mBacklightToBrightnessSpline + + ", mBacklightMinimum=" + mBacklightMinimum + + ", mBacklightMaximum=" + mBacklightMaximum + ", mBrightnessDefault=" + mBrightnessDefault + ", mQuirks=" + mQuirks + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled @@ -253,10 +295,6 @@ public class DisplayDeviceConfig { return str; } - private float getMaxBrightness() { - return mBrightness[mBrightness.length - 1]; - } - private static DisplayDeviceConfig getConfigFromSuffix(Context context, File baseDirectory, String suffixFormat, long idNumber) { @@ -264,7 +302,6 @@ public class DisplayDeviceConfig { final String filename = String.format(CONFIG_FILE_FORMAT, suffix); final File filePath = Environment.buildPath( baseDirectory, ETC_DIR, DISPLAY_CONFIG_DIR, filename); - if (filePath.exists()) { final DisplayDeviceConfig config = new DisplayDeviceConfig(context); config.initFromFile(filePath); @@ -299,9 +336,9 @@ public class DisplayDeviceConfig { try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) { final DisplayConfiguration config = XmlParser.read(in); if (config != null) { - loadBrightnessMap(config); loadBrightnessDefaultFromDdcXml(config); loadBrightnessConstraintsFromConfigXml(); + loadBrightnessMap(config); loadHighBrightnessModeData(config); loadQuirks(config); loadBrightnessRamps(config); @@ -318,13 +355,20 @@ public class DisplayDeviceConfig { // If no ddc exists, use config.xml loadBrightnessDefaultFromConfigXml(); loadBrightnessConstraintsFromConfigXml(); + loadBrightnessMapFromConfigXml(); loadBrightnessRampsFromConfigXml(); } private void initFromPmValues() { - mBrightnessMinimum = PowerManager.BRIGHTNESS_MIN; - mBrightnessMaximum = PowerManager.BRIGHTNESS_MAX; + // Set all to basic values + mBacklightMinimum = PowerManager.BRIGHTNESS_MIN; + mBacklightMaximum = PowerManager.BRIGHTNESS_MAX; mBrightnessDefault = BRIGHTNESS_DEFAULT; + mBrightnessRampFastDecrease = PowerManager.BRIGHTNESS_MAX; + mBrightnessRampFastIncrease = PowerManager.BRIGHTNESS_MAX; + mBrightnessRampSlowDecrease = PowerManager.BRIGHTNESS_MAX; + mBrightnessRampSlowIncrease = PowerManager.BRIGHTNESS_MAX; + setSimpleMappingStrategyValues(); } private void loadBrightnessDefaultFromDdcXml(DisplayConfiguration config) { @@ -364,24 +408,27 @@ public class DisplayDeviceConfig { final float max = mContext.getResources().getFloat(com.android.internal.R.dimen .config_screenBrightnessSettingMaximumFloat); if (min == INVALID_BRIGHTNESS_IN_CONFIG || max == INVALID_BRIGHTNESS_IN_CONFIG) { - mBrightnessMinimum = BrightnessSynchronizer.brightnessIntToFloat( + mBacklightMinimum = BrightnessSynchronizer.brightnessIntToFloat( mContext.getResources().getInteger(com.android.internal.R.integer .config_screenBrightnessSettingMinimum)); - mBrightnessMaximum = BrightnessSynchronizer.brightnessIntToFloat( + mBacklightMaximum = BrightnessSynchronizer.brightnessIntToFloat( mContext.getResources().getInteger(com.android.internal.R.integer .config_screenBrightnessSettingMaximum)); } else { - mBrightnessMinimum = min; - mBrightnessMaximum = max; + mBacklightMinimum = min; + mBacklightMaximum = max; } } private void loadBrightnessMap(DisplayConfiguration config) { final NitsMap map = config.getScreenBrightnessMap(); - // Map may not exist in config file + // Map may not exist in display device config if (map == null) { + loadBrightnessMapFromConfigXml(); return; } + + // Use the (preferred) display device config mapping final List points = map.getPoint(); final int size = points.size(); @@ -408,8 +455,123 @@ public class DisplayDeviceConfig { } ++i; } - mNits = nits; - mBrightness = backlight; + mRawNits = nits; + mRawBacklight = backlight; + constrainNitsAndBacklightArrays(); + } + + private void loadBrightnessMapFromConfigXml() { + // Use the config.xml mapping + final Resources res = mContext.getResources(); + final float[] sysNits = BrightnessMappingStrategy.getFloatArray(res.obtainTypedArray( + com.android.internal.R.array.config_screenBrightnessNits)); + final int[] sysBrightness = res.getIntArray( + com.android.internal.R.array.config_screenBrightnessBacklight); + final float[] sysBrightnessFloat = new float[sysBrightness.length]; + + for (int i = 0; i < sysBrightness.length; i++) { + sysBrightnessFloat[i] = BrightnessSynchronizer.brightnessIntToFloat( + sysBrightness[i]); + } + + // These arrays are allowed to be empty, we set null values so that + // BrightnessMappingStrategy will create a SimpleMappingStrategy instead. + if (sysBrightnessFloat.length == 0 || sysNits.length == 0) { + setSimpleMappingStrategyValues(); + return; + } + + mRawNits = sysNits; + mRawBacklight = sysBrightnessFloat; + constrainNitsAndBacklightArrays(); + } + + private void setSimpleMappingStrategyValues() { + // No translation from backlight to brightness should occur if we are using a + // SimpleMappingStrategy (ie they should be the same) so the splines are + // set to be linear, between 0.0 and 1.0 + mNits = null; + mBacklight = null; + float[] simpleMappingStrategyArray = new float[]{0.0f, 1.0f}; + mBrightnessToBacklightSpline = Spline.createSpline(simpleMappingStrategyArray, + simpleMappingStrategyArray); + mBacklightToBrightnessSpline = Spline.createSpline(simpleMappingStrategyArray, + simpleMappingStrategyArray); + } + + /** + * Change the nits and backlight arrays, so that they cover only the allowed backlight values + * Use the brightness minimum and maximum values to clamp these arrays. + */ + private void constrainNitsAndBacklightArrays() { + if (mRawBacklight[0] > mBacklightMinimum + || mRawBacklight[mRawBacklight.length - 1] < mBacklightMaximum + || mBacklightMinimum > mBacklightMaximum) { + throw new IllegalStateException("Min or max values are invalid" + + "; raw min=" + mRawBacklight[0] + + "; raw max=" + mRawBacklight[mRawBacklight.length - 1] + + "; backlight min=" + mBacklightMinimum + + "; backlight max=" + mBacklightMaximum); + } + + float[] newNits = new float[mRawBacklight.length]; + float[] newBacklight = new float[mRawBacklight.length]; + // Find the starting index of the clamped arrays. This may be less than the min so + // we'll need to clamp this value still when actually doing the remapping. + int newStart = 0; + for (int i = 0; i < mRawBacklight.length - 1; i++) { + if (mRawBacklight[i + 1] > mBacklightMinimum) { + newStart = i; + break; + } + } + + boolean isLastValue = false; + int newIndex = 0; + for (int i = newStart; i < mRawBacklight.length && !isLastValue; i++) { + newIndex = i - newStart; + final float newBacklightVal; + final float newNitsVal; + isLastValue = mRawBacklight[i] > mBacklightMaximum + || i >= mRawBacklight.length - 1; + // Clamp beginning and end to valid backlight values. + if (newIndex == 0) { + newBacklightVal = MathUtils.max(mRawBacklight[i], mBacklightMinimum); + newNitsVal = rawBacklightToNits(i, newBacklightVal); + } else if (isLastValue) { + newBacklightVal = MathUtils.min(mRawBacklight[i], mBacklightMaximum); + newNitsVal = rawBacklightToNits(i - 1, newBacklightVal); + } else { + newBacklightVal = mRawBacklight[i]; + newNitsVal = mRawNits[i]; + } + newBacklight[newIndex] = newBacklightVal; + newNits[newIndex] = newNitsVal; + } + mBacklight = Arrays.copyOf(newBacklight, newIndex + 1); + mNits = Arrays.copyOf(newNits, newIndex + 1); + createBacklightConversionSplines(); + } + + private float rawBacklightToNits(int i, float backlight) { + return MathUtils.map(mRawBacklight[i], mRawBacklight[i + 1], + mRawNits[i], mRawNits[i + 1], backlight); + } + + // This method creates a brightness spline that is of equal length with proportional increments + // to the backlight spline. The values of this array range from 0.0f to 1.0f instead of the + // potential constrained range that the backlight array covers + // These splines are used to convert from the system brightness value to the HAL backlight + // value + private void createBacklightConversionSplines() { + mBrightness = new float[mBacklight.length]; + for (int i = 0; i < mBrightness.length; i++) { + mBrightness[i] = MathUtils.map(mBacklight[0], + mBacklight[mBacklight.length - 1], + PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, mBacklight[i]); + } + mBrightnessToBacklightSpline = Spline.createSpline(mBrightness, mBacklight); + mBacklightToBrightnessSpline = Spline.createSpline(mBacklight, mBrightness); } private void loadQuirks(DisplayConfiguration config) { @@ -425,12 +587,14 @@ public class DisplayDeviceConfig { mIsHighBrightnessModeEnabled = hbm.getEnabled(); mHbmData = new HighBrightnessModeData(); mHbmData.minimumLux = hbm.getMinimumLux_all().floatValue(); - mHbmData.transitionPoint = hbm.getTransitionPoint_all().floatValue(); - if (mHbmData.transitionPoint >= getMaxBrightness()) { + float transitionPointBacklightScale = hbm.getTransitionPoint_all().floatValue(); + if (transitionPointBacklightScale >= mBacklightMaximum) { throw new IllegalArgumentException("HBM transition point invalid. " + mHbmData.transitionPoint + " is not less than " - + getMaxBrightness()); + + mBacklightMaximum); } + mHbmData.transitionPoint = + mBacklightToBrightnessSpline.interpolate(transitionPointBacklightScale); final HbmTiming hbmTiming = hbm.getTiming_all(); mHbmData.timeWindowMillis = hbmTiming.getTimeWindowSecs_all().longValue() * 1000; mHbmData.timeMaxMillis = hbmTiming.getTimeMaxSecs_all().longValue() * 1000; diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 62cf86b311807..2005a742c3d3f 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -190,12 +190,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // The dim screen brightness. private final float mScreenBrightnessDimConfig; - // The minimum allowed brightness. - private final float mScreenBrightnessRangeMinimum; - - // The maximum allowed brightness. - private final float mScreenBrightnessRangeMaximum; - private final float mScreenBrightnessDefault; // The minimum allowed brightness while in VR. @@ -443,8 +437,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call final Resources resources = context.getResources(); - final float screenBrightnessSettingMinimumFloat = clampAbsoluteBrightness( - pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM)); // DOZE AND DIM SETTINGS mScreenBrightnessDozeConfig = clampAbsoluteBrightness( @@ -453,10 +445,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM)); // NORMAL SCREEN SETTINGS - mScreenBrightnessRangeMinimum = - Math.min(screenBrightnessSettingMinimumFloat, mScreenBrightnessDimConfig); - mScreenBrightnessRangeMaximum = clampAbsoluteBrightness( - pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM)); mScreenBrightnessDefault = clampAbsoluteBrightness( mLogicalDisplay.getDisplayInfoLocked().brightnessDefault); @@ -545,12 +533,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call com.android.internal.R.string.config_displayLightSensorType); Sensor lightSensor = findDisplayLightSensor(lightSensorType); - mBrightnessMapper = BrightnessMappingStrategy.create(resources); + final DisplayDeviceConfig ddc = + logicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig(); + mBrightnessMapper = BrightnessMappingStrategy.create(resources, ddc); if (mBrightnessMapper != null) { mAutomaticBrightnessController = new AutomaticBrightnessController(this, handler.getLooper(), sensorManager, lightSensor, mBrightnessMapper, - lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum, - mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate, + lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN, + PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate, initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds, screenBrightnessThresholds, logicalDisplay, context); @@ -838,9 +828,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call noteScreenBrightness(mPowerState.getScreenBrightness()); // Initialize all of the brightness tracking state - final float brightness = convertToNits(BrightnessSynchronizer.brightnessFloatToInt( - mPowerState.getScreenBrightness())); - if (brightness >= 0.0f) { + final float brightness = convertToNits(mPowerState.getScreenBrightness()); + if (brightness >= PowerManager.BRIGHTNESS_MIN) { mBrightnessTracker.start(brightness); } @@ -1151,10 +1140,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Apply dimming by at least some minimum amount when user activity // timeout is about to expire. if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { - if (brightnessState > mScreenBrightnessRangeMinimum) { + if (brightnessState > PowerManager.BRIGHTNESS_MIN) { brightnessState = Math.max(Math.min(brightnessState - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT, - mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum); + mScreenBrightnessDimConfig), PowerManager.BRIGHTNESS_MIN); mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED); } if (!mAppliedDimming) { @@ -1168,12 +1157,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor // as long as it is above the minimum threshold. if (mPowerRequest.lowPowerMode) { - if (brightnessState > mScreenBrightnessRangeMinimum) { + if (brightnessState > PowerManager.BRIGHTNESS_MIN) { final float brightnessFactor = Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1); final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor); - brightnessState = Math.max(lowPowerBrightnessFloat, - mScreenBrightnessRangeMinimum); + brightnessState = Math.max(lowPowerBrightnessFloat, PowerManager.BRIGHTNESS_MIN); mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER); } if (!mAppliedLowPower) { @@ -1258,9 +1246,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // slider event so notify as if the system changed the brightness. userInitiatedChange = false; } - notifyBrightnessChanged( - BrightnessSynchronizer.brightnessFloatToInt(brightnessState), - userInitiatedChange, hadUserBrightnessPoint); + notifyBrightnessChanged(brightnessState, userInitiatedChange, + hadUserBrightnessPoint); } } @@ -1487,17 +1474,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private float clampScreenBrightness(float value) { if (Float.isNaN(value)) { - return mScreenBrightnessRangeMinimum; + return PowerManager.BRIGHTNESS_MIN; } return MathUtils.constrain( - value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum); + value, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX); } // Checks whether the brightness is within the valid brightness range, not including the off or // invalid states. private boolean isValidBrightnessValue(float brightnessState) { - return brightnessState >= mScreenBrightnessRangeMinimum - && brightnessState <= mScreenBrightnessRangeMaximum; + return brightnessState >= PowerManager.BRIGHTNESS_MIN + && brightnessState <= PowerManager.BRIGHTNESS_MAX; } private void animateScreenBrightness(float target, float rate) { @@ -1874,7 +1861,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call return true; } - private void notifyBrightnessChanged(int brightness, boolean userInitiated, + private void notifyBrightnessChanged(float brightness, boolean userInitiated, boolean hadUserDataPoint) { final float brightnessInNits = convertToNits(brightness); if (mPowerRequest.useAutoBrightness && brightnessInNits >= 0.0f @@ -1891,9 +1878,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } - private float convertToNits(int backlight) { + private float convertToNits(float brightness) { if (mBrightnessMapper != null) { - return mBrightnessMapper.convertToNits(backlight); + return mBrightnessMapper.convertToNits(brightness); } else { return -1.0f; } @@ -1972,12 +1959,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pw.println(); pw.println("Display Power Controller Configuration:"); - pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); - pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); pw.println(" mScreenBrightnessRangeDefault=" + mScreenBrightnessDefault); pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig); pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig); - pw.println(" mScreenBrightnessDefault=" + mScreenBrightnessDefault); pw.println(" mScreenBrightnessForVrRangeMinimum=" + mScreenBrightnessForVrRangeMinimum); pw.println(" mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum); pw.println(" mScreenBrightnessForVrDefault=" + mScreenBrightnessForVrDefault); @@ -2109,10 +2093,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } - private static int clampAbsoluteBrightness(int value) { - return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); - } - private static float clampAbsoluteBrightness(float value) { return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX); diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 5b2b3366b1175..48f335d775723 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -30,7 +30,6 @@ import android.os.Trace; import android.util.LongSparseArray; import android.util.Slog; import android.util.SparseArray; -import android.util.Spline; import android.view.Display; import android.view.DisplayAddress; import android.view.DisplayCutout; @@ -210,8 +209,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { private SurfaceControl.DisplayMode[] mSfDisplayModes; // The active display mode in SurfaceFlinger private SurfaceControl.DisplayMode mActiveSfDisplayMode; - private Spline mSystemBrightnessToNits; - private Spline mNitsToHalBrightness; + private DisplayDeviceConfig mDisplayDeviceConfig; private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides = new DisplayEventReceiver.FrameRateOverride[0]; @@ -410,16 +408,13 @@ final class LocalDisplayAdapter extends DisplayAdapter { @Override public DisplayDeviceConfig getDisplayDeviceConfig() { if (mDisplayDeviceConfig == null) { - loadDisplayConfiguration(); + loadDisplayDeviceConfig(); } return mDisplayDeviceConfig; } - private void loadDisplayConfiguration() { - Spline nitsToHal = null; - Spline sysToNits = null; - - // Load the mapping from nits to HAL brightness range (display-device-config.xml) + private void loadDisplayDeviceConfig() { + // Load display device config final Context context = getOverlayContext(); mDisplayDeviceConfig = DisplayDeviceConfig.create(context, mPhysicalDisplayId, mIsDefaultDisplay); @@ -427,33 +422,9 @@ final class LocalDisplayAdapter extends DisplayAdapter { return; } + // Load brightness HWC quirk mBacklightAdapter.setForceSurfaceControl(mDisplayDeviceConfig.hasQuirk( DisplayDeviceConfig.QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC)); - - final float[] halNits = mDisplayDeviceConfig.getNits(); - final float[] halBrightness = mDisplayDeviceConfig.getBrightness(); - if (halNits == null || halBrightness == null) { - return; - } - nitsToHal = Spline.createSpline(halNits, halBrightness); - - // Load the mapping from system brightness range to nits (config.xml) - final Resources res = context.getResources(); - final float[] sysNits = BrightnessMappingStrategy.getFloatArray(res.obtainTypedArray( - com.android.internal.R.array.config_screenBrightnessNits)); - final int[] sysBrightness = res.getIntArray( - com.android.internal.R.array.config_screenBrightnessBacklight); - if (sysNits.length == 0 || sysBrightness.length != sysNits.length) { - return; - } - final float[] sysBrightnessFloat = new float[sysBrightness.length]; - for (int i = 0; i < sysBrightness.length; i++) { - sysBrightnessFloat[i] = sysBrightness[i]; - } - sysToNits = Spline.createSpline(sysBrightnessFloat, sysNits); - - mNitsToHalBrightness = nitsToHal; - mSystemBrightnessToNits = sysToNits; } private boolean updateStaticInfo(SurfaceControl.StaticDisplayInfo info) { @@ -665,13 +636,11 @@ final class LocalDisplayAdapter extends DisplayAdapter { // The display is trusted since it is created by system. mInfo.flags |= DisplayDeviceInfo.FLAG_TRUSTED; + mInfo.brightnessMinimum = PowerManager.BRIGHTNESS_MIN; + mInfo.brightnessMaximum = PowerManager.BRIGHTNESS_MAX; if (mDisplayDeviceConfig != null) { - mInfo.brightnessMinimum = mDisplayDeviceConfig.getBrightnessMinimum(); - mInfo.brightnessMaximum = mDisplayDeviceConfig.getBrightnessMaximum(); mInfo.brightnessDefault = mDisplayDeviceConfig.getBrightnessDefault(); } else { - mInfo.brightnessMinimum = PowerManager.BRIGHTNESS_MIN; - mInfo.brightnessMaximum = PowerManager.BRIGHTNESS_MAX; mInfo.brightnessDefault = 0.5f; } } @@ -811,8 +780,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness(" + "id=" + physicalDisplayId + ", brightness=" + brightness + ")"); try { - brightness = displayBrightnessToHalBrightness(brightness); - mBacklightAdapter.setBrightness(brightness); + float backlight = brightnessToBacklight(brightness); + mBacklightAdapter.setBacklight(backlight); Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenBrightness", BrightnessSynchronizer.brightnessFloatToInt(brightness)); @@ -821,35 +790,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { } } - /** - * Converts brightness range from the framework's brightness space to the - * Hal brightness space if the HAL brightness space has been provided via - * a display device configuration file. - */ - private float displayBrightnessToHalBrightness(float brightness) { - // TODO: b/171380847 - This needs to be deprecated. The nits-to-brightness - // relationship should be specified in display-config OR config.xml, but not - // both, and no nits-space conversion should be necessary. - // - // Only do a conversion if there exists a unique system brightness and a - // unique HAL brightness-to-nits range defined. - if (mSystemBrightnessToNits == null || mNitsToHalBrightness == null) { - return brightness; - } - - // Sys brightness in this conversion is always specified in the old 1-255 - // range, so convert that here before the translation. - final float brightnessInt = - BrightnessSynchronizer.brightnessFloatToIntRange(brightness); - - if (BrightnessSynchronizer.floatEquals( - brightnessInt, PowerManager.BRIGHTNESS_OFF)) { - return PowerManager.BRIGHTNESS_OFF_FLOAT; - } - - final float nits = mSystemBrightnessToNits.interpolate(brightnessInt); - final float halBrightness = mNitsToHalBrightness.interpolate(nits); - return halBrightness; + private float brightnessToBacklight(float brightness) { + return getDisplayDeviceConfig().getBacklightFromBrightness(brightness); } }; } @@ -1338,11 +1280,12 @@ final class LocalDisplayAdapter extends DisplayAdapter { } } - void setBrightness(float brightness) { + // Set backlight within min and max backlight values + void setBacklight(float backlight) { if (mUseSurfaceControlBrightness || mForceSurfaceControl) { - mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, brightness); + mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, backlight); } else if (mBacklight != null) { - mBacklight.setBrightness(brightness); + mBacklight.setBrightness(backlight); } } diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java index 728b97cc3968b..18184b0a82afc 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -27,11 +27,14 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyFloat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; +import android.content.res.TypedArray; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -44,6 +47,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.dx.mockito.inline.extended.StaticMockitoSession; +import com.android.internal.R; import com.android.server.LocalServices; import com.android.server.display.LocalDisplayAdapter.BacklightAdapter; import com.android.server.lights.LightsManager; @@ -98,6 +102,9 @@ public class LocalDisplayAdapterTest { @Mock private LocalDisplayAdapter.SurfaceControlProxy mSurfaceControlProxy; + private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f }; + private static final int[] BACKLIGHT_RANGE = { 1, 255 }; + private static final float[] BACKLIGHT_RANGE_ZERO_TO_ONE = { 0.0f, 1.0f }; @Before public void setUp() throws Exception { @@ -114,6 +121,18 @@ public class LocalDisplayAdapterTest { mListener, mInjector); spyOn(mAdapter); doReturn(mMockedContext).when(mAdapter).getOverlayContext(); + + TypedArray mockNitsRange = createFloatTypedArray(DISPLAY_RANGE_NITS); + when(mMockedResources.obtainTypedArray(R.array.config_screenBrightnessNits)) + .thenReturn(mockNitsRange); + when(mMockedResources.getIntArray(R.array.config_screenBrightnessBacklight)) + .thenReturn(BACKLIGHT_RANGE); + when(mMockedResources.getFloat(com.android.internal.R.dimen + .config_screenBrightnessSettingMinimumFloat)) + .thenReturn(BACKLIGHT_RANGE_ZERO_TO_ONE[0]); + when(mMockedResources.getFloat(com.android.internal.R.dimen + .config_screenBrightnessSettingMaximumFloat)) + .thenReturn(BACKLIGHT_RANGE_ZERO_TO_ONE[1]); } @After @@ -629,13 +648,13 @@ public class LocalDisplayAdapterTest { // Test as default display BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/, mSurfaceControlProxy); - ba.setBrightness(0.514f); + ba.setBacklight(0.514f); verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.514f); // Test as not default display BacklightAdapter ba2 = new BacklightAdapter(displayToken, false /*isDefault*/, mSurfaceControlProxy); - ba2.setBrightness(0.323f); + ba2.setBacklight(0.323f); verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.323f); } @@ -648,7 +667,7 @@ public class LocalDisplayAdapterTest { BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/, mSurfaceControlProxy); - ba.setBrightness(0.123f); + ba.setBacklight(0.123f); verify(mMockedBacklight).setBrightness(0.123f); } @@ -661,7 +680,7 @@ public class LocalDisplayAdapterTest { BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/, mSurfaceControlProxy); - ba.setBrightness(0.456f); + ba.setBacklight(0.456f); // Adapter does not forward any brightness in this case. verify(mMockedBacklight, never()).setBrightness(anyFloat()); @@ -864,4 +883,23 @@ public class LocalDisplayAdapterTest { } } + private TypedArray createFloatTypedArray(float[] vals) { + TypedArray mockArray = mock(TypedArray.class); + when(mockArray.length()).thenAnswer(invocation -> { + return vals.length; + }); + when(mockArray.getFloat(anyInt(), anyFloat())).thenAnswer(invocation -> { + final float def = (float) invocation.getArguments()[1]; + if (vals == null) { + return def; + } + int idx = (int) invocation.getArguments()[0]; + if (idx >= 0 && idx < vals.length) { + return vals[idx]; + } else { + return def; + } + }); + return mockArray; + } } diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java index 23a4c2f417c5b..54825ee2745a6 100644 --- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java @@ -64,7 +64,6 @@ public class AutomaticBrightnessControllerTest { @Mock HysteresisLevels mAmbientBrightnessThresholds; @Mock HysteresisLevels mScreenBrightnessThresholds; @Mock Handler mNoOpHandler; - @Mock DisplayDeviceConfig mDisplayDeviceConfig; @Mock DisplayDevice mDisplayDevice; private static final int LIGHT_SENSOR_WARMUP_TIME = 0; 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 f0b4f1bec77b9..285806b5dcd70 100644 --- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java +++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java @@ -88,7 +88,9 @@ public class BrightnessMappingStrategyTest { }; private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f }; - private static final int[] BACKLIGHT_RANGE = { 1, 255 }; + 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 }; private static final float[] EMPTY_FLOAT_ARRAY = new float[0]; private static final int[] EMPTY_INT_ARRAY = new int[0]; @@ -114,25 +116,28 @@ public class BrightnessMappingStrategyTest { }; private static final Spline GAMMA_CORRECTION_SPLINE = Spline.createSpline( new float[] { 0.0f, 100.0f, 1000.0f, 2500.0f, 4000.0f, 4900.0f, 5000.0f }, - new float[] { 0.035f, 0.035f, 0.221f, 0.523f, 0.797f, 0.980f, 1.0f }); + new float[] { 0.0475f, 0.0475f, 0.2225f, 0.5140f, 0.8056f, 0.9805f, 1.0f }); @Test public void testSimpleStrategyMappingAtControlPoints() { Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT); - BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res, ddc); assertNotNull("BrightnessMappingStrategy should not be null", simple); for (int i = 0; i < LUX_LEVELS.length; i++) { - final float expectedLevel = - (float) DISPLAY_LEVELS_BACKLIGHT[i] / PowerManager.BRIGHTNESS_ON; + final float expectedLevel = MathUtils.map(PowerManager.BRIGHTNESS_OFF + 1, + PowerManager.BRIGHTNESS_ON, PowerManager.BRIGHTNESS_MIN, + PowerManager.BRIGHTNESS_MAX, DISPLAY_LEVELS_BACKLIGHT[i]); assertEquals(expectedLevel, - simple.getBrightness(LUX_LEVELS[i]), 0.01f /*tolerance*/); + simple.getBrightness(LUX_LEVELS[i]), 0.0001f /*tolerance*/); } } @Test public void testSimpleStrategyMappingBetweenControlPoints() { Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT); - BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res, ddc); assertNotNull("BrightnessMappingStrategy should not be null", simple); for (int i = 1; i < LUX_LEVELS.length; i++) { final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2; @@ -146,66 +151,71 @@ public class BrightnessMappingStrategyTest { @Test public void testSimpleStrategyIgnoresNewConfiguration() { Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc); - final int N = LUX_LEVELS.length; final float[] lux = { 0f, 1f }; final float[] nits = { 0, PowerManager.BRIGHTNESS_ON }; BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits) .build(); strategy.setBrightnessConfiguration(config); - assertNotEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/); + assertNotEquals(1.0f, strategy.getBrightness(1f), 0.0001f /*tolerance*/); } @Test public void testSimpleStrategyIgnoresNullConfiguration() { Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc); strategy.setBrightnessConfiguration(null); final int N = DISPLAY_LEVELS_BACKLIGHT.length; final float expectedBrightness = (float) DISPLAY_LEVELS_BACKLIGHT[N - 1] / PowerManager.BRIGHTNESS_ON; assertEquals(expectedBrightness, - strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01 /*tolerance*/); + strategy.getBrightness(LUX_LEVELS[N - 1]), 0.0001f /*tolerance*/); } @Test public void testPhysicalStrategyMappingAtControlPoints() { - Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, - DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); - BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res); + Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc); assertNotNull("BrightnessMappingStrategy should not be null", physical); for (int i = 0; i < LUX_LEVELS.length; i++) { - final float expectedLevel = DISPLAY_LEVELS_NITS[i] / DISPLAY_RANGE_NITS[1]; + final float expectedLevel = MathUtils.map(DISPLAY_RANGE_NITS[0], DISPLAY_RANGE_NITS[1], + DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT[0], + DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT[1], + DISPLAY_LEVELS_NITS[i]); assertEquals(expectedLevel, - physical.getBrightness(LUX_LEVELS[i]), 0.01f /*tolerance*/); + physical.getBrightness(LUX_LEVELS[i]), + 0.0001f /*tolerance*/); } } @Test public void testPhysicalStrategyMappingBetweenControlPoints() { - Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, - DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); - BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res); + Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS); + DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE); + BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc); assertNotNull("BrightnessMappingStrategy should not be null", physical); - Spline backlightToBrightness = - Spline.createSpline(toFloatArray(BACKLIGHT_RANGE), DISPLAY_RANGE_NITS); + Spline brightnessToNits = + Spline.createSpline(BACKLIGHT_RANGE_ZERO_TO_ONE, DISPLAY_RANGE_NITS); for (int i = 1; i < LUX_LEVELS.length; i++) { - final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2; - final float backlight = physical.getBrightness(lux) * PowerManager.BRIGHTNESS_ON; - final float nits = backlightToBrightness.interpolate(backlight); - assertTrue("Desired brightness should be between adjacent control points.", + final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2.0f; + final float brightness = physical.getBrightness(lux); + final float nits = brightnessToNits.interpolate(brightness); + assertTrue("Desired brightness should be between adjacent control points: " + nits, nits > DISPLAY_LEVELS_NITS[i - 1] && nits < DISPLAY_LEVELS_NITS[i]); } } @Test public void testPhysicalStrategyUsesNewConfigurations() { - Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, - DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); + Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc); final float[] lux = { 0f, 1f }; final float[] nits = { @@ -216,46 +226,53 @@ public class BrightnessMappingStrategyTest { BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits) .build(); strategy.setBrightnessConfiguration(config); - assertEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/); + assertEquals(1.0f, strategy.getBrightness(1f), 0.0001f /*tolerance*/); // Check that null returns us to the default configuration. strategy.setBrightnessConfiguration(null); final int N = DISPLAY_LEVELS_NITS.length; final float expectedBrightness = DISPLAY_LEVELS_NITS[N - 1] / DISPLAY_RANGE_NITS[1]; assertEquals(expectedBrightness, - strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01f /*tolerance*/); + strategy.getBrightness(LUX_LEVELS[N - 1]), 0.0001f /*tolerance*/); } @Test public void testPhysicalStrategyRecalculateSplines() { - Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, - BACKLIGHT_RANGE); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); + Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS); + DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc); float[] adjustedNits50p = new float[DISPLAY_RANGE_NITS.length]; for (int i = 0; i < DISPLAY_RANGE_NITS.length; i++) { adjustedNits50p[i] = DISPLAY_RANGE_NITS[i] * 0.5f; } // Default is unadjusted - assertEquals(2.685f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */); - assertEquals(478.5f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */); + assertEquals(DISPLAY_RANGE_NITS[0], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]), + 0.0001f /* tolerance */); + assertEquals(DISPLAY_RANGE_NITS[1], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[1]), + 0.0001f /* tolerance */); // When adjustment is turned on, adjustment array is used strategy.recalculateSplines(true, adjustedNits50p); - assertEquals(1.3425f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */); - assertEquals(239.25f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */); + assertEquals(DISPLAY_RANGE_NITS[0] / 2, + strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]), 0.0001f /* tolerance */); + assertEquals(DISPLAY_RANGE_NITS[1] / 2, + strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[1]), 0.0001f /* tolerance */); // When adjustment is turned off, adjustment array is ignored strategy.recalculateSplines(false, adjustedNits50p); - assertEquals(2.685f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */); - assertEquals(478.5f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */); + assertEquals(DISPLAY_RANGE_NITS[0], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]), + 0.0001f /* tolerance */); + assertEquals(DISPLAY_RANGE_NITS[1], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[1]), + 0.0001f /* tolerance */); } @Test public void testDefaultStrategyIsPhysical() { Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT, - DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); + DISPLAY_LEVELS_NITS); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc); assertTrue(strategy instanceof BrightnessMappingStrategy.PhysicalMappingStrategy); } @@ -266,15 +283,15 @@ public class BrightnessMappingStrategyTest { int tmp = lux[idx]; lux[idx] = lux[idx+1]; lux[idx+1] = tmp; - Resources res = createResources(lux, DISPLAY_LEVELS_NITS, - DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); + Resources res = createResources(lux, DISPLAY_LEVELS_NITS); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc); assertNull(strategy); // And make sure we get the same result even if it's monotone but not increasing. lux[idx] = lux[idx+1]; - res = createResources(lux, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); - strategy = BrightnessMappingStrategy.create(res); + res = createResources(lux, DISPLAY_LEVELS_NITS); + strategy = BrightnessMappingStrategy.create(res, ddc); assertNull(strategy); } @@ -285,13 +302,13 @@ public class BrightnessMappingStrategyTest { // Make sure it's strictly increasing so that the only failure is the differing array // lengths lux[lux.length - 1] = lux[lux.length - 2] + 1; - Resources res = createResources(lux, DISPLAY_LEVELS_NITS, - DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); + Resources res = createResources(lux, DISPLAY_LEVELS_NITS); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc); assertNull(strategy); res = createResources(lux, DISPLAY_LEVELS_BACKLIGHT); - strategy = BrightnessMappingStrategy.create(res); + strategy = BrightnessMappingStrategy.create(res, ddc); assertNull(strategy); // Extra backlight level @@ -299,43 +316,45 @@ public class BrightnessMappingStrategyTest { DISPLAY_LEVELS_BACKLIGHT, DISPLAY_LEVELS_BACKLIGHT.length+1); backlight[backlight.length - 1] = backlight[backlight.length - 2] + 1; res = createResources(LUX_LEVELS, backlight); - strategy = BrightnessMappingStrategy.create(res); + strategy = BrightnessMappingStrategy.create(res, ddc); assertNull(strategy); // Extra nits level final float[] nits = Arrays.copyOf(DISPLAY_RANGE_NITS, DISPLAY_LEVELS_NITS.length+1); nits[nits.length - 1] = nits[nits.length - 2] + 1; - res = createResources(LUX_LEVELS, nits, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); - strategy = BrightnessMappingStrategy.create(res); + res = createResources(LUX_LEVELS, nits); + strategy = BrightnessMappingStrategy.create(res, ddc); assertNull(strategy); } @Test public void testPhysicalStrategyRequiresNitsMapping() { Resources res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/, - DISPLAY_LEVELS_NITS, EMPTY_FLOAT_ARRAY /*nitsRange*/, BACKLIGHT_RANGE); - BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res); + DISPLAY_LEVELS_NITS); + DisplayDeviceConfig ddc = createDdc(EMPTY_FLOAT_ARRAY /*nitsRange*/); + BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc); assertNull(physical); res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/, - DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, EMPTY_INT_ARRAY /*backlightRange*/); - physical = BrightnessMappingStrategy.create(res); + DISPLAY_LEVELS_NITS); + physical = BrightnessMappingStrategy.create(res, ddc); assertNull(physical); res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/, - DISPLAY_LEVELS_NITS, EMPTY_FLOAT_ARRAY /*nitsRange*/, - EMPTY_INT_ARRAY /*backlightRange*/); - physical = BrightnessMappingStrategy.create(res); + DISPLAY_LEVELS_NITS); + physical = BrightnessMappingStrategy.create(res, ddc); assertNull(physical); } @Test public void testStrategiesAdaptToUserDataPoint() { - Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, - DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); - assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res)); + Resources res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/, + DISPLAY_LEVELS_NITS); + DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE); + assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res, ddc)); + ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE); res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT); - assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res)); + assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res, ddc)); } private static void assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy strategy) { @@ -351,7 +370,7 @@ public class BrightnessMappingStrategyTest { // Then make sure that all control points after the middle lux level are also set to max... for (int i = idx; i < LUX_LEVELS.length; i++) { - assertEquals(strategy.getBrightness(LUX_LEVELS[idx]), 1.0, 0.01 /*tolerance*/); + assertEquals(strategy.getBrightness(LUX_LEVELS[idx]), 1.0, 0.0001f /*tolerance*/); } // ...and that all control points before the middle lux level are strictly less than the @@ -369,12 +388,12 @@ public class BrightnessMappingStrategyTest { strategy.clearUserDataPoints(); for (int i = 0; i < LUX_LEVELS.length; i++) { assertEquals(initialBrightnessLevels[i], strategy.getBrightness(LUX_LEVELS[i]), - 0.01 /*tolerance*/); + 0.0001f /*tolerance*/); } // Now set the middle of the lux range to something just above the minimum. float minBrightness = strategy.getBrightness(LUX_LEVELS[0]); - strategy.addUserDataPoint(LUX_LEVELS[idx], minBrightness + 0.01f); + strategy.addUserDataPoint(LUX_LEVELS[idx], minBrightness + 0.0001f); // Then make sure the curve is still monotonic. prevBrightness = 0f; @@ -389,31 +408,21 @@ public class BrightnessMappingStrategyTest { // be true assuming that there are more than two lux levels in the curve since we picked a // brightness just barely above the minimum for the middle of the curve. minBrightness = (float) MathUtils.pow(minBrightness, MAXIMUM_GAMMA); // Gamma correction. - assertEquals(minBrightness, strategy.getBrightness(LUX_LEVELS[0]), 0.01 /*tolerance*/); - } - - private static float[] toFloatArray(int[] vals) { - float[] newVals = new float[vals.length]; - for (int i = 0; i < vals.length; i++) { - newVals[i] = (float) vals[i]; - } - return newVals; + assertEquals(minBrightness, strategy.getBrightness(LUX_LEVELS[0]), 0.0001f /*tolerance*/); } private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight) { return createResources(luxLevels, brightnessLevelsBacklight, - EMPTY_FLOAT_ARRAY /*brightnessLevelsNits*/, EMPTY_FLOAT_ARRAY /*nitsRange*/, - EMPTY_INT_ARRAY /*backlightRange*/); + EMPTY_FLOAT_ARRAY /*brightnessLevelsNits*/); } - private Resources createResources(int[] luxLevels, float[] brightnessLevelsNits, - float[] nitsRange, int[] backlightRange) { + private Resources createResources(int[] luxLevels, float[] brightnessLevelsNits) { return createResources(luxLevels, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/, - brightnessLevelsNits, nitsRange, backlightRange); + brightnessLevelsNits); } private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight, - float[] brightnessLevelsNits, float[] nitsRange, int[] backlightRange) { + float[] brightnessLevelsNits) { 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. @@ -430,15 +439,6 @@ public class BrightnessMappingStrategyTest { com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)) .thenReturn(mockBrightnessLevelNits); - TypedArray mockNitsRange = createFloatTypedArray(nitsRange); - when(mockResources.obtainTypedArray( - com.android.internal.R.array.config_screenBrightnessNits)) - .thenReturn(mockNitsRange); - - when(mockResources.getIntArray( - com.android.internal.R.array.config_screenBrightnessBacklight)) - .thenReturn(backlightRange); - when(mockResources.getInteger( com.android.internal.R.integer.config_screenBrightnessSettingMinimum)) .thenReturn(1); @@ -451,6 +451,21 @@ public class BrightnessMappingStrategyTest { return mockResources; } + private DisplayDeviceConfig createDdc() { + return createDdc(DISPLAY_RANGE_NITS); + } + + private DisplayDeviceConfig createDdc(float[] nitsArray) { + return createDdc(nitsArray, DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT); + } + + private DisplayDeviceConfig createDdc(float[] nitsArray, float[] backlightArray) { + DisplayDeviceConfig mockDdc = mock(DisplayDeviceConfig.class); + when(mockDdc.getNits()).thenReturn(nitsArray); + when(mockDdc.getBrightness()).thenReturn(backlightArray); + return mockDdc; + } + private TypedArray createFloatTypedArray(float[] vals) { TypedArray mockArray = mock(TypedArray.class); when(mockArray.length()).thenAnswer(invocation -> { @@ -488,21 +503,22 @@ public class BrightnessMappingStrategyTest { final float y1 = GAMMA_CORRECTION_SPLINE.interpolate(x1); final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2); final float y3 = GAMMA_CORRECTION_SPLINE.interpolate(x3); - Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS, - DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); + + Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc); // Let's start with a validity check: - assertEquals(y1, strategy.getBrightness(x1), 0.01f /* tolerance */); - assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */); - assertEquals(y3, strategy.getBrightness(x3), 0.01f /* tolerance */); + assertEquals(y1, strategy.getBrightness(x1), 0.0001f /* tolerance */); + assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */); + assertEquals(y3, strategy.getBrightness(x3), 0.0001f /* tolerance */); // OK, let's roll: float gamma = 0.5f; strategy.addUserDataPoint(x2, (float) MathUtils.pow(y2, gamma)); - assertEquals(MathUtils.pow(y1, gamma), strategy.getBrightness(x1), 0.01f /* tolerance */); - assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */); - assertEquals(MathUtils.pow(y3, gamma), strategy.getBrightness(x3), 0.01f /* tolerance */); - // The adjustment should be +0.63 (manual calculation). - assertEquals(+0.63f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); + assertEquals(MathUtils.pow(y1, gamma), strategy.getBrightness(x1), 0.0001f /* tolerance */); + assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */); + assertEquals(MathUtils.pow(y3, gamma), strategy.getBrightness(x3), 0.0001f /* tolerance */); + // The adjustment should be +0.6308 (manual calculation). + assertEquals(+0.6308f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */); } @Test @@ -516,39 +532,39 @@ public class BrightnessMappingStrategyTest { final float y1 = GAMMA_CORRECTION_SPLINE.interpolate(x1); final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2); final float y3 = GAMMA_CORRECTION_SPLINE.interpolate(x3); - Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS, - DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); + Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc); // Validity check: - assertEquals(y1, strategy.getBrightness(x1), 0.01f /* tolerance */); - assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */); - assertEquals(y3, strategy.getBrightness(x3), 0.01f /* tolerance */); + assertEquals(y1, strategy.getBrightness(x1), 0.0001f /* tolerance */); + assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */); + assertEquals(y3, strategy.getBrightness(x3), 0.0001f /* tolerance */); // Let's roll: float gamma = 0.25f; final float minGamma = 1.0f / MAXIMUM_GAMMA; strategy.addUserDataPoint(x2, (float) MathUtils.pow(y2, gamma)); - assertEquals(MathUtils.pow(y1, minGamma), strategy.getBrightness(x1), - 0.01f /* tolerance */); - assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), - 0.01f /* tolerance */); - assertEquals(MathUtils.pow(y3, minGamma), strategy.getBrightness(x3), - 0.01f /* tolerance */); + assertEquals(MathUtils.pow(y1, minGamma), + strategy.getBrightness(x1), 0.0001f /* tolerance */); + assertEquals(MathUtils.pow(y2, gamma), + strategy.getBrightness(x2), 0.0001f /* tolerance */); + assertEquals(MathUtils.pow(y3, minGamma), + strategy.getBrightness(x3), 0.0001f /* tolerance */); // The adjustment should be +1.0 (maximum adjustment). - assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); + assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */); } @Test public void testGammaCorrectionExtremeChangeAtCenter() { // Extreme changes (e.g. setting brightness to 0.0 or 1.0) can't be gamma corrected, so we // just make sure the adjustment reflects the change. - Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS, - DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); - assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); + Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc); + assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */); strategy.addUserDataPoint(2500, 1.0f); - assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); + assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */); strategy.addUserDataPoint(2500, 0.0f); - assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); + assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */); } @Test @@ -562,28 +578,28 @@ public class BrightnessMappingStrategyTest { final float y0 = GAMMA_CORRECTION_SPLINE.interpolate(x0); final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2); final float y4 = GAMMA_CORRECTION_SPLINE.interpolate(x4); - Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS, - DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); - BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); + Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS); + DisplayDeviceConfig ddc = createDdc(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc); // Validity, as per tradition: - assertEquals(y0, strategy.getBrightness(x0), 0.01f /* tolerance */); - assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */); - assertEquals(y4, strategy.getBrightness(x4), 0.01f /* tolerance */); + assertEquals(y0, strategy.getBrightness(x0), 0.0001f /* tolerance */); + assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */); + assertEquals(y4, strategy.getBrightness(x4), 0.0001f /* tolerance */); // Rollin': float adjustment = 0.3f; float gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment); strategy.addUserDataPoint(x0, y0 + adjustment); - assertEquals(y0 + adjustment, strategy.getBrightness(x0), 0.01f /* tolerance */); - assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */); - assertEquals(MathUtils.pow(y4, gamma), strategy.getBrightness(x4), 0.01f /* tolerance */); - assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); + assertEquals(y0 + adjustment, strategy.getBrightness(x0), 0.0001f /* tolerance */); + assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */); + assertEquals(MathUtils.pow(y4, gamma), strategy.getBrightness(x4), 0.0001f /* tolerance */); + assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */); // Similarly, if we set a user data point at (x4, 1.0), the adjustment should be 1 - y4. adjustment = 1.0f - y4; gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment); strategy.addUserDataPoint(x4, 1.0f); - assertEquals(MathUtils.pow(y0, gamma), strategy.getBrightness(x0), 0.01f /* tolerance */); - assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */); - assertEquals(1.0f, strategy.getBrightness(x4), 0.01f /* tolerance */); - assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); + assertEquals(MathUtils.pow(y0, gamma), strategy.getBrightness(x0), 0.0001f /* tolerance */); + assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */); + assertEquals(1.0f, strategy.getBrightness(x4), 0.0001f /* tolerance */); + assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */); } }