Adds SYSUI_STATE_BUBBLES_EXPANDED to QuickStepContract.

Also, modifies bubbles to update this value when bubbles are expanded or collapsed.

This will work in concert with the other CLs in this topic to collapse bubbles (but not the app behind it) when a swipe-to-home gesture occurs. It will not affect the behavior of the home button in three-button nav.

Test: atest SystemUITests
Bug: 146167884
Change-Id: I825afc7fa58c66e92a277bf94876c23917c412da
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 07bd3a0..1369350 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 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 @@
             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 @@
         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 c9ce8a1..7adeb56 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.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 @@
 
     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 @@
             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 @@
             NotifPipeline notifPipeline,
             FeatureFlags featureFlags,
             DumpManager dumpManager,
-            FloatingContentCoordinator floatingContentCoordinator) {
+            FloatingContentCoordinator floatingContentCoordinator,
+            SysUiState sysUiState) {
         dumpManager.registerDumpable(TAG, this);
         mContext = context;
         mShadeController = shadeController;
@@ -340,6 +344,7 @@
         });
 
         configurationController.addCallback(this /* configurationListener */);
+        mSysUiState = sysUiState;
 
         mBubbleData = data;
         mBubbleData.setListener(mBubbleDataListener);
@@ -593,7 +598,8 @@
     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 cff371f..0713881 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.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 @@
 
     private BubbleTouchHandler mTouchHandler;
     private BubbleController.BubbleExpandListener mExpandListener;
+    private SysUiState mSysUiState;
 
     private boolean mViewUpdatedRequested = false;
     private boolean mIsExpansionAnimating = false;
@@ -437,7 +440,8 @@
 
     public BubbleStackView(Context context, BubbleData data,
             @Nullable SurfaceSynchronizer synchronizer,
-            FloatingContentCoordinator floatingContentCoordinator) {
+            FloatingContentCoordinator floatingContentCoordinator,
+            SysUiState sysUiState) {
         super(context);
 
         mBubbleData = data;
@@ -445,6 +449,8 @@
         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);
@@ -1054,6 +1060,11 @@
         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 27c9e98..e84e932 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 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 @@
             NotifPipeline notifPipeline,
             FeatureFlags featureFlags,
             DumpManager dumpManager,
-            FloatingContentCoordinator floatingContentCoordinator) {
+            FloatingContentCoordinator floatingContentCoordinator,
+            SysUiState sysUiState) {
         return new BubbleController(
                 context,
                 notificationShadeWindowController,
@@ -79,6 +81,7 @@
                 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 6e612d7..4f16031 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.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 @@
     @Mock
     private FloatingContentCoordinator mFloatingContentCoordinator;
 
+    private SysUiState mSysUiState;
+    private boolean mSysUiStateBubblesExpanded;
+
     @Captor
     private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
     @Captor
@@ -229,6 +234,11 @@
         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 @@
                 mNotifPipeline,
                 mFeatureFlagsOldPipeline,
                 mDumpManager,
-                mFloatingContentCoordinator);
+                mFloatingContentCoordinator,
+                mSysUiState);
         mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener);
         mBubbleController.setExpandListener(mBubbleExpandListener);
 
@@ -277,6 +288,7 @@
         assertTrue(mBubbleController.hasBubbles());
 
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
+        assertFalse(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -284,6 +296,7 @@
         assertFalse(mBubbleController.hasBubbles());
         mBubbleController.updateBubble(mRow.getEntry());
         assertTrue(mBubbleController.hasBubbles());
+        assertFalse(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -300,6 +313,8 @@
         assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
         verify(mNotificationEntryManager, times(2)).updateNotifications(anyString());
         verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
+
+        assertFalse(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -323,6 +338,8 @@
         verify(mNotificationEntryManager, times(1)).performRemoveNotification(
                 eq(mRow.getEntry().getSbn()), anyInt());
         assertFalse(mBubbleController.hasBubbles());
+
+        assertFalse(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -340,6 +357,8 @@
         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 @@
         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 @@
         verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
         assertFalse(mBubbleController.isStackExpanded());
         assertFalse(mNotificationShadeWindowController.getBubbleExpanded());
+
+        assertFalse(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -395,6 +418,8 @@
         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 @@
         // Collapse
         mBubbleController.collapseStack();
         assertFalse(mBubbleController.isStackExpanded());
+
+        assertFalse(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -437,6 +464,8 @@
         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 @@
         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 @@
         BubbleStackView stackView = mBubbleController.getStackView();
         mBubbleController.expandStack();
 
+        assertTrue(mSysUiStateBubblesExpanded);
+
         assertTrue(mBubbleController.isStackExpanded());
         verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
 
@@ -522,6 +555,8 @@
         verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
         verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
         assertFalse(mBubbleController.hasBubbles());
+
+        assertFalse(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -541,6 +576,8 @@
 
         // # of bubbles should change
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
+
+        assertFalse(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -559,6 +596,8 @@
 
         // # of bubbles should change
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
+
+        assertTrue(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -579,6 +618,8 @@
 
         // # of bubbles should change
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
+
+        assertFalse(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -605,6 +646,8 @@
 
         // # of bubbles should change
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
+
+        assertFalse(mSysUiStateBubblesExpanded);
     }
 
     @Test
@@ -619,6 +662,8 @@
                 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 6244644..a31e3f8d 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.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 @@
     private KeyguardBypassController mKeyguardBypassController;
     @Mock
     private FloatingContentCoordinator mFloatingContentCoordinator;
+
+    private SysUiState mSysUiState = new SysUiState();
+
     @Captor
     private ArgumentCaptor<NotifCollectionListener> mNotifListenerCaptor;
     private TestableBubbleController mBubbleController;
@@ -242,7 +246,8 @@
                 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 d3d90c4..f486102 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 @@
 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 @@
             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);
     }
 }