Merge "Hookup active unlock running state to bouncer delay logic" into udc-dev

This commit is contained in:
Beverly Tai
2023-05-12 17:10:36 +00:00
committed by Android (Google) Code Review
12 changed files with 185 additions and 51 deletions

View File

@@ -4395,7 +4395,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mFingerprintListenBuffer.toList() mFingerprintListenBuffer.toList()
).printTableData(pw); ).printTableData(pw);
} }
pw.println("ActiveUnlockRunning="
+ mTrustManager.isActiveUnlockRunning(KeyguardUpdateMonitor.getCurrentUser()));
new DumpsysTableLogger( new DumpsysTableLogger(
"KeyguardActiveUnlockTriggers", "KeyguardActiveUnlockTriggers",
KeyguardActiveUnlockModel.TABLE_HEADERS, KeyguardActiveUnlockModel.TABLE_HEADERS,

View File

@@ -17,6 +17,7 @@
package com.android.keyguard.logging package com.android.keyguard.logging
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.ActiveUnlockModel
import com.android.systemui.keyguard.shared.model.TrustManagedModel import com.android.systemui.keyguard.shared.model.TrustManagedModel
import com.android.systemui.keyguard.shared.model.TrustModel import com.android.systemui.keyguard.shared.model.TrustModel
import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogBuffer
@@ -76,6 +77,18 @@ constructor(
) )
} }
fun activeUnlockModelEmitted(value: ActiveUnlockModel) {
logBuffer.log(
TAG,
LogLevel.DEBUG,
{
int1 = value.userId
bool1 = value.isRunning
},
{ "activeUnlockModel emitted: userId: $int1 isRunning: $bool1" }
)
}
fun isCurrentUserTrusted(isCurrentUserTrusted: Boolean) { fun isCurrentUserTrusted(isCurrentUserTrusted: Boolean) {
logBuffer.log( logBuffer.log(
TAG, TAG,
@@ -85,6 +98,15 @@ constructor(
) )
} }
fun isCurrentUserActiveUnlockRunning(isCurrentUserActiveUnlockRunning: Boolean) {
logBuffer.log(
TAG,
LogLevel.DEBUG,
{ bool1 = isCurrentUserActiveUnlockRunning },
{ "isCurrentUserActiveUnlockRunning emitted: $bool1" }
)
}
fun isCurrentUserTrustManaged(isTrustManaged: Boolean) { fun isCurrentUserTrustManaged(isTrustManaged: Boolean) {
logBuffer.log(TAG, DEBUG, { bool1 = isTrustManaged }, { "isTrustManaged emitted: $bool1" }) logBuffer.log(TAG, DEBUG, { bool1 = isTrustManaged }, { "isTrustManaged emitted: $bool1" })
} }

View File

@@ -22,6 +22,7 @@ import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLoggin
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.shared.model.ActiveUnlockModel
import com.android.systemui.keyguard.shared.model.TrustManagedModel import com.android.systemui.keyguard.shared.model.TrustManagedModel
import com.android.systemui.keyguard.shared.model.TrustModel import com.android.systemui.keyguard.shared.model.TrustModel
import com.android.systemui.user.data.repository.UserRepository import com.android.systemui.user.data.repository.UserRepository
@@ -29,7 +30,6 @@ import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
@@ -45,8 +45,8 @@ interface TrustRepository {
/** Flow representing whether the current user is trusted. */ /** Flow representing whether the current user is trusted. */
val isCurrentUserTrusted: Flow<Boolean> val isCurrentUserTrusted: Flow<Boolean>
/** Flow representing whether active unlock is available for the current user. */ /** Flow representing whether active unlock is running for the current user. */
val isCurrentUserActiveUnlockAvailable: StateFlow<Boolean> val isCurrentUserActiveUnlockRunning: Flow<Boolean>
/** Reports that whether trust is managed has changed for the current user. */ /** Reports that whether trust is managed has changed for the current user. */
val isCurrentUserTrustManaged: StateFlow<Boolean> val isCurrentUserTrustManaged: StateFlow<Boolean>
@@ -62,6 +62,7 @@ constructor(
private val logger: TrustRepositoryLogger, private val logger: TrustRepositoryLogger,
) : TrustRepository { ) : TrustRepository {
private val latestTrustModelForUser = mutableMapOf<Int, TrustModel>() private val latestTrustModelForUser = mutableMapOf<Int, TrustModel>()
private val activeUnlockRunningForUser = mutableMapOf<Int, ActiveUnlockModel>()
private val trustManagedForUser = mutableMapOf<Int, TrustManagedModel>() private val trustManagedForUser = mutableMapOf<Int, TrustManagedModel>()
private val trust = private val trust =
@@ -87,6 +88,17 @@ constructor(
override fun onEnabledTrustAgentsChanged(userId: Int) = Unit override fun onEnabledTrustAgentsChanged(userId: Int) = Unit
override fun onIsActiveUnlockRunningChanged(
isRunning: Boolean,
userId: Int
) {
trySendWithFailureLogging(
ActiveUnlockModel(isRunning, userId),
TrustRepositoryLogger.TAG,
"onActiveUnlockRunningChanged"
)
}
override fun onTrustManagedChanged(isTrustManaged: Boolean, userId: Int) { override fun onTrustManagedChanged(isTrustManaged: Boolean, userId: Int) {
logger.onTrustManagedChanged(isTrustManaged, userId) logger.onTrustManagedChanged(isTrustManaged, userId)
trySendWithFailureLogging( trySendWithFailureLogging(
@@ -95,11 +107,6 @@ constructor(
"onTrustManagedChanged" "onTrustManagedChanged"
) )
} }
override fun onIsActiveUnlockRunningChanged(
isRunning: Boolean,
userId: Int
) = Unit
} }
trustManager.registerTrustListener(callback) trustManager.registerTrustListener(callback)
logger.trustListenerRegistered() logger.trustListenerRegistered()
@@ -114,6 +121,10 @@ constructor(
latestTrustModelForUser[it.userId] = it latestTrustModelForUser[it.userId] = it
logger.trustModelEmitted(it) logger.trustModelEmitted(it)
} }
is ActiveUnlockModel -> {
activeUnlockRunningForUser[it.userId] = it
logger.activeUnlockModelEmitted(it)
}
is TrustManagedModel -> { is TrustManagedModel -> {
trustManagedForUser[it.userId] = it trustManagedForUser[it.userId] = it
logger.trustManagedModelEmitted(it) logger.trustManagedModelEmitted(it)
@@ -122,8 +133,17 @@ constructor(
} }
.shareIn(applicationScope, started = SharingStarted.Eagerly, replay = 1) .shareIn(applicationScope, started = SharingStarted.Eagerly, replay = 1)
// TODO: Implement based on TrustManager callback b/267322286 override val isCurrentUserActiveUnlockRunning: Flow<Boolean> =
override val isCurrentUserActiveUnlockAvailable: StateFlow<Boolean> = MutableStateFlow(true) combine(trust, userRepository.selectedUserInfo, ::Pair)
.map { activeUnlockRunningForUser[it.second.id]?.isRunning ?: false }
.distinctUntilChanged()
.onEach { logger.isCurrentUserActiveUnlockRunning(it) }
.onStart {
emit(
activeUnlockRunningForUser[userRepository.getSelectedUserInfo().id]?.isRunning
?: false
)
}
override val isCurrentUserTrustManaged: StateFlow<Boolean> override val isCurrentUserTrustManaged: StateFlow<Boolean>
get() = get() =

View File

@@ -31,6 +31,7 @@ import com.android.systemui.DejankUtils
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags import com.android.systemui.flags.Flags
@@ -43,11 +44,14 @@ import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.shared.system.SysUiStatsLog import com.android.systemui.shared.system.SysUiStatsLog
import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.KeyguardStateController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
/** /**
@@ -58,18 +62,19 @@ import javax.inject.Inject
class PrimaryBouncerInteractor class PrimaryBouncerInteractor
@Inject @Inject
constructor( constructor(
private val repository: KeyguardBouncerRepository, private val repository: KeyguardBouncerRepository,
private val primaryBouncerView: BouncerView, private val primaryBouncerView: BouncerView,
@Main private val mainHandler: Handler, @Main private val mainHandler: Handler,
private val keyguardStateController: KeyguardStateController, private val keyguardStateController: KeyguardStateController,
private val keyguardSecurityModel: KeyguardSecurityModel, private val keyguardSecurityModel: KeyguardSecurityModel,
private val primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor, private val primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor,
private val falsingCollector: FalsingCollector, private val falsingCollector: FalsingCollector,
private val dismissCallbackRegistry: DismissCallbackRegistry, private val dismissCallbackRegistry: DismissCallbackRegistry,
private val context: Context, private val context: Context,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val trustRepository: TrustRepository, private val trustRepository: TrustRepository,
private val featureFlags: FeatureFlags, private val featureFlags: FeatureFlags,
@Application private val applicationScope: CoroutineScope,
) { ) {
private val passiveAuthBouncerDelay = context.resources.getInteger( private val passiveAuthBouncerDelay = context.resources.getInteger(
R.integer.primary_bouncer_passive_auth_delay).toLong() R.integer.primary_bouncer_passive_auth_delay).toLong()
@@ -104,6 +109,7 @@ constructor(
/** Allow for interaction when just about fully visible */ /** Allow for interaction when just about fully visible */
val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 } val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
private var currentUserActiveUnlockRunning = false
/** This callback needs to be a class field so it does not get garbage collected. */ /** This callback needs to be a class field so it does not get garbage collected. */
val keyguardUpdateMonitorCallback = val keyguardUpdateMonitorCallback =
@@ -122,6 +128,13 @@ constructor(
init { init {
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
if (featureFlags.isEnabled(Flags.DELAY_BOUNCER)) {
applicationScope.launch {
trustRepository.isCurrentUserActiveUnlockRunning.collect {
currentUserActiveUnlockRunning = it
}
}
}
} }
// TODO(b/243685699): Move isScrimmed logic to data layer. // TODO(b/243685699): Move isScrimmed logic to data layer.
@@ -377,8 +390,9 @@ constructor(
private fun usePrimaryBouncerPassiveAuthDelay(): Boolean { private fun usePrimaryBouncerPassiveAuthDelay(): Boolean {
val canRunFaceAuth = keyguardStateController.isFaceAuthEnabled && val canRunFaceAuth = keyguardStateController.isFaceAuthEnabled &&
keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE) keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE)
val canRunActiveUnlock = trustRepository.isCurrentUserActiveUnlockAvailable.value && val canRunActiveUnlock = currentUserActiveUnlockRunning &&
keyguardUpdateMonitor.canTriggerActiveUnlockBasedOnDeviceState() keyguardUpdateMonitor.canTriggerActiveUnlockBasedOnDeviceState()
return featureFlags.isEnabled(Flags.DELAY_BOUNCER) && return featureFlags.isEnabled(Flags.DELAY_BOUNCER) &&
!needsFullscreenBouncer() && !needsFullscreenBouncer() &&
(canRunFaceAuth || canRunActiveUnlock) (canRunFaceAuth || canRunActiveUnlock)

View File

@@ -0,0 +1,25 @@
/*
* 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.shared.model
/** Represents the active unlock state */
data class ActiveUnlockModel(
/** If true, the system believes active unlock is available and can be usd to unlock. */
val isRunning: Boolean,
/** The user, for which active unlock may be running. */
val userId: Int,
)

View File

@@ -24,13 +24,14 @@ import com.android.keyguard.KeyguardSecurityModel
import com.android.systemui.RoboPilotTest import com.android.systemui.RoboPilotTest
import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepositoryImpl import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepositoryImpl
import com.android.systemui.keyguard.data.repository.TrustRepository
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
@@ -95,8 +96,9 @@ class UdfpsKeyguardViewLegacyControllerWithCoroutinesTest :
mock(DismissCallbackRegistry::class.java), mock(DismissCallbackRegistry::class.java),
context, context,
mKeyguardUpdateMonitor, mKeyguardUpdateMonitor,
mock(TrustRepository::class.java), FakeTrustRepository(),
FakeFeatureFlags(), FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) },
testScope.backgroundScope,
) )
mAlternateBouncerInteractor = mAlternateBouncerInteractor =
AlternateBouncerInteractor( AlternateBouncerInteractor(

View File

@@ -64,7 +64,6 @@ class TrustRepositoryTest : SysuiTestCase() {
testScope = TestScope() testScope = TestScope()
userRepository = FakeUserRepository() userRepository = FakeUserRepository()
userRepository.setUserInfos(users) userRepository.setUserInfos(users)
val logger = val logger =
TrustRepositoryLogger( TrustRepositoryLogger(
LogBuffer("TestBuffer", 1, mock(LogcatEchoTracker::class.java), false) LogBuffer("TestBuffer", 1, mock(LogcatEchoTracker::class.java), false)
@@ -224,4 +223,41 @@ class TrustRepositoryTest : SysuiTestCase() {
assertThat(isCurrentUserTrusted()).isTrue() assertThat(isCurrentUserTrusted()).isTrue()
} }
@Test
fun isCurrentUserActiveUnlockRunning_runningFirstBeforeUserInfoChanges_emitsCorrectValue() =
testScope.runTest {
runCurrent()
verify(trustManager).registerTrustListener(listener.capture())
val isCurrentUserActiveUnlockRunning by
collectLastValue(underTest.isCurrentUserActiveUnlockRunning)
userRepository.setSelectedUserInfo(users[1])
// active unlock running = true for users[0].id, but not the current user
listener.value.onIsActiveUnlockRunningChanged(true, users[0].id)
assertThat(isCurrentUserActiveUnlockRunning).isFalse()
// current user is now users[0].id
userRepository.setSelectedUserInfo(users[0])
assertThat(isCurrentUserActiveUnlockRunning).isTrue()
}
@Test
fun isCurrentUserActiveUnlockRunning_whenActiveUnlockRunningForCurrentUser_emitsNewValue() =
testScope.runTest {
runCurrent()
verify(trustManager).registerTrustListener(listener.capture())
val isCurrentUserActiveUnlockRunning by
collectLastValue(underTest.isCurrentUserActiveUnlockRunning)
userRepository.setSelectedUserInfo(users[0])
listener.value.onIsActiveUnlockRunningChanged(true, users[0].id)
assertThat(isCurrentUserActiveUnlockRunning).isTrue()
listener.value.onIsActiveUnlockRunningChanged(false, users[0].id)
assertThat(isCurrentUserActiveUnlockRunning).isFalse()
listener.value.onIsActiveUnlockRunningChanged(true, users[0].id)
assertThat(isCurrentUserActiveUnlockRunning).isTrue()
}
} }

View File

@@ -35,7 +35,7 @@ import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepo
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.TrustRepository import com.android.systemui.keyguard.data.repository.FakeTrustRepository
import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -100,8 +100,9 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
mock(DismissCallbackRegistry::class.java), mock(DismissCallbackRegistry::class.java),
context, context,
keyguardUpdateMonitor, keyguardUpdateMonitor,
mock(TrustRepository::class.java), FakeTrustRepository(),
FakeFeatureFlags(), FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) },
testScope.backgroundScope,
), ),
AlternateBouncerInteractor( AlternateBouncerInteractor(
mock(StatusBarStateController::class.java), mock(StatusBarStateController::class.java),

View File

@@ -44,6 +44,8 @@ import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever import com.android.systemui.util.mockito.whenever
import com.android.systemui.utils.os.FakeHandler import com.android.systemui.utils.os.FakeHandler
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -75,6 +77,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
private lateinit var resources: TestableResources private lateinit var resources: TestableResources
private lateinit var trustRepository: FakeTrustRepository private lateinit var trustRepository: FakeTrustRepository
private lateinit var featureFlags: FakeFeatureFlags private lateinit var featureFlags: FakeFeatureFlags
private lateinit var testScope: TestScope
@Before @Before
fun setUp() { fun setUp() {
@@ -83,9 +86,10 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
.thenReturn(KeyguardSecurityModel.SecurityMode.PIN) .thenReturn(KeyguardSecurityModel.SecurityMode.PIN)
DejankUtils.setImmediate(true) DejankUtils.setImmediate(true)
testScope = TestScope()
mainHandler = FakeHandler(android.os.Looper.getMainLooper()) mainHandler = FakeHandler(android.os.Looper.getMainLooper())
trustRepository = FakeTrustRepository() trustRepository = FakeTrustRepository()
featureFlags = FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, false) } featureFlags = FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) }
underTest = underTest =
PrimaryBouncerInteractor( PrimaryBouncerInteractor(
repository, repository,
@@ -100,6 +104,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
keyguardUpdateMonitor, keyguardUpdateMonitor,
trustRepository, trustRepository,
featureFlags, featureFlags,
testScope.backgroundScope,
) )
whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null) whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
whenever(repository.primaryBouncerShow.value).thenReturn(false) whenever(repository.primaryBouncerShow.value).thenReturn(false)
@@ -398,7 +403,6 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
mainHandler.setMode(FakeHandler.Mode.QUEUEING) mainHandler.setMode(FakeHandler.Mode.QUEUEING)
// GIVEN bouncer should be delayed due to face auth // GIVEN bouncer should be delayed due to face auth
featureFlags.apply { set(Flags.DELAY_BOUNCER, true) }
whenever(keyguardStateController.isFaceAuthEnabled).thenReturn(true) whenever(keyguardStateController.isFaceAuthEnabled).thenReturn(true)
whenever(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE)) whenever(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE))
.thenReturn(true) .thenReturn(true)
@@ -420,26 +424,29 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Test @Test
fun delayBouncerWhenActiveUnlockPossible() { fun delayBouncerWhenActiveUnlockPossible() {
mainHandler.setMode(FakeHandler.Mode.QUEUEING) testScope.run {
mainHandler.setMode(FakeHandler.Mode.QUEUEING)
// GIVEN bouncer should be delayed due to active unlock // GIVEN bouncer should be delayed due to active unlock
featureFlags.apply { set(Flags.DELAY_BOUNCER, true) } trustRepository.setCurrentUserActiveUnlockAvailable(true)
trustRepository.setCurrentUserActiveUnlockAvailable(true) whenever(keyguardUpdateMonitor.canTriggerActiveUnlockBasedOnDeviceState())
whenever(keyguardUpdateMonitor.canTriggerActiveUnlockBasedOnDeviceState()).thenReturn(true) .thenReturn(true)
runCurrent()
// WHEN bouncer show is requested // WHEN bouncer show is requested
underTest.show(true) underTest.show(true)
// THEN primary show & primary showing soon were scheduled to update // THEN primary show & primary showing soon were scheduled to update
verify(repository, never()).setPrimaryShow(true) verify(repository, never()).setPrimaryShow(true)
verify(repository, never()).setPrimaryShowingSoon(false) verify(repository, never()).setPrimaryShowingSoon(false)
// WHEN all queued messages are dispatched // WHEN all queued messages are dispatched
mainHandler.dispatchQueuedMessages() mainHandler.dispatchQueuedMessages()
// THEN primary show & primary showing soon are updated // THEN primary show & primary showing soon are updated
verify(repository).setPrimaryShow(true) verify(repository).setPrimaryShow(true)
verify(repository).setPrimaryShowingSoon(false) verify(repository).setPrimaryShowingSoon(false)
}
} }
private fun updateSideFpsVisibilityParameters( private fun updateSideFpsVisibilityParameters(

View File

@@ -26,6 +26,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
@@ -34,6 +35,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.utils.os.FakeHandler import com.android.systemui.utils.os.FakeHandler
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@@ -75,7 +77,8 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
context, context,
keyguardUpdateMonitor, keyguardUpdateMonitor,
Mockito.mock(TrustRepository::class.java), Mockito.mock(TrustRepository::class.java),
FakeFeatureFlags(), FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) },
TestScope().backgroundScope,
) )
} }

