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

Commit 87823ed2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add metrics within Biometric Prompt" into main

parents e04e0458 56614a85
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -824,7 +824,7 @@ public class AuthControllerTest extends SysuiTestCase {
        showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);

        // THEN callback should be received
        verify(callback).onBiometricPromptShown();
        verify(callback).onBiometricPromptShown(any());
    }

    @Test
@@ -840,7 +840,7 @@ public class AuthControllerTest extends SysuiTestCase {
                mAuthController.mCurrentDialog.getRequestId());

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

    @Test
@@ -854,7 +854,8 @@ public class AuthControllerTest extends SysuiTestCase {
        mAuthController.hideAuthenticationDialog(mAuthController.mCurrentDialog.getRequestId());

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

    @Test
+3 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.biometrics.data.repository

import android.hardware.biometrics.BiometricPrompt
import android.hardware.biometrics.PromptInfo
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -82,11 +83,11 @@ class PromptRepositoryImplTest : SysuiTestCase() {
            withArgCaptor<AuthController.Callback> {
                verify(authController).addCallback(capture())

                value.onBiometricPromptShown()
                value.onBiometricPromptShown(PromptInfo())
                runCurrent()
                assertThat(values).containsExactly(true, true)

                value.onBiometricPromptDismissed()
                value.onBiometricPromptDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL)
                runCurrent()
                assertThat(values).containsExactly(true, true, false).inOrder()

+88 −0
Original line number Diff line number Diff line
@@ -25,11 +25,13 @@ import android.hardware.biometrics.PromptInfo
import android.hardware.biometrics.PromptVerticalListContentView
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
import com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN
import com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.BiometricPromptLogger
import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
import com.android.systemui.biometrics.data.repository.FakePromptRepository
@@ -42,6 +44,8 @@ import com.android.systemui.display.data.repository.FakeDisplayRepository
import com.android.systemui.display.domain.interactor.DisplayStateInteractor
import com.android.systemui.display.domain.interactor.DisplayStateInteractorImpl
import com.android.systemui.display.shared.model.DisplayRotation
import com.android.systemui.log.SessionTracker
import com.android.systemui.shared.system.SysUiStatsLog
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
@@ -55,6 +59,8 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnit
import org.mockito.kotlin.eq
import org.mockito.kotlin.verify

@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -77,6 +83,9 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() {

    @Mock private lateinit var lockPatternUtils: LockPatternUtils
    @Mock private lateinit var biometricManager: BiometricManager
    @Mock private lateinit var sessionTracker: SessionTracker
    @Mock private lateinit var biometricPromptLogger: BiometricPromptLogger
    @Mock private lateinit var instanceId: InstanceId

    private val testScope = TestScope()
    private val fingerprintRepository = FakeFingerprintPropertyRepository()
@@ -110,7 +119,11 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() {
                lockPatternUtils,
                biometricManager,
                testScope.backgroundScope,
                sessionTracker,
                biometricPromptLogger,
            )

        whenever(sessionTracker.getSessionId(any())).thenReturn(instanceId)
    }

    private fun basicPromptInfo() =
@@ -303,6 +316,81 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() {
            verifyUnset()
        }

    @Test
    fun switchToCredential() =
        testScope.runTest {
            setUserCredentialType(isPassword = true)

            val promptKind by collectLastValue(interactor.promptKind)
            val currentView by collectLastValue(interactor.currentView)
            assertThat(promptKind).isEqualTo(PromptKind.None)

            setPrompt(onSwitchToCredential = false)
            interactor.onSwitchToCredential()

            assertThat(promptKind).isEqualTo(PromptKind.Password)
            assertThat(currentView).isEqualTo(BiometricPromptView.CREDENTIAL)
            verify(biometricPromptLogger)
                .logPromptEvent(
                    eq(instanceId),
                    eq(
                        SysUiStatsLog
                            .BIOMETRIC_PROMPT_EVENT__EVENT__EVENT_TYPE_CREDENTIAL_VIEW_SHOWN
                    ),
                )

            interactor.resetPrompt(REQUEST_ID)
            verifyUnset()
        }

    @Test
    fun switchToFallback() =
        testScope.runTest {
            setUserCredentialType(isPassword = true)

            val promptKind by collectLastValue(interactor.promptKind)
            val currentView by collectLastValue(interactor.currentView)
            assertThat(promptKind).isEqualTo(PromptKind.None)

            setPrompt(onSwitchToCredential = false)
            interactor.onSwitchToFallback()

            assertThat(promptKind!!.isBiometric()).isTrue()
            assertThat(currentView).isEqualTo(BiometricPromptView.FALLBACK)
            verify(biometricPromptLogger)
                .logPromptEvent(
                    eq(instanceId),
                    eq(SysUiStatsLog.BIOMETRIC_PROMPT_EVENT__EVENT__EVENT_TYPE_FALLBACK_VIEW_SHOWN),
                )

            interactor.resetPrompt(REQUEST_ID)
            verifyUnset()
        }

    @Test
    fun switchToAuth() =
        testScope.runTest {
            setUserCredentialType(isPassword = true)

            val promptKind by collectLastValue(interactor.promptKind)
            val currentView by collectLastValue(interactor.currentView)
            assertThat(promptKind).isEqualTo(PromptKind.None)

            setPrompt(onSwitchToCredential = true)
            interactor.onSwitchToAuth()

            assertThat(promptKind!!.isBiometric()).isTrue()
            assertThat(currentView).isEqualTo(BiometricPromptView.BIOMETRIC)
            verify(biometricPromptLogger)
                .logPromptEvent(
                    eq(instanceId),
                    eq(SysUiStatsLog.BIOMETRIC_PROMPT_EVENT__EVENT__EVENT_TYPE_BIOMETRIC_VIEW_SHOWN),
                )

            interactor.resetPrompt(REQUEST_ID)
            verifyUnset()
        }

    @Test
    fun promptKind_isCredential_whenBiometricIsNotAllowed() =
        testScope.runTest {
+14 −4
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.PromptInfo;
import android.os.RemoteException;
import android.testing.TestableLooper;

@@ -44,6 +46,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.BiometricPromptLogger;
import com.android.systemui.process.ProcessWrapper;
import com.android.systemui.statusbar.policy.KeyguardStateController;

@@ -71,6 +74,8 @@ public class SessionTrackerTest extends SysuiTestCase {
    private UiEventLogger mUiEventLogger;
    @Mock
    private ProcessWrapper mProcessWrapper;
    @Mock
    private BiometricPromptLogger mBiometricPromptLogger;

    @Captor
    ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
@@ -97,7 +102,8 @@ public class SessionTrackerTest extends SysuiTestCase {
                mKeyguardUpdateMonitor,
                mKeyguardStateController,
                mUiEventLogger,
                mProcessWrapper
                mProcessWrapper,
                mBiometricPromptLogger
        );
    }

@@ -137,7 +143,8 @@ public class SessionTrackerTest extends SysuiTestCase {
        captureAuthControllerCallback();

        // WHEN auth controller shows the biometric prompt
        mAuthControllerCallback.onBiometricPromptShown();
        PromptInfo promptInfo = new PromptInfo();
        mAuthControllerCallback.onBiometricPromptShown(promptInfo);

        // THEN the biometric prompt session has a session id
        assertNotNull(mSessionTracker.getSessionId(SESSION_BIOMETRIC_PROMPT));
@@ -145,6 +152,7 @@ public class SessionTrackerTest extends SysuiTestCase {
        // THEN session started event gets sent to status bar service
        verify(mStatusBarService).onSessionStarted(
                eq(SESSION_BIOMETRIC_PROMPT), any(InstanceId.class));
        verify(mBiometricPromptLogger).logPromptStart(any(InstanceId.class), eq(promptInfo));
    }

    @Test
@@ -154,13 +162,15 @@ public class SessionTrackerTest extends SysuiTestCase {
        captureAuthControllerCallback();

        // WHEN auth controller shows the biometric prompt and then hides it
        mAuthControllerCallback.onBiometricPromptShown();
        mAuthControllerCallback.onBiometricPromptDismissed();
        int reason = BiometricPrompt.DISMISSED_REASON_USER_CANCEL;
        mAuthControllerCallback.onBiometricPromptShown(new PromptInfo());
        mAuthControllerCallback.onBiometricPromptDismissed(reason);

        // THEN the biometric prompt session no longer has a session id
        assertNull(mSessionTracker.getSessionId(SESSION_BIOMETRIC_PROMPT));

        // THEN session end event gets sent to status bar service
        verify(mBiometricPromptLogger).logPromptEnd(any(InstanceId.class), eq(reason));
        verify(mStatusBarService).onSessionEnded(
                eq(SESSION_BIOMETRIC_PROMPT), any(InstanceId.class));
    }
+18 −4
Original line number Diff line number Diff line
@@ -232,7 +232,7 @@ public class AuthController implements
            mCurrentDialog = null;

            for (Callback cb : mCallbacks) {
                cb.onBiometricPromptDismissed();
                cb.onBiometricPromptDismissed(reason);
            }

            try {
@@ -1165,7 +1165,7 @@ public class AuthController implements

        mCurrentDialog.dismissFromSystemServer();
        for (Callback cb : mCallbacks) {
            cb.onBiometricPromptDismissed();
            cb.onBiometricPromptDismissed(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED);
        }

        // BiometricService will have already sent the callback to the client in this case.
@@ -1291,7 +1291,7 @@ public class AuthController implements

        mReceiver = (IBiometricSysuiReceiver) args.arg2;
        for (Callback cb : mCallbacks) {
            cb.onBiometricPromptShown();
            cb.onBiometricPromptShown(promptInfo);
        }
        mCurrentDialog = newDialog;

@@ -1345,7 +1345,7 @@ public class AuthController implements
        }

        for (Callback cb : mCallbacks) {
            cb.onBiometricPromptDismissed();
            cb.onBiometricPromptDismissed(reason);
        }

        mReceiver = null;
@@ -1457,11 +1457,25 @@ public class AuthController implements
         */
        default void onBiometricPromptShown() {}

        /**
         * Called when the biometric prompt starts showing.
         */
        default void onBiometricPromptShown(PromptInfo promptInfo) {
            onBiometricPromptShown();
        }

        /**
         * Called when the biometric prompt is no longer showing.
         */
        default void onBiometricPromptDismissed() {}

        /**
         * Called when the biometric prompt is no longer showing.
         */
        default void onBiometricPromptDismissed(@BiometricPrompt.DismissedReason int reason) {
            onBiometricPromptDismissed();
        }

        /**
         * Called when the location of the fingerprint sensor changes. The location in pixels can
         * change due to resolution changes.
Loading