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

Commit 02a8a302 authored by Vincent Wang's avatar Vincent Wang Committed by Android (Google) Code Review
Browse files

Merge "Fix BiometricPrompt cannot detect when press the notification in LS" into tm-qpr-dev

parents 975b2af4 357ab1b0
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -249,13 +249,13 @@ public class AuthContainerView extends LinearLayout
                    break;
                case AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN:
                    mFailedModalities.clear();
                    mConfig.mCallback.onTryAgainPressed();
                    mConfig.mCallback.onTryAgainPressed(getRequestId());
                    break;
                case AuthBiometricView.Callback.ACTION_ERROR:
                    animateAway(AuthDialogCallback.DISMISSED_ERROR);
                    break;
                case AuthBiometricView.Callback.ACTION_USE_DEVICE_CREDENTIAL:
                    mConfig.mCallback.onDeviceCredentialPressed();
                    mConfig.mCallback.onDeviceCredentialPressed(getRequestId());
                    mHandler.postDelayed(() -> {
                        addCredentialView(false /* animatePanel */, true /* animateContents */);
                    }, mConfig.mSkipAnimation ? 0 : AuthDialog.ANIMATE_CREDENTIAL_START_DELAY_MS);
@@ -373,7 +373,7 @@ public class AuthContainerView extends LinearLayout

    void sendEarlyUserCanceled() {
        mConfig.mCallback.onSystemEvent(
                BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL);
                BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL, getRequestId());
    }

    @Override
@@ -774,7 +774,8 @@ public class AuthContainerView extends LinearLayout
    private void sendPendingCallbackIfNotNull() {
        Log.d(TAG, "pendingCallback: " + mPendingCallbackReason);
        if (mPendingCallbackReason != null) {
            mConfig.mCallback.onDismissed(mPendingCallbackReason, mCredentialAttestation);
            mConfig.mCallback.onDismissed(mPendingCallbackReason,
                    mCredentialAttestation, getRequestId());
            mPendingCallbackReason = null;
        }
    }
@@ -804,7 +805,7 @@ public class AuthContainerView extends LinearLayout
        }
        mContainerState = STATE_SHOWING;
        if (mBiometricView != null) {
            mConfig.mCallback.onDialogAnimatedIn();
            mConfig.mCallback.onDialogAnimatedIn(getRequestId());
            mBiometricView.onDialogAnimatedIn();
        }
    }
