diff options
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java | 17 | ||||
| -rw-r--r-- | packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java | 85 |
2 files changed, 99 insertions, 3 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index bb35355ba03a..19bd86aba177 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -42,6 +42,7 @@ import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IUdfpsOverlayController; import android.hardware.fingerprint.IUdfpsOverlayControllerCallback; +import android.hardware.input.InputManager; import android.os.Build; import android.os.Handler; import android.os.PowerManager; @@ -169,6 +170,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull private final AlternateBouncerInteractor mAlternateBouncerInteractor; @NonNull private final SecureSettings mSecureSettings; @NonNull private final UdfpsUtils mUdfpsUtils; + @NonNull private final InputManager mInputManager; // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple // sensors, this, in addition to a lot of the code here, will be updated. @@ -576,6 +578,10 @@ public class UdfpsController implements DozeReceiver, Dumpable { data.getTime(), data.getGestureStart(), mStatusBarStateController.isDozing()); + + // Pilfer if valid overlap, don't allow following events to reach keyguard + mInputManager.pilferPointers( + mOverlay.getOverlayView().getViewRootImpl().getInputToken()); break; case UP: @@ -599,7 +605,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { break; case UNCHANGED: - if (!isWithinSensorArea(mOverlay.getOverlayView(), event.getX(), event.getY(), + if (!isWithinSensorArea(mOverlay.getOverlayView(), event.getRawX(), event.getRawY(), true) && mActivePointerId == MotionEvent.INVALID_POINTER_ID && event.getActionMasked() == MotionEvent.ACTION_DOWN && mAlternateBouncerInteractor.isVisibleState()) { @@ -612,6 +618,13 @@ public class UdfpsController implements DozeReceiver, Dumpable { } logBiometricTouch(processedTouch.getEvent(), data); + // Always pilfer pointers that are within sensor area + if (isWithinSensorArea(mOverlay.getOverlayView(), event.getRawX(), event.getRawY(), true)) { + Log.d("Austin", "pilferTouch invalid overlap"); + mInputManager.pilferPointers( + mOverlay.getOverlayView().getViewRootImpl().getInputToken()); + } + return processedTouch.getTouchData().isWithinSensor(mOverlayParams.getNativeSensorBounds()); } @@ -798,6 +811,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull SessionTracker sessionTracker, @NonNull AlternateBouncerInteractor alternateBouncerInteractor, @NonNull SecureSettings secureSettings, + @NonNull InputManager inputManager, @NonNull UdfpsUtils udfpsUtils) { mContext = context; mExecution = execution; @@ -841,6 +855,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { mAlternateBouncerInteractor = alternateBouncerInteractor; mSecureSettings = secureSettings; mUdfpsUtils = udfpsUtils; + mInputManager = inputManager; mTouchProcessor = mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION) ? singlePointerTouchProcessor : null; 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 9a73898ca7c7..445cc8739463 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -53,6 +53,7 @@ import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IUdfpsOverlayController; import android.hardware.fingerprint.IUdfpsOverlayControllerCallback; +import android.hardware.input.InputManager; import android.os.Handler; import android.os.PowerManager; import android.os.RemoteException; @@ -63,6 +64,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.Surface; import android.view.View; +import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; @@ -231,6 +233,10 @@ public class UdfpsControllerTest extends SysuiTestCase { private FingerprintSensorPropertiesInternal mOpticalProps; private FingerprintSensorPropertiesInternal mUltrasonicProps; private UdfpsUtils mUdfpsUtils; + @Mock + private InputManager mInputManager; + @Mock + private ViewRootImpl mViewRootImpl; @Before public void setUp() { @@ -248,6 +254,7 @@ public class UdfpsControllerTest extends SysuiTestCase { when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true); when(mSessionTracker.getSessionId(anyInt())).thenReturn( (new InstanceIdSequence(1 << 20)).newInstanceId()); + when(mUdfpsView.getViewRootImpl()).thenReturn(mViewRootImpl); final List<ComponentInfoInternal> componentInfo = new ArrayList<>(); componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */, @@ -304,7 +311,7 @@ public class UdfpsControllerTest extends SysuiTestCase { mUnlockedScreenOffAnimationController, mSystemUIDialogManager, mLatencyTracker, mActivityLaunchAnimator, alternateTouchProvider, mBiometricExecutor, mPrimaryBouncerInteractor, mSinglePointerTouchProcessor, mSessionTracker, - mAlternateBouncerInteractor, mSecureSettings, mUdfpsUtils); + mAlternateBouncerInteractor, mSecureSettings, mInputManager, mUdfpsUtils); verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture()); mOverlayController = mOverlayCaptor.getValue(); verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture()); @@ -1262,6 +1269,81 @@ public class UdfpsControllerTest extends SysuiTestCase { } @Test + public void onTouch_withNewTouchDetection_pilferPointer() throws RemoteException { + final NormalizedTouchData touchData = new NormalizedTouchData(0, 0f, 0f, 0f, 0f, 0f, 0L, + 0L); + final TouchProcessorResult processorResultDown = 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_DOWN event + when(mUdfpsView.isDisplayConfigured()).thenReturn(false); + when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); + + // GIVEN that the overlay is showing and a11y touch exploration NOT enabled + when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); + mFgExecutor.runAllReady(); + + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + + // WHEN ACTION_DOWN is received + when(mSinglePointerTouchProcessor.processTouch(any(), anyInt(), any())).thenReturn( + processorResultDown); + MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + mBiometricExecutor.runAllReady(); + downEvent.recycle(); + + // THEN the touch is pilfered, expected twice (valid overlap and touch on sensor) + verify(mInputManager, times(2)).pilferPointers(any()); + } + + @Test + public void onTouch_withNewTouchDetection_doNotPilferPointer() throws RemoteException { + final NormalizedTouchData touchData = new NormalizedTouchData(0, 0f, 0f, 0f, 0f, 0f, 0L, + 0L); + final TouchProcessorResult processorResultUnchanged = + new TouchProcessorResult.ProcessedTouch(InteractionEvent.UNCHANGED, + 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 not accept the ACTION_DOWN event + when(mUdfpsView.isDisplayConfigured()).thenReturn(false); + when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(false); + + // GIVEN that the overlay is showing and a11y touch exploration NOT enabled + when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); + mFgExecutor.runAllReady(); + + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + + // WHEN ACTION_DOWN is received and touch is not within sensor + when(mSinglePointerTouchProcessor.processTouch(any(), anyInt(), any())).thenReturn( + processorResultUnchanged); + MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + mBiometricExecutor.runAllReady(); + downEvent.recycle(); + + // THEN the touch is NOT pilfered + verify(mInputManager, times(0)).pilferPointers(any()); + } + + @Test public void onAodInterrupt_onAcquiredGood_fingerNoLongerDown() throws RemoteException { // GIVEN UDFPS overlay is showing mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId, @@ -1285,6 +1367,5 @@ public class UdfpsControllerTest extends SysuiTestCase { // THEN is fingerDown should be FALSE assertFalse(mUdfpsController.isFingerDown()); - } } |