Allow Bubble overflow to be opened without other active bubbles
Currently you can only access the overflow if you have bubbles in
the stack. There are a bunch of explorations that show accessing
the overflow without the stack (e.g. from taskbar, from people area).
- BubbleData holds onto BubbleOverflow now
- When last bubble is removed, if showing in taskbar/already expanded
& has overflow bubbs, select the overflow.
- No longer null out BubbleStackView when no more bubbles, this
allows overflow to continue to show
- Added tests for overflow behaviour in BubblesTest
Test: atest SystemUITests
Test: manua 1) - produce a bunch of bubbles
- expand the stack, dismiss each bubble
=> when you dismiss the last one, overflow selected
- collapse the stack
=> overflow goes away
2) - have taskbar cl / prototype
- have bubbles in the overflow but no active bubbles
=> observe that taskbar shows the overflow (i.e. sysui
renders the stack in that spot)
Bug: 171322463
Bug: 167413172
Change-Id: I36b9cedc492ace59105dba58c89f9ef92ff4b9e8
This commit is contained in:
@@ -171,7 +171,7 @@ public class BubbleController implements Bubbles {
|
||||
ShellTaskOrganizer organizer) {
|
||||
BubbleLogger logger = new BubbleLogger(uiEventLogger);
|
||||
BubblePositioner positioner = new BubblePositioner(context, windowManager);
|
||||
BubbleData data = new BubbleData(context, logger);
|
||||
BubbleData data = new BubbleData(context, logger, positioner);
|
||||
return new BubbleController(context, data, synchronizer, floatingContentCoordinator,
|
||||
new BubbleDataRepository(context, launcherApps),
|
||||
statusBarService, windowManager, windowManagerShellWrapper, launcherApps,
|
||||
@@ -382,7 +382,6 @@ public class BubbleController implements Bubbles {
|
||||
if (mStackView == null) {
|
||||
mStackView = new BubbleStackView(
|
||||
mContext, this, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator);
|
||||
mStackView.addView(mBubbleScrim);
|
||||
mStackView.onOrientationChanged();
|
||||
if (mExpandListener != null) {
|
||||
mStackView.setExpandListener(mExpandListener);
|
||||
@@ -422,6 +421,8 @@ public class BubbleController implements Bubbles {
|
||||
|
||||
try {
|
||||
mAddedToWindowManager = true;
|
||||
mBubbleData.getOverflow().initialize(this);
|
||||
mStackView.addView(mBubbleScrim);
|
||||
mWindowManager.addView(mStackView, mWmLayoutParams);
|
||||
// Position info is dependent on us being attached to a window
|
||||
mBubblePositioner.update(mOrientation);
|
||||
@@ -446,7 +447,7 @@ public class BubbleController implements Bubbles {
|
||||
if (mStackView != null) {
|
||||
mWindowManager.removeView(mStackView);
|
||||
mStackView.removeView(mBubbleScrim);
|
||||
mStackView = null;
|
||||
mBubbleData.getOverflow().cleanUpExpandedState();
|
||||
} else {
|
||||
Log.w(TAG, "StackView added to WindowManager, but was null when removing!");
|
||||
}
|
||||
@@ -578,7 +579,7 @@ public class BubbleController implements Bubbles {
|
||||
if (mStackView == null) {
|
||||
return false;
|
||||
}
|
||||
return mBubbleData.hasBubbles();
|
||||
return mBubbleData.hasBubbles() || mBubbleData.isShowingOverflow();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -69,7 +69,7 @@ public class BubbleData {
|
||||
boolean selectionChanged;
|
||||
boolean orderChanged;
|
||||
boolean expanded;
|
||||
@Nullable Bubble selectedBubble;
|
||||
@Nullable BubbleViewProvider selectedBubble;
|
||||
@Nullable Bubble addedBubble;
|
||||
@Nullable Bubble updatedBubble;
|
||||
@Nullable Bubble addedOverflowBubble;
|
||||
@@ -116,13 +116,15 @@ public class BubbleData {
|
||||
}
|
||||
|
||||
private final Context mContext;
|
||||
private final BubblePositioner mPositioner;
|
||||
/** Bubbles that are actively in the stack. */
|
||||
private final List<Bubble> mBubbles;
|
||||
/** Bubbles that aged out to overflow. */
|
||||
private final List<Bubble> mOverflowBubbles;
|
||||
/** Bubbles that are being loaded but haven't been added to the stack just yet. */
|
||||
private final HashMap<String, Bubble> mPendingBubbles;
|
||||
private Bubble mSelectedBubble;
|
||||
private BubbleViewProvider mSelectedBubble;
|
||||
private final BubbleOverflow mOverflow;
|
||||
private boolean mShowingOverflow;
|
||||
private boolean mExpanded;
|
||||
private final int mMaxBubbles;
|
||||
@@ -153,9 +155,11 @@ public class BubbleData {
|
||||
*/
|
||||
private HashMap<String, String> mSuppressedGroupKeys = new HashMap<>();
|
||||
|
||||
public BubbleData(Context context, BubbleLogger bubbleLogger) {
|
||||
public BubbleData(Context context, BubbleLogger bubbleLogger, BubblePositioner positioner) {
|
||||
mContext = context;
|
||||
mLogger = bubbleLogger;
|
||||
mPositioner = positioner;
|
||||
mOverflow = new BubbleOverflow(context, positioner);
|
||||
mBubbles = new ArrayList<>();
|
||||
mOverflowBubbles = new ArrayList<>();
|
||||
mPendingBubbles = new HashMap<>();
|
||||
@@ -178,6 +182,10 @@ public class BubbleData {
|
||||
return !mBubbles.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasOverflowBubbles() {
|
||||
return !mOverflowBubbles.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isExpanded() {
|
||||
return mExpanded;
|
||||
}
|
||||
@@ -195,10 +203,14 @@ public class BubbleData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Bubble getSelectedBubble() {
|
||||
public BubbleViewProvider getSelectedBubble() {
|
||||
return mSelectedBubble;
|
||||
}
|
||||
|
||||
public BubbleOverflow getOverflow() {
|
||||
return mOverflow;
|
||||
}
|
||||
|
||||
/** Return a read-only current active bubble lists. */
|
||||
public List<Bubble> getActiveBubbles() {
|
||||
return Collections.unmodifiableList(mBubbles);
|
||||
@@ -212,7 +224,7 @@ public class BubbleData {
|
||||
dispatchPendingChanges();
|
||||
}
|
||||
|
||||
public void setSelectedBubble(Bubble bubble) {
|
||||
public void setSelectedBubble(BubbleViewProvider bubble) {
|
||||
if (DEBUG_BUBBLE_DATA) {
|
||||
Log.d(TAG, "setSelectedBubble: " + bubble);
|
||||
}
|
||||
@@ -224,6 +236,10 @@ public class BubbleData {
|
||||
mShowingOverflow = showingOverflow;
|
||||
}
|
||||
|
||||
boolean isShowingOverflow() {
|
||||
return mShowingOverflow && (isExpanded() || mPositioner.showingInTaskbar());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new bubble or returns an existing one. Does not add new bubbles to
|
||||
* bubble data, must go through {@link #notificationEntryUpdated(Bubble, boolean, boolean)}
|
||||
@@ -264,8 +280,8 @@ public class BubbleData {
|
||||
|
||||
/**
|
||||
* When this method is called it is expected that all info in the bubble has completed loading.
|
||||
* @see Bubble#inflate(BubbleViewInfoTask.Callback, Context,
|
||||
* BubbleStackView, BubbleIconFactory, boolean).
|
||||
* @see Bubble#inflate(BubbleViewInfoTask.Callback, Context, BubbleController, BubbleStackView,
|
||||
* BubbleIconFactory, boolean)
|
||||
*/
|
||||
void notificationEntryUpdated(Bubble bubble, boolean suppressFlyout, boolean showInShade) {
|
||||
if (DEBUG_BUBBLE_DATA) {
|
||||
@@ -484,10 +500,17 @@ public class BubbleData {
|
||||
Bubble bubbleToRemove = mBubbles.get(indexToRemove);
|
||||
bubbleToRemove.stopInflation();
|
||||
if (mBubbles.size() == 1) {
|
||||
// Going to become empty, handle specially.
|
||||
setExpandedInternal(false);
|
||||
// Don't use setSelectedBubbleInternal because we don't want to trigger an applyUpdate
|
||||
mSelectedBubble = null;
|
||||
if (hasOverflowBubbles() && (mPositioner.showingInTaskbar() || isExpanded())) {
|
||||
// No more active bubbles but we have stuff in the overflow -- select that view
|
||||
// if we're already expanded or always showing.
|
||||
setShowingOverflow(true);
|
||||
setSelectedBubbleInternal(mOverflow);
|
||||
} else {
|
||||
setExpandedInternal(false);
|
||||
// Don't use setSelectedBubbleInternal because we don't want to trigger an
|
||||
// applyUpdate
|
||||
mSelectedBubble = null;
|
||||
}
|
||||
}
|
||||
if (indexToRemove < mBubbles.size() - 1) {
|
||||
// Removing anything but the last bubble means positions will change.
|
||||
@@ -505,7 +528,7 @@ public class BubbleData {
|
||||
if (Objects.equals(mSelectedBubble, bubbleToRemove)) {
|
||||
// Move selection to the new bubble at the same position.
|
||||
int newIndex = Math.min(indexToRemove, mBubbles.size() - 1);
|
||||
Bubble newSelected = mBubbles.get(newIndex);
|
||||
BubbleViewProvider newSelected = mBubbles.get(newIndex);
|
||||
setSelectedBubbleInternal(newSelected);
|
||||
}
|
||||
maybeSendDeleteIntent(reason, bubbleToRemove);
|
||||
@@ -564,7 +587,7 @@ public class BubbleData {
|
||||
*
|
||||
* @param bubble the new selected bubble
|
||||
*/
|
||||
private void setSelectedBubbleInternal(@Nullable Bubble bubble) {
|
||||
private void setSelectedBubbleInternal(@Nullable BubbleViewProvider bubble) {
|
||||
if (DEBUG_BUBBLE_DATA) {
|
||||
Log.d(TAG, "setSelectedBubbleInternal: " + bubble);
|
||||
}
|
||||
@@ -572,14 +595,17 @@ public class BubbleData {
|
||||
return;
|
||||
}
|
||||
// Otherwise, if we are showing the overflow menu, return to the previously selected bubble.
|
||||
|
||||
if (bubble != null && !mBubbles.contains(bubble) && !mOverflowBubbles.contains(bubble)) {
|
||||
boolean isOverflow = bubble != null && BubbleOverflow.KEY.equals(bubble.getKey());
|
||||
if (bubble != null
|
||||
&& !mBubbles.contains(bubble)
|
||||
&& !mOverflowBubbles.contains(bubble)
|
||||
&& !isOverflow) {
|
||||
Log.e(TAG, "Cannot select bubble which doesn't exist!"
|
||||
+ " (" + bubble + ") bubbles=" + mBubbles);
|
||||
return;
|
||||
}
|
||||
if (mExpanded && bubble != null) {
|
||||
bubble.markAsAccessedAt(mTimeSource.currentTimeMillis());
|
||||
if (mExpanded && bubble != null && !isOverflow) {
|
||||
((Bubble) bubble).markAsAccessedAt(mTimeSource.currentTimeMillis());
|
||||
}
|
||||
mSelectedBubble = bubble;
|
||||
mStateChange.selectedBubble = bubble;
|
||||
@@ -629,7 +655,7 @@ public class BubbleData {
|
||||
return;
|
||||
}
|
||||
if (shouldExpand) {
|
||||
if (mBubbles.isEmpty()) {
|
||||
if (mBubbles.isEmpty() && !mShowingOverflow) {
|
||||
Log.e(TAG, "Attempt to expand stack when empty!");
|
||||
return;
|
||||
}
|
||||
@@ -637,7 +663,9 @@ public class BubbleData {
|
||||
Log.e(TAG, "Attempt to expand stack without selected bubble!");
|
||||
return;
|
||||
}
|
||||
mSelectedBubble.markAsAccessedAt(mTimeSource.currentTimeMillis());
|
||||
if (mSelectedBubble instanceof Bubble) {
|
||||
((Bubble) mSelectedBubble).markAsAccessedAt(mTimeSource.currentTimeMillis());
|
||||
}
|
||||
mStateChange.orderChanged |= repackAll();
|
||||
} else if (!mBubbles.isEmpty()) {
|
||||
// Apply ordering and grouping rules from expanded -> collapsed, then save
|
||||
@@ -647,14 +675,18 @@ public class BubbleData {
|
||||
|
||||
if (mShowingOverflow) {
|
||||
// Show previously selected bubble instead of overflow menu on next expansion.
|
||||
setSelectedBubbleInternal(mSelectedBubble);
|
||||
if (!mSelectedBubble.getKey().equals(mOverflow.getKey())) {
|
||||
setSelectedBubbleInternal(mSelectedBubble);
|
||||
} else {
|
||||
setSelectedBubbleInternal(mBubbles.get(0));
|
||||
}
|
||||
}
|
||||
if (mBubbles.indexOf(mSelectedBubble) > 0) {
|
||||
// Move the selected bubble to the top while collapsed.
|
||||
int index = mBubbles.indexOf(mSelectedBubble);
|
||||
if (index != 0) {
|
||||
mBubbles.remove(mSelectedBubble);
|
||||
mBubbles.add(0, mSelectedBubble);
|
||||
mBubbles.remove((Bubble) mSelectedBubble);
|
||||
mBubbles.add(0, (Bubble) mSelectedBubble);
|
||||
mStateChange.orderChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,11 +63,17 @@ class BubbleOverflow(
|
||||
overflowBtn = null
|
||||
}
|
||||
|
||||
/** Call before use and again if cleanUpExpandedState was called. */
|
||||
fun initialize(controller: BubbleController) {
|
||||
getExpandedView()?.initialize(controller, controller.stackView)
|
||||
getExpandedView()?.setOverflow(true)
|
||||
}
|
||||
|
||||
fun cleanUpExpandedState() {
|
||||
expandedView?.cleanUpExpandedState()
|
||||
expandedView = null
|
||||
}
|
||||
|
||||
fun update() {
|
||||
updateResources()
|
||||
getExpandedView()?.applyThemeAttrs()
|
||||
@@ -132,11 +138,6 @@ class BubbleOverflow(
|
||||
overflowBtn?.updateDotVisibility(true /* animate */)
|
||||
}
|
||||
|
||||
fun cleanUpExpandedState() {
|
||||
expandedView?.cleanUpExpandedState()
|
||||
expandedView = null
|
||||
}
|
||||
|
||||
override fun getExpandedView(): BubbleExpandedView? {
|
||||
if (expandedView == null) {
|
||||
expandedView = inflater.inflate(R.layout.bubble_expanded_view,
|
||||
|
||||
@@ -227,7 +227,7 @@ public class BubbleStackView extends FrameLayout
|
||||
* once it collapses.
|
||||
*/
|
||||
@Nullable
|
||||
private Bubble mBubbleToExpandAfterFlyoutCollapse = null;
|
||||
private BubbleViewProvider mBubbleToExpandAfterFlyoutCollapse = null;
|
||||
|
||||
/** Layout change listener that moves the stack to the nearest valid position on rotation. */
|
||||
private OnLayoutChangeListener mOrientationChangedListener;
|
||||
@@ -571,6 +571,16 @@ public class BubbleStackView extends FrameLayout
|
||||
mBubbleContainer.setActiveController(mStackAnimationController);
|
||||
hideFlyoutImmediate();
|
||||
|
||||
if (!mPositioner.showingInTaskbar()) {
|
||||
// Also, save the magnetized stack so we can dispatch touch events to it.
|
||||
mMagnetizedObject = mStackAnimationController.getMagnetizedStack(
|
||||
mMagneticTarget);
|
||||
mMagnetizedObject.setMagnetListener(mStackMagnetListener);
|
||||
} else {
|
||||
// In taskbar, the stack isn't draggable so we shouldn't dispatch touch events.
|
||||
mMagnetizedObject = null;
|
||||
}
|
||||
|
||||
// Also, save the magnetized stack so we can dispatch touch events to it.
|
||||
mMagnetizedObject = mStackAnimationController.getMagnetizedStack(mMagneticTarget);
|
||||
mMagnetizedObject.setMagnetListener(mStackMagnetListener);
|
||||
@@ -592,7 +602,9 @@ public class BubbleStackView extends FrameLayout
|
||||
public void onMove(@NonNull View v, @NonNull MotionEvent ev, float viewInitialX,
|
||||
float viewInitialY, float dx, float dy) {
|
||||
// If we're expanding or collapsing, ignore all touch events.
|
||||
if (mIsExpansionAnimating) {
|
||||
if (mIsExpansionAnimating
|
||||
// Also ignore events if we shouldn't be draggable.
|
||||
|| (mPositioner.showingInTaskbar() && !mIsExpanded)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -602,7 +614,7 @@ public class BubbleStackView extends FrameLayout
|
||||
// First, see if the magnetized object consumes the event - if so, we shouldn't move the
|
||||
// bubble since it's stuck to the target.
|
||||
if (!passEventToMagnetizedObject(ev)) {
|
||||
if (mBubbleData.isExpanded()) {
|
||||
if (mBubbleData.isExpanded() || mPositioner.showingInTaskbar()) {
|
||||
mExpandedAnimationController.dragBubbleOut(
|
||||
v, viewInitialX + dx, viewInitialY + dy);
|
||||
} else {
|
||||
@@ -743,7 +755,7 @@ public class BubbleStackView extends FrameLayout
|
||||
ta.recycle();
|
||||
|
||||
final Runnable onBubbleAnimatedOut = () -> {
|
||||
if (getBubbleCount() == 0) {
|
||||
if (getBubbleCount() == 0 && !mBubbleData.isShowingOverflow()) {
|
||||
mBubbleController.onAllBubblesAnimatedOut();
|
||||
}
|
||||
};
|
||||
@@ -816,16 +828,16 @@ public class BubbleStackView extends FrameLayout
|
||||
setFocusable(true);
|
||||
mBubbleContainer.bringToFront();
|
||||
|
||||
mBubbleOverflow = new BubbleOverflow(getContext(), mPositioner);
|
||||
mBubbleOverflow.initialize(mBubbleController);
|
||||
mBubbleOverflow = mBubbleData.getOverflow();
|
||||
mBubbleContainer.addView(mBubbleOverflow.getIconView(),
|
||||
mBubbleContainer.getChildCount() /* index */,
|
||||
new FrameLayout.LayoutParams(mPositioner.getBubbleSize(),
|
||||
mPositioner.getBubbleSize()));
|
||||
updateOverflow();
|
||||
mBubbleOverflow.getIconView().setOnClickListener((View v) -> {
|
||||
setSelectedBubble(mBubbleOverflow);
|
||||
showManageMenu(false);
|
||||
mBubbleData.setShowingOverflow(true);
|
||||
mBubbleData.setSelectedBubble(mBubbleOverflow);
|
||||
mBubbleData.setExpanded(true);
|
||||
});
|
||||
|
||||
setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
|
||||
@@ -996,11 +1008,12 @@ public class BubbleStackView extends FrameLayout
|
||||
mManageMenu.findViewById(R.id.bubble_manage_menu_settings_container).setOnClickListener(
|
||||
view -> {
|
||||
showManageMenu(false /* show */);
|
||||
final Bubble bubble = mBubbleData.getSelectedBubble();
|
||||
final BubbleViewProvider bubble = mBubbleData.getSelectedBubble();
|
||||
if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
|
||||
final Intent intent = bubble.getSettingsIntent(mContext);
|
||||
// If it's in the stack it's a proper Bubble.
|
||||
final Intent intent = ((Bubble) bubble).getSettingsIntent(mContext);
|
||||
mBubbleData.setExpanded(false);
|
||||
mContext.startActivityAsUser(intent, bubble.getUser());
|
||||
mContext.startActivityAsUser(intent, ((Bubble) bubble).getUser());
|
||||
logBubbleEvent(bubble,
|
||||
FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
|
||||
}
|
||||
@@ -1443,10 +1456,9 @@ public class BubbleStackView extends FrameLayout
|
||||
}
|
||||
|
||||
private void updateOverflowVisibility() {
|
||||
if (mBubbleOverflow == null) {
|
||||
return;
|
||||
}
|
||||
mBubbleOverflow.setVisible(mIsExpanded ? VISIBLE : GONE);
|
||||
mBubbleOverflow.setVisible((mIsExpanded || mBubbleData.isShowingOverflow())
|
||||
? VISIBLE
|
||||
: GONE);
|
||||
}
|
||||
|
||||
// via BubbleData.Listener
|
||||
@@ -2128,7 +2140,7 @@ public class BubbleStackView extends FrameLayout
|
||||
}
|
||||
}
|
||||
|
||||
private void dismissBubbleIfExists(@Nullable Bubble bubble) {
|
||||
private void dismissBubbleIfExists(@Nullable BubbleViewProvider bubble) {
|
||||
if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
|
||||
mBubbleData.dismissBubbleWithKey(bubble.getKey(), Bubbles.DISMISS_USER_GESTURE);
|
||||
}
|
||||
@@ -2337,7 +2349,7 @@ public class BubbleStackView extends FrameLayout
|
||||
}
|
||||
|
||||
if (!mIsExpanded) {
|
||||
if (getBubbleCount() > 0) {
|
||||
if (getBubbleCount() > 0 || mBubbleData.isShowingOverflow()) {
|
||||
mBubbleContainer.getChildAt(0).getBoundsOnScreen(outRect);
|
||||
// Increase the touch target size of the bubble
|
||||
outRect.top -= mBubbleTouchPadding;
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.service.notification.StatusBarNotification;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.util.Pair;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -135,8 +136,9 @@ public class BubbleDataTest extends ShellTestCase {
|
||||
mBubbleB2 = new Bubble(mEntryB2, mSuppressionListener, mPendingIntentCanceledListener);
|
||||
mBubbleB3 = new Bubble(mEntryB3, mSuppressionListener, mPendingIntentCanceledListener);
|
||||
mBubbleC1 = new Bubble(mEntryC1, mSuppressionListener, mPendingIntentCanceledListener);
|
||||
|
||||
mBubbleData = new BubbleData(getContext(), mBubbleLogger);
|
||||
TestableBubblePositioner positioner = new TestableBubblePositioner(mContext,
|
||||
mock(WindowManager.class));
|
||||
mBubbleData = new BubbleData(getContext(), mBubbleLogger, positioner);
|
||||
|
||||
// Used by BubbleData to set lastAccessedTime
|
||||
when(mTimeSource.currentTimeMillis()).thenReturn(1000L);
|
||||
|
||||
@@ -96,6 +96,7 @@ import com.android.wm.shell.bubbles.BubbleData;
|
||||
import com.android.wm.shell.bubbles.BubbleDataRepository;
|
||||
import com.android.wm.shell.bubbles.BubbleEntry;
|
||||
import com.android.wm.shell.bubbles.BubbleLogger;
|
||||
import com.android.wm.shell.bubbles.BubbleOverflow;
|
||||
import com.android.wm.shell.bubbles.BubbleStackView;
|
||||
import com.android.wm.shell.bubbles.Bubbles;
|
||||
import com.android.wm.shell.common.FloatingContentCoordinator;
|
||||
@@ -251,9 +252,8 @@ public class BubblesTest extends SysuiTestCase {
|
||||
mSysUiStateBubblesExpanded =
|
||||
(sysUiFlags & QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED) != 0);
|
||||
|
||||
mBubbleData = new BubbleData(mContext, mBubbleLogger);
|
||||
|
||||
mPositioner = new TestableBubblePositioner(mContext, mWindowManager);
|
||||
mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner);
|
||||
|
||||
TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
|
||||
new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
|
||||
@@ -578,7 +578,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveLastExpandedCollapses() {
|
||||
public void testRemoveLastExpanded_selectsOverflow() {
|
||||
// Mark it as a bubble and add it explicitly
|
||||
mEntryListener.onPendingEntryAdded(mRow.getEntry());
|
||||
mEntryListener.onPendingEntryAdded(mRow2.getEntry());
|
||||
@@ -618,10 +618,38 @@ public class BubblesTest extends SysuiTestCase {
|
||||
stackView.getExpandedBubble().getKey()).getKey(),
|
||||
Bubbles.DISMISS_USER_GESTURE);
|
||||
|
||||
// Make sure state changes and collapse happens
|
||||
// Overflow should be selected
|
||||
assertEquals(mBubbleData.getSelectedBubble().getKey(), BubbleOverflow.KEY);
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, BubbleOverflow.KEY);
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
assertTrue(mSysUiStateBubblesExpanded);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveLastExpandedEmptyOverflow_collapses() {
|
||||
// Mark it as a bubble and add it explicitly
|
||||
mEntryListener.onPendingEntryAdded(mRow.getEntry());
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
// Expand
|
||||
BubbleStackView stackView = mBubbleController.getStackView();
|
||||
mBubbleData.setExpanded(true);
|
||||
|
||||
assertTrue(mSysUiStateBubblesExpanded);
|
||||
assertTrue(mBubbleController.isStackExpanded());
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
|
||||
|
||||
// Block the bubble so it won't be in the overflow
|
||||
mBubbleController.removeBubble(
|
||||
mBubbleData.getBubbleInStackWithKey(
|
||||
stackView.getExpandedBubble().getKey()).getKey(),
|
||||
Bubbles.DISMISS_BLOCKED);
|
||||
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
|
||||
|
||||
// We should be collapsed
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
|
||||
assertFalse(mBubbleController.hasBubbles());
|
||||
|
||||
assertFalse(mSysUiStateBubblesExpanded);
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ import com.android.wm.shell.bubbles.BubbleData;
|
||||
import com.android.wm.shell.bubbles.BubbleDataRepository;
|
||||
import com.android.wm.shell.bubbles.BubbleEntry;
|
||||
import com.android.wm.shell.bubbles.BubbleLogger;
|
||||
import com.android.wm.shell.bubbles.BubbleOverflow;
|
||||
import com.android.wm.shell.bubbles.BubbleStackView;
|
||||
import com.android.wm.shell.bubbles.Bubbles;
|
||||
import com.android.wm.shell.common.FloatingContentCoordinator;
|
||||
@@ -220,9 +221,8 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
|
||||
mZenModeConfig.suppressedVisualEffects = 0;
|
||||
when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
|
||||
|
||||
mBubbleData = new BubbleData(mContext, mBubbleLogger);
|
||||
|
||||
mPositioner = new TestableBubblePositioner(mContext, mWindowManager);
|
||||
mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner);
|
||||
|
||||
TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
|
||||
new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
|
||||
@@ -509,7 +509,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveLastExpandedCollapses() {
|
||||
public void testRemoveLastExpanded_selectsOverflow() {
|
||||
// Mark it as a bubble and add it explicitly
|
||||
mEntryListener.onEntryAdded(mRow.getEntry());
|
||||
mEntryListener.onEntryAdded(mRow2.getEntry());
|
||||
@@ -547,11 +547,39 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
|
||||
stackView.getExpandedBubble().getKey()).getKey(),
|
||||
Bubbles.DISMISS_USER_GESTURE);
|
||||
|
||||
// Make sure state changes and collapse happens
|
||||
// Overflow should be selected
|
||||
assertEquals(mBubbleData.getSelectedBubble().getKey(), BubbleOverflow.KEY);
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, BubbleOverflow.KEY);
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveLastExpandedEmptyOverflow_collapses() {
|
||||
// Mark it as a bubble and add it explicitly
|
||||
mEntryListener.onEntryAdded(mRow.getEntry());
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
// Expand
|
||||
BubbleStackView stackView = mBubbleController.getStackView();
|
||||
mBubbleData.setExpanded(true);
|
||||
|
||||
assertTrue(mBubbleController.isStackExpanded());
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
|
||||
|
||||
// Block the bubble so it won't be in the overflow
|
||||
mBubbleController.removeBubble(
|
||||
mBubbleData.getBubbleInStackWithKey(
|
||||
stackView.getExpandedBubble().getKey()).getKey(),
|
||||
Bubbles.DISMISS_BLOCKED);
|
||||
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
|
||||
|
||||
// We should be collapsed
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
|
||||
assertFalse(mBubbleController.hasBubbles());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAutoExpand_fails_noFlag() {
|
||||
assertFalse(mBubbleController.isStackExpanded());
|
||||
|
||||
Reference in New Issue
Block a user