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

Commit 086bed63 authored by Austin Delgado's avatar Austin Delgado Committed by Android (Google) Code Review
Browse files

Merge "Update Biometric Prompt for private space" into main

parents 7e62372d c4e39ae1
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -54,3 +54,10 @@ flag {
  description: "This flag is for API changes related to Identity Check"
  bug: "373424727"
}

flag {
  name: "private_space_bp"
  namespace: "biometrics_framework"
  description: "Feature flag for biometric prompt improvements in private space"
  bug: "365554098"
}
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
    <uses-permission android:name="android.permission.READ_WALLPAPER_INTERNAL" />

    <!-- Used to read storage for all users -->
    <uses-permission android:name="android.permission.STORAGE_INTERNAL" />
    <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
+83 −51
Original line number Diff line number Diff line
@@ -3,7 +3,9 @@ package com.android.systemui.biometrics.domain.interactor
import android.app.admin.DevicePolicyManager
import android.app.admin.DevicePolicyResourcesManager
import android.content.pm.UserInfo
import android.hardware.biometrics.Flags
import android.os.UserManager
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
@@ -33,6 +35,7 @@ import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit

private const val USER_ID = 22
private const val OWNER_ID = 10
private const val OPERATION_ID = 100L
private const val MAX_ATTEMPTS = 5

@@ -67,7 +70,7 @@ class CredentialInteractorImplTest : SysuiTestCase() {
                lockPatternUtils,
                userManager,
                devicePolicyManager,
                systemClock
                systemClock,
            )
    }

