Load even dimmer config mappings
- Allow minimum nits to be specified in even dimmer config
- Adjust strength based on requested nits
- Add tests
Bug: 369217612
Flag: com.android.server.display.feature.flags.even_dimmer
Test: atest DisplayServiceTests
Change-Id: Idcdaf087f13e74f7f61b1ad510db6d1eb9b17d67
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index dc263c5..af9c9ac 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -1080,7 +1080,7 @@
*/
public float[] getNits() {
if (mEvenDimmerBrightnessData != null) {
- return mEvenDimmerBrightnessData.mNits;
+ return mEvenDimmerBrightnessData.nits;
}
return mNits;
}
@@ -1093,7 +1093,7 @@
@VisibleForTesting
public float[] getBacklight() {
if (mEvenDimmerBrightnessData != null) {
- return mEvenDimmerBrightnessData.mBacklight;
+ return mEvenDimmerBrightnessData.backlight;
}
return mBacklight;
}
@@ -1107,7 +1107,7 @@
*/
public float getBacklightFromBrightness(float brightness) {
if (mEvenDimmerBrightnessData != null) {
- return mEvenDimmerBrightnessData.mBrightnessToBacklight.interpolate(brightness);
+ return mEvenDimmerBrightnessData.brightnessToBacklight.interpolate(brightness);
}
return mBrightnessToBacklightSpline.interpolate(brightness);
}
@@ -1120,7 +1120,7 @@
*/
public float getBrightnessFromBacklight(float backlight) {
if (mEvenDimmerBrightnessData != null) {
- return mEvenDimmerBrightnessData.mBacklightToBrightness.interpolate(backlight);
+ return mEvenDimmerBrightnessData.backlightToBrightness.interpolate(backlight);
}
return mBacklightToBrightnessSpline.interpolate(backlight);
}
@@ -1131,7 +1131,7 @@
*/
private Spline getBacklightToBrightnessSpline() {
if (mEvenDimmerBrightnessData != null) {
- return mEvenDimmerBrightnessData.mBacklightToBrightness;
+ return mEvenDimmerBrightnessData.backlightToBrightness;
}
return mBacklightToBrightnessSpline;
}
@@ -1144,11 +1144,11 @@
*/
public float getNitsFromBacklight(float backlight) {
if (mEvenDimmerBrightnessData != null) {
- if (mEvenDimmerBrightnessData.mBacklightToNits == null) {
+ if (mEvenDimmerBrightnessData.backlightToNits == null) {
return INVALID_NITS;
}
backlight = Math.max(backlight, mBacklightMinimum);
- return mEvenDimmerBrightnessData.mBacklightToNits.interpolate(backlight);
+ return mEvenDimmerBrightnessData.backlightToNits.interpolate(backlight);
}
if (mBacklightToNitsSpline == null) {
@@ -1165,14 +1165,14 @@
*/
public float getBacklightFromNits(float nits) {
if (mEvenDimmerBrightnessData != null) {
- return mEvenDimmerBrightnessData.mNitsToBacklight.interpolate(nits);
+ return mEvenDimmerBrightnessData.nitsToBacklight.interpolate(nits);
}
return mNitsToBacklightSpline.interpolate(nits);
}
private Spline getNitsToBacklightSpline() {
if (mEvenDimmerBrightnessData != null) {
- return mEvenDimmerBrightnessData.mNitsToBacklight;
+ return mEvenDimmerBrightnessData.nitsToBacklight;
}
return mNitsToBacklightSpline;
}
@@ -1186,7 +1186,7 @@
if (mEvenDimmerBrightnessData == null) {
return INVALID_NITS;
}
- return mEvenDimmerBrightnessData.mMinLuxToNits.interpolate(lux);
+ return mEvenDimmerBrightnessData.minLuxToNits.interpolate(lux);
}
/**
@@ -1197,7 +1197,7 @@
if (mEvenDimmerBrightnessData == null) {
return PowerManager.BRIGHTNESS_MIN;
}
- return mEvenDimmerBrightnessData.mTransitionPoint;
+ return mEvenDimmerBrightnessData.transitionPoint;
}
/**
@@ -1268,7 +1268,7 @@
*/
public float[] getBrightness() {
if (mEvenDimmerBrightnessData != null) {
- return mEvenDimmerBrightnessData.mBrightness;
+ return mEvenDimmerBrightnessData.brightness;
}
return mBrightness;
}
@@ -2617,13 +2617,13 @@
List<NonNegativeFloatToFloatPoint> points = map.getMap().getPoint();
for (NonNegativeFloatToFloatPoint point : points) {
float lux = point.getFirst().floatValue();
- float maxBrightness = point.getSecond().floatValue();
- if (maxBrightness > hbmTransitionPoint) {
+ float maxBacklight = point.getSecond().floatValue();
+ if (maxBacklight > hbmTransitionPoint) {
Slog.wtf(TAG,
- "Invalid NBM config: maxBrightness is greater than hbm"
+ "Invalid NBM config: maxBacklight is greater than hbm"
+ ".transitionPoint. type="
- + type + "; lux=" + lux + "; maxBrightness="
- + maxBrightness);
+ + type + "; lux=" + lux + "; maxBacklight="
+ + maxBacklight);
continue;
}
if (luxToTransitionPointMap.containsKey(lux)) {
@@ -2632,8 +2632,7 @@
+ lux);
continue;
}
- luxToTransitionPointMap.put(lux,
- getBrightnessFromBacklight(maxBrightness));
+ luxToTransitionPointMap.put(lux, getBrightnessFromBacklight(maxBacklight));
}
if (!luxToTransitionPointMap.isEmpty()) {
mLuxThrottlingData.put(mappedType, luxToTransitionPointMap);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index c3faec0..d703898 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -22,6 +22,7 @@
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE;
+import static com.android.server.display.brightness.BrightnessEvent.FLAG_EVEN_DIMMER;
import static com.android.server.display.config.DisplayBrightnessMappingConfig.autoBrightnessPresetToString;
import android.animation.Animator;
@@ -1748,6 +1749,8 @@
final float brightnessOnAvailableScale = MathUtils.constrainedMap(0.0f, 1.0f,
clampedState.getMinBrightness(), clampedMax,
brightnessState);
+ final boolean evenDimmerModeOn =
+ mCdsi != null && mCdsi.getReduceBrightColorsActivatedForEvenDimmer();
mTempBrightnessEvent.setPercent(Math.round(
1000.0f * com.android.internal.display.BrightnessUtils.convertLinearToGamma(
brightnessOnAvailableScale) / 10)); // rounded to one dp
@@ -1762,7 +1765,8 @@
mTempBrightnessEvent.setHbmMode(mBrightnessRangeController.getHighBrightnessMode());
mTempBrightnessEvent.setFlags(mTempBrightnessEvent.getFlags()
| (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0)
- | (mPowerRequest.lowPowerMode ? BrightnessEvent.FLAG_LOW_POWER_MODE : 0));
+ | (mPowerRequest.lowPowerMode ? BrightnessEvent.FLAG_LOW_POWER_MODE : 0)
+ | (evenDimmerModeOn ? FLAG_EVEN_DIMMER : 0));
mTempBrightnessEvent.setRbcStrength(mCdsi != null
? mCdsi.getReduceBrightColorsStrength() : -1);
mTempBrightnessEvent.setPowerFactor(mPowerRequest.screenLowPowerBrightnessFactor);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 0570b2a..5edea0a 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -37,9 +37,9 @@
import android.os.Trace;
import android.util.DisplayUtils;
import android.util.LongSparseArray;
-import android.util.MathUtils;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.Spline;
import android.view.Display;
import android.view.DisplayAddress;
import android.view.DisplayCutout;
@@ -81,10 +81,6 @@
private static final String UNIQUE_ID_PREFIX = "local:";
private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.boot.emulator.circular";
- // Min and max strengths for even dimmer feature.
- private static final float EVEN_DIMMER_MIN_STRENGTH = 0.0f;
- private static final float EVEN_DIMMER_MAX_STRENGTH = 90.0f;
- private static final float BRIGHTNESS_MIN = 0.0f;
private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();
@@ -99,7 +95,9 @@
private Context mOverlayContext;
private int mEvenDimmerStrength = -1;
+ private boolean mEvenDimmerEnabled = false;
private ColorDisplayService.ColorDisplayServiceInternal mCdsi;
+ private Spline mNitsToEvenDimmerStrength;
// Called with SyncRoot lock held.
LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, Context context,
@@ -279,7 +277,7 @@
mIsFirstDisplay = isFirstDisplay;
updateDisplayPropertiesLocked(staticDisplayInfo, dynamicInfo, modeSpecs);
mSidekickInternal = LocalServices.getService(SidekickInternal.class);
- mBacklightAdapter = new BacklightAdapter(displayToken, isFirstDisplay,
+ mBacklightAdapter = mInjector.getBacklightAdapter(displayToken, isFirstDisplay,
mSurfaceControlProxy);
mActiveSfDisplayModeAtStartId = dynamicInfo.activeDisplayModeId;
}
@@ -998,26 +996,36 @@
}
private void applyColorMatrixBasedDimming(float brightnessState) {
- int strength = (int) (MathUtils.constrainedMap(
- // to this range:
- EVEN_DIMMER_MAX_STRENGTH, EVEN_DIMMER_MIN_STRENGTH,
- // from this range:
- BRIGHTNESS_MIN, mDisplayDeviceConfig.getEvenDimmerTransitionPoint(),
- // map this (+ rounded up):
- brightnessState) + 0.5);
-
- if (mEvenDimmerStrength < 0 // uninitialised
- || MathUtils.abs(mEvenDimmerStrength - strength) > 1
- || strength <= 1) {
- mEvenDimmerStrength = strength;
- }
- boolean enabled = mEvenDimmerStrength > 0.0f;
-
if (mCdsi == null) {
mCdsi = LocalServices.getService(
ColorDisplayService.ColorDisplayServiceInternal.class);
}
- if (mCdsi != null) {
+ if (mCdsi == null) {
+ return;
+ }
+
+ final float minHardwareNits = backlightToNits(brightnessToBacklight(
+ mDisplayDeviceConfig.getEvenDimmerTransitionPoint()));
+ final float requestedNits =
+ backlightToNits(brightnessToBacklight(brightnessState));
+ mNitsToEvenDimmerStrength =
+ mCdsi.fetchEvenDimmerSpline(minHardwareNits);
+
+ if (mNitsToEvenDimmerStrength == null) {
+ return;
+ }
+
+ // Find required dimming strength, rounded up.
+ int strength = Math.round(mNitsToEvenDimmerStrength
+ .interpolate(requestedNits));
+ boolean enabled = strength > 0.0f;
+ if (mEvenDimmerEnabled != enabled) {
+ Slog.i(TAG, "Setting Extra Dim; strength: " + strength
+ + ", " + (enabled ? "enabled" : "disabled"));
+ }
+ if (mEvenDimmerStrength != strength || mEvenDimmerEnabled != enabled) {
+ mEvenDimmerEnabled = enabled;
+ mEvenDimmerStrength = strength;
mCdsi.applyEvenDimmerColorChanges(enabled, strength);
}
}
@@ -1290,6 +1298,9 @@
pw.println("DisplayDeviceConfig: ");
pw.println("---------------------");
pw.println(mDisplayDeviceConfig);
+ pw.println("mEvenDimmerEnabled=" + mEvenDimmerEnabled);
+ pw.println("mEvenDimmerStrength=" + mEvenDimmerStrength);
+ pw.println("mNitsToEvenDimmerStrength=" + mNitsToEvenDimmerStrength);
}
private int findSfDisplayModeIdLocked(int displayModeId, int modeGroup) {
@@ -1461,6 +1472,12 @@
long physicalDisplayId, boolean isFirstDisplay, DisplayManagerFlags flags) {
return DisplayDeviceConfig.create(context, physicalDisplayId, isFirstDisplay, flags);
}
+
+ public BacklightAdapter getBacklightAdapter(IBinder displayToken, boolean isFirstDisplay,
+ SurfaceControlProxy surfaceControlProxy) {
+ return new BacklightAdapter(displayToken, isFirstDisplay, surfaceControlProxy);
+
+ }
}
public interface DisplayEventListener {
diff --git a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
index ad57ebf..9e9b899 100644
--- a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
+++ b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
@@ -44,6 +44,7 @@
public static final int FLAG_DOZE_SCALE = 0x4;
public static final int FLAG_USER_SET = 0x8;
public static final int FLAG_LOW_POWER_MODE = 0x20;
+ public static final int FLAG_EVEN_DIMMER = 0x40;
private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
@@ -492,6 +493,7 @@
+ ((mFlags & FLAG_RBC) != 0 ? "rbc " : "")
+ ((mFlags & FLAG_INVALID_LUX) != 0 ? "invalid_lux " : "")
+ ((mFlags & FLAG_DOZE_SCALE) != 0 ? "doze_scale " : "")
- + ((mFlags & FLAG_LOW_POWER_MODE) != 0 ? "low_power_mode " : "");
+ + ((mFlags & FLAG_LOW_POWER_MODE) != 0 ? "low_power_mode " : "")
+ + ((mFlags & FLAG_EVEN_DIMMER) != 0 ? "even_dimmer " : "");
}
}
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 bd759f3..dc59e66 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -70,6 +70,7 @@
import android.util.MathUtils;
import android.util.Slog;
import android.util.SparseIntArray;
+import android.util.Spline;
import android.view.Display;
import android.view.SurfaceControl;
import android.view.accessibility.AccessibilityManager;
@@ -114,6 +115,8 @@
Matrix.setIdentityM(MATRIX_IDENTITY, 0);
}
+ private static final int EVEN_DIMMER_MAX_PERCENT_ALLOWED = 100;
+
private static final int MSG_USER_CHANGED = 0;
private static final int MSG_SET_UP = 1;
private static final int MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE = 2;
@@ -193,6 +196,9 @@
private final boolean mVisibleBackgroundUsersEnabled;
private final UserManagerService mUserManager;
+ private Spline mEvenDimmerSpline;
+ private boolean mEvenDimmerActivated;
+
public ColorDisplayService(Context context) {
super(context);
mHandler = new TintHandler(DisplayThread.get().getLooper());
@@ -1625,6 +1631,16 @@
}
/**
+ * Gets the adjusted nits, given a strength and nits.
+ * @param strength of reduce bright colors
+ * @param nits target nits
+ * @return the actual nits that would be output, given input nits and rbc strength.
+ */
+ public float getAdjustedNitsForStrength(float nits, int strength) {
+ return mReduceBrightColorsTintController.getAdjustedNitsForStrength(nits, strength);
+ }
+
+ /**
* Sets the listener and returns whether reduce bright colors is currently enabled.
*/
public boolean setReduceBrightColorsListener(ReduceBrightColorsListener listener) {
@@ -1644,6 +1660,14 @@
}
/**
+ *
+ * @return whether reduce bright colors is on, due to even dimmer being activated
+ */
+ public boolean getReduceBrightColorsActivatedForEvenDimmer() {
+ return mEvenDimmerActivated;
+ }
+
+ /**
* Gets the computed brightness, in nits, when the reduce bright colors feature is applied
* at the current strength.
*
@@ -1667,10 +1691,42 @@
* Applies tint changes for even dimmer feature.
*/
public void applyEvenDimmerColorChanges(boolean enabled, int strength) {
+ mEvenDimmerActivated = enabled;
mReduceBrightColorsTintController.setActivated(enabled);
mReduceBrightColorsTintController.setMatrix(strength);
mHandler.sendEmptyMessage(MSG_APPLY_REDUCE_BRIGHT_COLORS);
}
+
+ /**
+ * Get spline to map between requested nits, and required even dimmer strength.
+ * @return nits to strength spline
+ */
+ public Spline fetchEvenDimmerSpline(float nits) {
+ if (mEvenDimmerSpline == null) {
+ mEvenDimmerSpline = createNitsToStrengthSpline(nits);
+ }
+ return mEvenDimmerSpline;
+ }
+
+ /**
+ * Creates a spline mapping requested nits values, for each resulting strength value
+ * (in percent) for even dimmer.
+ * Returns null if coefficients are not initialised.
+ * @return spline from nits to strength
+ */
+ private Spline createNitsToStrengthSpline(float nits) {
+ final float[] requestedNits = new float[EVEN_DIMMER_MAX_PERCENT_ALLOWED + 1];
+ final float[] resultingStrength = new float[EVEN_DIMMER_MAX_PERCENT_ALLOWED + 1];
+ for (int i = 0; i <= EVEN_DIMMER_MAX_PERCENT_ALLOWED; i++) {
+ resultingStrength[EVEN_DIMMER_MAX_PERCENT_ALLOWED - i] = i;
+ requestedNits[EVEN_DIMMER_MAX_PERCENT_ALLOWED - i] =
+ getAdjustedNitsForStrength(nits, i);
+ if (requestedNits[EVEN_DIMMER_MAX_PERCENT_ALLOWED - i] == 0) {
+ return null;
+ }
+ }
+ return new Spline.LinearSpline(requestedNits, resultingStrength);
+ }
}
/**
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 f529c4c..4f6fbd0 100644
--- a/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java
+++ b/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java
@@ -123,6 +123,14 @@
return computeComponentValue(mStrength) * nits;
}
+ /**
+ * Returns the effective brightness (in nits), which has been adjusted to account for the effect
+ * of the bright color reduction.
+ */
+ public float getAdjustedNitsForStrength(float nits, int strength) {
+ return computeComponentValue(strength) * nits;
+ }
+
private float computeComponentValue(int strengthLevel) {
final float percentageStrength = strengthLevel / 100f;
final float squaredPercentageStrength = percentageStrength * percentageStrength;
diff --git a/services/core/java/com/android/server/display/config/EvenDimmerBrightnessData.java b/services/core/java/com/android/server/display/config/EvenDimmerBrightnessData.java
index 7e2e10a..9a590a2 100644
--- a/services/core/java/com/android/server/display/config/EvenDimmerBrightnessData.java
+++ b/services/core/java/com/android/server/display/config/EvenDimmerBrightnessData.java
@@ -34,72 +34,76 @@
/**
* Brightness value at which even dimmer methods are used.
*/
- public final float mTransitionPoint;
+ public final float transitionPoint;
/**
* Nits array, maps to mBacklight
*/
- public final float[] mNits;
+ public final float[] nits;
/**
* Backlight array, maps to mBrightness and mNits
*/
- public final float[] mBacklight;
+ public final float[] backlight;
/**
* Brightness array, maps to mBacklight
*/
- public final float[] mBrightness;
+ public final float[] brightness;
+
/**
* Spline, mapping between backlight and nits
*/
- public final Spline mBacklightToNits;
+ public final Spline backlightToNits;
+
/**
* Spline, mapping between nits and backlight
*/
- public final Spline mNitsToBacklight;
+ public final Spline nitsToBacklight;
+
/**
* Spline, mapping between brightness and backlight
*/
- public final Spline mBrightnessToBacklight;
+ public final Spline brightnessToBacklight;
+
/**
* Spline, mapping between backlight and brightness
*/
- public final Spline mBacklightToBrightness;
+ public final Spline backlightToBrightness;
/**
* Spline, mapping the minimum nits for each lux condition.
*/
- public final Spline mMinLuxToNits;
+ public final Spline minLuxToNits;
@VisibleForTesting
public EvenDimmerBrightnessData(float transitionPoint, float[] nits,
float[] backlight, float[] brightness, Spline backlightToNits,
Spline nitsToBacklight, Spline brightnessToBacklight, Spline backlightToBrightness,
Spline minLuxToNits) {
- mTransitionPoint = transitionPoint;
- mNits = nits;
- mBacklight = backlight;
- mBrightness = brightness;
- mBacklightToNits = backlightToNits;
- mNitsToBacklight = nitsToBacklight;
- mBrightnessToBacklight = brightnessToBacklight;
- mBacklightToBrightness = backlightToBrightness;
- mMinLuxToNits = minLuxToNits;
+ this.transitionPoint = transitionPoint;
+ this.nits = nits;
+ this.backlight = backlight;
+ this.brightness = brightness;
+ this.backlightToNits = backlightToNits;
+ this.nitsToBacklight = nitsToBacklight;
+ this.brightnessToBacklight = brightnessToBacklight;
+ this.backlightToBrightness = backlightToBrightness;
+ this.minLuxToNits = minLuxToNits;
}
@Override
public String toString() {
return "EvenDimmerBrightnessData {"
- + "mTransitionPoint: " + mTransitionPoint
- + ", mNits: " + Arrays.toString(mNits)
- + ", mBacklight: " + Arrays.toString(mBacklight)
- + ", mBrightness: " + Arrays.toString(mBrightness)
- + ", mBacklightToNits: " + mBacklightToNits
- + ", mNitsToBacklight: " + mNitsToBacklight
- + ", mBrightnessToBacklight: " + mBrightnessToBacklight
- + ", mBacklightToBrightness: " + mBacklightToBrightness
- + ", mMinLuxToNits: " + mMinLuxToNits
+ + "transitionPoint: " + transitionPoint
+ + ", nits: " + Arrays.toString(nits)
+ + ", backlight: " + Arrays.toString(backlight)
+ + ", brightness: " + Arrays.toString(brightness)
+ + ", backlightToNits: " + backlightToNits
+ + ", nitsToBacklight: " + nitsToBacklight
+ + ", brightnessToBacklight: " + brightnessToBacklight
+ + ", backlightToBrightness: " + backlightToBrightness
+ + ", minLuxToNits: " + minLuxToNits
+ "} ";
}
@@ -122,7 +126,6 @@
if (map == null) {
return null;
}
- String interpolation = map.getInterpolation();
List<BrightnessPoint> brightnessPoints = map.getBrightnessPoint();
if (brightnessPoints.isEmpty()) {
@@ -169,22 +172,11 @@
++i;
}
- // Explicitly choose linear interpolation.
- if ("linear".equals(interpolation)) {
- return new EvenDimmerBrightnessData(transitionPoint, nits, backlight, brightness,
- new Spline.LinearSpline(backlight, nits),
- new Spline.LinearSpline(nits, backlight),
- new Spline.LinearSpline(brightness, backlight),
- new Spline.LinearSpline(backlight, brightness),
- new Spline.LinearSpline(minLux, minNits)
- );
- }
-
return new EvenDimmerBrightnessData(transitionPoint, nits, backlight, brightness,
- Spline.createSpline(backlight, nits),
- Spline.createSpline(nits, backlight),
- Spline.createSpline(brightness, backlight),
- Spline.createSpline(backlight, brightness),
+ new Spline.LinearSpline(backlight, nits),
+ new Spline.LinearSpline(nits, backlight),
+ new Spline.LinearSpline(brightness, backlight),
+ new Spline.LinearSpline(backlight, brightness),
Spline.createSpline(minLux, minNits)
);
}
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 0eafb59..a07facf 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -512,8 +512,6 @@
<xs:annotation name="final"/>
</xs:element>
</xs:sequence>
- <!-- valid value of interpolation if specified: linear -->
- <xs:attribute name="interpolation" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="brightnessPoint">
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 355b0ab..5309263 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -91,8 +91,6 @@
public class ComprehensiveBrightnessMap {
ctor public ComprehensiveBrightnessMap();
method @NonNull public final java.util.List<com.android.server.display.config.BrightnessPoint> getBrightnessPoint();
- method public String getInterpolation();
- method public void setInterpolation(String);
}
public class Density {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
index fd05b26..8e1be9a 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -392,7 +392,7 @@
public void testInvalidLuxThrottling() throws Exception {
setupDisplayDeviceConfigFromDisplayConfigFile(
getContent(getInvalidLuxThrottling(), getValidProxSensor(),
- /* includeIdleMode= */ true, /* enableEvenDimmer */ false));
+ /* includeIdleMode= */ true, /* enableEvenDimmer= */ false));
Map<DisplayDeviceConfig.BrightnessLimitMapType, Map<Float, Float>> luxThrottlingData =
mDisplayDeviceConfig.getLuxThrottlingData();
@@ -600,7 +600,7 @@
public void testProximitySensorWithEmptyValuesFromDisplayConfig() throws IOException {
setupDisplayDeviceConfigFromDisplayConfigFile(
getContent(getValidLuxThrottling(), getProxSensorWithEmptyValues(),
- /* includeIdleMode= */ true, /* enableEvenDimmer */ false));
+ /* includeIdleMode= */ true, /* enableEvenDimmer= */ false));
assertNull(mDisplayDeviceConfig.getProximitySensor());
}
@@ -608,7 +608,7 @@
public void testProximitySensorWithRefreshRatesFromDisplayConfig() throws IOException {
setupDisplayDeviceConfigFromDisplayConfigFile(
getContent(getValidLuxThrottling(), getValidProxSensorWithRefreshRateAndVsyncRate(),
- /* includeIdleMode= */ true, /* enableEvenDimmer */ false));
+ /* includeIdleMode= */ true, /* enableEvenDimmer= */ false));
assertEquals("test_proximity_sensor",
mDisplayDeviceConfig.getProximitySensor().type);
assertEquals("Test Proximity Sensor",
@@ -803,7 +803,7 @@
@Test
public void testBrightnessRamps_IdleFallsBackToConfigInteractive() throws IOException {
setupDisplayDeviceConfigFromDisplayConfigFile(getContent(getValidLuxThrottling(),
- getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer */ false));
+ getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer= */ false));
assertEquals(mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis(), 3000);
assertEquals(mDisplayDeviceConfig.getBrightnessRampIncreaseMaxMillis(), 2000);
@@ -820,14 +820,14 @@
@Test
public void testBrightnessCapForWearBedtimeMode() throws IOException {
setupDisplayDeviceConfigFromDisplayConfigFile(getContent(getValidLuxThrottling(),
- getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer */ false));
+ getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer= */ false));
assertEquals(0.1f, mDisplayDeviceConfig.getBrightnessCapForWearBedtimeMode(), ZERO_DELTA);
}
@Test
public void testAutoBrightnessBrighteningLevels() throws IOException {
setupDisplayDeviceConfigFromDisplayConfigFile(getContent(getValidLuxThrottling(),
- getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer */ false));
+ getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer= */ false));
assertArrayEquals(new float[]{0.0f, 80},
mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(
@@ -890,7 +890,7 @@
when(mFlags.areAutoBrightnessModesEnabled()).thenReturn(false);
setupDisplayDeviceConfigFromConfigResourceFile();
setupDisplayDeviceConfigFromDisplayConfigFile(getContent(getValidLuxThrottling(),
- getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer */ false));
+ getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer= */ false));
assertArrayEquals(new float[]{brightnessIntToFloat(50), brightnessIntToFloat(100),
brightnessIntToFloat(150)},
@@ -929,7 +929,7 @@
when(mFlags.isEvenDimmerEnabled()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_evenDimmerEnabled)).thenReturn(true);
setupDisplayDeviceConfigFromDisplayConfigFile(getContent(getValidLuxThrottling(),
- getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer */ true));
+ getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer= */ true));
assertTrue(mDisplayDeviceConfig.isEvenDimmerAvailable());
assertEquals(0.01f, mDisplayDeviceConfig.getBacklightFromBrightness(0.002f), ZERO_DELTA);
@@ -1365,7 +1365,7 @@
private String getContent() {
return getContent(getValidLuxThrottling(), getValidProxSensor(),
- /* includeIdleMode= */ true, false);
+ /* includeIdleMode= */ true, /* enableEvenDimmer= */ false);
}
private String getContent(String brightnessCapConfig, String proxSensor,
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 120cc84..f5bed99 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -29,8 +29,10 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -45,6 +47,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.util.Spline;
import android.view.Display;
import android.view.DisplayAddress;
import android.view.SurfaceControl;
@@ -59,6 +62,7 @@
import com.android.internal.R;
import com.android.server.LocalServices;
import com.android.server.display.LocalDisplayAdapter.BacklightAdapter;
+import com.android.server.display.color.ColorDisplayService;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.mode.DisplayModeDirector;
import com.android.server.display.notifications.DisplayNotificationManager;
@@ -119,6 +123,8 @@
private DisplayManagerFlags mFlags;
@Mock
private DisplayPowerController mMockedDisplayPowerController;
+ @Mock
+ private ColorDisplayService.ColorDisplayServiceInternal mMockedColorDisplayServiceInternal;
private Handler mHandler;
@@ -133,6 +139,11 @@
private Injector mInjector;
@Mock
+ private DisplayDeviceConfig mMockDisplayDeviceConfig;
+ @Mock
+ private BacklightAdapter mMockBacklightAdapter;
+
+ @Mock
private LocalDisplayAdapter.SurfaceControlProxy mSurfaceControlProxy;
private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f };
private static final int[] BACKLIGHT_RANGE = { 1, 255 };
@@ -150,6 +161,9 @@
doReturn(mMockedResources).when(mMockedContext).getResources();
LocalServices.removeServiceForTest(LightsManager.class);
LocalServices.addService(LightsManager.class, mMockedLightsManager);
+ LocalServices.removeServiceForTest(ColorDisplayService.ColorDisplayServiceInternal.class);
+ LocalServices.addService(ColorDisplayService.ColorDisplayServiceInternal.class,
+ mMockedColorDisplayServiceInternal);
mInjector = new Injector();
when(mSurfaceControlProxy.getBootDisplayModeSupport()).thenReturn(true);
mAdapter = new LocalDisplayAdapter(mMockedSyncRoot, mMockedContext, mHandler,
@@ -211,7 +225,15 @@
when(mMockedResources.getIntArray(
com.android.internal.R.array.config_autoBrightnessLcdBacklightValues))
.thenReturn(new int[]{});
+
+ when(mMockedColorDisplayServiceInternal.fetchEvenDimmerSpline(3)).thenReturn(
+ new Spline.LinearSpline(
+ new float[]{2f, 3.0f, 500f, 2000f},
+ new float[]{100, 0, 0, 0}));
+ when(mMockDisplayDeviceConfig.isEvenDimmerAvailable()).thenReturn(true);
+
doReturn(true).when(mFlags).isDisplayOffloadEnabled();
+ doReturn(true).when(mFlags).isEvenDimmerEnabled();
initDisplayOffloadSession();
}
@@ -222,6 +244,122 @@
}
}
+ @Test
+ public void testEvenDimmer() throws InterruptedException {
+ // Set up
+ FakeDisplay display = new FakeDisplay(PORT_A);
+ setUpDisplay(display);
+ updateAvailableDisplays();
+ mAdapter.registerLocked();
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+ DisplayDevice displayDevice = mListener.addedDisplays.get(0);
+
+ // brightness|backlight| nits | strength
+ // 0.5 | 0.45 | 600 | 0 // initial setup value
+ // 0.4 | 0.35 | 500 | 0 // normal range value
+ // 0.31 | 0.2 | 3 | 0 // transition point
+ // 0.16 | 0.125 | 2.5 | 50 // mid point of even dimmer
+ // 0.1 | 0.05 | 2 | 100 // bottom of even dimmer range
+ // 0.05 | 0.01 | 1 | 100+ // beyond strength=100 range (should still return 100)
+ when(mMockDisplayDeviceConfig.getEvenDimmerTransitionPoint()).thenReturn(0.31f);
+ when(mMockDisplayDeviceConfig.getBacklightFromBrightness(0.5f)).thenReturn(0.45f);
+ when(mMockDisplayDeviceConfig.getBacklightFromBrightness(0.4f)).thenReturn(0.35f);
+ when(mMockDisplayDeviceConfig.getBacklightFromBrightness(0.31f)).thenReturn(0.2f);
+ when(mMockDisplayDeviceConfig.getBacklightFromBrightness(0.16f)).thenReturn(0.125f);
+ when(mMockDisplayDeviceConfig.getBacklightFromBrightness(0.1f)).thenReturn(0.05f);
+ when(mMockDisplayDeviceConfig.getBacklightFromBrightness(0.05f)).thenReturn(0.01f);
+ when(mMockDisplayDeviceConfig.getNitsFromBacklight(0.45f)).thenReturn(600f);
+ when(mMockDisplayDeviceConfig.getNitsFromBacklight(0.35f)).thenReturn(500f);
+ when(mMockDisplayDeviceConfig.getNitsFromBacklight(0.2f)).thenReturn(3f);
+ when(mMockDisplayDeviceConfig.getNitsFromBacklight(0.125f)).thenReturn(2.5f);
+ when(mMockDisplayDeviceConfig.getNitsFromBacklight(0.05f)).thenReturn(2f);
+ when(mMockDisplayDeviceConfig.getNitsFromBacklight(0.01f)).thenReturn(1f);
+
+ // initialise brightness to 0.5
+ Runnable changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON,
+ 0.5f, 0.5f, null);
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ changeStateRunnable.run();
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ verify(mSurfaceControlProxy).setDisplayPowerMode(any(), anyInt());
+ verify(mMockBacklightAdapter).setBacklight(anyFloat(), anyFloat(), anyFloat(), anyFloat());
+ verify(mMockedColorDisplayServiceInternal).applyEvenDimmerColorChanges(eq(false), eq(0));
+ verify(mMockedColorDisplayServiceInternal).fetchEvenDimmerSpline(eq(3.0f));
+
+ // set up normal brightness range
+ changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON, 0.4f, 0.4f,
+ null);
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ changeStateRunnable.run();
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ // verify normal brightness range
+ verify(mMockBacklightAdapter).setBacklight(0.35f, 500f, 0.35f, 500f);
+ verify(mMockedColorDisplayServiceInternal,
+ times(1)) // no more, since the strength is the same
+ .applyEvenDimmerColorChanges(eq(false), eq(0));
+ verify(mMockedColorDisplayServiceInternal, times(2)).fetchEvenDimmerSpline(eq(3.0f));
+
+ // set up even dimmer edge range
+ changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON, 0.31f,
+ 0.31f, null);
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ changeStateRunnable.run();
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ // verify even dimmer edge range
+ verify(mMockBacklightAdapter).setBacklight(0.2f, 3f, 0.2f, 3f);
+ // verify no more times, since the strength and enabled-ness is the same
+ verify(mMockedColorDisplayServiceInternal, times(1)).applyEvenDimmerColorChanges(eq(false),
+ eq(0));
+ verify(mMockedColorDisplayServiceInternal, times(3)).fetchEvenDimmerSpline(eq(3.0f));
+
+ // set up mid point of even dimmer range
+ changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON, 0.16f,
+ 0.16f, null);
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ changeStateRunnable.run();
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ // verify within even dimmer range
+ verify(mMockBacklightAdapter).setBacklight(0.125f, 2.5f, 0.125f, 2.5f);
+ verify(mMockedColorDisplayServiceInternal).applyEvenDimmerColorChanges(eq(true), eq(50));
+ verify(mMockedColorDisplayServiceInternal, times(4)).fetchEvenDimmerSpline(eq(3.0f));
+
+ // set up within even dimmer range
+ changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON, 0.1f, 0.1f,
+ null);
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ changeStateRunnable.run();
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ // verify within even dimmer range
+ verify(mMockBacklightAdapter).setBacklight(0.05f, 2f, 0.05f, 2f);
+ verify(mMockedColorDisplayServiceInternal).applyEvenDimmerColorChanges(eq(true), eq(100));
+ verify(mMockedColorDisplayServiceInternal, times(5)).fetchEvenDimmerSpline(eq(3.0f));
+
+ // set up below even dimmer range
+ changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON, 0.05f,
+ 0.05f, null);
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ changeStateRunnable.run();
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ // verify within even dimmer range
+ verify(mMockBacklightAdapter).setBacklight(0.01f, 1f, 0.01f, 1f);
+ // ensure no greater than 100 strength is returned, therefore not called again.
+ verify(mMockedColorDisplayServiceInternal).applyEvenDimmerColorChanges(eq(true), eq(100));
+ verify(mMockedColorDisplayServiceInternal, times(6)).fetchEvenDimmerSpline(eq(3.0f));
+
+ // set up return to normal range
+ changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON, 0.4f, 0.4f,
+ null);
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ changeStateRunnable.run();
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ // verify return to normal range
+ verify(mMockBacklightAdapter, times(2)).setBacklight(0.35f, 500f, 0.35f, 500f);
+ verify(mMockedColorDisplayServiceInternal, times(2)).applyEvenDimmerColorChanges(eq(false),
+ anyInt());
+ verify(mMockedColorDisplayServiceInternal, times(7)).fetchEvenDimmerSpline(eq(3.0f));
+ }
+
/**
* Confirm that display is marked as private when it is listed in
* com.android.internal.R.array.config_localPrivateDisplayPorts.
@@ -1461,15 +1599,16 @@
return mSurfaceControlProxy;
}
- // Instead of using DisplayDeviceConfig.create(context, physicalDisplayId, isFirstDisplay)
- // we should use DisplayDeviceConfig.create(context, isFirstDisplay) for the test to ensure
- // that real device DisplayDeviceConfig is not loaded for FakeDisplay and we are getting
- // consistent behaviour. Please also note that context passed to this method, is
- // mMockContext and values will be loaded from mMockResources.
@Override
public DisplayDeviceConfig createDisplayDeviceConfig(Context context,
long physicalDisplayId, boolean isFirstDisplay, DisplayManagerFlags flags) {
- return DisplayDeviceConfig.create(context, isFirstDisplay, flags);
+ return mMockDisplayDeviceConfig;
+ }
+
+ @Override
+ public BacklightAdapter getBacklightAdapter(IBinder displayToken, boolean isFirstDisplay,
+ LocalDisplayAdapter.SurfaceControlProxy surfaceControlProxy) {
+ return mMockBacklightAdapter;
}
}