View File

@@ -25,6 +25,7 @@ import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
@@ -38,6 +39,7 @@ import com.android.systemui.utils.os.FakeHandler
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Before import org.junit.Before
@@ -81,7 +83,8 @@ class KeyguardBouncerViewModelTest : SysuiTestCase() {
context, context,
keyguardUpdateMonitor, keyguardUpdateMonitor,
Mockito.mock(TrustRepository::class.java), Mockito.mock(TrustRepository::class.java),
FakeFeatureFlags(), FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) },
TestScope().backgroundScope,
) )
underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor) underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor)
} }

View File

@@ -28,7 +28,7 @@ class FakeTrustRepository : TrustRepository {
get() = _isCurrentUserTrusted get() = _isCurrentUserTrusted
private val _isCurrentUserActiveUnlockAvailable = MutableStateFlow(false) private val _isCurrentUserActiveUnlockAvailable = MutableStateFlow(false)
override val isCurrentUserActiveUnlockAvailable: StateFlow<Boolean> = override val isCurrentUserActiveUnlockRunning: StateFlow<Boolean> =
_isCurrentUserActiveUnlockAvailable.asStateFlow() _isCurrentUserActiveUnlockAvailable.asStateFlow()
private val _isCurrentUserTrustManaged = MutableStateFlow(false) private val _isCurrentUserTrustManaged = MutableStateFlow(false)