@@ -115,12 +118,35 @@ class CredentialInteractorImplTest : SysuiTestCase() {

    @Test fun pinCredentialWhenBadAndThrottled() = pinCredential(badCredential(timeout = 5_000))

    private fun pinCredential(result: VerifyCredentialResponse) = runTest {
    @EnableFlags(Flags.FLAG_PRIVATE_SPACE_BP)
    @Test
    fun pinCredentialTiedProfileWhenGood() = pinCredential(goodCredential(), OWNER_ID)

    @EnableFlags(Flags.FLAG_PRIVATE_SPACE_BP)
    @Test
    fun pinCredentialTiedProfileWhenBad() = pinCredential(badCredential(), OWNER_ID)

    @EnableFlags(Flags.FLAG_PRIVATE_SPACE_BP)
    @Test
    fun pinCredentialTiedProfileWhenBadAndThrottled() =
        pinCredential(badCredential(timeout = 5_000), OWNER_ID)

    private fun pinCredential(result: VerifyCredentialResponse, credentialOwner: Int = USER_ID) =
        runTest {
            val usedAttempts = 1
            whenever(lockPatternUtils.getCurrentFailedPasswordAttempts(eq(USER_ID)))
                .thenReturn(usedAttempts)
        whenever(lockPatternUtils.verifyCredential(any(), eq(USER_ID), anyInt())).thenReturn(result)
        whenever(lockPatternUtils.verifyGatekeeperPasswordHandle(anyLong(), anyLong(), eq(USER_ID)))
            whenever(lockPatternUtils.verifyCredential(any(), eq(USER_ID), anyInt()))
                .thenReturn(result)
            whenever(lockPatternUtils.verifyTiedProfileChallenge(any(), eq(USER_ID), anyInt()))
                .thenReturn(result)
            whenever(
                    lockPatternUtils.verifyGatekeeperPasswordHandle(
                        anyLong(),
                        anyLong(),
                        eq(USER_ID),
                    )
                )
                .thenReturn(result)
            whenever(lockPatternUtils.setLockoutAttemptDeadline(anyInt(), anyInt())).thenAnswer {
                systemClock.elapsedRealtime() + (it.arguments[1] as Int)
@@ -130,7 +156,10 @@ class CredentialInteractorImplTest : SysuiTestCase() {
            // checks prevents the method from returning
            val statusList = mutableListOf<CredentialStatus>()
            interactor
            .verifyCredential(pinRequest(), LockscreenCredential.createPin("1234"))
                .verifyCredential(
                    pinRequest(credentialOwner),
                    LockscreenCredential.createPin("1234"),
                )
                .toList(statusList)

            val last = statusList.removeLastOrNull()
@@ -154,10 +183,13 @@ class CredentialInteractorImplTest : SysuiTestCase() {
                    // messages are in the throttled errors, so the final Error.error is empty
                    assertThat(failedResult.error).isEmpty()
                    assertThat(statusList).isNotEmpty()
                assertThat(statusList.filterIsInstance(CredentialStatus.Fail.Throttled::class.java))
                    assertThat(
                            statusList.filterIsInstance(CredentialStatus.Fail.Throttled::class.java)
                        )
                        .hasSize(statusList.size)

                verify(lockPatternUtils).setLockoutAttemptDeadline(eq(USER_ID), eq(result.timeout))
                    verify(lockPatternUtils)
                        .setLockoutAttemptDeadline(eq(USER_ID), eq(result.timeout))
                } else { // failed
                    assertThat(failedResult.error)
                        .matches(Regex("(.*)try again(.*)", RegexOption.IGNORE_CASE).toPattern())
@@ -212,11 +244,11 @@ class CredentialInteractorImplTest : SysuiTestCase() {
    }
}

private fun pinRequest(): BiometricPromptRequest.Credential.Pin =
private fun pinRequest(credentialOwner: Int = USER_ID): BiometricPromptRequest.Credential.Pin =
    BiometricPromptRequest.Credential.Pin(
        promptInfo(),
        BiometricUserInfo(USER_ID),
        BiometricOperationInfo(OPERATION_ID)
        BiometricUserInfo(userId = USER_ID, deviceCredentialOwnerId = credentialOwner),
        BiometricOperationInfo(OPERATION_ID),
    )

private fun goodCredential(
+6 −4
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() {
    private val fingerprintRepository = FakeFingerprintPropertyRepository()
    private val promptRepository = FakePromptRepository()
    private val fakeExecutor = FakeExecutor(FakeSystemClock())
    private val credentialInteractor = FakeCredentialInteractor()

    private lateinit var displayStateRepository: FakeDisplayStateRepository
    private lateinit var displayRepository: FakeDisplayRepository
@@ -99,8 +100,9 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() {
            PromptSelectorInteractorImpl(
                fingerprintRepository,
                displayStateInteractor,
                credentialInteractor,
                promptRepository,
                lockPatternUtils
                lockPatternUtils,
            )
    }

@@ -134,13 +136,13 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() {
        testScope.runTest {
            useBiometricsAndReset(
                allowCredentialFallback = true,
                setComponentNameForConfirmDeviceCredentialActivity = true
                setComponentNameForConfirmDeviceCredentialActivity = true,
            )
        }

    private fun TestScope.useBiometricsAndReset(
        allowCredentialFallback: Boolean,
        setComponentNameForConfirmDeviceCredentialActivity: Boolean = false
        setComponentNameForConfirmDeviceCredentialActivity: Boolean = false,
    ) {
        setUserCredentialType(isPassword = true)

@@ -357,7 +359,7 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() {

    private fun setPrompt(
        info: PromptInfo = basicPromptInfo(),
        onSwitchToCredential: Boolean = false
        onSwitchToCredential: Boolean = false,
    ) {
        interactor.setPrompt(
            info,
+1 −1
Original line number Diff line number Diff line
@@ -323,7 +323,7 @@ public class AuthContainerView extends LinearLayout
        final boolean isLandscape = mContext.getResources().getConfiguration().orientation
                == Configuration.ORIENTATION_LANDSCAPE;
        mPromptSelectorInteractorProvider = promptSelectorInteractorProvider;
        mPromptSelectorInteractorProvider.get().setPrompt(mConfig.mPromptInfo, mEffectiveUserId,
        mPromptSelectorInteractorProvider.get().setPrompt(mConfig.mPromptInfo, mConfig.mUserId,
                getRequestId(), biometricModalities, mConfig.mOperationId, mConfig.mOpPackageName,
                false /*onSwitchToCredential*/, isLandscape);

Loading