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

Commit 98744f1a authored by Wenhui Yang's avatar Wenhui Yang
Browse files

Fix fingerprint unlock stuck after renaming

FingerprintAuthenticationClient wasn't cancelled successfully because cancelletion signal was set to null.

Test: Manual - rename an existing fingerprint and observe fingerprint unlock can be entered again
Test: atest FingerprintSettingsFragmentTest

Fixes: 283926104
Change-Id: Id33cc3d3e8052f5cc39eddac26a75047d3139633
parent d48ba611
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
import android.os.CancellationSignal;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.core.InstrumentedFragment;

/**
@@ -80,7 +81,6 @@ public class FingerprintAuthenticateSidecar extends InstrumentedFragment {

                @Override
                public void onAuthenticationError(int errMsgId, CharSequence errString) {
                    mCancellationSignal = null;
                    if (mListener != null) {
                        mListener.onAuthenticationError(errMsgId, errString);
                    } else {
@@ -108,11 +108,13 @@ public class FingerprintAuthenticateSidecar extends InstrumentedFragment {
    }

    public void stopAuthentication() {
        if (mCancellationSignal != null && !mCancellationSignal.isCanceled()) {
        if (mCancellationSignal != null) {
            // This will automatically check if the cancel has been sent and if so
            // it won't send it again.
            mCancellationSignal.cancel();
        }
            mCancellationSignal = null;
        }
    }

    public void setListener(Listener listener) {
        if (mListener == null && listener != null) {
@@ -129,4 +131,9 @@ public class FingerprintAuthenticateSidecar extends InstrumentedFragment {
        }
        mListener = listener;
    }

    @VisibleForTesting
    boolean isCancelled() {
        return mCancellationSignal == null || mCancellationSignal.isCanceled();
    }
}
 No newline at end of file
+44 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.hardware.biometrics.SensorProperties;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.view.LayoutInflater;
import android.view.ViewGroup;

@@ -68,6 +69,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -92,6 +94,16 @@ public class FingerprintSettingsFragmentTest {
    @Mock
    private FragmentTransaction mFragmentTransaction;

    @Captor
    private ArgumentCaptor<CancellationSignal> mCancellationSignalArgumentCaptor =
            ArgumentCaptor.forClass(CancellationSignal.class);
    @Captor
    private ArgumentCaptor<FingerprintManager.AuthenticationCallback>
            mAuthenticationCallbackArgumentCaptor = ArgumentCaptor.forClass(
            FingerprintManager.AuthenticationCallback.class);

    private FingerprintAuthenticateSidecar mFingerprintAuthenticateSidecar;

    @Before
    public void setUp() {
        doReturn(true).when(mFingerprintManager).isHardwareDetected();
@@ -146,6 +158,34 @@ public class FingerprintSettingsFragmentTest {
                false)).isTrue();
    }

    // Test the case when FingerprintAuthenticateSidecar receives an error callback from the
    // framework or from another authentication client. The cancellation signal should not be set
    // to null because there may exist a running authentication client.
    // The signal can only be cancelled from the caller in FingerprintSettings.
    @Test
    public void testCancellationSignalLifeCycle() {
        setUpFragment(false);

        mFingerprintAuthenticateSidecar.setFingerprintManager(mFingerprintManager);

        doNothing().when(mFingerprintManager).authenticate(any(),
                mCancellationSignalArgumentCaptor.capture(),
                mAuthenticationCallbackArgumentCaptor.capture(), any(), anyInt());

        mFingerprintAuthenticateSidecar.startAuthentication(1);

        assertThat(mAuthenticationCallbackArgumentCaptor.getValue()).isNotNull();
        assertThat(mCancellationSignalArgumentCaptor.getValue()).isNotNull();

        // Authentication error callback should not cancel the signal.
        mAuthenticationCallbackArgumentCaptor.getValue().onAuthenticationError(0, "");
        assertThat(mFingerprintAuthenticateSidecar.isCancelled()).isFalse();

        // The signal should be cancelled when caller stops the authentication.
        mFingerprintAuthenticateSidecar.stopAuthentication();
        assertThat(mFingerprintAuthenticateSidecar.isCancelled()).isTrue();
    }

    private void setUpFragment(boolean showChooseLock) {
        Intent intent = new Intent();
        if (!showChooseLock) {
@@ -166,6 +206,10 @@ public class FingerprintSettingsFragmentTest {
        doReturn(fragmentManager).when(mFragment).getFragmentManager();
        doReturn(fragmentManager).when(mActivity).getSupportFragmentManager();

        mFingerprintAuthenticateSidecar = new FingerprintAuthenticateSidecar();
        doReturn(mFingerprintAuthenticateSidecar).when(fragmentManager).findFragmentByTag(
                "authenticate_sidecar");

        doNothing().when(mFragment).startActivityForResult(any(Intent.class), anyInt());

        setSensor();