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

Commit 54b6be2d authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Fix BP implicit flow failure" into udc-qpr-dev am: 542f1376

parents 9ee08dd6 542f1376
Loading
Loading
Loading
Loading
+10 −17
Original line number Diff line number Diff line
@@ -78,17 +78,6 @@ constructor(

    private val _isOverlayTouched: MutableStateFlow<Boolean> = MutableStateFlow(false)

    /**
     * If the API caller or the user's personal preferences require explicit confirmation after
     * successful authentication.
     */
    val isConfirmationRequired: Flow<Boolean> =
        combine(_isOverlayTouched, promptSelectorInteractor.isConfirmationRequired) {
            isOverlayTouched,
            isConfirmationRequired ->
            !isOverlayTouched && isConfirmationRequired
        }

    /** The kind of credential the user has. */
    val credentialKind: Flow<PromptKind> = promptSelectorInteractor.credentialKind

@@ -137,6 +126,15 @@ constructor(
            }
            .distinctUntilChanged()

    /**
     * If the API caller or the user's personal preferences require explicit confirmation after
     * successful authentication. Confirmation always required when in explicit flow.
     */
    val isConfirmationRequired: Flow<Boolean> =
        combine(_isOverlayTouched, size) { isOverlayTouched, size ->
            !isOverlayTouched && size.isNotSmall
        }

    /** Title for the prompt. */
    val title: Flow<String> =
        promptSelectorInteractor.prompt.map { it?.title ?: "" }.distinctUntilChanged()
@@ -170,12 +168,7 @@ constructor(
            .distinctUntilChanged()

    /** If the icon can be used as a confirmation button. */
    val isIconConfirmButton: Flow<Boolean> =
        combine(size, promptSelectorInteractor.isConfirmationRequired) {
            size,
            isConfirmationRequired ->
            size.isNotSmall && isConfirmationRequired
        }
    val isIconConfirmButton: Flow<Boolean> = size.map { it.isNotSmall }.distinctUntilChanged()

    /** If the negative button should be shown. */
    val isNegativeButtonVisible: Flow<Boolean> =
+80 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.hardware.biometrics.PromptInfo
import android.hardware.face.FaceSensorPropertiesInternal
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.view.HapticFeedbackConstants
import android.view.MotionEvent
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.SysuiTestCase
@@ -499,6 +500,81 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
        assertThat(canTryAgain).isFalse()
    }

    @Test
    fun auto_confirm_authentication_when_finger_down() = runGenericTest {
        val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)

        // No icon button when face only, can't confirm before auth
        if (!testCase.isFaceOnly) {
            viewModel.onOverlayTouch(obtainMotionEvent(MotionEvent.ACTION_DOWN))
        }
        viewModel.showAuthenticated(testCase.authenticatedModality, 0)

        val authenticating by collectLastValue(viewModel.isAuthenticating)
        val authenticated by collectLastValue(viewModel.isAuthenticated)
        val message by collectLastValue(viewModel.message)
        val size by collectLastValue(viewModel.size)
        val legacyState by collectLastValue(viewModel.legacyState)
        val canTryAgain by collectLastValue(viewModel.canTryAgainNow)

        assertThat(authenticating).isFalse()
        assertThat(canTryAgain).isFalse()
        assertThat(authenticated?.isAuthenticated).isTrue()

        if (testCase.isFaceOnly && expectConfirmation) {
            assertThat(legacyState).isEqualTo(AuthBiometricView.STATE_PENDING_CONFIRMATION)

            assertThat(size).isEqualTo(PromptSize.MEDIUM)
            assertButtonsVisible(
                cancel = true,
                confirm = true,
            )

            viewModel.confirmAuthenticated()
            assertThat(message).isEqualTo(PromptMessage.Empty)
            assertButtonsVisible()
        } else {
            assertThat(legacyState).isEqualTo(AuthBiometricView.STATE_AUTHENTICATED)
        }
    }

    @Test
    fun cannot_auto_confirm_authentication_when_finger_up() = runGenericTest {
        val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)

        // No icon button when face only, can't confirm before auth
        if (!testCase.isFaceOnly) {
            viewModel.onOverlayTouch(obtainMotionEvent(MotionEvent.ACTION_DOWN))
            viewModel.onOverlayTouch(obtainMotionEvent(MotionEvent.ACTION_UP))
        }
        viewModel.showAuthenticated(testCase.authenticatedModality, 0)

        val authenticating by collectLastValue(viewModel.isAuthenticating)
        val authenticated by collectLastValue(viewModel.isAuthenticated)
        val message by collectLastValue(viewModel.message)
        val size by collectLastValue(viewModel.size)
        val legacyState by collectLastValue(viewModel.legacyState)
        val canTryAgain by collectLastValue(viewModel.canTryAgainNow)

        assertThat(authenticated?.needsUserConfirmation).isEqualTo(expectConfirmation)
        if (expectConfirmation) {
            assertThat(size).isEqualTo(PromptSize.MEDIUM)
            assertButtonsVisible(
                cancel = true,
                confirm = true,
            )

            viewModel.confirmAuthenticated()
            assertThat(message).isEqualTo(PromptMessage.Empty)
            assertButtonsVisible()
        }

        assertThat(authenticating).isFalse()
        assertThat(authenticated?.isAuthenticated).isTrue()
        assertThat(legacyState).isEqualTo(AuthBiometricView.STATE_AUTHENTICATED)
        assertThat(canTryAgain).isFalse()
    }

    @Test
    fun cannot_confirm_unless_authenticated() = runGenericTest {
        val authenticating by collectLastValue(viewModel.isAuthenticating)
@@ -679,6 +755,10 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
        testScope.runTest { block() }
    }

    /** Obtain a MotionEvent with the specified MotionEvent action constant */
    private fun obtainMotionEvent(action: Int): MotionEvent =
        MotionEvent.obtain(0, 0, action, 0f, 0f, 0)

    companion object {
        @JvmStatic
        @Parameterized.Parameters(name = "{0}")