blob: f612f9afed7740ac31dde6c86914b8cacf112098 [file] [log] [blame]
/*
* 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.bouncer.domain.interactor
import android.hardware.biometrics.BiometricSourceType
import android.os.CountDownTimer
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardSecurityModel.SecurityMode
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.biometrics.data.repository.FacePropertyRepository
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.bouncer.data.repository.BouncerMessageRepository
import com.android.systemui.bouncer.shared.model.BouncerMessageModel
import com.android.systemui.bouncer.shared.model.Message
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags.REVAMPED_BOUNCER_MESSAGES
import com.android.systemui.flags.SystemPropertiesHelper
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.TrustRepository
import com.android.systemui.res.R.string.bouncer_face_not_recognized
import com.android.systemui.res.R.string.keyguard_enter_password
import com.android.systemui.res.R.string.keyguard_enter_pattern
import com.android.systemui.res.R.string.keyguard_enter_pin
import com.android.systemui.res.R.string.kg_bio_too_many_attempts_password
import com.android.systemui.res.R.string.kg_bio_too_many_attempts_pattern
import com.android.systemui.res.R.string.kg_bio_too_many_attempts_pin
import com.android.systemui.res.R.string.kg_bio_try_again_or_password
import com.android.systemui.res.R.string.kg_bio_try_again_or_pattern
import com.android.systemui.res.R.string.kg_bio_try_again_or_pin
import com.android.systemui.res.R.string.kg_face_locked_out
import com.android.systemui.res.R.string.kg_fp_not_recognized
import com.android.systemui.res.R.string.kg_primary_auth_locked_out_password
import com.android.systemui.res.R.string.kg_primary_auth_locked_out_pattern
import com.android.systemui.res.R.string.kg_primary_auth_locked_out_pin
import com.android.systemui.res.R.string.kg_prompt_after_dpm_lock
import com.android.systemui.res.R.string.kg_prompt_after_update_password
import com.android.systemui.res.R.string.kg_prompt_after_update_pattern
import com.android.systemui.res.R.string.kg_prompt_after_update_pin
import com.android.systemui.res.R.string.kg_prompt_after_user_lockdown_password
import com.android.systemui.res.R.string.kg_prompt_after_user_lockdown_pattern
import com.android.systemui.res.R.string.kg_prompt_after_user_lockdown_pin
import com.android.systemui.res.R.string.kg_prompt_auth_timeout
import com.android.systemui.res.R.string.kg_prompt_password_auth_timeout
import com.android.systemui.res.R.string.kg_prompt_pattern_auth_timeout
import com.android.systemui.res.R.string.kg_prompt_pin_auth_timeout
import com.android.systemui.res.R.string.kg_prompt_reason_restart_password
import com.android.systemui.res.R.string.kg_prompt_reason_restart_pattern
import com.android.systemui.res.R.string.kg_prompt_reason_restart_pin
import com.android.systemui.res.R.string.kg_prompt_unattended_update
import com.android.systemui.res.R.string.kg_too_many_failed_attempts_countdown
import com.android.systemui.res.R.string.kg_trust_agent_disabled
import com.android.systemui.res.R.string.kg_unlock_with_password_or_fp
import com.android.systemui.res.R.string.kg_unlock_with_pattern_or_fp
import com.android.systemui.res.R.string.kg_unlock_with_pin_or_fp
import com.android.systemui.res.R.string.kg_wrong_input_try_fp_suggestion
import com.android.systemui.res.R.string.kg_wrong_password_try_again
import com.android.systemui.res.R.string.kg_wrong_pattern_try_again
import com.android.systemui.res.R.string.kg_wrong_pin_try_again
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.kotlin.Quint
import javax.inject.Inject
import kotlin.math.roundToInt
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
private const val SYS_BOOT_REASON_PROP = "sys.boot.reason.last"
private const val REBOOT_MAINLINE_UPDATE = "reboot,mainline_update"
private const val TAG = "BouncerMessageInteractor"
@SysUISingleton
class BouncerMessageInteractor
@Inject
constructor(
private val repository: BouncerMessageRepository,
private val userRepository: UserRepository,
private val countDownTimerUtil: CountDownTimerUtil,
private val featureFlags: FeatureFlags,
private val updateMonitor: KeyguardUpdateMonitor,
trustRepository: TrustRepository,
biometricSettingsRepository: BiometricSettingsRepository,
private val systemPropertiesHelper: SystemPropertiesHelper,
primaryBouncerInteractor: PrimaryBouncerInteractor,
@Application private val applicationScope: CoroutineScope,
private val facePropertyRepository: FacePropertyRepository,
deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
faceAuthRepository: DeviceEntryFaceAuthRepository,
private val securityModel: KeyguardSecurityModel,
) {
private val isFingerprintAuthCurrentlyAllowed =
deviceEntryFingerprintAuthRepository.isLockedOut
.isFalse()
.and(biometricSettingsRepository.isFingerprintAuthCurrentlyAllowed)
.stateIn(applicationScope, SharingStarted.Eagerly, false)
private val currentSecurityMode
get() = securityModel.getSecurityMode(currentUserId)
private val currentUserId
get() = userRepository.getSelectedUserInfo().id
private val kumCallback =
object : KeyguardUpdateMonitorCallback() {
override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType?) {
repository.setMessage(
when (biometricSourceType) {
BiometricSourceType.FINGERPRINT ->
incorrectFingerprintInput(currentSecurityMode)
BiometricSourceType.FACE ->
incorrectFaceInput(
currentSecurityMode,
isFingerprintAuthCurrentlyAllowed.value
)
else ->
defaultMessage(
currentSecurityMode,
isFingerprintAuthCurrentlyAllowed.value
)
}
)
}
override fun onBiometricAcquired(
biometricSourceType: BiometricSourceType?,
acquireInfo: Int
) {
super.onBiometricAcquired(biometricSourceType, acquireInfo)
}
override fun onBiometricAuthenticated(
userId: Int,
biometricSourceType: BiometricSourceType?,
isStrongBiometric: Boolean
) {
repository.setMessage(defaultMessage)
}
}
private val isAnyBiometricsEnabledAndEnrolled =
biometricSettingsRepository.isFaceAuthEnrolledAndEnabled.or(
biometricSettingsRepository.isFingerprintEnrolledAndEnabled
)
private val wasRebootedForMainlineUpdate
get() = systemPropertiesHelper.get(SYS_BOOT_REASON_PROP) == REBOOT_MAINLINE_UPDATE
private val isFaceAuthClass3
get() = facePropertyRepository.sensorInfo.value?.strength == SensorStrength.STRONG
private val initialBouncerMessage: Flow<BouncerMessageModel> =
combine(
biometricSettingsRepository.authenticationFlags,
trustRepository.isCurrentUserTrustManaged,
isAnyBiometricsEnabledAndEnrolled,
deviceEntryFingerprintAuthRepository.isLockedOut,
faceAuthRepository.isLockedOut,
::Quint
)
.map { (flags, _, biometricsEnrolledAndEnabled, fpLockedOut, faceLockedOut) ->
val isTrustUsuallyManaged = trustRepository.isCurrentUserTrustUsuallyManaged.value
val trustOrBiometricsAvailable =
(isTrustUsuallyManaged || biometricsEnrolledAndEnabled)
return@map if (
trustOrBiometricsAvailable && flags.isPrimaryAuthRequiredAfterReboot
) {
if (wasRebootedForMainlineUpdate) {
authRequiredForMainlineUpdate(currentSecurityMode)
} else {
authRequiredAfterReboot(currentSecurityMode)
}
} else if (trustOrBiometricsAvailable && flags.isPrimaryAuthRequiredAfterTimeout) {
authRequiredAfterPrimaryAuthTimeout(currentSecurityMode)
} else if (flags.isPrimaryAuthRequiredAfterDpmLockdown) {
authRequiredAfterAdminLockdown(currentSecurityMode)
} else if (
trustOrBiometricsAvailable && flags.primaryAuthRequiredForUnattendedUpdate
) {
authRequiredForUnattendedUpdate(currentSecurityMode)
} else if (fpLockedOut) {
class3AuthLockedOut(currentSecurityMode)
} else if (faceLockedOut) {
if (isFaceAuthClass3) {
class3AuthLockedOut(currentSecurityMode)
} else {
faceLockedOut(currentSecurityMode, isFingerprintAuthCurrentlyAllowed.value)
}
} else if (
trustOrBiometricsAvailable &&
flags.strongerAuthRequiredAfterNonStrongBiometricsTimeout
) {
nonStrongAuthTimeout(
currentSecurityMode,
isFingerprintAuthCurrentlyAllowed.value
)
} else if (isTrustUsuallyManaged && flags.someAuthRequiredAfterUserRequest) {
trustAgentDisabled(currentSecurityMode, isFingerprintAuthCurrentlyAllowed.value)
} else if (isTrustUsuallyManaged && flags.someAuthRequiredAfterTrustAgentExpired) {
trustAgentDisabled(currentSecurityMode, isFingerprintAuthCurrentlyAllowed.value)
} else if (trustOrBiometricsAvailable && flags.isInUserLockdown) {
authRequiredAfterUserLockdown(currentSecurityMode)
} else {
defaultMessage
}
}
fun onPrimaryAuthLockedOut(secondsBeforeLockoutReset: Long) {
if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
val callback =
object : CountDownTimerCallback {
override fun onFinish() {
repository.setMessage(defaultMessage)
}
override fun onTick(millisUntilFinished: Long) {
val secondsRemaining = (millisUntilFinished / 1000.0).roundToInt()
val message = primaryAuthLockedOut(currentSecurityMode)
message.message?.animate = false
message.message?.formatterArgs =
mutableMapOf<String, Any>(Pair("count", secondsRemaining))
repository.setMessage(message)
}
}
countDownTimerUtil.startNewTimer(secondsBeforeLockoutReset * 1000, 1000, callback)
}
fun onPrimaryAuthIncorrectAttempt() {
if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
repository.setMessage(
incorrectSecurityInput(currentSecurityMode, isFingerprintAuthCurrentlyAllowed.value)
)
}
fun setFingerprintAcquisitionMessage(value: String?) {
if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
repository.setMessage(
defaultMessage(currentSecurityMode, value, isFingerprintAuthCurrentlyAllowed.value)
)
}
fun setFaceAcquisitionMessage(value: String?) {
if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
repository.setMessage(
defaultMessage(currentSecurityMode, value, isFingerprintAuthCurrentlyAllowed.value)
)
}
fun setCustomMessage(value: String?) {
if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
repository.setMessage(
defaultMessage(currentSecurityMode, value, isFingerprintAuthCurrentlyAllowed.value)
)
}
private val defaultMessage: BouncerMessageModel
get() = defaultMessage(currentSecurityMode, isFingerprintAuthCurrentlyAllowed.value)
fun onPrimaryBouncerUserInput() {
if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
repository.setMessage(defaultMessage)
}
val bouncerMessage = repository.bouncerMessage
init {
updateMonitor.registerCallback(kumCallback)
combine(primaryBouncerInteractor.isShowing, initialBouncerMessage) { showing, bouncerMessage
->
if (showing) {
bouncerMessage
} else {
null
}
}
.filterNotNull()
.onEach { repository.setMessage(it) }
.launchIn(applicationScope)
}
}
interface CountDownTimerCallback {
fun onFinish()
fun onTick(millisUntilFinished: Long)
}
@SysUISingleton
open class CountDownTimerUtil @Inject constructor() {
/**
* Start a new count down timer that runs for [millisInFuture] with a tick every
* [millisInterval]
*/
fun startNewTimer(
millisInFuture: Long,
millisInterval: Long,
callback: CountDownTimerCallback,
): CountDownTimer {
return object : CountDownTimer(millisInFuture, millisInterval) {
override fun onFinish() = callback.onFinish()
override fun onTick(millisUntilFinished: Long) =
callback.onTick(millisUntilFinished)
}
.start()
}
}
private fun Flow<Boolean>.or(anotherFlow: Flow<Boolean>) =
this.combine(anotherFlow) { a, b -> a || b }
private fun Flow<Boolean>.and(anotherFlow: Flow<Boolean>) =
this.combine(anotherFlow) { a, b -> a && b }
private fun Flow<Boolean>.isFalse() = this.map { !it }
private fun defaultMessage(
securityMode: SecurityMode,
secondaryMessage: String?,
fpAuthIsAllowed: Boolean
): BouncerMessageModel {
return BouncerMessageModel(
message =
Message(
messageResId = defaultMessage(securityMode, fpAuthIsAllowed).message?.messageResId,
animate = false
),
secondaryMessage = Message(message = secondaryMessage, animate = false)
)
}
private fun defaultMessage(
securityMode: SecurityMode,
fpAuthIsAllowed: Boolean
): BouncerMessageModel {
return if (fpAuthIsAllowed) {
defaultMessageWithFingerprint(securityMode)
} else
when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
SecurityMode.Password -> Pair(keyguard_enter_password, 0)
SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
else -> Pair(0, 0)
}.toMessage()
}
private fun defaultMessageWithFingerprint(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, 0)
SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, 0)
SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, 0)
else -> Pair(0, 0)
}.toMessage()
}
private fun incorrectSecurityInput(
securityMode: SecurityMode,
fpAuthIsAllowed: Boolean
): BouncerMessageModel {
return if (fpAuthIsAllowed) {
incorrectSecurityInputWithFingerprint(securityMode)
} else
when (securityMode) {
SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, 0)
SecurityMode.Password -> Pair(kg_wrong_password_try_again, 0)
SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, 0)
else -> Pair(0, 0)
}.toMessage()
}
private fun incorrectSecurityInputWithFingerprint(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, kg_wrong_input_try_fp_suggestion)
SecurityMode.Password -> Pair(kg_wrong_password_try_again, kg_wrong_input_try_fp_suggestion)
SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, kg_wrong_input_try_fp_suggestion)
else -> Pair(0, 0)
}.toMessage()
}
private fun incorrectFingerprintInput(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pattern)
SecurityMode.Password -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_password)
SecurityMode.PIN -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pin)
else -> Pair(0, 0)
}.toMessage()
}
private fun incorrectFaceInput(
securityMode: SecurityMode,
fpAuthIsAllowed: Boolean
): BouncerMessageModel {
return if (fpAuthIsAllowed) incorrectFaceInputWithFingerprintAllowed(securityMode)
else
when (securityMode) {
SecurityMode.Pattern -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pattern)
SecurityMode.Password -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_password)
SecurityMode.PIN -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pin)
else -> Pair(0, 0)
}.toMessage()
}
private fun incorrectFaceInputWithFingerprintAllowed(
securityMode: SecurityMode
): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, bouncer_face_not_recognized)
SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, bouncer_face_not_recognized)
SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, bouncer_face_not_recognized)
else -> Pair(0, 0)
}.toMessage()
}
private fun biometricLockout(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_bio_too_many_attempts_pattern)
SecurityMode.Password -> Pair(keyguard_enter_password, kg_bio_too_many_attempts_password)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_bio_too_many_attempts_pin)
else -> Pair(0, 0)
}.toMessage()
}
private fun authRequiredAfterReboot(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_reason_restart_pattern)
SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_reason_restart_password)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin)
else -> Pair(0, 0)
}.toMessage()
}
private fun authRequiredAfterAdminLockdown(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_dpm_lock)
SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_after_dpm_lock)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock)
else -> Pair(0, 0)
}.toMessage()
}
private fun authRequiredAfterUserLockdown(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern)
SecurityMode.Password ->
Pair(keyguard_enter_password, kg_prompt_after_user_lockdown_password)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin)
else -> Pair(0, 0)
}.toMessage()
}
private fun authRequiredForUnattendedUpdate(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_unattended_update)
SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_unattended_update)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_unattended_update)
else -> Pair(0, 0)
}.toMessage()
}
private fun authRequiredForMainlineUpdate(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_update_pattern)
SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_after_update_password)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_update_pin)
else -> Pair(0, 0)
}.toMessage()
}
private fun authRequiredAfterPrimaryAuthTimeout(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_pattern_auth_timeout)
SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_password_auth_timeout)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout)
else -> Pair(0, 0)
}.toMessage()
}
private fun nonStrongAuthTimeout(
securityMode: SecurityMode,
fpAuthIsAllowed: Boolean
): BouncerMessageModel {
return if (fpAuthIsAllowed) {
nonStrongAuthTimeoutWithFingerprintAllowed(securityMode)
} else
when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_auth_timeout)
SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_auth_timeout)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_auth_timeout)
else -> Pair(0, 0)
}.toMessage()
}
fun nonStrongAuthTimeoutWithFingerprintAllowed(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_prompt_auth_timeout)
SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_prompt_auth_timeout)
SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_prompt_auth_timeout)
else -> Pair(0, 0)
}.toMessage()
}
private fun faceLockedOut(
securityMode: SecurityMode,
fpAuthIsAllowed: Boolean
): BouncerMessageModel {
return if (fpAuthIsAllowed) faceLockedOutButFingerprintAvailable(securityMode)
else
when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_face_locked_out)
SecurityMode.Password -> Pair(keyguard_enter_password, kg_face_locked_out)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_face_locked_out)
else -> Pair(0, 0)
}.toMessage()
}
private fun faceLockedOutButFingerprintAvailable(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_face_locked_out)
SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_face_locked_out)
SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_face_locked_out)
else -> Pair(0, 0)
}.toMessage()
}
private fun class3AuthLockedOut(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_bio_too_many_attempts_pattern)
SecurityMode.Password -> Pair(keyguard_enter_password, kg_bio_too_many_attempts_password)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_bio_too_many_attempts_pin)
else -> Pair(0, 0)
}.toMessage()
}
private fun trustAgentDisabled(
securityMode: SecurityMode,
fpAuthIsAllowed: Boolean
): BouncerMessageModel {
return if (fpAuthIsAllowed) trustAgentDisabledWithFingerprintAllowed(securityMode)
else
when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_trust_agent_disabled)
SecurityMode.Password -> Pair(keyguard_enter_password, kg_trust_agent_disabled)
SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_trust_agent_disabled)
else -> Pair(0, 0)
}.toMessage()
}
private fun trustAgentDisabledWithFingerprintAllowed(
securityMode: SecurityMode
): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_trust_agent_disabled)
SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_trust_agent_disabled)
SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_trust_agent_disabled)
else -> Pair(0, 0)
}.toMessage()
}
private fun primaryAuthLockedOut(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern ->
Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pattern)
SecurityMode.Password ->
Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_password)
SecurityMode.PIN ->
Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pin)
else -> Pair(0, 0)
}.toMessage()
}
private fun Pair<Int, Int>.toMessage(): BouncerMessageModel {
return BouncerMessageModel(
message = Message(messageResId = this.first, animate = false),
secondaryMessage = Message(messageResId = this.second, animate = false)
)
}