From 5f550c269c10622fa79f02b6e4194e89d55a7dab Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Tue, 8 Jun 2021 15:50:59 +0100 Subject: [PATCH] Update scrims when changing quick settings clip, fix clipping bounds in split shade Fixes two issues with scrims background: 1) Scrims become transparent on pin code bouncer when rotating from split shade to non-split shade mode This happens because we update mClipQsScrim in ScrimState enum, but we don't actually re-apply alpha values and tints to the scrim views/drawables. We applied these values only when current ScrimState has changed (see transitionTo method). When we rotate the device when we are on pin code bouncer the state remains the same (BOUNCER), so we didn't apply these values. Updated the code to set alpha values and tints when setClipsQsScrim is called (it invokes applyAndDispatchState which invokes applyState). 2) Background becomes black when we open pin code bouncer when using non-split shade mode and rotate the device to split shade mode It happened because in NotificationPanelViewController.setQSClippingBounds the clipping bounds are initialized with zeros and we didn't update them in case when we use split notification shade and qsPanelBottomY <= 0 (when quick settings are not visible). Empty bounds caused absence of the notifications scrim which should act as bouncer background. Fixed by using non-split shade logic for calculating bounds in this case, they cover the entire screen. Fixes: 188112748 Test: atest com.android.systemui.statusbar.phone.ScrimControllerTest Test: manual https://drive.google.com/drive/folders/1SRSzT0uQ-mETIVI87Ilr3dxlaUdcG9Go?usp=sharing Change-Id: I783b2d4f4335447f7abfb210005aa09bfd3e15a8 --- .../NotificationPanelViewController.java | 21 ++++----- .../statusbar/phone/ScrimController.java | 38 ++++++++-------- .../statusbar/phone/ScrimControllerTest.java | 43 +++++++++++++++++++ 3 files changed, 75 insertions(+), 27 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index a8b7b0c30d096..bb819668ef47d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -2224,10 +2224,16 @@ public class NotificationPanelViewController extends PanelViewController { int right = 0; final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction()); - final boolean visible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0) - && !mShouldUseSplitNotificationShade; + final boolean quickSettingsVisible = computeQsExpansionFraction() > 0 || qsPanelBottomY > 0; - if (!mShouldUseSplitNotificationShade) { + if (mShouldUseSplitNotificationShade && quickSettingsVisible) { + mAmbientState.setNotificationScrimTop(mSplitShadeNotificationsTopPadding); + + top = Math.max(0, Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding)); + bottom = mNotificationStackScrollLayoutController.getHeight(); + left = mNotificationStackScrollLayoutController.getLeft(); + right = mNotificationStackScrollLayoutController.getRight(); + } else { if (mTransitioningToFullShadeProgress > 0.0f) { // If we're transitioning, let's use the actual value. The else case // can be wrong during transitions when waiting for the keyguard to unlock @@ -2242,16 +2248,11 @@ public class NotificationPanelViewController extends PanelViewController { // notification bounds should take full screen width regardless of insets left = 0; right = getView().getRight() + mDisplayRightInset; - } else if (qsPanelBottomY > 0) { // so bounds are empty on lockscreen - mAmbientState.setNotificationScrimTop(mSplitShadeNotificationsTopPadding); - top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding); - bottom = mNotificationStackScrollLayoutController.getHeight(); - left = mNotificationStackScrollLayoutController.getLeft(); - right = mNotificationStackScrollLayoutController.getRight(); } // top should never be lower than bottom, otherwise it will be invisible. top = Math.min(top, bottom); - applyQSClippingBounds(left, top, right, bottom, visible); + applyQSClippingBounds(left, top, right, bottom, + quickSettingsVisible && !mShouldUseSplitNotificationShade); } private void applyQSClippingBounds(int left, int top, int right, int bottom, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 1331829201b8f..26a39a54460b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -359,21 +359,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump mAnimateChange = state.getAnimateChange(); mAnimationDuration = state.getAnimationDuration(); - mInFrontTint = state.getFrontTint(); - mBehindTint = state.getBehindTint(); - mNotificationsTint = state.getNotifTint(); - mBubbleTint = state.getBubbleTint(); - - mInFrontAlpha = state.getFrontAlpha(); - mBehindAlpha = state.getBehindAlpha(); - mBubbleAlpha = state.getBubbleAlpha(); - mNotificationsAlpha = state.getNotifAlpha(); - if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha) || isNaN(mNotificationsAlpha)) { - throw new IllegalStateException("Scrim opacity is NaN for state: " + state + ", front: " - + mInFrontAlpha + ", back: " + mBehindAlpha + ", notif: " - + mNotificationsAlpha); - } - applyStateToAlpha(); + applyState(); // Scrim might acquire focus when user is navigating with a D-pad or a keyboard. // We need to disable focus otherwise AOD would end up with a gray overlay. @@ -637,7 +623,19 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump } } - private void applyStateToAlpha() { + private void applyState() { + mInFrontTint = mState.getFrontTint(); + mBehindTint = mState.getBehindTint(); + mNotificationsTint = mState.getNotifTint(); + mBubbleTint = mState.getBubbleTint(); + + mInFrontAlpha = mState.getFrontAlpha(); + mBehindAlpha = mState.getBehindAlpha(); + mBubbleAlpha = mState.getBubbleAlpha(); + mNotificationsAlpha = mState.getNotifAlpha(); + + assertAlphasValid(); + if (!mExpansionAffectsAlpha) { return; } @@ -701,6 +699,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump mBehindTint = behindTint; } } + + assertAlphasValid(); + } + + private void assertAlphasValid() { if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha) || isNaN(mNotificationsAlpha)) { throw new IllegalStateException("Scrim opacity is NaN for state: " + mState + ", front: " + mInFrontAlpha + ", back: " + mBehindAlpha + ", notif: " @@ -740,7 +743,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump private void applyAndDispatchState() { - applyStateToAlpha(); + applyState(); if (mUpdatePending) { return; } @@ -1209,6 +1212,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump pw.println(" ScrimController: "); pw.print(" state: "); pw.println(mState); + pw.println(" mClipQsScrim = " + mState.mClipQsScrim); pw.print(" frontScrim:"); pw.print(" viewAlpha="); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index e55361e750b1d..30059a9190407 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -555,6 +555,49 @@ public class ScrimControllerTest extends SysuiTestCase { )); } + @Test + public void disableClipQsScrimWithoutStateTransition_updatesTintAndAlpha() { + mScrimController.setClipsQsScrim(true); + mScrimController.transitionTo(ScrimState.BOUNCER); + + mScrimController.setClipsQsScrim(false); + + finishAnimationsImmediately(); + // Front scrim should be transparent + // Back scrim should be visible without tint + assertScrimAlpha(Map.of( + mScrimInFront, TRANSPARENT, + mNotificationsScrim, TRANSPARENT, + mScrimBehind, OPAQUE)); + assertScrimTinted(Map.of( + mScrimInFront, false, + mScrimBehind, false, + mNotificationsScrim, false + )); + } + + @Test + public void enableClipQsScrimWithoutStateTransition_updatesTintAndAlpha() { + mScrimController.setClipsQsScrim(false); + mScrimController.transitionTo(ScrimState.BOUNCER); + + mScrimController.setClipsQsScrim(true); + + finishAnimationsImmediately(); + // Front scrim should be transparent + // Back scrim should be clipping QS + // Notif scrim should be visible without tint + assertScrimAlpha(Map.of( + mScrimInFront, TRANSPARENT, + mNotificationsScrim, OPAQUE, + mScrimBehind, OPAQUE)); + assertScrimTinted(Map.of( + mScrimInFront, false, + mScrimBehind, true, + mNotificationsScrim, false + )); + } + @Test public void transitionToBouncer() { mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);