From 6a7e3d36822226f02901cf68c262e21e66e0c2c0 Mon Sep 17 00:00:00 2001 From: Jordan Demeulenaere Date: Thu, 4 Mar 2021 14:27:09 +0100 Subject: [PATCH] Don't collapse the Shade when expanding a notification. This CL prevents the Shade from collapsing if a notification expansion animation is pending/running. It does so by: 1. Making sure that StatusBarNotificationActivityStarter#shouldCollapse is checked *after* ActivityLaunchAnimator#setLaunchResult is called. 2. Updating the clipped area of the parent of the notification that is expanding, if any. 3. Not moving the QS or the notification siblings while the animation is running. 4. Making sure that the notification is displayed above the QS. See b/181654098#comment4 for before/after videos. Bug: 181654098 Test: Manual; atest ActivityLaunchAnimatorTest ExpandableNotificationRowTest NotificationChildrenContainerTest NotificationStackScrollLayoutTest StatusBarNotificationActivityStarterTest Change-Id: I5a7beb4dc4883ed2757e286c4b480f83709680f7 --- .../row/ExpandableNotificationRow.java | 18 ++++++++------ .../stack/NotificationChildrenContainer.java | 5 ---- .../stack/StackScrollAlgorithm.java | 7 +----- .../NotificationPanelViewController.java | 24 +++++++++---------- .../NotificationsQuickSettingsContainer.java | 14 +++-------- .../StatusBarNotificationActivityStarter.java | 20 ++++++++++------ 6 files changed, 39 insertions(+), 49 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 0f23b770aacd3..c936369caa0ea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -2027,17 +2027,22 @@ public class ExpandableNotificationRow extends ActivatableNotificationView int top = params.getTop(); float interpolation = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(params.getProgress()); int startClipTopAmount = params.getStartClipTopAmount(); + int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, interpolation); if (mNotificationParent != null) { float parentY = mNotificationParent.getTranslationY(); top -= parentY; mNotificationParent.setTranslationZ(translationZ); + + // When the expanding notification is below its parent, the parent must be clipped + // exactly how it was clipped before the animation. When the expanding notification is + // on or above its parent (top <= 0), then the parent must be clipped exactly 'top' + // pixels to show the expanding notification, while still taking the decreasing + // notification clipTopAmount into consideration, so 'top + clipTopAmount'. int parentStartClipTopAmount = params.getParentStartClipTopAmount(); - if (startClipTopAmount != 0) { - int clipTopAmount = (int) MathUtils.lerp(parentStartClipTopAmount, - parentStartClipTopAmount - startClipTopAmount, - interpolation); - mNotificationParent.setClipTopAmount(clipTopAmount); - } + int parentClipTopAmount = Math.min(parentStartClipTopAmount, + top + clipTopAmount); + mNotificationParent.setClipTopAmount(parentClipTopAmount); + mNotificationParent.setExtraWidthForClipping(extraWidthForClipping); float clipBottom = Math.max(params.getBottom(), parentY + mNotificationParent.getActualHeight() @@ -2046,7 +2051,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView int minimumHeightForClipping = (int) (clipBottom - clipTop); mNotificationParent.setMinimumHeightForClipping(minimumHeightForClipping); } else if (startClipTopAmount != 0) { - int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, interpolation); setClipTopAmount(clipTopAmount); } setTranslationY(top); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java index d8ee102064e1b..2b194ba158168 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java @@ -34,7 +34,6 @@ import android.widget.RemoteViews; import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.widget.CachingIconView; import com.android.internal.widget.NotificationExpandButton; import com.android.systemui.R; import com.android.systemui.statusbar.CrossFadeHelper; @@ -638,10 +637,6 @@ public class NotificationChildrenContainer extends ViewGroup { childState.location = parentState.location; childState.inShelf = parentState.inShelf; yPosition += intrinsicHeight; - if (child.isExpandAnimationRunning()) { - launchTransitionCompensation = -ambientState.getExpandAnimationTopChange(); - } - } if (mOverflowNumber != null) { ExpandableNotificationRow overflowView = mAttachedChildren.get(Math.min( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 5d2203b57991a..d7a98bdf2715a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -28,14 +28,12 @@ import android.view.ViewGroup; import com.android.systemui.R; import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.NotificationShelf; -import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableView; import com.android.systemui.statusbar.notification.row.FooterView; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; /** @@ -156,7 +154,7 @@ public class StackScrollAlgorithm { private void updateClipping(StackScrollAlgorithmState algorithmState, AmbientState ambientState) { float drawStart = !ambientState.isOnKeyguard() ? ambientState.getTopPadding() - + ambientState.getStackTranslation() + ambientState.getExpandAnimationTopChange() + + ambientState.getStackTranslation() : 0; float clipStart = 0; int childCount = algorithmState.visibleChildren.size(); @@ -329,9 +327,6 @@ public class StackScrollAlgorithm { childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA; float inset = ambientState.getTopPadding() + ambientState.getStackTranslation() + ambientState.getSectionPadding(); - if (i <= algorithmState.getIndexOfExpandingNotification()) { - inset += ambientState.getExpandAnimationTopChange(); - } if (child.mustStayOnScreen() && childViewState.yTranslation >= 0) { // Even if we're not scrolled away we're in view and we're also not in the // shelf. We can relax the constraints and let us scroll off the top! 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 ae14fa943a4b2..fa579f9e79e0d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -439,7 +439,6 @@ public class NotificationPanelViewController extends PanelViewController { private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); private boolean mUserSetupComplete; private int mQsNotificationTopPadding; - private float mExpandOffset; private boolean mHideIconsDuringNotificationLaunch = true; private int mStackScrollerMeasuringPass; private ArrayList> @@ -2446,8 +2445,7 @@ public class NotificationPanelViewController extends PanelViewController { } startHeight = -mQs.getQsMinExpansionHeight(); } - float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount)) - + mExpandOffset; + float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount)); return Math.min(0, translation); } @@ -3187,16 +3185,16 @@ public class NotificationPanelViewController extends PanelViewController { } public void applyExpandAnimationParams(ExpandAnimationParameters params) { - mExpandOffset = params != null ? params.getTopChange() : 0; - updateQsExpansion(); - if (params != null) { - boolean hideIcons = params.getProgress( - ActivityLaunchAnimator.ANIMATION_DELAY_ICON_FADE_IN, 100) == 0.0f; - if (hideIcons != mHideIconsDuringNotificationLaunch) { - mHideIconsDuringNotificationLaunch = hideIcons; - if (!hideIcons) { - mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */); - } + if (params == null) { + return; + } + + boolean hideIcons = params.getProgress( + ActivityLaunchAnimator.ANIMATION_DELAY_ICON_FADE_IN, 100) == 0.0f; + if (hideIcons != mHideIconsDuringNotificationLaunch) { + mHideIconsDuringNotificationLaunch = hideIcons; + if (!hideIcons) { + mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java index 0c9ed661925c0..1cb0be0efc900 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java @@ -89,30 +89,22 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout @Override protected void dispatchDraw(Canvas canvas) { - // Invert the order of the scroll view and user switcher such that the notifications receive - // touches first but the panel gets drawn above. mDrawingOrderedChildren.clear(); mLayoutDrawingOrder.clear(); if (mKeyguardStatusBar.getVisibility() == View.VISIBLE) { mDrawingOrderedChildren.add(mKeyguardStatusBar); mLayoutDrawingOrder.add(mKeyguardStatusBar); } - if (mStackScroller.getVisibility() == View.VISIBLE) { - mDrawingOrderedChildren.add(mStackScroller); - mLayoutDrawingOrder.add(mStackScroller); - } if (mQsFrame.getVisibility() == View.VISIBLE) { mDrawingOrderedChildren.add(mQsFrame); mLayoutDrawingOrder.add(mQsFrame); } - - if (mHasViewsAboveShelf) { - // StackScroller needs to be on top - mDrawingOrderedChildren.remove(mStackScroller); + if (mStackScroller.getVisibility() == View.VISIBLE) { mDrawingOrderedChildren.add(mStackScroller); + mLayoutDrawingOrder.add(mStackScroller); } - // Let's now find the order that the view has when drawing regulary by sorting + // Let's now find the order that the view has when drawing regularly by sorting mLayoutDrawingOrder.sort(mIndexComparator); super.dispatchDraw(canvas); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index 34673f2503ce5..801ac964777b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -356,9 +356,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit if (isActivityIntent || canBubble) { mAssistManagerLazy.get().hideAssist(); } - if (shouldCollapse()) { - collapseOnMainThread(); - } NotificationVisibility.NotificationLocation location = NotificationLogger.getNotificationLocation(entry); @@ -408,6 +405,12 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mMainThreadHandler.post( () -> mBubblesManagerOptional.get().expandStackAndSelectBubble(entry)); } + + // expandStackAndSelectBubble won't affect shouldCollapse, so we can collapse directly even + // if we are not on the main thread. + if (shouldCollapse()) { + collapseOnMainThread(); + } } private void startNotificationIntent( @@ -438,6 +441,9 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit null, null, options); mMainThreadHandler.post(() -> { mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent); + if (shouldCollapse()) { + collapseOnMainThread(); + } }); } catch (RemoteException | PendingIntent.CanceledException e) { // the stack trace isn't very helpful here. @@ -465,11 +471,11 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */); removeHUN(row); + if (shouldCollapse()) { + mCommandQueue.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, + true /* force */); + } }); - if (shouldCollapse()) { - mMainThreadHandler.post(() -> mCommandQueue.animateCollapsePanels( - CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */)); - } }); return true; }, null, false /* afterKeyguardGone */);