From 04c683b50e6a21fd9e3ecdc9f5313c0727a35964 Mon Sep 17 00:00:00 2001 From: Fiona Campbell Date: Wed, 10 Nov 2021 16:48:04 +0000 Subject: [PATCH] Switch brightnessmapper within ABC Switch which brightness mapping strategy is used in automaticbrightnesscontroller based on calls from displaypowercontroller through ABC. Don't notify of brightness changes in idle mode. Bug: 205686215 Test: adb shell dumpsys display | grep -A10 Idle Test: atest BrightnessMappingStrategyTest AutomaticBrightnessControllerTest adb shell dumpsys DockObserver set state [0|3] Change-Id: I8babe42957bfa4939cc78a9763c7fca3c244b73b --- .../AutomaticBrightnessController.java | 121 ++++++++++++++---- .../display/BrightnessMappingStrategy.java | 22 +++- .../display/DisplayPowerController.java | 72 +++++++---- .../AutomaticBrightnessControllerTest.java | 45 ++++++- 4 files changed, 206 insertions(+), 54 deletions(-) diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index e9af60116ad2b..c04032fede2fd 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -87,7 +87,10 @@ class AutomaticBrightnessController { private final Sensor mLightSensor; // The mapper to translate ambient lux to screen brightness in the range [0, 1.0]. - private final BrightnessMappingStrategy mBrightnessMapper; + @Nullable + private BrightnessMappingStrategy mCurrentBrightnessMapper; + private final BrightnessMappingStrategy mInteractiveModeBrightnessMapper; + private final BrightnessMappingStrategy mIdleModeBrightnessMapper; // The minimum and maximum screen brightnesses. private final float mScreenBrightnessRangeMinimum; @@ -215,36 +218,41 @@ class AutomaticBrightnessController { private final Injector mInjector; AutomaticBrightnessController(Callbacks callbacks, Looper looper, - SensorManager sensorManager, Sensor lightSensor, BrightnessMappingStrategy mapper, + SensorManager sensorManager, Sensor lightSensor, + BrightnessMappingStrategy interactiveModeBrightnessMapper, int lightSensorWarmUpTime, float brightnessMin, float brightnessMax, float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig, long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds, HysteresisLevels screenBrightnessThresholds, Context context, - HighBrightnessModeController hbmController) { - this(new Injector(), callbacks, looper, sensorManager, lightSensor, mapper, + HighBrightnessModeController hbmController, + BrightnessMappingStrategy idleModeBrightnessMapper) { + this(new Injector(), callbacks, looper, sensorManager, lightSensor, + interactiveModeBrightnessMapper, lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor, lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig, darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds, screenBrightnessThresholds, context, - hbmController + hbmController, idleModeBrightnessMapper ); } @VisibleForTesting AutomaticBrightnessController(Injector injector, Callbacks callbacks, Looper looper, - SensorManager sensorManager, Sensor lightSensor, BrightnessMappingStrategy mapper, + SensorManager sensorManager, Sensor lightSensor, + BrightnessMappingStrategy interactiveModeBrightnessMapper, int lightSensorWarmUpTime, float brightnessMin, float brightnessMax, float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig, long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds, HysteresisLevels screenBrightnessThresholds, Context context, - HighBrightnessModeController hbmController) { + HighBrightnessModeController hbmController, + BrightnessMappingStrategy idleModeBrightnessMapper) { mInjector = injector; mContext = context; mCallbacks = callbacks; mSensorManager = sensorManager; - mBrightnessMapper = mapper; + mCurrentBrightnessMapper = interactiveModeBrightnessMapper; mScreenBrightnessRangeMinimum = brightnessMin; mScreenBrightnessRangeMaximum = brightnessMax; mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime; @@ -277,6 +285,10 @@ class AutomaticBrightnessController { mForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED; mPendingForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED; mHbmController = hbmController; + mInteractiveModeBrightnessMapper = interactiveModeBrightnessMapper; + mIdleModeBrightnessMapper = idleModeBrightnessMapper; + // Initialize to active (normal) screen brightness mode + switchToInteractiveScreenBrightnessMode(); } /** @@ -291,7 +303,12 @@ class AutomaticBrightnessController { if (mLoggingEnabled == loggingEnabled) { return false; } - mBrightnessMapper.setLoggingEnabled(loggingEnabled); + if (mInteractiveModeBrightnessMapper != null) { + mInteractiveModeBrightnessMapper.setLoggingEnabled(loggingEnabled); + } + if (mIdleModeBrightnessMapper != null) { + mIdleModeBrightnessMapper.setLoggingEnabled(loggingEnabled); + } mLoggingEnabled = loggingEnabled; return true; } @@ -311,7 +328,7 @@ class AutomaticBrightnessController { } public float getAutomaticScreenBrightnessAdjustment() { - return mBrightnessMapper.getAutoBrightnessAdjustment(); + return mCurrentBrightnessMapper.getAutoBrightnessAdjustment(); } public void configure(boolean enable, @Nullable BrightnessConfiguration configuration, @@ -350,15 +367,20 @@ class AutomaticBrightnessController { } public boolean hasUserDataPoints() { - return mBrightnessMapper.hasUserDataPoints(); + return mCurrentBrightnessMapper.hasUserDataPoints(); } + // Used internally to establish whether we have deviated from the default config. public boolean isDefaultConfig() { - return mBrightnessMapper.isDefaultConfig(); + if (isInIdleMode()) { + return false; + } + return mInteractiveModeBrightnessMapper.isDefaultConfig(); } + // Called from APIs to get the configuration. public BrightnessConfiguration getDefaultConfig() { - return mBrightnessMapper.getDefaultConfig(); + return mInteractiveModeBrightnessMapper.getDefaultConfig(); } /** @@ -379,7 +401,7 @@ class AutomaticBrightnessController { } if (!isInteractivePolicy(policy) && isInteractivePolicy(oldPolicy)) { mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE_SHORT_TERM_MODEL, - mBrightnessMapper.getShortTermModelTimeout()); + mCurrentBrightnessMapper.getShortTermModelTimeout()); } else if (isInteractivePolicy(policy) && !isInteractivePolicy(oldPolicy)) { mHandler.removeMessages(MSG_INVALIDATE_SHORT_TERM_MODEL); } @@ -398,7 +420,7 @@ class AutomaticBrightnessController { // and we can't use this data to add a new control point to the short-term model. return false; } - mBrightnessMapper.addUserDataPoint(mAmbientLux, brightness); + mCurrentBrightnessMapper.addUserDataPoint(mAmbientLux, brightness); mShortTermModelValid = true; mShortTermModelAnchor = mAmbientLux; if (mLoggingEnabled) { @@ -408,7 +430,7 @@ class AutomaticBrightnessController { } public void resetShortTermModel() { - mBrightnessMapper.clearUserDataPoints(); + mCurrentBrightnessMapper.clearUserDataPoints(); mShortTermModelValid = true; mShortTermModelAnchor = -1; } @@ -421,13 +443,19 @@ class AutomaticBrightnessController { } public boolean setBrightnessConfiguration(BrightnessConfiguration configuration) { - if (mBrightnessMapper.setBrightnessConfiguration(configuration)) { - resetShortTermModel(); + if (mInteractiveModeBrightnessMapper.setBrightnessConfiguration(configuration)) { + if (!isInIdleMode()) { + resetShortTermModel(); + } return true; } return false; } + public boolean isInIdleMode() { + return mCurrentBrightnessMapper.isForIdleMode(); + } + public void dump(PrintWriter pw) { pw.println(); pw.println("Automatic Brightness Controller Configuration:"); @@ -461,7 +489,12 @@ class AutomaticBrightnessController { pw.println(" mAmbientLightRingBuffer=" + mAmbientLightRingBuffer); pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness); pw.println(" mDisplayPolicy=" + DisplayPowerRequest.policyToString(mDisplayPolicy)); - pw.println(" mShortTermModelTimeout=" + mBrightnessMapper.getShortTermModelTimeout()); + pw.println(" mShortTermModelTimeout(active)=" + + mInteractiveModeBrightnessMapper.getShortTermModelTimeout()); + if (mIdleModeBrightnessMapper != null) { + pw.println(" mShortTermModelTimeout(idle)=" + + mIdleModeBrightnessMapper.getShortTermModelTimeout()); + } pw.println(" mShortTermModelAnchor=" + mShortTermModelAnchor); pw.println(" mShortTermModelValid=" + mShortTermModelValid); pw.println(" mBrightnessAdjustmentSamplePending=" + mBrightnessAdjustmentSamplePending); @@ -472,9 +505,15 @@ class AutomaticBrightnessController { pw.println(" mPendingForegroundAppPackageName=" + mPendingForegroundAppPackageName); pw.println(" mForegroundAppCategory=" + mForegroundAppCategory); pw.println(" mPendingForegroundAppCategory=" + mPendingForegroundAppCategory); + pw.println(" Idle mode active=" + mCurrentBrightnessMapper.isForIdleMode()); pw.println(); - mBrightnessMapper.dump(pw); + pw.println(" mActiveMapper="); + mInteractiveModeBrightnessMapper.dump(pw); + if (mIdleModeBrightnessMapper != null) { + pw.println(" mIdleMapper="); + mIdleModeBrightnessMapper.dump(pw); + } pw.println(); mAmbientBrightnessThresholds.dump(pw); @@ -544,7 +583,7 @@ class AutomaticBrightnessController { } private boolean setAutoBrightnessAdjustment(float adjustment) { - return mBrightnessMapper.setAutoBrightnessAdjustment(adjustment); + return mCurrentBrightnessMapper.setAutoBrightnessAdjustment(adjustment); } private void setAmbientLux(float lux) { @@ -562,7 +601,8 @@ class AutomaticBrightnessController { // If the short term model was invalidated and the change is drastic enough, reset it. if (!mShortTermModelValid && mShortTermModelAnchor != -1) { - if (mBrightnessMapper.shouldResetShortTermModel(mAmbientLux, mShortTermModelAnchor)) { + if (mCurrentBrightnessMapper.shouldResetShortTermModel( + mAmbientLux, mShortTermModelAnchor)) { resetShortTermModel(); } else { mShortTermModelValid = true; @@ -743,7 +783,7 @@ class AutomaticBrightnessController { return; } - float value = mBrightnessMapper.getBrightness(mAmbientLux, mForegroundAppPackageName, + float value = mCurrentBrightnessMapper.getBrightness(mAmbientLux, mForegroundAppPackageName, mForegroundAppCategory); float newScreenAutoBrightness = clampScreenBrightness(value); @@ -909,6 +949,41 @@ class AutomaticBrightnessController { updateAutoBrightness(true /* sendUpdate */, false /* isManuallySet */); } + void switchToIdleMode() { + if (mIdleModeBrightnessMapper == null) { + return; + } + if (mCurrentBrightnessMapper.isForIdleMode()) { + return; + } + Slog.i(TAG, "Switching to Idle Screen Brightness Mode"); + mCurrentBrightnessMapper = mIdleModeBrightnessMapper; + resetShortTermModel(); + update(); + } + + void switchToInteractiveScreenBrightnessMode() { + if (!mCurrentBrightnessMapper.isForIdleMode()) { + return; + } + Slog.i(TAG, "Switching to Interactive Screen Brightness Mode"); + mCurrentBrightnessMapper = mInteractiveModeBrightnessMapper; + resetShortTermModel(); + update(); + } + + public float convertToNits(float brightness) { + if (mCurrentBrightnessMapper != null) { + return mCurrentBrightnessMapper.convertToNits(brightness); + } else { + return -1.0f; + } + } + + public void recalculateSplines(boolean applyAdjustment, float[] adjustment) { + mCurrentBrightnessMapper.recalculateSplines(applyAdjustment, adjustment); + } + private final class AutomaticBrightnessHandler extends Handler { public AutomaticBrightnessHandler(Looper looper) { super(looper, null, true /*async*/); diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java index beb4d5b28d5c9..240168b1878ce 100644 --- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java +++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java @@ -135,7 +135,7 @@ public abstract class BrightnessMappingStrategy { builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO); builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO); return new PhysicalMappingStrategy(builder.build(), nitsRange, brightnessRange, - autoBrightnessAdjustmentMaxGamma); + autoBrightnessAdjustmentMaxGamma, isForIdleMode); } else if (isValidMapping(luxLevels, brightnessLevelsBacklight) && !isForIdleMode) { return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight, autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout); @@ -354,6 +354,12 @@ public abstract class BrightnessMappingStrategy { public abstract void dump(PrintWriter pw); + /** + * We can designate a mapping strategy to be used for idle screen brightness mode. + * @return whether this mapping strategy is to be used for idle screen brightness mode. + */ + public abstract boolean isForIdleMode(); + /** * Check if the short term model should be reset given the anchor lux the last * brightness change was made at and the current ambient lux. @@ -711,6 +717,11 @@ public abstract class BrightnessMappingStrategy { pw.println(" mUserBrightness=" + mUserBrightness); } + @Override + public boolean isForIdleMode() { + return false; + } + private void computeSpline() { Pair curve = getAdjustedCurve(mLux, mBrightness, mUserLux, mUserBrightness, mAutoBrightnessAdjustment, mMaxGamma); @@ -758,9 +769,10 @@ public abstract class BrightnessMappingStrategy { private float mAutoBrightnessAdjustment; private float mUserLux; private float mUserBrightness; + private final boolean mIsForIdleMode; public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits, - float[] brightness, float maxGamma) { + float[] brightness, float maxGamma, boolean isForIdleMode) { Preconditions.checkArgument(nits.length != 0 && brightness.length != 0, "Nits and brightness arrays must not be empty!"); @@ -772,6 +784,7 @@ public abstract class BrightnessMappingStrategy { Preconditions.checkArrayElementsInRange(brightness, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, "brightness"); + mIsForIdleMode = isForIdleMode; mMaxGamma = maxGamma; mAutoBrightnessAdjustment = 0; mUserLux = -1; @@ -933,6 +946,11 @@ public abstract class BrightnessMappingStrategy { pw.println(" mBrightnessRangeAdjustmentApplied=" + mBrightnessRangeAdjustmentApplied); } + @Override + public boolean isForIdleMode() { + return mIsForIdleMode; + } + private void computeNitsBrightnessSplines(float[] nits) { mNitsToBrightnessSpline = Spline.createSpline(nits, mBrightness); mBrightnessToNitsSpline = Spline.createSpline(mBrightness, nits); diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 7f78cac651dca..b46ee27d30cbe 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -386,12 +386,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private Sensor mLightSensor; - // The mapper between ambient lux, display backlight values, and display brightness. - // This mapper holds the current one that is being used. We will switch between the idle - // mapper and active mapper here. - @Nullable - private BrightnessMappingStrategy mCurrentBrightnessMapper; - + // The mappers between ambient lux, display backlight values, and display brightness. + // We will switch between the idle mapper and active mapper in AutomaticBrightnessController. // Mapper used for active (normal) screen brightness mode @Nullable private BrightnessMappingStrategy mInteractiveModeBrightnessMapper; @@ -399,6 +395,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Nullable private BrightnessMappingStrategy mIdleModeBrightnessMapper; + // If these are both true, and mIdleModeBrightnessMapper != null, + // then we are in idle screen brightness mode. + private boolean mIsDreaming; + private boolean mIsDocked; + // The current brightness configuration. @Nullable private BrightnessConfiguration mBrightnessConfiguration; @@ -610,8 +611,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } private void handleRbcChanged(boolean strengthChanged, boolean justActivated) { - if (mCurrentBrightnessMapper == null) { - Log.w(TAG, "No brightness mapping available to recalculate splines"); + if (mAutomaticBrightnessController == null) { + return; + } + if ((!mAutomaticBrightnessController.isInIdleMode() + && mInteractiveModeBrightnessMapper == null) + || (mAutomaticBrightnessController.isInIdleMode() + && mIdleModeBrightnessMapper == null)) { + Log.w(TAG, "No brightness mapping available to recalculate splines for this mode"); return; } @@ -619,7 +626,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call for (int i = 0; i < mNitsRange.length; i++) { adjustedNits[i] = mCdsi.getReduceBrightColorsAdjustedBrightnessNits(mNitsRange[i]); } - mCurrentBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), + mAutomaticBrightnessController.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), adjustedNits); mPendingRbcOnOrChanged = strengthChanged || justActivated; @@ -886,9 +893,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mIdleModeBrightnessMapper = BrightnessMappingStrategy.createForIdleMode(resources, mDisplayDeviceConfig); } - mCurrentBrightnessMapper = mInteractiveModeBrightnessMapper; - if (mCurrentBrightnessMapper != null) { + if (mInteractiveModeBrightnessMapper != null) { final float dozeScaleFactor = resources.getFraction( com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor, 1, 1); @@ -939,12 +945,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mAutomaticBrightnessController.stop(); } mAutomaticBrightnessController = new AutomaticBrightnessController(this, - handler.getLooper(), mSensorManager, mLightSensor, mCurrentBrightnessMapper, - lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN, - PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate, - initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce, - autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds, - screenBrightnessThresholds, mContext, mHbmController); + handler.getLooper(), mSensorManager, mLightSensor, + mInteractiveModeBrightnessMapper, lightSensorWarmUpTimeConfig, + PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, + lightSensorRate, initialLightSensorRate, brighteningLightDebounce, + darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp, + ambientBrightnessThresholds, screenBrightnessThresholds, mContext, + mHbmController, mIdleModeBrightnessMapper); } else { mUseSoftwareAutoBrightnessConfig = false; } @@ -974,6 +981,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } + public void setAutomaticScreenBrightnessMode(boolean isIdle) { + if (mAutomaticBrightnessController != null) { + if (isIdle) { + mAutomaticBrightnessController.switchToIdleMode(); + } else { + mAutomaticBrightnessController.switchToInteractiveScreenBrightnessMode(); + } + } + } + private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { @@ -1422,9 +1439,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } - if (!brightnessIsTemporary) { + // Report brightness to brightnesstracker: + // If brightness is not temporary (ie the slider has been released) + // AND if we are not in idle screen brightness mode. + if (!brightnessIsTemporary + && (mAutomaticBrightnessController != null + && !mAutomaticBrightnessController.isInIdleMode())) { if (userInitiatedChange && (mAutomaticBrightnessController == null - || !mAutomaticBrightnessController.hasValidAmbientLux())) { + || !mAutomaticBrightnessController.hasValidAmbientLux())) { // If we don't have a valid lux reading we can't report a valid // slider event so notify as if the system changed the brightness. userInitiatedChange = false; @@ -2162,11 +2184,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } private float convertToNits(float brightness) { - if (mCurrentBrightnessMapper != null) { - return mCurrentBrightnessMapper.convertToNits(brightness); - } else { - return -1.0f; + if (mAutomaticBrightnessController == null) { + return -1f; } + return mAutomaticBrightnessController.convertToNits(brightness); } private void updatePendingProximityRequestsLocked() { @@ -2315,11 +2336,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pw.println(" mReportedToPolicy=" + reportedToPolicyToString(mReportedScreenStateToPolicy)); - if (mIdleModeBrightnessMapper != null) { - pw.println(" mIdleModeBrightnessMapper= "); - mIdleModeBrightnessMapper.dump(pw); - } - if (mScreenBrightnessRampAnimator != null) { pw.println(" mScreenBrightnessRampAnimator.isAnimating()=" + mScreenBrightnessRampAnimator.isAnimating()); diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java index f664517c32636..abe7d89dfa412 100644 --- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java @@ -21,7 +21,9 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyFloat; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.content.Context; @@ -63,6 +65,7 @@ public class AutomaticBrightnessControllerTest { @Mock SensorManager mSensorManager; @Mock BrightnessMappingStrategy mBrightnessMappingStrategy; + @Mock BrightnessMappingStrategy mIdleBrightnessMappingStrategy; @Mock HysteresisLevels mAmbientBrightnessThresholds; @Mock HysteresisLevels mScreenBrightnessThresholds; @Mock Handler mNoOpHandler; @@ -100,7 +103,7 @@ public class AutomaticBrightnessControllerTest { INITIAL_LIGHT_SENSOR_RATE, BRIGHTENING_LIGHT_DEBOUNCE_CONFIG, DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG, mAmbientBrightnessThresholds, mScreenBrightnessThresholds, - mContext, mHbmController + mContext, mHbmController, mIdleBrightnessMappingStrategy ); when(mHbmController.getCurrentBrightnessMax()).thenReturn(BRIGHTNESS_MAX_FLOAT); @@ -231,4 +234,44 @@ public class AutomaticBrightnessControllerTest { // There should be a user data point added to the mapper. verify(mBrightnessMappingStrategy).addUserDataPoint(1000f, 0.5f); } + + @Test + public void testSwitchToIdleMappingStrategy() throws Exception { + Sensor lightSensor = TestUtils.createSensor(Sensor.TYPE_LIGHT, "Light Sensor"); + mController = setupController(lightSensor); + + ArgumentCaptor listenerCaptor = + ArgumentCaptor.forClass(SensorEventListener.class); + verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(lightSensor), + eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class)); + SensorEventListener listener = listenerCaptor.getValue(); + + // Sensor reads 1000 lux, + listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000)); + + // User sets brightness to 100 + mController.configure(true /* enable */, null /* configuration */, + 0.5f /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */, + false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT); + + // There should be a user data point added to the mapper. + verify(mBrightnessMappingStrategy, times(1)).addUserDataPoint(1000f, 0.5f); + verify(mBrightnessMappingStrategy, times(2)).setBrightnessConfiguration(any()); + verify(mBrightnessMappingStrategy, times(3)).getBrightness(anyFloat(), any(), anyInt()); + + // Now let's do the same for idle mode + mController.switchToIdleMode(); + // Called once for init, and once when switching + verify(mBrightnessMappingStrategy, times(2)).isForIdleMode(); + // Ensure, after switching, original BMS is not used anymore + verifyNoMoreInteractions(mBrightnessMappingStrategy); + + // User sets idle brightness to 0.5 + mController.configure(true /* enable */, null /* configuration */, + 0.5f /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */, + false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT); + + // Ensure we use the correct mapping strategy + verify(mIdleBrightnessMappingStrategy, times(1)).addUserDataPoint(1000f, 0.5f); + } }