Merge changes Ibca81eed,I5539cdaf,I3f7029f5,I9ce0fe29,I59e48540, ... into udc-qpr-dev

* changes:
  Change the default message to include fingerprint even for UDFPS.
  Use the default message as the primary line for fp/face acquisition messages
  Support custom messages for mainline update
  Remove code that was added to disable the views for udc-dev
  Show unlock with fingerprint message for co-ex face locked out scenario
  Update message shown for unattended update
  Fixes issue with wrong pin input message not being shown
  Do not show the primary auth lockout dialog if the feature flag is enabled
This commit is contained in:
Chandru S
2023-08-03 16:29:56 +00:00
committed by Android (Google) Code Review
11 changed files with 173 additions and 83 deletions

View File

@@ -192,7 +192,7 @@
<string name="kg_prompt_after_user_lockdown_pattern">Pattern is required after lockdown</string>
<!-- Message shown to prepare for an unattended update (OTA). Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
<string name="kg_prompt_unattended_update">Update will install during inactive hours</string>
<string name="kg_prompt_unattended_update">Update will install when device not in use</string>
<!-- Message shown when primary authentication hasn't been used for some time. [CHAR LIMIT=70] -->
<string name="kg_prompt_pin_auth_timeout">Added security required. PIN not used for a while.</string>

View File

@@ -178,6 +178,7 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
getKeyguardSecurityCallback().dismiss(true, userId, getSecurityMode());
}
} else {
mView.resetPasswordText(true /* animate */, false /* announce deletion if no match */);
if (isValidPassword) {
getKeyguardSecurityCallback().reportUnlockAttempt(userId, false, timeoutMs);
if (timeoutMs > 0) {
@@ -186,7 +187,6 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
handleAttemptLockout(deadline);
}
}
mView.resetPasswordText(true /* animate */, false /* announce deletion if no match */);
if (timeoutMs == 0) {
mMessageAreaController.setMessage(mView.getWrongPasswordStringId());
}

View File

@@ -27,6 +27,7 @@ import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_PRIMARY;
import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_SECONDARY_USER;
import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_WORK_PROFILE;
import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.flags.Flags.REVAMPED_BOUNCER_MESSAGES;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
@@ -1081,8 +1082,10 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mLockPatternUtils.reportFailedPasswordAttempt(userId);
if (timeoutMs > 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));
}
}
}

View File

@@ -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.
*/

View File

@@ -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<Int, Int>? {
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<In
}
}
private fun authRequiredForMainlineUpdate(securityMode: SecurityMode): Pair<Int, Int> {
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<Int, Int> {
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<Int, Int> {
private fun faceLockedOut(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)
@@ -320,6 +341,15 @@ private fun faceUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> {
}
}
private fun faceLockedOutButFingerprintAvailable(securityMode: SecurityMode): Pair<Int, Int> {
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<Int, Int> {
return when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_fp_locked_out)

View File

@@ -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<Int> =
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) {

View File

@@ -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 =

View File

@@ -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) {

View File

@@ -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
)
}
}

View File

@@ -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<KeyguardUpdateMonitorCallback>
@@ -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 {

View File

@@ -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