+35 −5
Original line number Diff line number Diff line
@@ -340,11 +340,17 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
    }

    @Override
    public void onTryAgainPressed() {
    public void onTryAgainPressed(long requestId) {
        if (mReceiver == null) {
            Log.e(TAG, "onTryAgainPressed: Receiver is null");
            return;
        }

        if (requestId != mCurrentDialog.getRequestId()) {
            Log.w(TAG, "requestId doesn't match, skip onTryAgainPressed");
            return;
        }

        try {
            mReceiver.onTryAgainPressed();
        } catch (RemoteException e) {
@@ -353,11 +359,17 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
    }

    @Override
    public void onDeviceCredentialPressed() {
    public void onDeviceCredentialPressed(long requestId) {
        if (mReceiver == null) {
            Log.e(TAG, "onDeviceCredentialPressed: Receiver is null");
            return;
        }

        if (requestId != mCurrentDialog.getRequestId()) {
            Log.w(TAG, "requestId doesn't match, skip onDeviceCredentialPressed");
            return;
        }

        try {
            mReceiver.onDeviceCredentialPressed();
        } catch (RemoteException e) {
@@ -366,11 +378,17 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
    }

    @Override
    public void onSystemEvent(int event) {
    public void onSystemEvent(int event, long requestId) {
        if (mReceiver == null) {
            Log.e(TAG, "onSystemEvent(" + event + "): Receiver is null");
            return;
        }

        if (requestId != mCurrentDialog.getRequestId()) {
            Log.w(TAG, "requestId doesn't match, skip onSystemEvent");
            return;
        }

        try {
            mReceiver.onSystemEvent(event);
        } catch (RemoteException e) {
@@ -379,12 +397,17 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
    }

    @Override
    public void onDialogAnimatedIn() {
    public void onDialogAnimatedIn(long requestId) {
        if (mReceiver == null) {
            Log.e(TAG, "onDialogAnimatedIn: Receiver is null");
            return;
        }

        if (requestId != mCurrentDialog.getRequestId()) {
            Log.w(TAG, "requestId doesn't match, skip onDialogAnimatedIn");
            return;
        }

        try {
            mReceiver.onDialogAnimatedIn();
        } catch (RemoteException e) {
@@ -393,7 +416,14 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
    }

    @Override
    public void onDismissed(@DismissedReason int reason, @Nullable byte[] credentialAttestation) {
    public void onDismissed(@DismissedReason int reason,
                            @Nullable byte[] credentialAttestation, long requestId) {

        if (mCurrentDialog != null && requestId != mCurrentDialog.getRequestId()) {
            Log.w(TAG, "requestId doesn't match, skip onDismissed");
            return;
        }

        switch (reason) {
            case AuthDialogCallback.DISMISSED_USER_CANCELED:
                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
+6 −5
Original line number Diff line number Diff line
@@ -47,27 +47,28 @@ public interface AuthDialogCallback {
     * @param reason
     * @param credentialAttestation the HAT received from LockSettingsService upon verification
     */
    void onDismissed(@DismissedReason int reason, @Nullable byte[] credentialAttestation);
    void onDismissed(@DismissedReason int reason,
                     @Nullable byte[] credentialAttestation, long requestId);

    /**
     * Invoked when the "try again" button is clicked
     */
    void onTryAgainPressed();
    void onTryAgainPressed(long requestId);

    /**
     * Invoked when the "use password" button is clicked
     */
    void onDeviceCredentialPressed();
    void onDeviceCredentialPressed(long requestId);

    /**
     * See {@link android.hardware.biometrics.BiometricPrompt.Builder
     * #setReceiveSystemEvents(boolean)}
     * @param event
     */
    void onSystemEvent(int event);
    void onSystemEvent(int event, long requestId);

    /**
     * Notifies when the dialog has finished animating.
     */
    void onDialogAnimatedIn();
    void onDialogAnimatedIn(long requestId);
}
+29 −20
Original line number Diff line number Diff line
@@ -48,11 +48,12 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.anyLong
import org.mockito.Mockito.eq
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit

@RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true)
@@ -87,7 +88,7 @@ class AuthContainerViewTest : SysuiTestCase() {
    @Test
    fun testNotifiesAnimatedIn() {
        initializeFingerprintContainer()
        verify(callback).onDialogAnimatedIn()
        verify(callback).onDialogAnimatedIn(authContainer?.requestId ?: 0L)
    }

    @Test
@@ -96,13 +97,13 @@ class AuthContainerViewTest : SysuiTestCase() {
        container.dismissFromSystemServer()
        waitForIdleSync()

        verify(callback, never()).onDialogAnimatedIn()
        verify(callback, never()).onDialogAnimatedIn(anyLong())

        container.addToView()
        waitForIdleSync()

        // attaching the view resets the state and allows this to happen again
        verify(callback).onDialogAnimatedIn()
        verify(callback).onDialogAnimatedIn(authContainer?.requestId ?: 0L)
    }

    @Test
@@ -110,14 +111,17 @@ class AuthContainerViewTest : SysuiTestCase() {
        val container = initializeFingerprintContainer()
        waitForIdleSync()

        verify(callback).onDialogAnimatedIn()
        val requestID = authContainer?.requestId ?: 0L

        verify(callback).onDialogAnimatedIn(requestID)

        container.onWindowFocusChanged(false)
        waitForIdleSync()

        verify(callback).onDismissed(
                eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
            eq<ByteArray?>(null) /* credentialAttestation */
                eq<ByteArray?>(null), /* credentialAttestation */
                eq(requestID)
        )
        assertThat(container.parent).isNull()
    }
@@ -132,7 +136,8 @@ class AuthContainerViewTest : SysuiTestCase() {

        verify(callback).onDismissed(
                eq(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED),
            eq<ByteArray?>(null) /* credentialAttestation */
                eq<ByteArray?>(null), /* credentialAttestation */
                eq(authContainer?.requestId ?: 0L)
        )
        assertThat(container.parent).isNull()
    }
@@ -146,11 +151,13 @@ class AuthContainerViewTest : SysuiTestCase() {
        waitForIdleSync()

        verify(callback).onSystemEvent(
            eq(BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL)
                eq(BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL),
                eq(authContainer?.requestId ?: 0L)
        )
        verify(callback).onDismissed(
                eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
            eq<ByteArray?>(null) /* credentialAttestation */
                eq<ByteArray?>(null), /* credentialAttestation */
                eq(authContainer?.requestId ?: 0L)
        )
        assertThat(container.parent).isNull()
    }
@@ -165,7 +172,8 @@ class AuthContainerViewTest : SysuiTestCase() {

        verify(callback).onDismissed(
                eq(AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE),
            eq<ByteArray?>(null) /* credentialAttestation */
                eq<ByteArray?>(null), /* credentialAttestation */
                eq(authContainer?.requestId ?: 0L)
        )
        assertThat(container.parent).isNull()
    }
@@ -180,7 +188,7 @@ class AuthContainerViewTest : SysuiTestCase() {
        )
        waitForIdleSync()

        verify(callback).onTryAgainPressed()
        verify(callback).onTryAgainPressed(authContainer?.requestId ?: 0L)
    }

    @Test
@@ -193,7 +201,8 @@ class AuthContainerViewTest : SysuiTestCase() {

        verify(callback).onDismissed(
                eq(AuthDialogCallback.DISMISSED_ERROR),
            eq<ByteArray?>(null) /* credentialAttestation */
                eq<ByteArray?>(null), /* credentialAttestation */
                eq(authContainer?.requestId ?: 0L)
        )
        assertThat(authContainer!!.parent).isNull()
    }
@@ -209,7 +218,7 @@ class AuthContainerViewTest : SysuiTestCase() {
        )
        waitForIdleSync()

        verify(callback).onDeviceCredentialPressed()
        verify(callback).onDeviceCredentialPressed(authContainer?.requestId ?: 0L)
        assertThat(container.hasCredentialView()).isTrue()
    }

@@ -322,12 +331,12 @@ class AuthContainerViewTest : SysuiTestCase() {
        container.onAuthenticationFailed(BiometricAuthenticator.TYPE_FACE, "failed")
        waitForIdleSync()

        verify(callback, never()).onTryAgainPressed()
        verify(callback, never()).onTryAgainPressed(anyLong())

        container.onPointerDown()
        waitForIdleSync()

        verify(callback).onTryAgainPressed()
        verify(callback).onTryAgainPressed(authContainer?.requestId ?: 0L)
    }

    private fun initializeFingerprintContainer(
+22 −13
Original line number Diff line number Diff line
@@ -291,7 +291,8 @@ public class AuthControllerTest extends SysuiTestCase {
    public void testSendsReasonUserCanceled_whenDismissedByUserCancel() throws Exception {
        showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);
        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED,
                null /* credentialAttestation */);
                null, /* credentialAttestation */
                mAuthController.mCurrentDialog.getRequestId());
        verify(mReceiver).onDialogDismissed(
                eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL),
                eq(null) /* credentialAttestation */);
@@ -301,7 +302,8 @@ public class AuthControllerTest extends SysuiTestCase {
    public void testSendsReasonNegative_whenDismissedByButtonNegative() throws Exception {
        showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE,
                null /* credentialAttestation */);
                null, /* credentialAttestation */
                mAuthController.mCurrentDialog.getRequestId());
        verify(mReceiver).onDialogDismissed(
                eq(BiometricPrompt.DISMISSED_REASON_NEGATIVE),
                eq(null) /* credentialAttestation */);
@@ -311,7 +313,8 @@ public class AuthControllerTest extends SysuiTestCase {
    public void testSendsReasonConfirmed_whenDismissedByButtonPositive() throws Exception {
        showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BUTTON_POSITIVE,
                null /* credentialAttestation */);
                null, /* credentialAttestation */
                mAuthController.mCurrentDialog.getRequestId());
        verify(mReceiver).onDialogDismissed(
                eq(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED),
                eq(null) /* credentialAttestation */);
@@ -321,7 +324,8 @@ public class AuthControllerTest extends SysuiTestCase {
    public void testSendsReasonConfirmNotRequired_whenDismissedByAuthenticated() throws Exception {
        showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED,
                null /* credentialAttestation */);
                null, /* credentialAttestation */
                mAuthController.mCurrentDialog.getRequestId());
        verify(mReceiver).onDialogDismissed(
                eq(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED),
                eq(null) /* credentialAttestation */);
@@ -331,7 +335,8 @@ public class AuthControllerTest extends SysuiTestCase {
    public void testSendsReasonError_whenDismissedByError() throws Exception {
        showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_ERROR,
                null /* credentialAttestation */);
                null, /* credentialAttestation */
                mAuthController.mCurrentDialog.getRequestId());
        verify(mReceiver).onDialogDismissed(
                eq(BiometricPrompt.DISMISSED_REASON_ERROR),
                eq(null) /* credentialAttestation */);
@@ -341,7 +346,8 @@ public class AuthControllerTest extends SysuiTestCase {
    public void testSendsReasonServerRequested_whenDismissedByServer() throws Exception {
        showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER,
                null /* credentialAttestation */);
                null, /* credentialAttestation */
                mAuthController.mCurrentDialog.getRequestId());
        verify(mReceiver).onDialogDismissed(
                eq(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED),
                eq(null) /* credentialAttestation */);
@@ -355,7 +361,7 @@ public class AuthControllerTest extends SysuiTestCase {
        final byte[] credentialAttestation = generateRandomHAT();

        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED,
                credentialAttestation);
                credentialAttestation, mAuthController.mCurrentDialog.getRequestId());
        verify(mReceiver).onDialogDismissed(
                eq(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED),
                AdditionalMatchers.aryEq(credentialAttestation));
@@ -531,7 +537,7 @@ public class AuthControllerTest extends SysuiTestCase {
        final byte[] credentialAttestation = generateRandomHAT();

        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED,
                credentialAttestation);
                credentialAttestation, mAuthController.mCurrentDialog.getRequestId());
        verify(mReceiver).onDialogDismissed(
                eq(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED),
                AdditionalMatchers.aryEq(credentialAttestation));
@@ -640,17 +646,19 @@ public class AuthControllerTest extends SysuiTestCase {
    @Test
    public void testDoesNotCrash_whenTryAgainPressedAfterDismissal() {
        showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
        final long requestID = mAuthController.mCurrentDialog.getRequestId();
        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED,
                null /* credentialAttestation */);
        mAuthController.onTryAgainPressed();
                null, /* credentialAttestation */requestID);
        mAuthController.onTryAgainPressed(requestID);
    }

    @Test
    public void testDoesNotCrash_whenDeviceCredentialPressedAfterDismissal() {
        showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
        final long requestID = mAuthController.mCurrentDialog.getRequestId();
        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED,
                null /* credentialAttestation */);
        mAuthController.onDeviceCredentialPressed();
                null /* credentialAttestation */, requestID);
        mAuthController.onDeviceCredentialPressed(requestID);
    }

    @Test
@@ -708,7 +716,8 @@ public class AuthControllerTest extends SysuiTestCase {
        // WHEN dialog is shown and then dismissed
        showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);
        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED,
                null /* credentialAttestation */);
                null /* credentialAttestation */,
                mAuthController.mCurrentDialog.getRequestId());

        // THEN callback should be received
        verify(callback).onBiometricPromptDismissed();