From 4c57c3d6c8450ffb89300556a300a11428dd4f38 Mon Sep 17 00:00:00 2001 From: Michal Brzezinski Date: Wed, 28 Dec 2022 14:24:40 +0100 Subject: [PATCH] Refreshing state in QS with upcoming state of KEYGUARD Transition to AOD was glitchy because many/all parts of QS were not aware we're transitioning to keyguard already (upcoming state) even though current state of StatusBarState still might not be there. This prevents QS becoming visible for a moment and then quickly disappearing when StatusBarState catches up with the upcoming state. Fixes: 258219778 Test: On large screen portrait, enable AOD and from unlocked state press power button. QS tiles should not be visible at any point. Change-Id: I0187f7bf0ee329d8f1ef7bb02bbcc5c69f14ec2a --- .../com/android/systemui/qs/QSFragment.java | 38 +++++++++++++------ .../android/systemui/qs/QSFragmentTest.java | 18 +++++++-- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 893574a59d948..da18b5734e811 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -19,7 +19,8 @@ import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS; import static com.android.systemui.media.dagger.MediaModule.QS_PANEL; import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL; import static com.android.systemui.statusbar.disableflags.DisableFlagsLogger.DisableState; - +import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; +import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.res.Configuration; @@ -124,7 +125,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca * we're on keyguard but use {@link #isKeyguardState()} instead since that is more accurate * during state transitions which often call into us. */ - private int mState; + private int mStatusBarState = -1; private QSContainerImplController mQSContainerImplController; private int[] mTmpLocation = new int[2]; private int mLastViewHeight; @@ -457,7 +458,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca private boolean isKeyguardState() { // We want the freshest state here since otherwise we'll have some weirdness if earlier // listeners trigger updates - return mStatusBarStateController.getState() == StatusBarState.KEYGUARD; + return mStatusBarStateController.getCurrentOrUpcomingState() == KEYGUARD; } private void updateShowCollapsedOnKeyguard() { @@ -672,8 +673,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca mQSAnimator.setPosition(expansion); } if (!mInSplitShade - || mStatusBarStateController.getState() == StatusBarState.KEYGUARD - || mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) { + || mStatusBarStateController.getState() == KEYGUARD + || mStatusBarStateController.getState() == SHADE_LOCKED) { // At beginning, state is 0 and will apply wrong squishiness to MediaHost in lockscreen // and media player expect no change by squishiness in lock screen shade. Don't bother // squishing mQsMediaHost when not in split shade to prevent problems with stale state. @@ -703,8 +704,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca // Large screens in landscape. // Need to check upcoming state as for unlocked -> AOD transition current state is // not updated yet, but we're transitioning and UI should already follow KEYGUARD state - if (mTransitioningToFullShade || mStatusBarStateController.getCurrentOrUpcomingState() - == StatusBarState.KEYGUARD) { + if (mTransitioningToFullShade + || mStatusBarStateController.getCurrentOrUpcomingState() == KEYGUARD) { // Always use "mFullShadeProgress" on keyguard, because // "panelExpansionFractions" is always 1 on keyguard split shade. return mLockscreenToShadeProgress; @@ -757,8 +758,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } private boolean headerWillBeAnimating() { - return mState == StatusBarState.KEYGUARD && mShowCollapsedOnKeyguard - && !isKeyguardState(); + return mStatusBarState == KEYGUARD && mShowCollapsedOnKeyguard && !isKeyguardState(); } @Override @@ -890,10 +890,24 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } }; + @Override + public void onUpcomingStateChanged(int upcomingState) { + if (upcomingState == KEYGUARD) { + // refresh state of QS as soon as possible - while it's still upcoming - so in case of + // transition to KEYGUARD (e.g. from unlocked to AOD) all objects are aware they should + // already behave like on keyguard. Otherwise we might be doing extra work, + // e.g. QSAnimator making QS visible and then quickly invisible + onStateChanged(upcomingState); + } + } + @Override public void onStateChanged(int newState) { - mState = newState; - setKeyguardShowing(newState == StatusBarState.KEYGUARD); + if (newState == mStatusBarState) { + return; + } + mStatusBarState = newState; + setKeyguardShowing(newState == KEYGUARD); updateShowCollapsedOnKeyguard(); } @@ -921,7 +935,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca indentingPw.println("mTemp: " + Arrays.toString(mLocationTemp)); indentingPw.println("mShowCollapsedOnKeyguard: " + mShowCollapsedOnKeyguard); indentingPw.println("mLastKeyguardAndExpanded: " + mLastKeyguardAndExpanded); - indentingPw.println("mState: " + StatusBarState.toString(mState)); + indentingPw.println("mStatusBarState: " + StatusBarState.toString(mStatusBarState)); indentingPw.println("mTmpLocation: " + Arrays.toString(mTmpLocation)); indentingPw.println("mLastViewHeight: " + mLastViewHeight); indentingPw.println("mLastHeaderTranslation: " + mLastHeaderTranslation); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java index ffe918d36d6f6..42ef9c2914cea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java @@ -151,7 +151,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { @Test public void transitionToFullShade_setsAlphaUsingShadeInterpolator() { QSFragment fragment = resumeAndGetFragment(); - setStatusBarState(StatusBarState.SHADE); + setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE); boolean isTransitioningToFullShade = true; float transitionProgress = 0.5f; float squishinessFraction = 0.5f; @@ -167,7 +167,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { public void transitionToFullShade_onKeyguard_noBouncer_setsAlphaUsingLinearInterpolator() { QSFragment fragment = resumeAndGetFragment(); - setStatusBarState(KEYGUARD); + setStatusBarCurrentAndUpcomingState(KEYGUARD); when(mQSPanelController.isBouncerInTransit()).thenReturn(false); boolean isTransitioningToFullShade = true; float transitionProgress = 0.5f; @@ -183,7 +183,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { public void transitionToFullShade_onKeyguard_bouncerActive_setsAlphaUsingBouncerInterpolator() { QSFragment fragment = resumeAndGetFragment(); - setStatusBarState(KEYGUARD); + setStatusBarCurrentAndUpcomingState(KEYGUARD); when(mQSPanelController.isBouncerInTransit()).thenReturn(true); boolean isTransitioningToFullShade = true; float transitionProgress = 0.5f; @@ -482,6 +482,15 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { assertEquals(175, mediaHostClip.bottom); } + @Test + public void testQsUpdatesQsAnimatorWithUpcomingState() { + QSFragment fragment = resumeAndGetFragment(); + setStatusBarCurrentAndUpcomingState(SHADE); + fragment.onUpcomingStateChanged(KEYGUARD); + + verify(mQSAnimator).setOnKeyguard(true); + } + @Override protected Fragment instantiate(Context context, String className, Bundle arguments) { MockitoAnnotations.initMocks(this); @@ -591,8 +600,9 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { return getFragment(); } - private void setStatusBarState(int statusBarState) { + private void setStatusBarCurrentAndUpcomingState(int statusBarState) { when(mStatusBarStateController.getState()).thenReturn(statusBarState); + when(mStatusBarStateController.getCurrentOrUpcomingState()).thenReturn(statusBarState); getFragment().onStateChanged(statusBarState); }