diff options
15 files changed, 390 insertions, 243 deletions
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index ec67212b46b7..b2dcf9091198 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -739,6 +739,9 @@ public abstract class DisplayManagerInternal { * on is done. */ void onBlockingScreenOn(Runnable unblocker); + + /** Whether auto brightness update in doze is allowed */ + boolean allowAutoBrightnessInDoze(); } /** A session token that associates a internal display with a {@link DisplayOffloader}. */ @@ -749,6 +752,9 @@ public abstract class DisplayManagerInternal { /** Whether the session is active. */ boolean isActive(); + /** Whether auto brightness update in doze is allowed */ + boolean allowAutoBrightnessInDoze(); + /** * Update the brightness from the offload chip. * @param brightness The brightness value between {@link PowerManager.BRIGHTNESS_MIN} and diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 30d12e670a6c..1949e6f2981e 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -56,10 +56,12 @@ import com.android.server.EventLogTags; import com.android.server.display.brightness.BrightnessEvent; import com.android.server.display.brightness.clamper.BrightnessClamperController; import com.android.server.display.config.HysteresisLevels; +import com.android.server.display.feature.DisplayManagerFlags; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.concurrent.TimeUnit; /** * Manages the associated display brightness when in auto-brightness mode. This is also @@ -206,7 +208,7 @@ public class AutomaticBrightnessController { private float mScreenBrighteningThreshold; private float mScreenDarkeningThreshold; // The most recent light sample. - private float mLastObservedLux = INVALID_LUX; + private float mLastObservedLux; // The time of the most light recent sample. private long mLastObservedLuxTime; @@ -277,6 +279,8 @@ public class AutomaticBrightnessController { private Clock mClock; private final Injector mInjector; + private final DisplayManagerFlags mDisplayManagerFlags; + AutomaticBrightnessController(Callbacks callbacks, Looper looper, SensorManager sensorManager, Sensor lightSensor, SparseArray<BrightnessMappingStrategy> brightnessMappingStrategyMap, @@ -291,7 +295,8 @@ public class AutomaticBrightnessController { BrightnessRangeController brightnessModeController, BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userNits, - BrightnessClamperController brightnessClamperController) { + BrightnessClamperController brightnessClamperController, + DisplayManagerFlags displayManagerFlags) { this(new Injector(), callbacks, looper, sensorManager, lightSensor, brightnessMappingStrategyMap, lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor, lightSensorRate, initialLightSensorRate, @@ -301,7 +306,7 @@ public class AutomaticBrightnessController { screenBrightnessThresholds, ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, context, brightnessModeController, brightnessThrottler, ambientLightHorizonShort, ambientLightHorizonLong, userLux, - userNits, brightnessClamperController + userNits, brightnessClamperController, displayManagerFlags ); } @@ -320,9 +325,10 @@ public class AutomaticBrightnessController { BrightnessRangeController brightnessRangeController, BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userNits, - BrightnessClamperController brightnessClamperController) { + BrightnessClamperController brightnessClamperController, + DisplayManagerFlags displayManagerFlags) { mInjector = injector; - mClock = injector.createClock(); + mClock = injector.createClock(displayManagerFlags.offloadControlsDozeAutoBrightness()); mContext = context; mCallbacks = callbacks; mSensorManager = sensorManager; @@ -367,6 +373,7 @@ public class AutomaticBrightnessController { mBrightnessClamperController = brightnessClamperController; mBrightnessThrottler = brightnessThrottler; mBrightnessMappingStrategyMap = brightnessMappingStrategyMap; + mDisplayManagerFlags = displayManagerFlags; // Use the given short-term model if (userNits != BrightnessMappingStrategy.INVALID_NITS) { @@ -429,34 +436,6 @@ public class AutomaticBrightnessController { return mRawScreenAutoBrightness; } - /** - * Get the automatic screen brightness based on the last observed lux reading. Used e.g. when - * entering doze - we disable the light sensor, invalidate the lux, but we still need to set - * the initial brightness in doze mode. - */ - public float getAutomaticScreenBrightnessBasedOnLastUsedLux( - BrightnessEvent brightnessEvent) { - float lastUsedLux = mAmbientLux; - if (lastUsedLux == INVALID_LUX) { - return PowerManager.BRIGHTNESS_INVALID_FLOAT; - } - - float brightness = mCurrentBrightnessMapper.getBrightness(lastUsedLux, - mForegroundAppPackageName, mForegroundAppCategory); - if (shouldApplyDozeScaleFactor()) { - brightness *= mDozeScaleFactor; - } - - if (brightnessEvent != null) { - brightnessEvent.setLux(lastUsedLux); - brightnessEvent.setRecommendedBrightness(brightness); - brightnessEvent.setFlags(brightnessEvent.getFlags() - | (shouldApplyDozeScaleFactor() ? BrightnessEvent.FLAG_DOZE_SCALE : 0)); - brightnessEvent.setAutoBrightnessMode(getMode()); - } - return brightness; - } - public boolean hasValidAmbientLux() { return mAmbientLuxValid; } @@ -747,7 +726,6 @@ public class AutomaticBrightnessController { mRecentLightSamples++; mAmbientLightRingBuffer.prune(time - mAmbientLightHorizonLong); mAmbientLightRingBuffer.push(time, lux); - // Remember this sample value. mLastObservedLux = lux; mLastObservedLuxTime = time; @@ -891,7 +869,7 @@ public class AutomaticBrightnessController { } private void updateAmbientLux() { - long time = mClock.uptimeMillis(); + long time = mClock.getSensorEventScaleTime(); mAmbientLightRingBuffer.prune(time - mAmbientLightHorizonLong); updateAmbientLux(time); } @@ -968,7 +946,16 @@ public class AutomaticBrightnessController { Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for " + nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime)); } - mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime); + + // The nextTransitionTime is computed as elapsedTime(Which also accounts for the time when + // android was sleeping) as the main reference. However, handlers work on the uptime(Not + // accounting for the time when android was sleeping) + mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, + convertToUptime(nextTransitionTime)); + } + + private long convertToUptime(long time) { + return time - mClock.getSensorEventScaleTime() + mClock.uptimeMillis(); } private void updateAutoBrightness(boolean sendUpdate, boolean isManuallySet) { @@ -1185,15 +1172,13 @@ public class AutomaticBrightnessController { } mPausedShortTermModel.copyFrom(tempShortTermModel); } - - update(); } /** * Responsible for switching the AutomaticBrightnessMode of the associated display. Also takes * care of resetting the short term model wherever required */ - public void switchMode(@AutomaticBrightnessMode int mode) { + public void switchMode(@AutomaticBrightnessMode int mode, boolean sendUpdate) { if (!mBrightnessMappingStrategyMap.contains(mode)) { return; } @@ -1208,6 +1193,11 @@ public class AutomaticBrightnessController { resetShortTermModel(); mCurrentBrightnessMapper = mBrightnessMappingStrategyMap.get(mode); } + if (sendUpdate) { + update(); + } else { + updateAutoBrightness(/* sendUpdate= */ false, /* isManuallySet= */ false); + } } float getUserLux() { @@ -1391,7 +1381,9 @@ public class AutomaticBrightnessController { @Override public void onSensorChanged(SensorEvent event) { if (mLightSensorEnabled) { - final long time = mClock.uptimeMillis(); + // The time received from the sensor is in nano seconds, hence changing it to ms + final long time = (mDisplayManagerFlags.offloadControlsDozeAutoBrightness()) + ? TimeUnit.NANOSECONDS.toMillis(event.timestamp) : mClock.uptimeMillis(); final float lux = event.values[0]; handleLightSensorEvent(time, lux); } @@ -1424,6 +1416,12 @@ public class AutomaticBrightnessController { * Returns current time in milliseconds since boot, not counting time spent in deep sleep. */ long uptimeMillis(); + + /** + * Gets the time on either the elapsedTime or the uptime scale, depending on how we + * processing the events from the sensor + */ + long getSensorEventScaleTime(); } /** @@ -1571,7 +1569,8 @@ public class AutomaticBrightnessController { StringBuilder buf = new StringBuilder(); buf.append('['); for (int i = 0; i < mCount; i++) { - final long next = i + 1 < mCount ? getTime(i + 1) : mClock.uptimeMillis(); + final long next = i + 1 < mCount ? getTime(i + 1) + : mClock.getSensorEventScaleTime(); if (i != 0) { buf.append(", "); } @@ -1596,13 +1595,31 @@ public class AutomaticBrightnessController { } } + private static class RealClock implements Clock { + private final boolean mOffloadControlsDozeBrightness; + + RealClock(boolean offloadControlsDozeBrightness) { + mOffloadControlsDozeBrightness = offloadControlsDozeBrightness; + } + + @Override + public long uptimeMillis() { + return SystemClock.uptimeMillis(); + } + + public long getSensorEventScaleTime() { + return (mOffloadControlsDozeBrightness) + ? SystemClock.elapsedRealtime() : uptimeMillis(); + } + } + public static class Injector { public Handler getBackgroundThreadHandler() { return BackgroundThread.getHandler(); } - Clock createClock() { - return SystemClock::uptimeMillis; + Clock createClock(boolean offloadControlsDozeBrightness) { + return new RealClock(offloadControlsDozeBrightness); } } } diff --git a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java index 65c9f3556fad..f77a360addd0 100644 --- a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java +++ b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java @@ -52,6 +52,14 @@ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.Display } @Override + public boolean allowAutoBrightnessInDoze() { + if (mDisplayOffloader == null) { + return false; + } + return mDisplayOffloader.allowAutoBrightnessInDoze(); + } + + @Override public void updateBrightness(float brightness) { if (mIsActive) { mDisplayPowerController.setBrightnessFromOffload(brightness); diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 0fcdf198eece..7d482f74d5b3 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -1115,7 +1115,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call screenBrightnessThresholdsIdle, mContext, mBrightnessRangeController, mBrightnessThrottler, mDisplayDeviceConfig.getAmbientHorizonShort(), mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userNits, - mBrightnessClamperController); + mBrightnessClamperController, mFlags); mDisplayBrightnessController.setUpAutoBrightness( mAutomaticBrightnessController, mSensorManager, mDisplayDeviceConfig, mHandler, defaultModeBrightnessMapper, mIsEnabled, mLeadDisplayId); @@ -1185,7 +1185,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @AutomaticBrightnessController.AutomaticBrightnessMode int mode) { boolean isIdle = mode == AUTO_BRIGHTNESS_MODE_IDLE; if (mAutomaticBrightnessController != null) { - mAutomaticBrightnessController.switchMode(mode); + // Set sendUpdate to true to make sure that updatePowerState() gets called + mAutomaticBrightnessController.switchMode(mode, /* sendUpdate= */ true); setAnimatorRampSpeeds(isIdle); } Message msg = mHandler.obtainMessage(); @@ -1334,7 +1335,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mDisplayStateController.shouldPerformScreenOffTransition()); state = mPowerState.getScreenState(); - DisplayBrightnessState displayBrightnessState = mDisplayBrightnessController .updateBrightness(mPowerRequest, state); float brightnessState = displayBrightnessState.getBrightness(); @@ -1366,17 +1366,26 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // request changes. final boolean wasShortTermModelActive = mAutomaticBrightnessStrategy.isShortTermModelActive(); + boolean allowAutoBrightnessWhileDozing = + mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig(); + if (mFlags.offloadControlsDozeAutoBrightness() && mFlags.isDisplayOffloadEnabled() + && mDisplayOffloadSession != null) { + allowAutoBrightnessWhileDozing &= mDisplayOffloadSession.allowAutoBrightnessInDoze(); + } if (!mFlags.isRefactorDisplayPowerControllerEnabled()) { // Switch to doze auto-brightness mode if needed if (mFlags.areAutoBrightnessModesEnabled() && mAutomaticBrightnessController != null && !mAutomaticBrightnessController.isInIdleMode()) { + // Set sendUpdate to false, we're already in updatePowerState() so there's no need + // to trigger it again mAutomaticBrightnessController.switchMode(Display.isDozeState(state) - ? AUTO_BRIGHTNESS_MODE_DOZE : AUTO_BRIGHTNESS_MODE_DEFAULT); + ? AUTO_BRIGHTNESS_MODE_DOZE : AUTO_BRIGHTNESS_MODE_DEFAULT, + /* sendUpdate= */ false); } mAutomaticBrightnessStrategy.setAutoBrightnessState(state, - mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig(), - mBrightnessReasonTemp.getReason(), mPowerRequest.policy, + allowAutoBrightnessWhileDozing, mBrightnessReasonTemp.getReason(), + mPowerRequest.policy, mDisplayBrightnessController.getLastUserSetScreenBrightness(), userSetBrightnessChanged); } @@ -1443,47 +1452,27 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } if (Display.isDozeState(state)) { - // If there's an offload session, we need to set the initial doze brightness before - // the offload session starts controlling the brightness. - // During the transition DOZE_SUSPEND -> DOZE -> DOZE_SUSPEND, this brightness strategy - // will be selected again, meaning that no new brightness will be sent to the hardware - // and the display will stay at the brightness level set by the offload session. + // TODO(b/329676661): Introduce a config property to choose between this brightness + // strategy and DOZE_DEFAULT + // On some devices, when auto-brightness is disabled and the device is dozing, we use + // the current brightness setting scaled by the doze scale factor if ((Float.isNaN(brightnessState) || displayBrightnessState.getDisplayBrightnessStrategyName() .equals(DisplayBrightnessStrategyConstants.FALLBACK_BRIGHTNESS_STRATEGY_NAME)) && mFlags.isDisplayOffloadEnabled() - && mDisplayOffloadSession != null) { - if (mAutomaticBrightnessController != null - && mAutomaticBrightnessStrategy.shouldUseAutoBrightness()) { - // Use the auto-brightness curve and the last observed lux - rawBrightnessState = mAutomaticBrightnessController - .getAutomaticScreenBrightnessBasedOnLastUsedLux( - mTempBrightnessEvent); - } else { - rawBrightnessState = getDozeBrightnessForOffload(); - mTempBrightnessEvent.setFlags(mTempBrightnessEvent.getFlags() - | BrightnessEvent.FLAG_DOZE_SCALE); - } - - if (BrightnessUtils.isValidBrightnessValue(rawBrightnessState)) { - brightnessState = clampScreenBrightness(rawBrightnessState); - mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_INITIAL); - - if (mAutomaticBrightnessController != null - && mAutomaticBrightnessStrategy.shouldUseAutoBrightness()) { - // Keep the brightness in the setting so that we can use it after the screen - // turns on, until a lux sample becomes available. We don't do this when - // auto-brightness is disabled - in that situation we still want to use - // the last brightness from when the screen was on. - updateScreenBrightnessSetting = currentBrightnessSetting != brightnessState; - } - } + && mDisplayOffloadSession != null + && (mAutomaticBrightnessController == null + || !mAutomaticBrightnessStrategy.shouldUseAutoBrightness())) { + rawBrightnessState = getDozeBrightnessForOffload(); + brightnessState = clampScreenBrightness(rawBrightnessState); + mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_MANUAL); + mTempBrightnessEvent.setFlags( + mTempBrightnessEvent.getFlags() | BrightnessEvent.FLAG_DOZE_SCALE); } // Use default brightness when dozing unless overridden. - if (Float.isNaN(brightnessState) - || displayBrightnessState.getDisplayBrightnessStrategyName() - .equals(DisplayBrightnessStrategyConstants.FALLBACK_BRIGHTNESS_STRATEGY_NAME)) { + if (Float.isNaN(brightnessState) && Display.isDozeState(state) + && !mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig()) { rawBrightnessState = mScreenBrightnessDozeConfig; brightnessState = clampScreenBrightness(rawBrightnessState); mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT); @@ -3169,7 +3158,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call BrightnessRangeController brightnessModeController, BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userNits, - BrightnessClamperController brightnessClamperController) { + BrightnessClamperController brightnessClamperController, + DisplayManagerFlags displayManagerFlags) { return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor, brightnessMappingStrategyMap, lightSensorWarmUpTime, brightnessMin, @@ -3180,7 +3170,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call screenBrightnessThresholds, ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, context, brightnessModeController, brightnessThrottler, ambientLightHorizonShort, ambientLightHorizonLong, userLux, - userNits, brightnessClamperController); + userNits, brightnessClamperController, displayManagerFlags); } BrightnessMappingStrategy getDefaultModeBrightnessMapper(Context context, diff --git a/services/core/java/com/android/server/display/brightness/BrightnessReason.java b/services/core/java/com/android/server/display/brightness/BrightnessReason.java index fc95d15ae6f4..9bf10a77d056 100644 --- a/services/core/java/com/android/server/display/brightness/BrightnessReason.java +++ b/services/core/java/com/android/server/display/brightness/BrightnessReason.java @@ -40,8 +40,8 @@ public final class BrightnessReason { public static final int REASON_SCREEN_OFF_BRIGHTNESS_SENSOR = 9; public static final int REASON_FOLLOWER = 10; public static final int REASON_OFFLOAD = 11; - public static final int REASON_DOZE_INITIAL = 12; - public static final int REASON_MAX = REASON_DOZE_INITIAL; + public static final int REASON_DOZE_MANUAL = 12; + public static final int REASON_MAX = REASON_DOZE_MANUAL; public static final int MODIFIER_DIMMED = 0x1; public static final int MODIFIER_LOW_POWER = 0x2; @@ -208,8 +208,8 @@ public final class BrightnessReason { return "follower"; case REASON_OFFLOAD: return "offload"; - case REASON_DOZE_INITIAL: - return "doze_initial"; + case REASON_DOZE_MANUAL: + return "doze_manual"; default: return Integer.toString(reason); } 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 index 37b693190f7f..29073644ee2e 100644 --- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java +++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java @@ -15,8 +15,6 @@ */ package com.android.server.display.brightness.strategy; -import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; - import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE; @@ -129,9 +127,11 @@ public class AutomaticBrightnessStrategy extends AutomaticBrightnessStrategy2 public void setAutoBrightnessState(int targetDisplayState, boolean allowAutoBrightnessWhileDozingConfig, int brightnessReason, int policy, float lastUserSetScreenBrightness, boolean userSetBrightnessChanged) { - switchMode(targetDisplayState); + // We are still in the process of updating the power state, so there's no need to trigger + // an update again + switchMode(targetDisplayState, /* sendUpdate= */ false); final boolean autoBrightnessEnabledInDoze = - allowAutoBrightnessWhileDozingConfig && policy == POLICY_DOZE; + allowAutoBrightnessWhileDozingConfig && Display.isDozeState(targetDisplayState); mIsAutoBrightnessEnabled = shouldUseAutoBrightness() && (targetDisplayState == Display.STATE_ON || autoBrightnessEnabledInDoze) && brightnessReason != BrightnessReason.REASON_OVERRIDE @@ -371,23 +371,6 @@ public class AutomaticBrightnessStrategy extends AutomaticBrightnessStrategy2 } /** - * Get the automatic screen brightness based on the last observed lux reading. Used e.g. when - * entering doze - we disable the light sensor, invalidate the lux, but we still need to set - * the initial brightness in doze mode. - * @param brightnessEvent Event object to populate with details about why the specific - * brightness was chosen. - */ - public float getAutomaticScreenBrightnessBasedOnLastUsedLux( - BrightnessEvent brightnessEvent) { - float brightness = (mAutomaticBrightnessController != null) - ? mAutomaticBrightnessController - .getAutomaticScreenBrightnessBasedOnLastUsedLux(brightnessEvent) - : PowerManager.BRIGHTNESS_INVALID_FLOAT; - adjustAutomaticBrightnessStateIfValid(brightness); - return brightness; - } - - /** * Returns if the auto brightness has been applied */ public boolean hasAppliedAutoBrightness() { @@ -495,14 +478,12 @@ public class AutomaticBrightnessStrategy extends AutomaticBrightnessStrategy2 mIsShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints(); } } - - - private void switchMode(int state) { + private void switchMode(int state, boolean sendUpdate) { if (mDisplayManagerFlags.areAutoBrightnessModesEnabled() && mAutomaticBrightnessController != null && !mAutomaticBrightnessController.isInIdleMode()) { mAutomaticBrightnessController.switchMode(Display.isDozeState(state) - ? AUTO_BRIGHTNESS_MODE_DOZE : AUTO_BRIGHTNESS_MODE_DEFAULT); + ? AUTO_BRIGHTNESS_MODE_DOZE : AUTO_BRIGHTNESS_MODE_DEFAULT, sendUpdate); } } diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java index 58670c97e944..4d9c18ab72fe 100644 --- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java +++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java @@ -15,8 +15,6 @@ */ package com.android.server.display.brightness.strategy; -import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; - import android.annotation.Nullable; import android.content.Context; import android.hardware.display.BrightnessConfiguration; @@ -110,7 +108,7 @@ public class AutomaticBrightnessStrategy2 { boolean allowAutoBrightnessWhileDozingConfig, int brightnessReason, int policy, float lastUserSetScreenBrightness, boolean userSetBrightnessChanged) { final boolean autoBrightnessEnabledInDoze = - allowAutoBrightnessWhileDozingConfig && policy == POLICY_DOZE; + allowAutoBrightnessWhileDozingConfig && Display.isDozeState(targetDisplayState); mIsAutoBrightnessEnabled = shouldUseAutoBrightness() && (targetDisplayState == Display.STATE_ON || autoBrightnessEnabledInDoze) && brightnessReason != BrightnessReason.REASON_OVERRIDE @@ -273,23 +271,6 @@ public class AutomaticBrightnessStrategy2 { } /** - * Get the automatic screen brightness based on the last observed lux reading. Used e.g. when - * entering doze - we disable the light sensor, invalidate the lux, but we still need to set - * the initial brightness in doze mode. - * @param brightnessEvent Event object to populate with details about why the specific - * brightness was chosen. - */ - public float getAutomaticScreenBrightnessBasedOnLastUsedLux( - BrightnessEvent brightnessEvent) { - float brightness = (mAutomaticBrightnessController != null) - ? mAutomaticBrightnessController - .getAutomaticScreenBrightnessBasedOnLastUsedLux(brightnessEvent) - : PowerManager.BRIGHTNESS_INVALID_FLOAT; - adjustAutomaticBrightnessStateIfValid(brightness); - return brightness; - } - - /** * Gets the auto-brightness adjustment flag change reason */ public int getAutoBrightnessAdjustmentReasonsFlags() { diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java index a5414fcf3970..8f775a54a8cd 100644 --- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java @@ -154,6 +154,11 @@ public class DisplayManagerFlags { Flags::useFusionProxSensor ); + private final FlagState mOffloadControlsDozeAutoBrightness = new FlagState( + Flags.FLAG_OFFLOAD_CONTROLS_DOZE_AUTO_BRIGHTNESS, + Flags::offloadControlsDozeAutoBrightness + ); + private final FlagState mPeakRefreshRatePhysicalLimit = new FlagState( Flags.FLAG_ENABLE_PEAK_REFRESH_RATE_PHYSICAL_LIMIT, Flags::enablePeakRefreshRatePhysicalLimit @@ -327,6 +332,13 @@ public class DisplayManagerFlags { return mUseFusionProxSensor.getName(); } + /** + * @return Whether DisplayOffload should control auto-brightness in doze + */ + public boolean offloadControlsDozeAutoBrightness() { + return mOffloadControlsDozeAutoBrightness.isEnabled(); + } + public boolean isPeakRefreshRatePhysicalLimitEnabled() { return mPeakRefreshRatePhysicalLimit.isEnabled(); } @@ -373,6 +385,7 @@ public class DisplayManagerFlags { pw.println(" " + mRefactorDisplayPowerController); pw.println(" " + mResolutionBackupRestore); pw.println(" " + mUseFusionProxSensor); + pw.println(" " + mOffloadControlsDozeAutoBrightness); pw.println(" " + mPeakRefreshRatePhysicalLimit); pw.println(" " + mIgnoreAppPreferredRefreshRate); pw.println(" " + mSynthetic60hzModes); diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig index 316b6db49954..697218dc0f41 100644 --- a/services/core/java/com/android/server/display/feature/display_flags.aconfig +++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig @@ -246,6 +246,17 @@ flag { } flag { + name: "offload_controls_doze_auto_brightness" + namespace: "display_manager" + description: "Allows the registered DisplayOffloader to control if auto-brightness is used in doze" + bug: "327392714" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "enable_peak_refresh_rate_physical_limit" namespace: "display_manager" description: "Flag for adding physical refresh rate limit if smooth display setting is on " diff --git a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java index 3628a57f2375..d3efcb6e50b3 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java @@ -16,7 +16,6 @@ package com.android.server.display; -import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE; @@ -44,6 +43,7 @@ import android.hardware.SensorManager; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; import android.os.Handler; import android.os.PowerManager; +import android.os.SystemClock; import android.os.test.TestLooper; import android.util.SparseArray; import android.view.Display; @@ -54,6 +54,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.server.display.brightness.clamper.BrightnessClamperController; import com.android.server.display.config.HysteresisLevels; +import com.android.server.display.feature.DisplayManagerFlags; import com.android.server.testutils.OffsettableClock; import org.junit.After; @@ -68,6 +69,8 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidJUnit4.class) public class AutomaticBrightnessControllerTest { + private static final int ANDROID_SLEEP_TIME = 1000; + private static final int NANO_SECONDS_MULTIPLIER = 1000000; private static final float BRIGHTNESS_MIN_FLOAT = 0.0f; private static final float BRIGHTNESS_MAX_FLOAT = 1.0f; private static final int LIGHT_SENSOR_RATE = 20; @@ -100,6 +103,8 @@ public class AutomaticBrightnessControllerTest { @Mock BrightnessRangeController mBrightnessRangeController; @Mock BrightnessClamperController mBrightnessClamperController; + @Mock + DisplayManagerFlags mDisplayManagerFlags; @Mock BrightnessThrottler mBrightnessThrottler; @Before @@ -148,8 +153,18 @@ public class AutomaticBrightnessControllerTest { } @Override - AutomaticBrightnessController.Clock createClock() { - return mClock::now; + AutomaticBrightnessController.Clock createClock(boolean isEnabled) { + return new AutomaticBrightnessController.Clock() { + @Override + public long uptimeMillis() { + return mClock.now(); + } + + @Override + public long getSensorEventScaleTime() { + return mClock.now() + ANDROID_SLEEP_TIME; + } + }; } }, // pass in test looper instead, pass in offsettable clock @@ -166,7 +181,7 @@ public class AutomaticBrightnessControllerTest { mContext, mBrightnessRangeController, mBrightnessThrottler, useHorizon ? AMBIENT_LIGHT_HORIZON_SHORT : 1, useHorizon ? AMBIENT_LIGHT_HORIZON_LONG : 10000, userLux, userNits, - mBrightnessClamperController + mBrightnessClamperController, mDisplayManagerFlags ); when(mBrightnessRangeController.getCurrentBrightnessMax()).thenReturn( @@ -350,7 +365,7 @@ public class AutomaticBrightnessControllerTest { when(mBrightnessMappingStrategy.getShortTermModelTimeout()).thenReturn(2000L); - mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE); + mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE, /* sendUpdate= */ true); when(mBrightnessMappingStrategy.shouldResetShortTermModel( 123f, 0.5f)).thenReturn(true); @@ -360,7 +375,7 @@ public class AutomaticBrightnessControllerTest { mBrightnessMappingStrategy.getShortTermModelTimeout() + 1000); mTestLooper.dispatchAll(); - mController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT); + mController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT, /* sendUpdate= */ true); mTestLooper.moveTimeForward(4000); mTestLooper.dispatchAll(); @@ -394,14 +409,14 @@ public class AutomaticBrightnessControllerTest { when(mBrightnessMappingStrategy.getUserBrightness()).thenReturn(0.51f); when(mBrightnessMappingStrategy.getUserLux()).thenReturn(123.0f); - mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE); + mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE, /* sendUpdate= */ true); // Time does not move forward, since clock is doesn't increment naturally. mTestLooper.dispatchAll(); // Sensor reads 100000 lux, listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 678910)); - mController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT); + mController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT, /* sendUpdate= */ true); // Verify short term model is not reset. verify(mBrightnessMappingStrategy, never()).clearUserDataPoints(); @@ -432,7 +447,7 @@ public class AutomaticBrightnessControllerTest { when(mBrightnessMappingStrategy.getUserBrightness()).thenReturn(0.5f); when(mBrightnessMappingStrategy.getUserLux()).thenReturn(123f); - mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE); + mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE, /* sendUpdate= */ true); when(mIdleBrightnessMappingStrategy.getUserBrightness()).thenReturn( PowerManager.BRIGHTNESS_INVALID_FLOAT); when(mIdleBrightnessMappingStrategy.getUserLux()).thenReturn( @@ -446,7 +461,7 @@ public class AutomaticBrightnessControllerTest { mBrightnessMappingStrategy.getShortTermModelTimeout() + 1000); mTestLooper.dispatchAll(); - mController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT); + mController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT, /* sendUpdate= */ true); mTestLooper.moveTimeForward(4000); mTestLooper.dispatchAll(); @@ -479,7 +494,7 @@ public class AutomaticBrightnessControllerTest { when(mBrightnessMappingStrategy.getUserBrightness()).thenReturn(0.5f); when(mBrightnessMappingStrategy.getUserLux()).thenReturn(123f); - mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE); + mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE, /* sendUpdate= */ true); when(mIdleBrightnessMappingStrategy.getUserBrightness()).thenReturn( PowerManager.BRIGHTNESS_INVALID_FLOAT); when(mIdleBrightnessMappingStrategy.getUserLux()).thenReturn( @@ -493,7 +508,7 @@ public class AutomaticBrightnessControllerTest { // Do not fast-forward time. mTestLooper.dispatchAll(); - mController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT); + mController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT, /* sendUpdate= */ true); // Do not fast-forward time mTestLooper.dispatchAll(); @@ -523,7 +538,7 @@ public class AutomaticBrightnessControllerTest { // No user brightness interaction. - mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE); + mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE, /* sendUpdate= */ true); when(mIdleBrightnessMappingStrategy.getUserBrightness()).thenReturn( PowerManager.BRIGHTNESS_INVALID_FLOAT); when(mIdleBrightnessMappingStrategy.getUserLux()).thenReturn( @@ -534,7 +549,7 @@ public class AutomaticBrightnessControllerTest { // Do not fast-forward time. mTestLooper.dispatchAll(); - mController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT); + mController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT, /* sendUpdate= */ true); // Do not fast-forward time mTestLooper.dispatchAll(); @@ -568,7 +583,7 @@ public class AutomaticBrightnessControllerTest { verify(mBrightnessMappingStrategy, times(3)).getBrightness(anyFloat(), any(), anyInt()); // Now let's do the same for idle mode - mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE); + mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE, /* sendUpdate= */ true); // Called once when switching, // setAmbientLux() is called twice and once in updateAutoBrightness(), // nextAmbientLightBrighteningTransition() and nextAmbientLightDarkeningTransition() are @@ -800,6 +815,43 @@ public class AutomaticBrightnessControllerTest { } @Test + public void testAmbientLuxBuffers_prunedBeyondLongHorizonExceptLatestValue() throws Exception { + when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true); + ArgumentCaptor<SensorEventListener> listenerCaptor = + ArgumentCaptor.forClass(SensorEventListener.class); + verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), + eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class)); + SensorEventListener listener = listenerCaptor.getValue(); + + // Choose values such that the ring buffer's capacity is extended and the buffer is pruned + int increment = 11; + int lux = 5000; + for (int i = 0; i < 1000; i++) { + lux += increment; + mClock.fastForward(increment); + listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux, + (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER)); + } + mClock.fastForward(AMBIENT_LIGHT_HORIZON_LONG + 10); + int newLux = 2000; + listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, newLux, + (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER)); + + float[] sensorValues = mController.getLastSensorValues(); + long[] sensorTimestamps = mController.getLastSensorTimestamps(); + // Only the values within the horizon should be kept + assertEquals(2, sensorValues.length); + assertEquals(2, sensorTimestamps.length); + + assertEquals(lux, sensorValues[0], EPSILON); + assertEquals(newLux, sensorValues[1], EPSILON); + assertEquals(mClock.now() + ANDROID_SLEEP_TIME - AMBIENT_LIGHT_HORIZON_LONG, + sensorTimestamps[0]); + assertEquals(mClock.now() + ANDROID_SLEEP_TIME, + sensorTimestamps[1]); + } + + @Test public void testGetSensorReadingsFullBuffer() throws Exception { ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); @@ -966,7 +1018,7 @@ public class AutomaticBrightnessControllerTest { BrightnessMappingStrategy.INVALID_NITS, /* applyDebounce= */ true, /* useHorizon= */ false); - mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE); + mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE, /* sendUpdate= */ true); ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); @@ -1003,7 +1055,7 @@ public class AutomaticBrightnessControllerTest { BrightnessMappingStrategy.INVALID_NITS, /* applyDebounce= */ true, /* useHorizon= */ false); - mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE); + mController.switchMode(AUTO_BRIGHTNESS_MODE_IDLE, /* sendUpdate= */ true); ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); @@ -1030,7 +1082,7 @@ public class AutomaticBrightnessControllerTest { } @Test - public void testBrightnessBasedOnLastUsedLux() throws Exception { + public void testAutoBrightnessInDoze() throws Exception { ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), @@ -1047,19 +1099,23 @@ public class AutomaticBrightnessControllerTest { /* category= */ anyInt())).thenReturn(normalizedBrightness); when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); - // Send a new sensor value, disable the sensor and verify - listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); - mController.configure(AUTO_BRIGHTNESS_DISABLED, /* configuration= */ null, + // Set policy to DOZE + mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0, - /* userChanged= */ false, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON, + /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE, Display.STATE_DOZE, /* shouldResetShortTermModel= */ true); - assertEquals(normalizedBrightness, - mController.getAutomaticScreenBrightnessBasedOnLastUsedLux( + + // Send a new sensor value + listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); + + // The brightness should be scaled by the doze factor + assertEquals(normalizedBrightness * DOZE_SCALE_FACTOR, + mController.getAutomaticScreenBrightness( /* brightnessEvent= */ null), EPSILON); } @Test - public void testAutoBrightnessInDoze() throws Exception { + public void testAutoBrightnessInDoze_ShouldNotScaleIfUsingDozeCurve() throws Exception { ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), @@ -1072,10 +1128,13 @@ public class AutomaticBrightnessControllerTest { float normalizedBrightness = 0.3f; when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux); when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); - when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), + when(mDozeBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); + // Switch mode to DOZE + mController.switchMode(AUTO_BRIGHTNESS_MODE_DOZE, /* sendUpdate= */ false); + // Set policy to DOZE mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0, @@ -1085,17 +1144,13 @@ public class AutomaticBrightnessControllerTest { // Send a new sensor value listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); - // The brightness should be scaled by the doze factor - assertEquals(normalizedBrightness * DOZE_SCALE_FACTOR, - mController.getAutomaticScreenBrightness( - /* brightnessEvent= */ null), EPSILON); - assertEquals(normalizedBrightness * DOZE_SCALE_FACTOR, - mController.getAutomaticScreenBrightnessBasedOnLastUsedLux( - /* brightnessEvent= */ null), EPSILON); + // The brightness should not be scaled by the doze factor + assertEquals(normalizedBrightness, + mController.getAutomaticScreenBrightness(/* brightnessEvent= */ null), EPSILON); } @Test - public void testAutoBrightnessInDoze_ShouldNotScaleIfUsingDozeCurve() throws Exception { + public void testAutoBrightnessInDoze_ShouldNotScaleIfScreenOn() throws Exception { ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), @@ -1108,17 +1163,14 @@ public class AutomaticBrightnessControllerTest { float normalizedBrightness = 0.3f; when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux); when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); - when(mDozeBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), + when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); - // Switch mode to DOZE - mController.switchMode(AUTO_BRIGHTNESS_MODE_DOZE); - // Set policy to DOZE mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0, - /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE, Display.STATE_DOZE, + /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE, Display.STATE_ON, /* shouldResetShortTermModel= */ true); // Send a new sensor value @@ -1127,13 +1179,10 @@ public class AutomaticBrightnessControllerTest { // The brightness should not be scaled by the doze factor assertEquals(normalizedBrightness, mController.getAutomaticScreenBrightness(/* brightnessEvent= */ null), EPSILON); - assertEquals(normalizedBrightness, - mController.getAutomaticScreenBrightnessBasedOnLastUsedLux( - /* brightnessEvent= */ null), EPSILON); } @Test - public void testAutoBrightnessInDoze_ShouldNotScaleIfScreenOn() throws Exception { + public void testSwitchMode_UpdateBrightnessImmediately() throws Exception { ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), @@ -1146,24 +1195,47 @@ public class AutomaticBrightnessControllerTest { float normalizedBrightness = 0.3f; when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux); when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); - when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), + when(mDozeBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); - // Set policy to DOZE - mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, - /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0, - /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); - // Send a new sensor value listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); - // The brightness should not be scaled by the doze factor + // Switch mode to DOZE + mController.switchMode(AUTO_BRIGHTNESS_MODE_DOZE, /* sendUpdate= */ false); + assertEquals(normalizedBrightness, mController.getAutomaticScreenBrightness(/* brightnessEvent= */ null), EPSILON); + } + + @Test + public void testSwitchMode_UpdateBrightnessInBackground() throws Exception { + ArgumentCaptor<SensorEventListener> listenerCaptor = + ArgumentCaptor.forClass(SensorEventListener.class); + verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), + eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class)); + SensorEventListener listener = listenerCaptor.getValue(); + + // Set up system to return 0.3f as a brightness value + float lux = 100.0f; + // Brightness as float (from 0.0f to 1.0f) + float normalizedBrightness = 0.3f; + when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux); + when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); + when(mDozeBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), + /* category= */ anyInt())).thenReturn(normalizedBrightness); + when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); + + // Send a new sensor value + listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); + + // Switch mode to DOZE + mController.switchMode(AUTO_BRIGHTNESS_MODE_DOZE, /* sendUpdate= */ true); + mClock.fastForward(SystemClock.uptimeMillis()); + mTestLooper.dispatchAll(); + assertEquals(normalizedBrightness, - mController.getAutomaticScreenBrightnessBasedOnLastUsedLux( - /* brightnessEvent= */ null), EPSILON); + mController.getAutomaticScreenBrightness(/* brightnessEvent= */ null), EPSILON); } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java index e5685c7f4f43..98f572d81adf 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -1021,6 +1021,36 @@ public final class DisplayPowerControllerTest { } @Test + public void testAutoBrightnessEnabled_DisplayIsInDoze_OffloadAllows() { + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true); + mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID); + when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true); + when(mDisplayManagerFlagsMock.offloadControlsDozeAutoBrightness()).thenReturn(true); + when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true); + mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession); + + DisplayPowerRequest dpr = new DisplayPowerRequest(); + dpr.policy = DisplayPowerRequest.POLICY_DOZE; + when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_DOZE); + mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + advanceTime(1); // Run updatePowerState + + verify(mHolder.automaticBrightnessController).configure( + AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, + /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT, + /* userChangedBrightness= */ false, /* adjustment= */ 0, + /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_DOZE, + Display.STATE_DOZE, /* shouldResetShortTermModel= */ false + ); + verify(mHolder.hbmController) + .setAutoBrightnessEnabled(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED); + } + + @Test public void testAutoBrightnessDisabled_ManualBrightnessMode() { Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, @@ -1067,7 +1097,7 @@ public final class DisplayPowerControllerTest { } @Test - public void testAutoBrightnessDisabled_DisplayIsInDoze() { + public void testAutoBrightnessDisabled_DisplayIsInDoze_ConfigDoesNotAllow() { Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); @@ -1093,6 +1123,36 @@ public final class DisplayPowerControllerTest { } @Test + public void testAutoBrightnessDisabled_DisplayIsInDoze_OffloadDoesNotAllow() { + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true); + mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID); + when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true); + when(mDisplayManagerFlagsMock.offloadControlsDozeAutoBrightness()).thenReturn(true); + when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(false); + mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession); + + DisplayPowerRequest dpr = new DisplayPowerRequest(); + dpr.policy = DisplayPowerRequest.POLICY_DOZE; + when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_DOZE); + mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + advanceTime(1); // Run updatePowerState + + verify(mHolder.automaticBrightnessController).configure( + AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE, + /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT, + /* userChangedBrightness= */ false, /* adjustment= */ 0, + /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_DOZE, + Display.STATE_DOZE, /* shouldResetShortTermModel= */ false + ); + verify(mHolder.hbmController).setAutoBrightnessEnabled( + AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE); + } + + @Test public void testAutoBrightnessDisabled_FollowerDisplay() { Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, @@ -1191,7 +1251,8 @@ public final class DisplayPowerControllerTest { /* ambientLightHorizonLong= */ anyInt(), eq(lux), eq(nits), - any(BrightnessClamperController.class) + any(BrightnessClamperController.class), + any(DisplayManagerFlags.class) ); } @@ -1668,7 +1729,8 @@ public final class DisplayPowerControllerTest { mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState - verify(mHolder.automaticBrightnessController).switchMode(AUTO_BRIGHTNESS_MODE_DOZE); + verify(mHolder.automaticBrightnessController) + .switchMode(AUTO_BRIGHTNESS_MODE_DOZE, /* sendUpdate= */ false); // Back to default mode when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON); @@ -1676,7 +1738,8 @@ public final class DisplayPowerControllerTest { mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState - verify(mHolder.automaticBrightnessController).switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT); + verify(mHolder.automaticBrightnessController) + .switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT, /* sendUpdate= */ false); } @Test @@ -1690,7 +1753,7 @@ public final class DisplayPowerControllerTest { advanceTime(1); // Run updatePowerState verify(mHolder.automaticBrightnessController, never()) - .switchMode(AUTO_BRIGHTNESS_MODE_DOZE); + .switchMode(eq(AUTO_BRIGHTNESS_MODE_DOZE), /* sendUpdate= */ anyBoolean()); } @Test @@ -1703,7 +1766,7 @@ public final class DisplayPowerControllerTest { advanceTime(1); // Run updatePowerState verify(mHolder.automaticBrightnessController, never()) - .switchMode(AUTO_BRIGHTNESS_MODE_DOZE); + .switchMode(eq(AUTO_BRIGHTNESS_MODE_DOZE), /* sendUpdate= */ anyBoolean()); } @Test @@ -1764,20 +1827,15 @@ public final class DisplayPowerControllerTest { } @Test - public void testInitialDozeBrightness_AutoBrightnessEnabled() { - when(mDisplayManagerFlagsMock.areAutoBrightnessModesEnabled()).thenReturn(true); + public void testDozeManualBrightness() { when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true); mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession); Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, - Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); - mContext.getOrCreateTestableResources().addOverride( - com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, false); + Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); float brightness = 0.277f; when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f); - when(mHolder.automaticBrightnessController - .getAutomaticScreenBrightnessBasedOnLastUsedLux(any(BrightnessEvent.class))) - .thenReturn(brightness); + when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness); when(mHolder.hbmController.getCurrentBrightnessMax()) .thenReturn(PowerManager.BRIGHTNESS_MAX); when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_DOZE); @@ -1785,17 +1843,27 @@ public final class DisplayPowerControllerTest { DisplayPowerRequest dpr = new DisplayPowerRequest(); dpr.policy = DisplayPowerRequest.POLICY_DOZE; mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); - advanceTime(1); // Run updatePowerState + advanceTime(1); // Run updatePowerState, initialize - verify(mHolder.animator).animateTo(eq(brightness), + ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor = + ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class); + verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture()); + BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); + listener.onBrightnessChanged(brightness); + advanceTime(1); // Send messages, run updatePowerState + + verify(mHolder.animator).animateTo(eq(brightness * DOZE_SCALE_FACTOR), /* linearSecondTarget= */ anyFloat(), /* rate= */ anyFloat(), /* ignoreAnimationLimits= */ anyBoolean()); - verify(mHolder.brightnessSetting).setBrightness(brightness); + assertEquals(brightness * DOZE_SCALE_FACTOR, mHolder.dpc.getDozeBrightnessForOffload(), + /* delta= */ 0); } @Test - public void testInitialDozeBrightness_AutoBrightnessDisabled() { + public void testDozeManualBrightness_AbcIsNull() { when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true); + mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID, /* isEnabled= */ true, + /* isAutoBrightnessAvailable= */ false); mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession); Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, @@ -1827,22 +1895,16 @@ public final class DisplayPowerControllerTest { } @Test - public void testInitialDozeBrightness_AbcIsNull() { - when(mDisplayManagerFlagsMock.areAutoBrightnessModesEnabled()).thenReturn(true); - when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true); - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.SCREEN_BRIGHTNESS_MODE, - Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + public void testDefaultDozeBrightness() { + float brightness = 0.121f; + when(mPowerManagerMock.getBrightnessConstraint( + PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE)).thenReturn(brightness); mContext.getOrCreateTestableResources().addOverride( com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, false); - mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID, /* isEnabled= */ true, - /* isAutoBrightnessAvailable= */ false); - mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession); - float brightness = 0.277f; + mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID); when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f); - when(mHolder.automaticBrightnessController - .getAutomaticScreenBrightnessBasedOnLastUsedLux(any(BrightnessEvent.class))) - .thenReturn(brightness); + when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness( + any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT); when(mHolder.hbmController.getCurrentBrightnessMax()) .thenReturn(PowerManager.BRIGHTNESS_MAX); when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_DOZE); @@ -1852,18 +1914,17 @@ public final class DisplayPowerControllerTest { mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState - // Automatic Brightness Controller is null so no initial doze brightness should be set and - // we should not crash - verify(mHolder.animator, never()).animateTo(eq(brightness), - /* linearSecondTarget= */ anyFloat(), /* rate= */ anyFloat(), - /* ignoreAnimationLimits= */ anyBoolean()); + verify(mHolder.animator).animateTo(eq(brightness), /* linearSecondTarget= */ anyFloat(), + eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE), eq(false)); } @Test - public void testDefaultDozeBrightness() { + public void testDefaultDozeBrightness_ShouldNotBeUsedIfAutoBrightnessAllowedInDoze() { float brightness = 0.121f; when(mPowerManagerMock.getBrightnessConstraint( PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE)).thenReturn(brightness); + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true); mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID); when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f); when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness( @@ -1877,8 +1938,9 @@ public final class DisplayPowerControllerTest { mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState - verify(mHolder.animator).animateTo(eq(brightness), /* linearSecondTarget= */ anyFloat(), - eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE), eq(false)); + verify(mHolder.animator, never()).animateTo(eq(brightness), + /* linearSecondTarget= */ anyFloat(), /* rate= */ anyFloat(), + /* ignoreAnimationLimits= */ anyBoolean()); } /** @@ -2186,7 +2248,8 @@ public final class DisplayPowerControllerTest { BrightnessRangeController brightnessRangeController, BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userNits, - BrightnessClamperController brightnessClamperController) { + BrightnessClamperController brightnessClamperController, + DisplayManagerFlags displayManagerFlags) { return mAutomaticBrightnessController; } diff --git a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java index 7fd96c57c215..12050e1beaed 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -1246,6 +1246,11 @@ public class LocalDisplayAdapterTest { @Override public void onBlockingScreenOn(Runnable unblocker) {} + + @Override + public boolean allowAutoBrightnessInDoze() { + return true; + } }); mDisplayOffloadSession = new DisplayOffloadSessionImpl(mDisplayOffloader, diff --git a/services/tests/displayservicetests/src/com/android/server/display/TestUtils.java b/services/tests/displayservicetests/src/com/android/server/display/TestUtils.java index 8b45145b160f..18dfcc1afd01 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/TestUtils.java +++ b/services/tests/displayservicetests/src/com/android/server/display/TestUtils.java @@ -30,13 +30,21 @@ import java.lang.reflect.Method; public final class TestUtils { public static SensorEvent createSensorEvent(Sensor sensor, int value) throws Exception { + return createSensorEvent(sensor, value, SystemClock.elapsedRealtimeNanos()); + } + + /** + * Creates a light sensor event + */ + public static SensorEvent createSensorEvent(Sensor sensor, int value, long timestamp) + throws Exception { final Constructor<SensorEvent> constructor = SensorEvent.class.getDeclaredConstructor(int.class); constructor.setAccessible(true); final SensorEvent event = constructor.newInstance(1); event.sensor = sensor; event.values[0] = value; - event.timestamp = SystemClock.elapsedRealtimeNanos(); + event.timestamp = timestamp; return event; } diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java index 09f5bb60a6ad..498bffd260dd 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java @@ -343,17 +343,11 @@ public class AutomaticBrightnessStrategy2Test { AutomaticBrightnessController.class); when(automaticBrightnessController.getAutomaticScreenBrightness(any(BrightnessEvent.class))) .thenReturn(automaticScreenBrightness); - when(automaticBrightnessController.getAutomaticScreenBrightnessBasedOnLastUsedLux( - any(BrightnessEvent.class))) - .thenReturn(automaticScreenBrightness); mAutomaticBrightnessStrategy.setAutomaticBrightnessController( automaticBrightnessController); assertEquals(automaticScreenBrightness, mAutomaticBrightnessStrategy.getAutomaticScreenBrightness( new BrightnessEvent(DISPLAY_ID)), 0.0f); - assertEquals(automaticScreenBrightness, - mAutomaticBrightnessStrategy.getAutomaticScreenBrightnessBasedOnLastUsedLux( - new BrightnessEvent(DISPLAY_ID)), 0.0f); } @Test diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java index d19f47951df1..afb5a5cc5cc4 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java @@ -18,6 +18,7 @@ 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.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; @@ -273,7 +274,8 @@ public class AutomaticBrightnessStrategyTest { mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON, allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, userSetBrightnessChanged); - verify(mAutomaticBrightnessController, never()).switchMode(anyInt()); + verify(mAutomaticBrightnessController, never()) + .switchMode(anyInt(), /* sendUpdate= */ anyBoolean()); // Validate interaction when automaticBrightnessController is in non-idle mode, and display // state is ON @@ -282,7 +284,8 @@ public class AutomaticBrightnessStrategyTest { allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController).switchMode( - AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT); + AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT, + /* sendUpdate= */ false); // Validate interaction when automaticBrightnessController is in non-idle mode, and display // state is DOZE @@ -290,7 +293,8 @@ public class AutomaticBrightnessStrategyTest { allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController).switchMode( - AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE); + AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE, + /* sendUpdate= */ false); } @Test @@ -388,17 +392,11 @@ public class AutomaticBrightnessStrategyTest { AutomaticBrightnessController.class); when(automaticBrightnessController.getAutomaticScreenBrightness(any(BrightnessEvent.class))) .thenReturn(automaticScreenBrightness); - when(automaticBrightnessController.getAutomaticScreenBrightnessBasedOnLastUsedLux( - any(BrightnessEvent.class))) - .thenReturn(automaticScreenBrightness); mAutomaticBrightnessStrategy.setAutomaticBrightnessController( automaticBrightnessController); assertEquals(automaticScreenBrightness, mAutomaticBrightnessStrategy.getAutomaticScreenBrightness( new BrightnessEvent(DISPLAY_ID), false), 0.0f); - assertEquals(automaticScreenBrightness, - mAutomaticBrightnessStrategy.getAutomaticScreenBrightnessBasedOnLastUsedLux( - new BrightnessEvent(DISPLAY_ID)), 0.0f); } @Test |