Don't register the binned brightness sensor for disabled displays

Bug: 267776127
Test: atest DisplayPowerControllerTest
Test: atest DisplayPowerController2Test
Change-Id: I3b1878c9f8fdee8cc21b4adf422afa7539cd84bd
(cherry picked from commit afae82a71d)
Merged-In: I3b1878c9f8fdee8cc21b4adf422afa7539cd84bd
This commit is contained in:
Piotr Wilczyński
2023-02-06 13:13:43 +00:00
parent 5d0abd461b
commit 7c182a2397
4 changed files with 436 additions and 60 deletions

View File

@@ -1193,17 +1193,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
loadScreenOffBrightnessSensor();
int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
// TODO (b/265793751): Don't instantiate ScreenOffBrightnessSensorController if this is
// a complementary display
if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
mScreenOffBrightnessSensorController = new ScreenOffBrightnessSensorController(
mSensorManager,
mScreenOffBrightnessSensor,
mHandler,
SystemClock::uptimeMillis,
sensorValueToLux,
mInteractiveModeBrightnessMapper
);
mScreenOffBrightnessSensorController =
mInjector.getScreenOffBrightnessSensorController(
mSensorManager,
mScreenOffBrightnessSensor,
mHandler,
SystemClock::uptimeMillis,
sensorValueToLux,
mInteractiveModeBrightnessMapper);
}
} else {
mUseSoftwareAutoBrightnessConfig = false;
@@ -1395,8 +1393,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.setLightSensorEnabled(mUseAutoBrightness
&& (state == Display.STATE_OFF || (state == Display.STATE_DOZE
&& !mAllowAutoBrightnessWhileDozingConfig)));
&& mIsEnabled && (state == Display.STATE_OFF || (state == Display.STATE_DOZE
&& !mAllowAutoBrightnessWhileDozingConfig))
&& mLeadDisplayId == Layout.NO_LEAD_DISPLAY);
}
boolean skipRampBecauseOfProximityChangeToNegative = false;
@@ -2544,11 +2543,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
mHandler.post(() -> {
mHandler.postAtTime(() -> {
mUseAutoBrightness = screenBrightnessModeSetting
== Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
updatePowerState();
});
}, mClock.uptimeMillis());
}
private float getAutoBrightnessAdjustmentSetting() {
@@ -3446,6 +3445,23 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold,
potentialOldBrightnessRange);
}
ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
SensorManager sensorManager,
Sensor lightSensor,
Handler handler,
ScreenOffBrightnessSensorController.Clock clock,
int[] sensorValueToLux,
BrightnessMappingStrategy brightnessMapper) {
return new ScreenOffBrightnessSensorController(
sensorManager,
lightSensor,
handler,
clock,
sensorValueToLux,
brightnessMapper
);
}
}
static class CachedBrightnessInfo {

View File

@@ -1030,17 +1030,15 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
loadScreenOffBrightnessSensor();
int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
// TODO (b/265793751): Don't instantiate ScreenOffBrightnessSensorController if this is
// a complementary display
if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
mScreenOffBrightnessSensorController = new ScreenOffBrightnessSensorController(
mSensorManager,
mScreenOffBrightnessSensor,
mHandler,
SystemClock::uptimeMillis,
sensorValueToLux,
mInteractiveModeBrightnessMapper
);
mScreenOffBrightnessSensorController =
mInjector.getScreenOffBrightnessSensorController(
mSensorManager,
mScreenOffBrightnessSensor,
mHandler,
SystemClock::uptimeMillis,
sensorValueToLux,
mInteractiveModeBrightnessMapper);
}
} else {
mUseSoftwareAutoBrightnessConfig = false;
@@ -1189,8 +1187,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.setLightSensorEnabled(mUseAutoBrightness
&& (state == Display.STATE_OFF || (state == Display.STATE_DOZE
&& !mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig())));
&& mIsEnabled && (state == Display.STATE_OFF || (state == Display.STATE_DOZE
&& !mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig()))
&& mLeadDisplayId == Layout.NO_LEAD_DISPLAY);
}
// Initialize things the first time the power state is changed.
@@ -2150,11 +2149,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
mHandler.post(() -> {
mHandler.postAtTime(() -> {
mUseAutoBrightness = screenBrightnessModeSetting
== Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
updatePowerState();
});
}, mClock.uptimeMillis());
}
private float getAutoBrightnessAdjustmentSetting() {
@@ -2924,6 +2923,23 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold,
potentialOldBrightnessRange);
}
ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
SensorManager sensorManager,
Sensor lightSensor,
Handler handler,
ScreenOffBrightnessSensorController.Clock clock,
int[] sensorValueToLux,
BrightnessMappingStrategy brightnessMapper) {
return new ScreenOffBrightnessSensorController(
sensorManager,
lightSensor,
handler,
clock,
sensorValueToLux,
brightnessMapper
);
}
}
static class CachedBrightnessInfo {

View File

@@ -26,12 +26,15 @@ 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.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
@@ -44,7 +47,9 @@ import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.test.TestLooper;
import android.provider.Settings;
import android.util.FloatProperty;
import android.view.Display;
import android.view.DisplayInfo;
@@ -57,6 +62,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.policy.WindowManagerPolicy;
@@ -122,6 +128,7 @@ public final class DisplayPowerController2Test {
.spyStatic(SystemProperties.class)
.spyStatic(LocalServices.class)
.spyStatic(BatteryStatsService.class)
.spyStatic(Settings.System.class)
.startMocking();
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
mClock = new OffsettableClock.Stopped();
@@ -139,8 +146,7 @@ public final class DisplayPowerController2Test {
ColorDisplayService.ColorDisplayServiceInternal.class));
doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService);
mProxSensor = setUpProxSensor();
setUpSensors();
mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
}
@@ -169,7 +175,7 @@ public final class DisplayPowerController2Test {
advanceTime(1);
// two times, one for unfinished business and one for proximity
verify(mHolder.wakelockController).acquireWakelock(
verify(mHolder.wakelockController, times(2)).acquireWakelock(
WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
verify(mHolder.wakelockController).acquireWakelock(
WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE);
@@ -177,7 +183,7 @@ public final class DisplayPowerController2Test {
mHolder.dpc.stop();
advanceTime(1);
// two times, one for unfinished business and one for proximity
verify(mHolder.wakelockController).acquireWakelock(
verify(mHolder.wakelockController, times(2)).acquireWakelock(
WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
verify(mHolder.wakelockController).acquireWakelock(
WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE);
@@ -214,12 +220,13 @@ public final class DisplayPowerController2Test {
mTestLooper.dispatchAll();
}
private Sensor setUpProxSensor() throws Exception {
Sensor proxSensor = TestUtils.createSensor(
private void setUpSensors() throws Exception {
mProxSensor = TestUtils.createSensor(
Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY);
Sensor screenOffBrightnessSensor = TestUtils.createSensor(
Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL)))
.thenReturn(List.of(proxSensor));
return proxSensor;
.thenReturn(List.of(mProxSensor, screenOffBrightnessSensor));
}
private SensorEventListener getSensorEventListener(Sensor sensor) {
@@ -229,14 +236,15 @@ public final class DisplayPowerController2Test {
}
private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock,
DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock) {
DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock,
boolean isEnabled) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(true);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
@@ -253,7 +261,14 @@ public final class DisplayPowerController2Test {
when(displayDeviceConfigMock.getAmbientLightSensor()).thenReturn(
new DisplayDeviceConfig.SensorData());
when(displayDeviceConfigMock.getScreenOffBrightnessSensor()).thenReturn(
new DisplayDeviceConfig.SensorData());
new DisplayDeviceConfig.SensorData() {
{
type = Sensor.STRING_TYPE_LIGHT;
name = null;
}
});
when(displayDeviceConfigMock.getScreenOffBrightnessSensorValueToLux())
.thenReturn(new int[0]);
}
@Test
@@ -466,7 +481,7 @@ public final class DisplayPowerController2Test {
DisplayPowerRequest dpr = new DisplayPowerRequest();
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1);
verify(mHolder.displayPowerState).setScreenState(anyInt());
verify(mHolder.displayPowerState, times(2)).setScreenState(anyInt());
mHolder = createDisplayPowerController(42, UNIQUE_ID);
@@ -479,8 +494,145 @@ public final class DisplayPowerController2Test {
verify(mHolder.displayPowerState).setScreenState(anyInt());
}
@Test
public void testSetScreenOffBrightnessSensorEnabled_DisplayIsOff() {
doAnswer((Answer<Integer>) invocationOnMock ->
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
.when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
eq(UserHandle.USER_CURRENT)));
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_OFF;
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(true);
// The display turns on and we use the brightness value recommended by
// ScreenOffBrightnessSensorController
clearInvocations(mHolder.screenOffBrightnessSensorController);
float brightness = 0.14f;
when(mHolder.screenOffBrightnessSensorController.getAutomaticScreenBrightness())
.thenReturn(brightness);
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.getAutomaticScreenBrightness();
verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
}
@Test
public void testSetScreenOffBrightnessSensorEnabled_DisplayIsInDoze() {
doAnswer((Answer<Integer>) invocationOnMock ->
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
.when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
eq(UserHandle.USER_CURRENT)));
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_DOZE;
when(mResourcesMock.getBoolean(
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing))
.thenReturn(true);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(true);
// The display turns on and we use the brightness value recommended by
// ScreenOffBrightnessSensorController
clearInvocations(mHolder.screenOffBrightnessSensorController);
float brightness = 0.14f;
when(mHolder.screenOffBrightnessSensorController.getAutomaticScreenBrightness())
.thenReturn(brightness);
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.getAutomaticScreenBrightness();
verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
}
@Test
public void testSetScreenOffBrightnessSensorDisabled_AutoBrightnessIsDisabled() {
doAnswer((Answer<Integer>) invocationOnMock ->
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL)
.when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
eq(UserHandle.USER_CURRENT)));
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_OFF;
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(false);
}
@Test
public void testSetScreenOffBrightnessSensorDisabled_DisplayIsDisabled() {
doAnswer((Answer<Integer>) invocationOnMock ->
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
.when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
eq(UserHandle.USER_CURRENT)));
mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID, /* isEnabled= */ false);
DisplayPowerRequest dpr = new DisplayPowerRequest();
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(false);
}
@Test
public void testSetScreenOffBrightnessSensorDisabled_DisplayIsOn() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(false);
}
@Test
public void testSetScreenOffBrightnessSensorDisabled_DisplayIsAFollower() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_OFF;
mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, /* leadDisplayId= */ 42);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(false);
}
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId) {
return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
}
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId, boolean isEnabled) {
final DisplayPowerState displayPowerState = mock(DisplayPowerState.class);
final DualRampAnimator<DisplayPowerState> animator = mock(DualRampAnimator.class);
final AutomaticBrightnessController automaticBrightnessController =
@@ -489,10 +641,12 @@ public final class DisplayPowerController2Test {
final BrightnessMappingStrategy brightnessMappingStrategy =
mock(BrightnessMappingStrategy.class);
final HysteresisLevels hysteresisLevels = mock(HysteresisLevels.class);
final ScreenOffBrightnessSensorController screenOffBrightnessSensorController =
mock(ScreenOffBrightnessSensorController.class);
TestInjector injector = new TestInjector(displayPowerState, animator,
automaticBrightnessController, wakelockController, brightnessMappingStrategy,
hysteresisLevels);
hysteresisLevels, screenOffBrightnessSensorController);
final LogicalDisplay display = mock(LogicalDisplay.class);
final DisplayDevice device = mock(DisplayDevice.class);
@@ -500,7 +654,7 @@ public final class DisplayPowerController2Test {
final BrightnessSetting brightnessSetting = mock(BrightnessSetting.class);
final DisplayDeviceConfig config = mock(DisplayDeviceConfig.class);
setUpDisplay(displayId, uniqueId, display, device, config);
setUpDisplay(displayId, uniqueId, display, device, config, isEnabled);
final DisplayPowerController2 dpc = new DisplayPowerController2(
mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler,
@@ -509,7 +663,8 @@ public final class DisplayPowerController2Test {
hbmMetadata, /* bootCompleted= */ false);
return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
automaticBrightnessController, wakelockController);
automaticBrightnessController, wakelockController,
screenOffBrightnessSensorController, hbmMetadata);
}
/**
@@ -523,18 +678,24 @@ public final class DisplayPowerController2Test {
public final DualRampAnimator<DisplayPowerState> animator;
public final AutomaticBrightnessController automaticBrightnessController;
public final WakelockController wakelockController;
public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
public final HighBrightnessModeMetadata hbmMetadata;
DisplayPowerControllerHolder(DisplayPowerController2 dpc,
DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController,
WakelockController wakelockController) {
WakelockController wakelockController,
ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
HighBrightnessModeMetadata hbmMetadata) {
this.dpc = dpc;
this.displayPowerState = displayPowerState;
this.brightnessSetting = brightnessSetting;
this.animator = animator;
this.automaticBrightnessController = automaticBrightnessController;
this.wakelockController = wakelockController;
this.screenOffBrightnessSensorController = screenOffBrightnessSensorController;
this.hbmMetadata = hbmMetadata;
}
}
@@ -545,18 +706,21 @@ public final class DisplayPowerController2Test {
private final WakelockController mWakelockController;
private final BrightnessMappingStrategy mBrightnessMappingStrategy;
private final HysteresisLevels mHysteresisLevels;
private final ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController,
WakelockController wakelockController,
BrightnessMappingStrategy brightnessMappingStrategy,
HysteresisLevels hysteresisLevels) {
HysteresisLevels hysteresisLevels,
ScreenOffBrightnessSensorController screenOffBrightnessSensorController) {
mDisplayPowerState = dps;
mAnimator = animator;
mAutomaticBrightnessController = automaticBrightnessController;
mWakelockController = wakelockController;
mBrightnessMappingStrategy = brightnessMappingStrategy;
mHysteresisLevels = hysteresisLevels;
mScreenOffBrightnessSensorController = screenOffBrightnessSensorController;
}
@Override
@@ -636,5 +800,13 @@ public final class DisplayPowerController2Test {
float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
return mHysteresisLevels;
}
@Override
ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
SensorManager sensorManager, Sensor lightSensor, Handler handler,
ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux,
BrightnessMappingStrategy brightnessMapper) {
return mScreenOffBrightnessSensorController;
}
}
}

View File

@@ -26,12 +26,15 @@ 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.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
@@ -44,7 +47,9 @@ import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.test.TestLooper;
import android.provider.Settings;
import android.util.FloatProperty;
import android.view.Display;
import android.view.DisplayInfo;
@@ -57,6 +62,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.policy.WindowManagerPolicy;
@@ -122,6 +128,7 @@ public final class DisplayPowerControllerTest {
.spyStatic(SystemProperties.class)
.spyStatic(LocalServices.class)
.spyStatic(BatteryStatsService.class)
.spyStatic(Settings.System.class)
.startMocking();
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
mClock = new OffsettableClock.Stopped();
@@ -140,8 +147,7 @@ public final class DisplayPowerControllerTest {
ColorDisplayService.ColorDisplayServiceInternal.class));
doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService);
mProxSensor = setUpProxSensor();
setUpSensors();
mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
}
@@ -217,12 +223,13 @@ public final class DisplayPowerControllerTest {
mTestLooper.dispatchAll();
}
private Sensor setUpProxSensor() throws Exception {
Sensor proxSensor = TestUtils.createSensor(
private void setUpSensors() throws Exception {
mProxSensor = TestUtils.createSensor(
Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY);
Sensor screenOffBrightnessSensor = TestUtils.createSensor(
Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL)))
.thenReturn(List.of(proxSensor));
return proxSensor;
.thenReturn(List.of(mProxSensor, screenOffBrightnessSensor));
}
private SensorEventListener getSensorEventListener(Sensor sensor) {
@@ -232,14 +239,15 @@ public final class DisplayPowerControllerTest {
}
private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock,
DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock) {
DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock,
boolean isEnabled) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(true);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
@@ -256,7 +264,14 @@ public final class DisplayPowerControllerTest {
when(displayDeviceConfigMock.getAmbientLightSensor()).thenReturn(
new DisplayDeviceConfig.SensorData());
when(displayDeviceConfigMock.getScreenOffBrightnessSensor()).thenReturn(
new DisplayDeviceConfig.SensorData());
new DisplayDeviceConfig.SensorData() {
{
type = Sensor.STRING_TYPE_LIGHT;
name = null;
}
});
when(displayDeviceConfigMock.getScreenOffBrightnessSensorValueToLux())
.thenReturn(new int[0]);
}
@Test
@@ -470,7 +485,7 @@ public final class DisplayPowerControllerTest {
DisplayPowerRequest dpr = new DisplayPowerRequest();
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1);
verify(mHolder.displayPowerState).setScreenState(anyInt());
verify(mHolder.displayPowerState, times(2)).setScreenState(anyInt());
mHolder = createDisplayPowerController(42, UNIQUE_ID);
@@ -483,8 +498,145 @@ public final class DisplayPowerControllerTest {
verify(mHolder.displayPowerState).setScreenState(anyInt());
}
@Test
public void testSetScreenOffBrightnessSensorEnabled_DisplayIsOff() {
doAnswer((Answer<Integer>) invocationOnMock ->
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
.when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
eq(UserHandle.USER_CURRENT)));
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_OFF;
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(true);
// The display turns on and we use the brightness value recommended by
// ScreenOffBrightnessSensorController
clearInvocations(mHolder.screenOffBrightnessSensorController);
float brightness = 0.14f;
when(mHolder.screenOffBrightnessSensorController.getAutomaticScreenBrightness())
.thenReturn(brightness);
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.getAutomaticScreenBrightness();
verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
}
@Test
public void testSetScreenOffBrightnessSensorEnabled_DisplayIsInDoze() {
doAnswer((Answer<Integer>) invocationOnMock ->
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
.when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
eq(UserHandle.USER_CURRENT)));
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_DOZE;
when(mResourcesMock.getBoolean(
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing))
.thenReturn(true);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(true);
// The display turns on and we use the brightness value recommended by
// ScreenOffBrightnessSensorController
clearInvocations(mHolder.screenOffBrightnessSensorController);
float brightness = 0.14f;
when(mHolder.screenOffBrightnessSensorController.getAutomaticScreenBrightness())
.thenReturn(brightness);
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.getAutomaticScreenBrightness();
verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
}
@Test
public void testSetScreenOffBrightnessSensorDisabled_AutoBrightnessIsDisabled() {
doAnswer((Answer<Integer>) invocationOnMock ->
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL)
.when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
eq(UserHandle.USER_CURRENT)));
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_OFF;
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(false);
}
@Test
public void testSetScreenOffBrightnessSensorDisabled_DisplayIsDisabled() {
doAnswer((Answer<Integer>) invocationOnMock ->
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
.when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
eq(UserHandle.USER_CURRENT)));
mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID, /* isEnabled= */ false);
DisplayPowerRequest dpr = new DisplayPowerRequest();
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(false);
}
@Test
public void testSetScreenOffBrightnessSensorDisabled_DisplayIsOn() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(false);
}
@Test
public void testSetScreenOffBrightnessSensorDisabled_DisplayIsAFollower() {
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_OFF;
mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, /* leadDisplayId= */ 42);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
.setLightSensorEnabled(false);
}
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId) {
return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
}
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId, boolean isEnabled) {
final DisplayPowerState displayPowerState = mock(DisplayPowerState.class);
final DualRampAnimator<DisplayPowerState> animator = mock(DualRampAnimator.class);
final AutomaticBrightnessController automaticBrightnessController =
@@ -492,9 +644,12 @@ public final class DisplayPowerControllerTest {
final BrightnessMappingStrategy brightnessMappingStrategy =
mock(BrightnessMappingStrategy.class);
final HysteresisLevels hysteresisLevels = mock(HysteresisLevels.class);
final ScreenOffBrightnessSensorController screenOffBrightnessSensorController =
mock(ScreenOffBrightnessSensorController.class);
DisplayPowerController.Injector injector = new TestInjector(displayPowerState, animator,
automaticBrightnessController, brightnessMappingStrategy, hysteresisLevels);
automaticBrightnessController, brightnessMappingStrategy, hysteresisLevels,
screenOffBrightnessSensorController);
final LogicalDisplay display = mock(LogicalDisplay.class);
final DisplayDevice device = mock(DisplayDevice.class);
@@ -502,7 +657,7 @@ public final class DisplayPowerControllerTest {
final BrightnessSetting brightnessSetting = mock(BrightnessSetting.class);
final DisplayDeviceConfig config = mock(DisplayDeviceConfig.class);
setUpDisplay(displayId, uniqueId, display, device, config);
setUpDisplay(displayId, uniqueId, display, device, config, isEnabled);
final DisplayPowerController dpc = new DisplayPowerController(
mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler,
@@ -511,7 +666,7 @@ public final class DisplayPowerControllerTest {
hbmMetadata, /* bootCompleted= */ false);
return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
automaticBrightnessController);
automaticBrightnessController, screenOffBrightnessSensorController, hbmMetadata);
}
/**
@@ -524,16 +679,22 @@ public final class DisplayPowerControllerTest {
public final BrightnessSetting brightnessSetting;
public final DualRampAnimator<DisplayPowerState> animator;
public final AutomaticBrightnessController automaticBrightnessController;
public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
public final HighBrightnessModeMetadata hbmMetadata;
DisplayPowerControllerHolder(DisplayPowerController dpc,
DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController) {
AutomaticBrightnessController automaticBrightnessController,
ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
HighBrightnessModeMetadata hbmMetadata) {
this.dpc = dpc;
this.displayPowerState = displayPowerState;
this.brightnessSetting = brightnessSetting;
this.animator = animator;
this.automaticBrightnessController = automaticBrightnessController;
this.screenOffBrightnessSensorController = screenOffBrightnessSensorController;
this.hbmMetadata = hbmMetadata;
}
}
@@ -543,16 +704,19 @@ public final class DisplayPowerControllerTest {
private final AutomaticBrightnessController mAutomaticBrightnessController;
private final BrightnessMappingStrategy mBrightnessMappingStrategy;
private final HysteresisLevels mHysteresisLevels;
private final ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController,
BrightnessMappingStrategy brightnessMappingStrategy,
HysteresisLevels hysteresisLevels) {
HysteresisLevels hysteresisLevels,
ScreenOffBrightnessSensorController screenOffBrightnessSensorController) {
mDisplayPowerState = dps;
mAnimator = animator;
mAutomaticBrightnessController = automaticBrightnessController;
mBrightnessMappingStrategy = brightnessMappingStrategy;
mHysteresisLevels = hysteresisLevels;
mScreenOffBrightnessSensorController = screenOffBrightnessSensorController;
}
@Override
@@ -616,5 +780,13 @@ public final class DisplayPowerControllerTest {
float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
return mHysteresisLevels;
}
@Override
ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
SensorManager sensorManager, Sensor lightSensor, Handler handler,
ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux,
BrightnessMappingStrategy brightnessMapper) {
return mScreenOffBrightnessSensorController;
}
}
}