Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85122e76 authored by Matt Pietal's avatar Matt Pietal
Browse files

Fix NSSL flicker when going to/from OCCLUDED

There was a small flicker as the alpha would be set to 1 briefly
during the transitions. It turns out the legacy shade interactor may
send an event indicating the shade is fully expanded when it
resets. This is followed by an event that says it's now collapsed but
the damage is done. Prevent this by never interrupting the transitions
from KeyguardTransitionRepository.

Fixes: 314290249
Test: Manual - observe the one frame flicker no longer happens during
OCCLUDED<->LOCKSCREEN
Flag: ACONFIG com.android.systemui.keyguard_shade_migration_nssl
DEVELOPMENT

Change-Id: I460dfc11a55d94d07db9a94b00c58b9fdfda2979
parent 5b1e3439
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -1160,9 +1160,9 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
        // Occluded->Lockscreen
        collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
                mOccludedToLockscreenTransition, mMainDispatcher);
        if (!KeyguardShadeMigrationNssl.isEnabled()) {
        collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
        if (!KeyguardShadeMigrationNssl.isEnabled()) {
            collectFlow(mView,
                    mOccludedToLockscreenTransitionViewModel.getLockscreenTranslationY(),
                    setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
@@ -1192,8 +1192,10 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
                mLockscreenToOccludedTransition, mMainDispatcher);
        collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
        if (!KeyguardShadeMigrationNssl.isEnabled()) {
            collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY(),
                    setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
        }

        // Primary bouncer->Gone (ensures lockscreen content is not visible on successful auth)
        collectFlow(mView, mPrimaryBouncerToGoneTransitionViewModel.getLockscreenAlpha(),
+48 −17
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED
import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel
import com.android.systemui.shade.domain.interactor.ShadeInteractor
@@ -71,6 +73,20 @@ constructor(
            KeyguardState.PRIMARY_BOUNCER
        )

    private val lockscreenToOccludedRunning =
        keyguardTransitionInteractor
            .transition(KeyguardState.LOCKSCREEN, KeyguardState.OCCLUDED)
            .map { it.transitionState == STARTED || it.transitionState == RUNNING }
            .distinctUntilChanged()
            .onStart { emit(false) }

    private val occludedToLockscreenRunning =
        keyguardTransitionInteractor
            .transition(KeyguardState.OCCLUDED, KeyguardState.LOCKSCREEN)
            .map { it.transitionState == STARTED || it.transitionState == RUNNING }
            .distinctUntilChanged()
            .onStart { emit(false) }

    val shadeCollapseFadeInComplete = MutableStateFlow(false)

    val configurationBasedDimensions: Flow<ConfigurationBasedDimensions> =
@@ -122,7 +138,11 @@ constructor(
            ) { isKeyguard, isShadeVisible, qsExpansion ->
                isKeyguard && !(isShadeVisible || qsExpansion)
            }
            .distinctUntilChanged()
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.Eagerly,
                initialValue = false,
            )

    /** Fade in only for use after the shade collapses */
    val shadeCollpaseFadeIn: Flow<Boolean> =
@@ -182,14 +202,22 @@ constructor(
            )

    val alpha: Flow<Float> =
        isOnLockscreenWithoutShade
            .flatMapLatest { isOnLockscreenWithoutShade ->
        // Due to issues with the legacy shade, some shade expansion events are sent incorrectly,
        // such as when the shade resets. This can happen while the LOCKSCREEN<->OCCLUDED transition
        // is running. Therefore use a series of flatmaps to prevent unwanted interruptions while
        // those transitions are in progress. Without this, the alpha value will produce a visible
        // flicker.
        lockscreenToOccludedRunning.flatMapLatest { isLockscreenToOccludedRunning ->
            if (isLockscreenToOccludedRunning) {
                lockscreenToOccludedTransitionViewModel.lockscreenAlpha
            } else {
                occludedToLockscreenRunning.flatMapLatest { isOccludedToLockscreenRunning ->
                    if (isOccludedToLockscreenRunning) {
                        occludedToLockscreenTransitionViewModel.lockscreenAlpha.onStart { emit(0f) }
                    } else {
                        isOnLockscreenWithoutShade.flatMapLatest { isOnLockscreenWithoutShade ->
                            combineTransform(
                    merge(
                        occludedToLockscreenTransitionViewModel.lockscreenAlpha,
                        lockscreenToOccludedTransitionViewModel.lockscreenAlpha,
                                keyguardInteractor.keyguardAlpha,
                    ),
                                shadeCollpaseFadeIn,
                            ) { alpha, shadeCollpaseFadeIn ->
                                if (isOnLockscreenWithoutShade) {
@@ -201,7 +229,10 @@ constructor(
                                }
                            }
                        }
            .distinctUntilChanged()
                    }
                }
            }
        }

    /**
     * Under certain scenarios, such as swiping up on the lockscreen, the container will need to be
+13 −6
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.notification.stack.domain.interactor.share
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -418,13 +419,13 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        }

    @Test
    fun shadeCollpaseFadeIn() =
    fun shadeCollapseFadeIn() =
        testScope.runTest {
            val fadeIn by collectLastValue(underTest.shadeCollpaseFadeIn)

            // Start on lockscreen without the shade
            underTest.setShadeCollapseFadeInComplete(false)
            showLockscreen()

            val fadeIn by collectLastValue(underTest.shadeCollpaseFadeIn)
            assertThat(fadeIn).isEqualTo(false)

            // ... then the shade expands
@@ -440,10 +441,12 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
            assertThat(fadeIn).isEqualTo(false)
        }

    private suspend fun showLockscreen() {
    private suspend fun TestScope.showLockscreen() {
        shadeRepository.setLockscreenShadeExpansion(0f)
        shadeRepository.setQsExpansion(0f)
        runCurrent()
        keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
        runCurrent()
        keyguardTransitionRepository.sendTransitionSteps(
            from = KeyguardState.AOD,
            to = KeyguardState.LOCKSCREEN,
@@ -451,10 +454,12 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        )
    }

    private suspend fun showLockscreenWithShadeExpanded() {
    private suspend fun TestScope.showLockscreenWithShadeExpanded() {
        shadeRepository.setLockscreenShadeExpansion(1f)
        shadeRepository.setQsExpansion(0f)
        runCurrent()
        keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
        runCurrent()
        keyguardTransitionRepository.sendTransitionSteps(
            from = KeyguardState.AOD,
            to = KeyguardState.LOCKSCREEN,
@@ -462,10 +467,12 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        )
    }

    private suspend fun showLockscreenWithQSExpanded() {
    private suspend fun TestScope.showLockscreenWithQSExpanded() {
        shadeRepository.setLockscreenShadeExpansion(0f)
        shadeRepository.setQsExpansion(1f)
        runCurrent()
        keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
        runCurrent()
        keyguardTransitionRepository.sendTransitionSteps(
            from = KeyguardState.AOD,
            to = KeyguardState.LOCKSCREEN,