Add follower DPC tests

- change 'mHandler.sendMessage' to 'mHandler.sendMessageAtTime' so that 'mClock' is used instead of 'SystemClock'
- move objects to the injector so that mocks can be injected

Bug: 241307563
Test: atest DisplayPowerControllerTest
Test: atest DisplayPowerController2Test
Change-Id: I6cf7b64733cb3655034ab042fa9476e24ef27f00
This commit is contained in:
Piotr Wilczyński
2023-01-24 15:02:17 +00:00
parent dd9a2c3318
commit 1e3ef210af
4 changed files with 740 additions and 161 deletions

View File

@@ -1011,7 +1011,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
mBrightnessSettingListener = brightnessValue -> {
Message msg = mHandler.obtainMessage(MSG_UPDATE_BRIGHTNESS, brightnessValue);
mHandler.sendMessage(msg);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
};
mBrightnessSetting.registerListener(mBrightnessSettingListener);
@@ -1040,7 +1040,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
final boolean isIdleScreenBrightnessEnabled = resources.getBoolean(
R.bool.config_enableIdleScreenBrightnessMode);
mInteractiveModeBrightnessMapper = BrightnessMappingStrategy.create(resources,
mInteractiveModeBrightnessMapper = mInjector.getInteractiveModeBrightnessMapper(resources,
mDisplayDeviceConfig, mDisplayWhiteBalanceController);
if (isIdleScreenBrightnessEnabled) {
mIdleModeBrightnessMapper = BrightnessMappingStrategy.createForIdleMode(resources,
@@ -1065,7 +1065,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mDisplayDeviceConfig.getAmbientLuxDarkeningMinThreshold();
float ambientBrighteningMinThreshold =
mDisplayDeviceConfig.getAmbientLuxBrighteningMinThreshold();
HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
HysteresisLevels ambientBrightnessThresholds = mInjector.getHysteresisLevels(
ambientBrighteningThresholds, ambientDarkeningThresholds,
ambientBrighteningLevels, ambientDarkeningLevels, ambientDarkeningMinThreshold,
ambientBrighteningMinThreshold);
@@ -1083,7 +1083,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mDisplayDeviceConfig.getScreenDarkeningMinThreshold();
float screenBrighteningMinThreshold =
mDisplayDeviceConfig.getScreenBrighteningMinThreshold();
HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
HysteresisLevels screenBrightnessThresholds = mInjector.getHysteresisLevels(
screenBrighteningThresholds, screenDarkeningThresholds,
screenBrighteningLevels, screenDarkeningLevels, screenDarkeningMinThreshold,
screenBrighteningMinThreshold, true);
@@ -1101,7 +1101,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mDisplayDeviceConfig.getAmbientBrighteningLevelsIdle();
float[] ambientDarkeningLevelsIdle =
mDisplayDeviceConfig.getAmbientDarkeningLevelsIdle();
HysteresisLevels ambientBrightnessThresholdsIdle = new HysteresisLevels(
HysteresisLevels ambientBrightnessThresholdsIdle = mInjector.getHysteresisLevels(
ambientBrighteningThresholdsIdle, ambientDarkeningThresholdsIdle,
ambientBrighteningLevelsIdle, ambientDarkeningLevelsIdle,
ambientDarkeningMinThresholdIdle, ambientBrighteningMinThresholdIdle);
@@ -1119,7 +1119,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mDisplayDeviceConfig.getScreenBrighteningLevelsIdle();
float[] screenDarkeningLevelsIdle =
mDisplayDeviceConfig.getScreenDarkeningLevelsIdle();
HysteresisLevels screenBrightnessThresholdsIdle = new HysteresisLevels(
HysteresisLevels screenBrightnessThresholdsIdle = mInjector.getHysteresisLevels(
screenBrighteningThresholdsIdle, screenDarkeningThresholdsIdle,
screenBrighteningLevelsIdle, screenDarkeningLevelsIdle,
screenDarkeningMinThresholdIdle, screenBrighteningMinThresholdIdle);
@@ -1155,8 +1155,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.stop();
}
mAutomaticBrightnessController = new AutomaticBrightnessController(this,
handler.getLooper(), mSensorManager, mLightSensor,
mAutomaticBrightnessController = mInjector.getAutomaticBrightnessController(
this, handler.getLooper(), mSensorManager, mLightSensor,
mInteractiveModeBrightnessMapper, lightSensorWarmUpTimeConfig,
PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, dozeScaleFactor,
lightSensorRate, initialLightSensorRate, brighteningLightDebounce,
@@ -1257,7 +1257,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
public void onAnimationEnd() {
sendUpdatePowerState();
Message msg = mHandler.obtainMessage(MSG_BRIGHTNESS_RAMP_DONE);
mHandler.sendMessage(msg);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
};
@@ -2949,7 +2949,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
msg.what = MSG_STATSD_HBM_BRIGHTNESS;
msg.arg1 = Float.floatToIntBits(brightness);
msg.arg2 = mDisplayStatsId;
mHandler.sendMessageDelayed(msg, BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis()
+ BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
}
}
}
@@ -3105,7 +3106,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
@Override
public void onScreenOn() {
Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
mHandler.sendMessage(msg);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
}
@@ -3113,7 +3114,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
@Override
public void onScreenOff() {
Message msg = mHandler.obtainMessage(MSG_SCREEN_OFF_UNBLOCKED, this);
mHandler.sendMessage(msg);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
}
@@ -3195,6 +3196,58 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
FloatProperty<DisplayPowerState> secondProperty) {
return new DualRampAnimator(dps, firstProperty, secondProperty);
}
AutomaticBrightnessController getAutomaticBrightnessController(
AutomaticBrightnessController.Callbacks callbacks, Looper looper,
SensorManager sensorManager, Sensor lightSensor,
BrightnessMappingStrategy interactiveModeBrightnessMapper,
int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
boolean resetAmbientLuxAfterWarmUpConfig,
HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds,
HysteresisLevels ambientBrightnessThresholdsIdle,
HysteresisLevels screenBrightnessThresholdsIdle, Context context,
HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler,
BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
int ambientLightHorizonLong, float userLux, float userBrightness) {
return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor,
interactiveModeBrightnessMapper, lightSensorWarmUpTime, brightnessMin,
brightnessMax, dozeScaleFactor, lightSensorRate, initialLightSensorRate,
brighteningLightDebounceConfig, darkeningLightDebounceConfig,
resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds,
screenBrightnessThresholds, ambientBrightnessThresholdsIdle,
screenBrightnessThresholdsIdle, context, hbmController, brightnessThrottler,
idleModeBrightnessMapper, ambientLightHorizonShort, ambientLightHorizonLong,
userLux, userBrightness);
}
BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
DisplayDeviceConfig displayDeviceConfig,
DisplayWhiteBalanceController displayWhiteBalanceController) {
return BrightnessMappingStrategy.create(resources,
displayDeviceConfig, displayWhiteBalanceController);
}
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold) {
return new HysteresisLevels(brighteningThresholdsPercentages,
darkeningThresholdsPercentages, brighteningThresholdLevels,
darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold);
}
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
return new HysteresisLevels(brighteningThresholdsPercentages,
darkeningThresholdsPercentages, brighteningThresholdLevels,
darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold,
potentialOldBrightnessRange);
}
}
static class CachedBrightnessInfo {

View File

@@ -850,7 +850,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
BrightnessSetting.BrightnessSettingListener brightnessSettingListener = brightnessValue -> {
Message msg = mHandler.obtainMessage(MSG_UPDATE_BRIGHTNESS, brightnessValue);
mHandler.sendMessage(msg);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
};
mDisplayBrightnessController
.registerBrightnessSettingChangeListener(brightnessSettingListener);
@@ -880,7 +880,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
final boolean isIdleScreenBrightnessEnabled = resources.getBoolean(
R.bool.config_enableIdleScreenBrightnessMode);
mInteractiveModeBrightnessMapper = BrightnessMappingStrategy.create(resources,
mInteractiveModeBrightnessMapper = mInjector.getInteractiveModeBrightnessMapper(resources,
mDisplayDeviceConfig, mDisplayWhiteBalanceController);
if (isIdleScreenBrightnessEnabled) {
mIdleModeBrightnessMapper = BrightnessMappingStrategy.createForIdleMode(resources,
@@ -905,7 +905,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mDisplayDeviceConfig.getAmbientLuxDarkeningMinThreshold();
float ambientBrighteningMinThreshold =
mDisplayDeviceConfig.getAmbientLuxBrighteningMinThreshold();
HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
HysteresisLevels ambientBrightnessThresholds = mInjector.getHysteresisLevels(
ambientBrighteningThresholds, ambientDarkeningThresholds,
ambientBrighteningLevels, ambientDarkeningLevels, ambientDarkeningMinThreshold,
ambientBrighteningMinThreshold);
@@ -923,7 +923,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mDisplayDeviceConfig.getScreenDarkeningMinThreshold();
float screenBrighteningMinThreshold =
mDisplayDeviceConfig.getScreenBrighteningMinThreshold();
HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
HysteresisLevels screenBrightnessThresholds = mInjector.getHysteresisLevels(
screenBrighteningThresholds, screenDarkeningThresholds,
screenBrighteningLevels, screenDarkeningLevels, screenDarkeningMinThreshold,
screenBrighteningMinThreshold, true);
@@ -941,7 +941,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mDisplayDeviceConfig.getAmbientBrighteningLevelsIdle();
float[] ambientDarkeningLevelsIdle =
mDisplayDeviceConfig.getAmbientDarkeningLevelsIdle();
HysteresisLevels ambientBrightnessThresholdsIdle = new HysteresisLevels(
HysteresisLevels ambientBrightnessThresholdsIdle = mInjector.getHysteresisLevels(
ambientBrighteningThresholdsIdle, ambientDarkeningThresholdsIdle,
ambientBrighteningLevelsIdle, ambientDarkeningLevelsIdle,
ambientDarkeningMinThresholdIdle, ambientBrighteningMinThresholdIdle);
@@ -959,7 +959,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mDisplayDeviceConfig.getScreenBrighteningLevelsIdle();
float[] screenDarkeningLevelsIdle =
mDisplayDeviceConfig.getScreenDarkeningLevelsIdle();
HysteresisLevels screenBrightnessThresholdsIdle = new HysteresisLevels(
HysteresisLevels screenBrightnessThresholdsIdle = mInjector.getHysteresisLevels(
screenBrighteningThresholdsIdle, screenDarkeningThresholdsIdle,
screenBrighteningLevelsIdle, screenDarkeningLevelsIdle,
screenDarkeningMinThresholdIdle, screenBrighteningMinThresholdIdle);
@@ -995,8 +995,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.stop();
}
mAutomaticBrightnessController = new AutomaticBrightnessController(this,
handler.getLooper(), mSensorManager, mLightSensor,
mAutomaticBrightnessController = mInjector.getAutomaticBrightnessController(
this, handler.getLooper(), mSensorManager, mLightSensor,
mInteractiveModeBrightnessMapper, lightSensorWarmUpTimeConfig,
PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, dozeScaleFactor,
lightSensorRate, initialLightSensorRate, brighteningLightDebounce,
@@ -1094,7 +1094,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
public void onAnimationEnd() {
sendUpdatePowerState();
Message msg = mHandler.obtainMessage(MSG_BRIGHTNESS_RAMP_DONE);
mHandler.sendMessage(msg);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
};
@@ -2458,7 +2458,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
msg.what = MSG_STATSD_HBM_BRIGHTNESS;
msg.arg1 = Float.floatToIntBits(brightness);
msg.arg2 = mDisplayStatsId;
mHandler.sendMessageDelayed(msg, BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis()
+ BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
}
}
}
@@ -2589,7 +2590,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
@Override
public void onScreenOn() {
Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
mHandler.sendMessage(msg);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
}
@@ -2597,7 +2598,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
@Override
public void onScreenOff() {
Message msg = mHandler.obtainMessage(MSG_SCREEN_OFF_UNBLOCKED, this);
mHandler.sendMessage(msg);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
}
@@ -2671,6 +2672,58 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
looper, nudgeUpdatePowerState,
displayId, sensorManager, /* injector= */ null);
}
AutomaticBrightnessController getAutomaticBrightnessController(
AutomaticBrightnessController.Callbacks callbacks, Looper looper,
SensorManager sensorManager, Sensor lightSensor,
BrightnessMappingStrategy interactiveModeBrightnessMapper,
int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
boolean resetAmbientLuxAfterWarmUpConfig,
HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds,
HysteresisLevels ambientBrightnessThresholdsIdle,
HysteresisLevels screenBrightnessThresholdsIdle, Context context,
HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler,
BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
int ambientLightHorizonLong, float userLux, float userBrightness) {
return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor,
interactiveModeBrightnessMapper, lightSensorWarmUpTime, brightnessMin,
brightnessMax, dozeScaleFactor, lightSensorRate, initialLightSensorRate,
brighteningLightDebounceConfig, darkeningLightDebounceConfig,
resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds,
screenBrightnessThresholds, ambientBrightnessThresholdsIdle,
screenBrightnessThresholdsIdle, context, hbmController, brightnessThrottler,
idleModeBrightnessMapper, ambientLightHorizonShort, ambientLightHorizonLong,
userLux, userBrightness);
}
BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
DisplayDeviceConfig displayDeviceConfig,
DisplayWhiteBalanceController displayWhiteBalanceController) {
return BrightnessMappingStrategy.create(resources,
displayDeviceConfig, displayWhiteBalanceController);
}
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold) {
return new HysteresisLevels(brighteningThresholdsPercentages,
darkeningThresholdsPercentages, brighteningThresholdLevels,
darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold);
}
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
return new HysteresisLevels(brighteningThresholdsPercentages,
darkeningThresholdsPercentages, brighteningThresholdLevels,
darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold,
potentialOldBrightnessRange);
}
}
static class CachedBrightnessInfo {

View File

@@ -19,13 +19,14 @@ package com.android.server.display;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -41,6 +42,7 @@ import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemProperties;
import android.os.test.TestLooper;
import android.util.FloatProperty;
import android.view.Display;
@@ -55,6 +57,7 @@ import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.testutils.OffsettableClock;
@@ -77,13 +80,18 @@ import java.util.List;
public final class DisplayPowerController2Test {
private static final String UNIQUE_DISPLAY_ID = "unique_id_test123";
private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY;
private static final int FOLLOWER_DISPLAY_ID = Display.DEFAULT_DISPLAY + 1;
private MockitoSession mSession;
private OffsettableClock mClock;
private TestLooper mTestLooper;
private Handler mHandler;
private DisplayPowerController2.Injector mInjector;
private DisplayPowerController2.Injector mFollowerInjector;
private Context mContextSpy;
private DisplayPowerController2 mDpc;
private DisplayPowerController2 mFollowerDpc;
private Sensor mProxSensor;
@Mock
private DisplayPowerCallbacks mDisplayPowerCallbacksMock;
@@ -94,14 +102,22 @@ public final class DisplayPowerController2Test {
@Mock
private HighBrightnessModeMetadata mHighBrightnessModeMetadataMock;
@Mock
private HighBrightnessModeMetadata mFollowerHighBrightnessModeMetadataMock;
@Mock
private LogicalDisplay mLogicalDisplayMock;
@Mock
private LogicalDisplay mFollowerLogicalDisplayMock;
@Mock
private DisplayDevice mDisplayDeviceMock;
@Mock
private DisplayDevice mFollowerDisplayDeviceMock;
@Mock
private BrightnessTracker mBrightnessTrackerMock;
@Mock
private BrightnessSetting mBrightnessSettingMock;
@Mock
private BrightnessSetting mFollowerBrightnessSettingMock;
@Mock
private WindowManagerPolicy mWindowManagerPolicyMock;
@Mock
private PowerManager mPowerManagerMock;
@@ -110,10 +126,22 @@ public final class DisplayPowerController2Test {
@Mock
private DisplayDeviceConfig mDisplayDeviceConfigMock;
@Mock
private DisplayDeviceConfig mFollowerDisplayDeviceConfigMock;
@Mock
private DisplayPowerState mDisplayPowerStateMock;
@Mock
private DualRampAnimator<DisplayPowerState> mDualRampAnimatorMock;
@Mock
private DualRampAnimator<DisplayPowerState> mFollowerDualRampAnimatorMock;
@Mock
private AutomaticBrightnessController mAutomaticBrightnessControllerMock;
@Mock
private AutomaticBrightnessController mFollowerAutomaticBrightnessControllerMock;
@Mock
private BrightnessMappingStrategy mBrightnessMapperMock;
@Mock
private HysteresisLevels mHysteresisLevelsMock;
@Mock
private WakelockController mWakelockController;
@Mock
private ColorDisplayService.ColorDisplayServiceInternal mCdsiMock;
@@ -126,6 +154,7 @@ public final class DisplayPowerController2Test {
mSession = ExtendedMockito.mockitoSession()
.initMocks(this)
.strictness(Strictness.LENIENT)
.spyStatic(SystemProperties.class)
.spyStatic(LocalServices.class)
.spyStatic(BatteryStatsService.class)
.startMocking();
@@ -167,6 +196,113 @@ public final class DisplayPowerController2Test {
displayDeviceConfig, looper, nudgeUpdatePowerState, displayId,
sensorManager, /* injector= */ null);
}
@Override
AutomaticBrightnessController getAutomaticBrightnessController(
AutomaticBrightnessController.Callbacks callbacks, Looper looper,
SensorManager sensorManager, Sensor lightSensor,
BrightnessMappingStrategy interactiveModeBrightnessMapper,
int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
boolean resetAmbientLuxAfterWarmUpConfig,
HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds,
HysteresisLevels ambientBrightnessThresholdsIdle,
HysteresisLevels screenBrightnessThresholdsIdle, Context context,
HighBrightnessModeController hbmController,
BrightnessThrottler brightnessThrottler,
BrightnessMappingStrategy idleModeBrightnessMapper,
int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux,
float userBrightness) {
return mAutomaticBrightnessControllerMock;
}
@Override
BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
DisplayDeviceConfig displayDeviceConfig,
DisplayWhiteBalanceController displayWhiteBalanceController) {
return mBrightnessMapperMock;
}
@Override
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold) {
return mHysteresisLevelsMock;
}
@Override
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
return mHysteresisLevelsMock;
}
};
mFollowerInjector = new DisplayPowerController2.Injector() {
@Override
DisplayPowerController2.Clock getClock() {
return mClock::now;
}
@Override
DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
int displayId, int displayState) {
return mDisplayPowerStateMock;
}
@Override
DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
FloatProperty<DisplayPowerState> firstProperty,
FloatProperty<DisplayPowerState> secondProperty) {
return mFollowerDualRampAnimatorMock;
}
@Override
AutomaticBrightnessController getAutomaticBrightnessController(
AutomaticBrightnessController.Callbacks callbacks, Looper looper,
SensorManager sensorManager, Sensor lightSensor,
BrightnessMappingStrategy interactiveModeBrightnessMapper,
int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
boolean resetAmbientLuxAfterWarmUpConfig,
HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds,
HysteresisLevels ambientBrightnessThresholdsIdle,
HysteresisLevels screenBrightnessThresholdsIdle, Context context,
HighBrightnessModeController hbmController,
BrightnessThrottler brightnessThrottler,
BrightnessMappingStrategy idleModeBrightnessMapper,
int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux,
float userBrightness) {
return mFollowerAutomaticBrightnessControllerMock;
}
@Override
BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
DisplayDeviceConfig displayDeviceConfig,
DisplayWhiteBalanceController displayWhiteBalanceController) {
return mBrightnessMapperMock;
}
@Override
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold) {
return mHysteresisLevelsMock;
}
@Override
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
return mHysteresisLevelsMock;
}
};
addLocalServiceMock(WindowManagerPolicy.class, mWindowManagerPolicyMock);
@@ -174,11 +310,30 @@ public final class DisplayPowerController2Test {
when(mContextSpy.getSystemService(eq(PowerManager.class))).thenReturn(mPowerManagerMock);
when(mContextSpy.getResources()).thenReturn(mResourcesMock);
doAnswer((Answer<Void>) invocationOnMock -> null).when(() ->
SystemProperties.set(anyString(), any()));
doAnswer((Answer<ColorDisplayService.ColorDisplayServiceInternal>) invocationOnMock ->
mCdsiMock).when(() -> LocalServices.getService(
ColorDisplayService.ColorDisplayServiceInternal.class));
doAnswer((Answer<Void>) invocationOnMock -> null).when(() ->
BatteryStatsService.getService());
doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService);
setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID, mLogicalDisplayMock, mDisplayDeviceMock,
mDisplayDeviceConfigMock);
setUpDisplay(FOLLOWER_DISPLAY_ID, UNIQUE_DISPLAY_ID, mFollowerLogicalDisplayMock,
mFollowerDisplayDeviceMock, mFollowerDisplayDeviceConfigMock);
mProxSensor = setUpProxSensor();
mDpc = new DisplayPowerController2(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
}, mHighBrightnessModeMetadataMock);
mFollowerDpc = new DisplayPowerController2(
mContextSpy, mFollowerInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mFollowerLogicalDisplayMock,
mBrightnessTrackerMock, mFollowerBrightnessSettingMock, () -> {
}, mFollowerHighBrightnessModeMetadataMock);
}
@After
@@ -189,30 +344,20 @@ public final class DisplayPowerController2Test {
@Test
public void testReleaseProxSuspendBlockersOnExit() throws Exception {
setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID);
Sensor proxSensor = setUpProxSensor();
DisplayPowerController2 dpc = new DisplayPowerController2(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
}, mHighBrightnessModeMetadataMock);
when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
// send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true;
dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
mDpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
// Run updatePowerState to start listener for the prox sensor
advanceTime(1);
SensorEventListener listener = getSensorEventListener(proxSensor);
SensorEventListener listener = getSensorEventListener(mProxSensor);
assertNotNull(listener);
listener.onSensorChanged(TestUtils.createSensorEvent(proxSensor, 5 /* lux */));
listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, 5 /* lux */));
advanceTime(1);
// two times, one for unfinished business and one for proximity
@@ -221,8 +366,7 @@ public final class DisplayPowerController2Test {
verify(mWakelockController).acquireWakelock(
WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE);
dpc.stop();
mDpc.stop();
advanceTime(1);
// two times, one for unfinished business and one for proximity
verify(mWakelockController).acquireWakelock(
@@ -232,29 +376,19 @@ public final class DisplayPowerController2Test {
}
@Test
public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() throws Exception {
setUpDisplay(1, UNIQUE_DISPLAY_ID);
Sensor proxSensor = setUpProxSensor();
DisplayPowerController2 dpc = new DisplayPowerController2(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
}, mHighBrightnessModeMetadataMock);
public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() {
when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
// send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true;
dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
mFollowerDpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
// Run updatePowerState
advanceTime(1);
verify(mSensorManagerMock, never()).registerListener(any(SensorEventListener.class),
eq(proxSensor), anyInt(), any(Handler.class));
eq(mProxSensor), anyInt(), any(Handler.class));
}
/**
@@ -284,56 +418,158 @@ public final class DisplayPowerController2Test {
return mSensorEventListenerCaptor.getValue();
}
private void setUpDisplay(int displayId, String uniqueId) {
private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock,
DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
when(mLogicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(mLogicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(mDisplayDeviceMock);
when(mLogicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(mLogicalDisplayMock.isEnabledLocked()).thenReturn(true);
when(mLogicalDisplayMock.isInTransitionLocked()).thenReturn(false);
when(mDisplayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(mDisplayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(mDisplayDeviceMock.getDisplayDeviceConfig()).thenReturn(mDisplayDeviceConfigMock);
when(mDisplayDeviceConfigMock.getProximitySensor()).thenReturn(
when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(true);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
when(displayDeviceConfigMock.getProximitySensor()).thenReturn(
new DisplayDeviceConfig.SensorData() {
{
type = Sensor.STRING_TYPE_PROXIMITY;
name = null;
}
});
when(mDisplayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
when(displayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
when(displayDeviceConfigMock.isAutoBrightnessAvailable()).thenReturn(true);
when(displayDeviceConfigMock.getAmbientLightSensor()).thenReturn(
new DisplayDeviceConfig.SensorData());
when(displayDeviceConfigMock.getScreenOffBrightnessSensor()).thenReturn(
new DisplayDeviceConfig.SensorData());
}
@Test
public void testDisplayBrightnessFollowers() {
setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID);
public void testDisplayBrightnessFollowers_BothDpcsSupportNits() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
DisplayPowerController2 defaultDpc = new DisplayPowerController2(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
}, mHighBrightnessModeMetadataMock);
DisplayPowerController2 followerDpc = new DisplayPowerController2(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
}, mHighBrightnessModeMetadataMock);
ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture());
BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
defaultDpc.addDisplayBrightnessFollower(followerDpc);
mDpc.addDisplayBrightnessFollower(mFollowerDpc);
defaultDpc.setBrightness(0.3f);
assertEquals(defaultDpc.getBrightnessInfo().brightness,
followerDpc.getBrightnessInfo().brightness, 0);
// Test different float scale values
float leadBrightness = 0.3f;
float followerBrightness = 0.4f;
float nits = 300;
when(mAutomaticBrightnessControllerMock.convertToNits(leadBrightness)).thenReturn(nits);
when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(nits))
.thenReturn(followerBrightness);
when(mBrightnessSettingMock.getBrightness()).thenReturn(leadBrightness);
listener.onBrightnessChanged(leadBrightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(leadBrightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock).animateTo(eq(followerBrightness), anyFloat(),
anyFloat());
defaultDpc.setBrightness(0.6f);
assertEquals(defaultDpc.getBrightnessInfo().brightness,
followerDpc.getBrightnessInfo().brightness, 0);
clearInvocations(mDualRampAnimatorMock, mFollowerDualRampAnimatorMock);
float brightness = 0.1f;
defaultDpc.clearDisplayBrightnessFollowers();
defaultDpc.setBrightness(brightness);
assertNotEquals(brightness, followerDpc.getBrightnessInfo().brightness, 0);
// Test the same float scale value
float brightness = 0.6f;
nits = 600;
when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(nits);
when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(nits))
.thenReturn(brightness);
when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness);
listener.onBrightnessChanged(brightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
clearInvocations(mDualRampAnimatorMock, mFollowerDualRampAnimatorMock);
// Test clear followers
mDpc.clearDisplayBrightnessFollowers();
when(mBrightnessSettingMock.getBrightness()).thenReturn(leadBrightness);
listener.onBrightnessChanged(leadBrightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(leadBrightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock, never()).animateTo(eq(followerBrightness), anyFloat(),
anyFloat());
}
@Test
public void testDisplayBrightnessFollowers_FollowerDoesNotSupportNits() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture());
BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
mDpc.addDisplayBrightnessFollower(mFollowerDpc);
float brightness = 0.3f;
when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(300f);
when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(anyFloat()))
.thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness);
listener.onBrightnessChanged(brightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
}
@Test
public void testDisplayBrightnessFollowers_LeadDpcDoesNotSupportNits() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture());
BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
mDpc.addDisplayBrightnessFollower(mFollowerDpc);
float brightness = 0.3f;
when(mAutomaticBrightnessControllerMock.convertToNits(anyFloat())).thenReturn(-1f);
when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness);
listener.onBrightnessChanged(brightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
}
@Test
public void testDisplayBrightnessFollowers_NeitherDpcSupportsNits() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture());
BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
mDpc.addDisplayBrightnessFollower(mFollowerDpc);
float brightness = 0.3f;
when(mAutomaticBrightnessControllerMock.convertToNits(anyFloat())).thenReturn(-1f);
when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(anyFloat()))
.thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness);
listener.onBrightnessChanged(brightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
}
}

View File

@@ -19,14 +19,14 @@ package com.android.server.display;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -40,7 +40,9 @@ import android.hardware.SensorManager;
import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemProperties;
import android.os.test.TestLooper;
import android.util.FloatProperty;
import android.view.Display;
@@ -55,6 +57,7 @@ import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.testutils.OffsettableClock;
@@ -77,13 +80,18 @@ import java.util.List;
public final class DisplayPowerControllerTest {
private static final String UNIQUE_DISPLAY_ID = "unique_id_test123";
private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY;
private static final int FOLLOWER_DISPLAY_ID = Display.DEFAULT_DISPLAY + 1;
private MockitoSession mSession;
private OffsettableClock mClock;
private TestLooper mTestLooper;
private Handler mHandler;
private DisplayPowerController.Injector mInjector;
private DisplayPowerController.Injector mFollowerInjector;
private Context mContextSpy;
private DisplayPowerController mDpc;
private DisplayPowerController mFollowerDpc;
private Sensor mProxSensor;
@Mock
private DisplayPowerCallbacks mDisplayPowerCallbacksMock;
@@ -94,14 +102,22 @@ public final class DisplayPowerControllerTest {
@Mock
private LogicalDisplay mLogicalDisplayMock;
@Mock
private LogicalDisplay mFollowerLogicalDisplayMock;
@Mock
private DisplayDevice mDisplayDeviceMock;
@Mock
private DisplayDevice mFollowerDisplayDeviceMock;
@Mock
private HighBrightnessModeMetadata mHighBrightnessModeMetadataMock;
@Mock
private HighBrightnessModeMetadata mFollowerHighBrightnessModeMetadataMock;
@Mock
private BrightnessTracker mBrightnessTrackerMock;
@Mock
private BrightnessSetting mBrightnessSettingMock;
@Mock
private BrightnessSetting mFollowerBrightnessSettingMock;
@Mock
private WindowManagerPolicy mWindowManagerPolicyMock;
@Mock
private PowerManager mPowerManagerMock;
@@ -110,10 +126,22 @@ public final class DisplayPowerControllerTest {
@Mock
private DisplayDeviceConfig mDisplayDeviceConfigMock;
@Mock
private DisplayDeviceConfig mFollowerDisplayDeviceConfigMock;
@Mock
private DisplayPowerState mDisplayPowerStateMock;
@Mock
private DualRampAnimator<DisplayPowerState> mDualRampAnimatorMock;
@Mock
private DualRampAnimator<DisplayPowerState> mFollowerDualRampAnimatorMock;
@Mock
private AutomaticBrightnessController mAutomaticBrightnessControllerMock;
@Mock
private AutomaticBrightnessController mFollowerAutomaticBrightnessControllerMock;
@Mock
private BrightnessMappingStrategy mBrightnessMapperMock;
@Mock
private HysteresisLevels mHysteresisLevelsMock;
@Mock
private ColorDisplayService.ColorDisplayServiceInternal mCdsiMock;
@Captor
@@ -124,6 +152,7 @@ public final class DisplayPowerControllerTest {
mSession = ExtendedMockito.mockitoSession()
.initMocks(this)
.strictness(Strictness.LENIENT)
.spyStatic(SystemProperties.class)
.spyStatic(LocalServices.class)
.spyStatic(BatteryStatsService.class)
.startMocking();
@@ -149,6 +178,113 @@ public final class DisplayPowerControllerTest {
FloatProperty<DisplayPowerState> secondProperty) {
return mDualRampAnimatorMock;
}
@Override
AutomaticBrightnessController getAutomaticBrightnessController(
AutomaticBrightnessController.Callbacks callbacks, Looper looper,
SensorManager sensorManager, Sensor lightSensor,
BrightnessMappingStrategy interactiveModeBrightnessMapper,
int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
boolean resetAmbientLuxAfterWarmUpConfig,
HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds,
HysteresisLevels ambientBrightnessThresholdsIdle,
HysteresisLevels screenBrightnessThresholdsIdle, Context context,
HighBrightnessModeController hbmController,
BrightnessThrottler brightnessThrottler,
BrightnessMappingStrategy idleModeBrightnessMapper,
int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux,
float userBrightness) {
return mAutomaticBrightnessControllerMock;
}
@Override
BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
DisplayDeviceConfig displayDeviceConfig,
DisplayWhiteBalanceController displayWhiteBalanceController) {
return mBrightnessMapperMock;
}
@Override
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold) {
return mHysteresisLevelsMock;
}
@Override
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
return mHysteresisLevelsMock;
}
};
mFollowerInjector = new DisplayPowerController.Injector() {
@Override
DisplayPowerController.Clock getClock() {
return mClock::now;
}
@Override
DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
int displayId, int displayState) {
return mDisplayPowerStateMock;
}
@Override
DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
FloatProperty<DisplayPowerState> firstProperty,
FloatProperty<DisplayPowerState> secondProperty) {
return mFollowerDualRampAnimatorMock;
}
@Override
AutomaticBrightnessController getAutomaticBrightnessController(
AutomaticBrightnessController.Callbacks callbacks, Looper looper,
SensorManager sensorManager, Sensor lightSensor,
BrightnessMappingStrategy interactiveModeBrightnessMapper,
int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
boolean resetAmbientLuxAfterWarmUpConfig,
HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds,
HysteresisLevels ambientBrightnessThresholdsIdle,
HysteresisLevels screenBrightnessThresholdsIdle, Context context,
HighBrightnessModeController hbmController,
BrightnessThrottler brightnessThrottler,
BrightnessMappingStrategy idleModeBrightnessMapper,
int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux,
float userBrightness) {
return mFollowerAutomaticBrightnessControllerMock;
}
@Override
BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
DisplayDeviceConfig displayDeviceConfig,
DisplayWhiteBalanceController displayWhiteBalanceController) {
return mBrightnessMapperMock;
}
@Override
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold) {
return mHysteresisLevelsMock;
}
@Override
HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
float[] darkeningThresholdLevels, float minDarkeningThreshold,
float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
return mHysteresisLevelsMock;
}
};
addLocalServiceMock(WindowManagerPolicy.class, mWindowManagerPolicyMock);
@@ -156,11 +292,30 @@ public final class DisplayPowerControllerTest {
when(mContextSpy.getSystemService(eq(PowerManager.class))).thenReturn(mPowerManagerMock);
when(mContextSpy.getResources()).thenReturn(mResourcesMock);
doAnswer((Answer<Void>) invocationOnMock -> null).when(() ->
SystemProperties.set(anyString(), any()));
doAnswer((Answer<ColorDisplayService.ColorDisplayServiceInternal>) invocationOnMock ->
mCdsiMock).when(() -> LocalServices.getService(
ColorDisplayService.ColorDisplayServiceInternal.class));
doAnswer((Answer<Void>) invocationOnMock -> null).when(() ->
BatteryStatsService.getService());
ColorDisplayService.ColorDisplayServiceInternal.class));
doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService);
setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID, mLogicalDisplayMock, mDisplayDeviceMock,
mDisplayDeviceConfigMock);
setUpDisplay(FOLLOWER_DISPLAY_ID, UNIQUE_DISPLAY_ID, mFollowerLogicalDisplayMock,
mFollowerDisplayDeviceMock, mFollowerDisplayDeviceConfigMock);
mProxSensor = setUpProxSensor();
mDpc = new DisplayPowerController(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
}, mHighBrightnessModeMetadataMock);
mFollowerDpc = new DisplayPowerController(
mContextSpy, mFollowerInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mFollowerLogicalDisplayMock,
mBrightnessTrackerMock, mFollowerBrightnessSettingMock, () -> {
}, mFollowerHighBrightnessModeMetadataMock);
}
@After
@@ -171,72 +326,52 @@ public final class DisplayPowerControllerTest {
@Test
public void testReleaseProxSuspendBlockersOnExit() throws Exception {
setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID);
Sensor proxSensor = setUpProxSensor();
DisplayPowerController dpc = new DisplayPowerController(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
}, mHighBrightnessModeMetadataMock);
when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
// send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true;
dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
mDpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
// Run updatePowerState to start listener for the prox sensor
advanceTime(1);
SensorEventListener listener = getSensorEventListener(proxSensor);
SensorEventListener listener = getSensorEventListener(mProxSensor);
assertNotNull(listener);
listener.onSensorChanged(TestUtils.createSensorEvent(proxSensor, 5 /* lux */));
listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, 5 /* lux */));
advanceTime(1);
// two times, one for unfinished business and one for proximity
verify(mDisplayPowerCallbacksMock).acquireSuspendBlocker(
dpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
mDpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
verify(mDisplayPowerCallbacksMock).acquireSuspendBlocker(
dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
mDpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
dpc.stop();
mDpc.stop();
advanceTime(1);
// two times, one for unfinished business and one for proximity
verify(mDisplayPowerCallbacksMock).releaseSuspendBlocker(
dpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
mDpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
verify(mDisplayPowerCallbacksMock).releaseSuspendBlocker(
dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
mDpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
}
@Test
public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() throws Exception {
setUpDisplay(1, UNIQUE_DISPLAY_ID);
Sensor proxSensor = setUpProxSensor();
DisplayPowerController dpc = new DisplayPowerController(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
}, mHighBrightnessModeMetadataMock);
public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() {
when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
// send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true;
dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
mFollowerDpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
// Run updatePowerState
advanceTime(1);
verify(mSensorManagerMock, never()).registerListener(any(SensorEventListener.class),
eq(proxSensor), anyInt(), any(Handler.class));
eq(mProxSensor), anyInt(), any(Handler.class));
}
/**
@@ -266,56 +401,158 @@ public final class DisplayPowerControllerTest {
return mSensorEventListenerCaptor.getValue();
}
private void setUpDisplay(int displayId, String uniqueId) {
private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock,
DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
when(mLogicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(mLogicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(mDisplayDeviceMock);
when(mLogicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(mLogicalDisplayMock.isEnabledLocked()).thenReturn(true);
when(mLogicalDisplayMock.isInTransitionLocked()).thenReturn(false);
when(mDisplayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(mDisplayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(mDisplayDeviceMock.getDisplayDeviceConfig()).thenReturn(mDisplayDeviceConfigMock);
when(mDisplayDeviceConfigMock.getProximitySensor()).thenReturn(
when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(true);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
when(displayDeviceConfigMock.getProximitySensor()).thenReturn(
new DisplayDeviceConfig.SensorData() {
{
type = Sensor.STRING_TYPE_PROXIMITY;
name = null;
}
});
when(mDisplayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
when(displayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
when(displayDeviceConfigMock.isAutoBrightnessAvailable()).thenReturn(true);
when(displayDeviceConfigMock.getAmbientLightSensor()).thenReturn(
new DisplayDeviceConfig.SensorData());
when(displayDeviceConfigMock.getScreenOffBrightnessSensor()).thenReturn(
new DisplayDeviceConfig.SensorData());
}
@Test
public void testDisplayBrightnessFollowers() {
setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID);
public void testDisplayBrightnessFollowers_BothDpcsSupportNits() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
DisplayPowerController defaultDpc = new DisplayPowerController(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
}, mHighBrightnessModeMetadataMock);
DisplayPowerController followerDpc = new DisplayPowerController(
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
}, mHighBrightnessModeMetadataMock);
ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture());
BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
defaultDpc.addDisplayBrightnessFollower(followerDpc);
mDpc.addDisplayBrightnessFollower(mFollowerDpc);
defaultDpc.setBrightness(0.3f);
assertEquals(defaultDpc.getBrightnessInfo().brightness,
followerDpc.getBrightnessInfo().brightness, 0);
// Test different float scale values
float leadBrightness = 0.3f;
float followerBrightness = 0.4f;
float nits = 300;
when(mAutomaticBrightnessControllerMock.convertToNits(leadBrightness)).thenReturn(nits);
when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(nits))
.thenReturn(followerBrightness);
when(mBrightnessSettingMock.getBrightness()).thenReturn(leadBrightness);
listener.onBrightnessChanged(leadBrightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(leadBrightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock).animateTo(eq(followerBrightness), anyFloat(),
anyFloat());
defaultDpc.setBrightness(0.6f);
assertEquals(defaultDpc.getBrightnessInfo().brightness,
followerDpc.getBrightnessInfo().brightness, 0);
clearInvocations(mDualRampAnimatorMock, mFollowerDualRampAnimatorMock);
float brightness = 0.1f;
defaultDpc.clearDisplayBrightnessFollowers();
defaultDpc.setBrightness(brightness);
assertNotEquals(brightness, followerDpc.getBrightnessInfo().brightness, 0);
// Test the same float scale value
float brightness = 0.6f;
nits = 600;
when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(nits);
when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(nits))
.thenReturn(brightness);
when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness);
listener.onBrightnessChanged(brightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
clearInvocations(mDualRampAnimatorMock, mFollowerDualRampAnimatorMock);
// Test clear followers
mDpc.clearDisplayBrightnessFollowers();
when(mBrightnessSettingMock.getBrightness()).thenReturn(leadBrightness);
listener.onBrightnessChanged(leadBrightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(leadBrightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock, never()).animateTo(eq(followerBrightness), anyFloat(),
anyFloat());
}
@Test
public void testDisplayBrightnessFollowers_FollowerDoesNotSupportNits() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture());
BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
mDpc.addDisplayBrightnessFollower(mFollowerDpc);
float brightness = 0.3f;
when(mAutomaticBrightnessControllerMock.convertToNits(brightness)).thenReturn(300f);
when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(anyFloat()))
.thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness);
listener.onBrightnessChanged(brightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
}
@Test
public void testDisplayBrightnessFollowers_LeadDpcDoesNotSupportNits() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture());
BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
mDpc.addDisplayBrightnessFollower(mFollowerDpc);
float brightness = 0.3f;
when(mAutomaticBrightnessControllerMock.convertToNits(anyFloat())).thenReturn(-1f);
when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness);
listener.onBrightnessChanged(brightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
}
@Test
public void testDisplayBrightnessFollowers_NeitherDpcSupportsNits() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
mDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
mFollowerDpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
verify(mBrightnessSettingMock).registerListener(listenerCaptor.capture());
BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
mDpc.addDisplayBrightnessFollower(mFollowerDpc);
float brightness = 0.3f;
when(mAutomaticBrightnessControllerMock.convertToNits(anyFloat())).thenReturn(-1f);
when(mFollowerAutomaticBrightnessControllerMock.convertToFloatScale(anyFloat()))
.thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
when(mBrightnessSettingMock.getBrightness()).thenReturn(brightness);
listener.onBrightnessChanged(brightness);
advanceTime(1); // Send messages, run updatePowerState
verify(mDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
verify(mFollowerDualRampAnimatorMock).animateTo(eq(brightness), anyFloat(), anyFloat());
}
}