diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 683bc844d2644..c050adcb61a06 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2875,6 +2875,9 @@ package android.hardware.display {
field public final boolean nightMode;
field public final String packageName;
field public final float powerBrightnessFactor;
+ field public final boolean reduceBrightColors;
+ field public final float reduceBrightColorsOffset;
+ field public final int reduceBrightColorsStrength;
field public final long timeStamp;
}
diff --git a/core/java/android/hardware/display/BrightnessChangeEvent.java b/core/java/android/hardware/display/BrightnessChangeEvent.java
index e2d836c590998..a6c6b46d5b81d 100644
--- a/core/java/android/hardware/display/BrightnessChangeEvent.java
+++ b/core/java/android/hardware/display/BrightnessChangeEvent.java
@@ -65,6 +65,23 @@ public final class BrightnessChangeEvent implements Parcelable {
/** If night mode color filter is active this will be the temperature in kelvin */
public final int colorTemperature;
+ /** Whether the bright color reduction color transform is active */
+ public final boolean reduceBrightColors;
+
+ /** How strong the bright color reduction color transform is set (only applicable if active),
+ * specified as an integer from 0 - 100, inclusive. This value (scaled to 0-1, inclusive) is
+ * then used in Ynew = (a * scaledStrength^2 + b * scaledStrength + c) * Ycurrent, where a, b,
+ * and c are coefficients provided in the bright color reduction coefficient matrix, and
+ * Ycurrent is the current hardware brightness in nits.
+ */
+ public final int reduceBrightColorsStrength;
+
+ /** Applied offset for the bright color reduction color transform (only applicable if active).
+ * The offset is computed by summing the coefficients a, b, and c, from the coefficient matrix
+ * and multiplying by the current brightness.
+ */
+ public final float reduceBrightColorsOffset;
+
/** Brightness level before slider adjustment */
public final float lastBrightness;
@@ -105,8 +122,9 @@ public final class BrightnessChangeEvent implements Parcelable {
private BrightnessChangeEvent(float brightness, long timeStamp, String packageName,
int userId, float[] luxValues, long[] luxTimestamps, float batteryLevel,
float powerBrightnessFactor, boolean nightMode, int colorTemperature,
- float lastBrightness, boolean isDefaultBrightnessConfig, boolean isUserSetBrightness,
- long[] colorValueBuckets, long colorSampleDuration) {
+ boolean reduceBrightColors, int reduceBrightColorsStrength,
+ float reduceBrightColorsOffset, float lastBrightness, boolean isDefaultBrightnessConfig,
+ boolean isUserSetBrightness, long[] colorValueBuckets, long colorSampleDuration) {
this.brightness = brightness;
this.timeStamp = timeStamp;
this.packageName = packageName;
@@ -117,6 +135,9 @@ public final class BrightnessChangeEvent implements Parcelable {
this.powerBrightnessFactor = powerBrightnessFactor;
this.nightMode = nightMode;
this.colorTemperature = colorTemperature;
+ this.reduceBrightColors = reduceBrightColors;
+ this.reduceBrightColorsStrength = reduceBrightColorsStrength;
+ this.reduceBrightColorsOffset = reduceBrightColorsOffset;
this.lastBrightness = lastBrightness;
this.isDefaultBrightnessConfig = isDefaultBrightnessConfig;
this.isUserSetBrightness = isUserSetBrightness;
@@ -136,6 +157,9 @@ public final class BrightnessChangeEvent implements Parcelable {
this.powerBrightnessFactor = other.powerBrightnessFactor;
this.nightMode = other.nightMode;
this.colorTemperature = other.colorTemperature;
+ this.reduceBrightColors = other.reduceBrightColors;
+ this.reduceBrightColorsStrength = other.reduceBrightColorsStrength;
+ this.reduceBrightColorsOffset = other.reduceBrightColorsOffset;
this.lastBrightness = other.lastBrightness;
this.isDefaultBrightnessConfig = other.isDefaultBrightnessConfig;
this.isUserSetBrightness = other.isUserSetBrightness;
@@ -154,6 +178,9 @@ public final class BrightnessChangeEvent implements Parcelable {
powerBrightnessFactor = source.readFloat();
nightMode = source.readBoolean();
colorTemperature = source.readInt();
+ reduceBrightColors = source.readBoolean();
+ reduceBrightColorsStrength = source.readInt();
+ reduceBrightColorsOffset = source.readFloat();
lastBrightness = source.readFloat();
isDefaultBrightnessConfig = source.readBoolean();
isUserSetBrightness = source.readBoolean();
@@ -188,6 +215,9 @@ public final class BrightnessChangeEvent implements Parcelable {
dest.writeFloat(powerBrightnessFactor);
dest.writeBoolean(nightMode);
dest.writeInt(colorTemperature);
+ dest.writeBoolean(reduceBrightColors);
+ dest.writeInt(reduceBrightColorsStrength);
+ dest.writeFloat(reduceBrightColorsOffset);
dest.writeFloat(lastBrightness);
dest.writeBoolean(isDefaultBrightnessConfig);
dest.writeBoolean(isUserSetBrightness);
@@ -207,6 +237,9 @@ public final class BrightnessChangeEvent implements Parcelable {
private float mPowerBrightnessFactor;
private boolean mNightMode;
private int mColorTemperature;
+ private boolean mReduceBrightColors;
+ private int mReduceBrightColorsStrength;
+ private float mReduceBrightColorsOffset;
private float mLastBrightness;
private boolean mIsDefaultBrightnessConfig;
private boolean mIsUserSetBrightness;
@@ -273,6 +306,24 @@ public final class BrightnessChangeEvent implements Parcelable {
return this;
}
+ /** {@see BrightnessChangeEvent#reduceBrightColors} */
+ public Builder setReduceBrightColors(boolean reduceBrightColors) {
+ mReduceBrightColors = reduceBrightColors;
+ return this;
+ }
+
+ /** {@see BrightnessChangeEvent#reduceBrightColorsStrength} */
+ public Builder setReduceBrightColorsStrength(int strength) {
+ mReduceBrightColorsStrength = strength;
+ return this;
+ }
+
+ /** {@see BrightnessChangeEvent#reduceBrightColorsOffset} */
+ public Builder setReduceBrightColorsOffset(float offset) {
+ mReduceBrightColorsOffset = offset;
+ return this;
+ }
+
/** {@see BrightnessChangeEvent#lastBrightness} */
public Builder setLastBrightness(float lastBrightness) {
mLastBrightness = lastBrightness;
@@ -304,7 +355,8 @@ public final class BrightnessChangeEvent implements Parcelable {
public BrightnessChangeEvent build() {
return new BrightnessChangeEvent(mBrightness, mTimeStamp,
mPackageName, mUserId, mLuxValues, mLuxTimestamps, mBatteryLevel,
- mPowerBrightnessFactor, mNightMode, mColorTemperature, mLastBrightness,
+ mPowerBrightnessFactor, mNightMode, mColorTemperature, mReduceBrightColors,
+ mReduceBrightColorsStrength, mReduceBrightColorsOffset, mLastBrightness,
mIsDefaultBrightnessConfig, mIsUserSetBrightness, mColorValueBuckets,
mColorSampleDuration);
}
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
index efeb89ed96ace..e247df320115a 100644
--- a/core/java/android/hardware/display/ColorDisplayManager.java
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -437,6 +437,56 @@ public final class ColorDisplayManager {
return mManager.isDisplayWhiteBalanceEnabled();
}
+ /**
+ * Enables or disables reduce bright colors.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
+ public boolean setReduceBrightColorsActivated(boolean activated) {
+ return mManager.setReduceBrightColorsActivated(activated);
+ }
+
+ /**
+ * Returns whether reduce bright colors is currently enabled.
+ *
+ * @hide
+ */
+ public boolean isReduceBrightColorsActivated() {
+ return mManager.isReduceBrightColorsActivated();
+ }
+
+ /**
+ * Set the strength level of bright color reduction to apply to the display.
+ *
+ * @param strength 0-100 (inclusive), where 100 is full strength
+ * @return whether the change was applied successfully
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
+ public boolean setReduceBrightColorsStrength(@IntRange(from = 0, to = 100) int strength) {
+ return mManager.setReduceBrightColorsStrength(strength);
+ }
+
+ /**
+ * Gets the strength of the bright color reduction transform.
+ *
+ * @hide
+ */
+ public int getReduceBrightColorsStrength() {
+ return mManager.getReduceBrightColorsStrength();
+ }
+
+ /**
+ * Gets the brightness impact of the bright color reduction transform, as in the factor by which
+ * the current brightness (in nits) should be multiplied to obtain the brightness offset 'b'.
+ *
+ * @hide
+ */
+ public float getReduceBrightColorsOffsetFactor() {
+ return mManager.getReduceBrightColorsOffsetFactor();
+ }
+
/**
* Returns {@code true} if Night Display is supported by the device.
*
@@ -477,6 +527,15 @@ public final class ColorDisplayManager {
return context.getResources().getBoolean(R.bool.config_displayWhiteBalanceAvailable);
}
+ /**
+ * Returns {@code true} if reduce bright colors is supported by the device.
+ *
+ * @hide
+ */
+ public static boolean isReduceBrightColorsAvailable(Context context) {
+ return context.getResources().getBoolean(R.bool.config_reduceBrightColorsAvailable);
+ }
+
/**
* Check if the color transforms are color accelerated. Some transforms are experimental only
* on non-accelerated platforms due to the performance implications.
@@ -678,6 +737,46 @@ public final class ColorDisplayManager {
}
}
+ boolean isReduceBrightColorsActivated() {
+ try {
+ return mCdm.isReduceBrightColorsActivated();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ boolean setReduceBrightColorsActivated(boolean activated) {
+ try {
+ return mCdm.setReduceBrightColorsActivated(activated);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ int getReduceBrightColorsStrength() {
+ try {
+ return mCdm.getReduceBrightColorsStrength();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ boolean setReduceBrightColorsStrength(int strength) {
+ try {
+ return mCdm.setReduceBrightColorsStrength(strength);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ float getReduceBrightColorsOffsetFactor() {
+ try {
+ return mCdm.getReduceBrightColorsOffsetFactor();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
int getColorMode() {
try {
return mCdm.getColorMode();
diff --git a/core/java/android/hardware/display/IColorDisplayManager.aidl b/core/java/android/hardware/display/IColorDisplayManager.aidl
index 7b1033df8b62d..ef4f5f9b05e97 100644
--- a/core/java/android/hardware/display/IColorDisplayManager.aidl
+++ b/core/java/android/hardware/display/IColorDisplayManager.aidl
@@ -45,4 +45,10 @@ interface IColorDisplayManager {
boolean isDisplayWhiteBalanceEnabled();
boolean setDisplayWhiteBalanceEnabled(boolean enabled);
+
+ boolean isReduceBrightColorsActivated();
+ boolean setReduceBrightColorsActivated(boolean activated);
+ int getReduceBrightColorsStrength();
+ boolean setReduceBrightColorsStrength(int strength);
+ float getReduceBrightColorsOffsetFactor();
}
\ No newline at end of file
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 01b8efafa2fd1..5c56ce413c329 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -822,28 +822,21 @@
- -0.198650895
-
- - -0.691218457
- - 0.050135153
- - 0.917684143
- - -0.691218457
- - 0.050135153
- - 0.917684143
- - -0.691218457
- - 0.050135153
- - 0.917684143
+
+ @bool/config_setColorTransformAccelerated
+
+
+ - -0.4429953456
+ - -0.2434077725
+ - 0.9809063061
- - 0.00000000000000154
- - -1.0
- - 1.045977011
- - 0.00000000000000224
- - -1.0
- - 1.045977011
- - 0.0000000000000022
- - -1.0
- - 1.045977011
+ - -0.000000000000001
+ - -0.955555555555554
+ - 1.000000000000000
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 815330ff18515..9b930fc07f33f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3191,8 +3191,9 @@
+
-
+
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index b8e579d58794c..4832e46be8a82 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -300,6 +300,8 @@ public abstract class BrightnessMappingStrategy {
/** @return The default brightness configuration. */
public abstract BrightnessConfiguration getDefaultConfig();
+ /** Recalculates the backlight-to-nits and nits-to-backlight splines. */
+ public abstract void recalculateSplines(boolean applyAdjustment, float[] adjustment);
/**
* Returns the timeout for the short term model
@@ -657,6 +659,11 @@ public abstract class BrightnessMappingStrategy {
return null;
}
+ @Override
+ public void recalculateSplines(boolean applyAdjustment, float[] adjustment) {
+ // Do nothing.
+ }
+
@Override
public void dump(PrintWriter pw) {
pw.println("SimpleMappingStrategy");
@@ -696,7 +703,7 @@ public abstract class BrightnessMappingStrategy {
// A spline mapping from nits to the corresponding backlight value, normalized to the range
// [0, 1.0].
- private final Spline mNitsToBacklightSpline;
+ private Spline mNitsToBacklightSpline;
// The default brightness configuration.
private final BrightnessConfiguration mDefaultConfig;
@@ -705,6 +712,11 @@ public abstract class BrightnessMappingStrategy {
// a brightness in nits.
private Spline mBacklightToNitsSpline;
+ private float[] mNits;
+ private int[] mBacklight;
+
+ private boolean mBrightnessRangeAdjustmentApplied;
+
private float mMaxGamma;
private float mAutoBrightnessAdjustment;
private float mUserLux;
@@ -726,15 +738,9 @@ public abstract class BrightnessMappingStrategy {
mUserLux = -1;
mUserBrightness = -1;
- // Setup the backlight spline
- final int N = nits.length;
- float[] normalizedBacklight = new float[N];
- for (int i = 0; i < N; i++) {
- normalizedBacklight[i] = normalizeAbsoluteBrightness(backlight[i]);
- }
-
- mNitsToBacklightSpline = Spline.createSpline(nits, normalizedBacklight);
- mBacklightToNitsSpline = Spline.createSpline(normalizedBacklight, nits);
+ mNits = nits;
+ mBacklight = backlight;
+ computeNitsBrightnessSplines(mNits);
mDefaultConfig = config;
if (mLoggingEnabled) {
@@ -867,6 +873,12 @@ public abstract class BrightnessMappingStrategy {
return mDefaultConfig;
}
+ @Override
+ public void recalculateSplines(boolean applyAdjustment, float[] adjustedNits) {
+ mBrightnessRangeAdjustmentApplied = applyAdjustment;
+ computeNitsBrightnessSplines(mBrightnessRangeAdjustmentApplied ? adjustedNits : mNits);
+ }
+
@Override
public void dump(PrintWriter pw) {
pw.println("PhysicalMappingStrategy");
@@ -878,6 +890,18 @@ public abstract class BrightnessMappingStrategy {
pw.println(" mUserLux=" + mUserLux);
pw.println(" mUserBrightness=" + mUserBrightness);
pw.println(" mDefaultConfig=" + mDefaultConfig);
+ pw.println(" mBrightnessRangeAdjustmentApplied=" + mBrightnessRangeAdjustmentApplied);
+ }
+
+ private void computeNitsBrightnessSplines(float[] nits) {
+ final int len = nits.length;
+ float[] normalizedBacklight = new float[len];
+ for (int i = 0; i < len; i++) {
+ normalizedBacklight[i] = normalizeAbsoluteBrightness(mBacklight[i]);
+ }
+
+ mNitsToBacklightSpline = Spline.createSpline(nits, normalizedBacklight);
+ mBacklightToNitsSpline = Spline.createSpline(normalizedBacklight, nits);
}
private void computeSpline() {
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 2375f746c57db..a186e334c5c0b 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -63,7 +63,6 @@ import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
-import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.RingBuffer;
import com.android.server.LocalServices;
@@ -71,7 +70,6 @@ import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileInputStream;
@@ -80,7 +78,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
-import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -118,6 +115,9 @@ public class BrightnessTracker {
private static final String ATTR_BATTERY_LEVEL = "batteryLevel";
private static final String ATTR_NIGHT_MODE = "nightMode";
private static final String ATTR_COLOR_TEMPERATURE = "colorTemperature";
+ private static final String ATTR_REDUCE_BRIGHT_COLORS = "reduceBrightColors";
+ private static final String ATTR_REDUCE_BRIGHT_COLORS_STRENGTH = "reduceBrightColorsStrength";
+ private static final String ATTR_REDUCE_BRIGHT_COLORS_OFFSET = "reduceBrightColorsOffset";
private static final String ATTR_LAST_NITS = "lastNits";
private static final String ATTR_DEFAULT_CONFIG = "defaultConfig";
private static final String ATTR_POWER_SAVE = "powerSaveFactor";
@@ -398,6 +398,10 @@ public class BrightnessTracker {
builder.setNightMode(mInjector.isNightDisplayActivated(mContext));
builder.setColorTemperature(mInjector.getNightDisplayColorTemperature(mContext));
+ builder.setReduceBrightColors(mInjector.isReduceBrightColorsActivated(mContext));
+ builder.setReduceBrightColorsStrength(mInjector.getReduceBrightColorsStrength(mContext));
+ builder.setReduceBrightColorsOffset(mInjector.getReduceBrightColorsOffsetFactor(mContext)
+ * brightness);
if (mColorSamplingEnabled) {
DisplayedContentSample sample = mInjector.sampleColor(mNoFramesToSample);
@@ -563,6 +567,12 @@ public class BrightnessTracker {
out.attributeBoolean(null, ATTR_NIGHT_MODE, toWrite[i].nightMode);
out.attributeInt(null, ATTR_COLOR_TEMPERATURE,
toWrite[i].colorTemperature);
+ out.attributeBoolean(null, ATTR_REDUCE_BRIGHT_COLORS,
+ toWrite[i].reduceBrightColors);
+ out.attributeInt(null, ATTR_REDUCE_BRIGHT_COLORS_STRENGTH,
+ toWrite[i].reduceBrightColorsStrength);
+ out.attributeFloat(null, ATTR_REDUCE_BRIGHT_COLORS_OFFSET,
+ toWrite[i].reduceBrightColorsOffset);
out.attributeFloat(null, ATTR_LAST_NITS,
toWrite[i].lastBrightness);
out.attributeBoolean(null, ATTR_DEFAULT_CONFIG,
@@ -641,6 +651,12 @@ public class BrightnessTracker {
builder.setNightMode(parser.getAttributeBoolean(null, ATTR_NIGHT_MODE));
builder.setColorTemperature(
parser.getAttributeInt(null, ATTR_COLOR_TEMPERATURE));
+ builder.setReduceBrightColors(
+ parser.getAttributeBoolean(null, ATTR_REDUCE_BRIGHT_COLORS));
+ builder.setReduceBrightColorsStrength(
+ parser.getAttributeInt(null, ATTR_REDUCE_BRIGHT_COLORS_STRENGTH));
+ builder.setReduceBrightColorsOffset(
+ parser.getAttributeFloat(null, ATTR_REDUCE_BRIGHT_COLORS_OFFSET));
builder.setLastBrightness(parser.getAttributeFloat(null, ATTR_LAST_NITS));
String luxValue = parser.getAttributeValue(null, ATTR_LUX);
@@ -1114,6 +1130,21 @@ public class BrightnessTracker {
return context.getSystemService(ColorDisplayManager.class).isNightDisplayActivated();
}
+ public int getReduceBrightColorsStrength(Context context) {
+ return context.getSystemService(ColorDisplayManager.class)
+ .getReduceBrightColorsStrength();
+ }
+
+ public float getReduceBrightColorsOffsetFactor(Context context) {
+ return context.getSystemService(ColorDisplayManager.class)
+ .getReduceBrightColorsOffsetFactor();
+ }
+
+ public boolean isReduceBrightColorsActivated(Context context) {
+ return context.getSystemService(ColorDisplayManager.class)
+ .isReduceBrightColorsActivated();
+ }
+
public DisplayedContentSample sampleColor(int noFramesToSample) {
final DisplayManagerInternal displayManagerInternal =
LocalServices.getService(DisplayManagerInternal.class);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 13dc0b9be21f5..8c65158caab76 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -58,6 +58,8 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
+import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
+import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory;
import com.android.server.display.whitebalance.DisplayWhiteBalanceSettings;
@@ -346,6 +348,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
@Nullable
private final DisplayWhiteBalanceController mDisplayWhiteBalanceController;
+ private final ColorDisplayServiceInternal mCdsi;
+ private final float[] mNitsRange;
+
// A record of state for skipping brightness ramps.
private int mSkipRampState = RAMP_STATE_SKIP_NONE;
@@ -580,6 +585,37 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
mDisplayWhiteBalanceSettings = displayWhiteBalanceSettings;
mDisplayWhiteBalanceController = displayWhiteBalanceController;
+
+ if (displayDeviceConfig != null && displayDeviceConfig.getNits() != null) {
+ mNitsRange = displayDeviceConfig.getNits();
+ } else {
+ Slog.w(TAG, "Screen brightness nits configuration is unavailable; falling back");
+ mNitsRange = BrightnessMappingStrategy.getFloatArray(context.getResources()
+ .obtainTypedArray(com.android.internal.R.array.config_screenBrightnessNits));
+ }
+ mCdsi = LocalServices.getService(ColorDisplayServiceInternal.class);
+ boolean active = mCdsi.setReduceBrightColorsListener(new ReduceBrightColorsListener() {
+ @Override
+ public void onReduceBrightColorsActivationChanged(boolean activated) {
+ applyReduceBrightColorsSplineAdjustment();
+ }
+
+ @Override
+ public void onReduceBrightColorsStrengthChanged(int strength) {
+ applyReduceBrightColorsSplineAdjustment();
+ }
+ });
+ if (active) {
+ applyReduceBrightColorsSplineAdjustment();
+ }
+ }
+
+ private void applyReduceBrightColorsSplineAdjustment() {
+ float[] adjustedNits = new float[mNitsRange.length];
+ for (int i = 0; i < mNitsRange.length; i++) {
+ adjustedNits[i] = mCdsi.getReduceBrightColorsAdjustedBrightnessNits(mNitsRange[i]);
+ }
+ mBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), adjustedNits);
}
private Sensor findDisplayLightSensor(String sensorType) {
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 4706edc151f8f..88b26680631e8 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -173,6 +173,7 @@ public final class ColorDisplayService extends SystemService {
private ContentObserver mContentObserver;
private DisplayWhiteBalanceListener mDisplayWhiteBalanceListener;
+ private ReduceBrightColorsListener mReduceBrightColorsListener;
private NightDisplayAutoMode mNightDisplayAutoMode;
@@ -617,18 +618,24 @@ public final class ColorDisplayService extends SystemService {
if (mCurrentUser == UserHandle.USER_NULL) {
return;
}
- mReduceBrightColorsTintController.setActivated(
- Secure.getIntForUser(getContext().getContentResolver(),
- Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0, mCurrentUser) == 1);
+ final boolean activated = Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0, mCurrentUser) == 1;
+ mReduceBrightColorsTintController.setActivated(activated);
+ if (mReduceBrightColorsListener != null) {
+ mReduceBrightColorsListener.onReduceBrightColorsActivationChanged(activated);
+ }
}
private void onReduceBrightColorsStrengthLevelChanged() {
if (mCurrentUser == UserHandle.USER_NULL) {
return;
}
- mReduceBrightColorsTintController.setMatrix(
- Secure.getIntForUser(getContext().getContentResolver(),
- Secure.REDUCE_BRIGHT_COLORS_LEVEL, 0, mCurrentUser));
+ final int strength = Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.REDUCE_BRIGHT_COLORS_LEVEL, 0, mCurrentUser);
+ mReduceBrightColorsTintController.setMatrix(strength);
+ if (mReduceBrightColorsListener != null) {
+ mReduceBrightColorsListener.onReduceBrightColorsStrengthChanged(strength);
+ }
}
/**
@@ -762,6 +769,22 @@ public final class ColorDisplayService extends SystemService {
mCurrentUser) == 1;
}
+ private boolean setReduceBrightColorsActivatedInternal(boolean activated) {
+ if (mCurrentUser == UserHandle.USER_NULL) {
+ return false;
+ }
+ return Secure.putIntForUser(getContext().getContentResolver(),
+ Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, activated ? 1 : 0, mCurrentUser);
+ }
+
+ private boolean setReduceBrightColorsStrengthInternal(int strength) {
+ if (mCurrentUser == UserHandle.USER_NULL) {
+ return false;
+ }
+ return Secure.putIntForUser(getContext().getContentResolver(),
+ Secure.REDUCE_BRIGHT_COLORS_LEVEL, strength, mCurrentUser);
+ }
+
private boolean isDeviceColorManagedInternal() {
final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
return dtm.isDeviceColorManaged();
@@ -1468,6 +1491,31 @@ public final class ColorDisplayService extends SystemService {
return isDisplayWhiteBalanceSettingEnabled();
}
+ /**
+ * Sets the listener and returns whether reduce bright colors is currently enabled.
+ */
+ public boolean setReduceBrightColorsListener(ReduceBrightColorsListener listener) {
+ mReduceBrightColorsListener = listener;
+ return mReduceBrightColorsTintController.isActivated();
+ }
+
+ /**
+ * Returns whether reduce bright colors is currently active.
+ */
+ public boolean isReduceBrightColorsActivated() {
+ return mReduceBrightColorsTintController.isActivated();
+ }
+
+ /**
+ * Gets the computed brightness, in nits, when the reduce bright colors feature is applied
+ * at the current strength.
+ *
+ * @hide
+ */
+ public float getReduceBrightColorsAdjustedBrightnessNits(float nits) {
+ return mReduceBrightColorsTintController.getAdjustedBrightness(nits);
+ }
+
/**
* Adds a {@link WeakReference} for a newly started activity, and
* invokes {@link ColorTransformController#applyAppSaturation(float[], float[])} if needed.
@@ -1491,6 +1539,22 @@ public final class ColorDisplayService extends SystemService {
void onDisplayWhiteBalanceStatusChanged(boolean activated);
}
+ /**
+ * Listener for changes in reduce bright colors status.
+ */
+ public interface ReduceBrightColorsListener {
+
+ /**
+ * Notify that the reduce bright colors activation status has changed.
+ */
+ void onReduceBrightColorsActivationChanged(boolean activated);
+
+ /**
+ * Notify that the reduce bright colors strength has changed.
+ */
+ void onReduceBrightColorsStrengthChanged(int strength);
+ }
+
private final class TintHandler extends Handler {
private TintHandler(Looper looper) {
@@ -1786,6 +1850,62 @@ public final class ColorDisplayService extends SystemService {
}
}
+ @Override
+ public boolean isReduceBrightColorsActivated() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mReduceBrightColorsTintController.isActivated();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean setReduceBrightColorsActivated(boolean activated) {
+ getContext().enforceCallingOrSelfPermission(
+ Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
+ "Permission required to set reduce bright colors activation state");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return setReduceBrightColorsActivatedInternal(activated);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public int getReduceBrightColorsStrength() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mReduceBrightColorsTintController.getStrength();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public float getReduceBrightColorsOffsetFactor() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mReduceBrightColorsTintController.getOffsetFactor();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean setReduceBrightColorsStrength(int strength) {
+ getContext().enforceCallingOrSelfPermission(
+ Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
+ "Permission required to set reduce bright colors strength");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return setReduceBrightColorsStrengthInternal(strength);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
diff --git a/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java b/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java
index 7e120c91ce9df..cb93cc8fc3a7d 100644
--- a/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java
+++ b/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java
@@ -34,7 +34,7 @@ import java.util.Arrays;
public class ReduceBrightColorsTintController extends TintController {
private final float[] mMatrix = new float[16];
- private final float[] mCoefficients = new float[9];
+ private final float[] mCoefficients = new float[3];
private int mStrength;
@@ -42,8 +42,8 @@ public class ReduceBrightColorsTintController extends TintController {
public void setUp(Context context, boolean needsLinear) {
final String[] coefficients = context.getResources().getStringArray(
needsLinear ? R.array.config_reduceBrightColorsCoefficients
- : R.array.config_reduceBrightColorsCoefficientsNative);
- for (int i = 0; i < 9 && i < coefficients.length; i++) {
+ : R.array.config_reduceBrightColorsCoefficientsNonlinear);
+ for (int i = 0; i < 3 && i < coefficients.length; i++) {
mCoefficients[i] = Float.parseFloat(coefficients[i]);
}
}
@@ -67,20 +67,11 @@ public class ReduceBrightColorsTintController extends TintController {
Matrix.setIdentityM(mMatrix, 0);
- final float percentageStrength = strengthLevel / 100f;
- final float squaredPercentageStrength = percentageStrength * percentageStrength;
- final float red =
- squaredPercentageStrength * mCoefficients[0] + percentageStrength * mCoefficients[1]
- + mCoefficients[2];
- final float green =
- squaredPercentageStrength * mCoefficients[3] + percentageStrength * mCoefficients[4]
- + mCoefficients[5];
- final float blue =
- squaredPercentageStrength * mCoefficients[6] + percentageStrength * mCoefficients[7]
- + mCoefficients[8];
- mMatrix[0] = clamp(red);
- mMatrix[5] = clamp(green);
- mMatrix[10] = clamp(blue);
+ // All three (r,g,b) components are equal and calculated with the same formula.
+ final float componentValue = computeComponentValue(strengthLevel);
+ mMatrix[0] = componentValue;
+ mMatrix[5] = componentValue;
+ mMatrix[10] = componentValue;
}
private float clamp(float value) {
@@ -110,4 +101,26 @@ public class ReduceBrightColorsTintController extends TintController {
public int getStrength() {
return mStrength;
}
+
+ /** Returns the offset factor at Ymax. */
+ public float getOffsetFactor() {
+ // Strength terms drop out as strength --> 1, leaving the coefficients.
+ return mCoefficients[0] + mCoefficients[1] + mCoefficients[2];
+ }
+
+ /**
+ * Returns the effective brightness (in nits), which has been adjusted to account for the effect
+ * of the bright color reduction.
+ */
+ public float getAdjustedBrightness(float nits) {
+ return computeComponentValue(mStrength) * nits;
+ }
+
+ private float computeComponentValue(int strengthLevel) {
+ final float percentageStrength = strengthLevel / 100f;
+ final float squaredPercentageStrength = percentageStrength * percentageStrength;
+ return clamp(
+ squaredPercentageStrength * mCoefficients[0] + percentageStrength * mCoefficients[1]
+ + mCoefficients[2]);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index ae966aaf2b583..f0b4f1bec77b9 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -226,6 +226,31 @@ public class BrightnessMappingStrategyTest {
strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01f /*tolerance*/);
}
+ @Test
+ public void testPhysicalStrategyRecalculateSplines() {
+ Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS,
+ BACKLIGHT_RANGE);
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+ float[] adjustedNits50p = new float[DISPLAY_RANGE_NITS.length];
+ for (int i = 0; i < DISPLAY_RANGE_NITS.length; i++) {
+ adjustedNits50p[i] = DISPLAY_RANGE_NITS[i] * 0.5f;
+ }
+
+ // Default is unadjusted
+ assertEquals(2.685f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */);
+ assertEquals(478.5f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */);
+
+ // When adjustment is turned on, adjustment array is used
+ strategy.recalculateSplines(true, adjustedNits50p);
+ assertEquals(1.3425f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */);
+ assertEquals(239.25f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */);
+
+ // When adjustment is turned off, adjustment array is ignored
+ strategy.recalculateSplines(false, adjustedNits50p);
+ assertEquals(2.685f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */);
+ assertEquals(478.5f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */);
+ }
+
@Test
public void testDefaultStrategyIsPhysical() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT,
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index e02a46af38490..d362791092540 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -335,6 +335,9 @@ public class BrightnessTrackerTest {
assertEquals(0.5, event.batteryLevel, FLOAT_DELTA);
assertTrue(event.nightMode);
assertEquals(3333, event.colorTemperature);
+ assertTrue(event.reduceBrightColors);
+ assertEquals(40, event.reduceBrightColorsStrength);
+ assertEquals(20f, event.reduceBrightColorsOffset, FLOAT_DELTA);
assertEquals("a.package", event.packageName);
assertEquals(0, event.userId);
assertArrayEquals(new long[] {1, 10, 100, 1000, 300, 30, 10, 1}, event.colorValueBuckets);
@@ -561,6 +564,9 @@ public class BrightnessTrackerTest {
mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 1);
mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, 3339);
+ mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
+ mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_LEVEL, 40);
+
startTracker(mTracker);
mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
batteryChangeEvent(30, 100));
@@ -592,6 +598,9 @@ public class BrightnessTrackerTest {
assertEquals(0.3, event.batteryLevel, FLOAT_DELTA);
assertTrue(event.nightMode);
assertEquals(3339, event.colorTemperature);
+ assertTrue(event.reduceBrightColors);
+ assertEquals(40, event.reduceBrightColorsStrength);
+ assertEquals(20f, event.reduceBrightColorsOffset, FLOAT_DELTA);
assertEquals(0.5f, event.powerBrightnessFactor, FLOAT_DELTA);
assertTrue(event.isUserSetBrightness);
assertFalse(event.isDefaultBrightnessConfig);
@@ -606,6 +615,9 @@ public class BrightnessTrackerTest {
mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 1);
mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, 3339);
+ mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
+ mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_LEVEL, 40);
+
startTracker(mTracker);
mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
batteryChangeEvent(30, 100));
@@ -639,6 +651,7 @@ public class BrightnessTrackerTest {
assertEquals(brightness, event.brightness, FLOAT_DELTA);
assertEquals(0.3, event.batteryLevel, FLOAT_DELTA);
assertTrue(event.nightMode);
+ assertTrue(event.reduceBrightColors);
assertEquals(3339, event.colorTemperature);
}
@@ -661,6 +674,9 @@ public class BrightnessTrackerTest {
builder.setBatteryLevel(0.7f);
builder.setNightMode(false);
builder.setColorTemperature(345);
+ builder.setReduceBrightColors(false);
+ builder.setReduceBrightColorsStrength(40);
+ builder.setReduceBrightColorsOffset(20f);
builder.setLastBrightness(50f);
builder.setColorValues(new long[] {23, 34, 45}, 1000L);
BrightnessChangeEvent event = builder.build();
@@ -684,6 +700,9 @@ public class BrightnessTrackerTest {
assertEquals(event.batteryLevel, event2.batteryLevel, FLOAT_DELTA);
assertEquals(event.nightMode, event2.nightMode);
assertEquals(event.colorTemperature, event2.colorTemperature);
+ assertEquals(event.reduceBrightColors, event2.reduceBrightColors);
+ assertEquals(event.reduceBrightColorsStrength, event2.reduceBrightColorsStrength);
+ assertEquals(event.reduceBrightColorsOffset, event2.reduceBrightColorsOffset, FLOAT_DELTA);
assertEquals(event.lastBrightness, event2.lastBrightness, FLOAT_DELTA);
assertArrayEquals(event.colorValueBuckets, event2.colorValueBuckets);
assertEquals(event.colorSampleDuration, event2.colorSampleDuration);
@@ -1019,6 +1038,18 @@ public class BrightnessTrackerTest {
0) == 1;
}
+ @Override
+ public int getReduceBrightColorsStrength(Context context) {
+ return mSecureIntSettings.getOrDefault(Settings.Secure.REDUCE_BRIGHT_COLORS_LEVEL,
+ 0);
+ }
+
+ @Override
+ public boolean isReduceBrightColorsActivated(Context context) {
+ return mSecureIntSettings.getOrDefault(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
+ 0) == 1;
+ }
+
@Override
public DisplayedContentSample sampleColor(int noFramesToSample) {
return new DisplayedContentSample(600L,
diff --git a/services/tests/servicestests/src/com/android/server/display/color/ReduceBrightColorsTintControllerTest.java b/services/tests/servicestests/src/com/android/server/display/color/ReduceBrightColorsTintControllerTest.java
new file mode 100644
index 0000000000000..35014dcb7492b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/color/ReduceBrightColorsTintControllerTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.color;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class ReduceBrightColorsTintControllerTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ final Resources mockResources = mock(Resources.class);
+ when(mockResources.getStringArray(
+ com.android.internal.R.array.config_reduceBrightColorsCoefficients))
+ .thenReturn(new String[]{"-0.000000000000001", "-0.955555555555554",
+ "1.000000000000000"});
+ when(mockResources.getStringArray(
+ com.android.internal.R.array.config_reduceBrightColorsCoefficientsNonlinear))
+ .thenReturn(new String[]{"-0.4429953456", "-0.2434077725", "0.9809063061"});
+ mContext = mock(Context.class);
+ when(mContext.getResources()).thenReturn(mockResources);
+ }
+
+ @Test
+ public void setAndGetMatrix() {
+ final ReduceBrightColorsTintController tintController =
+ new ReduceBrightColorsTintController();
+ tintController.setUp(mContext, /* needsLinear= */ true);
+ tintController.setMatrix(50);
+ tintController.setActivated(true);
+ assertThat(tintController.getStrength()).isEqualTo(50);
+ assertThat(tintController.getMatrix()).usingTolerance(0.00001f)
+ .containsExactly(
+ 0.5222222f, 0f, 0f, 0f,
+ 0f, 0.5222222f, 0f, 0f,
+ 0f, 0f, 0.5222222f, 0f,
+ 0f, 0f, 0f, 1f)
+ .inOrder();
+ }
+
+ @Test
+ public void setAndGetMatrixClampToZero() {
+ final ReduceBrightColorsTintController tintController =
+ new ReduceBrightColorsTintController();
+ tintController.setUp(mContext, /* needsLinear= */ true);
+ tintController.setMatrix(-50);
+ tintController.setActivated(true);
+ assertThat(tintController.getStrength()).isEqualTo(0);
+ assertThat(tintController.getMatrix()).usingTolerance(0.00001f)
+ .containsExactly(
+ 1f, 0f, 0f, 0f,
+ 0f, 1f, 0f, 0f,
+ 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 1f)
+ .inOrder();
+ }
+
+ @Test
+ public void setAndGetMatrixClampTo100() {
+ final ReduceBrightColorsTintController tintController =
+ new ReduceBrightColorsTintController();
+ tintController.setUp(mContext, /* needsLinear= */ true);
+ tintController.setMatrix(120);
+ tintController.setActivated(true);
+ assertThat(tintController.getStrength()).isEqualTo(100);
+ assertThat(tintController.getMatrix()).usingTolerance(0.00001f)
+ .containsExactly(
+ 0.04444444f, 0f, 0f, 0f,
+ 0f, 0.04444444f, 0f, 0f,
+ 0f, 0f, 0.04444444f, 0f,
+ 0f, 0f, 0f, 1f)
+ .inOrder();
+ }
+
+ @Test
+ public void returnsIdentityMatrixWhenNotActivated() {
+ final ReduceBrightColorsTintController tintController =
+ new ReduceBrightColorsTintController();
+ tintController.setUp(mContext, /* needsLinear= */ true);
+ tintController.setMatrix(50);
+ tintController.setActivated(true);
+ tintController.setActivated(false);
+ assertThat(tintController.getStrength()).isEqualTo(50);
+ assertThat(tintController.getMatrix()).usingTolerance(0.00001f)
+ .containsExactly(
+ 1f, 0f, 0f, 0f,
+ 0f, 1f, 0f, 0f,
+ 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 1f)
+ .inOrder();
+ }
+
+ @Test
+ public void getAdjustedBrightnessZeroRbcStrengthFullBrightness() {
+ final ReduceBrightColorsTintController tintController =
+ new ReduceBrightColorsTintController();
+ tintController.setUp(mContext, /* needsLinear= */ true);
+ tintController.setMatrix(0);
+ assertThat(tintController.getAdjustedBrightness(450f)).isEqualTo(450f);
+ }
+
+ @Test
+ public void getAdjustedBrightnessFullRbcStrengthFullBrightness() {
+ final ReduceBrightColorsTintController tintController =
+ new ReduceBrightColorsTintController();
+ tintController.setUp(mContext, /* needsLinear= */ true);
+ tintController.setMatrix(100);
+ assertThat(tintController.getAdjustedBrightness(450f)).isEqualTo(19.999998f);
+ }
+
+ @Test
+ public void getAdjustedBrightnessZeroRbcStrengthLowBrightness() {
+ final ReduceBrightColorsTintController tintController =
+ new ReduceBrightColorsTintController();
+ tintController.setUp(mContext, /* needsLinear= */ true);
+ tintController.setMatrix(0);
+ assertThat(tintController.getAdjustedBrightness(2.2f)).isEqualTo(2.2f);
+ }
+
+ @Test
+ public void getAdjustedBrightnessFullRbcStrengthLowBrightness() {
+ final ReduceBrightColorsTintController tintController =
+ new ReduceBrightColorsTintController();
+ tintController.setUp(mContext, /* needsLinear= */ true);
+ tintController.setMatrix(100);
+ assertThat(tintController.getAdjustedBrightness(2.2f)).isEqualTo(0.09777778f);
+ }
+}