Merge "Change BrightnessMappingStrategy to use DDC values" into sc-dev am: 26715c82b6

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13431734

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I22632984d47438a68286f9ad1f7249213cc9587e
This commit is contained in:
Fiona Campbell
2021-02-25 14:30:04 +00:00
committed by Automerger Merge Worker
8 changed files with 483 additions and 359 deletions

View File

@@ -72,8 +72,6 @@ public class BrightnessController implements ToggleSlider.Listener {
private static final Uri BRIGHTNESS_FOR_VR_FLOAT_URI = private static final Uri BRIGHTNESS_FOR_VR_FLOAT_URI =
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT); 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 mDefaultBacklight;
private final float mMinimumBacklightForVr; private final float mMinimumBacklightForVr;
private final float mMaximumBacklightForVr; private final float mMaximumBacklightForVr;
@@ -314,10 +312,6 @@ public class BrightnessController implements ToggleSlider.Listener {
mDisplayId = mContext.getDisplayId(); mDisplayId = mContext.getDisplayId();
PowerManager pm = context.getSystemService(PowerManager.class); 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(); mDefaultBacklight = mContext.getDisplay().getBrightnessDefault();
mMinimumBacklightForVr = pm.getBrightnessConstraint( mMinimumBacklightForVr = pm.getBrightnessConstraint(
PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR); PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR);
@@ -375,8 +369,8 @@ public class BrightnessController implements ToggleSlider.Listener {
metric = mAutomatic metric = mAutomatic
? MetricsEvent.ACTION_BRIGHTNESS_AUTO ? MetricsEvent.ACTION_BRIGHTNESS_AUTO
: MetricsEvent.ACTION_BRIGHTNESS; : MetricsEvent.ACTION_BRIGHTNESS;
minBacklight = mMinimumBacklight; minBacklight = PowerManager.BRIGHTNESS_MIN;
maxBacklight = mMaximumBacklight; maxBacklight = PowerManager.BRIGHTNESS_MAX;
settingToChange = Settings.System.SCREEN_BRIGHTNESS_FLOAT; settingToChange = Settings.System.SCREEN_BRIGHTNESS_FLOAT;
} }
final float valFloat = MathUtils.min(convertGammaToLinearFloat(value, final float valFloat = MathUtils.min(convertGammaToLinearFloat(value,
@@ -439,8 +433,8 @@ public class BrightnessController implements ToggleSlider.Listener {
min = mMinimumBacklightForVr; min = mMinimumBacklightForVr;
max = mMaximumBacklightForVr; max = mMaximumBacklightForVr;
} else { } else {
min = mMinimumBacklight; min = PowerManager.BRIGHTNESS_MIN;
max = mMaximumBacklight; max = PowerManager.BRIGHTNESS_MAX;
} }
// convertGammaToLinearFloat returns 0-1 // convertGammaToLinearFloat returns 0-1
if (BrightnessSynchronizer.floatEquals(brightnessValue, if (BrightnessSynchronizer.floatEquals(brightnessValue,

View File

@@ -61,7 +61,10 @@ public abstract class BrightnessMappingStrategy {
private static final Plog PLOG = Plog.createSystemPlog(TAG); private static final Plog PLOG = Plog.createSystemPlog(TAG);
@Nullable @Nullable
public static BrightnessMappingStrategy create(Resources resources) { public static BrightnessMappingStrategy create(Resources resources,
DisplayDeviceConfig displayDeviceConfig) {
// Display independent values
float[] luxLevels = getLuxLevels(resources.getIntArray( float[] luxLevels = getLuxLevels(resources.getIntArray(
com.android.internal.R.array.config_autoBrightnessLevels)); com.android.internal.R.array.config_autoBrightnessLevels));
int[] brightnessLevelsBacklight = resources.getIntArray( int[] brightnessLevelsBacklight = resources.getIntArray(
@@ -71,32 +74,22 @@ public abstract class BrightnessMappingStrategy {
float autoBrightnessAdjustmentMaxGamma = resources.getFraction( float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma, com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
1, 1); 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( long shortTermModelTimeout = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessShortTermModelTimeout); 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)) { && 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( BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
luxLevels, brightnessLevelsNits); luxLevels, brightnessLevelsNits);
builder.setShortTermModelTimeoutMillis(shortTermModelTimeout); builder.setShortTermModelTimeoutMillis(shortTermModelTimeout);
builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO); builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
builder.setShortTermModelUpperLuxMultiplier(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); autoBrightnessAdjustmentMaxGamma);
} else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) { } else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight, return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight,
@@ -264,11 +257,11 @@ public abstract class BrightnessMappingStrategy {
public abstract boolean setAutoBrightnessAdjustment(float adjustment); 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. * Adds a user interaction data point to the brightness mapping.
@@ -603,7 +596,7 @@ public abstract class BrightnessMappingStrategy {
} }
@Override @Override
public float convertToNits(int backlight) { public float convertToNits(float brightness) {
return -1.0f; return -1.0f;
} }
@@ -701,37 +694,39 @@ public abstract class BrightnessMappingStrategy {
// in nits. // in nits.
private Spline mBrightnessSpline; 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]. // [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. // The default brightness configuration.
private final BrightnessConfiguration mDefaultConfig; private final BrightnessConfiguration mDefaultConfig;
// A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to private final float[] mNits;
// a brightness in nits. private final float[] mBrightness;
private Spline mBacklightToNitsSpline;
private float[] mNits;
private int[] mBacklight;
private boolean mBrightnessRangeAdjustmentApplied; private boolean mBrightnessRangeAdjustmentApplied;
private float mMaxGamma; private final float mMaxGamma;
private float mAutoBrightnessAdjustment; private float mAutoBrightnessAdjustment;
private float mUserLux; private float mUserLux;
private float mUserBrightness; private float mUserBrightness;
public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits, public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits,
int[] backlight, float maxGamma) { float[] brightness, float maxGamma) {
Preconditions.checkArgument(nits.length != 0 && backlight.length != 0,
"Nits and backlight arrays must not be empty!"); Preconditions.checkArgument(nits.length != 0 && brightness.length != 0,
Preconditions.checkArgument(nits.length == backlight.length, "Nits and brightness arrays must not be empty!");
"Nits and backlight arrays must be the same length!");
Preconditions.checkArgument(nits.length == brightness.length,
"Nits and brightness arrays must be the same length!");
Objects.requireNonNull(config); Objects.requireNonNull(config);
Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits"); Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits");
Preconditions.checkArrayElementsInRange(backlight, Preconditions.checkArrayElementsInRange(brightness,
PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON, "backlight"); PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, "brightness");
mMaxGamma = maxGamma; mMaxGamma = maxGamma;
mAutoBrightnessAdjustment = 0; mAutoBrightnessAdjustment = 0;
@@ -739,7 +734,7 @@ public abstract class BrightnessMappingStrategy {
mUserBrightness = -1; mUserBrightness = -1;
mNits = nits; mNits = nits;
mBacklight = backlight; mBrightness = brightness;
computeNitsBrightnessSplines(mNits); computeNitsBrightnessSplines(mNits);
mDefaultConfig = config; mDefaultConfig = config;
@@ -784,15 +779,15 @@ public abstract class BrightnessMappingStrategy {
public float getBrightness(float lux, String packageName, public float getBrightness(float lux, String packageName,
@ApplicationInfo.Category int category) { @ApplicationInfo.Category int category) {
float nits = mBrightnessSpline.interpolate(lux); 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 // 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) { if (mUserLux == -1) {
backlight = correctBrightness(backlight, packageName, category); brightness = correctBrightness(brightness, packageName, category);
} else if (mLoggingEnabled) { } else if (mLoggingEnabled) {
Slog.d(TAG, "user point set, correction not applied"); Slog.d(TAG, "user point set, correction not applied");
} }
return backlight; return brightness;
} }
@Override @Override
@@ -817,8 +812,8 @@ public abstract class BrightnessMappingStrategy {
} }
@Override @Override
public float convertToNits(int backlight) { public float convertToNits(float brightness) {
return mBacklightToNitsSpline.interpolate(normalizeAbsoluteBrightness(backlight)); return mBrightnessToNitsSpline.interpolate(brightness);
} }
@Override @Override
@@ -884,7 +879,8 @@ public abstract class BrightnessMappingStrategy {
pw.println("PhysicalMappingStrategy"); pw.println("PhysicalMappingStrategy");
pw.println(" mConfig=" + mConfig); pw.println(" mConfig=" + mConfig);
pw.println(" mBrightnessSpline=" + mBrightnessSpline); pw.println(" mBrightnessSpline=" + mBrightnessSpline);
pw.println(" mNitsToBacklightSpline=" + mNitsToBacklightSpline); pw.println(" mNitsToBrightnessSpline=" + mNitsToBrightnessSpline);
pw.println(" mBrightnessToNitsSpline=" + mBrightnessToNitsSpline);
pw.println(" mMaxGamma=" + mMaxGamma); pw.println(" mMaxGamma=" + mMaxGamma);
pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment); pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
pw.println(" mUserLux=" + mUserLux); pw.println(" mUserLux=" + mUserLux);
@@ -894,31 +890,25 @@ public abstract class BrightnessMappingStrategy {
} }
private void computeNitsBrightnessSplines(float[] nits) { private void computeNitsBrightnessSplines(float[] nits) {
final int len = nits.length; mNitsToBrightnessSpline = Spline.createSpline(nits, mBrightness);
float[] normalizedBacklight = new float[len]; mBrightnessToNitsSpline = Spline.createSpline(mBrightness, nits);
for (int i = 0; i < len; i++) {
normalizedBacklight[i] = normalizeAbsoluteBrightness(mBacklight[i]);
}
mNitsToBacklightSpline = Spline.createSpline(nits, normalizedBacklight);
mBacklightToNitsSpline = Spline.createSpline(normalizedBacklight, nits);
} }
private void computeSpline() { private void computeSpline() {
Pair<float[], float[]> defaultCurve = mConfig.getCurve(); Pair<float[], float[]> defaultCurve = mConfig.getCurve();
float[] defaultLux = defaultCurve.first; float[] defaultLux = defaultCurve.first;
float[] defaultNits = defaultCurve.second; float[] defaultNits = defaultCurve.second;
float[] defaultBacklight = new float[defaultNits.length]; float[] defaultBrightness = new float[defaultNits.length];
for (int i = 0; i < defaultBacklight.length; i++) { for (int i = 0; i < defaultBrightness.length; i++) {
defaultBacklight[i] = mNitsToBacklightSpline.interpolate(defaultNits[i]); defaultBrightness[i] = mNitsToBrightnessSpline.interpolate(defaultNits[i]);
} }
Pair<float[], float[]> curve = getAdjustedCurve(defaultLux, defaultBacklight, mUserLux, Pair<float[], float[]> curve = getAdjustedCurve(defaultLux, defaultBrightness, mUserLux,
mUserBrightness, mAutoBrightnessAdjustment, mMaxGamma); mUserBrightness, mAutoBrightnessAdjustment, mMaxGamma);
float[] lux = curve.first; float[] lux = curve.first;
float[] backlight = curve.second; float[] brightness = curve.second;
float[] nits = new float[backlight.length]; float[] nits = new float[brightness.length];
for (int i = 0; i < nits.length; i++) { 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); mBrightnessSpline = Spline.createSpline(lux, nits);
} }
@@ -926,7 +916,7 @@ public abstract class BrightnessMappingStrategy {
private float getUnadjustedBrightness(float lux) { private float getUnadjustedBrightness(float lux) {
Pair<float[], float[]> curve = mConfig.getCurve(); Pair<float[], float[]> curve = mConfig.getCurve();
Spline spline = Spline.createSpline(curve.first, curve.second); 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) { private float correctBrightness(float brightness, String packageName, int category) {

View File

@@ -18,9 +18,12 @@ package com.android.server.display;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.os.Environment; import android.os.Environment;
import android.os.PowerManager; import android.os.PowerManager;
import android.util.MathUtils;
import android.util.Slog; import android.util.Slog;
import android.util.Spline;
import android.view.DisplayAddress; import android.view.DisplayAddress;
import com.android.internal.R; import com.android.internal.R;
@@ -72,15 +75,31 @@ public class DisplayDeviceConfig {
private final Context mContext; 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; 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[] 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 mBrightnessDefault = Float.NaN;
private float mBrightnessRampFastDecrease = Float.NaN; private float mBrightnessRampFastDecrease = Float.NaN;
private float mBrightnessRampFastIncrease = Float.NaN; private float mBrightnessRampFastIncrease = Float.NaN;
private float mBrightnessRampSlowDecrease = Float.NaN; private float mBrightnessRampSlowDecrease = Float.NaN;
private float mBrightnessRampSlowIncrease = Float.NaN; private float mBrightnessRampSlowIncrease = Float.NaN;
private Spline mBrightnessToBacklightSpline;
private Spline mBacklightToBrightnessSpline;
private List<String> mQuirks; private List<String> mQuirks;
private boolean mIsHighBrightnessModeEnabled = false; private boolean mIsHighBrightnessModeEnabled = false;
private HighBrightnessModeData mHbmData; 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. * @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() { public float[] getBrightness() {
return mBrightness; return mBrightness;
} }
public float getBrightnessMinimum() { /**
return mBrightnessMinimum; * Return the default brightness on a scale of 0.0f - 1.0f
} *
* @return default brightness
public float getBrightnessMaximum() { */
return mBrightnessMaximum;
}
public float getBrightnessDefault() { public float getBrightnessDefault() {
return mBrightnessDefault; return mBrightnessDefault;
} }
@@ -237,10 +274,15 @@ public class DisplayDeviceConfig {
@Override @Override
public String toString() { public String toString() {
String str = "DisplayDeviceConfig{" String str = "DisplayDeviceConfig{"
+ "mBrightness=" + Arrays.toString(mBrightness) + "mBacklight=" + Arrays.toString(mBacklight)
+ ", mNits=" + Arrays.toString(mNits) + ", mNits=" + Arrays.toString(mNits)
+ ", mBrightnessMinimum=" + mBrightnessMinimum + ", mRawBacklight=" + Arrays.toString(mRawBacklight)
+ ", mBrightnessMaximum=" + mBrightnessMaximum + ", mRawNits=" + Arrays.toString(mRawNits)
+ ", mBrightness=" + Arrays.toString(mBrightness)
+ ", mBrightnessToBacklightSpline=" + mBrightnessToBacklightSpline
+ ", mBacklightToBrightnessSpline=" + mBacklightToBrightnessSpline
+ ", mBacklightMinimum=" + mBacklightMinimum
+ ", mBacklightMaximum=" + mBacklightMaximum
+ ", mBrightnessDefault=" + mBrightnessDefault + ", mBrightnessDefault=" + mBrightnessDefault
+ ", mQuirks=" + mQuirks + ", mQuirks=" + mQuirks
+ ", isHbmEnabled=" + mIsHighBrightnessModeEnabled + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled
@@ -253,10 +295,6 @@ public class DisplayDeviceConfig {
return str; return str;
} }
private float getMaxBrightness() {
return mBrightness[mBrightness.length - 1];
}
private static DisplayDeviceConfig getConfigFromSuffix(Context context, File baseDirectory, private static DisplayDeviceConfig getConfigFromSuffix(Context context, File baseDirectory,
String suffixFormat, long idNumber) { String suffixFormat, long idNumber) {
@@ -264,7 +302,6 @@ public class DisplayDeviceConfig {
final String filename = String.format(CONFIG_FILE_FORMAT, suffix); final String filename = String.format(CONFIG_FILE_FORMAT, suffix);
final File filePath = Environment.buildPath( final File filePath = Environment.buildPath(
baseDirectory, ETC_DIR, DISPLAY_CONFIG_DIR, filename); baseDirectory, ETC_DIR, DISPLAY_CONFIG_DIR, filename);
if (filePath.exists()) { if (filePath.exists()) {
final DisplayDeviceConfig config = new DisplayDeviceConfig(context); final DisplayDeviceConfig config = new DisplayDeviceConfig(context);
config.initFromFile(filePath); config.initFromFile(filePath);
@@ -299,9 +336,9 @@ public class DisplayDeviceConfig {
try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) { try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
final DisplayConfiguration config = XmlParser.read(in); final DisplayConfiguration config = XmlParser.read(in);
if (config != null) { if (config != null) {
loadBrightnessMap(config);
loadBrightnessDefaultFromDdcXml(config); loadBrightnessDefaultFromDdcXml(config);
loadBrightnessConstraintsFromConfigXml(); loadBrightnessConstraintsFromConfigXml();
loadBrightnessMap(config);
loadHighBrightnessModeData(config); loadHighBrightnessModeData(config);
loadQuirks(config); loadQuirks(config);
loadBrightnessRamps(config); loadBrightnessRamps(config);
@@ -318,13 +355,20 @@ public class DisplayDeviceConfig {
// If no ddc exists, use config.xml // If no ddc exists, use config.xml
loadBrightnessDefaultFromConfigXml(); loadBrightnessDefaultFromConfigXml();
loadBrightnessConstraintsFromConfigXml(); loadBrightnessConstraintsFromConfigXml();
loadBrightnessMapFromConfigXml();
loadBrightnessRampsFromConfigXml(); loadBrightnessRampsFromConfigXml();
} }
private void initFromPmValues() { private void initFromPmValues() {
mBrightnessMinimum = PowerManager.BRIGHTNESS_MIN; // Set all to basic values
mBrightnessMaximum = PowerManager.BRIGHTNESS_MAX; mBacklightMinimum = PowerManager.BRIGHTNESS_MIN;
mBacklightMaximum = PowerManager.BRIGHTNESS_MAX;
mBrightnessDefault = BRIGHTNESS_DEFAULT; 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) { private void loadBrightnessDefaultFromDdcXml(DisplayConfiguration config) {
@@ -364,24 +408,27 @@ public class DisplayDeviceConfig {
final float max = mContext.getResources().getFloat(com.android.internal.R.dimen final float max = mContext.getResources().getFloat(com.android.internal.R.dimen
.config_screenBrightnessSettingMaximumFloat); .config_screenBrightnessSettingMaximumFloat);
if (min == INVALID_BRIGHTNESS_IN_CONFIG || max == INVALID_BRIGHTNESS_IN_CONFIG) { 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 mContext.getResources().getInteger(com.android.internal.R.integer
.config_screenBrightnessSettingMinimum)); .config_screenBrightnessSettingMinimum));
mBrightnessMaximum = BrightnessSynchronizer.brightnessIntToFloat( mBacklightMaximum = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer mContext.getResources().getInteger(com.android.internal.R.integer
.config_screenBrightnessSettingMaximum)); .config_screenBrightnessSettingMaximum));
} else { } else {
mBrightnessMinimum = min; mBacklightMinimum = min;
mBrightnessMaximum = max; mBacklightMaximum = max;
} }
} }
private void loadBrightnessMap(DisplayConfiguration config) { private void loadBrightnessMap(DisplayConfiguration config) {
final NitsMap map = config.getScreenBrightnessMap(); final NitsMap map = config.getScreenBrightnessMap();
// Map may not exist in config file // Map may not exist in display device config
if (map == null) { if (map == null) {
loadBrightnessMapFromConfigXml();
return; return;
} }
// Use the (preferred) display device config mapping
final List<Point> points = map.getPoint(); final List<Point> points = map.getPoint();
final int size = points.size(); final int size = points.size();
@@ -408,8 +455,123 @@ public class DisplayDeviceConfig {
} }
++i; ++i;
} }
mNits = nits; mRawNits = nits;
mBrightness = backlight; 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) { private void loadQuirks(DisplayConfiguration config) {
@@ -425,12 +587,14 @@ public class DisplayDeviceConfig {
mIsHighBrightnessModeEnabled = hbm.getEnabled(); mIsHighBrightnessModeEnabled = hbm.getEnabled();
mHbmData = new HighBrightnessModeData(); mHbmData = new HighBrightnessModeData();
mHbmData.minimumLux = hbm.getMinimumLux_all().floatValue(); mHbmData.minimumLux = hbm.getMinimumLux_all().floatValue();
mHbmData.transitionPoint = hbm.getTransitionPoint_all().floatValue(); float transitionPointBacklightScale = hbm.getTransitionPoint_all().floatValue();
if (mHbmData.transitionPoint >= getMaxBrightness()) { if (transitionPointBacklightScale >= mBacklightMaximum) {
throw new IllegalArgumentException("HBM transition point invalid. " throw new IllegalArgumentException("HBM transition point invalid. "
+ mHbmData.transitionPoint + " is not less than " + mHbmData.transitionPoint + " is not less than "
+ getMaxBrightness()); + mBacklightMaximum);
} }
mHbmData.transitionPoint =
mBacklightToBrightnessSpline.interpolate(transitionPointBacklightScale);
final HbmTiming hbmTiming = hbm.getTiming_all(); final HbmTiming hbmTiming = hbm.getTiming_all();
mHbmData.timeWindowMillis = hbmTiming.getTimeWindowSecs_all().longValue() * 1000; mHbmData.timeWindowMillis = hbmTiming.getTimeWindowSecs_all().longValue() * 1000;
mHbmData.timeMaxMillis = hbmTiming.getTimeMaxSecs_all().longValue() * 1000; mHbmData.timeMaxMillis = hbmTiming.getTimeMaxSecs_all().longValue() * 1000;

View File

@@ -190,12 +190,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// The dim screen brightness. // The dim screen brightness.
private final float mScreenBrightnessDimConfig; private final float mScreenBrightnessDimConfig;
// The minimum allowed brightness.
private final float mScreenBrightnessRangeMinimum;
// The maximum allowed brightness.
private final float mScreenBrightnessRangeMaximum;
private final float mScreenBrightnessDefault; private final float mScreenBrightnessDefault;
// The minimum allowed brightness while in VR. // The minimum allowed brightness while in VR.
@@ -443,8 +437,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
final Resources resources = context.getResources(); final Resources resources = context.getResources();
final float screenBrightnessSettingMinimumFloat = clampAbsoluteBrightness(
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM));
// DOZE AND DIM SETTINGS // DOZE AND DIM SETTINGS
mScreenBrightnessDozeConfig = clampAbsoluteBrightness( mScreenBrightnessDozeConfig = clampAbsoluteBrightness(
@@ -453,10 +445,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM)); pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM));
// NORMAL SCREEN SETTINGS // NORMAL SCREEN SETTINGS
mScreenBrightnessRangeMinimum =
Math.min(screenBrightnessSettingMinimumFloat, mScreenBrightnessDimConfig);
mScreenBrightnessRangeMaximum = clampAbsoluteBrightness(
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM));
mScreenBrightnessDefault = clampAbsoluteBrightness( mScreenBrightnessDefault = clampAbsoluteBrightness(
mLogicalDisplay.getDisplayInfoLocked().brightnessDefault); mLogicalDisplay.getDisplayInfoLocked().brightnessDefault);
@@ -545,12 +533,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
com.android.internal.R.string.config_displayLightSensorType); com.android.internal.R.string.config_displayLightSensorType);
Sensor lightSensor = findDisplayLightSensor(lightSensorType); Sensor lightSensor = findDisplayLightSensor(lightSensorType);
mBrightnessMapper = BrightnessMappingStrategy.create(resources); final DisplayDeviceConfig ddc =
logicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig();
mBrightnessMapper = BrightnessMappingStrategy.create(resources, ddc);
if (mBrightnessMapper != null) { if (mBrightnessMapper != null) {
mAutomaticBrightnessController = new AutomaticBrightnessController(this, mAutomaticBrightnessController = new AutomaticBrightnessController(this,
handler.getLooper(), sensorManager, lightSensor, mBrightnessMapper, handler.getLooper(), sensorManager, lightSensor, mBrightnessMapper,
lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum, lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN,
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate, PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate,
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce, initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds, autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
screenBrightnessThresholds, logicalDisplay, context); screenBrightnessThresholds, logicalDisplay, context);
@@ -838,9 +828,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
noteScreenBrightness(mPowerState.getScreenBrightness()); noteScreenBrightness(mPowerState.getScreenBrightness());
// Initialize all of the brightness tracking state // Initialize all of the brightness tracking state
final float brightness = convertToNits(BrightnessSynchronizer.brightnessFloatToInt( final float brightness = convertToNits(mPowerState.getScreenBrightness());
mPowerState.getScreenBrightness())); if (brightness >= PowerManager.BRIGHTNESS_MIN) {
if (brightness >= 0.0f) {
mBrightnessTracker.start(brightness); mBrightnessTracker.start(brightness);
} }
@@ -1151,10 +1140,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Apply dimming by at least some minimum amount when user activity // Apply dimming by at least some minimum amount when user activity
// timeout is about to expire. // timeout is about to expire.
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
if (brightnessState > mScreenBrightnessRangeMinimum) { if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
brightnessState = Math.max(Math.min(brightnessState brightnessState = Math.max(Math.min(brightnessState
- SCREEN_DIM_MINIMUM_REDUCTION_FLOAT, - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum); mScreenBrightnessDimConfig), PowerManager.BRIGHTNESS_MIN);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED); mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
} }
if (!mAppliedDimming) { if (!mAppliedDimming) {
@@ -1168,12 +1157,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
// as long as it is above the minimum threshold. // as long as it is above the minimum threshold.
if (mPowerRequest.lowPowerMode) { if (mPowerRequest.lowPowerMode) {
if (brightnessState > mScreenBrightnessRangeMinimum) { if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
final float brightnessFactor = final float brightnessFactor =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1); Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor); final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
brightnessState = Math.max(lowPowerBrightnessFloat, brightnessState = Math.max(lowPowerBrightnessFloat, PowerManager.BRIGHTNESS_MIN);
mScreenBrightnessRangeMinimum);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER); mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
} }
if (!mAppliedLowPower) { if (!mAppliedLowPower) {
@@ -1258,9 +1246,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// slider event so notify as if the system changed the brightness. // slider event so notify as if the system changed the brightness.
userInitiatedChange = false; userInitiatedChange = false;
} }
notifyBrightnessChanged( notifyBrightnessChanged(brightnessState, userInitiatedChange,
BrightnessSynchronizer.brightnessFloatToInt(brightnessState), hadUserBrightnessPoint);
userInitiatedChange, hadUserBrightnessPoint);
} }
} }
@@ -1487,17 +1474,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private float clampScreenBrightness(float value) { private float clampScreenBrightness(float value) {
if (Float.isNaN(value)) { if (Float.isNaN(value)) {
return mScreenBrightnessRangeMinimum; return PowerManager.BRIGHTNESS_MIN;
} }
return MathUtils.constrain( 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 // Checks whether the brightness is within the valid brightness range, not including the off or
// invalid states. // invalid states.
private boolean isValidBrightnessValue(float brightnessState) { private boolean isValidBrightnessValue(float brightnessState) {
return brightnessState >= mScreenBrightnessRangeMinimum return brightnessState >= PowerManager.BRIGHTNESS_MIN
&& brightnessState <= mScreenBrightnessRangeMaximum; && brightnessState <= PowerManager.BRIGHTNESS_MAX;
} }
private void animateScreenBrightness(float target, float rate) { private void animateScreenBrightness(float target, float rate) {
@@ -1874,7 +1861,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return true; return true;
} }
private void notifyBrightnessChanged(int brightness, boolean userInitiated, private void notifyBrightnessChanged(float brightness, boolean userInitiated,
boolean hadUserDataPoint) { boolean hadUserDataPoint) {
final float brightnessInNits = convertToNits(brightness); final float brightnessInNits = convertToNits(brightness);
if (mPowerRequest.useAutoBrightness && brightnessInNits >= 0.0f 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) { if (mBrightnessMapper != null) {
return mBrightnessMapper.convertToNits(backlight); return mBrightnessMapper.convertToNits(brightness);
} else { } else {
return -1.0f; return -1.0f;
} }
@@ -1972,12 +1959,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(); pw.println();
pw.println("Display Power Controller Configuration:"); pw.println("Display Power Controller Configuration:");
pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
pw.println(" mScreenBrightnessRangeDefault=" + mScreenBrightnessDefault); pw.println(" mScreenBrightnessRangeDefault=" + mScreenBrightnessDefault);
pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig); pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig); pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
pw.println(" mScreenBrightnessDefault=" + mScreenBrightnessDefault);
pw.println(" mScreenBrightnessForVrRangeMinimum=" + mScreenBrightnessForVrRangeMinimum); pw.println(" mScreenBrightnessForVrRangeMinimum=" + mScreenBrightnessForVrRangeMinimum);
pw.println(" mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum); pw.println(" mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum);
pw.println(" mScreenBrightnessForVrDefault=" + mScreenBrightnessForVrDefault); 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) { private static float clampAbsoluteBrightness(float value) {
return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN, return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN,
PowerManager.BRIGHTNESS_MAX); PowerManager.BRIGHTNESS_MAX);

View File

@@ -30,7 +30,6 @@ import android.os.Trace;
import android.util.LongSparseArray; import android.util.LongSparseArray;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
import android.util.Spline;
import android.view.Display; import android.view.Display;
import android.view.DisplayAddress; import android.view.DisplayAddress;
import android.view.DisplayCutout; import android.view.DisplayCutout;
@@ -210,8 +209,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private SurfaceControl.DisplayMode[] mSfDisplayModes; private SurfaceControl.DisplayMode[] mSfDisplayModes;
// The active display mode in SurfaceFlinger // The active display mode in SurfaceFlinger
private SurfaceControl.DisplayMode mActiveSfDisplayMode; private SurfaceControl.DisplayMode mActiveSfDisplayMode;
private Spline mSystemBrightnessToNits; private DisplayDeviceConfig mDisplayDeviceConfig;
private Spline mNitsToHalBrightness;
private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides = private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides =
new DisplayEventReceiver.FrameRateOverride[0]; new DisplayEventReceiver.FrameRateOverride[0];
@@ -410,16 +408,13 @@ final class LocalDisplayAdapter extends DisplayAdapter {
@Override @Override
public DisplayDeviceConfig getDisplayDeviceConfig() { public DisplayDeviceConfig getDisplayDeviceConfig() {
if (mDisplayDeviceConfig == null) { if (mDisplayDeviceConfig == null) {
loadDisplayConfiguration(); loadDisplayDeviceConfig();
} }
return mDisplayDeviceConfig; return mDisplayDeviceConfig;
} }
private void loadDisplayConfiguration() { private void loadDisplayDeviceConfig() {
Spline nitsToHal = null; // Load display device config
Spline sysToNits = null;
// Load the mapping from nits to HAL brightness range (display-device-config.xml)
final Context context = getOverlayContext(); final Context context = getOverlayContext();
mDisplayDeviceConfig = DisplayDeviceConfig.create(context, mPhysicalDisplayId, mDisplayDeviceConfig = DisplayDeviceConfig.create(context, mPhysicalDisplayId,
mIsDefaultDisplay); mIsDefaultDisplay);
@@ -427,33 +422,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
return; return;
} }
// Load brightness HWC quirk
mBacklightAdapter.setForceSurfaceControl(mDisplayDeviceConfig.hasQuirk( mBacklightAdapter.setForceSurfaceControl(mDisplayDeviceConfig.hasQuirk(
DisplayDeviceConfig.QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC)); 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) { 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. // The display is trusted since it is created by system.
mInfo.flags |= DisplayDeviceInfo.FLAG_TRUSTED; mInfo.flags |= DisplayDeviceInfo.FLAG_TRUSTED;
mInfo.brightnessMinimum = PowerManager.BRIGHTNESS_MIN;
mInfo.brightnessMaximum = PowerManager.BRIGHTNESS_MAX;
if (mDisplayDeviceConfig != null) { if (mDisplayDeviceConfig != null) {
mInfo.brightnessMinimum = mDisplayDeviceConfig.getBrightnessMinimum();
mInfo.brightnessMaximum = mDisplayDeviceConfig.getBrightnessMaximum();
mInfo.brightnessDefault = mDisplayDeviceConfig.getBrightnessDefault(); mInfo.brightnessDefault = mDisplayDeviceConfig.getBrightnessDefault();
} else { } else {
mInfo.brightnessMinimum = PowerManager.BRIGHTNESS_MIN;
mInfo.brightnessMaximum = PowerManager.BRIGHTNESS_MAX;
mInfo.brightnessDefault = 0.5f; mInfo.brightnessDefault = 0.5f;
} }
} }
@@ -811,8 +780,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness(" Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
+ "id=" + physicalDisplayId + ", brightness=" + brightness + ")"); + "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
try { try {
brightness = displayBrightnessToHalBrightness(brightness); float backlight = brightnessToBacklight(brightness);
mBacklightAdapter.setBrightness(brightness); mBacklightAdapter.setBacklight(backlight);
Trace.traceCounter(Trace.TRACE_TAG_POWER, Trace.traceCounter(Trace.TRACE_TAG_POWER,
"ScreenBrightness", "ScreenBrightness",
BrightnessSynchronizer.brightnessFloatToInt(brightness)); BrightnessSynchronizer.brightnessFloatToInt(brightness));
@@ -821,35 +790,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
} }
} }
/** private float brightnessToBacklight(float brightness) {
* Converts brightness range from the framework's brightness space to the return getDisplayDeviceConfig().getBacklightFromBrightness(brightness);
* 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;
} }
}; };
} }
@@ -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) { if (mUseSurfaceControlBrightness || mForceSurfaceControl) {
mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, brightness); mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, backlight);
} else if (mBacklight != null) { } else if (mBacklight != null) {
mBacklight.setBrightness(brightness); mBacklight.setBrightness(backlight);
} }
} }

View File

@@ -27,11 +27,14 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyFloat; 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.never;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Binder; import android.os.Binder;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
@@ -44,6 +47,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.internal.R;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.android.server.display.LocalDisplayAdapter.BacklightAdapter; import com.android.server.display.LocalDisplayAdapter.BacklightAdapter;
import com.android.server.lights.LightsManager; import com.android.server.lights.LightsManager;
@@ -98,6 +102,9 @@ public class LocalDisplayAdapterTest {
@Mock @Mock
private LocalDisplayAdapter.SurfaceControlProxy mSurfaceControlProxy; 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 @Before
public void setUp() throws Exception { public void setUp() throws Exception {
@@ -114,6 +121,18 @@ public class LocalDisplayAdapterTest {
mListener, mInjector); mListener, mInjector);
spyOn(mAdapter); spyOn(mAdapter);
doReturn(mMockedContext).when(mAdapter).getOverlayContext(); 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 @After
@@ -629,13 +648,13 @@ public class LocalDisplayAdapterTest {
// Test as default display // Test as default display
BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/, BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
mSurfaceControlProxy); mSurfaceControlProxy);
ba.setBrightness(0.514f); ba.setBacklight(0.514f);
verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.514f); verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.514f);
// Test as not default display // Test as not default display
BacklightAdapter ba2 = new BacklightAdapter(displayToken, false /*isDefault*/, BacklightAdapter ba2 = new BacklightAdapter(displayToken, false /*isDefault*/,
mSurfaceControlProxy); mSurfaceControlProxy);
ba2.setBrightness(0.323f); ba2.setBacklight(0.323f);
verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.323f); verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.323f);
} }
@@ -648,7 +667,7 @@ public class LocalDisplayAdapterTest {
BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/, BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
mSurfaceControlProxy); mSurfaceControlProxy);
ba.setBrightness(0.123f); ba.setBacklight(0.123f);
verify(mMockedBacklight).setBrightness(0.123f); verify(mMockedBacklight).setBrightness(0.123f);
} }
@@ -661,7 +680,7 @@ public class LocalDisplayAdapterTest {
BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/, BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/,
mSurfaceControlProxy); mSurfaceControlProxy);
ba.setBrightness(0.456f); ba.setBacklight(0.456f);
// Adapter does not forward any brightness in this case. // Adapter does not forward any brightness in this case.
verify(mMockedBacklight, never()).setBrightness(anyFloat()); 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;
}
} }

