Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e65f9a8 authored by Austin Delgado's avatar Austin Delgado
Browse files

Pilfer pointers on UDFPS sensor

Pilfer pointers when touch is valid overlap with sensor or within the
sensor area. This prevents long presses from passing through to keyguard.

Bug: 272210321
Test: atest SystemUITests:com.android.systemui.biometrics
Change-Id: Id9759b2f1f77fe23e6f33e78f2abe66b73571f25
parent 6f2a456d
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -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;
+83 −2
Original line number Diff line number Diff line
@@ -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());
@@ -1261,6 +1268,81 @@ public class UdfpsControllerTest extends SysuiTestCase {
        downEvent.recycle();
    }

    @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
@@ -1285,6 +1367,5 @@ public class UdfpsControllerTest extends SysuiTestCase {

        // THEN is fingerDown should be FALSE
        assertFalse(mUdfpsController.isFingerDown());

    }
}