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

Commit 56f4d434 authored by William Xiao's avatar William Xiao
Browse files

Fix correct scrim visibility not dispatched when closing bouncer on dream

The bouncer to dream keyguard transition manually fades the behind
scrim for a smooth transition. This can cause issues as the shade
window stays visible as long as any scrim is visible, but
ScrimController itself stops dispatching the scrim visibility state
when the scrim transition ends. This is not connected to the KTF
transition, meaning if the keyguard transition lasts longer, the scrims
are still visible by the end of the scrim transition.

This CL manually dispatches the scrim visibility state at the end of
the KTF transition.

Note that the scrim_fix flag prevents the issue of the shade window
staying visible in general. Still proposing this fix so that the scrim
visibility state (as seen by the shade) remains accurate.

This change introduces a new flag to control the bouncer transition fix
as it should not be rolled out without this fix as well.

Bug: 409720192
Bug: 434038809
Fixes: 434038809
Test: atest ScrimControllerTest
Flag: com.android.systemui.dream_bouncer_transition_fix
Change-Id: I8006c9f8aef139e6386f0cbadcf7eb6a78e0c584
parent f3af41ce
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1196,6 +1196,16 @@ flag {
  }
}

flag {
  name: "dream_bouncer_transition_fix"
  namespace: "systemui"
  description: "Flag for a minor transition fix when entering the dream with the bouncer open"
  bug: "409720192"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
  name: "lockscreen_shade_to_dream_transition_fix"
  namespace: "systemui"
+30 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;

import static com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER;
import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING;
import static com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB;
import static com.android.systemui.keyguard.shared.model.KeyguardState.GONE;
import static com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN;
@@ -339,8 +340,30 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
    };

    /**
     * Consumer used to fade the behind scrim when entering the dream from a lockscreen state. This
     * is done because the behind scrim is on top of the dream.
     * Consumer that dispatches the scrim state at the end of the primary bouncer to dream
     * transition. This triggers both when entering dream from lock screen with the bouncer open or
     * when closing the bouncer on top of the dream.
     *
     * This extra dispatch is needed as scrim transitions are not directly tied to keyguard
     * transitions and the scrim transition may end before the keyguard transition does. The last
     * dispatch of the scrim visibility happens when the scrim transition ends, meaning that if the
     * keyguard transition hasn't ended by then, the scrims aren't transparent yet as the bouncer to
     * dream keyguard transition directly controls the scrim alpha. This issue does not occur in
     * every shade configuration, but can cause the shade window to stay visible and steal touches
     * on top of the dream. See b/434038809.
     */
    Consumer<TransitionStep> mBouncerToDreamTransition = (TransitionStep step) -> {
        TransitionState state = step.getTransitionState();
        if (state == TransitionState.FINISHED || state == TransitionState.CANCELED) {
            dispatchScrimsVisible();
            dispatchBackScrimState(mScrimBehind.getViewAlpha());
        }
    };

    /**
     * Consumer used to fade the behind scrim when entering the dream from a lockscreen state or
     * when closing the primary bouncer from the dream. This is done because the behind scrim is on
     * top of the dream.
     */
    private final Consumer<ScrimAlpha> mDreamBehindScrimAlphaConsumer =
            (ScrimAlpha alphas) -> {
@@ -492,7 +515,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
                };

        // PRIMARY_BOUNCER->DREAMING
        if (Flags.dreamTransitionFixes()) {
        if (Flags.dreamBouncerTransitionFix()) {
            collectFlow(behindScrim, mKeyguardTransitionInteractor.transition(
                            Edge.Companion.create(PRIMARY_BOUNCER, Scenes.Dream),
                            Edge.Companion.create(PRIMARY_BOUNCER, DREAMING)),
                    mBouncerToDreamTransition, mMainDispatcher);
            collectFlow(behindScrim, mPrimaryBouncerToDreamingTransitionViewModel.getScrimAlpha(),
                    mDreamBehindScrimAlphaConsumer, mMainDispatcher);
        }
+36 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.animation.Animator;
import android.content.Context;
import android.graphics.Color;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.testing.TestableLooper;
import android.testing.ViewUtils;
import android.util.MathUtils;
@@ -832,6 +833,41 @@ public class ScrimControllerTest extends SysuiTestCase {
                mScrimBehind, TRANSPARENT));
    }

    @Test
    @EnableFlags(Flags.FLAG_DREAM_BOUNCER_TRANSITION_FIX)
    @DisableSceneContainer
    public void openBouncerOverDream() {
        mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
        mScrimController.legacyTransitionTo(ScrimState.DREAMING);

        // Open the bouncer.
        mScrimController.setRawPanelExpansionFraction(0f);
        when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true);
        mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_VISIBLE);
        finishAnimationsImmediately();

        // Only behind scrim is visible.
        assertScrimAlpha(Map.of(
                mScrimInFront, TRANSPARENT,
                mNotificationsScrim, TRANSPARENT,
                mScrimBehind, OPAQUE));
        assertScrimTint(mScrimBehind, mSurfaceColor);
        assertThat(mScrimVisibility).isEqualTo(OPAQUE);

        // Bouncer is closed.
        mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_HIDDEN);
        mScrimController.legacyTransitionTo(ScrimState.DREAMING);
        finishAnimationsImmediately();

        // All scrims are transparent.
        assertScrimAlpha(Map.of(
                mScrimInFront, TRANSPARENT,
                mNotificationsScrim, TRANSPARENT,
                mScrimBehind, TRANSPARENT));

        assertThat(mScrimVisibility).isEqualTo(TRANSPARENT);
    }

    @Test
    @DisableSceneContainer
    public void onThemeChange_bouncerBehindTint_isUpdatedToSurfaceColor() {