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

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

Merge "Fix Work Profile Biometric Prompt Credential crash" into main

parents bf8112e2 76d28152
Loading
Loading
Loading
Loading
+7 −10
Original line number Original line Diff line number Diff line
@@ -16,7 +16,6 @@
package com.android.systemui.biometrics
package com.android.systemui.biometrics


import android.app.ActivityTaskManager
import android.app.ActivityTaskManager
import android.app.admin.DevicePolicyManager
import android.content.pm.PackageManager
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.content.res.Configuration
import android.hardware.biometrics.BiometricAuthenticator
import android.hardware.biometrics.BiometricAuthenticator
@@ -43,6 +42,8 @@ import androidx.test.filters.SmallTest
import com.android.app.viewcapture.ViewCapture
import com.android.app.viewcapture.ViewCapture
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN
import com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN
import com.android.launcher3.icons.IconProvider
import com.android.launcher3.icons.IconProvider
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
@@ -432,8 +433,7 @@ open class AuthContainerViewTest : SysuiTestCase() {
                .setMoreOptionsButtonListener(fakeExecutor) { _, _ -> isButtonClicked = true }
                .setMoreOptionsButtonListener(fakeExecutor) { _, _ -> isButtonClicked = true }
                .build()
                .build()


        val container =
        val container = initializeFingerprintContainer()
            initializeFingerprintContainer(contentViewWithMoreOptionsButton = contentView)


        waitForIdleSync()
        waitForIdleSync()


@@ -488,8 +488,7 @@ open class AuthContainerViewTest : SysuiTestCase() {
                .build()
                .build()
        val container =
        val container =
            initializeFingerprintContainer(
            initializeFingerprintContainer(
                authenticators = BiometricManager.Authenticators.DEVICE_CREDENTIAL,
                authenticators = BiometricManager.Authenticators.DEVICE_CREDENTIAL
                contentViewWithMoreOptionsButton = contentView,
            )
            )
        waitForIdleSync()
        waitForIdleSync()


@@ -500,8 +499,8 @@ open class AuthContainerViewTest : SysuiTestCase() {
    @Test
    @Test
    fun testCredentialViewUsesEffectiveUserId() {
    fun testCredentialViewUsesEffectiveUserId() {
        whenever(userManager.getCredentialOwnerProfile(anyInt())).thenReturn(200)
        whenever(userManager.getCredentialOwnerProfile(anyInt())).thenReturn(200)
        whenever(lockPatternUtils.getKeyguardStoredPasswordQuality(eq(200)))
        whenever(lockPatternUtils.getCredentialTypeForUser(eq(200)))
            .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
            .thenReturn(CREDENTIAL_TYPE_PATTERN)


        val container =
        val container =
            initializeFingerprintContainer(
            initializeFingerprintContainer(
@@ -578,8 +577,7 @@ open class AuthContainerViewTest : SysuiTestCase() {
        addToView: Boolean = true
        addToView: Boolean = true
    ): TestAuthContainerView {
    ): TestAuthContainerView {
        whenever(userManager.getCredentialOwnerProfile(anyInt())).thenReturn(20)
        whenever(userManager.getCredentialOwnerProfile(anyInt())).thenReturn(20)
        whenever(lockPatternUtils.getKeyguardStoredPasswordQuality(eq(20)))
        whenever(lockPatternUtils.getCredentialTypeForUser(eq(20))).thenReturn(CREDENTIAL_TYPE_PIN)
            .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC)


        // In the credential view, clicking on the background (to cancel authentication) is not
        // In the credential view, clicking on the background (to cancel authentication) is not
        // valid. Thus, the listener should be null, and it should not be in the accessibility
        // valid. Thus, the listener should be null, and it should not be in the accessibility
@@ -599,7 +597,6 @@ open class AuthContainerViewTest : SysuiTestCase() {
        authenticators: Int = BiometricManager.Authenticators.BIOMETRIC_WEAK,
        authenticators: Int = BiometricManager.Authenticators.BIOMETRIC_WEAK,
        addToView: Boolean = true,
        addToView: Boolean = true,
        verticalListContentView: PromptVerticalListContentView? = null,
        verticalListContentView: PromptVerticalListContentView? = null,
        contentViewWithMoreOptionsButton: PromptContentViewWithMoreOptionsButton? = null,
    ) =
    ) =
        initializeContainer(
        initializeContainer(
            TestAuthContainerView(
            TestAuthContainerView(
+5 −5
Original line number Original line Diff line number Diff line
@@ -135,9 +135,9 @@ class CredentialInteractorImplTest : SysuiTestCase() {
    private fun pinCredential(result: VerifyCredentialResponse, credentialOwner: Int = USER_ID) =
    private fun pinCredential(result: VerifyCredentialResponse, credentialOwner: Int = USER_ID) =
        runTest {
        runTest {
            val usedAttempts = 1
            val usedAttempts = 1
            whenever(lockPatternUtils.getCurrentFailedPasswordAttempts(eq(USER_ID)))
            whenever(lockPatternUtils.getCurrentFailedPasswordAttempts(eq(credentialOwner)))
                .thenReturn(usedAttempts)
                .thenReturn(usedAttempts)
            whenever(lockPatternUtils.verifyCredential(any(), eq(USER_ID), anyInt()))
            whenever(lockPatternUtils.verifyCredential(any(), eq(credentialOwner), anyInt()))
                .thenReturn(result)
                .thenReturn(result)
            whenever(lockPatternUtils.verifyTiedProfileChallenge(any(), eq(USER_ID), anyInt()))
            whenever(lockPatternUtils.verifyTiedProfileChallenge(any(), eq(USER_ID), anyInt()))
                .thenReturn(result)
                .thenReturn(result)
@@ -170,7 +170,7 @@ class CredentialInteractorImplTest : SysuiTestCase() {
                assertThat(successfulResult).isNotNull()
                assertThat(successfulResult).isNotNull()
                assertThat(successfulResult!!.hat).isEqualTo(result.gatekeeperHAT)
                assertThat(successfulResult!!.hat).isEqualTo(result.gatekeeperHAT)


                verify(lockPatternUtils).userPresent(eq(USER_ID))
                verify(lockPatternUtils).userPresent(eq(credentialOwner))
                verify(lockPatternUtils)
                verify(lockPatternUtils)
                    .removeGatekeeperPasswordHandle(eq(result.gatekeeperPasswordHandle))
                    .removeGatekeeperPasswordHandle(eq(result.gatekeeperPasswordHandle))
            } else {
            } else {
@@ -190,13 +190,13 @@ class CredentialInteractorImplTest : SysuiTestCase() {
                        .hasSize(statusList.size)
                        .hasSize(statusList.size)


                    verify(lockPatternUtils)
                    verify(lockPatternUtils)
                        .setLockoutAttemptDeadline(eq(USER_ID), eq(result.timeout))
                        .setLockoutAttemptDeadline(eq(credentialOwner), eq(result.timeout))
                } else { // failed
                } else { // failed
                    assertThat(failedResult.error)
                    assertThat(failedResult.error)
                        .matches(Regex("(.*)try again(.*)", RegexOption.IGNORE_CASE).toPattern())
                        .matches(Regex("(.*)try again(.*)", RegexOption.IGNORE_CASE).toPattern())
                    assertThat(statusList).isEmpty()
                    assertThat(statusList).isEmpty()


                    verify(lockPatternUtils).reportFailedPasswordAttempt(eq(USER_ID))
                    verify(lockPatternUtils).reportFailedPasswordAttempt(eq(credentialOwner))
                }
                }
            }
            }
        }
        }
+9 −17
Original line number Original line Diff line number Diff line
@@ -17,13 +17,6 @@ package com.android.systemui.biometrics


import android.Manifest
import android.Manifest
import android.app.ActivityTaskManager
import android.app.ActivityTaskManager
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
import android.content.Context
import android.content.Context
import android.content.pm.PackageManager
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Bitmap
@@ -44,6 +37,9 @@ import android.view.WindowMetrics
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityManager
import android.view.accessibility.AccessibilityManager
import com.android.internal.widget.LockPatternUtils
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.biometrics.shared.model.PromptKind
import com.android.systemui.biometrics.shared.model.PromptKind


object Utils {
object Utils {
@@ -80,7 +76,7 @@ object Utils {
        view.notifySubtreeAccessibilityStateChanged(
        view.notifySubtreeAccessibilityStateChanged(
            view,
            view,
            view,
            view,
            AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE
            AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE,
        )
        )
    }
    }


@@ -94,14 +90,10 @@ object Utils {


    @JvmStatic
    @JvmStatic
    fun getCredentialType(utils: LockPatternUtils, userId: Int): PromptKind =
    fun getCredentialType(utils: LockPatternUtils, userId: Int): PromptKind =
        when (utils.getKeyguardStoredPasswordQuality(userId)) {
        when (utils.getCredentialTypeForUser(userId)) {
            PASSWORD_QUALITY_SOMETHING -> PromptKind.Pattern
            CREDENTIAL_TYPE_PATTERN -> PromptKind.Pattern
            PASSWORD_QUALITY_NUMERIC,
            CREDENTIAL_TYPE_PIN -> PromptKind.Pin
            PASSWORD_QUALITY_NUMERIC_COMPLEX -> PromptKind.Pin
            CREDENTIAL_TYPE_PASSWORD -> PromptKind.Password
            PASSWORD_QUALITY_ALPHABETIC,
            PASSWORD_QUALITY_ALPHANUMERIC,
            PASSWORD_QUALITY_COMPLEX,
            PASSWORD_QUALITY_MANAGED -> PromptKind.Password
            else -> PromptKind.Password
            else -> PromptKind.Password
        }
        }


@@ -112,7 +104,7 @@ object Utils {
    @JvmStatic
    @JvmStatic
    fun <T : SensorPropertiesInternal> findFirstSensorProperties(
    fun <T : SensorPropertiesInternal> findFirstSensorProperties(
        properties: List<T>?,
        properties: List<T>?,
        sensorIds: IntArray
        sensorIds: IntArray,
    ): T? = properties?.firstOrNull { sensorIds.contains(it.sensorId) }
    ): T? = properties?.firstOrNull { sensorIds.contains(it.sensorId) }


    @JvmStatic
    @JvmStatic
+2 −3
Original line number Original line Diff line number Diff line
@@ -72,10 +72,9 @@ constructor(
        // Request LockSettingsService to return the Gatekeeper Password in the
        // Request LockSettingsService to return the Gatekeeper Password in the
        // VerifyCredentialResponse so that we can request a Gatekeeper HAT with the
        // VerifyCredentialResponse so that we can request a Gatekeeper HAT with the
        // Gatekeeper Password and operationId.
        // Gatekeeper Password and operationId.
        var effectiveUserId = request.userInfo.deviceCredentialOwnerId
        val effectiveUserId = request.userInfo.deviceCredentialOwnerId
        val response =
        val response =
            if (Flags.privateSpaceBp() && effectiveUserId != request.userInfo.userId) {
            if (Flags.privateSpaceBp() && effectiveUserId != request.userInfo.userId) {
                effectiveUserId = request.userInfo.userId
                lockPatternUtils.verifyTiedProfileChallenge(
                lockPatternUtils.verifyTiedProfileChallenge(
                    credential,
                    credential,
                    request.userInfo.userId,
                    request.userInfo.userId,
@@ -101,7 +100,7 @@ constructor(
                lockPatternUtils.verifyGatekeeperPasswordHandle(
                lockPatternUtils.verifyGatekeeperPasswordHandle(
                    pwHandle,
                    pwHandle,
                    request.operationInfo.gatekeeperChallenge,
                    request.operationInfo.gatekeeperChallenge,
                    effectiveUserId,
                    request.userInfo.userId,
                )
                )
            val hat = gkResponse.gatekeeperHAT
            val hat = gkResponse.gatekeeperHAT
            lockPatternUtils.removeGatekeeperPasswordHandle(pwHandle)
            lockPatternUtils.removeGatekeeperPasswordHandle(pwHandle)
+6 −1
Original line number Original line Diff line number Diff line
@@ -126,7 +126,12 @@ constructor(
                is PromptKind.Biometric ->
                is PromptKind.Biometric ->
                    BiometricPromptRequest.Biometric(
                    BiometricPromptRequest.Biometric(
                        info = promptInfo,
                        info = promptInfo,
                        userInfo = BiometricUserInfo(userId = userId),
                        userInfo =
                            BiometricUserInfo(
                                userId = userId,
                                deviceCredentialOwnerId =
                                    credentialInteractor.getCredentialOwnerOrSelfId(userId),
                            ),
                        operationInfo = BiometricOperationInfo(gatekeeperChallenge = challenge),
                        operationInfo = BiometricOperationInfo(gatekeeperChallenge = challenge),
                        modalities = kind.activeModalities,
                        modalities = kind.activeModalities,
                        opPackageName = opPackageName,
                        opPackageName = opPackageName,
Loading