Inline notif pipeline flag into BubblesManager
This change is a no-op; the flag is now enabled-by-default, so all removed code paths here are effectively dead. Bug: 200269355 Test: atest SystemUITests Change-Id: I5ccc8d1926a5973ba02bfc20c565a18ec100d805
This commit is contained in:
@@ -55,8 +55,6 @@ import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.QsFrameTranslateModule;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
|
||||
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
|
||||
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
|
||||
@@ -220,11 +218,9 @@ public abstract class SystemUIModule {
|
||||
ZenModeController zenModeController,
|
||||
NotificationLockscreenUserManager notifUserManager,
|
||||
NotificationGroupManagerLegacy groupManager,
|
||||
NotificationEntryManager entryManager,
|
||||
CommonNotifCollection notifCollection,
|
||||
NotifPipeline notifPipeline,
|
||||
SysUiState sysUiState,
|
||||
NotifPipelineFlags notifPipelineFlags,
|
||||
DumpManager dumpManager,
|
||||
@Main Executor sysuiMainExecutor) {
|
||||
return Optional.ofNullable(BubblesManager.create(context,
|
||||
@@ -240,11 +236,9 @@ public abstract class SystemUIModule {
|
||||
zenModeController,
|
||||
notifUserManager,
|
||||
groupManager,
|
||||
entryManager,
|
||||
notifCollection,
|
||||
notifPipeline,
|
||||
sysUiState,
|
||||
notifPipelineFlags,
|
||||
dumpManager,
|
||||
sysuiMainExecutor));
|
||||
}
|
||||
|
||||
@@ -21,14 +21,10 @@ import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
|
||||
import static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
|
||||
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
|
||||
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
|
||||
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
|
||||
import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
|
||||
import static android.service.notification.NotificationListenerService.REASON_CLICK;
|
||||
import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
|
||||
import static android.service.notification.NotificationStats.DISMISSAL_BUBBLE;
|
||||
import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
|
||||
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
|
||||
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
|
||||
@@ -55,7 +51,6 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.statusbar.NotificationVisibility;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
@@ -63,9 +58,7 @@ import com.android.systemui.model.SysUiState;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationChannelHelper;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryListener;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifCollection;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
|
||||
@@ -114,7 +107,6 @@ public class BubblesManager implements Dumpable {
|
||||
private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
|
||||
private final NotificationLockscreenUserManager mNotifUserManager;
|
||||
private final NotificationGroupManagerLegacy mNotificationGroupManager;
|
||||
private final NotificationEntryManager mNotificationEntryManager;
|
||||
private final CommonNotifCollection mCommonNotifCollection;
|
||||
private final NotifPipeline mNotifPipeline;
|
||||
private final Executor mSysuiMainExecutor;
|
||||
@@ -142,11 +134,9 @@ public class BubblesManager implements Dumpable {
|
||||
ZenModeController zenModeController,
|
||||
NotificationLockscreenUserManager notifUserManager,
|
||||
NotificationGroupManagerLegacy groupManager,
|
||||
NotificationEntryManager entryManager,
|
||||
CommonNotifCollection notifCollection,
|
||||
NotifPipeline notifPipeline,
|
||||
SysUiState sysUiState,
|
||||
NotifPipelineFlags notifPipelineFlags,
|
||||
DumpManager dumpManager,
|
||||
Executor sysuiMainExecutor) {
|
||||
if (bubblesOptional.isPresent()) {
|
||||
@@ -163,11 +153,9 @@ public class BubblesManager implements Dumpable {
|
||||
zenModeController,
|
||||
notifUserManager,
|
||||
groupManager,
|
||||
entryManager,
|
||||
notifCollection,
|
||||
notifPipeline,
|
||||
sysUiState,
|
||||
notifPipelineFlags,
|
||||
dumpManager,
|
||||
sysuiMainExecutor);
|
||||
} else {
|
||||
@@ -189,11 +177,9 @@ public class BubblesManager implements Dumpable {
|
||||
ZenModeController zenModeController,
|
||||
NotificationLockscreenUserManager notifUserManager,
|
||||
NotificationGroupManagerLegacy groupManager,
|
||||
NotificationEntryManager entryManager,
|
||||
CommonNotifCollection notifCollection,
|
||||
NotifPipeline notifPipeline,
|
||||
SysUiState sysUiState,
|
||||
NotifPipelineFlags notifPipelineFlags,
|
||||
DumpManager dumpManager,
|
||||
Executor sysuiMainExecutor) {
|
||||
mContext = context;
|
||||
@@ -205,7 +191,6 @@ public class BubblesManager implements Dumpable {
|
||||
mNotificationInterruptStateProvider = interruptionStateProvider;
|
||||
mNotifUserManager = notifUserManager;
|
||||
mNotificationGroupManager = groupManager;
|
||||
mNotificationEntryManager = entryManager;
|
||||
mCommonNotifCollection = notifCollection;
|
||||
mNotifPipeline = notifPipeline;
|
||||
mSysuiMainExecutor = sysuiMainExecutor;
|
||||
@@ -215,11 +200,7 @@ public class BubblesManager implements Dumpable {
|
||||
ServiceManager.getService(Context.STATUS_BAR_SERVICE))
|
||||
: statusBarService;
|
||||
|
||||
if (notifPipelineFlags.isNewPipelineEnabled()) {
|
||||
setupNotifPipeline();
|
||||
} else {
|
||||
setupNEM();
|
||||
}
|
||||
setupNotifPipeline();
|
||||
|
||||
dumpManager.registerDumpable(TAG, this);
|
||||
|
||||
@@ -438,141 +419,6 @@ public class BubblesManager implements Dumpable {
|
||||
mBubbles.setSysuiProxy(mSysuiProxy);
|
||||
}
|
||||
|
||||
private void setupNEM() {
|
||||
mNotificationEntryManager.addNotificationEntryListener(
|
||||
new NotificationEntryListener() {
|
||||
@Override
|
||||
public void onPendingEntryAdded(NotificationEntry entry) {
|
||||
BubblesManager.this.onEntryAdded(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreEntryUpdated(NotificationEntry entry) {
|
||||
BubblesManager.this.onEntryUpdated(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntryRemoved(
|
||||
NotificationEntry entry,
|
||||
@Nullable NotificationVisibility visibility,
|
||||
boolean removedByUser,
|
||||
int reason) {
|
||||
BubblesManager.this.onEntryRemoved(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationRankingUpdated(RankingMap rankingMap) {
|
||||
BubblesManager.this.onRankingUpdate(rankingMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationChannelModified(
|
||||
String pkgName,
|
||||
UserHandle user,
|
||||
NotificationChannel channel,
|
||||
int modificationType) {
|
||||
BubblesManager.this.onNotificationChannelModified(pkgName,
|
||||
user,
|
||||
channel,
|
||||
modificationType);
|
||||
}
|
||||
});
|
||||
|
||||
// The new pipeline takes care of this as a NotifDismissInterceptor BubbleCoordinator
|
||||
mNotificationEntryManager.addNotificationRemoveInterceptor(
|
||||
(key, entry, dismissReason) -> {
|
||||
final boolean isClearAll = dismissReason == REASON_CANCEL_ALL;
|
||||
final boolean isUserDismiss = dismissReason == REASON_CANCEL
|
||||
|| dismissReason == REASON_CLICK;
|
||||
final boolean isAppCancel = dismissReason == REASON_APP_CANCEL
|
||||
|| dismissReason == REASON_APP_CANCEL_ALL;
|
||||
final boolean isSummaryCancel =
|
||||
dismissReason == REASON_GROUP_SUMMARY_CANCELED;
|
||||
|
||||
// Need to check for !appCancel here because the notification may have
|
||||
// previously been dismissed & entry.isRowDismissed would still be true
|
||||
boolean userRemovedNotif =
|
||||
(entry != null && entry.isRowDismissed() && !isAppCancel)
|
||||
|| isClearAll || isUserDismiss || isSummaryCancel;
|
||||
|
||||
if (userRemovedNotif) {
|
||||
return handleDismissalInterception(entry);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
mNotificationGroupManager.registerGroupChangeListener(
|
||||
new NotificationGroupManagerLegacy.OnGroupChangeListener() {
|
||||
@Override
|
||||
public void onGroupSuppressionChanged(
|
||||
NotificationGroupManagerLegacy.NotificationGroup group,
|
||||
boolean suppressed) {
|
||||
// More notifications could be added causing summary to no longer
|
||||
// be suppressed -- in this case need to remove the key.
|
||||
final String groupKey = group.summary != null
|
||||
? group.summary.getSbn().getGroupKey()
|
||||
: null;
|
||||
if (!suppressed && groupKey != null) {
|
||||
mBubbles.removeSuppressedSummaryIfNecessary(groupKey, null, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addNotifCallback(new NotifCallback() {
|
||||
@Override
|
||||
public void removeNotification(NotificationEntry entry,
|
||||
DismissedByUserStats dismissedByUserStats, int reason) {
|
||||
mNotificationEntryManager.performRemoveNotification(entry.getSbn(),
|
||||
dismissedByUserStats, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateNotifications(String reason) {
|
||||
mNotificationEntryManager.updateNotifications(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maybeCancelSummary(NotificationEntry entry) {
|
||||
// Check if removed bubble has an associated suppressed group summary that needs
|
||||
// to be removed now.
|
||||
final String groupKey = entry.getSbn().getGroupKey();
|
||||
mBubbles.removeSuppressedSummaryIfNecessary(groupKey, (summaryKey) -> {
|
||||
final NotificationEntry summary =
|
||||
mNotificationEntryManager.getActiveNotificationUnfiltered(summaryKey);
|
||||
if (summary != null) {
|
||||
mNotificationEntryManager.performRemoveNotification(
|
||||
summary.getSbn(),
|
||||
getDismissedByUserStats(summary, false),
|
||||
UNDEFINED_DISMISS_REASON);
|
||||
}
|
||||
}, mSysuiMainExecutor);
|
||||
|
||||
// Check if we still need to remove the summary from NoManGroup because the summary
|
||||
// may not be in the mBubbleData.mSuppressedGroupKeys list and removed above.
|
||||
// For example:
|
||||
// 1. Bubbled notifications (group) is posted to shade and are visible bubbles
|
||||
// 2. User expands bubbles so now their respective notifications in the shade are
|
||||
// hidden, including the group summary
|
||||
// 3. User removes all bubbles
|
||||
// 4. We expect all the removed bubbles AND the summary (note: the summary was
|
||||
// never added to the suppressedSummary list in BubbleData, so we add this check)
|
||||
NotificationEntry summary = mNotificationGroupManager.getLogicalGroupSummary(entry);
|
||||
if (summary != null) {
|
||||
ArrayList<NotificationEntry> summaryChildren =
|
||||
mNotificationGroupManager.getLogicalChildren(summary.getSbn());
|
||||
boolean isSummaryThisNotif = summary.getKey().equals(entry.getKey());
|
||||
if (!isSummaryThisNotif && (summaryChildren == null
|
||||
|| summaryChildren.isEmpty())) {
|
||||
mNotificationEntryManager.performRemoveNotification(
|
||||
summary.getSbn(),
|
||||
getDismissedByUserStats(summary, false),
|
||||
UNDEFINED_DISMISS_REASON);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupNotifPipeline() {
|
||||
mNotifPipeline.addCollectionListener(new NotifCollectionListener() {
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,12 +21,9 @@ import static android.app.PendingIntent.FLAG_MUTABLE;
|
||||
import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED;
|
||||
import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED;
|
||||
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
|
||||
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
|
||||
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.android.wm.shell.bubbles.Bubbles.DISMISS_NOTIF_CANCEL;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -62,7 +59,6 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.hardware.display.AmbientDisplayConfiguration;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.os.UserHandle;
|
||||
@@ -90,18 +86,16 @@ 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.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
|
||||
import com.android.systemui.statusbar.RankingBuilder;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryListener;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
|
||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
|
||||
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
|
||||
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider;
|
||||
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptLogger;
|
||||
@@ -118,7 +112,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.policy.ZenModeController;
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.TaskViewTransitions;
|
||||
import com.android.wm.shell.WindowManagerShellWrapper;
|
||||
@@ -140,8 +133,6 @@ import com.android.wm.shell.common.TaskStackListenerImpl;
|
||||
import com.android.wm.shell.draganddrop.DragAndDropController;
|
||||
import com.android.wm.shell.onehanded.OneHandedController;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
@@ -155,22 +146,17 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Tests the NotificationEntryManager setup with BubbleController.
|
||||
* The {@link NotifPipeline} setup with BubbleController is tested in
|
||||
* {@link NewNotifPipelineBubblesTest}.
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper(setAsMainLooper = true)
|
||||
public class BubblesTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private NotificationEntryManager mNotificationEntryManager;
|
||||
@Mock
|
||||
private CommonNotifCollection mCommonNotifCollection;
|
||||
@Mock
|
||||
private NotificationGroupManagerLegacy mNotificationGroupManager;
|
||||
@Mock
|
||||
private BubblesManager.NotifCallback mNotifCallback;
|
||||
@Mock
|
||||
private WindowManager mWindowManager;
|
||||
@Mock
|
||||
private IActivityManager mActivityManager;
|
||||
@@ -183,8 +169,6 @@ public class BubblesTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private ZenModeConfig mZenModeConfig;
|
||||
@Mock
|
||||
private FaceManager mFaceManager;
|
||||
@Mock
|
||||
private NotificationLockscreenUserManager mLockscreenUserManager;
|
||||
@Mock
|
||||
private SysuiStatusBarStateController mStatusBarStateController;
|
||||
@@ -196,15 +180,17 @@ public class BubblesTest extends SysuiTestCase {
|
||||
private FloatingContentCoordinator mFloatingContentCoordinator;
|
||||
@Mock
|
||||
private BubbleDataRepository mDataRepository;
|
||||
@Mock
|
||||
private NotificationShadeWindowView mNotificationShadeWindowView;
|
||||
@Mock
|
||||
private AuthController mAuthController;
|
||||
|
||||
private SysUiState mSysUiState;
|
||||
private boolean mSysUiStateBubblesExpanded;
|
||||
private boolean mSysUiStateBubblesManageMenuExpanded;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<NotificationRemoveInterceptor> mRemoveInterceptorCaptor;
|
||||
private ArgumentCaptor<NotifCollectionListener> mNotifListenerCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<List<Bubble>> mBubbleListCaptor;
|
||||
@Captor
|
||||
@@ -212,22 +198,16 @@ public class BubblesTest extends SysuiTestCase {
|
||||
@Captor
|
||||
private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverArgumentCaptor;
|
||||
|
||||
|
||||
private BubblesManager mBubblesManager;
|
||||
// TODO(178618782): Move tests on the controller directly to the shell
|
||||
private TestableBubbleController mBubbleController;
|
||||
private NotificationShadeWindowControllerImpl mNotificationShadeWindowController;
|
||||
private NotificationEntryListener mEntryListener;
|
||||
private NotificationRemoveInterceptor mRemoveInterceptor;
|
||||
|
||||
private NotifCollectionListener mEntryListener;
|
||||
private NotificationTestHelper mNotificationTestHelper;
|
||||
private NotificationEntry mRow;
|
||||
private NotificationEntry mRow2;
|
||||
private NotificationEntry mRow3;
|
||||
private ExpandableNotificationRow mNonBubbleNotifRow;
|
||||
private BubbleEntry mBubbleEntry;
|
||||
private BubbleEntry mBubbleEntry2;
|
||||
private BubbleEntry mBubbleEntry3;
|
||||
|
||||
private BubbleEntry mBubbleEntryUser11;
|
||||
private BubbleEntry mBubbleEntry2User11;
|
||||
@@ -245,12 +225,8 @@ public class BubblesTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private NotifPipeline mNotifPipeline;
|
||||
@Mock
|
||||
private NotifPipelineFlags mNotifPipelineFlags;
|
||||
@Mock
|
||||
private DumpManager mDumpManager;
|
||||
@Mock
|
||||
private NotificationShadeWindowView mNotificationShadeWindowView;
|
||||
@Mock
|
||||
private IStatusBarService mStatusBarService;
|
||||
@Mock
|
||||
private NotificationVisibilityProvider mVisibilityProvider;
|
||||
@@ -269,8 +245,6 @@ public class BubblesTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private ScreenOffAnimationController mScreenOffAnimationController;
|
||||
@Mock
|
||||
private AuthController mAuthController;
|
||||
@Mock
|
||||
private TaskViewTransitions mTaskViewTransitions;
|
||||
@Mock
|
||||
private Optional<OneHandedController> mOneHandedOptional;
|
||||
@@ -290,7 +264,6 @@ public class BubblesTest extends SysuiTestCase {
|
||||
// For the purposes of this test, just run everything synchronously
|
||||
ShellExecutor syncExecutor = new SyncExecutor();
|
||||
|
||||
mContext.addMockSystemService(FaceManager.class, mFaceManager);
|
||||
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
|
||||
|
||||
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
|
||||
@@ -308,11 +281,9 @@ public class BubblesTest extends SysuiTestCase {
|
||||
TestableLooper.get(this));
|
||||
mRow = mNotificationTestHelper.createBubble(mDeleteIntent);
|
||||
mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent);
|
||||
mRow3 = mNotificationTestHelper.createBubble(mDeleteIntent);
|
||||
mNonBubbleNotifRow = mNotificationTestHelper.createRow();
|
||||
mBubbleEntry = BubblesManager.notifToBubbleEntry(mRow);
|
||||
mBubbleEntry2 = BubblesManager.notifToBubbleEntry(mRow2);
|
||||
mBubbleEntry3 = BubblesManager.notifToBubbleEntry(mRow3);
|
||||
|
||||
UserHandle handle = mock(UserHandle.class);
|
||||
when(handle.getIdentifier()).thenReturn(11);
|
||||
@@ -321,9 +292,6 @@ public class BubblesTest extends SysuiTestCase {
|
||||
mBubbleEntry2User11 = BubblesManager.notifToBubbleEntry(
|
||||
mNotificationTestHelper.createBubble(handle));
|
||||
|
||||
// Return non-null notification data from the CommonNotifCollection
|
||||
when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
|
||||
|
||||
mZenModeConfig.suppressedVisualEffects = 0;
|
||||
when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
|
||||
|
||||
@@ -336,7 +304,6 @@ public class BubblesTest extends SysuiTestCase {
|
||||
(sysUiFlags & QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED) != 0;
|
||||
});
|
||||
|
||||
// TODO: Fix
|
||||
mPositioner = new TestableBubblePositioner(mContext, mWindowManager);
|
||||
mPositioner.setMaxBubbles(5);
|
||||
mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner, syncExecutor);
|
||||
@@ -355,8 +322,6 @@ public class BubblesTest extends SysuiTestCase {
|
||||
mock(NotifPipelineFlags.class),
|
||||
mock(KeyguardNotificationVisibilityProvider.class)
|
||||
);
|
||||
|
||||
when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
|
||||
when(mShellTaskOrganizer.getExecutor()).thenReturn(syncExecutor);
|
||||
mBubbleController = new TestableBubbleController(
|
||||
mContext,
|
||||
@@ -396,23 +361,17 @@ public class BubblesTest extends SysuiTestCase {
|
||||
mZenModeController,
|
||||
mLockscreenUserManager,
|
||||
mNotificationGroupManager,
|
||||
mNotificationEntryManager,
|
||||
mCommonNotifCollection,
|
||||
mNotifPipeline,
|
||||
mSysUiState,
|
||||
mNotifPipelineFlags,
|
||||
mDumpManager,
|
||||
syncExecutor);
|
||||
mBubblesManager.addNotifCallback(mNotifCallback);
|
||||
|
||||
// XXX: Does *this* need to be changed?
|
||||
// Get a reference to the BubbleController's entry listener
|
||||
verify(mNotificationEntryManager, atLeastOnce())
|
||||
.addNotificationEntryListener(mEntryListenerCaptor.capture());
|
||||
mEntryListener = mEntryListenerCaptor.getValue();
|
||||
// And the remove interceptor
|
||||
verify(mNotificationEntryManager, atLeastOnce())
|
||||
.addNotificationRemoveInterceptor(mRemoveInterceptorCaptor.capture());
|
||||
mRemoveInterceptor = mRemoveInterceptorCaptor.getValue();
|
||||
verify(mNotifPipeline, atLeastOnce())
|
||||
.addCollectionListener(mNotifListenerCaptor.capture());
|
||||
mEntryListener = mNotifListenerCaptor.getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -433,90 +392,75 @@ public class BubblesTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testRemoveBubble() {
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
assertNotNull(mBubbleData.getBubbleInStackWithKey(mBubbleEntry.getKey()));
|
||||
assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
verify(mNotificationEntryManager).updateNotifications(any());
|
||||
verify(mNotifCallback, times(1)).invalidateNotifications(anyString());
|
||||
|
||||
mBubbleController.removeBubble(
|
||||
mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
|
||||
assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
|
||||
verify(mNotificationEntryManager, times(2)).updateNotifications(anyString());
|
||||
verify(mNotifCallback, times(2)).invalidateNotifications(anyString());
|
||||
|
||||
assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPromoteBubble_autoExpand() throws Exception {
|
||||
mBubbleController.updateBubble(mBubbleEntry2);
|
||||
public void testRemoveBubble_withDismissedNotif_inOverflow() {
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
|
||||
when(mCommonNotifCollection.getEntry(mRow2.getKey())).thenReturn(mRow2);
|
||||
mBubbleController.removeBubble(
|
||||
mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
|
||||
|
||||
Bubble b = mBubbleData.getOverflowBubbleWithKey(mRow.getKey());
|
||||
assertThat(mBubbleData.getOverflowBubbles()).isEqualTo(ImmutableList.of(b));
|
||||
verify(mNotificationEntryManager, never()).performRemoveNotification(
|
||||
eq(mRow.getSbn()), any(), anyInt());
|
||||
assertThat(mRow.isBubble()).isFalse();
|
||||
|
||||
Bubble b2 = mBubbleData.getBubbleInStackWithKey(mRow2.getKey());
|
||||
assertThat(mBubbleData.getSelectedBubble()).isEqualTo(b2);
|
||||
|
||||
mBubbleController.promoteBubbleFromOverflow(b);
|
||||
|
||||
assertThat(b.isBubble()).isTrue();
|
||||
assertThat(b.shouldAutoExpand()).isTrue();
|
||||
int flags = Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
|
||||
| Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
|
||||
verify(mStatusBarService, times(1)).onNotificationBubbleChanged(
|
||||
eq(b.getKey()), eq(true), eq(flags));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelOverflowBubble() {
|
||||
mBubbleController.updateBubble(mBubbleEntry2);
|
||||
mBubbleController.updateBubble(mBubbleEntry, /* suppressFlyout */
|
||||
false, /* showInShade */ true);
|
||||
when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
|
||||
when(mCommonNotifCollection.getEntry(mRow2.getKey())).thenReturn(mRow2);
|
||||
mBubbleController.removeBubble(
|
||||
mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
|
||||
|
||||
mBubbleController.removeBubble(
|
||||
mRow.getKey(), DISMISS_NOTIF_CANCEL);
|
||||
verify(mNotificationEntryManager, times(1)).performRemoveNotification(
|
||||
eq(mRow.getSbn()), any(), anyInt());
|
||||
assertThat(mBubbleData.getOverflowBubbles()).isEmpty();
|
||||
assertFalse(mRow.isBubble());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserChange_doesNotRemoveNotif() {
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
|
||||
|
||||
// Make it look like dismissed notif
|
||||
mBubbleData.getBubbleInStackWithKey(mRow.getKey()).setSuppressNotification(true);
|
||||
|
||||
// Now remove the bubble
|
||||
mBubbleController.removeBubble(
|
||||
mRow.getKey(), Bubbles.DISMISS_USER_CHANGED);
|
||||
verify(mNotificationEntryManager, never()).performRemoveNotification(
|
||||
eq(mRow.getSbn()), any(), anyInt());
|
||||
mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
|
||||
assertTrue(mBubbleData.hasOverflowBubbleWithKey(mRow.getKey()));
|
||||
|
||||
// We don't remove the notification since the bubble is still in overflow.
|
||||
verify(mNotifCallback, never()).removeNotification(eq(mRow), any(), anyInt());
|
||||
assertFalse(mBubbleController.hasBubbles());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveBubble_withDismissedNotif_notInOverflow() {
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
|
||||
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
|
||||
|
||||
// Make it look like dismissed notif
|
||||
mBubbleData.getBubbleInStackWithKey(mRow.getKey()).setSuppressNotification(true);
|
||||
|
||||
// Now remove the bubble
|
||||
mBubbleController.removeBubble(
|
||||
mRow.getKey(), Bubbles.DISMISS_NOTIF_CANCEL);
|
||||
assertFalse(mBubbleData.hasOverflowBubbleWithKey(mRow.getKey()));
|
||||
|
||||
// Since the notif is dismissed and not in overflow, once the bubble is removed,
|
||||
// removeNotification gets called to really remove the notif
|
||||
verify(mNotifCallback, times(1)).removeNotification(eq(mRow),
|
||||
any(), anyInt());
|
||||
assertFalse(mBubbleController.hasBubbles());
|
||||
assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
|
||||
assertTrue(mRow.isBubble());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDismissStack() {
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
verify(mNotificationEntryManager, times(1)).updateNotifications(any());
|
||||
verify(mNotifCallback, times(1)).invalidateNotifications(anyString());
|
||||
assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
|
||||
mBubbleController.updateBubble(mBubbleEntry2);
|
||||
verify(mNotificationEntryManager, times(2)).updateNotifications(any());
|
||||
verify(mNotifCallback, times(2)).invalidateNotifications(anyString());
|
||||
assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow2.getKey()));
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
|
||||
mBubbleData.dismissAll(Bubbles.DISMISS_USER_GESTURE);
|
||||
verify(mNotificationEntryManager, times(3)).updateNotifications(any());
|
||||
verify(mNotifCallback, times(3)).invalidateNotifications(anyString());
|
||||
assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
|
||||
assertNull(mBubbleData.getBubbleInStackWithKey(mRow2.getKey()));
|
||||
|
||||
@@ -528,7 +472,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
assertStackCollapsed();
|
||||
|
||||
// Mark it as a bubble and add it explicitly
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
// We should have bubbles & their notifs should not be suppressed
|
||||
@@ -536,7 +480,6 @@ public class BubblesTest extends SysuiTestCase {
|
||||
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
|
||||
|
||||
// Expand the stack
|
||||
BubbleStackView stackView = mBubbleController.getStackView();
|
||||
mBubbleData.setExpanded(true);
|
||||
assertStackExpanded();
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
|
||||
@@ -556,8 +499,8 @@ public class BubblesTest extends SysuiTestCase {
|
||||
@Ignore("Currently broken.")
|
||||
public void testCollapseAfterChangingExpandedBubble() {
|
||||
// Mark it as a bubble and add it explicitly
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onPendingEntryAdded(mRow2);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow2);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
mBubbleController.updateBubble(mBubbleEntry2);
|
||||
|
||||
@@ -593,6 +536,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
|
||||
true, mRow.getKey());
|
||||
|
||||
|
||||
// Collapse
|
||||
mBubbleController.collapseStack();
|
||||
assertStackCollapsed();
|
||||
@@ -602,7 +546,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testExpansionRemovesShowInShadeAndDot() {
|
||||
// Mark it as a bubble and add it explicitly
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
// We should have bubbles & their notifs should not be suppressed
|
||||
@@ -627,7 +571,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testUpdateWhileExpanded_DoesntChangeShowInShadeAndDot() {
|
||||
// Mark it as a bubble and add it explicitly
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
// We should have bubbles & their notifs should not be suppressed
|
||||
@@ -649,7 +593,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
|
||||
|
||||
// Send update
|
||||
mEntryListener.onPreEntryUpdated(mRow);
|
||||
mEntryListener.onEntryUpdated(mRow);
|
||||
|
||||
// Nothing should have changed
|
||||
// Notif is suppressed after expansion
|
||||
@@ -661,8 +605,8 @@ public class BubblesTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testRemoveLastExpanded_collapses() {
|
||||
// Mark it as a bubble and add it explicitly
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onPendingEntryAdded(mRow2);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow2);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
mBubbleController.updateBubble(mBubbleEntry2);
|
||||
|
||||
@@ -707,7 +651,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testRemoveLastExpandedEmptyOverflow_collapses() {
|
||||
// Mark it as a bubble and add it explicitly
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
// Expand
|
||||
@@ -732,6 +676,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAutoExpand_fails_noFlag() {
|
||||
assertStackCollapsed();
|
||||
@@ -739,7 +684,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, false /* enableFlag */);
|
||||
|
||||
// Add the auto expand bubble
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
// Expansion shouldn't change
|
||||
@@ -755,7 +700,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, true /* enableFlag */);
|
||||
|
||||
// Add the auto expand bubble
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
// Expansion should change
|
||||
@@ -771,7 +716,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, true /* enableFlag */);
|
||||
|
||||
// Add the suppress notif bubble
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
// Notif should be suppressed because we were foreground
|
||||
@@ -804,23 +749,9 @@ public class BubblesTest extends SysuiTestCase {
|
||||
assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandStackAndSelectBubble_removedFirst() {
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
// Simulate notification cancellation.
|
||||
mRemoveInterceptor.onNotificationRemoveRequested(
|
||||
mRow.getKey(), mRow, REASON_APP_CANCEL);
|
||||
|
||||
mBubbleController.expandStackAndSelectBubble(mBubbleEntry);
|
||||
|
||||
assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarkNewNotificationAsShowInShade() {
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
@@ -829,8 +760,8 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testAddNotif_notBubble() {
|
||||
mEntryListener.onPendingEntryAdded(mNonBubbleNotifRow.getEntry());
|
||||
mEntryListener.onPreEntryUpdated(mNonBubbleNotifRow.getEntry());
|
||||
mEntryListener.onEntryAdded(mNonBubbleNotifRow.getEntry());
|
||||
mEntryListener.onEntryUpdated(mNonBubbleNotifRow.getEntry());
|
||||
|
||||
assertThat(mBubbleController.hasBubbles()).isFalse();
|
||||
}
|
||||
@@ -868,48 +799,33 @@ public class BubblesTest extends SysuiTestCase {
|
||||
NotificationListenerService.Ranking ranking = new RankingBuilder(
|
||||
mRow.getRanking()).setCanBubble(false).build();
|
||||
mRow.setRanking(ranking);
|
||||
mEntryListener.onPreEntryUpdated(mRow);
|
||||
mEntryListener.onEntryUpdated(mRow);
|
||||
|
||||
assertFalse(mBubbleController.hasBubbles());
|
||||
verify(mDeleteIntent, never()).send();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveBubble_succeeds_appCancel() {
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
|
||||
boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
|
||||
mRow.getKey(), mRow, REASON_APP_CANCEL);
|
||||
|
||||
// Cancels always remove so no need to intercept
|
||||
assertFalse(intercepted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveBubble_entryListenerRemove() {
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
|
||||
// Removes the notification
|
||||
mEntryListener.onEntryRemoved(mRow, null, false, REASON_APP_CANCEL);
|
||||
mEntryListener.onEntryRemoved(mRow, REASON_APP_CANCEL);
|
||||
assertFalse(mBubbleController.hasBubbles());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeBubble_clearAllIntercepted() {
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
public void removeBubble_intercepted() {
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
|
||||
|
||||
boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
|
||||
mRow.getKey(), mRow, REASON_CANCEL_ALL);
|
||||
boolean intercepted = mBubblesManager.handleDismissalInterception(mRow);
|
||||
|
||||
// Intercept!
|
||||
assertTrue(intercepted);
|
||||
@@ -918,99 +834,51 @@ public class BubblesTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeBubble_userDismissNotifIntercepted() {
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
public void removeBubble_dismissIntoOverflow_intercepted() {
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
|
||||
|
||||
boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
|
||||
mRow.getKey(), mRow, REASON_CANCEL);
|
||||
|
||||
// Intercept!
|
||||
assertTrue(intercepted);
|
||||
// Should update show in shade state
|
||||
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeNotif_inOverflow_intercepted() {
|
||||
// Get bubble with notif in shade.
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
|
||||
|
||||
// Dismiss the bubble into overflow.
|
||||
mBubbleController.removeBubble(
|
||||
mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
|
||||
// Dismiss the bubble
|
||||
mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
|
||||
assertFalse(mBubbleController.hasBubbles());
|
||||
|
||||
boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
|
||||
mRow.getKey(), mRow, REASON_CANCEL);
|
||||
// Dismiss the notification
|
||||
boolean intercepted = mBubblesManager.handleDismissalInterception(mRow);
|
||||
|
||||
// Notif is no longer a bubble, but still in overflow, so we intercept removal.
|
||||
// Intercept dismissal since bubble is going into overflow
|
||||
assertTrue(intercepted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeNotif_notInOverflow_notIntercepted() {
|
||||
// Get bubble with notif in shade.
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
public void removeBubble_notIntercepted() {
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
|
||||
|
||||
mBubbleController.removeBubble(
|
||||
mRow.getKey(), Bubbles.DISMISS_NO_LONGER_BUBBLE);
|
||||
// Dismiss the bubble
|
||||
mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_NOTIF_CANCEL);
|
||||
assertFalse(mBubbleController.hasBubbles());
|
||||
|
||||
boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
|
||||
mRow.getKey(), mRow, REASON_CANCEL);
|
||||
// Dismiss the notification
|
||||
boolean intercepted = mBubblesManager.handleDismissalInterception(mRow);
|
||||
|
||||
// Notif is no longer a bubble, so we should not intercept removal.
|
||||
// Not a bubble anymore so we don't intercept dismissal.
|
||||
assertFalse(intercepted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverflowBubble_maxReached_notInShade_bubbleRemoved() {
|
||||
mBubbleController.updateBubble(
|
||||
mBubbleEntry, /* suppressFlyout */ false, /* showInShade */ false);
|
||||
mBubbleController.updateBubble(
|
||||
mBubbleEntry2, /* suppressFlyout */ false, /* showInShade */ false);
|
||||
mBubbleController.updateBubble(
|
||||
mBubbleEntry3, /* suppressFlyout */ false, /* showInShade */ false);
|
||||
when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
|
||||
when(mCommonNotifCollection.getEntry(mRow2.getKey())).thenReturn(mRow2);
|
||||
when(mCommonNotifCollection.getEntry(mRow3.getKey())).thenReturn(mRow3);
|
||||
assertEquals(mBubbleData.getBubbles().size(), 3);
|
||||
|
||||
mBubbleData.setMaxOverflowBubbles(1);
|
||||
mBubbleController.removeBubble(
|
||||
mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
|
||||
assertEquals(mBubbleData.getBubbles().size(), 2);
|
||||
assertEquals(mBubbleData.getOverflowBubbles().size(), 1);
|
||||
|
||||
mBubbleController.removeBubble(
|
||||
mRow2.getKey(), Bubbles.DISMISS_USER_GESTURE);
|
||||
// Overflow max of 1 is reached; mRow is oldest, so it gets removed
|
||||
verify(mNotificationEntryManager, times(1)).performRemoveNotification(
|
||||
eq(mRow.getSbn()), any(), eq(REASON_CANCEL));
|
||||
assertEquals(mBubbleData.getBubbles().size(), 1);
|
||||
assertEquals(mBubbleData.getOverflowBubbles().size(), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyShadeSuppressionChange_notificationDismiss() {
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
|
||||
|
||||
mRemoveInterceptor.onNotificationRemoveRequested(
|
||||
mRow.getKey(), mRow, REASON_CANCEL);
|
||||
mBubblesManager.handleDismissalInterception(mRow);
|
||||
|
||||
// Should update show in shade state
|
||||
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
|
||||
@@ -1022,7 +890,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testNotifyShadeSuppressionChange_bubbleExpanded() {
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
|
||||
@@ -1042,9 +910,9 @@ public class BubblesTest extends SysuiTestCase {
|
||||
// GIVEN a group summary with a bubble child
|
||||
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
|
||||
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
||||
mEntryListener.onEntryAdded(groupedBubble.getEntry());
|
||||
when(mCommonNotifCollection.getEntry(groupedBubble.getEntry().getKey()))
|
||||
.thenReturn(groupedBubble.getEntry());
|
||||
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
|
||||
groupSummary.addChildNotification(groupedBubble);
|
||||
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
||||
|
||||
@@ -1054,10 +922,10 @@ 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().getSbn().getGroupKey()));
|
||||
assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
|
||||
groupedBubble.getEntry().getKey(),
|
||||
groupSummary.getEntry().getSbn().getGroupKey()));
|
||||
groupedBubble.getEntry().getSbn().getGroupKey()));
|
||||
assertTrue(mBubbleData.isSummarySuppressed(groupSummary.getEntry().getSbn().getGroupKey()));
|
||||
}
|
||||
|
||||
@@ -1066,7 +934,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
// GIVEN a group summary with a bubble child
|
||||
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
|
||||
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
||||
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
|
||||
mEntryListener.onEntryAdded(groupedBubble.getEntry());
|
||||
when(mCommonNotifCollection.getEntry(groupedBubble.getEntry().getKey()))
|
||||
.thenReturn(groupedBubble.getEntry());
|
||||
groupSummary.addChildNotification(groupedBubble);
|
||||
@@ -1076,7 +944,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
mBubblesManager.handleDismissalInterception(groupSummary.getEntry());
|
||||
|
||||
// WHEN the summary is cancelled by the app
|
||||
mEntryListener.onEntryRemoved(groupSummary.getEntry(), null, false, REASON_APP_CANCEL);
|
||||
mEntryListener.onEntryRemoved(groupSummary.getEntry(), REASON_APP_CANCEL);
|
||||
|
||||
// THEN the summary and its children are removed from bubble data
|
||||
assertFalse(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
||||
@@ -1085,14 +953,14 @@ public class BubblesTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSummaryDismissal_marksBubblesHiddenFromShadeAndDismissesNonBubbledChildren()
|
||||
public void testSummaryDismissalMarksBubblesHiddenFromShadeAndDismissesNonBubbledChildren()
|
||||
throws Exception {
|
||||
// GIVEN a group summary with two (non-bubble) children and one bubble child
|
||||
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
|
||||
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
||||
mEntryListener.onEntryAdded(groupedBubble.getEntry());
|
||||
when(mCommonNotifCollection.getEntry(groupedBubble.getEntry().getKey()))
|
||||
.thenReturn(groupedBubble.getEntry());
|
||||
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
|
||||
groupSummary.addChildNotification(groupedBubble);
|
||||
|
||||
// WHEN the summary is dismissed
|
||||
@@ -1100,16 +968,15 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
// THEN only the NON-bubble children are dismissed
|
||||
List<ExpandableNotificationRow> childrenRows = groupSummary.getAttachedChildren();
|
||||
verify(mNotificationEntryManager, times(1)).performRemoveNotification(
|
||||
eq(childrenRows.get(0).getEntry().getSbn()), any(),
|
||||
eq(REASON_GROUP_SUMMARY_CANCELED));
|
||||
verify(mNotificationEntryManager, times(1)).performRemoveNotification(
|
||||
eq(childrenRows.get(1).getEntry().getSbn()), any(),
|
||||
eq(REASON_GROUP_SUMMARY_CANCELED));
|
||||
verify(mNotificationEntryManager, never()).performRemoveNotification(
|
||||
eq(groupedBubble.getEntry().getSbn()), any(), anyInt());
|
||||
verify(mNotifCallback, times(1)).removeNotification(
|
||||
eq(childrenRows.get(0).getEntry()), any(), eq(REASON_GROUP_SUMMARY_CANCELED));
|
||||
verify(mNotifCallback, times(1)).removeNotification(
|
||||
eq(childrenRows.get(1).getEntry()), any(), eq(REASON_GROUP_SUMMARY_CANCELED));
|
||||
verify(mNotifCallback, never()).removeNotification(eq(groupedBubble.getEntry()),
|
||||
any(), anyInt());
|
||||
|
||||
// THEN the bubble child is suppressed from the shade
|
||||
// THEN the bubble child still exists as a bubble and is suppressed from the shade
|
||||
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
||||
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
||||
groupedBubble.getEntry().getKey(),
|
||||
groupedBubble.getEntry().getSbn().getGroupKey()));
|
||||
@@ -1117,33 +984,16 @@ public class BubblesTest extends SysuiTestCase {
|
||||
groupedBubble.getEntry().getKey(),
|
||||
groupedBubble.getEntry().getSbn().getGroupKey()));
|
||||
|
||||
// THEN the summary is removed from GroupManager
|
||||
verify(mNotificationGroupManager, times(1)).onEntryRemoved(groupSummary.getEntry());
|
||||
// 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()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that when a non visually interruptive update occurs for a bubble in the overflow,
|
||||
* the that bubble does not get promoted from the overflow.
|
||||
*/
|
||||
@Test
|
||||
public void test_notVisuallyInterruptive_updateOverflowBubble_notAdded() {
|
||||
// Setup
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
mBubbleController.updateBubble(mBubbleEntry2);
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
|
||||
// Overflow it
|
||||
mBubbleData.dismissBubbleWithKey(mRow.getKey(),
|
||||
Bubbles.DISMISS_USER_GESTURE);
|
||||
assertThat(mBubbleData.hasBubbleInStackWithKey(mRow.getKey())).isFalse();
|
||||
assertThat(mBubbleData.hasOverflowBubbleWithKey(mRow.getKey())).isTrue();
|
||||
|
||||
// Test
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
assertThat(mBubbleData.hasBubbleInStackWithKey(mRow.getKey())).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that when the user changes, the bubbles in the overflow list is cleared. Doesn't
|
||||
* test the loading from the repository which would be a nice thing to add.
|
||||
@@ -1185,15 +1035,17 @@ public class BubblesTest extends SysuiTestCase {
|
||||
*/
|
||||
@Test
|
||||
public void testOverflowLoadedOnce() {
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
mBubbleController.updateBubble(mBubbleEntry2);
|
||||
mBubbleData.dismissAll(Bubbles.DISMISS_USER_GESTURE);
|
||||
assertThat(mBubbleData.getOverflowBubbles().isEmpty()).isFalse();
|
||||
// XXX
|
||||
when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
|
||||
when(mCommonNotifCollection.getEntry(mRow2.getKey())).thenReturn(mRow2);
|
||||
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
mBubbleController.updateBubble(mBubbleEntry2);
|
||||
mBubbleController.removeBubble(mBubbleEntry.getKey(), DISMISS_NOTIF_CANCEL);
|
||||
mBubbleController.removeBubble(mBubbleEntry2.getKey(), DISMISS_NOTIF_CANCEL);
|
||||
mEntryListener.onEntryAdded(mRow);
|
||||
mEntryListener.onEntryAdded(mRow2);
|
||||
mBubbleData.dismissAll(Bubbles.DISMISS_USER_GESTURE);
|
||||
assertThat(mBubbleData.getOverflowBubbles()).isNotEmpty();
|
||||
|
||||
mEntryListener.onEntryRemoved(mRow, REASON_APP_CANCEL);
|
||||
mEntryListener.onEntryRemoved(mRow2, REASON_APP_CANCEL);
|
||||
assertThat(mBubbleData.getOverflowBubbles()).isEmpty();
|
||||
|
||||
verify(mDataRepository, times(1)).loadBubbles(anyInt(), any());
|
||||
@@ -1376,6 +1228,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
assertStackCollapsed();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRegisterUnregisterBroadcastListener() {
|
||||
spyOn(mContext);
|
||||
@@ -1455,7 +1308,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testSetShouldAutoExpand_notifiesFlagChanged() {
|
||||
mEntryListener.onPendingEntryAdded(mRow);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
Bubble b = mBubbleData.getBubbleInStackWithKey(mBubbleEntry.getKey());
|
||||
@@ -1551,7 +1404,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bubble metadata flags for this entry. These ]flags are normally set by
|
||||
* Sets the bubble metadata flags for this entry. These flags are normally set by
|
||||
* NotificationManagerService when the notification is sent, however, these tests do not
|
||||
* go through that path so we set them explicitly when testing.
|
||||
*/
|
||||
@@ -1570,12 +1423,15 @@ public class BubblesTest extends SysuiTestCase {
|
||||
private Notification.BubbleMetadata getMetadata() {
|
||||
Intent target = new Intent(mContext, BubblesTestActivity.class);
|
||||
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, FLAG_MUTABLE);
|
||||
|
||||
return new Notification.BubbleMetadata.Builder(bubbleIntent,
|
||||
Icon.createWithResource(mContext, R.drawable.bubble_ic_create_bubble))
|
||||
return new Notification.BubbleMetadata.Builder(
|
||||
bubbleIntent,
|
||||
Icon.createWithResource(
|
||||
mContext,
|
||||
com.android.wm.shell.R.drawable.bubble_ic_create_bubble))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asserts that the bubble stack is expanded and also validates the cached state is updated.
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user