Don't show lockout messages over occluding apps

When fingerprint lockout occurs, the bouncer will show immediately,
so we filter out the fingerprint lockout messages from showing
over occluding apps so that we don't flicker the chipbar message.

Test: atest OccludingAppDeviceEntryInteractorTest
Fixes: 292545014
Change-Id: I229ce6dd55ff584a4579ee212b4dbad818ae67b3
This commit is contained in:
Beverly
2023-07-24 18:20:02 +00:00
parent b7d2d3e458
commit d459a3672f
4 changed files with 51 additions and 11 deletions

View File

@@ -20,6 +20,7 @@ package com.android.systemui.keyguard.domain.interactor
import android.content.res.Resources
import android.hardware.biometrics.BiometricSourceType
import android.hardware.biometrics.BiometricSourceType.FINGERPRINT
import android.hardware.fingerprint.FingerprintManager
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED
import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
@@ -129,7 +130,14 @@ data class BiometricMessage(
val type: BiometricMessageType,
val id: Int,
val message: String?,
)
) {
fun isFingerprintLockoutMessage(): Boolean {
return source == FINGERPRINT &&
type == BiometricMessageType.ERROR &&
(id == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT ||
id == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
}
}
enum class BiometricMessageType {
HELP,

View File

@@ -18,7 +18,6 @@ package com.android.systemui.keyguard.domain.interactor
import android.content.Context
import android.content.Intent
import android.hardware.fingerprint.FingerprintManager
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.dagger.SysUISingleton
@@ -35,6 +34,7 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
@@ -74,15 +74,13 @@ constructor(
private val fingerprintLockoutEvents: Flow<Unit> =
fingerprintAuthRepository.authenticationStatus
.ifKeyguardOccludedByApp()
.filter {
it is ErrorFingerprintAuthenticationStatus &&
(it.msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT ||
it.msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
}
.filter { it is ErrorFingerprintAuthenticationStatus && it.isLockoutMessage() }
.map {} // maps FingerprintAuthenticationStatus => Unit
val message: Flow<BiometricMessage?> =
merge(
biometricMessageInteractor.fingerprintErrorMessage,
biometricMessageInteractor.fingerprintErrorMessage.filterNot {
it.isFingerprintLockoutMessage()
},
biometricMessageInteractor.fingerprintFailMessage,
biometricMessageInteractor.fingerprintHelpMessage,
)

View File

@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.shared.model
import android.hardware.fingerprint.FingerprintManager
import android.os.SystemClock.elapsedRealtime
/**
@@ -49,4 +50,9 @@ data class ErrorFingerprintAuthenticationStatus(
val msg: String? = null,
// present to break equality check if the same error occurs repeatedly.
val createdAt: Long = elapsedRealtime(),
) : FingerprintAuthenticationStatus()
) : FingerprintAuthenticationStatus() {
fun isLockoutMessage(): Boolean {
return msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT ||
msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT
}
}

View File

@@ -233,12 +233,12 @@ class OccludingAppDeviceEntryInteractorTest : SysuiTestCase() {
// ERROR message
fingerprintAuthRepository.setAuthenticationStatus(
ErrorFingerprintAuthenticationStatus(
FingerprintManager.FINGERPRINT_ERROR_LOCKOUT,
FingerprintManager.FINGERPRINT_ERROR_CANCELED,
"testError",
)
)
assertThat(message?.source).isEqualTo(BiometricSourceType.FINGERPRINT)
assertThat(message?.id).isEqualTo(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)
assertThat(message?.id).isEqualTo(FingerprintManager.FINGERPRINT_ERROR_CANCELED)
assertThat(message?.message).isEqualTo("testError")
assertThat(message?.type).isEqualTo(BiometricMessageType.ERROR)
@@ -262,6 +262,34 @@ class OccludingAppDeviceEntryInteractorTest : SysuiTestCase() {
assertThat(message?.type).isEqualTo(BiometricMessageType.FAIL)
}
@Test
fun message_fpError_lockoutFilteredOut() =
testScope.runTest {
val message by collectLastValue(underTest.message)
givenOnOccludingApp(true)
givenPrimaryAuthRequired(false)
runCurrent()
// permanent lockout error message
fingerprintAuthRepository.setAuthenticationStatus(
ErrorFingerprintAuthenticationStatus(
FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT,
"testPermanentLockoutMessageFiltered",
)
)
assertThat(message).isNull()
// temporary lockout error message
fingerprintAuthRepository.setAuthenticationStatus(
ErrorFingerprintAuthenticationStatus(
FingerprintManager.FINGERPRINT_ERROR_LOCKOUT,
"testLockoutMessageFiltered",
)
)
assertThat(message).isNull()
}
private fun givenOnOccludingApp(isOnOccludingApp: Boolean) {
keyguardRepository.setKeyguardOccluded(isOnOccludingApp)
keyguardRepository.setKeyguardShowing(isOnOccludingApp)