diff options
4 files changed, 115 insertions, 27 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 2c7c5cc91120..76925a7eceee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT; import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE; import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; +import static com.android.systemui.util.Utils.shouldUseSplitNotificationShade; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -83,6 +84,7 @@ import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DragDownHelper.DragDownCallback; import com.android.systemui.statusbar.EmptyShadeView; +import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; @@ -453,6 +455,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private NotificationEntry mTopHeadsUpEntry; private long mNumHeadsUp; private NotificationStackScrollLayoutController.TouchHandler mTouchHandler; + private final FeatureFlags mFeatureFlags; private final ExpandableView.OnHeightChangedListener mOnChildHeightChangedListener = new ExpandableView.OnHeightChangedListener() { @@ -492,8 +495,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable GroupMembershipManager groupMembershipManager, GroupExpansionManager groupExpansionManager, SysuiStatusBarStateController statusbarStateController, - AmbientState ambientState - ) { + AmbientState ambientState, + FeatureFlags featureFlags) { super(context, attrs, 0, 0); Resources res = getResources(); mSectionsManager = notificationSectionsManager; @@ -530,6 +533,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mGroupMembershipManager = groupMembershipManager; mGroupExpansionManager = groupExpansionManager; mStatusbarStateController = statusbarStateController; + mFeatureFlags = featureFlags; } void initializeForegroundServiceSection(ForegroundServiceDungeonView fgsSectionView) { @@ -1156,8 +1160,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (stackStartPosition <= stackEndPosition) { stackHeight = stackEndPosition; } else { - stackHeight = (int) NotificationUtils.interpolate(stackStartPosition, - stackEndPosition, mQsExpansionFraction); + if (shouldUseSplitNotificationShade(mFeatureFlags, getResources())) { + // This prevents notifications from being collapsed when QS is expanded. + stackHeight = (int) height; + } else { + stackHeight = (int) NotificationUtils.interpolate(stackStartPosition, + stackEndPosition, mQsExpansionFraction); + } } } else { stackHeight = (int) height; 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 0b3fd161d865..d179b9a8c275 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -196,7 +196,8 @@ public class NotificationPanelViewController extends PanelViewController { new MyOnHeadsUpChangedListener(); private final HeightListener mHeightListener = new HeightListener(); private final ConfigurationListener mConfigurationListener = new ConfigurationListener(); - private final StatusBarStateListener mStatusBarStateListener = new StatusBarStateListener(); + @VisibleForTesting final StatusBarStateListener mStatusBarStateListener = + new StatusBarStateListener(); private final ExpansionCallback mExpansionCallback = new ExpansionCallback(); private final BiometricUnlockController mBiometricUnlockController; private final NotificationPanelView mView; @@ -1852,7 +1853,7 @@ public class NotificationPanelViewController extends PanelViewController { } } - private void setQsExpanded(boolean expanded) { + @VisibleForTesting void setQsExpanded(boolean expanded) { boolean changed = mQsExpanded != expanded; if (changed) { mQsExpanded = expanded; @@ -1955,8 +1956,10 @@ public class NotificationPanelViewController extends PanelViewController { private void updateQsState() { mNotificationStackScrollLayoutController.setQsExpanded(mQsExpanded); mNotificationStackScrollLayoutController.setScrollingEnabled( - mBarState != KEYGUARD && (!mQsExpanded - || mQsExpansionFromOverscroll)); + mBarState != KEYGUARD + && (!mQsExpanded + || mQsExpansionFromOverscroll + || Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources))); if (mKeyguardUserSwitcherController != null && mQsExpanded && !mStackScrollerOverscrolling) { @@ -2236,13 +2239,16 @@ public class NotificationPanelViewController extends PanelViewController { @Override protected boolean canCollapsePanelOnTouch() { - if (!isInSettings()) { - return mBarState == KEYGUARD - || mIsPanelCollapseOnQQS - || mNotificationStackScrollLayoutController.isScrolledToBottom(); - } else { + if (!isInSettings() && mBarState == KEYGUARD) { + return true; + } + + if (mNotificationStackScrollLayoutController.isScrolledToBottom()) { return true; } + + return !Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources) + && (isInSettings() || mIsPanelCollapseOnQQS); } @Override @@ -3615,6 +3621,10 @@ public class NotificationPanelViewController extends PanelViewController { NotificationStackScrollLayout.OnOverscrollTopChangedListener { @Override public void onOverscrollTopChanged(float amount, boolean isRubberbanded) { + // When in split shade, overscroll shouldn't carry through to QS + if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { + return; + } cancelQsAnimation(); if (!mQsExpansionEnabled) { amount = 0f; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 461f64eda6e5..84fb3689b0b0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -21,6 +21,8 @@ import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE; +import static com.google.common.truth.Truth.assertWithMessage; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; @@ -49,6 +51,7 @@ import com.android.systemui.ExpandHelper; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.EmptyShadeView; +import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; @@ -101,6 +104,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private SysuiStatusBarStateController mStatusBarStateController; @Mock private NotificationSwipeHelper mNotificationSwipeHelper; @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController; + @Mock private FeatureFlags mFeatureFlags; @Before @UiThreadTest @@ -139,8 +143,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mGroupMembershipManger, mGroupExpansionManager, mStatusBarStateController, - mAmbientState - ); + mAmbientState, + mFeatureFlags); mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider, mNotificationSwipeHelper); mStackScroller = spy(mStackScrollerInternal); @@ -205,8 +209,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test @UiThreadTest public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() { - final float expectedHeight[] = {0f}; - final float expectedAppear[] = {0f}; + final float[] expectedHeight = {0f}; + final float[] expectedAppear = {0f}; mStackScroller.addOnExpandedHeightChangedListener((height, appear) -> { Assert.assertEquals(expectedHeight[0], height, 0); @@ -222,6 +226,29 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test + @UiThreadTest + public void testSetExpandedHeight_withSplitShade_doesntInterpolateStackHeight() { + when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); + final int[] expectedStackHeight = {0}; + + mStackScroller.addOnExpandedHeightChangedListener((expandedHeight, appear) -> { + assertWithMessage("Given shade enabled: %s", + mFeatureFlags.isTwoColumnNotificationShadeEnabled()) + .that(mStackScroller.getHeight()) + .isEqualTo(expectedStackHeight[0]); + }); + + when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false); + expectedStackHeight[0] = 0; + mStackScroller.setExpandedHeight(100f); + + when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); + expectedStackHeight[0] = 100; + mStackScroller.setExpandedHeight(100f); + } + + + @Test public void manageNotifications_visible() { FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index e788a1c0954b..b7d338c0e977 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -18,13 +18,15 @@ package com.android.systemui.statusbar.phone; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; +import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; +import static com.android.systemui.statusbar.StatusBarState.SHADE; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -45,6 +47,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewPropertyAnimator; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; @@ -53,6 +56,7 @@ import androidx.constraintlayout.widget.ConstraintSet; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.internal.util.LatencyTracker; import com.android.keyguard.KeyguardClockSwitch; @@ -100,7 +104,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; @@ -116,8 +119,6 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Mock private StatusBar mStatusBar; @Mock - private SysuiStatusBarStateController mStatusBarStateController; - @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout; @Mock private KeyguardBottomAreaView mKeyguardBottomArea; @@ -227,7 +228,10 @@ public class NotificationPanelViewTest extends SysuiTestCase { private AmbientState mAmbientState; @Mock private UserManager mUserManager; + @Mock + private UiEventLogger mUiEventLogger; + private SysuiStatusBarStateController mStatusBarStateController; private NotificationPanelViewController mNotificationPanelViewController; private View.AccessibilityDelegate mAccessibiltyDelegate; private NotificationsQuickSettingsContainer mNotificationContainerParent; @@ -235,6 +239,8 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Before public void setup() { MockitoAnnotations.initMocks(this); + mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger); + when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false); when(mHeadsUpCallback.getContext()).thenReturn(mContext); when(mView.getResources()).thenReturn(mResources); @@ -258,6 +264,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea); when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class)); when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class)); + when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class)); when(mView.findViewById(R.id.big_clock_container)).thenReturn(mBigClockContainer); when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame); when(mView.findViewById(R.id.keyguard_status_view)) @@ -336,17 +343,19 @@ public class NotificationPanelViewTest extends SysuiTestCase { ArgumentCaptor.forClass(View.AccessibilityDelegate.class); verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture()); mAccessibiltyDelegate = accessibilityDelegateArgumentCaptor.getValue(); + mNotificationPanelViewController.mStatusBarStateController + .addCallback(mNotificationPanelViewController.mStatusBarStateListener); + mNotificationPanelViewController + .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class)); } @Test public void testSetDozing_notifiesNsslAndStateController() { - mNotificationPanelViewController.setDozing(true /* dozing */, true /* animate */, + mNotificationPanelViewController.setDozing(true /* dozing */, false /* animate */, null /* touch */); - InOrder inOrder = inOrder( - mNotificationStackScrollLayoutController, mStatusBarStateController); - inOrder.verify(mNotificationStackScrollLayoutController) - .setDozing(eq(true), eq(true), eq(null)); - inOrder.verify(mStatusBarStateController).setDozeAmount(eq(1f), eq(true)); + verify(mNotificationStackScrollLayoutController) + .setDozing(eq(true), eq(false), eq(null)); + assertThat(mStatusBarStateController.getDozeAmount()).isEqualTo(1f); } @Test @@ -489,6 +498,39 @@ public class NotificationPanelViewTest extends SysuiTestCase { assertThat(stackScrollerLayout.startToStart).isEqualTo(R.id.qs_edge_guideline); } + @Test + public void testCanCollapsePanelOnTouch_trueForKeyGuard() { + mStatusBarStateController.setState(KEYGUARD); + + assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue(); + } + + @Test + public void testCanCollapsePanelOnTouch_trueWhenScrolledToBottom() { + mStatusBarStateController.setState(SHADE); + when(mNotificationStackScrollLayoutController.isScrolledToBottom()).thenReturn(true); + + assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue(); + } + + @Test + public void testCanCollapsePanelOnTouch_trueWhenInSettings() { + mStatusBarStateController.setState(SHADE); + mNotificationPanelViewController.setQsExpanded(true); + + assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue(); + } + + @Test + public void testCanCollapsePanelOnTouch_falseInDualPaneShade() { + mStatusBarStateController.setState(SHADE); + when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true); + when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); + mNotificationPanelViewController.setQsExpanded(true); + + assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isFalse(); + } + private View newViewWithId(int id) { View view = new View(mContext); view.setId(id); |