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:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user