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

Commit c121056f authored by Beverly Tai's avatar Beverly Tai Committed by Automerger Merge Worker
Browse files

Merge "Update FP failure bouncer & messaging logic" into tm-qpr-dev am: 5cdb41a8

parents a2e6ee02 5cdb41a8
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -206,7 +206,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
     */
    private static final int BIOMETRIC_STATE_CANCELLING_RESTARTING = 3;

    private static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
    @VisibleForTesting
    public static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
    public static final int BIOMETRIC_HELP_FACE_NOT_RECOGNIZED = -2;

    /**
+11 −1
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ public class KeyguardIndicationController {
    private static final int MSG_HIDE_TRANSIENT = 1;
    private static final int MSG_SHOW_ACTION_TO_UNLOCK = 2;
    private static final int MSG_HIDE_BIOMETRIC_MESSAGE = 3;
    private static final int MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON = 4;
    private static final long TRANSIENT_BIOMETRIC_ERROR_TIMEOUT = 1300;
    public static final long DEFAULT_HIDE_DELAY_MS =
            3500 + KeyguardIndicationTextView.Y_IN_DURATION;
@@ -188,9 +189,11 @@ public class KeyguardIndicationController {
                }
            };
    private ScreenLifecycle mScreenLifecycle;
    private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
    private final ScreenLifecycle.Observer mScreenObserver =
            new ScreenLifecycle.Observer() {
        @Override
        public void onScreenTurnedOn() {
            mHandler.removeMessages(MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON);
            if (mBiometricErrorMessageToShowOnScreenOn != null) {
                showBiometricMessage(mBiometricErrorMessageToShowOnScreenOn);
                // We want to keep this message around in case the screen was off
@@ -259,6 +262,8 @@ public class KeyguardIndicationController {
                    showActionToUnlock();
                } else if (msg.what == MSG_HIDE_BIOMETRIC_MESSAGE) {
                    hideBiometricMessage();
                } else if (msg.what == MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON) {
                    mBiometricErrorMessageToShowOnScreenOn = null;
                }
            }
        };
@@ -1060,6 +1065,11 @@ public class KeyguardIndicationController {
            } else if (showActionToUnlock) {
                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_ACTION_TO_UNLOCK),
                        TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
            } else {
                mBiometricErrorMessageToShowOnScreenOn = helpString;
                mHandler.sendMessageDelayed(
                        mHandler.obtainMessage(MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON),
                        1000);
            }
        }

+11 −11
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.res.Resources;
import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.metrics.LogMaker;
import android.os.Handler;
@@ -64,7 +65,6 @@ import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.KeyguardStateController;

@@ -87,7 +87,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
    private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
    private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
    private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
    private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 2;
    private static final int UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3;
    private static final VibrationEffect SUCCESS_VIBRATION_EFFECT =
            VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
    private static final VibrationEffect ERROR_VIBRATION_EFFECT =
@@ -450,7 +450,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
        // During wake and unlock, we need to draw black before waking up to avoid abrupt
        // brightness changes due to display state transitions.
        Runnable wakeUp = ()-> {
            if (!wasDeviceInteractive) {
            if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) {
                if (DEBUG_BIO_WAKELOCK) {
                    Log.i(TAG, "bio wakelock: Authenticated, waking up...");
                }
@@ -662,7 +662,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp

        if (!mVibratorHelper.hasVibrator()
                && (!mUpdateMonitor.isDeviceInteractive() || mUpdateMonitor.isDreaming())) {
            startWakeAndUnlock(MODE_SHOW_BOUNCER);
            startWakeAndUnlock(MODE_ONLY_WAKE);
        } else if (biometricSourceType == BiometricSourceType.FINGERPRINT
                && mUpdateMonitor.isUdfpsSupported()) {
            long currUptimeMillis = SystemClock.uptimeMillis();
@@ -673,7 +673,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
            }
            mLastFpFailureUptimeMillis = currUptimeMillis;

            if (mNumConsecutiveFpFailures >= FP_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
            if (mNumConsecutiveFpFailures >= UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
                startWakeAndUnlock(MODE_SHOW_BOUNCER);
                UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId());
                mNumConsecutiveFpFailures = 0;
@@ -699,13 +699,13 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
        Optional.ofNullable(BiometricUiEvent.ERROR_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
                .ifPresent(event -> UI_EVENT_LOGGER.log(event, getSessionId()));

        // if we're on the shade and we're locked out, immediately show the bouncer
        if (biometricSourceType == BiometricSourceType.FINGERPRINT
        final boolean fingerprintLockout = biometricSourceType == BiometricSourceType.FINGERPRINT
                && (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
                || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
                && mUpdateMonitor.isUdfpsSupported()
                && (mStatusBarStateController.getState() == StatusBarState.SHADE
                    || mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED)) {
                || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT);
        final boolean faceLockout = biometricSourceType == BiometricSourceType.FACE
                && (msgId == FaceManager.FACE_ERROR_LOCKOUT
                || msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT);
        if (fingerprintLockout || faceLockout) {
            startWakeAndUnlock(MODE_SHOW_BOUNCER);
            UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId());
        }
+33 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;

import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE;
@@ -31,6 +32,7 @@ import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewCont
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRANSIENT;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRUST;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_USER_LOCKED;
import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_OFF;
import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;

import static com.google.common.truth.Truth.assertThat;
@@ -178,9 +180,12 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
    private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
    @Captor
    private ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallbackCaptor;
    @Captor
    private ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor;
    private KeyguardStateController.Callback mKeyguardStateControllerCallback;
    private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback;
    private StatusBarStateController.StateListener mStatusBarStateListener;
    private ScreenLifecycle.Observer mScreenObserver;
    private BroadcastReceiver mBroadcastReceiver;
    private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
    private TestableLooper mTestableLooper;
@@ -273,6 +278,9 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
                mKeyguardUpdateMonitorCallbackCaptor.capture());
        mKeyguardUpdateMonitorCallback = mKeyguardUpdateMonitorCallbackCaptor.getValue();

        verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
        mScreenObserver = mScreenObserverCaptor.getValue();

        mExecutor.runAllReady();
        reset(mRotateTextViewController);
    }
@@ -536,6 +544,31 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
        assertThat(mTextView.getText()).isNotEqualTo(message);
    }

    @Test
    public void transientIndication_visibleWhenWokenUp() {
        createController();
        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
        final String message = "helpMsg";

        // GIVEN screen is off
        when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_OFF);

        // WHEN fingeprint help message received
        mController.setVisible(true);
        mController.getKeyguardCallback().onBiometricHelp(BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED,
                message, BiometricSourceType.FINGERPRINT);

        // THEN message isn't shown right away
        verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE);

        // WHEN the screen turns on
        mScreenObserver.onScreenTurnedOn();
        mTestableLooper.processAllMessages();

        // THEN the message is shown
        verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, message);
    }

    @Test
    public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() {
        createController();
+16 −13
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -395,15 +397,19 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
    }

    @Test
    public void onUdfpsConsecutivelyFailedTwoTimes_showBouncer() {
    public void onUdfpsConsecutivelyFailedThreeTimes_showBouncer() {
        // GIVEN UDFPS is supported
        when(mUpdateMonitor.isUdfpsSupported()).thenReturn(true);

        // WHEN udfps fails once - then don't show the bouncer
        // WHEN udfps fails once - then don't show the bouncer yet
        mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
        verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());

        // WHEN udfps fails the second time
        // WHEN udfps fails the second time - then don't show the bouncer yet
        mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
        verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());

        // WHEN udpfs fails the third time
        mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);

        // THEN show the bouncer
@@ -427,8 +433,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
    }

    @Test
    public void onFPFailureNoHaptics_notDeviceInteractive_showBouncer() {
        // GIVEN no vibrator and the screen is off
    public void onFPFailureNoHaptics_notInteractive_showLockScreen() {
        // GIVEN no vibrator and device is dreaming
        when(mVibratorHelper.hasVibrator()).thenReturn(false);
        when(mUpdateMonitor.isDeviceInteractive()).thenReturn(false);
        when(mUpdateMonitor.isDreaming()).thenReturn(false);
@@ -436,15 +442,12 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
        // WHEN FP fails
        mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);

        // after device is finished waking up
        mBiometricUnlockController.mWakefulnessObserver.onFinishedWakingUp();

        // THEN show the bouncer
        verify(mStatusBarKeyguardViewManager).showBouncer(true);
        // THEN wakeup the device
        verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
    }

    @Test
    public void onFPFailureNoHaptics_dreaming_showBouncer() {
    public void onFPFailureNoHaptics_dreaming_showLockScreen() {
        // GIVEN no vibrator and device is dreaming
        when(mVibratorHelper.hasVibrator()).thenReturn(false);
        when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
@@ -453,7 +456,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
        // WHEN FP fails
        mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);

        // THEN show the bouncer
        verify(mStatusBarKeyguardViewManager).showBouncer(true);
        // THEN wakeup the device
        verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
    }
}