diff options
5 files changed, 151 insertions, 8 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index 0ce1846e7745..a4123c769d1e 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -786,7 +786,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, .build(sensorIds, credentialAllowed, mFpProps, mFaceProps); } - interface Callback { + public interface Callback { /** * Called when authenticators are registered. If authenticators are already * registered before this call, this callback will never be triggered. diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index 41964652ac49..657d9246be8f 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -214,6 +214,14 @@ public class DozeLog implements Dumpable { } /** + * 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 */ diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt index 9bc74be9b9c3..fe37d49980b2 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt @@ -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) diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java index 8c50a16b566f..8f1486b0c7cb 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java @@ -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; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java index 41d7fd64fe7a..150ab7700e4b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java @@ -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); + } }
\ No newline at end of file |