Remove visibility and show race condition.

Visibility and show were emitted by two different flows. Sometimes we
were setting visibility to visible before show is called, leading to UI
jank. I removed the visibility flow and added it into the show and hide
flows. I also removed the hide flow for further simplification.

Fixes: 263924084
Bug: 267821080
Test: Long press lock icon to show bouncer like 20 times.
Test: Look at sim pin and sim puk views.
Change-Id: Id5d0e86eb64844b06f6082e2c51c5a3e50c45a41
This commit is contained in:
Aaron Liu
2023-03-08 13:40:50 -08:00
parent 988d98eca1
commit 248fe3fbbe
15 changed files with 90 additions and 174 deletions

View File

@@ -55,4 +55,5 @@ interface BouncerViewDelegate {
fun willRunDismissFromKeyguard(): Boolean
/** @return the {@link OnBackAnimationCallback} to animate Bouncer during a back gesture. */
fun getBackCallback(): OnBackAnimationCallback
fun showPromptReason(reason: Int)
}

View File

@@ -22,7 +22,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import com.android.systemui.log.dagger.BouncerLog
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
@@ -43,10 +42,8 @@ import kotlinx.coroutines.flow.map
*/
interface KeyguardBouncerRepository {
/** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
val primaryBouncerVisible: StateFlow<Boolean>
val primaryBouncerShow: StateFlow<KeyguardBouncerModel?>
val primaryBouncerShow: StateFlow<Boolean>
val primaryBouncerShowingSoon: StateFlow<Boolean>
val primaryBouncerHide: StateFlow<Boolean>
val primaryBouncerStartingToHide: StateFlow<Boolean>
val primaryBouncerStartingDisappearAnimation: StateFlow<Runnable?>
/** Determines if we want to instantaneously show the primary bouncer instead of translating. */
@@ -76,14 +73,10 @@ interface KeyguardBouncerRepository {
fun setPrimaryScrimmed(isScrimmed: Boolean)
fun setPrimaryVisible(isVisible: Boolean)
fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?)
fun setPrimaryShow(isShowing: Boolean)
fun setPrimaryShowingSoon(showingSoon: Boolean)
fun setPrimaryHide(hide: Boolean)
fun setPrimaryStartingToHide(startingToHide: Boolean)
fun setPrimaryStartDisappearAnimation(runnable: Runnable?)
@@ -117,14 +110,10 @@ constructor(
@BouncerLog private val buffer: TableLogBuffer,
) : KeyguardBouncerRepository {
/** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
private val _primaryBouncerVisible = MutableStateFlow(false)
override val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null)
private val _primaryBouncerShow = MutableStateFlow(false)
override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
private val _primaryBouncerShowingSoon = MutableStateFlow(false)
override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
private val _primaryBouncerHide = MutableStateFlow(false)
override val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
private val _primaryBouncerStartingToHide = MutableStateFlow(false)
override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
@@ -177,10 +166,6 @@ constructor(
_primaryBouncerScrimmed.value = isScrimmed
}
override fun setPrimaryVisible(isVisible: Boolean) {
_primaryBouncerVisible.value = isVisible
}
override fun setAlternateVisible(isVisible: Boolean) {
if (isVisible && !_alternateBouncerVisible.value) {
lastAlternateBouncerVisibleTime = clock.uptimeMillis()
@@ -194,18 +179,14 @@ constructor(
_alternateBouncerUIAvailable.value = isAvailable
}
override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
_primaryBouncerShow.value = keyguardBouncerModel
override fun setPrimaryShow(isShowing: Boolean) {
_primaryBouncerShow.value = isShowing
}
override fun setPrimaryShowingSoon(showingSoon: Boolean) {
_primaryBouncerShowingSoon.value = showingSoon
}
override fun setPrimaryHide(hide: Boolean) {
_primaryBouncerHide.value = hide
}
override fun setPrimaryStartingToHide(startingToHide: Boolean) {
_primaryBouncerStartingToHide.value = startingToHide
}
@@ -248,19 +229,12 @@ constructor(
return
}
primaryBouncerVisible
.logDiffsForTable(buffer, "", "PrimaryBouncerVisible", false)
.launchIn(applicationScope)
primaryBouncerShow
.map { it != null }
.logDiffsForTable(buffer, "", "PrimaryBouncerShow", false)
.launchIn(applicationScope)
primaryBouncerShowingSoon
.logDiffsForTable(buffer, "", "PrimaryBouncerShowingSoon", false)
.launchIn(applicationScope)
primaryBouncerHide
.logDiffsForTable(buffer, "", "PrimaryBouncerHide", false)
.launchIn(applicationScope)
primaryBouncerStartingToHide
.logDiffsForTable(buffer, "", "PrimaryBouncerStartingToHide", false)
.launchIn(applicationScope)

View File

@@ -137,7 +137,7 @@ constructor(
/** Whether the keyguard is going away. */
val isKeyguardGoingAway: Flow<Boolean> = repository.isKeyguardGoingAway
/** Whether the primary bouncer is showing or not. */
val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerVisible
val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow
/** Whether the alternate bouncer is showing or not. */
val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
/** Observable for the [StatusBarState] */
@@ -159,7 +159,7 @@ constructor(
if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) {
combine(
isKeyguardVisible,
bouncerRepository.primaryBouncerVisible,
primaryBouncerShowing,
onCameraLaunchDetected,
) { isKeyguardVisible, isPrimaryBouncerShowing, cameraLaunchEvent ->
when {

View File

@@ -23,12 +23,13 @@ import android.os.Handler
import android.os.Trace
import android.os.UserHandle
import android.os.UserManager
import android.view.View
import android.util.Log
import android.view.View
import com.android.keyguard.KeyguardConstants
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.settingslib.Utils
import com.android.systemui.DejankUtils
import com.android.systemui.R
import com.android.systemui.classifier.FalsingCollector
@@ -39,7 +40,6 @@ import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.shared.system.SysUiStatsLog
import com.android.systemui.statusbar.phone.KeyguardBypassController
@@ -83,23 +83,21 @@ constructor(
/** Runnable to show the primary bouncer. */
val showRunnable = Runnable {
repository.setPrimaryVisible(true)
repository.setPrimaryShow(
KeyguardBouncerModel(
promptReason = repository.bouncerPromptReason ?: 0,
errorMessage = repository.bouncerErrorMessage,
expansionAmount = repository.panelExpansionAmount.value
repository.setPrimaryShow(true)
primaryBouncerView.delegate?.showPromptReason(repository.bouncerPromptReason)
(repository.bouncerErrorMessage as? String)?.let {
repository.setShowMessage(
BouncerShowMessageModel(message = it, Utils.getColorError(context))
)
)
}
repository.setPrimaryShowingSoon(false)
primaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.VISIBLE)
}
val keyguardAuthenticated: Flow<Boolean> = repository.keyguardAuthenticated.filterNotNull()
val show: Flow<KeyguardBouncerModel> = repository.primaryBouncerShow.filterNotNull()
val hide: Flow<Unit> = repository.primaryBouncerHide.filter { it }.map {}
val show: Flow<Unit> = repository.primaryBouncerShow.filter { it }.map {}
val hide: Flow<Unit> = repository.primaryBouncerShow.filter { !it }.map {}
val startingToHide: Flow<Unit> = repository.primaryBouncerStartingToHide.filter { it }.map {}
val isVisible: Flow<Boolean> = repository.primaryBouncerVisible
val isBackButtonEnabled: Flow<Boolean> = repository.isBackButtonEnabled.filterNotNull()
val showMessage: Flow<BouncerShowMessageModel> = repository.showMessage.filterNotNull()
val startingDisappearAnimation: Flow<Runnable> =
@@ -109,10 +107,11 @@ constructor(
val panelExpansionAmount: Flow<Float> = repository.panelExpansionAmount
/** 0f = bouncer fully hidden. 1f = bouncer fully visible. */
val bouncerExpansion: Flow<Float> =
combine(repository.panelExpansionAmount, repository.primaryBouncerVisible) {
panelExpansion,
primaryBouncerVisible ->
if (primaryBouncerVisible) {
combine(
repository.panelExpansionAmount,
repository.primaryBouncerShow
) { panelExpansion, primaryBouncerIsShowing ->
if (primaryBouncerIsShowing) {
1f - panelExpansion
} else {
0f
@@ -122,21 +121,20 @@ constructor(
val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
/**
* This callback needs to be a class field so it does not get garbage collected.
*/
val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() {
override fun onBiometricRunningStateChanged(
running: Boolean,
biometricSourceType: BiometricSourceType?
) {
updateSideFpsVisibility()
}
/** This callback needs to be a class field so it does not get garbage collected. */
val keyguardUpdateMonitorCallback =
object : KeyguardUpdateMonitorCallback() {
override fun onBiometricRunningStateChanged(
running: Boolean,
biometricSourceType: BiometricSourceType?
) {
updateSideFpsVisibility()
}
override fun onStrongAuthStateChanged(userId: Int) {
updateSideFpsVisibility()
override fun onStrongAuthStateChanged(userId: Int) {
updateSideFpsVisibility()
}
}
}
init {
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
@@ -149,14 +147,13 @@ constructor(
fun show(isScrimmed: Boolean) {
// Reset some states as we show the bouncer.
repository.setKeyguardAuthenticated(null)
repository.setPrimaryHide(false)
repository.setPrimaryStartingToHide(false)
val resumeBouncer =
(repository.primaryBouncerVisible.value ||
repository.primaryBouncerShowingSoon.value) && needsFullscreenBouncer()
(isBouncerShowing() || repository.primaryBouncerShowingSoon.value) &&
needsFullscreenBouncer()
if (!resumeBouncer && repository.primaryBouncerShow.value != null) {
if (!resumeBouncer && isBouncerShowing()) {
// If bouncer is visible, the bouncer is already showing.
return
}
@@ -209,9 +206,7 @@ constructor(
keyguardStateController.notifyPrimaryBouncerShowing(false /* showing */)
cancelShowRunnable()
repository.setPrimaryShowingSoon(false)
repository.setPrimaryVisible(false)
repository.setPrimaryHide(true)
repository.setPrimaryShow(null)
repository.setPrimaryShow(false)
primaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.INVISIBLE)
Trace.endSection()
}
@@ -328,9 +323,8 @@ constructor(
val fpsDetectionRunning: Boolean = keyguardUpdateMonitor.isFingerprintDetectionRunning
val isUnlockingWithFpAllowed: Boolean =
keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed
val bouncerVisible = repository.primaryBouncerVisible.value
val toShow =
(repository.primaryBouncerVisible.value &&
(isBouncerShowing() &&
sfpsEnabled &&
fpsDetectionRunning &&
isUnlockingWithFpAllowed &&
@@ -340,7 +334,7 @@ constructor(
Log.d(
TAG,
("sideFpsToShow=$toShow\n" +
"bouncerVisible=$bouncerVisible\n" +
"isBouncerShowing=${isBouncerShowing()}\n" +
"configEnabled=$sfpsEnabled\n" +
"fpsDetectionRunning=$fpsDetectionRunning\n" +
"isUnlockingWithFpAllowed=$isUnlockingWithFpAllowed\n" +
@@ -352,8 +346,7 @@ constructor(
/** Returns whether bouncer is fully showing. */
fun isFullyShowing(): Boolean {
return (repository.primaryBouncerShowingSoon.value ||
repository.primaryBouncerVisible.value) &&
return (repository.primaryBouncerShowingSoon.value || isBouncerShowing()) &&
repository.panelExpansionAmount.value == KeyguardBouncerConstants.EXPANSION_VISIBLE &&
repository.primaryBouncerStartingDisappearAnimation.value == null
}
@@ -399,6 +392,10 @@ constructor(
mainHandler.removeCallbacks(showRunnable)
}
private fun isBouncerShowing(): Boolean {
return repository.primaryBouncerShow.value
}
companion object {
private const val TAG = "PrimaryBouncerInteractor"
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright (C) 2022 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
/** Models the state of the lock-screen bouncer */
data class KeyguardBouncerModel(
val promptReason: Int = 0,
val errorMessage: CharSequence? = null,
val expansionAmount: Float = 0f,
)

View File

@@ -27,7 +27,6 @@ import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardSecurityView
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.dagger.KeyguardBouncerComponent
import com.android.settingslib.Utils
import com.android.systemui.keyguard.data.BouncerViewDelegate
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
@@ -101,6 +100,10 @@ object KeyguardBouncerViewBinder {
override fun willRunDismissFromKeyguard(): Boolean {
return securityContainerController.willRunDismissFromKeyguard()
}
override fun showPromptReason(reason: Int) {
securityContainerController.showPromptReason(reason)
}
}
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
@@ -109,14 +112,11 @@ object KeyguardBouncerViewBinder {
launch {
viewModel.show.collect {
// Reset Security Container entirely.
view.visibility = View.VISIBLE
securityContainerController.onBouncerVisibilityChanged(
/* isVisible= */ true
)
securityContainerController.reinflateViewFlipper()
securityContainerController.showPromptReason(it.promptReason)
it.errorMessage?.let { errorMessage ->
securityContainerController.showMessage(
errorMessage,
Utils.getColorError(view.context)
)
}
securityContainerController.showPrimarySecurityScreen(
/* turningOff= */ false
)
@@ -127,8 +127,13 @@ object KeyguardBouncerViewBinder {
launch {
viewModel.hide.collect {
view.visibility = View.INVISIBLE
securityContainerController.onBouncerVisibilityChanged(
/* isVisible= */ false
)
securityContainerController.cancelDismissAction()
securityContainerController.reset()
securityContainerController.onPause()
}
}
@@ -165,19 +170,6 @@ object KeyguardBouncerViewBinder {
}
}
launch {
viewModel.isBouncerVisible.collect { isVisible ->
view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
securityContainerController.onBouncerVisibilityChanged(isVisible)
}
}
launch {
viewModel.isBouncerVisible
.filter { !it }
.collect { securityContainerController.onPause() }
}
launch {
viewModel.isInteractable.collect { isInteractable ->
securityContainerController.setInteractable(isInteractable)

View File

@@ -21,7 +21,6 @@ import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.BouncerViewDelegate
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filterNotNull
@@ -38,14 +37,11 @@ constructor(
/** Observe on bouncer expansion amount. */
val bouncerExpansionAmount: Flow<Float> = interactor.panelExpansionAmount
/** Observe on bouncer visibility. */
val isBouncerVisible: Flow<Boolean> = interactor.isVisible
/** Can the user interact with the view? */
val isInteractable: Flow<Boolean> = interactor.isInteractable
/** Observe whether bouncer is showing. */
val show: Flow<KeyguardBouncerModel> = interactor.show
val show: Flow<Unit> = interactor.show
/** Observe whether bouncer is hiding. */
val hide: Flow<Unit> = interactor.hide
@@ -75,7 +71,7 @@ constructor(
val shouldUpdateSideFps: Flow<Unit> =
merge(
interactor.startingToHide,
interactor.isVisible.map {},
interactor.show,
interactor.startingDisappearAnimation.filterNotNull().map {}
)

View File

@@ -138,7 +138,7 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
// WHEN the bouncer expansion is VISIBLE
val job = mController.listenForBouncerExpansion(this)
keyguardBouncerRepository.setPrimaryVisible(true)
keyguardBouncerRepository.setPrimaryShow(true)
keyguardBouncerRepository.setPanelExpansion(KeyguardBouncerConstants.EXPANSION_VISIBLE)
yield()

View File

@@ -55,7 +55,7 @@ class KeyguardBouncerRepositoryTest : SysuiTestCase() {
@Test
fun changingFlowValueTriggersLogging() = runBlocking {
underTest.setPrimaryHide(true)
verify(bouncerLogger).logChange("", "PrimaryBouncerHide", false)
underTest.setPrimaryShow(true)
verify(bouncerLogger).logChange("", "PrimaryBouncerShow", false)
}
}

View File

@@ -145,7 +145,7 @@ class KeyguardInteractorTest : SysuiTestCase() {
repository.setKeyguardOccluded(true)
assertThat(secureCameraActive()).isTrue()
bouncerRepository.setPrimaryVisible(true)
bouncerRepository.setPrimaryShow(true)
assertThat(secureCameraActive()).isFalse()
}

View File

@@ -259,7 +259,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
runCurrent()
// WHEN the primary bouncer is set to show
bouncerRepository.setPrimaryVisible(true)
bouncerRepository.setPrimaryShow(true)
runCurrent()
val info =
@@ -697,7 +697,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
reset(mockTransitionRepository)
// WHEN the alternateBouncer stops showing and then the primary bouncer shows
bouncerRepository.setPrimaryVisible(true)
bouncerRepository.setPrimaryShow(true)
runCurrent()
val info =
@@ -735,7 +735,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
reset(mockTransitionRepository)
// GIVEN the primary bouncer isn't showing, aod available and starting to sleep
bouncerRepository.setPrimaryVisible(false)
bouncerRepository.setPrimaryShow(false)
keyguardRepository.setAodAvailable(true)
keyguardRepository.setWakefulnessModel(startingToSleep())
@@ -779,7 +779,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
// GIVEN the primary bouncer isn't showing, aod not available and starting to sleep
// to sleep
bouncerRepository.setPrimaryVisible(false)
bouncerRepository.setPrimaryShow(false)
keyguardRepository.setAodAvailable(false)
keyguardRepository.setWakefulnessModel(startingToSleep())
@@ -822,7 +822,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
reset(mockTransitionRepository)
// GIVEN the primary bouncer isn't showing and device not sleeping
bouncerRepository.setPrimaryVisible(false)
bouncerRepository.setPrimaryShow(false)
keyguardRepository.setWakefulnessModel(startingToWake())
// WHEN the alternateBouncer stops showing
@@ -846,7 +846,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fun `PRIMARY_BOUNCER to AOD`() =
testScope.runTest {
// GIVEN a prior transition has run to PRIMARY_BOUNCER
bouncerRepository.setPrimaryVisible(true)
bouncerRepository.setPrimaryShow(true)
runner.startTransition(
testScope,
TransitionInfo(
@@ -868,7 +868,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(startingToSleep())
// WHEN the primaryBouncer stops showing
bouncerRepository.setPrimaryVisible(false)
bouncerRepository.setPrimaryShow(false)
runCurrent()
val info =
@@ -888,7 +888,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fun `PRIMARY_BOUNCER to DOZING`() =
testScope.runTest {
// GIVEN a prior transition has run to PRIMARY_BOUNCER
bouncerRepository.setPrimaryVisible(true)
bouncerRepository.setPrimaryShow(true)
runner.startTransition(
testScope,
TransitionInfo(
@@ -910,7 +910,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(startingToSleep())
// WHEN the primaryBouncer stops showing
bouncerRepository.setPrimaryVisible(false)
bouncerRepository.setPrimaryShow(false)
runCurrent()
val info =
@@ -930,7 +930,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fun `PRIMARY_BOUNCER to LOCKSCREEN`() =
testScope.runTest {
// GIVEN a prior transition has run to PRIMARY_BOUNCER
bouncerRepository.setPrimaryVisible(true)
bouncerRepository.setPrimaryShow(true)
runner.startTransition(
testScope,
TransitionInfo(
@@ -951,7 +951,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(startingToWake())
// WHEN the alternateBouncer stops showing
bouncerRepository.setPrimaryVisible(false)
bouncerRepository.setPrimaryShow(false)
runCurrent()
val info =

View File

@@ -35,7 +35,6 @@ import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -92,7 +91,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
keyguardBypassController,
)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
`when`(repository.primaryBouncerShow.value).thenReturn(null)
`when`(repository.primaryBouncerShow.value).thenReturn(false)
`when`(bouncerView.delegate).thenReturn(bouncerViewDelegate)
resources = context.orCreateTestableResources
}
@@ -101,15 +100,13 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
fun testShow_isScrimmed() {
underTest.show(true)
verify(repository).setKeyguardAuthenticated(null)
verify(repository).setPrimaryHide(false)
verify(repository).setPrimaryStartingToHide(false)
verify(repository).setPrimaryScrimmed(true)
verify(repository).setPanelExpansion(EXPANSION_VISIBLE)
verify(repository).setPrimaryShowingSoon(true)
verify(keyguardStateController).notifyPrimaryBouncerShowing(true)
verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToShow()
verify(repository).setPrimaryVisible(true)
verify(repository).setPrimaryShow(any(KeyguardBouncerModel::class.java))
verify(repository).setPrimaryShow(true)
verify(repository).setPrimaryShowingSoon(false)
verify(mPrimaryBouncerCallbackInteractor).dispatchVisibilityChanged(View.VISIBLE)
}
@@ -132,9 +129,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
verify(falsingCollector).onBouncerHidden()
verify(keyguardStateController).notifyPrimaryBouncerShowing(false)
verify(repository).setPrimaryShowingSoon(false)
verify(repository).setPrimaryVisible(false)
verify(repository).setPrimaryHide(true)
verify(repository).setPrimaryShow(null)
verify(repository).setPrimaryShow(false)
verify(mPrimaryBouncerCallbackInteractor).dispatchVisibilityChanged(View.INVISIBLE)
}
@@ -160,9 +155,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
`when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
underTest.setPanelExpansion(EXPANSION_HIDDEN)
verify(repository).setPrimaryVisible(false)
verify(repository).setPrimaryShow(null)
verify(repository).setPrimaryHide(true)
verify(repository).setPrimaryShow(false)
verify(falsingCollector).onBouncerHidden()
verify(mPrimaryBouncerCallbackInteractor).dispatchReset()
verify(mPrimaryBouncerCallbackInteractor).dispatchFullyHidden()
@@ -243,11 +236,11 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Test
fun testIsFullShowing() {
`when`(repository.primaryBouncerVisible.value).thenReturn(true)
`when`(repository.primaryBouncerShow.value).thenReturn(true)
`when`(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
assertThat(underTest.isFullyShowing()).isTrue()
`when`(repository.primaryBouncerVisible.value).thenReturn(false)
`when`(repository.primaryBouncerShow.value).thenReturn(false)
assertThat(underTest.isFullyShowing()).isFalse()
}
@@ -370,7 +363,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
isUnlockingWithFpAllowed: Boolean,
isAnimatingAway: Boolean
) {
`when`(repository.primaryBouncerVisible.value).thenReturn(isVisible)
`when`(repository.primaryBouncerShow.value).thenReturn(isVisible)
resources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, sfpsEnabled)
`when`(keyguardUpdateMonitor.isFingerprintDetectionRunning).thenReturn(fpsDetectionRunning)
`when`(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)

View File

@@ -77,7 +77,7 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
fun notInteractableWhenExpansionIsBelow90Percent() = runTest {
val isInteractable = collectLastValue(underTest.isInteractable)
repository.setPrimaryVisible(true)
repository.setPrimaryShow(true)
repository.setPanelExpansion(0.15f)
assertThat(isInteractable()).isFalse()
@@ -87,7 +87,7 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
fun notInteractableWhenExpansionAbove90PercentButNotVisible() = runTest {
val isInteractable = collectLastValue(underTest.isInteractable)
repository.setPrimaryVisible(false)
repository.setPrimaryShow(false)
repository.setPanelExpansion(0.05f)
assertThat(isInteractable()).isFalse()
@@ -97,7 +97,7 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
fun isInteractableWhenExpansionAbove90PercentAndVisible() = runTest {
var isInteractable = collectLastValue(underTest.isInteractable)
repository.setPrimaryVisible(true)
repository.setPrimaryShow(true)
repository.setPanelExpansion(0.09f)
assertThat(isInteractable()).isTrue()

View File

@@ -96,7 +96,7 @@ class KeyguardBouncerViewModelTest : SysuiTestCase() {
fun shouldUpdateSideFps() = runTest {
var count = 0
val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
repository.setPrimaryVisible(true)
repository.setPrimaryShow(true)
// Run the tasks that are pending at this point of virtual time.
runCurrent()
assertThat(count).isEqualTo(1)

View File

@@ -19,21 +19,16 @@ package com.android.systemui.keyguard.data.repository
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/** Fake implementation of [KeyguardRepository] */
class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
private val _primaryBouncerVisible = MutableStateFlow(false)
override val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null)
private val _primaryBouncerShow = MutableStateFlow(false)
override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
private val _primaryBouncerShowingSoon = MutableStateFlow(false)
override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
private val _primaryBouncerHide = MutableStateFlow(false)
override val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
private val _primaryBouncerStartingToHide = MutableStateFlow(false)
override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
@@ -67,10 +62,6 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
_primaryBouncerScrimmed.value = isScrimmed
}
override fun setPrimaryVisible(isVisible: Boolean) {
_primaryBouncerVisible.value = isVisible
}
override fun setAlternateVisible(isVisible: Boolean) {
_isAlternateBouncerVisible.value = isVisible
}
@@ -79,18 +70,14 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
_isAlternateBouncerUIAvailable.value = isAvailable
}
override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
_primaryBouncerShow.value = keyguardBouncerModel
override fun setPrimaryShow(isShowing: Boolean) {
_primaryBouncerShow.value = isShowing
}
override fun setPrimaryShowingSoon(showingSoon: Boolean) {
_primaryBouncerShowingSoon.value = showingSoon
}
override fun setPrimaryHide(hide: Boolean) {
_primaryBouncerHide.value = hide
}
override fun setPrimaryStartingToHide(startingToHide: Boolean) {
_primaryBouncerStartingToHide.value = startingToHide
}