diff options
| author | 2022-12-07 22:39:11 +0000 | |
|---|---|---|
| committer | 2022-12-12 14:26:05 +0000 | |
| commit | b681e2f5a8dedb3d85da5b4e417a1a2f54b3c19e (patch) | |
| tree | ff0a821107eb221baf53114a5bfdfb03f961d98d | |
| parent | 631554e2528a4faf141f1a3fdece1903be16c343 (diff) | |
Make sure aodInterrupts are cancelled
Else, the UDFPS fingerDown state can be stale
and cause downstream bugs (ie: remaining in the screen on state
instead of transitioninf back to AoD since the DozeMachine
thinks that the user is still interacting with UDFPS).
Test: manually fail UDFPS from AoD, observe device goes back
into DOZE_AOD 5+ seconds after the fingerprint failure
Test: atest UdfpsControllerTest
Fixes: 261758656
Change-Id: Ied60ead5aae4f00e57d0e9457581bf3796392aca
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java | 32 | ||||
| -rw-r--r-- | packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java | 221 |
2 files changed, 152 insertions, 101 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 419cf1faf1fd..f3136babada6 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -115,7 +115,7 @@ import kotlin.Unit; @SysUISingleton public class UdfpsController implements DozeReceiver, Dumpable { private static final String TAG = "UdfpsController"; - private static final long AOD_INTERRUPT_TIMEOUT_MILLIS = 1000; + private static final long AOD_SEND_FINGER_UP_DELAY_MILLIS = 1000; // Minimum required delay between consecutive touch logs in milliseconds. private static final long MIN_TOUCH_LOG_INTERVAL = 50; @@ -178,7 +178,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { // interrupt is being tracked and a timeout is used as a last resort to turn off high brightness // mode. private boolean mIsAodInterruptActive; - @Nullable private Runnable mCancelAodTimeoutAction; + @Nullable private Runnable mCancelAodFingerUpAction; private boolean mScreenOn; private Runnable mAodInterruptRunnable; private boolean mOnFingerDown; @@ -272,6 +272,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (view != null && isOptical()) { unconfigureDisplay(view); } + tryAodSendFingerUp(); if (acquiredGood) { mOverlay.onAcquiredGood(); } @@ -868,12 +869,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { private void unconfigureDisplay(@NonNull UdfpsView view) { if (view.isDisplayConfigured()) { view.unconfigureDisplay(); - - if (mCancelAodTimeoutAction != null) { - mCancelAodTimeoutAction.run(); - mCancelAodTimeoutAction = null; - } - mIsAodInterruptActive = false; } } @@ -913,8 +908,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { // ACTION_UP/ACTION_CANCEL, we need to be careful about not letting the screen // accidentally remain in high brightness mode. As a mitigation, queue a call to // cancel the fingerprint scan. - mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::cancelAodInterrupt, - AOD_INTERRUPT_TIMEOUT_MILLIS); + mCancelAodFingerUpAction = mFgExecutor.executeDelayed(this::tryAodSendFingerUp, + AOD_SEND_FINGER_UP_DELAY_MILLIS); // using a hard-coded value for major and minor until it is available from the sensor onFingerDown(requestId, screenX, screenY, minor, major); }; @@ -948,15 +943,27 @@ public class UdfpsController implements DozeReceiver, Dumpable { * sensors, this can result in illumination persisting for longer than necessary. */ @VisibleForTesting - void cancelAodInterrupt() { + void tryAodSendFingerUp() { if (!mIsAodInterruptActive) { return; } + cancelAodSendFingerUpAction(); if (mOverlay != null && mOverlay.getOverlayView() != null) { onFingerUp(mOverlay.getRequestId(), mOverlay.getOverlayView()); } - mCancelAodTimeoutAction = null; + } + + /** + * Cancels any scheduled AoD finger-up actions without triggered the finger-up action. Only + * call this method if the finger-up event has been guaranteed to have already occurred. + */ + @VisibleForTesting + void cancelAodSendFingerUpAction() { mIsAodInterruptActive = false; + if (mCancelAodFingerUpAction != null) { + mCancelAodFingerUpAction.run(); + mCancelAodFingerUpAction = null; + } } private boolean isOptical() { @@ -1118,6 +1125,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (isOptical()) { unconfigureDisplay(view); } + cancelAodSendFingerUpAction(); } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index a94f3427eebe..b061eb395119 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -16,6 +16,7 @@ package com.android.systemui.biometrics; +import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_UP; @@ -23,6 +24,8 @@ import static android.view.MotionEvent.ACTION_UP; import static com.android.internal.util.FunctionalUtils.ThrowingConsumer; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -124,7 +127,7 @@ public class UdfpsControllerTest extends SysuiTestCase { // Unit under test private UdfpsController mUdfpsController; // Dependencies - private FakeExecutor mBiometricsExecutor; + private FakeExecutor mBiometricExecutor; @Mock private LayoutInflater mLayoutInflater; @Mock @@ -212,6 +215,8 @@ public class UdfpsControllerTest extends SysuiTestCase { private ArgumentCaptor<Runnable> mOnDisplayConfiguredCaptor; @Captor private ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor; + @Captor + private ArgumentCaptor<UdfpsController.UdfpsOverlayController> mUdfpsOverlayControllerCaptor; private ScreenLifecycle.Observer mScreenObserver; private FingerprintSensorPropertiesInternal mOpticalProps; private FingerprintSensorPropertiesInternal mUltrasonicProps; @@ -258,7 +263,7 @@ public class UdfpsControllerTest extends SysuiTestCase { mFgExecutor = new FakeExecutor(new FakeSystemClock()); // Create a fake background executor. - mBiometricsExecutor = new FakeExecutor(new FakeSystemClock()); + mBiometricExecutor = new FakeExecutor(new FakeSystemClock()); initUdfpsController(true /* hasAlternateTouchProvider */); } @@ -286,7 +291,7 @@ public class UdfpsControllerTest extends SysuiTestCase { mVibrator, mUdfpsHapticsSimulator, mUdfpsShell, mKeyguardStateController, mDisplayManager, mHandler, mConfigurationController, mSystemClock, mUnlockedScreenOffAnimationController, mSystemUIDialogManager, mLatencyTracker, - mActivityLaunchAnimator, alternateTouchProvider, mBiometricsExecutor, + mActivityLaunchAnimator, alternateTouchProvider, mBiometricExecutor, mPrimaryBouncerInteractor, mSinglePointerTouchProcessor); verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture()); mOverlayController = mOverlayCaptor.getValue(); @@ -322,7 +327,7 @@ public class UdfpsControllerTest extends SysuiTestCase { verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); downEvent.recycle(); // THEN notify keyguard authenticate to dismiss the keyguard @@ -360,7 +365,7 @@ public class UdfpsControllerTest extends SysuiTestCase { mFgExecutor.runAllReady(); } mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); moveEvent.recycle(); // THEN notify keyguard authenticate to dismiss the keyguard @@ -384,12 +389,12 @@ public class UdfpsControllerTest extends SysuiTestCase { verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); downEvent.recycle(); MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); moveEvent.recycle(); // THEN notify keyguard authenticate to dismiss the keyguard @@ -578,11 +583,11 @@ public class UdfpsControllerTest extends SysuiTestCase { MotionEvent event = obtainMotionEvent(ACTION_DOWN, displayWidth, displayHeight, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); event.recycle(); event = obtainMotionEvent(ACTION_MOVE, displayWidth, displayHeight, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); event.recycle(); if (testParams.hasAlternateTouchProvider) { verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX), @@ -601,11 +606,11 @@ public class UdfpsControllerTest extends SysuiTestCase { scaleFactor, Surface.ROTATION_90)); event = obtainMotionEvent(ACTION_DOWN, displayHeight, 0, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); event.recycle(); event = obtainMotionEvent(ACTION_MOVE, displayHeight, 0, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); event.recycle(); if (testParams.hasAlternateTouchProvider) { verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX), @@ -624,11 +629,11 @@ public class UdfpsControllerTest extends SysuiTestCase { scaleFactor, Surface.ROTATION_270)); event = obtainMotionEvent(ACTION_DOWN, 0, displayWidth, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); event.recycle(); event = obtainMotionEvent(ACTION_MOVE, 0, displayWidth, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); event.recycle(); if (testParams.hasAlternateTouchProvider) { verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX), @@ -648,11 +653,11 @@ public class UdfpsControllerTest extends SysuiTestCase { // ROTATION_180 is not supported. It should be treated like ROTATION_0. event = obtainMotionEvent(ACTION_DOWN, displayWidth, displayHeight, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); event.recycle(); event = obtainMotionEvent(ACTION_MOVE, displayWidth, displayHeight, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); event.recycle(); if (testParams.hasAlternateTouchProvider) { verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX), @@ -687,12 +692,12 @@ public class UdfpsControllerTest extends SysuiTestCase { // WHEN ACTION_DOWN is received MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); downEvent.recycle(); MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); moveEvent.recycle(); mFgExecutor.runAllReady(); @@ -725,7 +730,7 @@ public class UdfpsControllerTest extends SysuiTestCase { if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) { // AND onDisplayConfigured notifies FingerprintManager about onUiReady mOnDisplayConfiguredCaptor.getValue().run(); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); if (testParams.hasAlternateTouchProvider) { InOrder inOrder = inOrder(mAlternateTouchProvider, mLatencyTracker); inOrder.verify(mAlternateTouchProvider).onUiReady(); @@ -748,13 +753,15 @@ public class UdfpsControllerTest extends SysuiTestCase { } } + + @Test public void aodInterrupt() { runWithAllParams(this::aodInterruptParameterized); } private void aodInterruptParameterized(TestParams testParams) throws RemoteException { - mUdfpsController.cancelAodInterrupt(); + mUdfpsController.cancelAodSendFingerUpAction(); reset(mUdfpsView, mAlternateTouchProvider, mFingerprintManager, mKeyguardUpdateMonitor); when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true); @@ -774,7 +781,7 @@ public class UdfpsControllerTest extends SysuiTestCase { } else { verify(mUdfpsView, never()).configureDisplay(mOnDisplayConfiguredCaptor.capture()); } - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); if (testParams.hasAlternateTouchProvider) { verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(0), eq(0), @@ -792,7 +799,7 @@ public class UdfpsControllerTest extends SysuiTestCase { } @Test - public void cancelAodInterrupt() { + public void tryAodSendFingerUp_displayConfigurationChanges() { runWithAllParams(this::cancelAodInterruptParameterized); } @@ -808,24 +815,25 @@ public class UdfpsControllerTest extends SysuiTestCase { if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) { when(mUdfpsView.isDisplayConfigured()).thenReturn(true); // WHEN it is cancelled - mUdfpsController.cancelAodInterrupt(); + mUdfpsController.tryAodSendFingerUp(); // THEN the display is unconfigured verify(mUdfpsView).unconfigureDisplay(); } else { when(mUdfpsView.isDisplayConfigured()).thenReturn(false); // WHEN it is cancelled - mUdfpsController.cancelAodInterrupt(); + mUdfpsController.tryAodSendFingerUp(); // THEN the display configuration is unchanged. verify(mUdfpsView, never()).unconfigureDisplay(); } } @Test - public void aodInterruptTimeout() { - runWithAllParams(this::aodInterruptTimeoutParameterized); + public void onFingerUp_displayConfigurationChange() { + runWithAllParams(this::onFingerUp_displayConfigurationParameterized); } - private void aodInterruptTimeoutParameterized(TestParams testParams) throws RemoteException { + private void onFingerUp_displayConfigurationParameterized(TestParams testParams) + throws RemoteException { reset(mUdfpsView); // GIVEN AOD interrupt @@ -834,99 +842,105 @@ public class UdfpsControllerTest extends SysuiTestCase { mScreenObserver.onScreenTurnedOn(); mFgExecutor.runAllReady(); mUdfpsController.onAodInterrupt(0, 0, 0f, 0f); - mFgExecutor.runAllReady(); if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) { when(mUdfpsView.isDisplayConfigured()).thenReturn(true); - } else { - when(mUdfpsView.isDisplayConfigured()).thenReturn(false); - } - // WHEN it times out - mFgExecutor.advanceClockToNext(); - mFgExecutor.runAllReady(); - if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) { - // THEN the display is unconfigured. + + // WHEN up-action received + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + MotionEvent upEvent = MotionEvent.obtain(0, 0, ACTION_UP, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, upEvent); + mBiometricExecutor.runAllReady(); + upEvent.recycle(); + mFgExecutor.runAllReady(); + + // THEN the display is unconfigured verify(mUdfpsView).unconfigureDisplay(); } else { + when(mUdfpsView.isDisplayConfigured()).thenReturn(false); + + // WHEN up-action received + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + MotionEvent upEvent = MotionEvent.obtain(0, 0, ACTION_UP, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, upEvent); + mBiometricExecutor.runAllReady(); + upEvent.recycle(); + mFgExecutor.runAllReady(); + // THEN the display configuration is unchanged. verify(mUdfpsView, never()).unconfigureDisplay(); } } @Test - public void aodInterruptCancelTimeoutActionOnFingerUp() { - runWithAllParams(this::aodInterruptCancelTimeoutActionOnFingerUpParameterized); + public void onAcquiredGood_displayConfigurationChange() { + runWithAllParams(this::onAcquiredGood_displayConfigurationParameterized); } - private void aodInterruptCancelTimeoutActionOnFingerUpParameterized(TestParams testParams) + private void onAcquiredGood_displayConfigurationParameterized(TestParams testParams) throws RemoteException { reset(mUdfpsView); - when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); - // GIVEN AOD interrupt + // GIVEN overlay is showing mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); - mScreenObserver.onScreenTurnedOn(); mFgExecutor.runAllReady(); - mUdfpsController.onAodInterrupt(0, 0, 0f, 0f); - mFgExecutor.runAllReady(); - if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) { - // Configure UdfpsView to accept the ACTION_UP event when(mUdfpsView.isDisplayConfigured()).thenReturn(true); + // WHEN ACQUIRED_GOOD received + mOverlayController.onAcquired(testParams.sensorProps.sensorId, + BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD); + mFgExecutor.runAllReady(); + // THEN the display is unconfigured + verify(mUdfpsView).unconfigureDisplay(); } else { when(mUdfpsView.isDisplayConfigured()).thenReturn(false); + // WHEN ACQUIRED_GOOD received + mOverlayController.onAcquired(testParams.sensorProps.sensorId, + BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD); + mFgExecutor.runAllReady(); + // THEN the display configuration is unchanged. + verify(mUdfpsView, never()).unconfigureDisplay(); } + } - // WHEN ACTION_UP is received - verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); - MotionEvent upEvent = MotionEvent.obtain(0, 0, ACTION_UP, 0, 0, 0); - mTouchListenerCaptor.getValue().onTouch(mUdfpsView, upEvent); - mBiometricsExecutor.runAllReady(); - upEvent.recycle(); - - // Configure UdfpsView to accept the ACTION_DOWN event - when(mUdfpsView.isDisplayConfigured()).thenReturn(false); + @Test + public void aodInterruptTimeout() { + runWithAllParams(this::aodInterruptTimeoutParameterized); + } - // WHEN ACTION_DOWN is received - MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); - mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); - mBiometricsExecutor.runAllReady(); - downEvent.recycle(); + private void aodInterruptTimeoutParameterized(TestParams testParams) throws RemoteException { + reset(mUdfpsView); - // WHEN ACTION_MOVE is received - MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); - mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); - mBiometricsExecutor.runAllReady(); - moveEvent.recycle(); + // GIVEN AOD interrupt + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); + mScreenObserver.onScreenTurnedOn(); + mFgExecutor.runAllReady(); + mUdfpsController.onAodInterrupt(0, 0, 0f, 0f); mFgExecutor.runAllReady(); - if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) { - // Configure UdfpsView to accept the finger up event when(mUdfpsView.isDisplayConfigured()).thenReturn(true); } else { when(mUdfpsView.isDisplayConfigured()).thenReturn(false); } - // WHEN it times out mFgExecutor.advanceClockToNext(); mFgExecutor.runAllReady(); - if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) { - // THEN the display should be unconfigured once. If the timeout action is not - // cancelled, the display would be unconfigured twice which would cause two - // FP attempts. - verify(mUdfpsView, times(1)).unconfigureDisplay(); + // THEN the display is unconfigured. + verify(mUdfpsView).unconfigureDisplay(); } else { + // THEN the display configuration is unchanged. verify(mUdfpsView, never()).unconfigureDisplay(); } } @Test - public void aodInterruptCancelTimeoutActionOnAcquired() { - runWithAllParams(this::aodInterruptCancelTimeoutActionOnAcquiredParameterized); + public void aodInterruptCancelTimeoutActionOnFingerUp() { + runWithAllParams(this::aodInterruptCancelTimeoutActionOnFingerUpParameterized); } - private void aodInterruptCancelTimeoutActionOnAcquiredParameterized(TestParams testParams) + private void aodInterruptCancelTimeoutActionOnFingerUpParameterized(TestParams testParams) throws RemoteException { reset(mUdfpsView); when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); @@ -940,30 +954,32 @@ public class UdfpsControllerTest extends SysuiTestCase { mFgExecutor.runAllReady(); if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) { - // Configure UdfpsView to accept the acquired event + // Configure UdfpsView to accept the ACTION_UP event when(mUdfpsView.isDisplayConfigured()).thenReturn(true); } else { when(mUdfpsView.isDisplayConfigured()).thenReturn(false); } - // WHEN acquired is received - mOverlayController.onAcquired(testParams.sensorProps.sensorId, - BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD); + // WHEN ACTION_UP is received + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + MotionEvent upEvent = MotionEvent.obtain(0, 0, ACTION_UP, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, upEvent); + mBiometricExecutor.runAllReady(); + upEvent.recycle(); // Configure UdfpsView to accept the ACTION_DOWN event when(mUdfpsView.isDisplayConfigured()).thenReturn(false); // WHEN ACTION_DOWN is received - verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); downEvent.recycle(); // WHEN ACTION_MOVE is received MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); moveEvent.recycle(); mFgExecutor.runAllReady(); @@ -1083,11 +1099,11 @@ public class UdfpsControllerTest extends SysuiTestCase { verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); downEvent.recycle(); MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); moveEvent.recycle(); // THEN NO haptic played @@ -1123,19 +1139,19 @@ public class UdfpsControllerTest extends SysuiTestCase { // WHEN ACTION_DOWN is received MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); downEvent.recycle(); // AND ACTION_MOVE is received MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); moveEvent.recycle(); // AND ACTION_UP is received MotionEvent upEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, upEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); upEvent.recycle(); // THEN the old FingerprintManager path is invoked. @@ -1177,7 +1193,7 @@ public class UdfpsControllerTest extends SysuiTestCase { processorResultDown); MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); downEvent.recycle(); // AND ACTION_UP is received @@ -1185,7 +1201,7 @@ public class UdfpsControllerTest extends SysuiTestCase { processorResultUp); MotionEvent upEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, upEvent); - mBiometricsExecutor.runAllReady(); + mBiometricExecutor.runAllReady(); upEvent.recycle(); // THEN the new FingerprintManager path is invoked. @@ -1194,4 +1210,31 @@ public class UdfpsControllerTest extends SysuiTestCase { verify(mFingerprintManager).onPointerUp(anyLong(), anyInt(), anyInt(), anyFloat(), anyFloat(), anyFloat(), anyFloat(), anyFloat(), anyLong(), anyLong(), anyBoolean()); } + + @Test + public void onAodInterrupt_onAcquiredGood_fingerNoLongerDown() throws RemoteException { + // GIVEN UDFPS overlay is showing + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); + mFgExecutor.runAllReady(); + + // GIVEN there's been an AoD interrupt + when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true); + mScreenObserver.onScreenTurnedOn(); + mUdfpsController.onAodInterrupt(0, 0, 0, 0); + + // THEN finger is considered down + assertTrue(mUdfpsController.isFingerDown()); + + // WHEN udfps receives an ACQUIRED_GOOD after the display is configured + when(mUdfpsView.isDisplayConfigured()).thenReturn(true); + verify(mFingerprintManager).setUdfpsOverlayController( + mUdfpsOverlayControllerCaptor.capture()); + mUdfpsOverlayControllerCaptor.getValue().onAcquired(0, FINGERPRINT_ACQUIRED_GOOD); + mFgExecutor.runAllReady(); + + // THEN is fingerDown should be FALSE + assertFalse(mUdfpsController.isFingerDown()); + + } } |