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

Commit 2588c8d5 authored by Juan Sebastian Martinez's avatar Juan Sebastian Martinez Committed by Android (Google) Code Review
Browse files

Merge "Using performHapticFeedback on UdfpsController" into udc-qpr-dev

parents 5723d596 0ac98182
Loading
Loading
Loading
Loading
+40 −12
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROL

import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION;
import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;

import android.content.BroadcastReceiver;
import android.content.Context;
@@ -50,6 +51,7 @@ import android.os.Trace;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
@@ -234,6 +236,8 @@ public class UdfpsController implements DozeReceiver, Dumpable {
    public static final VibrationEffect EFFECT_CLICK =
            VibrationEffect.get(VibrationEffect.EFFECT_CLICK);

    public static final int LONG_PRESS = HapticFeedbackConstants.LONG_PRESS;

    private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
        @Override
        public void onScreenTurnedOn() {
@@ -926,6 +930,17 @@ public class UdfpsController implements DozeReceiver, Dumpable {
    @VisibleForTesting
    public void playStartHaptic() {
        if (mAccessibilityManager.isTouchExplorationEnabled()) {
            if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) {
                if (mOverlay != null && mOverlay.getOverlayView() != null) {
                    mVibrator.performHapticFeedback(
                            mOverlay.getOverlayView(),
                            HapticFeedbackConstants.CONTEXT_CLICK
                    );
                } else {
                    Log.e(TAG, "No haptics played. Could not obtain overlay view to perform"
                            + "vibration. Either the controller overlay is null or has no view");
                }
            } else {
                mVibrator.vibrate(
                        Process.myUid(),
                        mContext.getOpPackageName(),
@@ -934,6 +949,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
                        UDFPS_VIBRATION_ATTRIBUTES);
            }
        }
    }

    @Override
    public void dozeTimeTick() {
@@ -1024,12 +1040,24 @@ public class UdfpsController implements DozeReceiver, Dumpable {
            mKeyguardViewManager.showPrimaryBouncer(true);

            // play the same haptic as the LockIconViewController longpress
            if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) {
                if (mOverlay != null && mOverlay.getOverlayView() != null) {
                    mVibrator.performHapticFeedback(
                            mOverlay.getOverlayView(),
                            UdfpsController.LONG_PRESS
                    );
                } else {
                    Log.e(TAG, "No haptics played. Could not obtain overlay view to perform"
                            + "vibration. Either the controller overlay is null or has no view");
                }
            } else {
                mVibrator.vibrate(
                        Process.myUid(),
                        mContext.getOpPackageName(),
                        UdfpsController.EFFECT_CLICK,
                        "aod-lock-icon-longpress",
                        LOCK_ICON_VIBRATION_ATTRIBUTES);
            }
            return;
        }

+102 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.view.MotionEvent.ACTION_UP;

import static com.android.internal.util.FunctionalUtils.ThrowingConsumer;
import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION;
import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -61,6 +62,7 @@ import android.os.RemoteException;
import android.os.VibrationAttributes;
import android.testing.TestableLooper.RunWithLooper;
import android.util.Pair;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
@@ -1127,6 +1129,36 @@ public class UdfpsControllerTest extends SysuiTestCase {
                UdfpsController.UDFPS_VIBRATION_ATTRIBUTES.getUsage());
    }

    @Test
    public void playHapticOnTouchUdfpsArea_a11yTouchExplorationEnabled_oneWayHapticsEnabled()
            throws RemoteException {
        when(mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)).thenReturn(true);
        // 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 enabled
        when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true);
        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
        mFgExecutor.runAllReady();

        // WHEN ACTION_HOVER is received
        verify(mUdfpsView).setOnHoverListener(mHoverListenerCaptor.capture());
        MotionEvent enterEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0);
        mHoverListenerCaptor.getValue().onHover(mUdfpsView, enterEvent);
        enterEvent.recycle();
        MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0);
        mHoverListenerCaptor.getValue().onHover(mUdfpsView, moveEvent);
        moveEvent.recycle();

        // THEN context click haptic is played
        verify(mVibrator).performHapticFeedback(
                any(),
                eq(HapticFeedbackConstants.CONTEXT_CLICK)
        );
    }

    @Test
    public void noHapticOnTouchUdfpsArea_a11yTouchExplorationDisabled() throws RemoteException {
        // Configure UdfpsView to accept the ACTION_DOWN event
@@ -1159,6 +1191,35 @@ public class UdfpsControllerTest extends SysuiTestCase {
                any());
    }

    @Test
    public void noHapticOnTouchUdfpsArea_a11yTouchExplorationDisabled__oneWayHapticsEnabled()
            throws RemoteException {
        when(mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)).thenReturn(true);
        // 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();

        // 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);
        mBiometricExecutor.runAllReady();
        downEvent.recycle();
        MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0);
        mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
        mBiometricExecutor.runAllReady();
        moveEvent.recycle();

        // THEN NO haptic played
        verify(mVibrator, never()).performHapticFeedback(any(), anyInt());
    }

    @Test
    public void onTouch_withoutNewTouchDetection_shouldCallOldFingerprintManagerPath()
            throws RemoteException {
@@ -1514,4 +1575,45 @@ public class UdfpsControllerTest extends SysuiTestCase {
        // THEN is fingerDown should be FALSE
        assertFalse(mUdfpsController.isFingerDown());
    }

    @Test
    public void playHaptic_onAodInterrupt_oneWayHapticsDisabled_onAcquiredBad_usesVibrate()
            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(false);
        mScreenObserver.onScreenTurnedOn();
        mUdfpsController.onAodInterrupt(0, 0, 0, 0);

        // THEN vibrate is used
        verify(mVibrator).vibrate(
                anyInt(),
                anyString(),
                eq(UdfpsController.EFFECT_CLICK),
                eq("aod-lock-icon-longpress"),
                eq(UdfpsController.LOCK_ICON_VIBRATION_ATTRIBUTES)
        );
    }

    @Test
    public void playHaptic_onAodInterrupt_oneWayHapticsEnabled_onAcquiredBad_performHapticFeedback()
            throws RemoteException {
        when(mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)).thenReturn(true);
        // 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(false);
        mScreenObserver.onScreenTurnedOn();
        mUdfpsController.onAodInterrupt(0, 0, 0, 0);

        // THEN vibrate is used
        verify(mVibrator).performHapticFeedback(any(), eq(UdfpsController.LONG_PRESS));
    }
}