diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index ffb602d93b0f2..16511a678760d 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -6346,4 +6346,8 @@ true true + + + false diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 92dc5694ff2c9..6974bd29e5488 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2229,6 +2229,7 @@ + diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 592daa61f36c9..720ea99da93d2 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -50,7 +50,12 @@ import com.android.server.display.brightness.BrightnessEvent; import java.io.PrintWriter; -class AutomaticBrightnessController { +/** + * Manages the associated display brightness when in auto-brightness mode. This is also + * responsible for managing the brightness lux-nits mapping strategies. Internally also listens to + * the LightSensor and adjusts the system brightness in case of changes in the surrounding lux. + */ +public class AutomaticBrightnessController { private static final String TAG = "AutomaticBrightnessController"; private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false; @@ -1140,7 +1145,7 @@ class AutomaticBrightnessController { if (mCurrentBrightnessMapper != null) { return mCurrentBrightnessMapper.convertToFloatScale(nits); } else { - return -1.0f; + return PowerManager.BRIGHTNESS_INVALID_FLOAT; } } diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java index d7c1529aedc4e..d0471837d79b3 100644 --- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java +++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java @@ -322,9 +322,10 @@ public abstract class BrightnessMappingStrategy { public abstract float convertToNits(float brightness); /** - * Converts the provided nits value to a float value if possible. + * Converts the provided nit value to a float scale value if possible. * - * Returns -1.0f if there's no available mapping for the nits to float. + * Returns {@link PowerManager.BRIGHTNESS_INVALID_FLOAT} if there's no available mapping for + * the nits to float scale. */ public abstract float convertToFloatScale(float nits); @@ -679,7 +680,7 @@ public abstract class BrightnessMappingStrategy { @Override public float convertToFloatScale(float nits) { - return -1.0f; + return PowerManager.BRIGHTNESS_INVALID_FLOAT; } @Override diff --git a/services/core/java/com/android/server/display/BrightnessSetting.java b/services/core/java/com/android/server/display/BrightnessSetting.java index 4a9b562be697c..de42370e6d847 100644 --- a/services/core/java/com/android/server/display/BrightnessSetting.java +++ b/services/core/java/com/android/server/display/BrightnessSetting.java @@ -121,6 +121,23 @@ public class BrightnessSetting { } } + /** + * @return The brightness for the default display in nits. Used when the underlying display + * device has changed but we want to persist the nit value. + */ + public float getBrightnessNitsForDefaultDisplay() { + return mPersistentDataStore.getBrightnessNitsForDefaultDisplay(); + } + + /** + * Set brightness in nits for the default display. Used when we want to persist the nit value + * even if the underlying display device changes. + * @param nits The brightness value in nits + */ + public void setBrightnessNitsForDefaultDisplay(float nits) { + mPersistentDataStore.setBrightnessNitsForDefaultDisplay(nits); + } + private void notifyListeners(float brightness) { for (BrightnessSettingListener l : mListeners) { l.onBrightnessChanged(brightness); diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 84fe8f21b7648..055ca37d9a3f4 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -233,6 +233,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // True if should use light sensor to automatically determine doze screen brightness. private final boolean mAllowAutoBrightnessWhileDozingConfig; + // True if we want to persist the brightness value in nits even if the underlying display + // device changes. + private final boolean mPersistBrightnessNitsForDefaultDisplay; + // True if the brightness config has changed and the short-term model needs to be reset private boolean mShouldResetShortTermModel; @@ -590,6 +594,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean( com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing); + mPersistBrightnessNitsForDefaultDisplay = resources.getBoolean( + com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay); + mDisplayDeviceConfig = logicalDisplay.getPrimaryDisplayDeviceLocked() .getDisplayDeviceConfig(); @@ -658,7 +665,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call loadProximitySensor(); - mCurrentScreenBrightnessSetting = getScreenBrightnessSetting(); + loadNitBasedBrightnessSetting(); mBrightnessToFollow = PowerManager.BRIGHTNESS_INVALID_FLOAT; mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting(); mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; @@ -745,10 +752,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Override public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) { mHbmController.onAmbientLuxChange(ambientLux); - if (mAutomaticBrightnessController == null || nits < 0) { + if (nits < 0) { mBrightnessToFollow = leadDisplayBrightness; } else { - float brightness = mAutomaticBrightnessController.convertToFloatScale(nits); + float brightness = convertToFloatScale(nits); if (isValidBrightnessValue(brightness)) { mBrightnessToFollow = brightness; } else { @@ -895,6 +902,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mDisplayDeviceConfig = config; mBrightnessThrottlingDataId = brightnessThrottlingDataId; loadFromDisplayDeviceConfig(token, info, hbmMetadata); + loadNitBasedBrightnessSetting(); /// Since the underlying display-device changed, we really don't know the // last command that was sent to change it's state. Lets assume it is unknown so @@ -2563,11 +2571,34 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call return clampAbsoluteBrightness(brightness); } + private void loadNitBasedBrightnessSetting() { + if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) { + float brightnessNitsForDefaultDisplay = + mBrightnessSetting.getBrightnessNitsForDefaultDisplay(); + if (brightnessNitsForDefaultDisplay >= 0) { + float brightnessForDefaultDisplay = convertToFloatScale( + brightnessNitsForDefaultDisplay); + if (isValidBrightnessValue(brightnessForDefaultDisplay)) { + mBrightnessSetting.setBrightness(brightnessForDefaultDisplay); + mCurrentScreenBrightnessSetting = brightnessForDefaultDisplay; + return; + } + } + } + mCurrentScreenBrightnessSetting = getScreenBrightnessSetting(); + } + @Override public void setBrightness(float brightnessValue) { // Update the setting, which will eventually call back into DPC to have us actually update // the display with the new value. mBrightnessSetting.setBrightness(brightnessValue); + if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) { + float nits = convertToNits(brightnessValue); + if (nits >= 0) { + mBrightnessSetting.setBrightnessNitsForDefaultDisplay(nits); + } + } } @Override @@ -2582,7 +2613,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call return; } setCurrentScreenBrightness(brightnessValue); - mBrightnessSetting.setBrightness(brightnessValue); + setBrightness(brightnessValue); } private void setCurrentScreenBrightness(float brightnessValue) { @@ -2661,6 +2692,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call return mAutomaticBrightnessController.convertToNits(brightness); } + private float convertToFloatScale(float nits) { + if (mAutomaticBrightnessController == null) { + return PowerManager.BRIGHTNESS_INVALID_FLOAT; + } + return mAutomaticBrightnessController.convertToFloatScale(nits); + } + @GuardedBy("mLock") private void updatePendingProximityRequestsLocked() { mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked; @@ -2759,6 +2797,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pw.println(" mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig); pw.println(" mAllowAutoBrightnessWhileDozingConfig=" + mAllowAutoBrightnessWhileDozingConfig); + pw.println(" mPersistBrightnessNitsForDefaultDisplay=" + + mPersistBrightnessNitsForDefaultDisplay); pw.println(" mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp); pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig); pw.println(" mColorFadeEnabled=" + mColorFadeEnabled); diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java index 297a6f8a52e5b..3c937e82a2fa5 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController2.java +++ b/services/core/java/com/android/server/display/DisplayPowerController2.java @@ -861,7 +861,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal noteScreenBrightness(mPowerState.getScreenBrightness()); // Initialize all of the brightness tracking state - final float brightness = convertToNits(mPowerState.getScreenBrightness()); + final float brightness = mDisplayBrightnessController.convertToNits( + mPowerState.getScreenBrightness()); if (mBrightnessTracker != null && brightness >= PowerManager.BRIGHTNESS_MIN) { mBrightnessTracker.start(brightness); } @@ -1024,6 +1025,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mHbmController, mBrightnessThrottler, mIdleModeBrightnessMapper, mDisplayDeviceConfig.getAmbientHorizonShort(), mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userBrightness); + mDisplayBrightnessController.setAutomaticBrightnessController( + mAutomaticBrightnessController); mBrightnessEventRingBuffer = new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX); @@ -1389,7 +1392,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal : mAutomaticBrightnessController.getAmbientLux(); for (int i = 0; i < displayBrightnessFollowers.size(); i++) { DisplayPowerControllerInterface follower = displayBrightnessFollowers.valueAt(i); - follower.setBrightnessToFollow(rawBrightnessState, convertToNits(rawBrightnessState), + follower.setBrightnessToFollow(rawBrightnessState, + mDisplayBrightnessController.convertToNits(rawBrightnessState), ambientLux); } @@ -2191,10 +2195,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal @Override public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) { mHbmController.onAmbientLuxChange(ambientLux); - if (mAutomaticBrightnessController == null || nits < 0) { + if (nits < 0) { mDisplayBrightnessController.setBrightnessToFollow(leadDisplayBrightness); } else { - float brightness = mAutomaticBrightnessController.convertToFloatScale(nits); + float brightness = mDisplayBrightnessController.convertToFloatScale(nits); if (BrightnessUtils.isValidBrightnessValue(brightness)) { mDisplayBrightnessController.setBrightnessToFollow(brightness); } else { @@ -2230,7 +2234,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated, boolean wasShortTermModelActive) { - final float brightnessInNits = convertToNits(brightness); + final float brightnessInNits = mDisplayBrightnessController.convertToNits(brightness); if (mUseAutoBrightness && brightnessInNits >= 0.0f && mAutomaticBrightnessController != null && mBrightnessTracker != null) { // We only want to track changes on devices that can actually map the display backlight @@ -2247,13 +2251,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal } } - private float convertToNits(float brightness) { - if (mAutomaticBrightnessController == null) { - return -1f; - } - return mAutomaticBrightnessController.convertToNits(brightness); - } - @Override public void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower) { synchronized (mLock) { @@ -2513,17 +2510,17 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal int appliedRbcStrength = event.isRbcEnabled() ? event.getRbcStrength() : -1; float appliedHbmMaxNits = event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF - ? -1f : convertToNits(event.getHbmMax()); + ? -1f : mDisplayBrightnessController.convertToNits(event.getHbmMax()); // thermalCapNits set to -1 if not currently capping max brightness float appliedThermalCapNits = event.getThermalMax() == PowerManager.BRIGHTNESS_MAX - ? -1f : convertToNits(event.getThermalMax()); + ? -1f : mDisplayBrightnessController.convertToNits(event.getThermalMax()); if (mLogicalDisplay.getPrimaryDisplayDeviceLocked() != null && mLogicalDisplay.getPrimaryDisplayDeviceLocked() .getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL) { FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED, - convertToNits(event.getInitialBrightness()), - convertToNits(event.getBrightness()), + mDisplayBrightnessController.convertToNits(event.getInitialBrightness()), + mDisplayBrightnessController.convertToNits(event.getBrightness()), event.getLux(), event.getPhysicalDisplayId(), event.wasShortTermModelActive(), diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java index e7601bcd8f3ad..ec70c8966736c 100644 --- a/services/core/java/com/android/server/display/PersistentDataStore.java +++ b/services/core/java/com/android/server/display/PersistentDataStore.java @@ -94,6 +94,7 @@ import java.util.Objects; * </brightness-curve> * </brightness-configuration> * </brightness-configurations> + * <brightness-nits-for-default-display>600</brightness-nits-for-default-display> * </display-manager-state> * * @@ -130,6 +131,9 @@ final class PersistentDataStore { private static final String TAG_RESOLUTION_HEIGHT = "resolution-height"; private static final String TAG_REFRESH_RATE = "refresh-rate"; + private static final String TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY = + "brightness-nits-for-default-display"; + // Remembered Wifi display devices. private ArrayList mRememberedWifiDisplays = new ArrayList(); @@ -137,6 +141,8 @@ final class PersistentDataStore { private final HashMap mDisplayStates = new HashMap(); + private float mBrightnessNitsForDefaultDisplay = -1; + // Display values which should be stable across the device's lifetime. private final StableDeviceValues mStableDeviceValues = new StableDeviceValues(); @@ -312,6 +318,19 @@ final class PersistentDataStore { return false; } + public float getBrightnessNitsForDefaultDisplay() { + return mBrightnessNitsForDefaultDisplay; + } + + public boolean setBrightnessNitsForDefaultDisplay(float nits) { + if (nits != mBrightnessNitsForDefaultDisplay) { + mBrightnessNitsForDefaultDisplay = nits; + setDirty(); + return true; + } + return false; + } + public boolean setUserPreferredRefreshRate(DisplayDevice displayDevice, float refreshRate) { final String displayDeviceUniqueId = displayDevice.getUniqueId(); if (!displayDevice.hasStableUniqueId() || displayDeviceUniqueId == null) { @@ -513,6 +532,10 @@ final class PersistentDataStore { if (parser.getName().equals(TAG_BRIGHTNESS_CONFIGURATIONS)) { mGlobalBrightnessConfigurations.loadFromXml(parser); } + if (parser.getName().equals(TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY)) { + String value = parser.nextText(); + mBrightnessNitsForDefaultDisplay = Float.parseFloat(value); + } } } @@ -592,6 +615,9 @@ final class PersistentDataStore { serializer.startTag(null, TAG_BRIGHTNESS_CONFIGURATIONS); mGlobalBrightnessConfigurations.saveToXml(serializer); serializer.endTag(null, TAG_BRIGHTNESS_CONFIGURATIONS); + serializer.startTag(null, TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY); + serializer.text(Float.toString(mBrightnessNitsForDefaultDisplay)); + serializer.endTag(null, TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY); serializer.endTag(null, TAG_DISPLAY_MANAGER_STATE); serializer.endDocument(); } @@ -615,6 +641,7 @@ final class PersistentDataStore { mStableDeviceValues.dump(pw, " "); pw.println(" GlobalBrightnessConfigurations:"); mGlobalBrightnessConfigurations.dump(pw, " "); + pw.println(" mBrightnessNitsForDefaultDisplay=" + mBrightnessNitsForDefaultDisplay); } private static final class DisplayState { diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java index 68758caa808ab..2916fefefe1b1 100644 --- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java +++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java @@ -16,14 +16,17 @@ package com.android.server.display.brightness; +import android.annotation.Nullable; import android.content.Context; import android.hardware.display.DisplayManagerInternal; import android.os.HandlerExecutor; import android.os.PowerManager; import android.util.IndentingPrintWriter; +import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.display.AutomaticBrightnessController; import com.android.server.display.BrightnessSetting; import com.android.server.display.DisplayBrightnessState; import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy; @@ -84,6 +87,15 @@ public final class DisplayBrightnessController { // callback is not executed in sync and is not blocking the thread from which it is called. private final HandlerExecutor mBrightnessChangeExecutor; + // True if we want to persist the brightness value in nits even if the underlying display + // device changes. + private final boolean mPersistBrightnessNitsForDefaultDisplay; + + // The controller for the automatic brightness level. + // TODO(b/265415257): Move to the automatic brightness strategy + @Nullable + private AutomaticBrightnessController mAutomaticBrightnessController; + /** * The constructor of DisplayBrightnessController. */ @@ -103,6 +115,8 @@ public final class DisplayBrightnessController { mDisplayBrightnessStrategySelector = injector.getDisplayBrightnessStrategySelector(context, displayId); mBrightnessChangeExecutor = brightnessChangeExecutor; + mPersistBrightnessNitsForDefaultDisplay = context.getResources().getBoolean( + com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay); } /** @@ -263,6 +277,12 @@ public final class DisplayBrightnessController { // Update the setting, which will eventually call back into DPC to have us actually // update the display with the new value. mBrightnessSetting.setBrightness(brightnessValue); + if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) { + float nits = convertToNits(brightnessValue); + if (nits >= 0) { + mBrightnessSetting.setBrightnessNitsForDefaultDisplay(nits); + } + } } /** @@ -280,6 +300,42 @@ public final class DisplayBrightnessController { setBrightness(brightnessValue); } + /** + * Set the {@link AutomaticBrightnessController} which is needed to perform nit-to-float-scale + * conversion. + * @param automaticBrightnessController The ABC + */ + public void setAutomaticBrightnessController( + AutomaticBrightnessController automaticBrightnessController) { + mAutomaticBrightnessController = automaticBrightnessController; + loadNitBasedBrightnessSetting(); + } + + /** + * Convert a brightness float scale value to a nit value. + * @param brightness The float scale value + * @return The nit value or -1f if no conversion is possible. + */ + public float convertToNits(float brightness) { + if (mAutomaticBrightnessController == null) { + return -1f; + } + return mAutomaticBrightnessController.convertToNits(brightness); + } + + /** + * Convert a brightness nit value to a float scale value. + * @param nits The nit value + * @return The float scale value or {@link PowerManager.BRIGHTNESS_INVALID_FLOAT} if no + * conversion is possible. + */ + public float convertToFloatScale(float nits) { + if (mAutomaticBrightnessController == null) { + return PowerManager.BRIGHTNESS_INVALID_FLOAT; + } + return mAutomaticBrightnessController.convertToFloatScale(nits); + } + /** * Stops the associated listeners when the display is stopped. Invoked when the {@link * #mDisplayId} is being removed. @@ -300,6 +356,8 @@ public final class DisplayBrightnessController { writer.println("DisplayBrightnessController:"); writer.println(" mDisplayId=: " + mDisplayId); writer.println(" mScreenBrightnessDefault=" + mScreenBrightnessDefault); + writer.println(" mPersistBrightnessNitsForDefaultDisplay=" + + mPersistBrightnessNitsForDefaultDisplay); synchronized (mLock) { writer.println(" mPendingScreenBrightness=" + mPendingScreenBrightness); writer.println(" mCurrentScreenBrightness=" + mCurrentScreenBrightness); @@ -353,4 +411,29 @@ public final class DisplayBrightnessController { private void notifyCurrentScreenBrightness() { mBrightnessChangeExecutor.execute(mOnBrightnessChangeRunnable); } + + /** + * Loads the brightness value. If this is the default display and the config says that we should + * persist the nit value, the nit value for the default display will be loaded. + */ + private void loadNitBasedBrightnessSetting() { + if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) { + float brightnessNitsForDefaultDisplay = + mBrightnessSetting.getBrightnessNitsForDefaultDisplay(); + if (brightnessNitsForDefaultDisplay >= 0) { + float brightnessForDefaultDisplay = convertToFloatScale( + brightnessNitsForDefaultDisplay); + if (BrightnessUtils.isValidBrightnessValue(brightnessForDefaultDisplay)) { + mBrightnessSetting.setBrightness(brightnessForDefaultDisplay); + synchronized (mLock) { + mCurrentScreenBrightness = brightnessForDefaultDisplay; + } + return; + } + } + } + synchronized (mLock) { + mCurrentScreenBrightness = getScreenBrightnessSetting(); + } + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java index 7942e246c2a73..19aae194e73a7 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java @@ -643,6 +643,34 @@ public final class DisplayPowerController2Test { verify(mHolder.screenOffBrightnessSensorController).stop(); } + @Test + public void testBrightnessNitsPersistWhenDisplayDeviceChanges() { + float brightness = 0.3f; + float nits = 500; + when(mResourcesMock.getBoolean( + com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay)) + .thenReturn(true); + mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID); + when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits); + + mHolder.dpc.setBrightness(brightness); + verify(mHolder.brightnessSetting).setBrightnessNitsForDefaultDisplay(nits); + + float newBrightness = 0.4f; + when(mHolder.brightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits); + when(mHolder.automaticBrightnessController.convertToFloatScale(nits)) + .thenReturn(newBrightness); + // New display device + setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class), + mock(DisplayDeviceConfig.class), /* isEnabled= */ true); + mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY); + DisplayPowerRequest dpr = new DisplayPowerRequest(); + mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + advanceTime(1); // Run updatePowerState + // One triggered by handleBrightnessModeChange, another triggered by onDisplayChanged + verify(mHolder.animator, times(2)).animateTo(eq(newBrightness), anyFloat(), anyFloat()); + } + private DisplayPowerControllerHolder createDisplayPowerController(int displayId, String uniqueId) { return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true); diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java index 16bf2a227c8a1..02b6ea0d1116d 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -488,17 +488,17 @@ public final class DisplayPowerControllerTest { // We should still set screen state for the default display DisplayPowerRequest dpr = new DisplayPowerRequest(); mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - advanceTime(1); + advanceTime(1); // Run updatePowerState verify(mHolder.displayPowerState, times(2)).setScreenState(anyInt()); mHolder = createDisplayPowerController(42, UNIQUE_ID); mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - advanceTime(1); + advanceTime(1); // Run updatePowerState verify(mHolder.displayPowerState, never()).setScreenState(anyInt()); mHolder.dpc.onBootCompleted(); - advanceTime(1); + advanceTime(1); // Run updatePowerState verify(mHolder.displayPowerState).setScreenState(anyInt()); } @@ -647,6 +647,34 @@ public final class DisplayPowerControllerTest { verify(mHolder.screenOffBrightnessSensorController).stop(); } + @Test + public void testBrightnessNitsPersistWhenDisplayDeviceChanges() { + float brightness = 0.3f; + float nits = 500; + when(mResourcesMock.getBoolean( + com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay)) + .thenReturn(true); + mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID); + when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits); + + mHolder.dpc.setBrightness(brightness); + verify(mHolder.brightnessSetting).setBrightnessNitsForDefaultDisplay(nits); + + float newBrightness = 0.4f; + when(mHolder.brightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits); + when(mHolder.automaticBrightnessController.convertToFloatScale(nits)) + .thenReturn(newBrightness); + // New display device + setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class), + mock(DisplayDeviceConfig.class), /* isEnabled= */ true); + mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY); + DisplayPowerRequest dpr = new DisplayPowerRequest(); + mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + advanceTime(1); // Run updatePowerState + // One triggered by handleBrightnessModeChange, another triggered by onDisplayChanged + verify(mHolder.animator, times(2)).animateTo(eq(newBrightness), anyFloat(), anyFloat()); + } + private DisplayPowerControllerHolder createDisplayPowerController(int displayId, String uniqueId) { return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true); diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java index 35a677e0f816d..817b245a78bf1 100644 --- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java @@ -377,6 +377,33 @@ public class PersistentDataStoreTest { assertTrue(Float.isNaN(mDataStore.getBrightness(testDisplayDevice))); } + @Test + public void testStoreAndRestoreBrightnessNitsForDefaultDisplay() { + float brightnessNitsForDefaultDisplay = 190; + mDataStore.loadIfNeeded(); + mDataStore.setBrightnessNitsForDefaultDisplay(brightnessNitsForDefaultDisplay); + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + mInjector.setWriteStream(baos); + mDataStore.saveIfNeeded(); + mTestLooper.dispatchAll(); + assertTrue(mInjector.wasWriteSuccessful()); + TestInjector newInjector = new TestInjector(); + PersistentDataStore newDataStore = new PersistentDataStore(newInjector); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + newInjector.setReadStream(bais); + newDataStore.loadIfNeeded(); + assertEquals(brightnessNitsForDefaultDisplay, + mDataStore.getBrightnessNitsForDefaultDisplay(), 0); + assertEquals(brightnessNitsForDefaultDisplay, + newDataStore.getBrightnessNitsForDefaultDisplay(), 0); + } + + @Test + public void testInitialBrightnessNitsForDefaultDisplay() { + mDataStore.loadIfNeeded(); + assertEquals(-1, mDataStore.getBrightnessNitsForDefaultDisplay(), 0); + } public class TestInjector extends PersistentDataStore.Injector { private InputStream mReadStream; diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java index ae05e32ae9167..cfb432ab37849 100644 --- a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.res.Resources; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; import android.os.HandlerExecutor; import android.os.PowerManager; @@ -34,6 +35,7 @@ import android.view.Display; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.server.display.AutomaticBrightnessController; import com.android.server.display.BrightnessSetting; import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy; import com.android.server.display.brightness.strategy.TemporaryBrightnessStrategy; @@ -47,7 +49,7 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidJUnit4.class) public final class DisplayBrightnessControllerTest { - private static final int DISPLAY_ID = 1; + private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY; private static final float DEFAULT_BRIGHTNESS = 0.15f; @Mock @@ -55,6 +57,8 @@ public final class DisplayBrightnessControllerTest { @Mock private Context mContext; @Mock + private Resources mResources; + @Mock private BrightnessSetting mBrightnessSetting; @Mock private Runnable mOnBrightnessChangeRunnable; @@ -67,6 +71,7 @@ public final class DisplayBrightnessControllerTest { @Before public void before() { MockitoAnnotations.initMocks(this); + when(mContext.getResources()).thenReturn(mResources); DisplayBrightnessController.Injector injector = new DisplayBrightnessController.Injector() { @Override DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector( @@ -75,6 +80,10 @@ public final class DisplayBrightnessControllerTest { } }; when(mBrightnessSetting.getBrightness()).thenReturn(Float.NaN); + when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(-1f); + when(mResources.getBoolean( + com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay)) + .thenReturn(true); mDisplayBrightnessController = new DisplayBrightnessController(mContext, injector, DISPLAY_ID, DEFAULT_BRIGHTNESS, mBrightnessSetting, mOnBrightnessChangeRunnable, mBrightnessChangeExecutor); @@ -82,8 +91,8 @@ public final class DisplayBrightnessControllerTest { @Test public void testIfFirstScreenBrightnessIsDefault() { - assertEquals(mDisplayBrightnessController.getCurrentBrightness(), DEFAULT_BRIGHTNESS, - 0.0f); + assertEquals(DEFAULT_BRIGHTNESS, mDisplayBrightnessController.getCurrentBrightness(), + /* delta= */ 0.0f); } @Test @@ -123,7 +132,7 @@ public final class DisplayBrightnessControllerTest { float currentScreenBrightness = 0.4f; mDisplayBrightnessController.setAndNotifyCurrentScreenBrightness(currentScreenBrightness); assertEquals(mDisplayBrightnessController.getCurrentBrightness(), - currentScreenBrightness, 0.0f); + currentScreenBrightness, /* delta= */ 0.0f); verify(mBrightnessChangeExecutor).execute(mOnBrightnessChangeRunnable); // No change to the current screen brightness is same as the existing one @@ -136,7 +145,7 @@ public final class DisplayBrightnessControllerTest { float pendingScreenBrightness = 0.4f; mDisplayBrightnessController.setPendingScreenBrightness(pendingScreenBrightness); assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(), - pendingScreenBrightness, 0.0f); + pendingScreenBrightness, /* delta= */ 0.0f); } @Test @@ -158,7 +167,7 @@ public final class DisplayBrightnessControllerTest { verify(temporaryBrightnessStrategy).setTemporaryScreenBrightness( PowerManager.BRIGHTNESS_INVALID_FLOAT); assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(), - PowerManager.BRIGHTNESS_INVALID_FLOAT, 0.0f); + PowerManager.BRIGHTNESS_INVALID_FLOAT, /* delta= */ 0.0f); // user set brightness is set as expected currentBrightness = 0.4f; @@ -169,15 +178,15 @@ public final class DisplayBrightnessControllerTest { mDisplayBrightnessController.setTemporaryBrightness(temporaryScreenBrightness); assertTrue(mDisplayBrightnessController.updateUserSetScreenBrightness()); assertEquals(mDisplayBrightnessController.getCurrentBrightness(), - pendingScreenBrightness, 0.0f); + pendingScreenBrightness, /* delta= */ 0.0f); assertEquals(mDisplayBrightnessController.getLastUserSetScreenBrightness(), - pendingScreenBrightness, 0.0f); + pendingScreenBrightness, /* delta= */ 0.0f); verify(mBrightnessChangeExecutor, times(2)) .execute(mOnBrightnessChangeRunnable); verify(temporaryBrightnessStrategy, times(2)) .setTemporaryScreenBrightness(PowerManager.BRIGHTNESS_INVALID_FLOAT); assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(), - PowerManager.BRIGHTNESS_INVALID_FLOAT, 0.0f); + PowerManager.BRIGHTNESS_INVALID_FLOAT, /* delta= */ 0.0f); } @Test @@ -198,20 +207,20 @@ public final class DisplayBrightnessControllerTest { float brightnessSetting = 0.2f; when(mBrightnessSetting.getBrightness()).thenReturn(brightnessSetting); assertEquals(mDisplayBrightnessController.getScreenBrightnessSetting(), brightnessSetting, - 0.0f); + /* delta= */ 0.0f); // getScreenBrightnessSetting value is clamped if BrightnessSetting returns value beyond max brightnessSetting = 1.1f; when(mBrightnessSetting.getBrightness()).thenReturn(brightnessSetting); assertEquals(mDisplayBrightnessController.getScreenBrightnessSetting(), 1.0f, - 0.0f); + /* delta= */ 0.0f); // getScreenBrightnessSetting returns default value is BrightnessSetting returns invalid // value. brightnessSetting = Float.NaN; when(mBrightnessSetting.getBrightness()).thenReturn(brightnessSetting); assertEquals(mDisplayBrightnessController.getScreenBrightnessSetting(), DEFAULT_BRIGHTNESS, - 0.0f); + /* delta= */ 0.0f); } @Test @@ -247,6 +256,64 @@ public final class DisplayBrightnessControllerTest { verifyNoMoreInteractions(mBrightnessChangeExecutor, mBrightnessSetting); } + @Test + public void testBrightnessNitsForDefaultDisplay() { + float brightness = 0.3f; + float nits = 500; + AutomaticBrightnessController automaticBrightnessController = + mock(AutomaticBrightnessController.class); + when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness); + when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits); + + mDisplayBrightnessController.setAutomaticBrightnessController( + automaticBrightnessController); + assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(), + /* delta= */ 0); + + float newBrightness = 0.5f; + float newNits = 700; + when(automaticBrightnessController.convertToNits(newBrightness)).thenReturn(newNits); + mDisplayBrightnessController.setBrightness(newBrightness); + verify(mBrightnessSetting).setBrightnessNitsForDefaultDisplay(newNits); + } + + @Test + public void testConvertToNits() { + float brightness = 0.5f; + float nits = 300; + + // ABC is null + assertEquals(-1f, mDisplayBrightnessController.convertToNits(brightness), + /* delta= */ 0); + + AutomaticBrightnessController automaticBrightnessController = + mock(AutomaticBrightnessController.class); + when(automaticBrightnessController.convertToNits(brightness)).thenReturn(nits); + mDisplayBrightnessController.setAutomaticBrightnessController( + automaticBrightnessController); + + assertEquals(nits, mDisplayBrightnessController.convertToNits(brightness), /* delta= */ 0); + } + + @Test + public void testConvertToFloatScale() { + float brightness = 0.5f; + float nits = 300; + + // ABC is null + assertEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT, + mDisplayBrightnessController.convertToFloatScale(nits), /* delta= */ 0); + + AutomaticBrightnessController automaticBrightnessController = + mock(AutomaticBrightnessController.class); + when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness); + mDisplayBrightnessController.setAutomaticBrightnessController( + automaticBrightnessController); + + assertEquals(brightness, mDisplayBrightnessController.convertToFloatScale(nits), + /* delta= */ 0); + } + @Test public void stop() { BrightnessSetting.BrightnessSettingListener brightnessSettingListener = mock(