diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index badad584824b8..28b58703b02de 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -192,7 +192,7 @@ Pattern is required after lockdown - Update will install during inactive hours + Update will install when device not in use Added security required. PIN not used for a while. diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java index bb112175ded7b..b81e08183cdc4 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java @@ -178,6 +178,7 @@ public abstract class KeyguardAbsKeyInputViewController 0) { @@ -186,7 +187,6 @@ public abstract class KeyguardAbsKeyInputViewController 0) { mLockPatternUtils.reportPasswordLockout(timeoutMs, userId); - mView.showTimeoutDialog(userId, timeoutMs, mLockPatternUtils, - mSecurityModel.getSecurityMode(userId)); + if (!mFeatureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) { + mView.showTimeoutDialog(userId, timeoutMs, mLockPatternUtils, + mSecurityModel.getSecurityMode(userId)); + } } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 48442a5f527ef..c03053d0a8a2c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2695,14 +2695,6 @@ 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. */ diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactory.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactory.kt index 3206c0043d5c3..1817ea9024fce 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactory.kt @@ -32,6 +32,7 @@ import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMET import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART +import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE 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 @@ -53,6 +54,9 @@ import com.android.systemui.R.string.kg_primary_auth_locked_out_password import com.android.systemui.R.string.kg_primary_auth_locked_out_pattern import com.android.systemui.R.string.kg_primary_auth_locked_out_pin import com.android.systemui.R.string.kg_prompt_after_dpm_lock +import com.android.systemui.R.string.kg_prompt_after_update_password +import com.android.systemui.R.string.kg_prompt_after_update_pattern +import com.android.systemui.R.string.kg_prompt_after_update_pin import com.android.systemui.R.string.kg_prompt_after_user_lockdown_password import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pattern import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pin @@ -89,69 +93,76 @@ constructor( fun createFromPromptReason( @BouncerPromptReason reason: Int, userId: Int, + secondaryMsgOverride: String? = null ): BouncerMessageModel? { val pair = getBouncerMessage( reason, securityModel.getSecurityMode(userId), - updateMonitor.isFingerprintAllowedInBouncer + updateMonitor.isUnlockingWithFingerprintAllowed ) return pair?.let { BouncerMessageModel( - message = Message(messageResId = pair.first), - secondaryMessage = Message(messageResId = pair.second) + message = Message(messageResId = pair.first, animate = false), + secondaryMessage = + secondaryMsgOverride?.let { + Message(message = secondaryMsgOverride, animate = false) + } + ?: Message(messageResId = pair.second, animate = false) ) } } - 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 + * scenarios indicated by [reason]. [securityMode] & [fpAuthIsAllowed] parameters are used to * provide a more specific message. */ private fun getBouncerMessage( @BouncerPromptReason reason: Int, securityMode: SecurityMode, - fpAllowedInBouncer: Boolean = false + fpAuthIsAllowed: Boolean = false ): Pair? { return when (reason) { + // Primary auth locked out + PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT -> primaryAuthLockedOut(securityMode) + // Primary auth required reasons 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_RESTART_FOR_MAINLINE_UPDATE -> authRequiredForMainlineUpdate(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_AFTER_LOCKOUT -> biometricLockout(securityMode) + // Non strong auth not available reasons + PROMPT_REASON_FACE_LOCKED_OUT -> + if (fpAuthIsAllowed) faceLockedOutButFingerprintAvailable(securityMode) + else faceLockedOut(securityMode) PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT -> - if (fpAllowedInBouncer) nonStrongAuthTimeoutWithFingerprintAllowed(securityMode) + if (fpAuthIsAllowed) nonStrongAuthTimeoutWithFingerprintAllowed(securityMode) else nonStrongAuthTimeout(securityMode) PROMPT_REASON_TRUSTAGENT_EXPIRED -> - if (fpAllowedInBouncer) trustAgentDisabledWithFingerprintAllowed(securityMode) + if (fpAuthIsAllowed) trustAgentDisabledWithFingerprintAllowed(securityMode) else trustAgentDisabled(securityMode) + // Auth incorrect input reasons. + PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT -> + if (fpAuthIsAllowed) incorrectSecurityInputWithFingerprint(securityMode) + else incorrectSecurityInput(securityMode) PROMPT_REASON_INCORRECT_FACE_INPUT -> - if (fpAllowedInBouncer) incorrectFaceInputWithFingerprintAllowed(securityMode) + if (fpAuthIsAllowed) incorrectFaceInputWithFingerprintAllowed(securityMode) else incorrectFaceInput(securityMode) PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT -> incorrectFingerprintInput(securityMode) + // Default message PROMPT_REASON_DEFAULT -> - if (fpAllowedInBouncer) defaultMessageWithFingerprint(securityMode) + if (fpAuthIsAllowed) defaultMessageWithFingerprint(securityMode) else defaultMessage(securityMode) - PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT -> primaryAuthLockedOut(securityMode) else -> null } } + + fun emptyMessage(): BouncerMessageModel = + BouncerMessageModel(Message(message = ""), Message(message = "")) } @Retention(AnnotationRetention.SOURCE) @@ -172,6 +183,7 @@ constructor( PROMPT_REASON_NONE, PROMPT_REASON_RESTART, PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT, + PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE, ) annotation class BouncerPromptReason @@ -284,6 +296,15 @@ private fun authRequiredForUnattendedUpdate(securityMode: SecurityMode): Pair { + 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) + } +} + private fun authRequiredAfterPrimaryAuthTimeout(securityMode: SecurityMode): Pair { return when (securityMode) { SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_pattern_auth_timeout) @@ -311,7 +332,7 @@ private fun nonStrongAuthTimeoutWithFingerprintAllowed(securityMode: SecurityMod } } -private fun faceUnlockUnavailable(securityMode: SecurityMode): Pair { +private fun faceLockedOut(securityMode: SecurityMode): Pair { return when (securityMode) { SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_face_locked_out) SecurityMode.Password -> Pair(keyguard_enter_password, kg_face_locked_out) @@ -320,6 +341,15 @@ private fun faceUnlockUnavailable(securityMode: SecurityMode): Pair { } } +private fun faceLockedOutButFingerprintAvailable(securityMode: SecurityMode): Pair { + 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) + } +} + private fun fingerprintUnlockUnavailable(securityMode: SecurityMode): Pair { return when (securityMode) { SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_fp_locked_out) diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerMessageRepository.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerMessageRepository.kt index 7e420cfcea757..6fb0d4cc5e135 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerMessageRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerMessageRepository.kt @@ -28,6 +28,7 @@ import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART +import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE 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 @@ -38,6 +39,7 @@ import com.android.systemui.bouncer.shared.model.BouncerMessageModel import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.SystemPropertiesHelper import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.TrustRepository @@ -105,6 +107,9 @@ interface BouncerMessageRepository { fun clearMessage() } +private const val SYS_BOOT_REASON_PROP = "sys.boot.reason.last" +private const val REBOOT_MAINLINE_UPDATE = "reboot,mainline_update" + @SysUISingleton class BouncerMessageRepositoryImpl @Inject @@ -114,6 +119,7 @@ constructor( updateMonitor: KeyguardUpdateMonitor, private val bouncerMessageFactory: BouncerMessageFactory, private val userRepository: UserRepository, + private val systemPropertiesHelper: SystemPropertiesHelper, fingerprintAuthRepository: DeviceEntryFingerprintAuthRepository, ) : BouncerMessageRepository { @@ -132,6 +138,9 @@ constructor( private val isAnyBiometricsEnabledAndEnrolled = or(isFaceEnrolledAndEnabled, isFingerprintEnrolledAndEnabled) + private val wasRebootedForMainlineUpdate + get() = systemPropertiesHelper.get(SYS_BOOT_REASON_PROP) == REBOOT_MAINLINE_UPDATE + private val authFlagsBasedPromptReason: Flow = combine( biometricSettingsRepository.authenticationFlags, @@ -144,7 +153,8 @@ constructor( return@map if ( trustOrBiometricsAvailable && flags.isPrimaryAuthRequiredAfterReboot ) { - PROMPT_REASON_RESTART + if (wasRebootedForMainlineUpdate) PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE + else PROMPT_REASON_RESTART } else if (trustOrBiometricsAvailable && flags.isPrimaryAuthRequiredAfterTimeout) { PROMPT_REASON_TIMEOUT } else if (flags.isPrimaryAuthRequiredAfterDpmLockdown) { diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt index d06dd8e1c1241..fe01d081e60ca 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt @@ -86,7 +86,11 @@ constructor( repository.setFingerprintAcquisitionMessage( if (value != null) { - factory.createFromString(secondaryMsg = value) + factory.createFromPromptReason( + PROMPT_REASON_DEFAULT, + userRepository.getSelectedUserInfo().id, + secondaryMsgOverride = value + ) } else { null } @@ -98,7 +102,11 @@ constructor( repository.setFaceAcquisitionMessage( if (value != null) { - factory.createFromString(secondaryMsg = value) + factory.createFromPromptReason( + PROMPT_REASON_DEFAULT, + userRepository.getSelectedUserInfo().id, + secondaryMsgOverride = value + ) } else { null } @@ -110,7 +118,11 @@ constructor( repository.setCustomMessage( if (value != null) { - factory.createFromString(secondaryMsg = value) + factory.createFromPromptReason( + PROMPT_REASON_DEFAULT, + userRepository.getSelectedUserInfo().id, + secondaryMsgOverride = value + ) } else { null } @@ -140,8 +152,7 @@ constructor( // always maps to an empty string. private fun nullOrEmptyMessage() = flowOf( - if (featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) null - else factory.createFromString("", "") + if (featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) null else factory.emptyMessage() ) val bouncerMessage = diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt index 47fac2b4269dd..648680293e3d8 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt @@ -41,8 +41,6 @@ class BouncerMessageView : LinearLayout { super.onFinishInflate() primaryMessageView = findViewById(R.id.bouncer_primary_message_area) secondaryMessageView = findViewById(R.id.bouncer_secondary_message_area) - primaryMessageView?.disable() - secondaryMessageView?.disable() } fun init(factory: KeyguardMessageAreaController.Factory) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactoryTest.kt index 992ee1a83254b..efae3fe1af2c7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactoryTest.kt @@ -59,63 +59,79 @@ class BouncerMessageFactoryTest : SysuiTestCase() { } @Test - fun bouncerMessages_choosesTheRightMessage_basedOnSecurityModeAndFpAllowedInBouncer() = + fun bouncerMessages_choosesTheRightMessage_basedOnSecurityModeAndFpAuthIsAllowed() = testScope.runTest { - primaryMessage(PROMPT_REASON_DEFAULT, mode = PIN, fpAllowedInBouncer = false) + primaryMessage(PROMPT_REASON_DEFAULT, mode = PIN, fpAuthAllowed = false) .isEqualTo("Enter PIN") - primaryMessage(PROMPT_REASON_DEFAULT, mode = PIN, fpAllowedInBouncer = true) + primaryMessage(PROMPT_REASON_DEFAULT, mode = PIN, fpAuthAllowed = true) .isEqualTo("Unlock with PIN or fingerprint") - primaryMessage(PROMPT_REASON_DEFAULT, mode = Password, fpAllowedInBouncer = false) + primaryMessage(PROMPT_REASON_DEFAULT, mode = Password, fpAuthAllowed = false) .isEqualTo("Enter password") - primaryMessage(PROMPT_REASON_DEFAULT, mode = Password, fpAllowedInBouncer = true) + primaryMessage(PROMPT_REASON_DEFAULT, mode = Password, fpAuthAllowed = true) .isEqualTo("Unlock with password or fingerprint") - primaryMessage(PROMPT_REASON_DEFAULT, mode = Pattern, fpAllowedInBouncer = false) + primaryMessage(PROMPT_REASON_DEFAULT, mode = Pattern, fpAuthAllowed = false) .isEqualTo("Draw pattern") - primaryMessage(PROMPT_REASON_DEFAULT, mode = Pattern, fpAllowedInBouncer = true) + primaryMessage(PROMPT_REASON_DEFAULT, mode = Pattern, fpAuthAllowed = true) .isEqualTo("Unlock with pattern or fingerprint") } @Test - fun bouncerMessages_setsPrimaryAndSecondaryMessage_basedOnSecurityModeAndFpAllowedInBouncer() = + fun bouncerMessages_overridesSecondaryMessageValue() = + testScope.runTest { + val bouncerMessageModel = + bouncerMessageModel( + PIN, + true, + PROMPT_REASON_DEFAULT, + secondaryMessageOverride = "face acquisition message" + )!! + assertThat(context.resources.getString(bouncerMessageModel.message!!.messageResId!!)) + .isEqualTo("Unlock with PIN or fingerprint") + assertThat(bouncerMessageModel.secondaryMessage!!.message!!) + .isEqualTo("face acquisition message") + } + + @Test + fun bouncerMessages_setsPrimaryAndSecondaryMessage_basedOnSecurityModeAndFpAuthIsAllowed() = testScope.runTest { primaryMessage( PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT, mode = PIN, - fpAllowedInBouncer = true + fpAuthAllowed = true ) .isEqualTo("Wrong PIN. Try again.") secondaryMessage( PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT, mode = PIN, - fpAllowedInBouncer = true + fpAuthAllowed = true ) .isEqualTo("Or unlock with fingerprint") primaryMessage( PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT, mode = Password, - fpAllowedInBouncer = true + fpAuthAllowed = true ) .isEqualTo("Wrong password. Try again.") secondaryMessage( PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT, mode = Password, - fpAllowedInBouncer = true + fpAuthAllowed = true ) .isEqualTo("Or unlock with fingerprint") primaryMessage( PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT, mode = Pattern, - fpAllowedInBouncer = true + fpAuthAllowed = true ) .isEqualTo("Wrong pattern. Try again.") secondaryMessage( PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT, mode = Pattern, - fpAllowedInBouncer = true + fpAuthAllowed = true ) .isEqualTo("Or unlock with fingerprint") } @@ -123,11 +139,11 @@ class BouncerMessageFactoryTest : SysuiTestCase() { private fun primaryMessage( reason: Int, mode: KeyguardSecurityModel.SecurityMode, - fpAllowedInBouncer: Boolean + fpAuthAllowed: Boolean ): StringSubject { return assertThat( context.resources.getString( - bouncerMessageModel(mode, fpAllowedInBouncer, reason)!!.message!!.messageResId!! + bouncerMessageModel(mode, fpAuthAllowed, reason)!!.message!!.messageResId!! ) )!! } @@ -135,25 +151,28 @@ class BouncerMessageFactoryTest : SysuiTestCase() { private fun secondaryMessage( reason: Int, mode: KeyguardSecurityModel.SecurityMode, - fpAllowedInBouncer: Boolean + fpAuthAllowed: Boolean ): StringSubject { return assertThat( context.resources.getString( - bouncerMessageModel(mode, fpAllowedInBouncer, reason)!! - .secondaryMessage!! - .messageResId!! + bouncerMessageModel(mode, fpAuthAllowed, reason)!!.secondaryMessage!!.messageResId!! ) )!! } private fun bouncerMessageModel( mode: KeyguardSecurityModel.SecurityMode, - fpAllowedInBouncer: Boolean, - reason: Int + fpAuthAllowed: Boolean, + reason: Int, + secondaryMessageOverride: String? = null, ): BouncerMessageModel? { whenever(securityModel.getSecurityMode(0)).thenReturn(mode) - whenever(updateMonitor.isFingerprintAllowedInBouncer).thenReturn(fpAllowedInBouncer) + whenever(updateMonitor.isUnlockingWithFingerprintAllowed).thenReturn(fpAuthAllowed) - return underTest.createFromPromptReason(reason, 0) + return underTest.createFromPromptReason( + reason, + 0, + secondaryMsgOverride = secondaryMessageOverride + ) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repo/BouncerMessageRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repo/BouncerMessageRepositoryTest.kt index de712da9d99bf..2be7d8a43a189 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repo/BouncerMessageRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repo/BouncerMessageRepositoryTest.kt @@ -51,6 +51,7 @@ import com.android.systemui.bouncer.data.repository.BouncerMessageRepositoryImpl import com.android.systemui.bouncer.shared.model.BouncerMessageModel import com.android.systemui.bouncer.shared.model.Message import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.SystemPropertiesHelper import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.FakeTrustRepository @@ -79,6 +80,7 @@ class BouncerMessageRepositoryTest : SysuiTestCase() { @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor @Mock private lateinit var securityModel: KeyguardSecurityModel + @Mock private lateinit var systemPropertiesHelper: SystemPropertiesHelper @Captor private lateinit var updateMonitorCallback: ArgumentCaptor @@ -99,7 +101,7 @@ class BouncerMessageRepositoryTest : SysuiTestCase() { fingerprintRepository = FakeDeviceEntryFingerprintAuthRepository() testScope = TestScope() - whenever(updateMonitor.isFingerprintAllowedInBouncer).thenReturn(false) + whenever(updateMonitor.isUnlockingWithFingerprintAllowed).thenReturn(false) whenever(securityModel.getSecurityMode(PRIMARY_USER_ID)).thenReturn(PIN) underTest = BouncerMessageRepositoryImpl( @@ -108,7 +110,8 @@ class BouncerMessageRepositoryTest : SysuiTestCase() { updateMonitor = updateMonitor, bouncerMessageFactory = BouncerMessageFactory(updateMonitor, securityModel), userRepository = userRepository, - fingerprintAuthRepository = fingerprintRepository + fingerprintAuthRepository = fingerprintRepository, + systemPropertiesHelper = systemPropertiesHelper ) } @@ -213,6 +216,21 @@ class BouncerMessageRepositoryTest : SysuiTestCase() { assertThat(lockedOutMessage()).isNull() } + @Test + fun onRestartForMainlineUpdate_shouldProvideRelevantMessage() = + testScope.runTest { + whenever(systemPropertiesHelper.get("sys.boot.reason.last")) + .thenReturn("reboot,mainline_update") + userRepository.setSelectedUserInfo(PRIMARY_USER) + biometricSettingsRepository.setFaceEnrolled(true) + biometricSettingsRepository.setIsFaceAuthEnabled(true) + + verifyMessagesForAuthFlag( + STRONG_AUTH_REQUIRED_AFTER_BOOT to + Pair(keyguard_enter_pin, R.string.kg_prompt_after_update_pin), + ) + } + @Test fun onAuthFlagsChanged_withTrustNotManagedAndNoBiometrics_isANoop() = testScope.runTest { @@ -345,8 +363,8 @@ class BouncerMessageRepositoryTest : SysuiTestCase() { private fun message(primaryResId: Int, secondaryResId: Int): BouncerMessageModel { return BouncerMessageModel( - message = Message(messageResId = primaryResId), - secondaryMessage = Message(messageResId = secondaryResId) + message = Message(messageResId = primaryResId, animate = false), + secondaryMessage = Message(messageResId = secondaryResId, animate = false) ) } private fun message(value: String): BouncerMessageModel { diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt index 8e5256e970a30..3ca94aa8e7afa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt @@ -76,7 +76,7 @@ class BouncerMessageInteractorTest : SysuiTestCase() { allowTestableLooperAsMainThread() whenever(securityModel.getSecurityMode(PRIMARY_USER_ID)).thenReturn(PIN) - whenever(updateMonitor.isFingerprintAllowedInBouncer).thenReturn(false) + whenever(updateMonitor.isUnlockingWithFingerprintAllowed).thenReturn(false) } suspend fun TestScope.init() { @@ -150,11 +150,12 @@ class BouncerMessageInteractorTest : SysuiTestCase() { underTest.setCustomMessage("not empty") - assertThat(repository.customMessage.value) - .isEqualTo(BouncerMessageModel(secondaryMessage = Message(message = "not empty"))) + val customMessage = repository.customMessage + assertThat(customMessage.value!!.message!!.messageResId).isEqualTo(keyguard_enter_pin) + assertThat(customMessage.value!!.secondaryMessage!!.message).isEqualTo("not empty") underTest.setCustomMessage(null) - assertThat(repository.customMessage.value).isNull() + assertThat(customMessage.value).isNull() } @Test @@ -164,11 +165,15 @@ class BouncerMessageInteractorTest : SysuiTestCase() { underTest.setFaceAcquisitionMessage("not empty") - assertThat(repository.faceAcquisitionMessage.value) - .isEqualTo(BouncerMessageModel(secondaryMessage = Message(message = "not empty"))) + val faceAcquisitionMessage = repository.faceAcquisitionMessage + + assertThat(faceAcquisitionMessage.value!!.message!!.messageResId) + .isEqualTo(keyguard_enter_pin) + assertThat(faceAcquisitionMessage.value!!.secondaryMessage!!.message) + .isEqualTo("not empty") underTest.setFaceAcquisitionMessage(null) - assertThat(repository.faceAcquisitionMessage.value).isNull() + assertThat(faceAcquisitionMessage.value).isNull() } @Test @@ -178,11 +183,15 @@ class BouncerMessageInteractorTest : SysuiTestCase() { underTest.setFingerprintAcquisitionMessage("not empty") - assertThat(repository.fingerprintAcquisitionMessage.value) - .isEqualTo(BouncerMessageModel(secondaryMessage = Message(message = "not empty"))) + val fingerprintAcquisitionMessage = repository.fingerprintAcquisitionMessage + + assertThat(fingerprintAcquisitionMessage.value!!.message!!.messageResId) + .isEqualTo(keyguard_enter_pin) + assertThat(fingerprintAcquisitionMessage.value!!.secondaryMessage!!.message) + .isEqualTo("not empty") underTest.setFingerprintAcquisitionMessage(null) - assertThat(repository.fingerprintAcquisitionMessage.value).isNull() + assertThat(fingerprintAcquisitionMessage.value).isNull() } @Test