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

Commit 97c7a5cd authored by Joe Bolinger's avatar Joe Bolinger
Browse files

Show only first face error message for coex.

Fix: 291126484
Test: atest PromptHistoryImplTest PromptViewModelTest
Test: manual (use bp test app, fail coex multiple times, retry face, and verify error message)
Change-Id: I0349ec3be6d0d0312c87f02ec51043be2070fd72
parent f29c879c
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -479,10 +479,10 @@ private class Spaghetti(
                failureReason,
                messageAfterError = modalities.asDefaultHelpMessage(applicationContext),
                authenticateAfterError = modalities.hasFingerprint,
                suppressIf = { currentMessage ->
                suppressIf = { currentMessage, history ->
                    modalities.hasFaceAndFingerprint &&
                        failedModality == BiometricModality.Face &&
                        currentMessage.isError
                        (currentMessage.isError || history.faceFailed)
                },
                failedModality = failedModality,
            )
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.biometrics.ui.viewmodel

import com.android.systemui.biometrics.shared.model.BiometricModality

/** Contains metadata about key events that have occurred while biometric prompt is showing. */
interface PromptHistory {

    /** If face authentication has failed at least once. */
    val faceFailed: Boolean

    /** If fingerprint authentication has failed at least once. */
    val fingerprintFailed: Boolean
}

class PromptHistoryImpl : PromptHistory {
    private var failures = mutableSetOf<BiometricModality>()

    override val faceFailed
        get() = failures.contains(BiometricModality.Face)

    override val fingerprintFailed
        get() = failures.contains(BiometricModality.Fingerprint)

    /** Record a failure event. */
    fun failure(modality: BiometricModality) {
        if (modality != BiometricModality.None) {
            failures.add(modality)
        }
    }
}
+6 −3
Original line number Diff line number Diff line
@@ -204,6 +204,7 @@ constructor(
            }
            .distinctUntilChanged()

    private val history = PromptHistoryImpl()
    private var messageJob: Job? = null

    /**
@@ -214,13 +215,13 @@ constructor(
     * is set (or via [showHelp] when not set) after the error is dismissed.
     *
     * The error is ignored if the user has already authenticated or if [suppressIf] is true given
     * the currently showing [PromptMessage].
     * the currently showing [PromptMessage] and [PromptHistory].
     */
    suspend fun showTemporaryError(
        message: String,
        messageAfterError: String,
        authenticateAfterError: Boolean,
        suppressIf: (PromptMessage) -> Boolean = { false },
        suppressIf: (PromptMessage, PromptHistory) -> Boolean = { _, _ -> false },
        hapticFeedback: Boolean = true,
        failedModality: BiometricModality = BiometricModality.None,
    ) = coroutineScope {
@@ -230,7 +231,9 @@ constructor(

        _canTryAgainNow.value = supportsRetry(failedModality)

        if (suppressIf(_message.value)) {
        val suppress = suppressIf(_message.value, history)
        history.failure(failedModality)
        if (suppress) {
            return@coroutineScope
        }

+76 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.biometrics.ui.viewmodel

import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.shared.model.BiometricModality
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

@SmallTest
@RunWith(JUnit4::class)
class PromptHistoryImplTest : SysuiTestCase() {

    private lateinit var history: PromptHistoryImpl

    @Before
    fun setup() {
        history = PromptHistoryImpl()
    }

    @Test
    fun empty() {
        assertThat(history.faceFailed).isFalse()
        assertThat(history.fingerprintFailed).isFalse()
    }

    @Test
    fun faceFailed() =
        repeat(2) {
            history.failure(BiometricModality.None)
            history.failure(BiometricModality.Face)

            assertThat(history.faceFailed).isTrue()
            assertThat(history.fingerprintFailed).isFalse()
        }

    @Test
    fun fingerprintFailed() =
        repeat(2) {
            history.failure(BiometricModality.None)
            history.failure(BiometricModality.Fingerprint)

            assertThat(history.faceFailed).isFalse()
            assertThat(history.fingerprintFailed).isTrue()
        }

    @Test
    fun coexFailed() =
        repeat(2) {
            history.failure(BiometricModality.Face)
            history.failure(BiometricModality.Fingerprint)

            assertThat(history.faceFailed).isTrue()
            assertThat(history.fingerprintFailed).isTrue()

            history.failure(BiometricModality.None)
        }
}
+2 −2
Original line number Diff line number Diff line
@@ -335,7 +335,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
                    error,
                    messageAfterError = "or me",
                    authenticateAfterError = false,
                    suppressIf = { _ -> true },
                    suppressIf = { _, _ -> true },
                )
            }
        }
@@ -364,7 +364,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
                    error,
                    messageAfterError = "$error $afterSuffix",
                    authenticateAfterError = false,
                    suppressIf = { currentMessage -> suppress && currentMessage.isError },
                    suppressIf = { currentMessage, _ -> suppress && currentMessage.isError },
                )
            }
        }