summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Rupesh Bansal <brup@google.com> 2023-03-27 16:58:52 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-03-27 16:58:52 +0000
commit1b35bc3e463af7ededf7d0cd7250cad4e76f3226 (patch)
tree378ceaa615b680a72330d98a429d14ab8b4cbf3f
parent9faf11fc4eb30bd11011f02be4c9fc1a6bfefa3d (diff)
parentd6080c5a8743150e177d9ca2c85569ace34488d3 (diff)
Merge "Introducing AutomaticBrightnessStrategy" into udc-dev
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java1
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController2.java223
-rw-r--r--services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java404
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java329
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);
+ }
+}