Report negative proximity if we lose the prox sensor

Bug: 265612914
Test: Start a phone call, cover the prox sensor so the screen turns off, perform a state transition so that we no longer have a prox sensor, see that the screen turns back on.
Test: atest DisplayPowerControllerTest
Test: atest DisplayPowerController2Test
Test: atest DisplayPowerProximityStateControllerTest
Change-Id: I01e7c8ad2a5dc8fb9e01aa6e9622d2b4dbd812df
This commit is contained in:
Piotr Wilczyński
2023-03-07 15:44:24 +00:00
parent dd887408f2
commit e08fd8c10d
5 changed files with 192 additions and 15 deletions

View File

@@ -1441,8 +1441,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
sendOnProximityNegativeWithWakelock(); sendOnProximityNegativeWithWakelock();
} }
} else { } else {
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false; mWaitingForNegativeProximity = false;
mIgnoreProximityUntilChanged = false; mIgnoreProximityUntilChanged = false;
if (mScreenOffBecauseOfProximity) {
// The screen *was* off due to prox being near, but now there's no prox sensor, so
// let's turn the screen back on.
mScreenOffBecauseOfProximity = false;
skipRampBecauseOfProximityChangeToNegative = true;
sendOnProximityNegativeWithWakelock();
}
} }
if (!mIsEnabled if (!mIsEnabled

View File

@@ -262,8 +262,17 @@ public final class DisplayPowerProximityStateController {
sendOnProximityNegativeWithWakelock(); sendOnProximityNegativeWithWakelock();
} }
} else { } else {
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false; mWaitingForNegativeProximity = false;
mIgnoreProximityUntilChanged = false; mIgnoreProximityUntilChanged = false;
if (mScreenOffBecauseOfProximity) {
// The screen *was* off due to prox being near, but now there's no prox sensor, so
// let's turn the screen back on.
mScreenOffBecauseOfProximity = false;
mSkipRampBecauseOfProximityChangeToNegative = true;
sendOnProximityNegativeWithWakelock();
}
} }
} }

View File

@@ -30,6 +30,7 @@ import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -92,6 +93,7 @@ public final class DisplayPowerController2Test {
private static final String FOLLOWER_UNIQUE_ID = "unique_id_456"; private static final String FOLLOWER_UNIQUE_ID = "unique_id_456";
private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1; private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1;
private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789"; private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789";
private static final float PROX_SENSOR_MAX_RANGE = 5;
private MockitoSession mSession; private MockitoSession mSession;
private OffsettableClock mClock; private OffsettableClock mClock;
@@ -160,7 +162,7 @@ public final class DisplayPowerController2Test {
@Test @Test
public void testReleaseProxSuspendBlockersOnExit() throws Exception { public void testReleaseProxSuspendBlockersOnExit() throws Exception {
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON); when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
// send a display power request // Send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest(); DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT; dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true; dpr.useProximitySensor = true;
@@ -172,7 +174,7 @@ public final class DisplayPowerController2Test {
SensorEventListener listener = getSensorEventListener(mProxSensor); SensorEventListener listener = getSensorEventListener(mProxSensor);
assertNotNull(listener); assertNotNull(listener);
listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, 5 /* lux */)); listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 5));
advanceTime(1); advanceTime(1);
// two times, one for unfinished business and one for proximity // two times, one for unfinished business and one for proximity
@@ -190,6 +192,83 @@ public final class DisplayPowerController2Test {
WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE); WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE);
} }
@Test
public void testScreenOffBecauseOfProximity() throws Exception {
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
// Send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true;
mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
// Run updatePowerState to start listener for the prox sensor
advanceTime(1);
SensorEventListener listener = getSensorEventListener(mProxSensor);
assertNotNull(listener);
// Send a positive proximity event
listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 1));
advanceTime(1);
// The display should have been turned off
verify(mHolder.displayPowerState).setScreenState(Display.STATE_OFF);
clearInvocations(mHolder.displayPowerState);
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
// Send a negative proximity event
listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor,
(int) PROX_SENSOR_MAX_RANGE + 1));
// Advance time by less than PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY
advanceTime(1);
// The prox sensor is debounced so the display should not have been turned back on yet
verify(mHolder.displayPowerState, never()).setScreenState(Display.STATE_ON);
// Advance time by more than PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY
advanceTime(1000);
// The display should have been turned back on
verify(mHolder.displayPowerState).setScreenState(Display.STATE_ON);
}
@Test
public void testScreenOffBecauseOfProximity_ProxSensorGone() throws Exception {
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
// Send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true;
mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
// Run updatePowerState to start listener for the prox sensor
advanceTime(1);
SensorEventListener listener = getSensorEventListener(mProxSensor);
assertNotNull(listener);
// Send a positive proximity event
listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 1));
advanceTime(1);
// The display should have been turned off
verify(mHolder.displayPowerState).setScreenState(Display.STATE_OFF);
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
// The display device changes and we no longer have a prox sensor
reset(mSensorManagerMock);
setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
advanceTime(1); // Run updatePowerState
// The display should have been turned back on and the listener should have been
// unregistered
verify(mHolder.displayPowerState).setScreenState(Display.STATE_ON);
verify(mSensorManagerMock).unregisterListener(listener);
}
@Test @Test
public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() { public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() {
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON); when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
@@ -222,8 +301,8 @@ public final class DisplayPowerController2Test {
} }
private void setUpSensors() throws Exception { private void setUpSensors() throws Exception {
mProxSensor = TestUtils.createSensor( mProxSensor = TestUtils.createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY,
Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY); PROX_SENSOR_MAX_RANGE);
Sensor screenOffBrightnessSensor = TestUtils.createSensor( Sensor screenOffBrightnessSensor = TestUtils.createSensor(
Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT); Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL))) when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL)))
@@ -773,7 +852,13 @@ public final class DisplayPowerController2Test {
SensorManager sensorManager) { SensorManager sensorManager) {
return new DisplayPowerProximityStateController(wakelockController, return new DisplayPowerProximityStateController(wakelockController,
displayDeviceConfig, looper, nudgeUpdatePowerState, displayId, displayDeviceConfig, looper, nudgeUpdatePowerState, displayId,
sensorManager, /* injector= */ null); sensorManager,
new DisplayPowerProximityStateController.Injector() {
@Override
DisplayPowerProximityStateController.Clock createClock() {
return mClock::now;
}
});
} }
@Override @Override

