diff options
| author | 2023-03-27 16:58:52 +0000 | |
|---|---|---|
| committer | 2023-03-27 16:58:52 +0000 | |
| commit | 1b35bc3e463af7ededf7d0cd7250cad4e76f3226 (patch) | |
| tree | 378ceaa615b680a72330d98a429d14ab8b4cbf3f | |
| parent | 9faf11fc4eb30bd11011f02be4c9fc1a6bfefa3d (diff) | |
| parent | d6080c5a8743150e177d9ca2c85569ace34488d3 (diff) | |
Merge "Introducing AutomaticBrightnessStrategy" into udc-dev
5 files changed, 804 insertions, 162 deletions
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 656882f3f615..f5859eed34f1 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -1634,7 +1634,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mAppliedAutoBrightness = false; brightnessAdjustmentFlags = 0; } - // Use default brightness when dozing unless overridden. if ((Float.isNaN(brightnessState)) && Display.isDozeState(state)) { diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java index 3e01222bbae6..5306ac0e57b9 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController2.java +++ b/services/core/java/com/android/server/display/DisplayPowerController2.java @@ -64,6 +64,7 @@ import com.android.internal.display.BrightnessSynchronizer; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.FrameworkStatsLog; +import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.RingBuffer; import com.android.server.LocalServices; import com.android.server.am.BatteryStatsService; @@ -72,6 +73,7 @@ import com.android.server.display.brightness.BrightnessEvent; import com.android.server.display.brightness.BrightnessReason; import com.android.server.display.brightness.BrightnessUtils; import com.android.server.display.brightness.DisplayBrightnessController; +import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy; import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal; import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener; import com.android.server.display.layout.Layout; @@ -209,9 +211,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal // True if auto-brightness should be used. private boolean mUseSoftwareAutoBrightnessConfig; - // True if the brightness config has changed and the short-term model needs to be reset - private boolean mShouldResetShortTermModel; - // Whether or not the color fade on screen on / off is enabled. private final boolean mColorFadeEnabled; @@ -296,12 +295,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal // If the last recorded screen state was dozing or not. private boolean mDozing; - // Remembers whether certain kinds of brightness adjustments - // were recently applied so that we can decide how to transition. - private boolean mAppliedAutoBrightness; private boolean mAppliedDimming; private boolean mAppliedLowPower; - private boolean mAppliedTemporaryAutoBrightnessAdjustment; private boolean mAppliedThrottling; // Reason for which the brightness was last changed. See {@link BrightnessReason} for more @@ -359,6 +354,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal // Tracks and manages the display state of the associated display. private final DisplayStateController mDisplayStateController; + + // Responsible for evaluating and tracking the automatic brightness relevant states. + // Todo: This is a temporary workaround. Ideally DPC2 should never talk to the strategies + private final AutomaticBrightnessStrategy mAutomaticBrightnessStrategy; + // A record of state for skipping brightness ramps. private int mSkipRampState = RAMP_STATE_SKIP_NONE; @@ -385,24 +385,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal @Nullable private BrightnessMappingStrategy mIdleModeBrightnessMapper; - // The current brightness configuration. - @Nullable - private BrightnessConfiguration mBrightnessConfiguration; - - // The last auto brightness adjustment that was set by the user and not temporary. Set to - // Float.NaN when an auto-brightness adjustment hasn't been recorded yet. - private float mAutoBrightnessAdjustment; - - // The pending auto brightness adjustment that will take effect on the next power state update. - private float mPendingAutoBrightnessAdjustment; - - // The temporary auto brightness adjustment. Typically set when a user is interacting with the - // adjustment slider but hasn't settled on a choice yet. Set to - // PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set. - private float mTemporaryAutoBrightnessAdjustment; - - private boolean mUseAutoBrightness; - private boolean mIsRbcActive; // Animators. @@ -454,6 +436,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal () -> updatePowerState(), mDisplayId, mSensorManager); mHighBrightnessModeMetadata = hbmMetadata; mDisplayStateController = new DisplayStateController(mDisplayPowerProximityStateController); + mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy(context, mDisplayId); mTag = "DisplayPowerController2[" + mDisplayId + "]"; mBrightnessThrottlingDataId = logicalDisplay.getBrightnessThrottlingDataIdLocked(); @@ -555,9 +538,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mBrightnessBucketsInDozeConfig = resources.getBoolean( R.bool.config_displayBrightnessBucketsInDoze); - mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting(); - mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT; - mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT; mBootCompleted = bootCompleted; } @@ -1038,6 +1018,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mDisplayBrightnessController.setAutomaticBrightnessController( mAutomaticBrightnessController); + mAutomaticBrightnessStrategy + .setAutomaticBrightnessController(mAutomaticBrightnessController); mBrightnessEventRingBuffer = new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX); @@ -1168,7 +1150,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal final boolean mustNotify; final int previousPolicy; boolean mustInitialize = false; - int brightnessAdjustmentFlags = 0; mBrightnessReasonTemp.set(null); mTempBrightnessEvent.reset(); SparseArray<DisplayPowerControllerInterface> displayBrightnessFollowers; @@ -1208,7 +1189,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal .updateDisplayState(mPowerRequest, mIsEnabled, mIsInTransition); if (mScreenOffBrightnessSensorController != null) { - mScreenOffBrightnessSensorController.setLightSensorEnabled(mUseAutoBrightness + mScreenOffBrightnessSensorController + .setLightSensorEnabled(mAutomaticBrightnessStrategy.shouldUseAutoBrightness() && mIsEnabled && (state == Display.STATE_OFF || (state == Display.STATE_DOZE && !mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig())) && mLeadDisplayId == Layout.NO_LEAD_DISPLAY); @@ -1222,7 +1204,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal // Animate the screen state change unless already animating. // The transition may be deferred, so after this point we will use the // actual state instead of the desired one. - final int oldState = mPowerState.getScreenState(); animateScreenStateChange(state, mDisplayStateController.shouldPerformScreenOffTransition()); state = mPowerState.getScreenState(); @@ -1231,112 +1212,59 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal float brightnessState = displayBrightnessState.getBrightness(); float rawBrightnessState = displayBrightnessState.getBrightness(); mBrightnessReasonTemp.set(displayBrightnessState.getBrightnessReason()); - - final boolean autoBrightnessEnabledInDoze = - mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig() - && Display.isDozeState(state); - final boolean autoBrightnessEnabled = mUseAutoBrightness - && (state == Display.STATE_ON || autoBrightnessEnabledInDoze) - && (Float.isNaN(brightnessState) - || mBrightnessReasonTemp.getReason() == BrightnessReason.REASON_TEMPORARY - || mBrightnessReasonTemp.getReason() == BrightnessReason.REASON_BOOST) - && mAutomaticBrightnessController != null - && mBrightnessReasonTemp.getReason() != BrightnessReason.REASON_FOLLOWER; - final boolean autoBrightnessDisabledDueToDisplayOff = mUseAutoBrightness - && !(state == Display.STATE_ON || autoBrightnessEnabledInDoze); - final int autoBrightnessState = autoBrightnessEnabled - ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED - : autoBrightnessDisabledDueToDisplayOff - ? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE - : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED; - final boolean userSetBrightnessChanged = mDisplayBrightnessController .updateUserSetScreenBrightness(); - - final boolean autoBrightnessAdjustmentChanged = updateAutoBrightnessAdjustment(); - - // Use the autobrightness adjustment override if set. - final float autoBrightnessAdjustment; - if (!Float.isNaN(mTemporaryAutoBrightnessAdjustment)) { - autoBrightnessAdjustment = mTemporaryAutoBrightnessAdjustment; - brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO_TEMP; - mAppliedTemporaryAutoBrightnessAdjustment = true; - } else { - autoBrightnessAdjustment = mAutoBrightnessAdjustment; - brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO; - mAppliedTemporaryAutoBrightnessAdjustment = false; - } + // Take note if the short term model was already active before applying the current + // request changes. + final boolean wasShortTermModelActive = + mAutomaticBrightnessStrategy.isShortTermModelActive(); + mAutomaticBrightnessStrategy.setAutoBrightnessState(state, + mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig(), + brightnessState, mBrightnessReasonTemp.getReason(), mPowerRequest.policy, + mDisplayBrightnessController.getLastUserSetScreenBrightness(), + userSetBrightnessChanged); // If the brightness is already set then it's been overridden by something other than the // user, or is a temporary adjustment. boolean userInitiatedChange = (Float.isNaN(brightnessState)) - && (autoBrightnessAdjustmentChanged || userSetBrightnessChanged); - boolean wasShortTermModelActive = false; - // Configure auto-brightness. - if (mAutomaticBrightnessController != null) { - wasShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints(); - mAutomaticBrightnessController.configure(autoBrightnessState, - mBrightnessConfiguration, - mDisplayBrightnessController.getLastUserSetScreenBrightness(), - userSetBrightnessChanged, autoBrightnessAdjustment, - autoBrightnessAdjustmentChanged, mPowerRequest.policy, - mShouldResetShortTermModel); - mShouldResetShortTermModel = false; - } - mHbmController.setAutoBrightnessEnabled(mUseAutoBrightness + && (mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged() + || userSetBrightnessChanged); + + mHbmController.setAutoBrightnessEnabled(mAutomaticBrightnessStrategy + .shouldUseAutoBrightness() ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED); - if (mBrightnessTracker != null) { - mBrightnessTracker.setShouldCollectColorSample(mBrightnessConfiguration != null - && mBrightnessConfiguration.shouldCollectColorSamples()); - } - boolean updateScreenBrightnessSetting = false; float currentBrightnessSetting = mDisplayBrightnessController.getCurrentBrightness(); // Apply auto-brightness. boolean slowChange = false; + int brightnessAdjustmentFlags = 0; if (Float.isNaN(brightnessState)) { - float newAutoBrightnessAdjustment = autoBrightnessAdjustment; - if (autoBrightnessEnabled) { - rawBrightnessState = mAutomaticBrightnessController - .getRawAutomaticScreenBrightness(); - brightnessState = mAutomaticBrightnessController.getAutomaticScreenBrightness( - mTempBrightnessEvent); - newAutoBrightnessAdjustment = - mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment(); - } - if (BrightnessUtils.isValidBrightnessValue(brightnessState) - || brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT) { - // Use current auto-brightness value and slowly adjust to changes. - brightnessState = clampScreenBrightness(brightnessState); - if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) { - slowChange = true; // slowly adapt to auto-brightness - } - updateScreenBrightnessSetting = currentBrightnessSetting != brightnessState; - mAppliedAutoBrightness = true; - mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC); - if (mScreenOffBrightnessSensorController != null) { - mScreenOffBrightnessSensorController.setLightSensorEnabled(false); + if (mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()) { + brightnessState = mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(); + if (BrightnessUtils.isValidBrightnessValue(brightnessState) + || brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT) { + rawBrightnessState = mAutomaticBrightnessController + .getRawAutomaticScreenBrightness(); + brightnessState = clampScreenBrightness(brightnessState); + // slowly adapt to auto-brightness + slowChange = mAutomaticBrightnessStrategy.hasAppliedAutoBrightness() + && !mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged(); + brightnessAdjustmentFlags = + mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags(); + updateScreenBrightnessSetting = currentBrightnessSetting != brightnessState; + mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC); + if (mScreenOffBrightnessSensorController != null) { + mScreenOffBrightnessSensorController.setLightSensorEnabled(false); + } } - } else { - mAppliedAutoBrightness = false; - } - if (autoBrightnessAdjustment != newAutoBrightnessAdjustment) { - // If the autobrightness controller has decided to change the adjustment value - // used, make sure that's reflected in settings. - putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment); - } else { - // Adjustment values resulted in no change - brightnessAdjustmentFlags = 0; } } else { // Any non-auto-brightness values such as override or temporary should still be subject // to clamping so that they don't go beyond the current max as specified by HBM // Controller. brightnessState = clampScreenBrightness(brightnessState); - mAppliedAutoBrightness = false; - brightnessAdjustmentFlags = 0; } // Use default brightness when dozing unless overridden. @@ -1349,7 +1277,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal // The ALS is not available yet - use the screen off sensor to determine the initial // brightness - if (Float.isNaN(brightnessState) && autoBrightnessEnabled + if (Float.isNaN(brightnessState) && mAutomaticBrightnessStrategy.isAutoBrightnessEnabled() && mScreenOffBrightnessSensorController != null) { rawBrightnessState = mScreenOffBrightnessSensorController.getAutomaticScreenBrightness(); @@ -1466,7 +1394,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal boolean brightnessAdjusted = false; final boolean brightnessIsTemporary = (mBrightnessReason.getReason() == BrightnessReason.REASON_TEMPORARY) - || mAppliedTemporaryAutoBrightnessAdjustment; + || mAutomaticBrightnessStrategy + .isTemporaryAutoBrightnessAdjustmentApplied(); if (!mPendingScreenOff) { if (mSkipScreenOnBrightnessRamp) { if (state == Display.STATE_ON) { @@ -1524,6 +1453,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal final float currentBrightness = mPowerState.getScreenBrightness(); final float currentSdrBrightness = mPowerState.getSdrScreenBrightness(); + if (BrightnessUtils.isValidBrightnessValue(animateValue) && (animateValue != currentBrightness || sdrAnimateValue != currentSdrBrightness)) { @@ -1605,7 +1535,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mTempBrightnessEvent.setWasShortTermModelActive(wasShortTermModelActive); mTempBrightnessEvent.setDisplayBrightnessStrategyName(displayBrightnessState .getDisplayBrightnessStrategyName()); - mTempBrightnessEvent.setAutomaticBrightnessEnabled(mUseAutoBrightness); + mTempBrightnessEvent.setAutomaticBrightnessEnabled(mAutomaticBrightnessStrategy + .shouldUseAutoBrightness()); // Temporary is what we use during slider interactions. We avoid logging those so that // we don't spam logcat when the slider is being used. boolean tempToTempTransition = @@ -2151,13 +2082,12 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mDisplayBrightnessController .setPendingScreenBrightness(mDisplayBrightnessController .getScreenBrightnessSetting()); - mPendingAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting(); + mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(userSwitch); if (userSwitch) { // Don't treat user switches as user initiated change. mDisplayBrightnessController .setAndNotifyCurrentScreenBrightness(mDisplayBrightnessController .getPendingScreenBrightness()); - updateAutoBrightnessAdjustment(); if (mAutomaticBrightnessController != null) { mAutomaticBrightnessController.resetShortTermModel(); } @@ -2171,8 +2101,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT); mHandler.postAtTime(() -> { - mUseAutoBrightness = screenBrightnessModeSetting - == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; + mAutomaticBrightnessStrategy.setUseAutoBrightness(screenBrightnessModeSetting + == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); updatePowerState(); }, mClock.uptimeMillis()); } @@ -2220,33 +2150,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal sendUpdatePowerState(); } - private void putAutoBrightnessAdjustmentSetting(float adjustment) { - if (mDisplayId == Display.DEFAULT_DISPLAY) { - mAutoBrightnessAdjustment = adjustment; - Settings.System.putFloatForUser(mContext.getContentResolver(), - Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adjustment, - UserHandle.USER_CURRENT); - } - } - - private boolean updateAutoBrightnessAdjustment() { - if (Float.isNaN(mPendingAutoBrightnessAdjustment)) { - return false; - } - if (mAutoBrightnessAdjustment == mPendingAutoBrightnessAdjustment) { - mPendingAutoBrightnessAdjustment = Float.NaN; - return false; - } - mAutoBrightnessAdjustment = mPendingAutoBrightnessAdjustment; - mPendingAutoBrightnessAdjustment = Float.NaN; - mTemporaryAutoBrightnessAdjustment = Float.NaN; - return true; - } - private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated, boolean wasShortTermModelActive) { final float brightnessInNits = mDisplayBrightnessController.convertToNits(brightness); - if (mUseAutoBrightness && brightnessInNits >= 0.0f + if (mAutomaticBrightnessStrategy.shouldUseAutoBrightness() && brightnessInNits >= 0.0f && mAutomaticBrightnessController != null && mBrightnessTracker != null) { // We only want to track changes on devices that can actually map the display backlight // values into a physical brightness unit since the value provided by the API is in @@ -2329,16 +2236,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal pw.println(); pw.println("Display Power Controller Thread State:"); pw.println(" mPowerRequest=" + mPowerRequest); - pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment); pw.println(" mBrightnessReason=" + mBrightnessReason); - pw.println(" mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment); - pw.println(" mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment); - pw.println(" mAppliedAutoBrightness=" + mAppliedAutoBrightness); pw.println(" mAppliedDimming=" + mAppliedDimming); pw.println(" mAppliedLowPower=" + mAppliedLowPower); pw.println(" mAppliedThrottling=" + mAppliedThrottling); - pw.println(" mAppliedTemporaryAutoBrightnessAdjustment=" - + mAppliedTemporaryAutoBrightnessAdjustment); pw.println(" mDozing=" + mDozing); pw.println(" mSkipRampState=" + skipRampStateToString(mSkipRampState)); pw.println(" mScreenOnBlockStartRealTime=" + mScreenOnBlockStartRealTime); @@ -2349,6 +2250,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal pw.println(" mReportedToPolicy=" + reportedToPolicyToString(mReportedScreenStateToPolicy)); pw.println(" mIsRbcActive=" + mIsRbcActive); + IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); + mAutomaticBrightnessStrategy.dump(ipw); if (mScreenBrightnessRampAnimator != null) { pw.println(" mScreenBrightnessRampAnimator.isAnimating()=" @@ -2580,8 +2483,15 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal } break; case MSG_CONFIGURE_BRIGHTNESS: - mBrightnessConfiguration = (BrightnessConfiguration) msg.obj; - mShouldResetShortTermModel = msg.arg1 == 1; + BrightnessConfiguration brightnessConfiguration = + (BrightnessConfiguration) msg.obj; + mAutomaticBrightnessStrategy.setBrightnessConfiguration(brightnessConfiguration, + msg.arg1 == 1); + if (mBrightnessTracker != null) { + mBrightnessTracker + .setShouldCollectColorSample(brightnessConfiguration != null + && brightnessConfiguration.shouldCollectColorSamples()); + } updatePowerState(); break; @@ -2593,7 +2503,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal break; case MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT: - mTemporaryAutoBrightnessAdjustment = Float.intBitsToFloat(msg.arg1); + mAutomaticBrightnessStrategy + .setTemporaryAutoBrightnessAdjustment(Float.intBitsToFloat(msg.arg1)); updatePowerState(); break; diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java new file mode 100644 index 000000000000..f6cf866dfa2f --- /dev/null +++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.display.brightness.strategy; + +import android.annotation.Nullable; +import android.content.Context; +import android.hardware.display.BrightnessConfiguration; +import android.os.PowerManager; +import android.os.UserHandle; +import android.provider.Settings; +import android.view.Display; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.display.AutomaticBrightnessController; +import com.android.server.display.brightness.BrightnessReason; +import com.android.server.display.brightness.BrightnessUtils; + +import java.io.PrintWriter; + +/** + * Helps manage the brightness based on the ambient environment (Ambient Light/lux sensor) using + * mappings from lux to nits to brightness, configured in the + * {@link com.android.server.display.DisplayDeviceConfig} class. This class inherently assumes + * that it is being executed from the power thread, and hence doesn't synchronize + * any of its resources + */ +public class AutomaticBrightnessStrategy { + private final Context mContext; + // The DisplayId of the associated logical display + private final int mDisplayId; + // The last auto brightness adjustment that was set by the user and is not temporary. Set to + // Float.NaN when an auto-brightness adjustment hasn't been recorded yet. + private float mAutoBrightnessAdjustment; + // The pending auto brightness adjustment that will take effect on the next power state update. + private float mPendingAutoBrightnessAdjustment; + // The temporary auto brightness adjustment. This was historically used when a user interacts + // with the adjustment slider but hasn't settled on a choice yet. + // Set to PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set. + private float mTemporaryAutoBrightnessAdjustment; + // Indicates if the temporary auto brightness adjustment has been applied while updating the + // associated display brightness + private boolean mAppliedTemporaryAutoBrightnessAdjustment; + // Indicates if the auto brightness adjustment has happened. + private boolean mAutoBrightnessAdjustmentChanged; + // Indicates the reasons for the auto-brightness adjustment + private int mAutoBrightnessAdjustmentReasonsFlags = 0; + // Indicates if the short term model should be reset before fetching the new brightness + // Todo(273543270): Short term model is an internal information of + // AutomaticBrightnessController and shouldn't be exposed outside of that class + private boolean mShouldResetShortTermModel = false; + // Remembers whether the auto-brightness has been applied in the latest brightness update. + private boolean mAppliedAutoBrightness = false; + // The controller for the automatic brightness level. + @Nullable + private AutomaticBrightnessController mAutomaticBrightnessController; + // The system setting denoting if the auto-brightness for the current user is enabled or not + private boolean mUseAutoBrightness = false; + // Indicates if the auto-brightness is currently enabled or not. It's possible that even if + // the user has enabled the auto-brightness from the settings, it is disabled because the + // display is off + private boolean mIsAutoBrightnessEnabled = false; + // If the auto-brightness model for the last manual changes done by the user. + private boolean mIsShortTermModelActive = false; + + // The BrightnessConfiguration currently being used + // Todo(273543270): BrightnessConfiguration is an internal implementation detail of + // AutomaticBrightnessController, and AutomaticBrightnessStrategy shouldn't be aware of its + // existence. + @Nullable + private BrightnessConfiguration mBrightnessConfiguration; + + public AutomaticBrightnessStrategy(Context context, int displayId) { + mContext = context; + mDisplayId = displayId; + mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting(); + mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT; + mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT; + } + + /** + * Sets up the automatic brightness states of this class. Also configures + * AutomaticBrightnessController accounting for any manual changes made by the user. + */ + public void setAutoBrightnessState(int targetDisplayState, + boolean allowAutoBrightnessWhileDozingConfig, + float brightnessState, int brightnessReason, int policy, + float lastUserSetScreenBrightness, boolean userSetBrightnessChanged) { + final boolean autoBrightnessEnabledInDoze = + allowAutoBrightnessWhileDozingConfig + && Display.isDozeState(targetDisplayState); + mIsAutoBrightnessEnabled = shouldUseAutoBrightness() + && (targetDisplayState == Display.STATE_ON || autoBrightnessEnabledInDoze) + && (Float.isNaN(brightnessState) + || brightnessReason == BrightnessReason.REASON_TEMPORARY + || brightnessReason == BrightnessReason.REASON_BOOST) + && mAutomaticBrightnessController != null + && brightnessReason != BrightnessReason.REASON_FOLLOWER; + final boolean autoBrightnessDisabledDueToDisplayOff = shouldUseAutoBrightness() + && !(targetDisplayState == Display.STATE_ON || autoBrightnessEnabledInDoze); + final int autoBrightnessState = mIsAutoBrightnessEnabled + ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED + : autoBrightnessDisabledDueToDisplayOff + ? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE + : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED; + + accommodateUserBrightnessChanges(userSetBrightnessChanged, lastUserSetScreenBrightness, + policy, mBrightnessConfiguration, autoBrightnessState); + } + + public boolean isAutoBrightnessEnabled() { + return mIsAutoBrightnessEnabled; + } + + /** + * Updates the {@link BrightnessConfiguration} that is currently being used by the associated + * display. + */ + public void setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration, + boolean shouldResetShortTermModel) { + mBrightnessConfiguration = brightnessConfiguration; + setShouldResetShortTermModel(shouldResetShortTermModel); + } + + /** + * Promotes the pending auto-brightness adjustments which are yet to be applied to the current + * adjustments. Note that this is not applying the new adjustments to the AutoBrightness mapping + * strategies, but is only accommodating the changes in this class. + */ + public boolean processPendingAutoBrightnessAdjustments() { + mAutoBrightnessAdjustmentChanged = false; + if (Float.isNaN(mPendingAutoBrightnessAdjustment)) { + return false; + } + if (mAutoBrightnessAdjustment == mPendingAutoBrightnessAdjustment) { + mPendingAutoBrightnessAdjustment = Float.NaN; + return false; + } + mAutoBrightnessAdjustment = mPendingAutoBrightnessAdjustment; + mPendingAutoBrightnessAdjustment = Float.NaN; + mTemporaryAutoBrightnessAdjustment = Float.NaN; + mAutoBrightnessAdjustmentChanged = true; + return true; + } + + /** + * Updates the associated AutomaticBrightnessController + */ + public void setAutomaticBrightnessController( + AutomaticBrightnessController automaticBrightnessController) { + if (automaticBrightnessController == mAutomaticBrightnessController) { + return; + } + if (mAutomaticBrightnessController != null) { + mAutomaticBrightnessController.stop(); + } + mAutomaticBrightnessController = automaticBrightnessController; + } + + /** + * Returns if the auto-brightness of the associated display has been enabled or not + */ + public boolean shouldUseAutoBrightness() { + return mUseAutoBrightness; + } + + /** + * Sets the auto-brightness state of the associated display. Called when the user makes a change + * in the system setting to enable/disable the auto-brightness. + */ + public void setUseAutoBrightness(boolean useAutoBrightness) { + mUseAutoBrightness = useAutoBrightness; + } + + /** + * Returns if the user made brightness change events(Typically when they interact with the + * brightness slider) were accommodated in the auto-brightness mapping strategies. This doesn't + * account for the latest changes that have been made by the user. + */ + public boolean isShortTermModelActive() { + return mIsShortTermModelActive; + } + + /** + * Sets the pending auto-brightness adjustments in the system settings. Executed + * when there is a change in the brightness system setting, or when there is a user switch. + */ + public void updatePendingAutoBrightnessAdjustments(boolean userSwitch) { + final float adj = Settings.System.getFloatForUser(mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT); + mPendingAutoBrightnessAdjustment = Float.isNaN(adj) ? Float.NaN + : BrightnessUtils.clampAbsoluteBrightness(adj); + if (userSwitch) { + processPendingAutoBrightnessAdjustments(); + } + } + + /** + * Sets the temporary auto-brightness adjustments + */ + public void setTemporaryAutoBrightnessAdjustment(float temporaryAutoBrightnessAdjustment) { + mTemporaryAutoBrightnessAdjustment = temporaryAutoBrightnessAdjustment; + } + + /** + * Dumps the state of this class. + */ + public void dump(PrintWriter writer) { + writer.println("AutomaticBrightnessStrategy:"); + writer.println(" mDisplayId=" + mDisplayId); + writer.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment); + writer.println(" mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment); + writer.println( + " mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment); + writer.println(" mShouldResetShortTermModel=" + mShouldResetShortTermModel); + writer.println(" mAppliedAutoBrightness=" + mAppliedAutoBrightness); + writer.println(" mAutoBrightnessAdjustmentChanged=" + mAutoBrightnessAdjustmentChanged); + writer.println(" mAppliedTemporaryAutoBrightnessAdjustment=" + + mAppliedTemporaryAutoBrightnessAdjustment); + writer.println(" mUseAutoBrightness=" + mUseAutoBrightness); + writer.println(" mWasShortTermModelActive=" + mIsShortTermModelActive); + writer.println(" mAutoBrightnessAdjustmentReasonsFlags=" + + mAutoBrightnessAdjustmentReasonsFlags); + } + + /** + * Indicates if any auto-brightness adjustments have happened since the last auto-brightness was + * set. + */ + public boolean getAutoBrightnessAdjustmentChanged() { + return mAutoBrightnessAdjustmentChanged; + } + + /** + * Returns whether the latest temporary auto-brightness adjustments have been applied or not + */ + public boolean isTemporaryAutoBrightnessAdjustmentApplied() { + return mAppliedTemporaryAutoBrightnessAdjustment; + } + + /** + * Evaluates the target automatic brightness of the associated display. + */ + public float getAutomaticScreenBrightness() { + float brightness = (mAutomaticBrightnessController != null) + ? mAutomaticBrightnessController.getAutomaticScreenBrightness() + : PowerManager.BRIGHTNESS_INVALID_FLOAT; + adjustAutomaticBrightnessStateIfValid(brightness); + return brightness; + } + + /** + * Gets the auto-brightness adjustment flag change reason + */ + public int getAutoBrightnessAdjustmentReasonsFlags() { + return mAutoBrightnessAdjustmentReasonsFlags; + } + + /** + * Returns if the auto brightness has been applied + */ + public boolean hasAppliedAutoBrightness() { + return mAppliedAutoBrightness; + } + + /** + * Used to adjust the state of this class when the automatic brightness value for the + * associated display is valid + */ + @VisibleForTesting + void adjustAutomaticBrightnessStateIfValid(float brightnessState) { + mAutoBrightnessAdjustmentReasonsFlags = isTemporaryAutoBrightnessAdjustmentApplied() + ? BrightnessReason.ADJUSTMENT_AUTO_TEMP + : BrightnessReason.ADJUSTMENT_AUTO; + mAppliedAutoBrightness = BrightnessUtils.isValidBrightnessValue(brightnessState) + || brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT; + float newAutoBrightnessAdjustment = + (mAutomaticBrightnessController != null) + ? mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment() + : 0.0f; + if (!Float.isNaN(newAutoBrightnessAdjustment) + && mAutoBrightnessAdjustment != newAutoBrightnessAdjustment) { + // If the auto-brightness controller has decided to change the adjustment value + // used, make sure that's reflected in settings. + putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment); + } else { + mAutoBrightnessAdjustmentReasonsFlags = 0; + } + } + + /** + * Sets up the system to reset the short term model. Note that this will not reset the model + * right away, but ensures that the reset happens whenever the next brightness change happens + */ + @VisibleForTesting + void setShouldResetShortTermModel(boolean shouldResetShortTermModel) { + mShouldResetShortTermModel = shouldResetShortTermModel; + } + + @VisibleForTesting + boolean shouldResetShortTermModel() { + return mShouldResetShortTermModel; + } + + @VisibleForTesting + float getAutoBrightnessAdjustment() { + return mAutoBrightnessAdjustment; + } + + @VisibleForTesting + float getPendingAutoBrightnessAdjustment() { + return mPendingAutoBrightnessAdjustment; + } + + @VisibleForTesting + float getTemporaryAutoBrightnessAdjustment() { + return mTemporaryAutoBrightnessAdjustment; + } + + @VisibleForTesting + void putAutoBrightnessAdjustmentSetting(float adjustment) { + if (mDisplayId == Display.DEFAULT_DISPLAY) { + mAutoBrightnessAdjustment = adjustment; + Settings.System.putFloatForUser(mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adjustment, + UserHandle.USER_CURRENT); + } + } + + /** + * Sets if the auto-brightness is applied on the latest brightness change. + */ + @VisibleForTesting + void setAutoBrightnessApplied(boolean autoBrightnessApplied) { + mAppliedAutoBrightness = autoBrightnessApplied; + } + + /** + * Accommodates the latest manual changes made by the user. Also updates {@link + * AutomaticBrightnessController} about the changes and configures it accordingly. + */ + @VisibleForTesting + void accommodateUserBrightnessChanges(boolean userSetBrightnessChanged, + float lastUserSetScreenBrightness, int policy, + BrightnessConfiguration brightnessConfiguration, int autoBrightnessState) { + // Update the pending auto-brightness adjustments if any. This typically checks and adjusts + // the state of the class if the user moves the brightness slider and has settled to a + // different value + processPendingAutoBrightnessAdjustments(); + // Update the temporary auto-brightness adjustments if any. This typically checks and + // adjusts the state of this class if the user is in the process of moving the brightness + // slider, but hasn't settled to any value yet + float autoBrightnessAdjustment = updateTemporaryAutoBrightnessAdjustments(); + mIsShortTermModelActive = false; + // Configure auto-brightness. + if (mAutomaticBrightnessController != null) { + // Accommodate user changes if any in the auto-brightness model + mAutomaticBrightnessController.configure(autoBrightnessState, + brightnessConfiguration, + lastUserSetScreenBrightness, + userSetBrightnessChanged, autoBrightnessAdjustment, + mAutoBrightnessAdjustmentChanged, policy, mShouldResetShortTermModel); + mShouldResetShortTermModel = false; + // We take note if the user brightness point is still being used in the current + // auto-brightness model. + mIsShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints(); + } + } + + /** + * Evaluates if there are any temporary auto-brightness adjustments which is not applied yet. + * Temporary brightness adjustments happen when the user moves the brightness slider in the + * auto-brightness mode, but hasn't settled to a value yet + */ + private float updateTemporaryAutoBrightnessAdjustments() { + mAppliedTemporaryAutoBrightnessAdjustment = + !Float.isNaN(mTemporaryAutoBrightnessAdjustment); + // We do not update the mAutoBrightnessAdjustment with mTemporaryAutoBrightnessAdjustment + // since we have not settled to a value yet + return mAppliedTemporaryAutoBrightnessAdjustment + ? mTemporaryAutoBrightnessAdjustment : mAutoBrightnessAdjustment; + } + + /** + * Returns the auto-brightness adjustment that is set in the system setting. + */ + private float getAutoBrightnessAdjustmentSetting() { + final float adj = Settings.System.getFloatForUser(mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT); + return Float.isNaN(adj) ? 0.0f : BrightnessUtils.clampAbsoluteBrightness(adj); + } +} 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 0ab984bd9381..fc503b7a749b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java @@ -66,7 +66,6 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.server.LocalServices; import com.android.server.am.BatteryStatsService; import com.android.server.display.RampAnimator.DualRampAnimator; -import com.android.server.display.brightness.BrightnessEvent; import com.android.server.display.color.ColorDisplayService; import com.android.server.display.layout.Layout; import com.android.server.display.whitebalance.DisplayWhiteBalanceController; @@ -565,8 +564,8 @@ public final class DisplayPowerController2Test { .thenReturn(brightness); dpr.policy = DisplayPowerRequest.POLICY_BRIGHT; when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON); - when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness( - any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT); + when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness()) + .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT); mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState @@ -603,8 +602,8 @@ public final class DisplayPowerController2Test { .thenReturn(brightness); dpr.policy = DisplayPowerRequest.POLICY_BRIGHT; when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON); - when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness( - any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT); + when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness()) + .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT); mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java new file mode 100644 index 000000000000..eb208d2e6c7f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.display.brightness.strategy; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.ContextWrapper; +import android.hardware.display.BrightnessConfiguration; +import android.hardware.display.DisplayManagerInternal; +import android.os.PowerManager; +import android.os.UserHandle; +import android.provider.Settings; +import android.test.mock.MockContentResolver; +import android.view.Display; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.internal.util.test.FakeSettingsProvider; +import com.android.internal.util.test.FakeSettingsProviderRule; +import com.android.server.display.AutomaticBrightnessController; +import com.android.server.display.brightness.BrightnessReason; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AutomaticBrightnessStrategyTest { + private static final int DISPLAY_ID = 0; + @Rule + public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); + + @Mock + private AutomaticBrightnessController mAutomaticBrightnessController; + + private BrightnessConfiguration mBrightnessConfiguration; + private float mDefaultScreenAutoBrightnessAdjustment; + private Context mContext; + private AutomaticBrightnessStrategy mAutomaticBrightnessStrategy; + + @Before + public void before() { + MockitoAnnotations.initMocks(this); + mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext())); + final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext); + when(mContext.getContentResolver()).thenReturn(resolver); + mDefaultScreenAutoBrightnessAdjustment = Settings.System.getFloat( + mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, Float.NaN); + Settings.System.putFloat(mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.5f); + mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy(mContext, DISPLAY_ID); + + mBrightnessConfiguration = new BrightnessConfiguration.Builder( + new float[]{0f, 1f}, new float[]{0, PowerManager.BRIGHTNESS_ON}).build(); + when(mAutomaticBrightnessController.hasUserDataPoints()).thenReturn(true); + mAutomaticBrightnessStrategy.setAutomaticBrightnessController( + mAutomaticBrightnessController); + mAutomaticBrightnessStrategy.setBrightnessConfiguration(mBrightnessConfiguration, + true); + } + + @After + public void after() { + Settings.System.putFloat(mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, mDefaultScreenAutoBrightnessAdjustment); + } + + @Test + public void setAutoBrightnessWhenDisabled() { + mAutomaticBrightnessStrategy.setUseAutoBrightness(false); + int targetDisplayState = Display.STATE_ON; + boolean allowAutoBrightnessWhileDozing = false; + float brightnessState = Float.NaN; + int brightnessReason = BrightnessReason.REASON_OVERRIDE; + int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT; + float lastUserSetBrightness = 0.2f; + boolean userSetBrightnessChanged = true; + mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(true); + mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, + allowAutoBrightnessWhileDozing, brightnessState, brightnessReason, policy, + lastUserSetBrightness, userSetBrightnessChanged); + verify(mAutomaticBrightnessController) + .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, + mBrightnessConfiguration, + lastUserSetBrightness, + userSetBrightnessChanged, 0.5f, + false, policy, true); + } + + @Test + public void setAutoBrightnessWhenEnabledAndDisplayIsDozing() { + mAutomaticBrightnessStrategy.setUseAutoBrightness(true); + int targetDisplayState = Display.STATE_DOZE; + float brightnessState = Float.NaN; + boolean allowAutoBrightnessWhileDozing = true; + int brightnessReason = BrightnessReason.REASON_DOZE; + int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; + float lastUserSetBrightness = 0.2f; + boolean userSetBrightnessChanged = true; + Settings.System.putFloat(mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.4f); + mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(false); + mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, + allowAutoBrightnessWhileDozing, brightnessState, brightnessReason, policy, + lastUserSetBrightness, userSetBrightnessChanged); + verify(mAutomaticBrightnessController) + .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, + mBrightnessConfiguration, + lastUserSetBrightness, + userSetBrightnessChanged, 0.4f, + true, policy, true); + } + + @Test + public void setAutoBrightnessWhenEnabledAndDisplayIsOn() { + mAutomaticBrightnessStrategy.setUseAutoBrightness(true); + int targetDisplayState = Display.STATE_ON; + float brightnessState = Float.NaN; + boolean allowAutoBrightnessWhileDozing = false; + int brightnessReason = BrightnessReason.REASON_OVERRIDE; + float lastUserSetBrightness = 0.2f; + boolean userSetBrightnessChanged = true; + int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT; + float pendingBrightnessAdjustment = 0.1f; + Settings.System.putFloat(mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingBrightnessAdjustment); + mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(false); + mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, + allowAutoBrightnessWhileDozing, brightnessState, brightnessReason, policy, + lastUserSetBrightness, userSetBrightnessChanged); + verify(mAutomaticBrightnessController) + .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, + mBrightnessConfiguration, + lastUserSetBrightness, + userSetBrightnessChanged, pendingBrightnessAdjustment, + true, policy, true); + } + + @Test + public void accommodateUserBrightnessChangesWorksAsExpected() { + // Verify the state if automaticBrightnessController is configured. + assertFalse(mAutomaticBrightnessStrategy.isShortTermModelActive()); + boolean userSetBrightnessChanged = true; + float lastUserSetScreenBrightness = 0.2f; + int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT; + BrightnessConfiguration brightnessConfiguration = new BrightnessConfiguration.Builder( + new float[]{0f, 1f}, new float[]{0, PowerManager.BRIGHTNESS_ON}).build(); + int autoBrightnessState = AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED; + float temporaryAutoBrightnessAdjustments = 0.4f; + mAutomaticBrightnessStrategy.setShouldResetShortTermModel(true); + setTemporaryAutoBrightnessAdjustment(temporaryAutoBrightnessAdjustments); + mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(userSetBrightnessChanged, + lastUserSetScreenBrightness, policy, brightnessConfiguration, + autoBrightnessState); + verify(mAutomaticBrightnessController).configure(autoBrightnessState, + brightnessConfiguration, + lastUserSetScreenBrightness, + userSetBrightnessChanged, temporaryAutoBrightnessAdjustments, + /* userChangedAutoBrightnessAdjustment= */ false, policy, + /* shouldResetShortTermModel= */ true); + assertTrue(mAutomaticBrightnessStrategy.isTemporaryAutoBrightnessAdjustmentApplied()); + assertFalse(mAutomaticBrightnessStrategy.shouldResetShortTermModel()); + assertTrue(mAutomaticBrightnessStrategy.isShortTermModelActive()); + // Verify the state when automaticBrightnessController is not configured + setTemporaryAutoBrightnessAdjustment(Float.NaN); + mAutomaticBrightnessStrategy.setAutomaticBrightnessController(null); + mAutomaticBrightnessStrategy.setShouldResetShortTermModel(true); + mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(userSetBrightnessChanged, + lastUserSetScreenBrightness, policy, brightnessConfiguration, + autoBrightnessState); + assertFalse(mAutomaticBrightnessStrategy.isTemporaryAutoBrightnessAdjustmentApplied()); + assertTrue(mAutomaticBrightnessStrategy.shouldResetShortTermModel()); + assertFalse(mAutomaticBrightnessStrategy.isShortTermModelActive()); + } + + @Test + public void adjustAutomaticBrightnessStateIfValid() throws Settings.SettingNotFoundException { + float brightnessState = 0.3f; + float autoBrightnessAdjustment = 0.2f; + when(mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment()).thenReturn( + autoBrightnessAdjustment); + mAutomaticBrightnessStrategy.adjustAutomaticBrightnessStateIfValid(brightnessState); + assertTrue(mAutomaticBrightnessStrategy.hasAppliedAutoBrightness()); + assertEquals(autoBrightnessAdjustment, + mAutomaticBrightnessStrategy.getAutoBrightnessAdjustment(), 0.0f); + assertEquals(autoBrightnessAdjustment, Settings.System.getFloatForUser( + mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, + UserHandle.USER_CURRENT), 0.0f); + assertEquals(BrightnessReason.ADJUSTMENT_AUTO, + mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags()); + float invalidBrightness = -0.5f; + mAutomaticBrightnessStrategy + .adjustAutomaticBrightnessStateIfValid(invalidBrightness); + assertFalse(mAutomaticBrightnessStrategy.hasAppliedAutoBrightness()); + assertEquals(autoBrightnessAdjustment, + mAutomaticBrightnessStrategy.getAutoBrightnessAdjustment(), 0.0f); + assertEquals(0, + mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags()); + } + + @Test + public void updatePendingAutoBrightnessAdjustments() { + // Verify the state when the pendingAutoBrightnessAdjustments are not present + setPendingAutoBrightnessAdjustment(Float.NaN); + assertFalse(mAutomaticBrightnessStrategy.processPendingAutoBrightnessAdjustments()); + assertFalse(mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged()); + // Verify the state when the pendingAutoBrightnessAdjustments are present, but + // pendingAutoBrightnessAdjustments and autoBrightnessAdjustments are the same + float autoBrightnessAdjustment = 0.3f; + setPendingAutoBrightnessAdjustment(autoBrightnessAdjustment); + setAutoBrightnessAdjustment(autoBrightnessAdjustment); + assertFalse(mAutomaticBrightnessStrategy.processPendingAutoBrightnessAdjustments()); + assertFalse(mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged()); + assertEquals(Float.NaN, mAutomaticBrightnessStrategy.getPendingAutoBrightnessAdjustment(), + 0.0f); + // Verify the state when the pendingAutoBrightnessAdjustments are present, and + // pendingAutoBrightnessAdjustments and autoBrightnessAdjustments are not the same + float pendingAutoBrightnessAdjustment = 0.2f; + setPendingAutoBrightnessAdjustment(pendingAutoBrightnessAdjustment); + setTemporaryAutoBrightnessAdjustment(0.1f); + assertTrue(mAutomaticBrightnessStrategy.processPendingAutoBrightnessAdjustments()); + assertTrue(mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged()); + assertEquals(pendingAutoBrightnessAdjustment, + mAutomaticBrightnessStrategy.getAutoBrightnessAdjustment(), 0.0f); + assertEquals(Float.NaN, mAutomaticBrightnessStrategy.getPendingAutoBrightnessAdjustment(), + 0.0f); + assertEquals(Float.NaN, mAutomaticBrightnessStrategy.getTemporaryAutoBrightnessAdjustment(), + 0.0f); + } + + @Test + public void setAutomaticBrightnessWorksAsExpected() { + float automaticScreenBrightness = 0.3f; + AutomaticBrightnessController automaticBrightnessController = mock( + AutomaticBrightnessController.class); + when(automaticBrightnessController.getAutomaticScreenBrightness()).thenReturn( + automaticScreenBrightness); + mAutomaticBrightnessStrategy.setAutomaticBrightnessController( + automaticBrightnessController); + assertEquals(automaticScreenBrightness, + mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(), 0.0f); + } + + @Test + public void shouldUseAutoBrightness() { + mAutomaticBrightnessStrategy.setUseAutoBrightness(true); + assertTrue(mAutomaticBrightnessStrategy.shouldUseAutoBrightness()); + } + + @Test + public void setPendingAutoBrightnessAdjustments() throws Settings.SettingNotFoundException { + float pendingAutoBrightnessAdjustments = 0.3f; + setPendingAutoBrightnessAdjustment(pendingAutoBrightnessAdjustments); + assertEquals(pendingAutoBrightnessAdjustments, + mAutomaticBrightnessStrategy.getPendingAutoBrightnessAdjustment(), 0.0f); + assertEquals(pendingAutoBrightnessAdjustments, Settings.System.getFloatForUser( + mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, + UserHandle.USER_CURRENT), 0.0f); + } + + @Test + public void setTemporaryAutoBrightnessAdjustment() { + float temporaryAutoBrightnessAdjustment = 0.3f; + mAutomaticBrightnessStrategy.setTemporaryAutoBrightnessAdjustment( + temporaryAutoBrightnessAdjustment); + assertEquals(temporaryAutoBrightnessAdjustment, + mAutomaticBrightnessStrategy.getTemporaryAutoBrightnessAdjustment(), 0.0f); + } + + @Test + public void setAutoBrightnessApplied() { + mAutomaticBrightnessStrategy.setAutoBrightnessApplied(true); + assertTrue(mAutomaticBrightnessStrategy.hasAppliedAutoBrightness()); + } + + @Test + public void testVerifyNoAutoBrightnessAdjustmentsArePopulatedForNonDefaultDisplay() { + int newDisplayId = 1; + mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy(mContext, newDisplayId); + mAutomaticBrightnessStrategy.putAutoBrightnessAdjustmentSetting(0.3f); + assertEquals(0.5f, mAutomaticBrightnessStrategy.getAutoBrightnessAdjustment(), + 0.0f); + } + + private void setPendingAutoBrightnessAdjustment(float pendingAutoBrightnessAdjustment) { + Settings.System.putFloat(mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingAutoBrightnessAdjustment); + mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(false); + } + + private void setTemporaryAutoBrightnessAdjustment(float temporaryAutoBrightnessAdjustment) { + mAutomaticBrightnessStrategy.setTemporaryAutoBrightnessAdjustment( + temporaryAutoBrightnessAdjustment); + } + + private void setAutoBrightnessAdjustment(float autoBrightnessAdjustment) { + mAutomaticBrightnessStrategy.putAutoBrightnessAdjustmentSetting(autoBrightnessAdjustment); + } +} |