Add cached state to prevent blocking calls from SysUI->Shell

- WindowManagerGlobal has a shared lock which means that code in the
  shell main thread can deadlock with code running on the sysui main
  thread in rare cases (ie. display changes when folding/unfolding).

  Ideally there are no blocking calls between SysUI/Shell so this
  change caches state changes from the Bubbles side for querying from
  SysUI.  In particular, the expanded states and the suppressed states.

Bug: 190453559
Test: atest SystemUITests


Change-Id: I4e60b168a84618033604e7d097599b048a5886a1
This commit is contained in:
Winson Chung
2021-06-15 22:49:44 -07:00
parent 5d552869af
commit 523ab2ab6f
6 changed files with 332 additions and 183 deletions

View File

@@ -284,6 +284,15 @@ public class Bubble implements BubbleViewProvider {
return mTitle;
}
/**
* @return the ShortcutInfo id if it exists, or the metadata shortcut id otherwise.
*/
String getShortcutId() {
return getShortcutInfo() != null
? getShortcutInfo().getId()
: getMetadataShortcutId();
}
String getMetadataShortcutId() {
return mMetadataShortcutId;
}

View File

@@ -93,6 +93,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -265,15 +266,7 @@ public class BubbleController {
public void initialize() {
mBubbleData.setListener(mBubbleDataListener);
mBubbleData.setSuppressionChangedListener(bubble -> {
// Make sure NoMan knows suppression state so that anyone querying it can tell.
try {
mBarService.onBubbleNotificationSuppressionChanged(bubble.getKey(),
!bubble.showInShade(), bubble.isSuppressed());
} catch (RemoteException e) {
// Bad things have happened
}
});
mBubbleData.setSuppressionChangedListener(this::onBubbleNotificationSuppressionChanged);
mBubbleData.setPendingIntentCancelledListener(bubble -> {
if (bubble.getBubbleIntent() == null) {
@@ -401,6 +394,11 @@ public class BubbleController {
return mImpl;
}
@VisibleForTesting
public BubblesImpl.CachedState getImplCachedState() {
return mImpl.mCachedState;
}
public ShellExecutor getMainExecutor() {
return mMainExecutor;
}
@@ -500,6 +498,18 @@ public class BubbleController {
updateStack();
}
@VisibleForTesting
public void onBubbleNotificationSuppressionChanged(Bubble bubble) {
// Make sure NoMan knows suppression state so that anyone querying it can tell.
try {
mBarService.onBubbleNotificationSuppressionChanged(bubble.getKey(),
!bubble.showInShade(), bubble.isSuppressed());
} catch (RemoteException e) {
// Bad things have happened
}
mImpl.mCachedState.updateBubbleSuppressedState(bubble);
}
/** Called when the current user changes. */
@VisibleForTesting
public void onUserChanged(int newUserId) {
@@ -808,11 +818,6 @@ public class BubbleController {
}
}
private boolean isBubbleExpanded(String key) {
return isStackExpanded() && mBubbleData != null && mBubbleData.getSelectedBubble() != null
&& mBubbleData.getSelectedBubble().getKey().equals(key);
}
/** Promote the provided bubble from the overflow view. */
public void promoteBubbleFromOverflow(Bubble bubble) {
mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_BACK_TO_STACK);
@@ -1191,6 +1196,9 @@ public class BubbleController {
mSysuiProxy.notifyInvalidateNotifications("BubbleData.Listener.applyUpdate");
updateStack();
// Update the cached state for queries from SysUI
mImpl.mCachedState.update(update);
}
};
@@ -1364,25 +1372,124 @@ public class BubbleController {
}
private class BubblesImpl implements Bubbles {
// Up-to-date cached state of bubbles data for SysUI to query from the calling thread
@VisibleForTesting
public class CachedState {
private boolean mIsStackExpanded;
private String mSelectedBubbleKey;
private HashSet<String> mSuppressedBubbleKeys = new HashSet<>();
private HashMap<String, String> mSuppressedGroupToNotifKeys = new HashMap<>();
private HashMap<String, Bubble> mShortcutIdToBubble = new HashMap<>();
private ArrayList<Bubble> mTmpBubbles = new ArrayList<>();
/**
* Updates the cached state based on the last full BubbleData change.
*/
synchronized void update(BubbleData.Update update) {
if (update.selectionChanged) {
mSelectedBubbleKey = update.selectedBubble != null
? update.selectedBubble.getKey()
: null;
}
if (update.expandedChanged) {
mIsStackExpanded = update.expanded;
}
if (update.suppressedSummaryChanged) {
String summaryKey =
mBubbleData.getSummaryKey(update.suppressedSummaryGroup);
if (summaryKey != null) {
mSuppressedGroupToNotifKeys.put(update.suppressedSummaryGroup, summaryKey);
} else {
mSuppressedGroupToNotifKeys.remove(update.suppressedSummaryGroup);
}
}
mTmpBubbles.clear();
mTmpBubbles.addAll(update.bubbles);
mTmpBubbles.addAll(update.overflowBubbles);
mSuppressedBubbleKeys.clear();
mShortcutIdToBubble.clear();
for (Bubble b : mTmpBubbles) {
mShortcutIdToBubble.put(b.getShortcutId(), b);
updateBubbleSuppressedState(b);
}
}
/**
* Updates a specific bubble suppressed state. This is used mainly because notification
* suppression changes don't go through the same BubbleData update mechanism.
*/
synchronized void updateBubbleSuppressedState(Bubble b) {
if (!b.showInShade()) {
mSuppressedBubbleKeys.add(b.getKey());
} else {
mSuppressedBubbleKeys.remove(b.getKey());
}
}
public synchronized boolean isStackExpanded() {
return mIsStackExpanded;
}
public synchronized boolean isBubbleExpanded(String key) {
return mIsStackExpanded && key.equals(mSelectedBubbleKey);
}
public synchronized boolean isBubbleNotificationSuppressedFromShade(String key,
String groupKey) {
return mSuppressedBubbleKeys.contains(key)
|| (mSuppressedGroupToNotifKeys.containsKey(groupKey)
&& key.equals(mSuppressedGroupToNotifKeys.get(groupKey)));
}
@Nullable
public synchronized Bubble getBubbleWithShortcutId(String id) {
return mShortcutIdToBubble.get(id);
}
synchronized void dump(PrintWriter pw) {
pw.println("BubbleImpl.CachedState state:");
pw.println("mIsStackExpanded: " + mIsStackExpanded);
pw.println("mSelectedBubbleKey: " + mSelectedBubbleKey);
pw.print("mSuppressedBubbleKeys: ");
pw.println(mSuppressedBubbleKeys.size());
for (String key : mSuppressedBubbleKeys) {
pw.println(" suppressing: " + key);
}
pw.print("mSuppressedGroupToNotifKeys: ");
pw.println(mSuppressedGroupToNotifKeys.size());
for (String key : mSuppressedGroupToNotifKeys.keySet()) {
pw.println(" suppressing: " + key);
}
}
}
private CachedState mCachedState = new CachedState();
@Override
public boolean isBubbleNotificationSuppressedFromShade(String key, String groupKey) {
return mMainExecutor.executeBlockingForResult(() -> {
return BubbleController.this.isBubbleNotificationSuppressedFromShade(key, groupKey);
}, Boolean.class);
return mCachedState.isBubbleNotificationSuppressedFromShade(key, groupKey);
}
@Override
public boolean isBubbleExpanded(String key) {
return mMainExecutor.executeBlockingForResult(() -> {
return BubbleController.this.isBubbleExpanded(key);
}, Boolean.class);
return mCachedState.isBubbleExpanded(key);
}
@Override
public boolean isStackExpanded() {
return mMainExecutor.executeBlockingForResult(() -> {
return BubbleController.this.isStackExpanded();
}, Boolean.class);
return mCachedState.isStackExpanded();
}
@Override
@Nullable
public Bubble getBubbleWithShortcutId(String shortcutId) {
return mCachedState.getBubbleWithShortcutId(shortcutId);
}
@Override
@@ -1424,14 +1531,6 @@ public class BubbleController {
});
}
@Override
@Nullable
public Bubble getBubbleWithShortcutId(String shortcutId) {
return mMainExecutor.executeBlockingForResult(() -> {
return BubbleController.this.mBubbleData.getAnyBubbleWithShortcutId(shortcutId);
}, Bubble.class);
}
@Override
public void onTaskbarChanged(Bundle b) {
mMainExecutor.execute(() -> {
@@ -1555,6 +1654,7 @@ public class BubbleController {
try {
mMainExecutor.executeBlocking(() -> {
BubbleController.this.dump(fd, pw, args);
mCachedState.dump(pw);
});
} catch (InterruptedException e) {
Slog.e(TAG, "Failed to dump BubbleController in 2s");

View File

@@ -73,6 +73,7 @@ public class BubbleData {
boolean expandedChanged;
boolean selectionChanged;
boolean orderChanged;
boolean suppressedSummaryChanged;
boolean expanded;
@Nullable BubbleViewProvider selectedBubble;
@Nullable Bubble addedBubble;
@@ -81,6 +82,7 @@ public class BubbleData {
@Nullable Bubble removedOverflowBubble;
@Nullable Bubble suppressedBubble;
@Nullable Bubble unsuppressedBubble;
@Nullable String suppressedSummaryGroup;
// Pair with Bubble and @DismissReason Integer
final List<Pair<Bubble, Integer>> removedBubbles = new ArrayList<>();
@@ -103,7 +105,9 @@ public class BubbleData {
|| removedOverflowBubble != null
|| orderChanged
|| suppressedBubble != null
|| unsuppressedBubble != null;
|| unsuppressedBubble != null
|| suppressedSummaryChanged
|| suppressedSummaryGroup != null;
}
void bubbleRemoved(Bubble bubbleToRemove, @DismissReason int reason) {
@@ -380,6 +384,9 @@ public class BubbleData {
*/
void addSummaryToSuppress(String groupKey, String notifKey) {
mSuppressedGroupKeys.put(groupKey, notifKey);
mStateChange.suppressedSummaryChanged = true;
mStateChange.suppressedSummaryGroup = groupKey;
dispatchPendingChanges();
}
/**
@@ -397,6 +404,9 @@ public class BubbleData {
*/
void removeSuppressedSummary(String groupKey) {
mSuppressedGroupKeys.remove(groupKey);
mStateChange.suppressedSummaryChanged = true;
mStateChange.suppressedSummaryGroup = groupKey;
dispatchPendingChanges();
}
/**

View File

@@ -617,7 +617,7 @@ public class BubblesManager implements Dumpable {
* cancel it (and hence the bubbles associated with it).
*
* @return true if we want to intercept the dismissal of the entry, else false.
* @see Bubbles#handleDismissalInterception(BubbleEntry, List, IntConsumer)
* @see Bubbles#handleDismissalInterception(BubbleEntry, List, IntConsumer, Executor)
*/
public boolean handleDismissalInterception(NotificationEntry entry) {
if (entry == null) {

View File

@@ -23,6 +23,8 @@ import static android.service.notification.NotificationListenerService.REASON_CA
import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
@@ -37,6 +39,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -320,6 +323,7 @@ public class BubblesTest extends SysuiTestCase {
syncExecutor,
mock(Handler.class));
mBubbleController.setExpandListener(mBubbleExpandListener);
spyOn(mBubbleController);
mBubblesManager = new BubblesManager(
mContext,
@@ -466,7 +470,7 @@ public class BubblesTest extends SysuiTestCase {
@Test
public void testExpandCollapseStack() {
assertFalse(mBubbleController.isStackExpanded());
assertStackCollapsed();
// Mark it as a bubble and add it explicitly
mEntryListener.onPendingEntryAdded(mRow);
@@ -474,25 +478,23 @@ public class BubblesTest extends SysuiTestCase {
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Expand the stack
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
assertTrue(mSysUiStateBubblesExpanded);
// Make sure the notif is suppressed
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Collapse
mBubbleController.collapseStack();
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getKey());
assertFalse(mBubbleController.isStackExpanded());
assertStackCollapsed();
assertFalse(mSysUiStateBubblesExpanded);
}
@@ -508,15 +510,13 @@ public class BubblesTest extends SysuiTestCase {
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry2.getKey(), mBubbleEntry2.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry2);
// Expand
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
true, mRow2.getKey());
@@ -524,8 +524,7 @@ public class BubblesTest extends SysuiTestCase {
// Last added is the one that is expanded
assertEquals(mRow2.getKey(), mBubbleData.getSelectedBubble().getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry2.getKey(), mBubbleEntry2.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry2);
// Switch which bubble is expanded
mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(
@@ -533,8 +532,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleData.setExpanded(true);
assertEquals(mRow.getKey(), mBubbleData.getBubbleInStackWithKey(
stackView.getExpandedBubble().getKey()).getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// collapse for previous bubble
verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
@@ -545,7 +543,7 @@ public class BubblesTest extends SysuiTestCase {
// Collapse
mBubbleController.collapseStack();
assertFalse(mBubbleController.isStackExpanded());
assertStackCollapsed();
assertFalse(mSysUiStateBubblesExpanded);
}
@@ -558,22 +556,20 @@ public class BubblesTest extends SysuiTestCase {
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
// Expand
mBubbleData.setExpanded(true);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
assertTrue(mSysUiStateBubblesExpanded);
// Notif is suppressed after expansion
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
}
@@ -586,22 +582,20 @@ public class BubblesTest extends SysuiTestCase {
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
// Expand
mBubbleData.setExpanded(true);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
assertTrue(mSysUiStateBubblesExpanded);
// Notif is suppressed after expansion
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -610,8 +604,7 @@ public class BubblesTest extends SysuiTestCase {
// Nothing should have changed
// Notif is suppressed after expansion
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
}
@@ -630,14 +623,13 @@ public class BubblesTest extends SysuiTestCase {
assertTrue(mSysUiStateBubblesExpanded);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getKey());
// Last added is the one that is expanded
assertEquals(mRow2.getKey(), mBubbleData.getBubbleInStackWithKey(
stackView.getExpandedBubble().getKey()).getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry2.getKey(), mBubbleEntry2.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry2);
// Dismiss currently expanded
mBubbleController.removeBubble(
@@ -675,7 +667,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleData.setExpanded(true);
assertTrue(mSysUiStateBubblesExpanded);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
// Block the bubble so it won't be in the overflow
@@ -694,7 +686,7 @@ public class BubblesTest extends SysuiTestCase {
@Test
public void testAutoExpand_fails_noFlag() {
assertFalse(mBubbleController.isStackExpanded());
assertStackCollapsed();
setMetadataFlags(mRow,
Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, false /* enableFlag */);
@@ -705,7 +697,7 @@ public class BubblesTest extends SysuiTestCase {
// Expansion shouldn't change
verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
mRow.getKey());
assertFalse(mBubbleController.isStackExpanded());
assertStackCollapsed();
assertFalse(mSysUiStateBubblesExpanded);
}
@@ -722,7 +714,7 @@ public class BubblesTest extends SysuiTestCase {
// Expansion should change
verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
mRow.getKey());
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
assertTrue(mSysUiStateBubblesExpanded);
}
@@ -737,8 +729,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
// Notif should be suppressed because we were foreground
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Dot + flyout is hidden because notif is suppressed
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showFlyout());
@@ -751,8 +742,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
// Should not be suppressed
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Should show dot
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -762,8 +752,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
// Notif should be suppressed
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Dot + flyout is hidden because notif is suppressed
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showFlyout());
@@ -788,8 +777,7 @@ public class BubblesTest extends SysuiTestCase {
@Test
public void testMarkNewNotificationAsShowInShade() {
mEntryListener.onPendingEntryAdded(mRow);
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -874,8 +862,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
mRow.getKey(), mRow, REASON_CANCEL_ALL);
@@ -883,8 +870,7 @@ public class BubblesTest extends SysuiTestCase {
// Intercept!
assertTrue(intercepted);
// Should update show in shade state
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
}
@Test
@@ -893,8 +879,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
mRow.getKey(), mRow, REASON_CANCEL);
@@ -902,8 +887,7 @@ public class BubblesTest extends SysuiTestCase {
// Intercept!
assertTrue(intercepted);
// Should update show in shade state
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
}
@Test
@@ -912,8 +896,7 @@ public class BubblesTest extends SysuiTestCase {
mEntryListener.onPendingEntryAdded(mRow);
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Dismiss the bubble into overflow.
mBubbleController.removeBubble(
@@ -934,8 +917,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mBubbleController.removeBubble(
mRow.getKey(), Bubbles.DISMISS_NO_LONGER_BUBBLE);
@@ -981,48 +963,36 @@ public class BubblesTest extends SysuiTestCase {
@Test
public void testNotifyShadeSuppressionChange_notificationDismiss() {
Bubbles.SuppressionChangedListener listener =
mock(Bubbles.SuppressionChangedListener.class);
mBubbleData.setSuppressionChangedListener(listener);
mEntryListener.onPendingEntryAdded(mRow);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mRemoveInterceptor.onNotificationRemoveRequested(
mRow.getKey(), mRow, REASON_CANCEL);
// Should update show in shade state
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Should notify delegate that shade state changed
verify(listener).onBubbleNotificationSuppressionChange(
verify(mBubbleController).onBubbleNotificationSuppressionChanged(
mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
}
@Test
public void testNotifyShadeSuppressionChange_bubbleExpanded() {
Bubbles.SuppressionChangedListener listener =
mock(Bubbles.SuppressionChangedListener.class);
mBubbleData.setSuppressionChangedListener(listener);
mEntryListener.onPendingEntryAdded(mRow);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mBubbleData.setExpanded(true);
// Once a bubble is expanded the notif is suppressed
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Should notify delegate that shade state changed
verify(listener).onBubbleNotificationSuppressionChange(
verify(mBubbleController).onBubbleNotificationSuppressionChanged(
mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
}
@@ -1042,7 +1012,11 @@ public class BubblesTest extends SysuiTestCase {
// THEN the summary and bubbled child are suppressed from the shade
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(), groupSummary.getEntry().getSbn().getGroupKey()));
groupedBubble.getEntry().getKey(),
groupSummary.getEntry().getSbn().getGroupKey()));
assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(),
groupSummary.getEntry().getSbn().getGroupKey()));
assertTrue(mBubbleData.isSummarySuppressed(groupSummary.getEntry().getSbn().getGroupKey()));
}
@@ -1098,6 +1072,9 @@ public class BubblesTest extends SysuiTestCase {
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(),
groupedBubble.getEntry().getSbn().getGroupKey()));
assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(),
groupedBubble.getEntry().getSbn().getGroupKey()));
// THEN the summary is removed from GroupManager
verify(mNotificationGroupManager, times(1)).onEntryRemoved(groupSummary.getEntry());
@@ -1253,4 +1230,42 @@ public class BubblesTest extends SysuiTestCase {
Icon.createWithResource(mContext, R.drawable.bubble_ic_create_bubble))
.build();
}
/**
* Asserts that the bubble stack is expanded and also validates the cached state is updated.
*/
private void assertStackExpanded() {
assertTrue(mBubbleController.isStackExpanded());
assertTrue(mBubbleController.getImplCachedState().isStackExpanded());
}
/**
* Asserts that the bubble stack is collapsed and also validates the cached state is updated.
*/
private void assertStackCollapsed() {
assertFalse(mBubbleController.isStackExpanded());
assertFalse(mBubbleController.getImplCachedState().isStackExpanded());
}
/**
* Asserts that a bubble notification is suppressed from the shade and also validates the cached
* state is updated.
*/
private void assertBubbleNotificationSuppressedFromShade(BubbleEntry entry) {
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
entry.getKey(), entry.getGroupKey()));
assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
entry.getKey(), entry.getGroupKey()));
}
/**
* Asserts that a bubble notification is not suppressed from the shade and also validates the
* cached state is updated.
*/
private void assertBubbleNotificationNotSuppressedFromShade(BubbleEntry entry) {
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
entry.getKey(), entry.getGroupKey()));
assertFalse(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
entry.getKey(), entry.getGroupKey()));
}
}

View File

@@ -19,6 +19,8 @@ package com.android.systemui.wmshell;
import static android.app.Notification.FLAG_BUBBLE;
import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
@@ -264,6 +266,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
syncExecutor,
mock(Handler.class));
mBubbleController.setExpandListener(mBubbleExpandListener);
spyOn(mBubbleController);
mBubblesManager = new BubblesManager(
mContext,
@@ -324,8 +327,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Make it look like dismissed notif
mBubbleData.getBubbleInStackWithKey(mRow.getKey()).setSuppressNotification(true);
@@ -348,8 +350,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
.thenReturn(mRow);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Make it look like dismissed notif
mBubbleData.getBubbleInStackWithKey(mRow.getKey()).setSuppressNotification(true);
@@ -384,7 +385,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
@Test
public void testExpandCollapseStack() {
assertFalse(mBubbleController.isStackExpanded());
assertStackCollapsed();
// Mark it as a bubble and add it explicitly
mEntryListener.onEntryAdded(mRow);
@@ -392,23 +393,20 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Expand the stack
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
// Make sure the notif is suppressed
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Collapse
mBubbleController.collapseStack();
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getKey());
assertFalse(mBubbleController.isStackExpanded());
assertStackCollapsed();
}
@Test
@@ -422,22 +420,19 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry2);
// Expand
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
true, mRow2.getKey());
// Last added is the one that is expanded
assertEquals(mRow2.getKey(), mBubbleData.getSelectedBubble().getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry2.getKey(), mBubbleEntry2.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry2);
// Switch which bubble is expanded
mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(
@@ -445,8 +440,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
mBubbleData.setExpanded(true);
assertEquals(mRow.getKey(), mBubbleData.getBubbleInStackWithKey(
stackView.getExpandedBubble().getKey()).getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// collapse for previous bubble
verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
@@ -458,7 +452,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
// Collapse
mBubbleController.collapseStack();
assertFalse(mBubbleController.isStackExpanded());
assertStackCollapsed();
}
@Test
@@ -469,20 +463,18 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
// Expand
mBubbleData.setExpanded(true);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
// Notif is suppressed after expansion
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
}
@@ -495,20 +487,18 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
// Expand
mBubbleData.setExpanded(true);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
// Notif is suppressed after expansion
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -517,8 +507,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
// Nothing should have changed
// Notif is suppressed after expansion
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
}
@@ -535,14 +524,13 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getKey());
// Last added is the one that is expanded
assertEquals(mRow2.getKey(), mBubbleData.getBubbleInStackWithKey(
stackView.getExpandedBubble().getKey()).getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry2.getKey(), mBubbleEntry2.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry2);
// Dismiss currently expanded
mBubbleController.removeBubble(
@@ -578,7 +566,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
// Block the bubble so it won't be in the overflow
@@ -597,7 +585,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
@Test
public void testAutoExpand_fails_noFlag() {
assertFalse(mBubbleController.isStackExpanded());
assertStackCollapsed();
setMetadataFlags(mRow,
Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, false /* enableFlag */);
@@ -608,7 +596,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
// Expansion shouldn't change
verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
mRow.getKey());
assertFalse(mBubbleController.isStackExpanded());
assertStackCollapsed();
}
@Test
@@ -623,7 +611,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
// Expansion should change
verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
mRow.getKey());
assertTrue(mBubbleController.isStackExpanded());
assertStackExpanded();
}
@Test
@@ -636,8 +624,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
// Notif should be suppressed because we were foreground
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Dot + flyout is hidden because notif is suppressed
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showFlyout());
@@ -648,8 +635,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
// Should not be suppressed
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Should show dot
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -659,8 +645,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
// Notif should be suppressed
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Dot + flyout is hidden because notif is suppressed
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showFlyout());
@@ -669,8 +654,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
@Test
public void testMarkNewNotificationAsShowInShade() {
mEntryListener.onEntryAdded(mRow);
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -741,16 +725,14 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
boolean intercepted = mBubblesManager.handleDismissalInterception(mRow);
// Intercept!
assertTrue(intercepted);
// Should update show in shade state
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
}
@Test
@@ -759,8 +741,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Dismiss the bubble
mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
@@ -779,8 +760,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Dismiss the bubble
mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_NOTIF_CANCEL);
@@ -795,47 +775,35 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
@Test
public void testNotifyShadeSuppressionChange_notificationDismiss() {
Bubbles.SuppressionChangedListener listener =
mock(Bubbles.SuppressionChangedListener.class);
mBubbleData.setSuppressionChangedListener(listener);
mEntryListener.onEntryAdded(mRow);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mBubblesManager.handleDismissalInterception(mRow);
// Should update show in shade state
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Should notify delegate that shade state changed
verify(listener).onBubbleNotificationSuppressionChange(
verify(mBubbleController).onBubbleNotificationSuppressionChanged(
mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
}
@Test
public void testNotifyShadeSuppressionChange_bubbleExpanded() {
Bubbles.SuppressionChangedListener listener =
mock(Bubbles.SuppressionChangedListener.class);
mBubbleData.setSuppressionChangedListener(listener);
mEntryListener.onEntryAdded(mRow);
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mBubbleData.setExpanded(true);
// Once a bubble is expanded the notif is suppressed
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Should notify delegate that shade state changed
verify(listener).onBubbleNotificationSuppressionChange(
verify(mBubbleController).onBubbleNotificationSuppressionChanged(
mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
}
@@ -857,6 +825,9 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(),
groupedBubble.getEntry().getSbn().getGroupKey()));
assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(),
groupedBubble.getEntry().getSbn().getGroupKey()));
assertTrue(mBubbleData.isSummarySuppressed(groupSummary.getEntry().getSbn().getGroupKey()));
}
@@ -911,11 +882,17 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(),
groupedBubble.getEntry().getSbn().getGroupKey()));
assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(),
groupedBubble.getEntry().getSbn().getGroupKey()));
// THEN the summary is also suppressed from the shade
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
groupSummary.getEntry().getKey(),
groupSummary.getEntry().getSbn().getGroupKey()));
assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
groupSummary.getEntry().getKey(),
groupSummary.getEntry().getSbn().getGroupKey()));
}
/**
@@ -934,4 +911,42 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
}
bubbleMetadata.setFlags(flags);
}
/**
* Asserts that the bubble stack is expanded and also validates the cached state is updated.
*/
private void assertStackExpanded() {
assertTrue(mBubbleController.isStackExpanded());
assertTrue(mBubbleController.getImplCachedState().isStackExpanded());
}
/**
* Asserts that the bubble stack is collapsed and also validates the cached state is updated.
*/
private void assertStackCollapsed() {
assertFalse(mBubbleController.isStackExpanded());
assertFalse(mBubbleController.getImplCachedState().isStackExpanded());
}
/**
* Asserts that a bubble notification is suppressed from the shade and also validates the cached
* state is updated.
*/
private void assertBubbleNotificationSuppressedFromShade(BubbleEntry entry) {
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
entry.getKey(), entry.getGroupKey()));
assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
entry.getKey(), entry.getGroupKey()));
}
/**
* Asserts that a bubble notification is not suppressed from the shade and also validates the
* cached state is updated.
*/
private void assertBubbleNotificationNotSuppressedFromShade(BubbleEntry entry) {
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
entry.getKey(), entry.getGroupKey()));
assertFalse(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
entry.getKey(), entry.getGroupKey()));
}
}