View File

@@ -30,6 +30,7 @@ import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -92,6 +93,7 @@ public final class DisplayPowerControllerTest {
private static final String FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_456"; private static final String FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_456";
private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1; private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1;
private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789"; private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789";
private static final float PROX_SENSOR_MAX_RANGE = 5;
private MockitoSession mSession; private MockitoSession mSession;
private OffsettableClock mClock; private OffsettableClock mClock;
@@ -161,7 +163,7 @@ public final class DisplayPowerControllerTest {
@Test @Test
public void testReleaseProxSuspendBlockersOnExit() throws Exception { public void testReleaseProxSuspendBlockersOnExit() throws Exception {
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON); when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
// send a display power request // Send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest(); DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT; dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true; dpr.useProximitySensor = true;
@@ -173,7 +175,7 @@ public final class DisplayPowerControllerTest {
SensorEventListener listener = getSensorEventListener(mProxSensor); SensorEventListener listener = getSensorEventListener(mProxSensor);
assertNotNull(listener); assertNotNull(listener);
listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, 5 /* lux */)); listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 5));
advanceTime(1); advanceTime(1);
// two times, one for unfinished business and one for proximity // two times, one for unfinished business and one for proximity
@@ -192,6 +194,83 @@ public final class DisplayPowerControllerTest {
mHolder.dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID)); mHolder.dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
} }
@Test
public void testScreenOffBecauseOfProximity() throws Exception {
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
// Send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true;
mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
// Run updatePowerState to start listener for the prox sensor
advanceTime(1);
SensorEventListener listener = getSensorEventListener(mProxSensor);
assertNotNull(listener);
// Send a positive proximity event
listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 1));
advanceTime(1);
// The display should have been turned off
verify(mHolder.displayPowerState).setScreenState(Display.STATE_OFF);
clearInvocations(mHolder.displayPowerState);
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
// Send a negative proximity event
listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor,
(int) PROX_SENSOR_MAX_RANGE + 1));
// Advance time by less than PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY
advanceTime(1);
// The prox sensor is debounced so the display should not have been turned back on yet
verify(mHolder.displayPowerState, never()).setScreenState(Display.STATE_ON);
// Advance time by more than PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY
advanceTime(1000);
// The display should have been turned back on
verify(mHolder.displayPowerState).setScreenState(Display.STATE_ON);
}
@Test
public void testScreenOffBecauseOfProximity_ProxSensorGone() throws Exception {
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
// Send a display power request
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
dpr.useProximitySensor = true;
mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
// Run updatePowerState to start listener for the prox sensor
advanceTime(1);
SensorEventListener listener = getSensorEventListener(mProxSensor);
assertNotNull(listener);
// Send a positive proximity event
listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 1));
advanceTime(1);
// The display should have been turned off
verify(mHolder.displayPowerState).setScreenState(Display.STATE_OFF);
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
// The display device changes and we no longer have a prox sensor
reset(mSensorManagerMock);
setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
advanceTime(1); // Run updatePowerState
// The display should have been turned back on and the listener should have been
// unregistered
verify(mHolder.displayPowerState).setScreenState(Display.STATE_ON);
verify(mSensorManagerMock).unregisterListener(listener);
}
@Test @Test
public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() { public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() {
DisplayPowerControllerHolder followerDpc = DisplayPowerControllerHolder followerDpc =
@@ -225,8 +304,8 @@ public final class DisplayPowerControllerTest {
} }
private void setUpSensors() throws Exception { private void setUpSensors() throws Exception {
mProxSensor = TestUtils.createSensor( mProxSensor = TestUtils.createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY,
Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY); PROX_SENSOR_MAX_RANGE);
Sensor screenOffBrightnessSensor = TestUtils.createSensor( Sensor screenOffBrightnessSensor = TestUtils.createSensor(
Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT); Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL))) when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL)))

View File

@@ -87,12 +87,7 @@ public final class DisplayPowerProximityStateControllerTest {
new DisplayPowerProximityStateController.Injector() { new DisplayPowerProximityStateController.Injector() {
@Override @Override
DisplayPowerProximityStateController.Clock createClock() { DisplayPowerProximityStateController.Clock createClock() {
return new DisplayPowerProximityStateController.Clock() { return mClock::now;
@Override
public long uptimeMillis() {
return mClock.now();
}
};
} }
}; };
mDisplayPowerProximityStateController = new DisplayPowerProximityStateController( mDisplayPowerProximityStateController = new DisplayPowerProximityStateController(