diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java index 07bd3a0567e6e..136935080824e 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java @@ -73,14 +73,19 @@ public class QuickStepContract { public static final int SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED = 1 << 9; // The search feature is disabled (either by SUW/SysUI/device policy) public static final int SYSUI_STATE_SEARCH_DISABLED = 1 << 10; - // The notification panel is expanded and interactive (either locked or unlocked), and the - // quick settings is not expanded + // The notification panel is expanded and interactive (either locked or unlocked), and quick + // settings is expanded. public static final int SYSUI_STATE_QUICK_SETTINGS_EXPANDED = 1 << 11; // Winscope tracing is enabled public static final int SYSUI_STATE_TRACING_ENABLED = 1 << 12; // The Assistant gesture should be constrained. It is up to the launcher implementation to // decide how to constrain it public static final int SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED = 1 << 13; + // The bubble stack is expanded. This means that the home gesture should be ignored, since a + // swipe up is an attempt to close the bubble stack, but that the back gesture should remain + // enabled (since it's used to navigate back within the bubbled app, or to collapse the bubble + // stack. + public static final int SYSUI_STATE_BUBBLES_EXPANDED = 1 << 14; @Retention(RetentionPolicy.SOURCE) @IntDef({SYSUI_STATE_SCREEN_PINNING, @@ -96,7 +101,8 @@ public class QuickStepContract { SYSUI_STATE_HOME_DISABLED, SYSUI_STATE_SEARCH_DISABLED, SYSUI_STATE_TRACING_ENABLED, - SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED + SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED, + SYSUI_STATE_BUBBLES_EXPANDED }) public @interface SystemUiStateFlags {} @@ -118,6 +124,7 @@ public class QuickStepContract { str.add((flags & SYSUI_STATE_TRACING_ENABLED) != 0 ? "tracing" : ""); str.add((flags & SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED) != 0 ? "asst_gesture_constrain" : ""); + str.add((flags & SYSUI_STATE_BUBBLES_EXPANDED) != 0 ? "bubbles_expanded" : ""); return str.toString(); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 31f90c6a86489..01c2faa624030 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -74,6 +74,7 @@ import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.bubbles.dagger.BubbleModule; import com.android.systemui.dump.DumpManager; +import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PinnedStackListenerForwarder; @@ -174,6 +175,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private final NotificationInterruptStateProvider mNotificationInterruptStateProvider; private IStatusBarService mBarService; + private SysUiState mSysUiState; // Used for determining view rect for touch interaction private Rect mTempRect = new Rect(); @@ -290,11 +292,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi NotifPipeline notifPipeline, FeatureFlags featureFlags, DumpManager dumpManager, - FloatingContentCoordinator floatingContentCoordinator) { + FloatingContentCoordinator floatingContentCoordinator, + SysUiState sysUiState) { this(context, notificationShadeWindowController, statusBarStateController, shadeController, data, null /* synchronizer */, configurationController, interruptionStateProvider, zenModeController, notifUserManager, groupManager, entryManager, - notifPipeline, featureFlags, dumpManager, floatingContentCoordinator); + notifPipeline, featureFlags, dumpManager, floatingContentCoordinator, sysUiState); } /** @@ -315,7 +318,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi NotifPipeline notifPipeline, FeatureFlags featureFlags, DumpManager dumpManager, - FloatingContentCoordinator floatingContentCoordinator) { + FloatingContentCoordinator floatingContentCoordinator, + SysUiState sysUiState) { dumpManager.registerDumpable(TAG, this); mContext = context; mShadeController = shadeController; @@ -340,6 +344,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi }); configurationController.addCallback(this /* configurationListener */); + mSysUiState = sysUiState; mBubbleData = data; mBubbleData.setListener(mBubbleDataListener); @@ -593,7 +598,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private void ensureStackViewCreated() { if (mStackView == null) { mStackView = new BubbleStackView( - mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator); + mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator, + mSysUiState); ViewGroup nsv = mNotificationShadeWindowController.getNotificationShadeView(); int bubbleScrimIndex = nsv.indexOfChild(nsv.findViewById(R.id.scrim_for_bubble)); int stackIndex = bubbleScrimIndex + 1; // Show stack above bubble scrim. diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 541c8cf19943b..7191a203ea8cc 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -80,6 +80,8 @@ import com.android.systemui.R; import com.android.systemui.bubbles.animation.ExpandedAnimationController; import com.android.systemui.bubbles.animation.PhysicsAnimationLayout; import com.android.systemui.bubbles.animation.StackAnimationController; +import com.android.systemui.model.SysUiState; +import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.util.DismissCircleView; import com.android.systemui.util.FloatingContentCoordinator; @@ -241,6 +243,7 @@ public class BubbleStackView extends FrameLayout { private BubbleTouchHandler mTouchHandler; private BubbleController.BubbleExpandListener mExpandListener; + private SysUiState mSysUiState; private boolean mViewUpdatedRequested = false; private boolean mIsExpansionAnimating = false; @@ -437,7 +440,8 @@ public class BubbleStackView extends FrameLayout { public BubbleStackView(Context context, BubbleData data, @Nullable SurfaceSynchronizer synchronizer, - FloatingContentCoordinator floatingContentCoordinator) { + FloatingContentCoordinator floatingContentCoordinator, + SysUiState sysUiState) { super(context); mBubbleData = data; @@ -445,6 +449,8 @@ public class BubbleStackView extends FrameLayout { mTouchHandler = new BubbleTouchHandler(this, data, context); setOnTouchListener(mTouchHandler); + mSysUiState = sysUiState; + Resources res = getResources(); mMaxBubbles = res.getInteger(R.integer.bubbles_max_rendered); mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size); @@ -1055,6 +1061,11 @@ public class BubbleStackView extends FrameLayout { if (shouldExpand == mIsExpanded) { return; } + + mSysUiState + .setFlag(QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED, shouldExpand) + .commitUpdate(mContext.getDisplayId()); + if (mIsExpanded) { animateCollapse(); logBubbleEvent(mExpandedBubble, SysUiStatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java index 27c9e9895324b..e84e932c9e61d 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java @@ -21,6 +21,7 @@ import android.content.Context; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.bubbles.BubbleData; import com.android.systemui.dump.DumpManager; +import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -62,7 +63,8 @@ public interface BubbleModule { NotifPipeline notifPipeline, FeatureFlags featureFlags, DumpManager dumpManager, - FloatingContentCoordinator floatingContentCoordinator) { + FloatingContentCoordinator floatingContentCoordinator, + SysUiState sysUiState) { return new BubbleController( context, notificationShadeWindowController, @@ -79,6 +81,7 @@ public interface BubbleModule { notifPipeline, featureFlags, dumpManager, - floatingContentCoordinator); + floatingContentCoordinator, + sysUiState); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index 6e612d7124ede..4f16031741bc1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -62,7 +62,9 @@ import com.android.systemui.SystemUIFactory; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dump.DumpManager; +import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationRemoveInterceptor; @@ -136,6 +138,9 @@ public class BubbleControllerTest extends SysuiTestCase { @Mock private FloatingContentCoordinator mFloatingContentCoordinator; + private SysUiState mSysUiState; + private boolean mSysUiStateBubblesExpanded; + @Captor private ArgumentCaptor mEntryListenerCaptor; @Captor @@ -229,6 +234,11 @@ public class BubbleControllerTest extends SysuiTestCase { mZenModeConfig.suppressedVisualEffects = 0; when(mZenModeController.getConfig()).thenReturn(mZenModeConfig); + mSysUiState = new SysUiState(); + mSysUiState.addCallback(sysUiFlags -> + mSysUiStateBubblesExpanded = + (sysUiFlags & QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED) != 0); + TestableNotificationInterruptStateProviderImpl interruptionStateProvider = new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(), mock(PowerManager.class), @@ -257,7 +267,8 @@ public class BubbleControllerTest extends SysuiTestCase { mNotifPipeline, mFeatureFlagsOldPipeline, mDumpManager, - mFloatingContentCoordinator); + mFloatingContentCoordinator, + mSysUiState); mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener); mBubbleController.setExpandListener(mBubbleExpandListener); @@ -277,6 +288,7 @@ public class BubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.hasBubbles()); verify(mBubbleStateChangeListener).onHasBubblesChanged(true); + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -284,6 +296,7 @@ public class BubbleControllerTest extends SysuiTestCase { assertFalse(mBubbleController.hasBubbles()); mBubbleController.updateBubble(mRow.getEntry()); assertTrue(mBubbleController.hasBubbles()); + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -300,6 +313,8 @@ public class BubbleControllerTest extends SysuiTestCase { assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey())); verify(mNotificationEntryManager, times(2)).updateNotifications(anyString()); verify(mBubbleStateChangeListener).onHasBubblesChanged(false); + + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -323,6 +338,8 @@ public class BubbleControllerTest extends SysuiTestCase { verify(mNotificationEntryManager, times(1)).performRemoveNotification( eq(mRow.getEntry().getSbn()), anyInt()); assertFalse(mBubbleController.hasBubbles()); + + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -340,6 +357,8 @@ public class BubbleControllerTest extends SysuiTestCase { verify(mNotificationEntryManager, times(3)).updateNotifications(any()); assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey())); assertNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().getKey())); + + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -363,6 +382,8 @@ public class BubbleControllerTest extends SysuiTestCase { verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey()); assertTrue(mNotificationShadeWindowController.getBubbleExpanded()); + assertTrue(mSysUiStateBubblesExpanded); + // Make sure the notif is suppressed assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade( mRow.getEntry())); @@ -372,6 +393,8 @@ public class BubbleControllerTest extends SysuiTestCase { verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey()); assertFalse(mBubbleController.isStackExpanded()); assertFalse(mNotificationShadeWindowController.getBubbleExpanded()); + + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -395,6 +418,8 @@ public class BubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.isStackExpanded()); verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey()); + assertTrue(mSysUiStateBubblesExpanded); + // Last added is the one that is expanded assertEquals(mRow2.getEntry(), mBubbleData.getSelectedBubble().getEntry()); assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade( @@ -416,6 +441,8 @@ public class BubbleControllerTest extends SysuiTestCase { // Collapse mBubbleController.collapseStack(); assertFalse(mBubbleController.isStackExpanded()); + + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -437,6 +464,8 @@ public class BubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.isStackExpanded()); verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey()); + assertTrue(mSysUiStateBubblesExpanded); + // Notif is suppressed after expansion assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade( mRow.getEntry())); @@ -463,6 +492,8 @@ public class BubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.isStackExpanded()); verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey()); + assertTrue(mSysUiStateBubblesExpanded); + // Notif is suppressed after expansion assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade( mRow.getEntry())); @@ -493,6 +524,8 @@ public class BubbleControllerTest extends SysuiTestCase { BubbleStackView stackView = mBubbleController.getStackView(); mBubbleController.expandStack(); + assertTrue(mSysUiStateBubblesExpanded); + assertTrue(mBubbleController.isStackExpanded()); verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey()); @@ -522,6 +555,8 @@ public class BubbleControllerTest extends SysuiTestCase { verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey()); verify(mBubbleStateChangeListener).onHasBubblesChanged(false); assertFalse(mBubbleController.hasBubbles()); + + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -541,6 +576,8 @@ public class BubbleControllerTest extends SysuiTestCase { // # of bubbles should change verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */); + + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -559,6 +596,8 @@ public class BubbleControllerTest extends SysuiTestCase { // # of bubbles should change verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */); + + assertTrue(mSysUiStateBubblesExpanded); } @Test @@ -579,6 +618,8 @@ public class BubbleControllerTest extends SysuiTestCase { // # of bubbles should change verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */); + + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -605,6 +646,8 @@ public class BubbleControllerTest extends SysuiTestCase { // # of bubbles should change verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */); + + assertFalse(mSysUiStateBubblesExpanded); } @Test @@ -619,6 +662,8 @@ public class BubbleControllerTest extends SysuiTestCase { mRow.getEntry().getKey(), mRow.getEntry(), REASON_APP_CANCEL); mBubbleController.expandStackAndSelectBubble(key); + + assertTrue(mSysUiStateBubblesExpanded); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java index 624464401a4a5..a31e3f8d7cc90 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java @@ -58,6 +58,7 @@ import com.android.systemui.SystemUIFactory; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dump.DumpManager; +import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -132,6 +133,9 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { private KeyguardBypassController mKeyguardBypassController; @Mock private FloatingContentCoordinator mFloatingContentCoordinator; + + private SysUiState mSysUiState = new SysUiState(); + @Captor private ArgumentCaptor mNotifListenerCaptor; private TestableBubbleController mBubbleController; @@ -242,7 +246,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { mNotifPipeline, mFeatureFlagsNewPipeline, mDumpManager, - mFloatingContentCoordinator); + mFloatingContentCoordinator, + mSysUiState); mBubbleController.addNotifCallback(mNotifCallback); mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener); mBubbleController.setExpandListener(mBubbleExpandListener); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java index d3d90c4084684..f4861028e81ae 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java @@ -19,6 +19,7 @@ package com.android.systemui.bubbles; import android.content.Context; import com.android.systemui.dump.DumpManager; +import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -52,12 +53,13 @@ public class TestableBubbleController extends BubbleController { NotifPipeline notifPipeline, FeatureFlags featureFlags, DumpManager dumpManager, - FloatingContentCoordinator floatingContentCoordinator) { + FloatingContentCoordinator floatingContentCoordinator, + SysUiState sysUiState) { super(context, notificationShadeWindowController, statusBarStateController, shadeController, data, Runnable::run, configurationController, interruptionStateProvider, zenModeController, lockscreenUserManager, groupManager, entryManager, - notifPipeline, featureFlags, dumpManager, floatingContentCoordinator); + notifPipeline, featureFlags, dumpManager, floatingContentCoordinator, sysUiState); setInflateSynchronously(true); } }