Create BouncerMessageFactory to easily create BouncerMessage data model.
Bug: 275600559 Test: pending Change-Id: Ia12e8cd6de851113da718a4bdec6583d8f310160
This commit is contained in:
@@ -2622,6 +2622,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
return mAuthController.isUdfpsSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the FP sensor is non-UDFPS and the device can be unlocked using fingerprint
|
||||
* at this moment.
|
||||
*/
|
||||
public boolean isFingerprintAllowedInBouncer() {
|
||||
return !isUdfpsSupported() && isUnlockingWithFingerprintAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if there's at least one sfps enrollment for the current user.
|
||||
*/
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.keyguard
|
||||
package com.android.systemui.keyguard.bouncer.data.factory
|
||||
|
||||
import android.annotation.IntDef
|
||||
import com.android.keyguard.KeyguardSecurityModel
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode
|
||||
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT
|
||||
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEFAULT
|
||||
@@ -34,6 +35,7 @@ import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART
|
||||
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT
|
||||
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED
|
||||
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST
|
||||
import com.android.keyguard.KeyguardUpdateMonitor
|
||||
import com.android.systemui.R.string.bouncer_face_not_recognized
|
||||
import com.android.systemui.R.string.keyguard_enter_password
|
||||
import com.android.systemui.R.string.keyguard_enter_pattern
|
||||
@@ -71,10 +73,86 @@ import com.android.systemui.R.string.kg_wrong_input_try_fp_suggestion
|
||||
import com.android.systemui.R.string.kg_wrong_password_try_again
|
||||
import com.android.systemui.R.string.kg_wrong_pattern_try_again
|
||||
import com.android.systemui.R.string.kg_wrong_pin_try_again
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
|
||||
import com.android.systemui.keyguard.bouncer.shared.model.Message
|
||||
import javax.inject.Inject
|
||||
|
||||
typealias BouncerMessage = Pair<Int, Int>
|
||||
@SysUISingleton
|
||||
class BouncerMessageFactory
|
||||
@Inject
|
||||
constructor(
|
||||
private val updateMonitor: KeyguardUpdateMonitor,
|
||||
private val securityModel: KeyguardSecurityModel,
|
||||
) {
|
||||
|
||||
fun emptyBouncerMessage(): BouncerMessage = Pair(0, 0)
|
||||
fun createFromPromptReason(
|
||||
@BouncerPromptReason reason: Int,
|
||||
userId: Int,
|
||||
): BouncerMessageModel? {
|
||||
val pair =
|
||||
getBouncerMessage(
|
||||
reason,
|
||||
securityModel.getSecurityMode(userId),
|
||||
updateMonitor.isFingerprintAllowedInBouncer
|
||||
)
|
||||
return pair?.let {
|
||||
BouncerMessageModel(
|
||||
message = Message(messageResId = pair.first),
|
||||
secondaryMessage = Message(messageResId = pair.second)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun createFromString(
|
||||
primaryMsg: String? = null,
|
||||
secondaryMsg: String? = null
|
||||
): BouncerMessageModel =
|
||||
BouncerMessageModel(
|
||||
message = primaryMsg?.let { Message(message = it) },
|
||||
secondaryMessage = secondaryMsg?.let { Message(message = it) },
|
||||
)
|
||||
|
||||
/**
|
||||
* Helper method that provides the relevant bouncer message that should be shown for different
|
||||
* scenarios indicated by [reason]. [securityMode] & [fpAllowedInBouncer] parameters are used to
|
||||
* provide a more specific message.
|
||||
*/
|
||||
private fun getBouncerMessage(
|
||||
@BouncerPromptReason reason: Int,
|
||||
securityMode: SecurityMode,
|
||||
fpAllowedInBouncer: Boolean = false
|
||||
): Pair<Int, Int>? {
|
||||
return when (reason) {
|
||||
PROMPT_REASON_RESTART -> authRequiredAfterReboot(securityMode)
|
||||
PROMPT_REASON_TIMEOUT -> authRequiredAfterPrimaryAuthTimeout(securityMode)
|
||||
PROMPT_REASON_DEVICE_ADMIN -> authRequiredAfterAdminLockdown(securityMode)
|
||||
PROMPT_REASON_USER_REQUEST -> authRequiredAfterUserLockdown(securityMode)
|
||||
PROMPT_REASON_AFTER_LOCKOUT -> biometricLockout(securityMode)
|
||||
PROMPT_REASON_PREPARE_FOR_UPDATE -> authRequiredForUnattendedUpdate(securityMode)
|
||||
PROMPT_REASON_FINGERPRINT_LOCKED_OUT -> fingerprintUnlockUnavailable(securityMode)
|
||||
PROMPT_REASON_FACE_LOCKED_OUT -> faceUnlockUnavailable(securityMode)
|
||||
PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT ->
|
||||
if (fpAllowedInBouncer) incorrectSecurityInputWithFingerprint(securityMode)
|
||||
else incorrectSecurityInput(securityMode)
|
||||
PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT ->
|
||||
if (fpAllowedInBouncer) nonStrongAuthTimeoutWithFingerprintAllowed(securityMode)
|
||||
else nonStrongAuthTimeout(securityMode)
|
||||
PROMPT_REASON_TRUSTAGENT_EXPIRED ->
|
||||
if (fpAllowedInBouncer) trustAgentDisabledWithFingerprintAllowed(securityMode)
|
||||
else trustAgentDisabled(securityMode)
|
||||
PROMPT_REASON_INCORRECT_FACE_INPUT ->
|
||||
if (fpAllowedInBouncer) incorrectFaceInputWithFingerprintAllowed(securityMode)
|
||||
else incorrectFaceInput(securityMode)
|
||||
PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT -> incorrectFingerprintInput(securityMode)
|
||||
PROMPT_REASON_DEFAULT ->
|
||||
if (fpAllowedInBouncer) defaultMessageWithFingerprint(securityMode)
|
||||
else defaultMessage(securityMode)
|
||||
PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT -> primaryAuthLockedOut(securityMode)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@IntDef(
|
||||
@@ -97,48 +175,7 @@ fun emptyBouncerMessage(): BouncerMessage = Pair(0, 0)
|
||||
)
|
||||
annotation class BouncerPromptReason
|
||||
|
||||
/**
|
||||
* Helper method that provides the relevant bouncer message that should be shown for different
|
||||
* scenarios indicated by [reason]. [securityMode] & [fpAllowedInBouncer] parameters are used to
|
||||
* provide a more specific message.
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun getBouncerMessage(
|
||||
@BouncerPromptReason reason: Int,
|
||||
securityMode: SecurityMode,
|
||||
fpAllowedInBouncer: Boolean = false
|
||||
): BouncerMessage {
|
||||
return when (reason) {
|
||||
PROMPT_REASON_RESTART -> authRequiredAfterReboot(securityMode)
|
||||
PROMPT_REASON_TIMEOUT -> authRequiredAfterPrimaryAuthTimeout(securityMode)
|
||||
PROMPT_REASON_DEVICE_ADMIN -> authRequiredAfterAdminLockdown(securityMode)
|
||||
PROMPT_REASON_USER_REQUEST -> authRequiredAfterUserLockdown(securityMode)
|
||||
PROMPT_REASON_AFTER_LOCKOUT -> biometricLockout(securityMode)
|
||||
PROMPT_REASON_PREPARE_FOR_UPDATE -> authRequiredForUnattendedUpdate(securityMode)
|
||||
PROMPT_REASON_FINGERPRINT_LOCKED_OUT -> fingerprintUnlockUnavailable(securityMode)
|
||||
PROMPT_REASON_FACE_LOCKED_OUT -> faceUnlockUnavailable(securityMode)
|
||||
PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT ->
|
||||
if (fpAllowedInBouncer) incorrectSecurityInputWithFingerprint(securityMode)
|
||||
else incorrectSecurityInput(securityMode)
|
||||
PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT ->
|
||||
if (fpAllowedInBouncer) nonStrongAuthTimeoutWithFingerprintAllowed(securityMode)
|
||||
else nonStrongAuthTimeout(securityMode)
|
||||
PROMPT_REASON_TRUSTAGENT_EXPIRED ->
|
||||
if (fpAllowedInBouncer) trustAgentDisabledWithFingerprintAllowed(securityMode)
|
||||
else trustAgentDisabled(securityMode)
|
||||
PROMPT_REASON_INCORRECT_FACE_INPUT ->
|
||||
if (fpAllowedInBouncer) incorrectFaceInputWithFingerprintAllowed(securityMode)
|
||||
else incorrectFaceInput(securityMode)
|
||||
PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT -> incorrectFingerprintInput(securityMode)
|
||||
PROMPT_REASON_DEFAULT ->
|
||||
if (fpAllowedInBouncer) defaultMessageWithFingerprint(securityMode)
|
||||
else defaultMessage(securityMode)
|
||||
PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT -> primaryAuthLockedOut(securityMode)
|
||||
else -> emptyBouncerMessage()
|
||||
}
|
||||
}
|
||||
|
||||
fun defaultMessage(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun defaultMessage(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return when (securityMode) {
|
||||
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
|
||||
SecurityMode.Password -> Pair(keyguard_enter_password, 0)
|
||||
@@ -147,7 +184,7 @@ fun defaultMessage(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun defaultMessageWithFingerprint(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun defaultMessageWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return when (securityMode) {
|
||||
SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, 0)
|
||||
SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, 0)
|
||||
@@ -156,7 +193,7 @@ fun defaultMessageWithFingerprint(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun incorrectSecurityInput(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun incorrectSecurityInput(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return when (securityMode) {
|
||||
SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, 0)
|
||||
SecurityMode.Password -> Pair(kg_wrong_password_try_again, 0)
|
||||
@@ -165,7 +202,7 @@ fun incorrectSecurityInput(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun incorrectSecurityInputWithFingerprint(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun incorrectSecurityInputWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
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)
|
||||
@@ -174,7 +211,7 @@ fun incorrectSecurityInputWithFingerprint(securityMode: SecurityMode): BouncerMe
|
||||
}
|
||||
}
|
||||
|
||||
fun incorrectFingerprintInput(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun incorrectFingerprintInput(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
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)
|
||||
@@ -183,7 +220,7 @@ fun incorrectFingerprintInput(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun incorrectFaceInput(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun incorrectFaceInput(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return 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)
|
||||
@@ -192,7 +229,7 @@ fun incorrectFaceInput(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun incorrectFaceInputWithFingerprintAllowed(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun incorrectFaceInputWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
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)
|
||||
@@ -201,7 +238,7 @@ fun incorrectFaceInputWithFingerprintAllowed(securityMode: SecurityMode): Bounce
|
||||
}
|
||||
}
|
||||
|
||||
fun biometricLockout(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun biometricLockout(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
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)
|
||||
@@ -210,7 +247,7 @@ fun biometricLockout(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun authRequiredAfterReboot(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun authRequiredAfterReboot(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
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)
|
||||
@@ -219,7 +256,7 @@ fun authRequiredAfterReboot(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun authRequiredAfterAdminLockdown(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun authRequiredAfterAdminLockdown(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
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)
|
||||
@@ -228,7 +265,7 @@ fun authRequiredAfterAdminLockdown(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun authRequiredAfterUserLockdown(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun authRequiredAfterUserLockdown(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return when (securityMode) {
|
||||
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern)
|
||||
SecurityMode.Password ->
|
||||
@@ -238,7 +275,7 @@ fun authRequiredAfterUserLockdown(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun authRequiredForUnattendedUpdate(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun authRequiredForUnattendedUpdate(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return when (securityMode) {
|
||||
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_unattended_update)
|
||||
SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_unattended_update)
|
||||
@@ -247,7 +284,7 @@ fun authRequiredForUnattendedUpdate(securityMode: SecurityMode): BouncerMessage
|
||||
}
|
||||
}
|
||||
|
||||
fun authRequiredAfterPrimaryAuthTimeout(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun authRequiredAfterPrimaryAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
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)
|
||||
@@ -256,7 +293,7 @@ fun authRequiredAfterPrimaryAuthTimeout(securityMode: SecurityMode): BouncerMess
|
||||
}
|
||||
}
|
||||
|
||||
fun nonStrongAuthTimeout(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun nonStrongAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return when (securityMode) {
|
||||
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_auth_timeout)
|
||||
SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_auth_timeout)
|
||||
@@ -265,7 +302,7 @@ fun nonStrongAuthTimeout(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun nonStrongAuthTimeoutWithFingerprintAllowed(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun nonStrongAuthTimeoutWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
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)
|
||||
@@ -274,7 +311,7 @@ fun nonStrongAuthTimeoutWithFingerprintAllowed(securityMode: SecurityMode): Boun
|
||||
}
|
||||
}
|
||||
|
||||
fun faceUnlockUnavailable(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun faceUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return when (securityMode) {
|
||||
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_face_locked_out)
|
||||
SecurityMode.Password -> Pair(keyguard_enter_password, kg_face_locked_out)
|
||||
@@ -283,7 +320,7 @@ fun faceUnlockUnavailable(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun fingerprintUnlockUnavailable(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun fingerprintUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return when (securityMode) {
|
||||
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_fp_locked_out)
|
||||
SecurityMode.Password -> Pair(keyguard_enter_password, kg_fp_locked_out)
|
||||
@@ -292,7 +329,7 @@ fun fingerprintUnlockUnavailable(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun trustAgentDisabled(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun trustAgentDisabled(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return when (securityMode) {
|
||||
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_trust_agent_disabled)
|
||||
SecurityMode.Password -> Pair(keyguard_enter_password, kg_trust_agent_disabled)
|
||||
@@ -301,7 +338,7 @@ fun trustAgentDisabled(securityMode: SecurityMode): BouncerMessage {
|
||||
}
|
||||
}
|
||||
|
||||
fun trustAgentDisabledWithFingerprintAllowed(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun trustAgentDisabledWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
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)
|
||||
@@ -310,7 +347,7 @@ fun trustAgentDisabledWithFingerprintAllowed(securityMode: SecurityMode): Bounce
|
||||
}
|
||||
}
|
||||
|
||||
fun primaryAuthLockedOut(securityMode: SecurityMode): BouncerMessage {
|
||||
private fun primaryAuthLockedOut(securityMode: SecurityMode): Pair<Int, Int> {
|
||||
return when (securityMode) {
|
||||
SecurityMode.Pattern ->
|
||||
Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pattern)
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.keyguard.bouncer.shared.model
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
|
||||
/**
|
||||
* Represents the message displayed on the bouncer. It has two parts, primary and a secondary
|
||||
* message
|
||||
*/
|
||||
data class BouncerMessageModel(val message: Message? = null, val secondaryMessage: Message? = null)
|
||||
|
||||
/**
|
||||
* Representation of a single message on the bouncer. It can be either a string or a string resource
|
||||
* ID
|
||||
*/
|
||||
data class Message(
|
||||
val message: String? = null,
|
||||
val messageResId: Int? = null,
|
||||
val colorState: ColorStateList? = null,
|
||||
/** Any plural formatter arguments that can used to format the [messageResId] */
|
||||
var formatterArgs: Map<String, Any>? = null,
|
||||
/** Specifies whether this text should be animated when it is shown. */
|
||||
var animate: Boolean = true,
|
||||
)
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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.keyguard.bouncer.data.factory
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.keyguard.KeyguardSecurityModel
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Password
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Pattern
|
||||
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEFAULT
|
||||
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT
|
||||
import com.android.keyguard.KeyguardUpdateMonitor
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.google.common.truth.StringSubject
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class BouncerMessageFactoryTest : SysuiTestCase() {
|
||||
private lateinit var underTest: BouncerMessageFactory
|
||||
|
||||
@Mock private lateinit var updateMonitor: KeyguardUpdateMonitor
|
||||
|
||||
@Mock private lateinit var securityModel: KeyguardSecurityModel
|
||||
|
||||
private lateinit var testScope: TestScope
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
testScope = TestScope()
|
||||
underTest = BouncerMessageFactory(updateMonitor, securityModel)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun bouncerMessages_choosesTheRightMessage_basedOnSecurityModeAndFpAllowedInBouncer() =
|
||||
testScope.runTest {
|
||||
primaryMessage(PROMPT_REASON_DEFAULT, mode = PIN, fpAllowedInBouncer = false)
|
||||
.isEqualTo("Enter PIN")
|
||||
primaryMessage(PROMPT_REASON_DEFAULT, mode = PIN, fpAllowedInBouncer = true)
|
||||
.isEqualTo("Unlock with PIN or fingerprint")
|
||||
|
||||
primaryMessage(PROMPT_REASON_DEFAULT, mode = Password, fpAllowedInBouncer = false)
|
||||
.isEqualTo("Enter password")
|
||||
primaryMessage(PROMPT_REASON_DEFAULT, mode = Password, fpAllowedInBouncer = true)
|
||||
.isEqualTo("Unlock with password or fingerprint")
|
||||
|
||||
primaryMessage(PROMPT_REASON_DEFAULT, mode = Pattern, fpAllowedInBouncer = false)
|
||||
.isEqualTo("Draw pattern")
|
||||
primaryMessage(PROMPT_REASON_DEFAULT, mode = Pattern, fpAllowedInBouncer = true)
|
||||
.isEqualTo("Unlock with pattern or fingerprint")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun bouncerMessages_setsPrimaryAndSecondaryMessage_basedOnSecurityModeAndFpAllowedInBouncer() =
|
||||
testScope.runTest {
|
||||
primaryMessage(
|
||||
PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
|
||||
mode = PIN,
|
||||
fpAllowedInBouncer = true
|
||||
)
|
||||
.isEqualTo("Wrong PIN. Try again.")
|
||||
secondaryMessage(
|
||||
PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
|
||||
mode = PIN,
|
||||
fpAllowedInBouncer = true
|
||||
)
|
||||
.isEqualTo("Or unlock with fingerprint")
|
||||
|
||||
primaryMessage(
|
||||
PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
|
||||
mode = Password,
|
||||
fpAllowedInBouncer = true
|
||||
)
|
||||
.isEqualTo("Wrong password. Try again.")
|
||||
secondaryMessage(
|
||||
PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
|
||||
mode = Password,
|
||||
fpAllowedInBouncer = true
|
||||
)
|
||||
.isEqualTo("Or unlock with fingerprint")
|
||||
|
||||
primaryMessage(
|
||||
PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
|
||||
mode = Pattern,
|
||||
fpAllowedInBouncer = true
|
||||
)
|
||||
.isEqualTo("Wrong pattern. Try again.")
|
||||
secondaryMessage(
|
||||
PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
|
||||
mode = Pattern,
|
||||
fpAllowedInBouncer = true
|
||||
)
|
||||
.isEqualTo("Or unlock with fingerprint")
|
||||
}
|
||||
|
||||
private fun primaryMessage(
|
||||
reason: Int,
|
||||
mode: KeyguardSecurityModel.SecurityMode,
|
||||
fpAllowedInBouncer: Boolean
|
||||
): StringSubject {
|
||||
return assertThat(
|
||||
context.resources.getString(
|
||||
bouncerMessageModel(mode, fpAllowedInBouncer, reason)!!.message!!.messageResId!!
|
||||
)
|
||||
)!!
|
||||
}
|
||||
|
||||
private fun secondaryMessage(
|
||||
reason: Int,
|
||||
mode: KeyguardSecurityModel.SecurityMode,
|
||||
fpAllowedInBouncer: Boolean
|
||||
): StringSubject {
|
||||
return assertThat(
|
||||
context.resources.getString(
|
||||
bouncerMessageModel(mode, fpAllowedInBouncer, reason)!!
|
||||
.secondaryMessage!!
|
||||
.messageResId!!
|
||||
)
|
||||
)!!
|
||||
}
|
||||
|
||||
private fun bouncerMessageModel(
|
||||
mode: KeyguardSecurityModel.SecurityMode,
|
||||
fpAllowedInBouncer: Boolean,
|
||||
reason: Int
|
||||
): BouncerMessageModel? {
|
||||
whenever(securityModel.getSecurityMode(0)).thenReturn(mode)
|
||||
whenever(updateMonitor.isFingerprintAllowedInBouncer).thenReturn(fpAllowedInBouncer)
|
||||
|
||||
return underTest.createFromPromptReason(reason, 0)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user