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

Commit d2a79074 authored by Joshua McCloskey's avatar Joshua McCloskey
Browse files

Updated keyguard to be robust against fpm

Test: atest KeyguardUpdateMonitorTest
Bug: 238070374
Change-Id: If51313b03dc40442ad6c42603f77579e77b0c873
parent 382cf794
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -214,7 +214,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
     * If no cancel signal has been received after this amount of time, set the biometric running
     * state to stopped to allow Keyguard to retry authentication.
     */
    private static final int DEFAULT_CANCEL_SIGNAL_TIMEOUT = 3000;
    @VisibleForTesting
    protected static final int DEFAULT_CANCEL_SIGNAL_TIMEOUT = 3000;

    private static final ComponentName FALLBACK_HOME_COMPONENT = new ComponentName(
            "com.android.settings", "com.android.settings.FallbackHome");
@@ -332,10 +333,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private static final int HAL_ERROR_RETRY_TIMEOUT = 500; // ms
    private static final int HAL_ERROR_RETRY_MAX = 20;

    private final Runnable mFpCancelNotReceived = this::onFingerprintCancelNotReceived;
    @VisibleForTesting
    protected final Runnable mFpCancelNotReceived = this::onFingerprintCancelNotReceived;

    private final Runnable mFaceCancelNotReceived = this::onFaceCancelNotReceived;

    @VisibleForTesting
    protected Handler getHandler() {
        return mHandler;
    }
    private final Handler mHandler;

    private SparseBooleanArray mBiometricEnabledForUser = new SparseBooleanArray();
@@ -723,6 +729,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab

    private void handleFingerprintAuthFailed() {
        Assert.isMainThread();
        if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
            Log.d(TAG, "handleFingerprintAuthFailed()"
                    + " triggered while waiting for cancellation, removing watchdog");
            mHandler.removeCallbacks(mFpCancelNotReceived);
        }
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
@@ -753,6 +764,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab

    private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
        Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
        if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
            Log.d(TAG, "handleFingerprintAuthenticated()"
                    + " triggered while waiting for cancellation, removing watchdog");
            mHandler.removeCallbacks(mFpCancelNotReceived);
        }
        try {
            final int userId;
            try {
+47 −7
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;

import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;

import static com.google.common.truth.Truth.assertThat;

@@ -109,6 +110,7 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.internal.util.reflection.FieldSetter;

import java.util.ArrayList;
import java.util.Arrays;
@@ -200,9 +202,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
    private ArgumentCaptor<CancellationSignal> mCancellationSignalCaptor;

    // Direct executor
    private Executor mBackgroundExecutor = Runnable::run;
    private Executor mMainExecutor = Runnable::run;
    private final Executor mBackgroundExecutor = Runnable::run;
    private final Executor mMainExecutor = Runnable::run;
    private TestableLooper mTestableLooper;
    private Handler mHandler;
    private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
    private TestableContext mSpiedContext;
    private MockitoSession mMockitoSession;
@@ -291,6 +294,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        mBiometricEnabledOnKeyguardCallback = mBiometricEnabledCallbackArgCaptor.getValue();
        biometricsEnabledForCurrentUser();

        mHandler = spy(mKeyguardUpdateMonitor.getHandler());
        try {
            FieldSetter.setField(mKeyguardUpdateMonitor,
                    KeyguardUpdateMonitor.class.getDeclaredField("mHandler"), mHandler);
        } catch (NoSuchFieldException e) {

        }
        verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
        mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue();
        mKeyguardUpdateMonitor.registerCallback(mTestCallback);
@@ -791,7 +801,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
    public void testBiometricsCleared_whenUserSwitches() throws Exception {
        final IRemoteCallback reply = new IRemoteCallback.Stub() {
            @Override
            public void sendResult(Bundle data) {} // do nothing
            public void sendResult(Bundle data) {
            } // do nothing
        };
        final BiometricAuthenticated dummyAuthentication =
                new BiometricAuthenticated(true /* authenticated */, true /* strong */);
@@ -809,7 +820,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
    public void testMultiUserJankMonitor_whenUserSwitches() throws Exception {
        final IRemoteCallback reply = new IRemoteCallback.Stub() {
            @Override
            public void sendResult(Bundle data) {} // do nothing
            public void sendResult(Bundle data) {
            } // do nothing
        };
        mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */);
        verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH);
@@ -1499,6 +1511,34 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        assertThat(cancelSignal.isCanceled()).isTrue();
    }

    @Test
    public void testFingerprintCanAuth_whenCancellationNotReceivedAndAuthFailed() {
        mKeyguardUpdateMonitor.dispatchStartedWakingUp();
        mTestableLooper.processAllMessages();
        mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);

        verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
        verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
                anyInt());

        mKeyguardUpdateMonitor.onFaceAuthenticated(0, false);
        // Make sure keyguard is going away after face auth attempt, and that it calls
        // updateBiometricStateListeningState.
        mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(false);
        mTestableLooper.processAllMessages();

        verify(mHandler).postDelayed(mKeyguardUpdateMonitor.mFpCancelNotReceived,
                DEFAULT_CANCEL_SIGNAL_TIMEOUT);

        mKeyguardUpdateMonitor.onFingerprintAuthenticated(0, true);
        mTestableLooper.processAllMessages();

        verify(mHandler, times(1)).removeCallbacks(mKeyguardUpdateMonitor.mFpCancelNotReceived);
        mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
        mTestableLooper.processAllMessages();
        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(anyBoolean())).isEqualTo(true);
    }

    private void fingerprintIsNotEnrolled() {
        when(mFingerprintManager.hasEnrolledTemplates(mCurrentUserId)).thenReturn(false);
    }