diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index ac30311e1f968..aabdafb885586 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -563,6 +563,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { (TouchProcessorResult.ProcessedTouch) result; final NormalizedTouchData data = processedTouch.getTouchData(); + boolean shouldPilfer = false; mActivePointerId = processedTouch.getPointerOnSensorId(); switch (processedTouch.getEvent()) { case DOWN: @@ -581,8 +582,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { mStatusBarStateController.isDozing()); // Pilfer if valid overlap, don't allow following events to reach keyguard - mInputManager.pilferPointers( - mOverlay.getOverlayView().getViewRootImpl().getInputToken()); + shouldPilfer = true; break; case UP: @@ -621,6 +621,12 @@ public class UdfpsController implements DozeReceiver, Dumpable { // Always pilfer pointers that are within sensor area or when alternate bouncer is showing if (isWithinSensorArea(mOverlay.getOverlayView(), event.getRawX(), event.getRawY(), true) || mAlternateBouncerInteractor.isVisibleState()) { + shouldPilfer = true; + } + + // Execute the pilfer, never pilfer if a vertical swipe is in progress + if (shouldPilfer && mLockscreenShadeTransitionController.getQSDragProgress() == 0f + && !mPrimaryBouncerInteractor.isInTransit()) { mInputManager.pilferPointers( mOverlay.getOverlayView().getViewRootImpl().getInputToken()); } 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 edee3f1b9f022..64c028e6a0952 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -1017,7 +1017,7 @@ public class UdfpsControllerTest extends SysuiTestCase { // 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(); + verify(mUdfpsView).unconfigureDisplay(); } else { verify(mUdfpsView, never()).unconfigureDisplay(); } @@ -1301,8 +1301,8 @@ public class UdfpsControllerTest extends SysuiTestCase { mBiometricExecutor.runAllReady(); downEvent.recycle(); - // THEN the touch is pilfered, expected twice (valid overlap and touch on sensor) - verify(mInputManager, times(2)).pilferPointers(any()); + // THEN the touch is pilfered + verify(mInputManager).pilferPointers(any()); } @Test @@ -1340,7 +1340,7 @@ public class UdfpsControllerTest extends SysuiTestCase { downEvent.recycle(); // THEN the touch is NOT pilfered - verify(mInputManager, times(0)).pilferPointers(any()); + verify(mInputManager, never()).pilferPointers(any()); } @Test @@ -1380,7 +1380,51 @@ public class UdfpsControllerTest extends SysuiTestCase { downEvent.recycle(); // THEN the touch is pilfered - verify(mInputManager, times(1)).pilferPointers(any()); + verify(mInputManager).pilferPointers(any()); + } + + @Test + public void onTouch_withNewTouchDetection_doNotPilferWhenPullingUpBouncer() + throws RemoteException { + final NormalizedTouchData touchData = new NormalizedTouchData(0, 0f, 0f, 0f, 0f, 0f, 0L, + 0L); + final TouchProcessorResult processorResultMove = + new TouchProcessorResult.ProcessedTouch(InteractionEvent.DOWN, + 1 /* pointerId */, touchData); + + // Enable new touch detection. + when(mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)).thenReturn(true); + + // Configure UdfpsController to use FingerprintManager as opposed to AlternateTouchProvider. + initUdfpsController(mOpticalProps, false /* hasAlternateTouchProvider */); + + // Configure UdfpsView to accept the ACTION_MOVE event + when(mUdfpsView.isDisplayConfigured()).thenReturn(false); + when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); + + // GIVEN that the alternate bouncer is not showing and a11y touch exploration NOT enabled + when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); + when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(false); + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); + mFgExecutor.runAllReady(); + + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + + // GIVEN a swipe up to bring up primary bouncer is in progress or swipe down for QS + when(mPrimaryBouncerInteractor.isInTransit()).thenReturn(true); + when(mLockscreenShadeTransitionController.getFractionToShade()).thenReturn(1f); + + // WHEN ACTION_MOVE is received and touch is within sensor + when(mSinglePointerTouchProcessor.processTouch(any(), anyInt(), any())).thenReturn( + processorResultMove); + MotionEvent moveEvent = MotionEvent.obtain(0, 0, ACTION_MOVE, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + mBiometricExecutor.runAllReady(); + moveEvent.recycle(); + + // THEN the touch is NOT pilfered + verify(mInputManager, never()).pilferPointers(any()); } @Test