diff options
11 files changed, 318 insertions, 105 deletions
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index dc263c5a6b32..af9c9accb635 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 class DisplayDeviceConfig { */ public float[] getNits() { if (mEvenDimmerBrightnessData != null) { - return mEvenDimmerBrightnessData.mNits; + return mEvenDimmerBrightnessData.nits; } return mNits; } @@ -1093,7 +1093,7 @@ public class DisplayDeviceConfig { @VisibleForTesting public float[] getBacklight() { if (mEvenDimmerBrightnessData != null) { - return mEvenDimmerBrightnessData.mBacklight; + return mEvenDimmerBrightnessData.backlight; } return mBacklight; } @@ -1107,7 +1107,7 @@ public class DisplayDeviceConfig { */ 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 class DisplayDeviceConfig { */ 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 @@ public class DisplayDeviceConfig { */ private Spline getBacklightToBrightnessSpline() { if (mEvenDimmerBrightnessData != null) { - return mEvenDimmerBrightnessData.mBacklightToBrightness; + return mEvenDimmerBrightnessData.backlightToBrightness; } return mBacklightToBrightnessSpline; } @@ -1144,11 +1144,11 @@ public class DisplayDeviceConfig { */ 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 class DisplayDeviceConfig { */ 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 @@ public class DisplayDeviceConfig { if (mEvenDimmerBrightnessData == null) { return INVALID_NITS; } - return mEvenDimmerBrightnessData.mMinLuxToNits.interpolate(lux); + return mEvenDimmerBrightnessData.minLuxToNits.interpolate(lux); } /** @@ -1197,7 +1197,7 @@ public class DisplayDeviceConfig { if (mEvenDimmerBrightnessData == null) { return PowerManager.BRIGHTNESS_MIN; } - return mEvenDimmerBrightnessData.mTransitionPoint; + return mEvenDimmerBrightnessData.transitionPoint; } /** @@ -1268,7 +1268,7 @@ public class DisplayDeviceConfig { */ public float[] getBrightness() { if (mEvenDimmerBrightnessData != null) { - return mEvenDimmerBrightnessData.mBrightness; + return mEvenDimmerBrightnessData.brightness; } return mBrightness; } @@ -2617,13 +2617,13 @@ public class DisplayDeviceConfig { 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 @@ public class DisplayDeviceConfig { + 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 711bc7972091..62d876102720 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 android.hardware.display.DisplayManagerInternal.DisplayPowerReques 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; @@ -1755,6 +1756,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call 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 @@ -1769,7 +1772,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call 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 0570b2ab510b..5edea0a8b031 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.SystemProperties; 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { } 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 ad57ebfb0600..9e9b899ffa7d 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 final class BrightnessEvent { 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 @@ public final class BrightnessEvent { + ((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 bd759f378d5b..dc59e66d85f2 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.provider.Settings.System; 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 @@ public final class ColorDisplayService extends SystemService { 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 @@ public final class ColorDisplayService extends SystemService { 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 @@ public final class ColorDisplayService extends SystemService { } /** + * 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 @@ public final class ColorDisplayService extends SystemService { } /** + * + * @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 @@ public final class ColorDisplayService extends SystemService { * 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 f529c4c65a9a..4f6fbd003d9a 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 @@ public class ReduceBrightColorsTintController extends TintController { 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 7e2e10a7639f..9a590a293ea3 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 @@ public class EvenDimmerBrightnessData { /** * 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 @@ public class EvenDimmerBrightnessData { if (map == null) { return null; } - String interpolation = map.getInterpolation(); List<BrightnessPoint> brightnessPoints = map.getBrightnessPoint(); if (brightnessPoints.isEmpty()) { @@ -169,22 +172,11 @@ public class EvenDimmerBrightnessData { ++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 0eafb59bdeac..a07facf79423 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 355b0ab15a62..5309263ed87c 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 @@ package com.android.server.display.config { 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 fd05b26c320b..8e1be9a777fd 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 final class DisplayDeviceConfigTest { 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 final class DisplayDeviceConfigTest { 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 final class DisplayDeviceConfigTest { 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 @@ public final class DisplayDeviceConfigTest { @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 @@ public final class DisplayDeviceConfigTest { @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 @@ public final class DisplayDeviceConfigTest { 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 @@ public final class DisplayDeviceConfigTest { 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 @@ public final class DisplayDeviceConfigTest { 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 120cc84193cd..f5bed999d5a0 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.assertFalse; 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.Binder; 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.dx.mockito.inline.extended.StaticMockitoSession; import com.android.internal.R; import com.android.server.LocalServices; import com.android.server.display.LocalDisplayAdapter.BacklightAdapter; +import com.android.server.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 @@ public class LocalDisplayAdapterTest { private DisplayManagerFlags mFlags; @Mock private DisplayPowerController mMockedDisplayPowerController; + @Mock + private ColorDisplayService.ColorDisplayServiceInternal mMockedColorDisplayServiceInternal; private Handler mHandler; @@ -133,6 +139,11 @@ public class LocalDisplayAdapterTest { 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 @@ public class LocalDisplayAdapterTest { 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 @@ public class LocalDisplayAdapterTest { 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 @@ public class LocalDisplayAdapterTest { } } + @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 @@ public class LocalDisplayAdapterTest { 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; } } |