Do not separate flow into two.
In the logs of the bug report, bouncershow(true) and bouncershow(hide) is called 50 ms apart. The theory is that the ordering of the flow collection is not deterministic because bouncershow is separated into two separate flows with a map. Also added a log in the bouncer repository when the bouncer is showing/hiding. Fixes: 274608304 Test: Open and close bouncer from occluded state. Change-Id: I57595b76af9385bb83ab007f25347a5566e9903a
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.keyguard.data.repository
|
||||
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import com.android.keyguard.ViewMediatorCallback
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
@@ -34,6 +35,7 @@ import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
/**
|
||||
* Encapsulates app state for the lock screen primary and alternate bouncer.
|
||||
@@ -231,6 +233,7 @@ constructor(
|
||||
|
||||
primaryBouncerShow
|
||||
.logDiffsForTable(buffer, "", "PrimaryBouncerShow", false)
|
||||
.onEach { Log.d(TAG, "Keyguard Bouncer is ${if (it) "showing" else "hiding."}") }
|
||||
.launchIn(applicationScope)
|
||||
primaryBouncerShowingSoon
|
||||
.logDiffsForTable(buffer, "", "PrimaryBouncerShowingSoon", false)
|
||||
@@ -274,5 +277,6 @@ constructor(
|
||||
|
||||
companion object {
|
||||
private const val NOT_VISIBLE = -1L
|
||||
private const val TAG = "KeyguardBouncerRepositoryImpl"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,8 +95,7 @@ constructor(
|
||||
}
|
||||
|
||||
val keyguardAuthenticated: Flow<Boolean> = repository.keyguardAuthenticated.filterNotNull()
|
||||
val show: Flow<Unit> = repository.primaryBouncerShow.filter { it }.map {}
|
||||
val hide: Flow<Unit> = repository.primaryBouncerShow.filter { !it }.map {}
|
||||
val isShowing: Flow<Boolean> = repository.primaryBouncerShow
|
||||
val startingToHide: Flow<Unit> = repository.primaryBouncerStartingToHide.filter { it }.map {}
|
||||
val isBackButtonEnabled: Flow<Boolean> = repository.isBackButtonEnabled.filterNotNull()
|
||||
val showMessage: Flow<BouncerShowMessageModel> = repository.showMessage.filterNotNull()
|
||||
|
||||
@@ -109,35 +109,35 @@ object KeyguardBouncerViewBinder {
|
||||
try {
|
||||
viewModel.setBouncerViewDelegate(delegate)
|
||||
launch {
|
||||
viewModel.show.collect {
|
||||
// Reset Security Container entirely.
|
||||
securityContainerController.reinflateViewFlipper {
|
||||
viewModel.isShowing.collect { isShowing ->
|
||||
if (isShowing) {
|
||||
// Reset Security Container entirely.
|
||||
view.visibility = View.VISIBLE
|
||||
securityContainerController.reinflateViewFlipper {
|
||||
// Reset Security Container entirely.
|
||||
view.visibility = View.VISIBLE
|
||||
securityContainerController.onBouncerVisibilityChanged(
|
||||
/* isVisible= */ true
|
||||
)
|
||||
securityContainerController.showPrimarySecurityScreen(
|
||||
/* turningOff= */ false
|
||||
)
|
||||
securityContainerController.appear()
|
||||
securityContainerController.onResume(
|
||||
KeyguardSecurityView.SCREEN_ON
|
||||
)
|
||||
}
|
||||
} else {
|
||||
view.visibility = View.INVISIBLE
|
||||
securityContainerController.onBouncerVisibilityChanged(
|
||||
/* isVisible= */ true
|
||||
/* isVisible= */ false
|
||||
)
|
||||
securityContainerController.showPrimarySecurityScreen(
|
||||
/* turningOff= */ false
|
||||
)
|
||||
securityContainerController.appear()
|
||||
securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
|
||||
securityContainerController.cancelDismissAction()
|
||||
securityContainerController.reset()
|
||||
securityContainerController.onPause()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
viewModel.hide.collect {
|
||||
view.visibility = View.INVISIBLE
|
||||
securityContainerController.onBouncerVisibilityChanged(
|
||||
/* isVisible= */ false
|
||||
)
|
||||
securityContainerController.cancelDismissAction()
|
||||
securityContainerController.reset()
|
||||
securityContainerController.onPause()
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
viewModel.startingToHide.collect {
|
||||
securityContainerController.onStartingToHide()
|
||||
|
||||
@@ -40,11 +40,8 @@ constructor(
|
||||
/** Can the user interact with the view? */
|
||||
val isInteractable: Flow<Boolean> = interactor.isInteractable
|
||||
|
||||
/** Observe whether bouncer is showing. */
|
||||
val show: Flow<Unit> = interactor.show
|
||||
|
||||
/** Observe whether bouncer is hiding. */
|
||||
val hide: Flow<Unit> = interactor.hide
|
||||
/** Observe whether bouncer is showing or not. */
|
||||
val isShowing: Flow<Boolean> = interactor.isShowing
|
||||
|
||||
/** Observe whether bouncer is starting to hide. */
|
||||
val startingToHide: Flow<Unit> = interactor.startingToHide
|
||||
@@ -70,8 +67,8 @@ constructor(
|
||||
/** Observe whether we should update fps is showing. */
|
||||
val shouldUpdateSideFps: Flow<Unit> =
|
||||
merge(
|
||||
interactor.hide,
|
||||
interactor.show,
|
||||
interactor.isShowing.map {},
|
||||
interactor.startingToHide,
|
||||
interactor.startingDisappearAnimation.filterNotNull().map {}
|
||||
)
|
||||
|
||||
|
||||
@@ -125,4 +125,26 @@ class KeyguardBouncerViewModelTest : SysuiTestCase() {
|
||||
assertThat(sideFpsIsShowing).isEqualTo(true)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isShowing() = runTest {
|
||||
var isShowing: Boolean? = null
|
||||
val job = underTest.isShowing.onEach { isShowing = it }.launchIn(this)
|
||||
repository.setPrimaryShow(true)
|
||||
// Run the tasks that are pending at this point of virtual time.
|
||||
runCurrent()
|
||||
assertThat(isShowing).isEqualTo(true)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isNotShowing() = runTest {
|
||||
var isShowing: Boolean? = null
|
||||
val job = underTest.isShowing.onEach { isShowing = it }.launchIn(this)
|
||||
repository.setPrimaryShow(false)
|
||||
// Run the tasks that are pending at this point of virtual time.
|
||||
runCurrent()
|
||||
assertThat(isShowing).isEqualTo(false)
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user