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

Commit 26a6f683 authored by Chandru S's avatar Chandru S
Browse files

Create BouncerMessageFactory to easily create BouncerMessage data model.

Bug: 275600559
Test: pending
Change-Id: Ia12e8cd6de851113da718a4bdec6583d8f310160
parent cd933eed
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -2622,6 +2622,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        return mAuthController.isUdfpsSupported();
        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.
     * @return true if there's at least one sfps enrollment for the current user.
     */
     */
+101 −64
Original line number Original line Diff line number Diff line
@@ -14,9 +14,10 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


package com.android.keyguard
package com.android.systemui.keyguard.bouncer.data.factory


import android.annotation.IntDef
import android.annotation.IntDef
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardSecurityModel.SecurityMode
import com.android.keyguard.KeyguardSecurityModel.SecurityMode
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEFAULT
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_TIMEOUT
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST
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.bouncer_face_not_recognized
import com.android.systemui.R.string.keyguard_enter_password
import com.android.systemui.R.string.keyguard_enter_password
import com.android.systemui.R.string.keyguard_enter_pattern
import com.android.systemui.R.string.keyguard_enter_pattern
@@ -71,43 +73,56 @@ 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_password_try_again
import com.android.systemui.R.string.kg_wrong_pattern_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.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)
            )
        }
    }


@Retention(AnnotationRetention.SOURCE)
    fun createFromString(
@IntDef(
        primaryMsg: String? = null,
    PROMPT_REASON_TIMEOUT,
        secondaryMsg: String? = null
    PROMPT_REASON_DEVICE_ADMIN,
    ): BouncerMessageModel =
    PROMPT_REASON_USER_REQUEST,
        BouncerMessageModel(
    PROMPT_REASON_AFTER_LOCKOUT,
            message = primaryMsg?.let { Message(message = it) },
    PROMPT_REASON_PREPARE_FOR_UPDATE,
            secondaryMessage = secondaryMsg?.let { Message(message = it) },
    PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT,
    PROMPT_REASON_TRUSTAGENT_EXPIRED,
    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
    PROMPT_REASON_INCORRECT_FACE_INPUT,
    PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT,
    PROMPT_REASON_FACE_LOCKED_OUT,
    PROMPT_REASON_FINGERPRINT_LOCKED_OUT,
    PROMPT_REASON_DEFAULT,
    PROMPT_REASON_NONE,
    PROMPT_REASON_RESTART,
    PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT,
        )
        )
annotation class BouncerPromptReason


    /**
    /**
     * Helper method that provides the relevant bouncer message that should be shown for different
     * Helper method that provides the relevant bouncer message that should be shown for different
     * scenarios indicated by [reason]. [securityMode] & [fpAllowedInBouncer] parameters are used to
     * scenarios indicated by [reason]. [securityMode] & [fpAllowedInBouncer] parameters are used to
     * provide a more specific message.
     * provide a more specific message.
     */
     */
@JvmOverloads
    private fun getBouncerMessage(
fun getBouncerMessage(
        @BouncerPromptReason reason: Int,
        @BouncerPromptReason reason: Int,
        securityMode: SecurityMode,
        securityMode: SecurityMode,
        fpAllowedInBouncer: Boolean = false
        fpAllowedInBouncer: Boolean = false
): BouncerMessage {
    ): Pair<Int, Int>? {
        return when (reason) {
        return when (reason) {
            PROMPT_REASON_RESTART -> authRequiredAfterReboot(securityMode)
            PROMPT_REASON_RESTART -> authRequiredAfterReboot(securityMode)
            PROMPT_REASON_TIMEOUT -> authRequiredAfterPrimaryAuthTimeout(securityMode)
            PROMPT_REASON_TIMEOUT -> authRequiredAfterPrimaryAuthTimeout(securityMode)
@@ -134,11 +149,33 @@ fun getBouncerMessage(
                if (fpAllowedInBouncer) defaultMessageWithFingerprint(securityMode)
                if (fpAllowedInBouncer) defaultMessageWithFingerprint(securityMode)
                else defaultMessage(securityMode)
                else defaultMessage(securityMode)
            PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT -> primaryAuthLockedOut(securityMode)
            PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT -> primaryAuthLockedOut(securityMode)
        else -> emptyBouncerMessage()
            else -> null
        }
    }
    }
}
}


fun defaultMessage(securityMode: SecurityMode): BouncerMessage {
@Retention(AnnotationRetention.SOURCE)
@IntDef(
    PROMPT_REASON_TIMEOUT,
    PROMPT_REASON_DEVICE_ADMIN,
    PROMPT_REASON_USER_REQUEST,
    PROMPT_REASON_AFTER_LOCKOUT,
    PROMPT_REASON_PREPARE_FOR_UPDATE,
    PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT,
    PROMPT_REASON_TRUSTAGENT_EXPIRED,
    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
    PROMPT_REASON_INCORRECT_FACE_INPUT,
    PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT,
    PROMPT_REASON_FACE_LOCKED_OUT,
    PROMPT_REASON_FINGERPRINT_LOCKED_OUT,
    PROMPT_REASON_DEFAULT,
    PROMPT_REASON_NONE,
    PROMPT_REASON_RESTART,
    PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT,
)
annotation class BouncerPromptReason

private fun defaultMessage(securityMode: SecurityMode): Pair<Int, Int> {
    return when (securityMode) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
        SecurityMode.Password -> Pair(keyguard_enter_password, 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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, 0)
        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, 0)
        SecurityMode.Password -> Pair(kg_unlock_with_password_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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, 0)
        SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, 0)
        SecurityMode.Password -> Pair(kg_wrong_password_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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, kg_wrong_input_try_fp_suggestion)
        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.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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pattern)
        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.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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pattern)
        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.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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, bouncer_face_not_recognized)
        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.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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_bio_too_many_attempts_pattern)
        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.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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_reason_restart_pattern)
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_reason_restart_pattern)
        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_reason_restart_password)
        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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_dpm_lock)
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_dpm_lock)
        SecurityMode.Password -> Pair(keyguard_enter_password, 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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern)
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern)
        SecurityMode.Password ->
        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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_unattended_update)
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_unattended_update)
        SecurityMode.Password -> Pair(keyguard_enter_password, 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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_pattern_auth_timeout)
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_pattern_auth_timeout)
        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_password_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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_auth_timeout)
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_auth_timeout)
        SecurityMode.Password -> Pair(keyguard_enter_password, 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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_prompt_auth_timeout)
        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.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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_face_locked_out)
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_face_locked_out)
        SecurityMode.Password -> Pair(keyguard_enter_password, 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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_fp_locked_out)
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_fp_locked_out)
        SecurityMode.Password -> Pair(keyguard_enter_password, 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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_trust_agent_disabled)
        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_trust_agent_disabled)
        SecurityMode.Password -> Pair(keyguard_enter_password, 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) {
    return when (securityMode) {
        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_trust_agent_disabled)
        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.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) {
    return when (securityMode) {
        SecurityMode.Pattern ->
        SecurityMode.Pattern ->
            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pattern)
            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pattern)
+39 −0
Original line number Original line 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.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,
)
+159 −0
Original line number Original line 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.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)
    }
}