View File

@@ -64,7 +64,6 @@ public class AutomaticBrightnessControllerTest {
@Mock HysteresisLevels mAmbientBrightnessThresholds; @Mock HysteresisLevels mAmbientBrightnessThresholds;
@Mock HysteresisLevels mScreenBrightnessThresholds; @Mock HysteresisLevels mScreenBrightnessThresholds;
@Mock Handler mNoOpHandler; @Mock Handler mNoOpHandler;
@Mock DisplayDeviceConfig mDisplayDeviceConfig;
@Mock DisplayDevice mDisplayDevice; @Mock DisplayDevice mDisplayDevice;
private static final int LIGHT_SENSOR_WARMUP_TIME = 0; private static final int LIGHT_SENSOR_WARMUP_TIME = 0;

View File

@@ -88,7 +88,9 @@ public class BrightnessMappingStrategyTest {
}; };
private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f }; 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 float[] EMPTY_FLOAT_ARRAY = new float[0];
private static final int[] EMPTY_INT_ARRAY = new int[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( 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.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 @Test
public void testSimpleStrategyMappingAtControlPoints() { public void testSimpleStrategyMappingAtControlPoints() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT); 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); assertNotNull("BrightnessMappingStrategy should not be null", simple);
for (int i = 0; i < LUX_LEVELS.length; i++) { for (int i = 0; i < LUX_LEVELS.length; i++) {
final float expectedLevel = final float expectedLevel = MathUtils.map(PowerManager.BRIGHTNESS_OFF + 1,
(float) DISPLAY_LEVELS_BACKLIGHT[i] / PowerManager.BRIGHTNESS_ON; PowerManager.BRIGHTNESS_ON, PowerManager.BRIGHTNESS_MIN,
PowerManager.BRIGHTNESS_MAX, DISPLAY_LEVELS_BACKLIGHT[i]);
assertEquals(expectedLevel, assertEquals(expectedLevel,
simple.getBrightness(LUX_LEVELS[i]), 0.01f /*tolerance*/); simple.getBrightness(LUX_LEVELS[i]), 0.0001f /*tolerance*/);
} }
} }
@Test @Test
public void testSimpleStrategyMappingBetweenControlPoints() { public void testSimpleStrategyMappingBetweenControlPoints() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT); 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); assertNotNull("BrightnessMappingStrategy should not be null", simple);
for (int i = 1; i < LUX_LEVELS.length; i++) { for (int i = 1; i < LUX_LEVELS.length; i++) {
final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2; final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2;
@@ -146,66 +151,71 @@ public class BrightnessMappingStrategyTest {
@Test @Test
public void testSimpleStrategyIgnoresNewConfiguration() { public void testSimpleStrategyIgnoresNewConfiguration() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT); 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[] lux = { 0f, 1f };
final float[] nits = { 0, PowerManager.BRIGHTNESS_ON }; final float[] nits = { 0, PowerManager.BRIGHTNESS_ON };
BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits) BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
.build(); .build();
strategy.setBrightnessConfiguration(config); strategy.setBrightnessConfiguration(config);
assertNotEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/); assertNotEquals(1.0f, strategy.getBrightness(1f), 0.0001f /*tolerance*/);
} }
@Test @Test
public void testSimpleStrategyIgnoresNullConfiguration() { public void testSimpleStrategyIgnoresNullConfiguration() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT); 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); strategy.setBrightnessConfiguration(null);
final int N = DISPLAY_LEVELS_BACKLIGHT.length; final int N = DISPLAY_LEVELS_BACKLIGHT.length;
final float expectedBrightness = final float expectedBrightness =
(float) DISPLAY_LEVELS_BACKLIGHT[N - 1] / PowerManager.BRIGHTNESS_ON; (float) DISPLAY_LEVELS_BACKLIGHT[N - 1] / PowerManager.BRIGHTNESS_ON;
assertEquals(expectedBrightness, assertEquals(expectedBrightness,
strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01 /*tolerance*/); strategy.getBrightness(LUX_LEVELS[N - 1]), 0.0001f /*tolerance*/);
} }
@Test @Test
public void testPhysicalStrategyMappingAtControlPoints() { public void testPhysicalStrategyMappingAtControlPoints() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); DisplayDeviceConfig ddc = createDdc();
BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res); BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc);
assertNotNull("BrightnessMappingStrategy should not be null", physical); assertNotNull("BrightnessMappingStrategy should not be null", physical);
for (int i = 0; i < LUX_LEVELS.length; i++) { 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, assertEquals(expectedLevel,
physical.getBrightness(LUX_LEVELS[i]), 0.01f /*tolerance*/); physical.getBrightness(LUX_LEVELS[i]),
0.0001f /*tolerance*/);
} }
} }
@Test @Test
public void testPhysicalStrategyMappingBetweenControlPoints() { public void testPhysicalStrategyMappingBetweenControlPoints() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE);
BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res); BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc);
assertNotNull("BrightnessMappingStrategy should not be null", physical); assertNotNull("BrightnessMappingStrategy should not be null", physical);
Spline backlightToBrightness = Spline brightnessToNits =
Spline.createSpline(toFloatArray(BACKLIGHT_RANGE), DISPLAY_RANGE_NITS); Spline.createSpline(BACKLIGHT_RANGE_ZERO_TO_ONE, DISPLAY_RANGE_NITS);
for (int i = 1; i < LUX_LEVELS.length; i++) { for (int i = 1; i < LUX_LEVELS.length; i++) {
final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2; final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2.0f;
final float backlight = physical.getBrightness(lux) * PowerManager.BRIGHTNESS_ON; final float brightness = physical.getBrightness(lux);
final float nits = backlightToBrightness.interpolate(backlight); final float nits = brightnessToNits.interpolate(brightness);
assertTrue("Desired brightness should be between adjacent control points.", assertTrue("Desired brightness should be between adjacent control points: " + nits,
nits > DISPLAY_LEVELS_NITS[i - 1] && nits < DISPLAY_LEVELS_NITS[i]); nits > DISPLAY_LEVELS_NITS[i - 1] && nits < DISPLAY_LEVELS_NITS[i]);
} }
} }
@Test @Test
public void testPhysicalStrategyUsesNewConfigurations() { public void testPhysicalStrategyUsesNewConfigurations() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); DisplayDeviceConfig ddc = createDdc();
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
final float[] lux = { 0f, 1f }; final float[] lux = { 0f, 1f };
final float[] nits = { final float[] nits = {
@@ -216,46 +226,53 @@ public class BrightnessMappingStrategyTest {
BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits) BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
.build(); .build();
strategy.setBrightnessConfiguration(config); 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. // Check that null returns us to the default configuration.
strategy.setBrightnessConfiguration(null); strategy.setBrightnessConfiguration(null);
final int N = DISPLAY_LEVELS_NITS.length; final int N = DISPLAY_LEVELS_NITS.length;
final float expectedBrightness = DISPLAY_LEVELS_NITS[N - 1] / DISPLAY_RANGE_NITS[1]; final float expectedBrightness = DISPLAY_LEVELS_NITS[N - 1] / DISPLAY_RANGE_NITS[1];
assertEquals(expectedBrightness, assertEquals(expectedBrightness,
strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01f /*tolerance*/); strategy.getBrightness(LUX_LEVELS[N - 1]), 0.0001f /*tolerance*/);
} }
@Test @Test
public void testPhysicalStrategyRecalculateSplines() { public void testPhysicalStrategyRecalculateSplines() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
BACKLIGHT_RANGE); DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS);
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
float[] adjustedNits50p = new float[DISPLAY_RANGE_NITS.length]; float[] adjustedNits50p = new float[DISPLAY_RANGE_NITS.length];
for (int i = 0; i < DISPLAY_RANGE_NITS.length; i++) { for (int i = 0; i < DISPLAY_RANGE_NITS.length; i++) {
adjustedNits50p[i] = DISPLAY_RANGE_NITS[i] * 0.5f; adjustedNits50p[i] = DISPLAY_RANGE_NITS[i] * 0.5f;
} }
// Default is unadjusted // Default is unadjusted
assertEquals(2.685f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */); assertEquals(DISPLAY_RANGE_NITS[0], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]),
assertEquals(478.5f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */); 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 // When adjustment is turned on, adjustment array is used
strategy.recalculateSplines(true, adjustedNits50p); strategy.recalculateSplines(true, adjustedNits50p);
assertEquals(1.3425f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */); assertEquals(DISPLAY_RANGE_NITS[0] / 2,
assertEquals(239.25f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */); 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 // When adjustment is turned off, adjustment array is ignored
strategy.recalculateSplines(false, adjustedNits50p); strategy.recalculateSplines(false, adjustedNits50p);
assertEquals(2.685f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */); assertEquals(DISPLAY_RANGE_NITS[0], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]),
assertEquals(478.5f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */); 0.0001f /* tolerance */);
assertEquals(DISPLAY_RANGE_NITS[1], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[1]),
0.0001f /* tolerance */);
} }
@Test @Test
public void testDefaultStrategyIsPhysical() { public void testDefaultStrategyIsPhysical() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT, Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT,
DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); DISPLAY_LEVELS_NITS);
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); DisplayDeviceConfig ddc = createDdc();
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
assertTrue(strategy instanceof BrightnessMappingStrategy.PhysicalMappingStrategy); assertTrue(strategy instanceof BrightnessMappingStrategy.PhysicalMappingStrategy);
} }
@@ -266,15 +283,15 @@ public class BrightnessMappingStrategyTest {
int tmp = lux[idx]; int tmp = lux[idx];
lux[idx] = lux[idx+1]; lux[idx] = lux[idx+1];
lux[idx+1] = tmp; lux[idx+1] = tmp;
Resources res = createResources(lux, DISPLAY_LEVELS_NITS, Resources res = createResources(lux, DISPLAY_LEVELS_NITS);
DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); DisplayDeviceConfig ddc = createDdc();
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy); assertNull(strategy);
// And make sure we get the same result even if it's monotone but not increasing. // And make sure we get the same result even if it's monotone but not increasing.
lux[idx] = lux[idx+1]; lux[idx] = lux[idx+1];
res = createResources(lux, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); res = createResources(lux, DISPLAY_LEVELS_NITS);
strategy = BrightnessMappingStrategy.create(res); strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy); assertNull(strategy);
} }
@@ -285,13 +302,13 @@ public class BrightnessMappingStrategyTest {
// Make sure it's strictly increasing so that the only failure is the differing array // Make sure it's strictly increasing so that the only failure is the differing array
// lengths // lengths
lux[lux.length - 1] = lux[lux.length - 2] + 1; lux[lux.length - 1] = lux[lux.length - 2] + 1;
Resources res = createResources(lux, DISPLAY_LEVELS_NITS, Resources res = createResources(lux, DISPLAY_LEVELS_NITS);
DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); DisplayDeviceConfig ddc = createDdc();
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res); BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy); assertNull(strategy);
res = createResources(lux, DISPLAY_LEVELS_BACKLIGHT); res = createResources(lux, DISPLAY_LEVELS_BACKLIGHT);
strategy = BrightnessMappingStrategy.create(res); strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy); assertNull(strategy);
// Extra backlight level // Extra backlight level
@@ -299,43 +316,45 @@ public class BrightnessMappingStrategyTest {
DISPLAY_LEVELS_BACKLIGHT, DISPLAY_LEVELS_BACKLIGHT.length+1); DISPLAY_LEVELS_BACKLIGHT, DISPLAY_LEVELS_BACKLIGHT.length+1);
backlight[backlight.length - 1] = backlight[backlight.length - 2] + 1; backlight[backlight.length - 1] = backlight[backlight.length - 2] + 1;
res = createResources(LUX_LEVELS, backlight); res = createResources(LUX_LEVELS, backlight);
strategy = BrightnessMappingStrategy.create(res); strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy); assertNull(strategy);
// Extra nits level // Extra nits level
final float[] nits = Arrays.copyOf(DISPLAY_RANGE_NITS, DISPLAY_LEVELS_NITS.length+1); final float[] nits = Arrays.copyOf(DISPLAY_RANGE_NITS, DISPLAY_LEVELS_NITS.length+1);
nits[nits.length - 1] = nits[nits.length - 2] + 1; nits[nits.length - 1] = nits[nits.length - 2] + 1;
res = createResources(LUX_LEVELS, nits, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); res = createResources(LUX_LEVELS, nits);
strategy = BrightnessMappingStrategy.create(res); strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy); assertNull(strategy);
} }
@Test @Test
public void testPhysicalStrategyRequiresNitsMapping() { public void testPhysicalStrategyRequiresNitsMapping() {
Resources res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/, Resources res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
DISPLAY_LEVELS_NITS, EMPTY_FLOAT_ARRAY /*nitsRange*/, BACKLIGHT_RANGE); DISPLAY_LEVELS_NITS);
BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res); DisplayDeviceConfig ddc = createDdc(EMPTY_FLOAT_ARRAY /*nitsRange*/);
BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc);
assertNull(physical); assertNull(physical);
res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/, res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, EMPTY_INT_ARRAY /*backlightRange*/); DISPLAY_LEVELS_NITS);
physical = BrightnessMappingStrategy.create(res); physical = BrightnessMappingStrategy.create(res, ddc);
assertNull(physical); assertNull(physical);
res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/, res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
DISPLAY_LEVELS_NITS, EMPTY_FLOAT_ARRAY /*nitsRange*/, DISPLAY_LEVELS_NITS);
EMPTY_INT_ARRAY /*backlightRange*/); physical = BrightnessMappingStrategy.create(res, ddc);
physical = BrightnessMappingStrategy.create(res);
assertNull(physical); assertNull(physical);
} }
@Test @Test
public void testStrategiesAdaptToUserDataPoint() { public void testStrategiesAdaptToUserDataPoint() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, Resources res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); DISPLAY_LEVELS_NITS);
assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res)); 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); res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res)); assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res, ddc));
} }
private static void assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy strategy) { 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... // 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++) { 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 // ...and that all control points before the middle lux level are strictly less than the
@@ -369,12 +388,12 @@ public class BrightnessMappingStrategyTest {
strategy.clearUserDataPoints(); strategy.clearUserDataPoints();
for (int i = 0; i < LUX_LEVELS.length; i++) { for (int i = 0; i < LUX_LEVELS.length; i++) {
assertEquals(initialBrightnessLevels[i], strategy.getBrightness(LUX_LEVELS[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. // Now set the middle of the lux range to something just above the minimum.
float minBrightness = strategy.getBrightness(LUX_LEVELS[0]); 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. // Then make sure the curve is still monotonic.
prevBrightness = 0f; 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 // 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. // brightness just barely above the minimum for the middle of the curve.
minBrightness = (float) MathUtils.pow(minBrightness, MAXIMUM_GAMMA); // Gamma correction. minBrightness = (float) MathUtils.pow(minBrightness, MAXIMUM_GAMMA); // Gamma correction.
assertEquals(minBrightness, strategy.getBrightness(LUX_LEVELS[0]), 0.01 /*tolerance*/); assertEquals(minBrightness, strategy.getBrightness(LUX_LEVELS[0]), 0.0001f /*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;
} }
private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight) { private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight) {
return createResources(luxLevels, brightnessLevelsBacklight, return createResources(luxLevels, brightnessLevelsBacklight,
EMPTY_FLOAT_ARRAY /*brightnessLevelsNits*/, EMPTY_FLOAT_ARRAY /*nitsRange*/, EMPTY_FLOAT_ARRAY /*brightnessLevelsNits*/);
EMPTY_INT_ARRAY /*backlightRange*/);
} }
private Resources createResources(int[] luxLevels, float[] brightnessLevelsNits, private Resources createResources(int[] luxLevels, float[] brightnessLevelsNits) {
float[] nitsRange, int[] backlightRange) {
return createResources(luxLevels, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/, return createResources(luxLevels, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
brightnessLevelsNits, nitsRange, backlightRange); brightnessLevelsNits);
} }
private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight, private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight,
float[] brightnessLevelsNits, float[] nitsRange, int[] backlightRange) { float[] brightnessLevelsNits) {
Resources mockResources = mock(Resources.class); Resources mockResources = mock(Resources.class);
// For historical reasons, the lux levels resource implicitly defines the first point as 0, // 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. // 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)) com.android.internal.R.array.config_autoBrightnessDisplayValuesNits))
.thenReturn(mockBrightnessLevelNits); .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( when(mockResources.getInteger(
com.android.internal.R.integer.config_screenBrightnessSettingMinimum)) com.android.internal.R.integer.config_screenBrightnessSettingMinimum))
.thenReturn(1); .thenReturn(1);
@@ -451,6 +451,21 @@ public class BrightnessMappingStrategyTest {
return mockResources; 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) { private TypedArray createFloatTypedArray(float[] vals) {
TypedArray mockArray = mock(TypedArray.class); TypedArray mockArray = mock(TypedArray.class);
when(mockArray.length()).thenAnswer(invocation -> { when(mockArray.length()).thenAnswer(invocation -> {
@@ -488,21 +503,22 @@ public class BrightnessMappingStrategyTest {
final float y1 = GAMMA_CORRECTION_SPLINE.interpolate(x1); final float y1 = GAMMA_CORRECTION_SPLINE.interpolate(x1);
final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2); final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2);
final float y3 = GAMMA_CORRECTION_SPLINE.interpolate(x3); final float y3 = GAMMA_CORRECTION_SPLINE.interpolate(x3);
Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS,
DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); DisplayDeviceConfig ddc = createDdc();
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
// Let's start with a validity check: // Let's start with a validity check:
assertEquals(y1, strategy.getBrightness(x1), 0.01f /* tolerance */); assertEquals(y1, strategy.getBrightness(x1), 0.0001f /* tolerance */);
assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */); assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */);
assertEquals(y3, strategy.getBrightness(x3), 0.01f /* tolerance */); assertEquals(y3, strategy.getBrightness(x3), 0.0001f /* tolerance */);
// OK, let's roll: // OK, let's roll:
float gamma = 0.5f; float gamma = 0.5f;
strategy.addUserDataPoint(x2, (float) MathUtils.pow(y2, gamma)); strategy.addUserDataPoint(x2, (float) MathUtils.pow(y2, gamma));
assertEquals(MathUtils.pow(y1, gamma), strategy.getBrightness(x1), 0.01f /* tolerance */); assertEquals(MathUtils.pow(y1, gamma), strategy.getBrightness(x1), 0.0001f /* tolerance */);
assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */); assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
assertEquals(MathUtils.pow(y3, gamma), strategy.getBrightness(x3), 0.01f /* tolerance */); assertEquals(MathUtils.pow(y3, gamma), strategy.getBrightness(x3), 0.0001f /* tolerance */);
// The adjustment should be +0.63 (manual calculation). // The adjustment should be +0.6308 (manual calculation).
assertEquals(+0.63f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); assertEquals(+0.6308f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
} }
@Test @Test
@@ -516,39 +532,39 @@ public class BrightnessMappingStrategyTest {
final float y1 = GAMMA_CORRECTION_SPLINE.interpolate(x1); final float y1 = GAMMA_CORRECTION_SPLINE.interpolate(x1);
final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2); final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2);
final float y3 = GAMMA_CORRECTION_SPLINE.interpolate(x3); final float y3 = GAMMA_CORRECTION_SPLINE.interpolate(x3);
Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS, Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); DisplayDeviceConfig ddc = createDdc();
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
// Validity check: // Validity check:
assertEquals(y1, strategy.getBrightness(x1), 0.01f /* tolerance */); assertEquals(y1, strategy.getBrightness(x1), 0.0001f /* tolerance */);
assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */); assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */);
assertEquals(y3, strategy.getBrightness(x3), 0.01f /* tolerance */); assertEquals(y3, strategy.getBrightness(x3), 0.0001f /* tolerance */);
// Let's roll: // Let's roll:
float gamma = 0.25f; float gamma = 0.25f;
final float minGamma = 1.0f / MAXIMUM_GAMMA; final float minGamma = 1.0f / MAXIMUM_GAMMA;
strategy.addUserDataPoint(x2, (float) MathUtils.pow(y2, gamma)); strategy.addUserDataPoint(x2, (float) MathUtils.pow(y2, gamma));
assertEquals(MathUtils.pow(y1, minGamma), strategy.getBrightness(x1), assertEquals(MathUtils.pow(y1, minGamma),
0.01f /* tolerance */); strategy.getBrightness(x1), 0.0001f /* tolerance */);
assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), assertEquals(MathUtils.pow(y2, gamma),
0.01f /* tolerance */); strategy.getBrightness(x2), 0.0001f /* tolerance */);
assertEquals(MathUtils.pow(y3, minGamma), strategy.getBrightness(x3), assertEquals(MathUtils.pow(y3, minGamma),
0.01f /* tolerance */); strategy.getBrightness(x3), 0.0001f /* tolerance */);
// The adjustment should be +1.0 (maximum adjustment). // 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 @Test
public void testGammaCorrectionExtremeChangeAtCenter() { public void testGammaCorrectionExtremeChangeAtCenter() {
// Extreme changes (e.g. setting brightness to 0.0 or 1.0) can't be gamma corrected, so we // 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. // just make sure the adjustment reflects the change.
Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS, Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); DisplayDeviceConfig ddc = createDdc();
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
strategy.addUserDataPoint(2500, 1.0f); 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); strategy.addUserDataPoint(2500, 0.0f);
assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
} }
@Test @Test
@@ -562,28 +578,28 @@ public class BrightnessMappingStrategyTest {
final float y0 = GAMMA_CORRECTION_SPLINE.interpolate(x0); final float y0 = GAMMA_CORRECTION_SPLINE.interpolate(x0);
final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2); final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2);
final float y4 = GAMMA_CORRECTION_SPLINE.interpolate(x4); final float y4 = GAMMA_CORRECTION_SPLINE.interpolate(x4);
Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS, Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT); DisplayDeviceConfig ddc = createDdc();
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources); BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
// Validity, as per tradition: // Validity, as per tradition:
assertEquals(y0, strategy.getBrightness(x0), 0.01f /* tolerance */); assertEquals(y0, strategy.getBrightness(x0), 0.0001f /* tolerance */);
assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */); assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */);
assertEquals(y4, strategy.getBrightness(x4), 0.01f /* tolerance */); assertEquals(y4, strategy.getBrightness(x4), 0.0001f /* tolerance */);
// Rollin': // Rollin':
float adjustment = 0.3f; float adjustment = 0.3f;
float gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment); float gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment);
strategy.addUserDataPoint(x0, y0 + adjustment); strategy.addUserDataPoint(x0, y0 + adjustment);
assertEquals(y0 + adjustment, strategy.getBrightness(x0), 0.01f /* tolerance */); assertEquals(y0 + adjustment, strategy.getBrightness(x0), 0.0001f /* tolerance */);
assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */); assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
assertEquals(MathUtils.pow(y4, gamma), strategy.getBrightness(x4), 0.01f /* tolerance */); assertEquals(MathUtils.pow(y4, gamma), strategy.getBrightness(x4), 0.0001f /* tolerance */);
assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.01f /* 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. // Similarly, if we set a user data point at (x4, 1.0), the adjustment should be 1 - y4.
adjustment = 1.0f - y4; adjustment = 1.0f - y4;
gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment); gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment);
strategy.addUserDataPoint(x4, 1.0f); strategy.addUserDataPoint(x4, 1.0f);
assertEquals(MathUtils.pow(y0, gamma), strategy.getBrightness(x0), 0.01f /* tolerance */); assertEquals(MathUtils.pow(y0, gamma), strategy.getBrightness(x0), 0.0001f /* tolerance */);
assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */); assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
assertEquals(1.0f, strategy.getBrightness(x4), 0.01f /* tolerance */); assertEquals(1.0f, strategy.getBrightness(x4), 0.0001f /* tolerance */);
assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */); assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
} }
} }