Delay the transition to AOD1 if udfps is activated

We don't want to change display states while the user
is interacting with the UDFPS sensor or else we'll
lose the touch and cut fp authentication short.

Test: atest DozeScreenSTateTest
Bug: 198710028
Change-Id: I3a8168e6f1970c36717e0a7a223bcc74c3ec5600
This commit is contained in:
Beverly
2021-09-13 11:10:19 -04:00
parent 906b2ed5a1
commit c87d7f79ca
4 changed files with 150 additions and 7 deletions

View File

@@ -213,6 +213,14 @@ public class DozeLog implements Dumpable {
mLogger.logStateChangedSent(state);
}
/**
* Appends display state delayed by UDFPS event to the logs
* @param delayedDisplayState the display screen state that was delayed
*/
public void traceDisplayStateDelayedByUdfps(int delayedDisplayState) {
mLogger.logDisplayStateDelayedByUdfps(delayedDisplayState);
}
/**
* Appends display state changed event to the logs
* @param displayState new DozeMachine state

View File

@@ -160,6 +160,14 @@ class DozeLogger @Inject constructor(
})
}
fun logDisplayStateDelayedByUdfps(delayedDisplayState: Int) {
buffer.log(TAG, INFO, {
str1 = Display.stateToString(delayedDisplayState)
}, {
"Delaying display state change to: $str1 due to UDFPS activity"
})
}
fun logDisplayStateChanged(displayState: Int) {
buffer.log(TAG, INFO, {
str1 = Display.stateToString(displayState)

View File

@@ -26,6 +26,11 @@ import android.os.Handler;
import android.util.Log;
import android.view.Display;
import androidx.annotation.Nullable;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.UdfpsController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.doze.dagger.WrappedService;
@@ -34,6 +39,7 @@ import com.android.systemui.util.wakelock.SettableWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
import javax.inject.Inject;
import javax.inject.Provider;
/**
* Controls the screen when dozing.
@@ -56,23 +62,61 @@ public class DozeScreenState implements DozeMachine.Part {
*/
public static final int ENTER_DOZE_HIDE_WALLPAPER_DELAY = 2500;
/**
* Add an extra delay to the transition to DOZE when udfps is current activated before
* the display state transitions from ON => DOZE.
*/
public static final int UDFPS_DISPLAY_STATE_DELAY = 1200;
private final DozeMachine.Service mDozeService;
private final Handler mHandler;
private final Runnable mApplyPendingScreenState = this::applyPendingScreenState;
private final DozeParameters mParameters;
private final DozeHost mDozeHost;
private final AuthController mAuthController;
private final Provider<UdfpsController> mUdfpsControllerProvider;
@Nullable private UdfpsController mUdfpsController;
private final DozeLog mDozeLog;
private int mPendingScreenState = Display.STATE_UNKNOWN;
private SettableWakeLock mWakeLock;
@Inject
public DozeScreenState(@WrappedService DozeMachine.Service service, @Main Handler handler,
DozeHost host, DozeParameters parameters, WakeLock wakeLock) {
public DozeScreenState(
@WrappedService DozeMachine.Service service,
@Main Handler handler,
DozeHost host,
DozeParameters parameters,
WakeLock wakeLock,
AuthController authController,
Provider<UdfpsController> udfpsControllerProvider,
DozeLog dozeLog) {
mDozeService = service;
mHandler = handler;
mParameters = parameters;
mDozeHost = host;
mWakeLock = new SettableWakeLock(wakeLock, TAG);
mAuthController = authController;
mUdfpsControllerProvider = udfpsControllerProvider;
mDozeLog = dozeLog;
updateUdfpsController();
if (mUdfpsController == null) {
mAuthController.addCallback(new AuthController.Callback() {
@Override
public void onAllAuthenticatorsRegistered() {
updateUdfpsController();
}
});
}
}
private void updateUdfpsController() {
if (mAuthController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser())) {
mUdfpsController = mUdfpsControllerProvider.get();
} else {
mUdfpsController = null;
}
}
@Override
@@ -110,21 +154,28 @@ public class DozeScreenState implements DozeMachine.Part {
mPendingScreenState = screenState;
// Delay screen state transitions even longer while animations are running.
boolean shouldDelayTransition = newState == DOZE_AOD
boolean shouldDelayTransitionEnteringDoze = newState == DOZE_AOD
&& mParameters.shouldControlScreenOff() && !turningOn;
if (shouldDelayTransition) {
// Delay screen state transition longer if UDFPS is actively authenticating a fp
boolean shouldDelayTransitionForUDFPS = newState == DOZE_AOD
&& mUdfpsController != null && mUdfpsController.isFingerDown();
if (shouldDelayTransitionEnteringDoze || shouldDelayTransitionForUDFPS) {
mWakeLock.setAcquired(true);
}
if (!messagePending) {
if (DEBUG) {
Log.d(TAG, "Display state changed to " + screenState + " delayed by "
+ (shouldDelayTransition ? ENTER_DOZE_DELAY : 1));
+ (shouldDelayTransitionEnteringDoze ? ENTER_DOZE_DELAY : 1));
}
if (shouldDelayTransition) {
if (shouldDelayTransitionEnteringDoze) {
mHandler.postDelayed(mApplyPendingScreenState, ENTER_DOZE_DELAY);
} else if (shouldDelayTransitionForUDFPS) {
mDozeLog.traceDisplayStateDelayedByUdfps(mPendingScreenState);
mHandler.postDelayed(mApplyPendingScreenState, UDFPS_DISPLAY_STATE_DELAY);
} else {
mHandler.post(mApplyPendingScreenState);
}
@@ -139,6 +190,12 @@ public class DozeScreenState implements DozeMachine.Part {
}
private void applyPendingScreenState() {
if (mUdfpsController != null && mUdfpsController.isFingerDown()) {
mDozeLog.traceDisplayStateDelayedByUdfps(mPendingScreenState);
mHandler.postDelayed(mApplyPendingScreenState, UDFPS_DISPLAY_STATE_DELAY);
return;
}
applyScreenState(mPendingScreenState);
mPendingScreenState = Display.STATE_UNKNOWN;
}

View File

@@ -21,6 +21,7 @@ import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_DOCKED;
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSING;
import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE;
import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING;
import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE;
import static com.android.systemui.doze.DozeMachine.State.FINISH;
@@ -34,6 +35,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -45,6 +47,8 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.UdfpsController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.WakeLockFake;
import com.android.systemui.utils.os.FakeHandler;
@@ -56,6 +60,8 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import javax.inject.Provider;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DozeScreenStateTest extends SysuiTestCase {
@@ -68,17 +74,29 @@ public class DozeScreenStateTest extends SysuiTestCase {
private DozeParameters mDozeParameters;
private WakeLockFake mWakeLock;
private DozeScreenState mScreen;
@Mock
private Provider<UdfpsController> mUdfpsControllerProvider;
@Mock
private AuthController mAuthController;
@Mock
private UdfpsController mUdfpsController;
@Mock
private DozeLog mDozeLog;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
when(mUdfpsControllerProvider.get()).thenReturn(mUdfpsController);
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
when(mUdfpsController.isFingerDown()).thenReturn(false);
mServiceFake = new DozeServiceFake();
mHandlerFake = new FakeHandler(Looper.getMainLooper());
mWakeLock = new WakeLockFake();
mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeHost, mDozeParameters,
mWakeLock);
mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog);
}
@Test
@@ -233,4 +251,56 @@ public class DozeScreenStateTest extends SysuiTestCase {
assertEquals(Display.STATE_OFF, mServiceFake.screenState);
}
@Test
public void testDelayEnterDozeScreenState_whenUdfpsFingerDown() {
// GIVEN AOD is initialized
when(mDozeParameters.shouldControlScreenOff()).thenReturn(true);
mHandlerFake.setMode(QUEUEING);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mHandlerFake.dispatchQueuedMessages();
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
// WHEN udfps is activated (fingerDown)
when(mUdfpsController.isFingerDown()).thenReturn(true);
mHandlerFake.dispatchQueuedMessages();
// THEN the display screen state doesn't immediately change
assertEquals(Display.STATE_ON, mServiceFake.screenState);
// WHEN udfpsController finger is no longer down and the queued messages are run
when(mUdfpsController.isFingerDown()).thenReturn(false);
mHandlerFake.dispatchQueuedMessages();
// THEN the display screen state will change
assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
}
@Test
public void testDelayExitPulsingScreenState_whenUdfpsFingerDown() {
// GIVEN we're pulsing
when(mDozeParameters.shouldControlScreenOff()).thenReturn(true);
mHandlerFake.setMode(QUEUEING);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
mScreen.transitionTo(DOZE_AOD, DOZE_REQUEST_PULSE);
mScreen.transitionTo(DOZE_REQUEST_PULSE, DOZE_PULSING);
mScreen.transitionTo(DOZE_PULSING, DOZE_PULSE_DONE);
mHandlerFake.dispatchQueuedMessages();
// WHEN udfps is activated while are transitioning back to DOZE_AOD
mScreen.transitionTo(DOZE_PULSE_DONE, DOZE_AOD);
when(mUdfpsController.isFingerDown()).thenReturn(true);
mHandlerFake.dispatchQueuedMessages();
// THEN the display screen state doesn't immediately change
assertEquals(Display.STATE_ON, mServiceFake.screenState);
// WHEN udfpsController finger is no longer down and the queued messages are run
when(mUdfpsController.isFingerDown()).thenReturn(false);
mHandlerFake.dispatchQueuedMessages();
// THEN the display screen state will change
assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
}
}