blob: 5b46b7fa4d9ff93bda116205838d66b40ec115f6 [file] [log] [blame]
Mady Mellorebdbbb92018-11-15 14:36:48 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.bubbles;
18
Mady Melloraa8fef22019-04-11 13:36:40 -070019import static android.app.Notification.FLAG_BUBBLE;
Mady Mellorc2ff0112019-03-28 14:18:06 -070020import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
21import static android.service.notification.NotificationListenerService.REASON_CANCEL;
22import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
Beverlya53fb0d2020-01-29 15:26:13 -050023import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
Mady Mellor1a4e86f2019-05-03 16:07:23 -070024
Mady Mellorfc02cc32019-04-01 14:47:55 -070025import static com.google.common.truth.Truth.assertThat;
26
Mady Melloredd4ee12019-01-18 10:45:11 -080027import static org.junit.Assert.assertEquals;
Mady Mellorebdbbb92018-11-15 14:36:48 -080028import static org.junit.Assert.assertFalse;
Mady Mellored99c272019-06-13 15:58:30 -070029import static org.junit.Assert.assertNotNull;
30import static org.junit.Assert.assertNull;
Mady Mellorebdbbb92018-11-15 14:36:48 -080031import static org.junit.Assert.assertTrue;
Mady Mellorc2ff0112019-03-28 14:18:06 -070032import static org.mockito.ArgumentMatchers.any;
Mady Mellorc2ff0112019-03-28 14:18:06 -070033import static org.mockito.ArgumentMatchers.anyInt;
Beverly85d4c192019-09-30 11:40:39 -040034import static org.mockito.ArgumentMatchers.anyString;
Beverlya53fb0d2020-01-29 15:26:13 -050035import static org.mockito.ArgumentMatchers.eq;
Ned Burns01e38212019-01-03 16:32:52 -050036import static org.mockito.Mockito.atLeastOnce;
Mady Melloraa8fef22019-04-11 13:36:40 -070037import static org.mockito.Mockito.mock;
Mark Renouf08bc42a2019-03-07 13:01:59 -050038import static org.mockito.Mockito.never;
39import static org.mockito.Mockito.times;
Ned Burns01e38212019-01-03 16:32:52 -050040import static org.mockito.Mockito.verify;
41import static org.mockito.Mockito.when;
Mady Mellorebdbbb92018-11-15 14:36:48 -080042
43import android.app.IActivityManager;
Mady Mellor9adfe6a2020-03-30 17:23:26 -070044import android.app.INotificationManager;
Mady Mellore80930e2019-03-21 16:00:45 -070045import android.app.Notification;
Mark Renouf08bc42a2019-03-07 13:01:59 -050046import android.app.PendingIntent;
Joshua Tsuji33477392020-06-19 18:35:35 -040047import android.content.pm.LauncherApps;
Beverly Taid1e175c2020-03-10 16:37:04 +000048import android.hardware.display.AmbientDisplayConfiguration;
Mady Mellor80c25b22019-06-17 14:40:37 -070049import android.hardware.face.FaceManager;
Beverly Taid1e175c2020-03-10 16:37:04 +000050import android.os.Handler;
51import android.os.PowerManager;
52import android.service.dreams.IDreamManager;
Mady Mellor76343012020-05-13 11:02:50 -070053import android.service.notification.NotificationListenerService;
Joshua Tsujidd4d9f92019-05-13 13:57:38 -040054import android.service.notification.ZenModeConfig;
Mady Mellorebdbbb92018-11-15 14:36:48 -080055import android.testing.AndroidTestingRunner;
56import android.testing.TestableLooper;
57import android.view.WindowManager;
Mady Mellorebdbbb92018-11-15 14:36:48 -080058
Brett Chabot84151d92019-02-27 15:37:59 -080059import androidx.test.filters.SmallTest;
60
Dave Mankoff2aff6c32019-10-14 17:40:37 -040061import com.android.internal.colorextraction.ColorExtractor;
Mady Mellor458a6262020-06-07 21:09:19 -070062import com.android.internal.statusbar.IStatusBarService;
Mady Mellorebdbbb92018-11-15 14:36:48 -080063import com.android.systemui.SysuiTestCase;
Dave Mankoff2aff6c32019-10-14 17:40:37 -040064import com.android.systemui.colorextraction.SysuiColorExtractor;
Ned Burnsaaeb44b2020-02-12 23:48:26 -050065import com.android.systemui.dump.DumpManager;
Joshua Tsujibe60a582020-03-23 17:17:26 -040066import com.android.systemui.model.SysUiState;
Mady Mellorc55b4122019-06-07 18:14:02 -070067import com.android.systemui.plugins.statusbar.StatusBarStateController;
Joshua Tsujibe60a582020-03-23 17:17:26 -040068import com.android.systemui.shared.system.QuickStepContract;
Beverlya53fb0d2020-01-29 15:26:13 -050069import com.android.systemui.statusbar.FeatureFlags;
Mark Renoufc19b4732019-06-26 12:08:33 -040070import com.android.systemui.statusbar.NotificationLockscreenUserManager;
Mady Mellorc2ff0112019-03-28 14:18:06 -070071import com.android.systemui.statusbar.NotificationRemoveInterceptor;
Mady Mellor76343012020-05-13 11:02:50 -070072import com.android.systemui.statusbar.RankingBuilder;
Lucas Dupine25c4872019-07-29 13:51:35 -070073import com.android.systemui.statusbar.SysuiStatusBarStateController;
Ned Burns01e38212019-01-03 16:32:52 -050074import com.android.systemui.statusbar.notification.NotificationEntryListener;
75import com.android.systemui.statusbar.notification.NotificationEntryManager;
Mady Mellorc55b4122019-06-07 18:14:02 -070076import com.android.systemui.statusbar.notification.NotificationFilter;
Beverlya53fb0d2020-01-29 15:26:13 -050077import com.android.systemui.statusbar.notification.collection.NotifPipeline;
Mady Mellor8d25b202019-06-25 13:59:28 -070078import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Mady Mellorebdbbb92018-11-15 14:36:48 -080079import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
Kevin Han933dc7c2020-01-29 11:17:46 -080080import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
Mady Mellorebdbbb92018-11-15 14:36:48 -080081import com.android.systemui.statusbar.phone.DozeParameters;
Lucas Dupine25c4872019-07-29 13:51:35 -070082import com.android.systemui.statusbar.phone.KeyguardBypassController;
Ned Burns296aec162019-09-04 17:30:59 -040083import com.android.systemui.statusbar.phone.NotificationGroupManager;
wilsonshihe8321942019-10-18 18:39:46 +080084import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
Fabian Kozynskib00c70b2020-04-03 12:41:31 -040085import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
Mady Mellor7f234902019-10-20 12:06:29 -070086import com.android.systemui.statusbar.phone.ShadeController;
Lucas Dupinbd7366d2019-09-25 13:39:21 -070087import com.android.systemui.statusbar.policy.BatteryController;
Lyn Hanf1c9b8b2019-03-14 16:49:48 -070088import com.android.systemui.statusbar.policy.ConfigurationController;
Mady Melloraa8fef22019-04-11 13:36:40 -070089import com.android.systemui.statusbar.policy.HeadsUpManager;
Joshua Tsujidd4d9f92019-05-13 13:57:38 -040090import com.android.systemui.statusbar.policy.ZenModeController;
Joshua Tsuji7155bf12020-02-13 16:14:29 -050091import com.android.systemui.util.FloatingContentCoordinator;
Mady Mellorebdbbb92018-11-15 14:36:48 -080092
Lyn Han89274b42020-03-25 00:56:26 -070093import com.google.common.collect.ImmutableList;
94
Mady Mellorebdbbb92018-11-15 14:36:48 -080095import org.junit.Before;
Josh Tsuji72e12cb2020-06-12 16:49:33 -040096import org.junit.Ignore;
Mady Mellorebdbbb92018-11-15 14:36:48 -080097import org.junit.Test;
98import org.junit.runner.RunWith;
Ned Burns01e38212019-01-03 16:32:52 -050099import org.mockito.ArgumentCaptor;
100import org.mockito.Captor;
Mady Mellorebdbbb92018-11-15 14:36:48 -0800101import org.mockito.Mock;
102import org.mockito.MockitoAnnotations;
103
Beverlya53fb0d2020-01-29 15:26:13 -0500104import java.util.List;
105
106/**
107 * Tests the NotificationEntryManager setup with BubbleController.
108 * The {@link NotifPipeline} setup with BubbleController is tested in
109 * {@link NewNotifPipelineBubbleControllerTest}.
110 */
Mady Mellorebdbbb92018-11-15 14:36:48 -0800111@SmallTest
112@RunWith(AndroidTestingRunner.class)
113@TestableLooper.RunWithLooper(setAsMainLooper = true)
114public class BubbleControllerTest extends SysuiTestCase {
Mady Mellorebdbbb92018-11-15 14:36:48 -0800115 @Mock
Ned Burns01e38212019-01-03 16:32:52 -0500116 private NotificationEntryManager mNotificationEntryManager;
117 @Mock
Mady Mellor22f2f072019-04-18 13:26:18 -0700118 private NotificationGroupManager mNotificationGroupManager;
119 @Mock
Mady Mellorebdbbb92018-11-15 14:36:48 -0800120 private WindowManager mWindowManager;
121 @Mock
122 private IActivityManager mActivityManager;
123 @Mock
124 private DozeParameters mDozeParameters;
Lyn Hanf1c9b8b2019-03-14 16:49:48 -0700125 @Mock
126 private ConfigurationController mConfigurationController;
Joshua Tsujidd4d9f92019-05-13 13:57:38 -0400127 @Mock
128 private ZenModeController mZenModeController;
129 @Mock
130 private ZenModeConfig mZenModeConfig;
Mady Mellor80c25b22019-06-17 14:40:37 -0700131 @Mock
132 private FaceManager mFaceManager;
Mark Renoufc19b4732019-06-26 12:08:33 -0400133 @Mock
134 private NotificationLockscreenUserManager mLockscreenUserManager;
Mady Mellorf474e0d2019-08-01 11:08:40 -0700135 @Mock
Lucas Dupine25c4872019-07-29 13:51:35 -0700136 private SysuiStatusBarStateController mStatusBarStateController;
137 @Mock
138 private KeyguardBypassController mKeyguardBypassController;
Joshua Tsuji7155bf12020-02-13 16:14:29 -0500139 @Mock
140 private FloatingContentCoordinator mFloatingContentCoordinator;
Pinyao Tingee191b12020-04-29 18:35:39 -0700141 @Mock
142 private BubbleDataRepository mDataRepository;
Lyn Hanf1c9b8b2019-03-14 16:49:48 -0700143
Joshua Tsujibe60a582020-03-23 17:17:26 -0400144 private SysUiState mSysUiState;
145 private boolean mSysUiStateBubblesExpanded;
146
Ned Burns01e38212019-01-03 16:32:52 -0500147 @Captor
148 private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
Mady Mellorc2ff0112019-03-28 14:18:06 -0700149 @Captor
150 private ArgumentCaptor<NotificationRemoveInterceptor> mRemoveInterceptorCaptor;
Mady Mellorebdbbb92018-11-15 14:36:48 -0800151
152 private TestableBubbleController mBubbleController;
wilsonshihe8321942019-10-18 18:39:46 +0800153 private NotificationShadeWindowController mNotificationShadeWindowController;
Ned Burns01e38212019-01-03 16:32:52 -0500154 private NotificationEntryListener mEntryListener;
Mady Mellorc2ff0112019-03-28 14:18:06 -0700155 private NotificationRemoveInterceptor mRemoveInterceptor;
Mady Mellorebdbbb92018-11-15 14:36:48 -0800156
157 private NotificationTestHelper mNotificationTestHelper;
158 private ExpandableNotificationRow mRow;
159 private ExpandableNotificationRow mRow2;
Lyn Han2f6e89d2020-04-15 10:01:01 -0700160 private ExpandableNotificationRow mRow3;
Mady Mellorfc02cc32019-04-01 14:47:55 -0700161 private ExpandableNotificationRow mNonBubbleNotifRow;
Mady Mellorebdbbb92018-11-15 14:36:48 -0800162
Mady Mellorb4991e62019-01-10 15:14:51 -0800163 @Mock
Mady Melloracb12152019-01-29 15:24:48 -0800164 private BubbleController.BubbleExpandListener mBubbleExpandListener;
Mark Renouf6b2331c2019-03-21 13:40:08 -0400165 @Mock
Mark Renouf08bc42a2019-03-07 13:01:59 -0500166 private PendingIntent mDeleteIntent;
Dave Mankoff2aff6c32019-10-14 17:40:37 -0400167 @Mock
168 private SysuiColorExtractor mColorExtractor;
169 @Mock
170 ColorExtractor.GradientColors mGradientColors;
Heemin Seogafb3dbc2019-11-04 16:05:19 -0800171 @Mock
Heemin Seogba6337f2019-12-10 15:34:37 -0800172 private ShadeController mShadeController;
Aran Inkaa4dfa72019-11-18 16:49:07 -0500173 @Mock
Beverlya53fb0d2020-01-29 15:26:13 -0500174 private NotifPipeline mNotifPipeline;
175 @Mock
176 private FeatureFlags mFeatureFlagsOldPipeline;
177 @Mock
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500178 private DumpManager mDumpManager;
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500179 @Mock
Fabian Kozynskib00c70b2020-04-03 12:41:31 -0400180 private NotificationShadeWindowView mNotificationShadeWindowView;
Mady Mellor458a6262020-06-07 21:09:19 -0700181 @Mock
182 private IStatusBarService mStatusBarService;
Joshua Tsuji33477392020-06-19 18:35:35 -0400183 @Mock
184 private LauncherApps mLauncherApps;
Mark Renouf08bc42a2019-03-07 13:01:59 -0500185
Mady Mellorcfd06c12019-02-13 14:32:12 -0800186 private BubbleData mBubbleData;
187
Mady Mellorb8aaf972019-11-26 10:28:00 -0800188 private TestableLooper mTestableLooper;
189
Mady Mellorebdbbb92018-11-15 14:36:48 -0800190 @Before
191 public void setUp() throws Exception {
192 MockitoAnnotations.initMocks(this);
Mady Mellorb8aaf972019-11-26 10:28:00 -0800193
194 mTestableLooper = TestableLooper.get(this);
195
Mady Mellor80c25b22019-06-17 14:40:37 -0700196 mContext.addMockSystemService(FaceManager.class, mFaceManager);
Dave Mankoff2aff6c32019-10-14 17:40:37 -0400197 when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800198
wilsonshihe8321942019-10-18 18:39:46 +0800199 mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
200 mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
Lucas Dupind73410a2020-02-18 12:54:41 -0800201 mConfigurationController, mKeyguardBypassController, mColorExtractor,
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500202 mDumpManager);
Fabian Kozynskib00c70b2020-04-03 12:41:31 -0400203 mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
wilsonshihe8321942019-10-18 18:39:46 +0800204 mNotificationShadeWindowController.attach();
Mady Mellorebdbbb92018-11-15 14:36:48 -0800205
206 // Need notifications for bubbles
Kevin Hana7c21be2020-04-01 17:58:35 -0700207 mNotificationTestHelper = new NotificationTestHelper(
208 mContext,
209 mDependency,
210 TestableLooper.get(this));
Mark Renouf08bc42a2019-03-07 13:01:59 -0500211 mRow = mNotificationTestHelper.createBubble(mDeleteIntent);
212 mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700213 mRow3 = mNotificationTestHelper.createBubble(mDeleteIntent);
Mady Mellorfc02cc32019-04-01 14:47:55 -0700214 mNonBubbleNotifRow = mNotificationTestHelper.createRow();
Mady Mellor3ed46202019-03-26 20:22:35 -0700215
Ned Burns01e38212019-01-03 16:32:52 -0500216 // Return non-null notification data from the NEM
Evan Laird181de622019-10-24 09:53:02 -0400217 when(mNotificationEntryManager
218 .getActiveNotificationUnfiltered(mRow.getEntry().getKey())).thenReturn(
219 mRow.getEntry());
Ned Burns01e38212019-01-03 16:32:52 -0500220
Joshua Tsujidd4d9f92019-05-13 13:57:38 -0400221 mZenModeConfig.suppressedVisualEffects = 0;
222 when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
223
Joshua Tsujibe60a582020-03-23 17:17:26 -0400224 mSysUiState = new SysUiState();
225 mSysUiState.addCallback(sysUiFlags ->
226 mSysUiStateBubblesExpanded =
227 (sysUiFlags & QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED) != 0);
228
Beverly Taid1e175c2020-03-10 16:37:04 +0000229 TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
230 new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
231 mock(PowerManager.class),
232 mock(IDreamManager.class),
233 mock(AmbientDisplayConfiguration.class),
Mady Mellorc55b4122019-06-07 18:14:02 -0700234 mock(NotificationFilter.class),
Lucas Dupinbd7366d2019-09-25 13:39:21 -0700235 mock(StatusBarStateController.class),
Beverly Taid1e175c2020-03-10 16:37:04 +0000236 mock(BatteryController.class),
237 mock(HeadsUpManager.class),
238 mock(Handler.class)
239 );
Mark Renouf71a3af62019-04-08 15:02:54 -0400240 mBubbleData = new BubbleData(mContext);
Beverlya53fb0d2020-01-29 15:26:13 -0500241 when(mFeatureFlagsOldPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500242 mBubbleController = new TestableBubbleController(
243 mContext,
wilsonshihe8321942019-10-18 18:39:46 +0800244 mNotificationShadeWindowController,
Mady Mellor7f234902019-10-20 12:06:29 -0700245 mStatusBarStateController,
246 mShadeController,
Mady Mellor22f2f072019-04-18 13:26:18 -0700247 mBubbleData,
248 mConfigurationController,
249 interruptionStateProvider,
250 mZenModeController,
251 mLockscreenUserManager,
Mady Mellor7f234902019-10-20 12:06:29 -0700252 mNotificationGroupManager,
Beverlya53fb0d2020-01-29 15:26:13 -0500253 mNotificationEntryManager,
254 mNotifPipeline,
255 mFeatureFlagsOldPipeline,
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500256 mDumpManager,
Joshua Tsujibe60a582020-03-23 17:17:26 -0400257 mFloatingContentCoordinator,
Pinyao Tingee191b12020-04-29 18:35:39 -0700258 mDataRepository,
Mady Mellor9adfe6a2020-03-30 17:23:26 -0700259 mSysUiState,
Mady Mellor59a7b982020-05-11 15:19:59 -0700260 mock(INotificationManager.class),
Mady Mellor458a6262020-06-07 21:09:19 -0700261 mStatusBarService,
Joshua Tsuji33477392020-06-19 18:35:35 -0400262 mWindowManager,
263 mLauncherApps);
Mady Melloracb12152019-01-29 15:24:48 -0800264 mBubbleController.setExpandListener(mBubbleExpandListener);
Ned Burns01e38212019-01-03 16:32:52 -0500265
266 // Get a reference to the BubbleController's entry listener
267 verify(mNotificationEntryManager, atLeastOnce())
268 .addNotificationEntryListener(mEntryListenerCaptor.capture());
269 mEntryListener = mEntryListenerCaptor.getValue();
Mady Mellorc2ff0112019-03-28 14:18:06 -0700270 // And the remove interceptor
271 verify(mNotificationEntryManager, atLeastOnce())
Evan Laird04373662020-01-24 17:37:39 -0500272 .addNotificationRemoveInterceptor(mRemoveInterceptorCaptor.capture());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700273 mRemoveInterceptor = mRemoveInterceptorCaptor.getValue();
Mady Mellorebdbbb92018-11-15 14:36:48 -0800274 }
275
276 @Test
Mady Mellorebdbbb92018-11-15 14:36:48 -0800277 public void testAddBubble() {
Mark Renouff97ed462019-04-05 13:46:24 -0400278 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800279 assertTrue(mBubbleController.hasBubbles());
Mady Melloracb12152019-01-29 15:24:48 -0800280
Joshua Tsujibe60a582020-03-23 17:17:26 -0400281 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800282 }
283
284 @Test
285 public void testHasBubbles() {
286 assertFalse(mBubbleController.hasBubbles());
Mark Renouff97ed462019-04-05 13:46:24 -0400287 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800288 assertTrue(mBubbleController.hasBubbles());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400289 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800290 }
291
292 @Test
293 public void testRemoveBubble() {
Mark Renouff97ed462019-04-05 13:46:24 -0400294 mBubbleController.updateBubble(mRow.getEntry());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700295 assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Mady Mellorebdbbb92018-11-15 14:36:48 -0800296 assertTrue(mBubbleController.hasBubbles());
Beverly85d4c192019-09-30 11:40:39 -0400297 verify(mNotificationEntryManager).updateNotifications(any());
Mady Melloracb12152019-01-29 15:24:48 -0800298
Ned Burns00b4b2d2019-10-17 22:09:27 -0400299 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000300 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700301 assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Beverly85d4c192019-09-30 11:40:39 -0400302 verify(mNotificationEntryManager, times(2)).updateNotifications(anyString());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400303
304 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800305 }
306
307 @Test
Mady Mellor458a6262020-06-07 21:09:19 -0700308 public void testPromoteBubble_autoExpand() throws Exception {
Lyn Han89274b42020-03-25 00:56:26 -0700309 mBubbleController.updateBubble(mRow2.getEntry());
310 mBubbleController.updateBubble(mRow.getEntry());
Pinyao Ting175a5b82020-06-15 23:41:14 +0000311 when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
312 .thenReturn(mRow.getEntry());
313 when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getEntry().getKey()))
314 .thenReturn(mRow2.getEntry());
Lyn Han89274b42020-03-25 00:56:26 -0700315 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000316 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Lyn Han89274b42020-03-25 00:56:26 -0700317
318 Bubble b = mBubbleData.getOverflowBubbleWithKey(mRow.getEntry().getKey());
319 assertThat(mBubbleData.getOverflowBubbles()).isEqualTo(ImmutableList.of(b));
Lyn Han2f6e89d2020-04-15 10:01:01 -0700320 verify(mNotificationEntryManager, never()).performRemoveNotification(
321 eq(mRow.getEntry().getSbn()), anyInt());
Mady Mellor458a6262020-06-07 21:09:19 -0700322 assertThat(mRow.getEntry().isBubble()).isFalse();
Lyn Han89274b42020-03-25 00:56:26 -0700323
Lyn Han2f6e89d2020-04-15 10:01:01 -0700324 Bubble b2 = mBubbleData.getBubbleInStackWithKey(mRow2.getEntry().getKey());
Lyn Han89274b42020-03-25 00:56:26 -0700325 assertThat(mBubbleData.getSelectedBubble()).isEqualTo(b2);
326
327 mBubbleController.promoteBubbleFromOverflow(b);
Mady Mellor458a6262020-06-07 21:09:19 -0700328
329 assertThat(b.isBubble()).isTrue();
330 assertThat(b.shouldAutoExpand()).isTrue();
331 int flags = Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
332 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
333 verify(mStatusBarService, times(1)).onNotificationBubbleChanged(
334 eq(b.getKey()), eq(true), eq(flags));
Lyn Han89274b42020-03-25 00:56:26 -0700335 }
336
337 @Test
Lyn Han2f6e89d2020-04-15 10:01:01 -0700338 public void testCancelOverflowBubble() {
339 mBubbleController.updateBubble(mRow2.getEntry());
340 mBubbleController.updateBubble(mRow.getEntry(), /* suppressFlyout */
341 false, /* showInShade */ true);
Pinyao Ting175a5b82020-06-15 23:41:14 +0000342 when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
343 .thenReturn(mRow.getEntry());
344 when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getEntry().getKey()))
345 .thenReturn(mRow2.getEntry());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400346 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000347 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700348
Pinyao Ting3c930612020-05-19 00:26:03 +0000349 mBubbleController.removeBubble(
350 mRow.getEntry().getKey(), BubbleController.DISMISS_NOTIF_CANCEL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700351 verify(mNotificationEntryManager, times(1)).performRemoveNotification(
Beverlya53fb0d2020-01-29 15:26:13 -0500352 eq(mRow.getEntry().getSbn()), anyInt());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700353 assertThat(mBubbleData.getOverflowBubbles()).isEmpty();
354 assertFalse(mRow.getEntry().isBubble());
355 }
Joshua Tsujibe60a582020-03-23 17:17:26 -0400356
Lyn Han2f6e89d2020-04-15 10:01:01 -0700357 @Test
358 public void testUserChange_doesNotRemoveNotif() {
359 mBubbleController.updateBubble(mRow.getEntry());
360 assertTrue(mBubbleController.hasBubbles());
361
362 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000363 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_CHANGED);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700364 verify(mNotificationEntryManager, never()).performRemoveNotification(
365 eq(mRow.getEntry().getSbn()), anyInt());
366 assertFalse(mBubbleController.hasBubbles());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400367 assertFalse(mSysUiStateBubblesExpanded);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700368 assertTrue(mRow.getEntry().isBubble());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700369 }
370
371 @Test
Mady Mellorebdbbb92018-11-15 14:36:48 -0800372 public void testDismissStack() {
Mark Renouff97ed462019-04-05 13:46:24 -0400373 mBubbleController.updateBubble(mRow.getEntry());
Beverly85d4c192019-09-30 11:40:39 -0400374 verify(mNotificationEntryManager, times(1)).updateNotifications(any());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700375 assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Mark Renouff97ed462019-04-05 13:46:24 -0400376 mBubbleController.updateBubble(mRow2.getEntry());
Beverly85d4c192019-09-30 11:40:39 -0400377 verify(mNotificationEntryManager, times(2)).updateNotifications(any());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700378 assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow2.getEntry().getKey()));
Mady Mellorebdbbb92018-11-15 14:36:48 -0800379 assertTrue(mBubbleController.hasBubbles());
380
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400381 mBubbleData.dismissAll(BubbleController.DISMISS_USER_GESTURE);
Beverly85d4c192019-09-30 11:40:39 -0400382 verify(mNotificationEntryManager, times(3)).updateNotifications(any());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700383 assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
384 assertNull(mBubbleData.getBubbleInStackWithKey(mRow2.getEntry().getKey()));
Joshua Tsujibe60a582020-03-23 17:17:26 -0400385
386 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800387 }
388
389 @Test
Mady Melloracb12152019-01-29 15:24:48 -0800390 public void testExpandCollapseStack() {
Mady Mellorebdbbb92018-11-15 14:36:48 -0800391 assertFalse(mBubbleController.isStackExpanded());
Mady Melloracb12152019-01-29 15:24:48 -0800392
393 // Mark it as a bubble and add it explicitly
Mady Mellor78133512020-01-31 08:45:52 -0800394 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mark Renouff97ed462019-04-05 13:46:24 -0400395 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800396
Mady Mellorce23c462019-06-17 17:30:07 -0700397 // We should have bubbles & their notifs should not be suppressed
Mady Melloracb12152019-01-29 15:24:48 -0800398 assertTrue(mBubbleController.hasBubbles());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400399 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500400 mRow.getEntry()));
Mady Melloracb12152019-01-29 15:24:48 -0800401
402 // Expand the stack
Mady Mellorebdbbb92018-11-15 14:36:48 -0800403 BubbleStackView stackView = mBubbleController.getStackView();
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400404 mBubbleData.setExpanded(true);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800405 assertTrue(mBubbleController.isStackExpanded());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400406 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800407
Joshua Tsujibe60a582020-03-23 17:17:26 -0400408 assertTrue(mSysUiStateBubblesExpanded);
409
Mady Mellorce23c462019-06-17 17:30:07 -0700410 // Make sure the notif is suppressed
Ned Burns00b4b2d2019-10-17 22:09:27 -0400411 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500412 mRow.getEntry()));
Mady Melloracb12152019-01-29 15:24:48 -0800413
414 // Collapse
Mark Renouf71a3af62019-04-08 15:02:54 -0400415 mBubbleController.collapseStack();
Ned Burns00b4b2d2019-10-17 22:09:27 -0400416 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800417 assertFalse(mBubbleController.isStackExpanded());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400418
419 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800420 }
421
422 @Test
Josh Tsuji72e12cb2020-06-12 16:49:33 -0400423 @Ignore("Currently broken.")
Mady Melloracb12152019-01-29 15:24:48 -0800424 public void testCollapseAfterChangingExpandedBubble() {
425 // Mark it as a bubble and add it explicitly
Mady Mellor78133512020-01-31 08:45:52 -0800426 mEntryListener.onPendingEntryAdded(mRow.getEntry());
427 mEntryListener.onPendingEntryAdded(mRow2.getEntry());
Mark Renouff97ed462019-04-05 13:46:24 -0400428 mBubbleController.updateBubble(mRow.getEntry());
429 mBubbleController.updateBubble(mRow2.getEntry());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800430
Mady Mellorce23c462019-06-17 17:30:07 -0700431 // We should have bubbles & their notifs should not be suppressed
Mady Melloracb12152019-01-29 15:24:48 -0800432 assertTrue(mBubbleController.hasBubbles());
Mady Mellorce23c462019-06-17 17:30:07 -0700433 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500434 mRow.getEntry()));
Ned Burns00b4b2d2019-10-17 22:09:27 -0400435 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500436 mRow2.getEntry()));
Mady Melloracb12152019-01-29 15:24:48 -0800437
438 // Expand
Mady Mellorebdbbb92018-11-15 14:36:48 -0800439 BubbleStackView stackView = mBubbleController.getStackView();
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400440 mBubbleData.setExpanded(true);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800441 assertTrue(mBubbleController.isStackExpanded());
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400442 verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
443 true, mRow2.getEntry().getKey());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800444
Joshua Tsujibe60a582020-03-23 17:17:26 -0400445 assertTrue(mSysUiStateBubblesExpanded);
446
Mark Renoufba5ab512019-05-02 15:21:01 -0400447 // Last added is the one that is expanded
Pinyao Ting175a5b82020-06-15 23:41:14 +0000448 assertEquals(mRow2.getEntry().getKey(), mBubbleData.getSelectedBubble().getKey());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400449 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500450 mRow2.getEntry()));
Mark Renouf71a3af62019-04-08 15:02:54 -0400451
Mark Renoufba5ab512019-05-02 15:21:01 -0400452 // Switch which bubble is expanded
Pinyao Ting175a5b82020-06-15 23:41:14 +0000453 mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(
454 mRow.getEntry().getKey()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800455 mBubbleData.setExpanded(true);
Pinyao Ting175a5b82020-06-15 23:41:14 +0000456 assertEquals(mRow.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
457 stackView.getExpandedBubble().getKey()).getKey());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400458 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500459 mRow.getEntry()));
Mark Renoufba5ab512019-05-02 15:21:01 -0400460
Mady Melloracb12152019-01-29 15:24:48 -0800461 // collapse for previous bubble
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400462 verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
463 false, mRow2.getEntry().getKey());
Mady Melloracb12152019-01-29 15:24:48 -0800464 // expand for selected bubble
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400465 verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
466 true, mRow.getEntry().getKey());
Mady Melloredd4ee12019-01-18 10:45:11 -0800467
Mady Melloracb12152019-01-29 15:24:48 -0800468 // Collapse
Mady Mellorebdbbb92018-11-15 14:36:48 -0800469 mBubbleController.collapseStack();
470 assertFalse(mBubbleController.isStackExpanded());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400471
472 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800473 }
474
Ned Burns01e38212019-01-03 16:32:52 -0500475 @Test
Mady Melloraea895f02019-07-10 14:37:48 -0700476 public void testExpansionRemovesShowInShadeAndDot() {
Mady Melloracb12152019-01-29 15:24:48 -0800477 // Mark it as a bubble and add it explicitly
Mady Mellor78133512020-01-31 08:45:52 -0800478 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mark Renouff97ed462019-04-05 13:46:24 -0400479 mBubbleController.updateBubble(mRow.getEntry());
Mady Melloracb12152019-01-29 15:24:48 -0800480
Mady Mellorce23c462019-06-17 17:30:07 -0700481 // We should have bubbles & their notifs should not be suppressed
Mady Melloracb12152019-01-29 15:24:48 -0800482 assertTrue(mBubbleController.hasBubbles());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400483 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500484 mRow.getEntry()));
Mady Mellorb8aaf972019-11-26 10:28:00 -0800485
486 mTestableLooper.processAllMessages();
Lyn Han2f6e89d2020-04-15 10:01:01 -0700487 assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Mady Melloracb12152019-01-29 15:24:48 -0800488
489 // Expand
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400490 mBubbleData.setExpanded(true);
Mady Melloracb12152019-01-29 15:24:48 -0800491 assertTrue(mBubbleController.isStackExpanded());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400492 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
Mady Melloracb12152019-01-29 15:24:48 -0800493
Joshua Tsujibe60a582020-03-23 17:17:26 -0400494 assertTrue(mSysUiStateBubblesExpanded);
495
Mady Mellorce23c462019-06-17 17:30:07 -0700496 // Notif is suppressed after expansion
Ned Burns00b4b2d2019-10-17 22:09:27 -0400497 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500498 mRow.getEntry()));
Mady Melloraea895f02019-07-10 14:37:48 -0700499 // Notif shouldn't show dot after expansion
Lyn Han2f6e89d2020-04-15 10:01:01 -0700500 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Mady Melloraea895f02019-07-10 14:37:48 -0700501 }
502
503 @Test
504 public void testUpdateWhileExpanded_DoesntChangeShowInShadeAndDot() {
505 // Mark it as a bubble and add it explicitly
Mady Mellor78133512020-01-31 08:45:52 -0800506 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Melloraea895f02019-07-10 14:37:48 -0700507 mBubbleController.updateBubble(mRow.getEntry());
508
509 // We should have bubbles & their notifs should not be suppressed
510 assertTrue(mBubbleController.hasBubbles());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400511 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500512 mRow.getEntry()));
Mady Mellorb8aaf972019-11-26 10:28:00 -0800513
514 mTestableLooper.processAllMessages();
Lyn Han2f6e89d2020-04-15 10:01:01 -0700515 assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Mady Melloraea895f02019-07-10 14:37:48 -0700516
517 // Expand
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400518 mBubbleData.setExpanded(true);
Mady Melloraea895f02019-07-10 14:37:48 -0700519 assertTrue(mBubbleController.isStackExpanded());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400520 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
Mady Melloraea895f02019-07-10 14:37:48 -0700521
Joshua Tsujibe60a582020-03-23 17:17:26 -0400522 assertTrue(mSysUiStateBubblesExpanded);
523
Mady Melloraea895f02019-07-10 14:37:48 -0700524 // Notif is suppressed after expansion
Ned Burns00b4b2d2019-10-17 22:09:27 -0400525 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500526 mRow.getEntry()));
Mady Melloraea895f02019-07-10 14:37:48 -0700527 // Notif shouldn't show dot after expansion
Lyn Han2f6e89d2020-04-15 10:01:01 -0700528 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Mady Melloraea895f02019-07-10 14:37:48 -0700529
530 // Send update
531 mEntryListener.onPreEntryUpdated(mRow.getEntry());
532
533 // Nothing should have changed
534 // Notif is suppressed after expansion
Ned Burns00b4b2d2019-10-17 22:09:27 -0400535 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500536 mRow.getEntry()));
Mady Melloraea895f02019-07-10 14:37:48 -0700537 // Notif shouldn't show dot after expansion
Lyn Han2f6e89d2020-04-15 10:01:01 -0700538 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Mady Melloracb12152019-01-29 15:24:48 -0800539 }
540
541 @Test
542 public void testRemoveLastExpandedCollapses() {
543 // Mark it as a bubble and add it explicitly
Mady Mellor78133512020-01-31 08:45:52 -0800544 mEntryListener.onPendingEntryAdded(mRow.getEntry());
545 mEntryListener.onPendingEntryAdded(mRow2.getEntry());
Mark Renouff97ed462019-04-05 13:46:24 -0400546 mBubbleController.updateBubble(mRow.getEntry());
547 mBubbleController.updateBubble(mRow2.getEntry());
Mady Melloracb12152019-01-29 15:24:48 -0800548
549 // Expand
550 BubbleStackView stackView = mBubbleController.getStackView();
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400551 mBubbleData.setExpanded(true);
Mady Melloracb12152019-01-29 15:24:48 -0800552
Joshua Tsujibe60a582020-03-23 17:17:26 -0400553 assertTrue(mSysUiStateBubblesExpanded);
554
Mady Melloracb12152019-01-29 15:24:48 -0800555 assertTrue(mBubbleController.isStackExpanded());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400556 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
Mady Melloracb12152019-01-29 15:24:48 -0800557
Mark Renoufba5ab512019-05-02 15:21:01 -0400558 // Last added is the one that is expanded
Pinyao Ting175a5b82020-06-15 23:41:14 +0000559 assertEquals(mRow2.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
560 stackView.getExpandedBubble().getKey()).getKey());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400561 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500562 mRow2.getEntry()));
Mady Melloracb12152019-01-29 15:24:48 -0800563
564 // Dismiss currently expanded
Lyn Han9f66c3b2020-03-05 23:59:29 -0800565 mBubbleController.removeBubble(
Pinyao Ting175a5b82020-06-15 23:41:14 +0000566 mBubbleData.getBubbleInStackWithKey(
567 stackView.getExpandedBubble().getKey()).getKey(),
Mark Renouf08bc42a2019-03-07 13:01:59 -0500568 BubbleController.DISMISS_USER_GESTURE);
Ned Burns00b4b2d2019-10-17 22:09:27 -0400569 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
Mady Melloracb12152019-01-29 15:24:48 -0800570
Mark Renoufba5ab512019-05-02 15:21:01 -0400571 // Make sure first bubble is selected
Pinyao Ting175a5b82020-06-15 23:41:14 +0000572 assertEquals(mRow.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
573 stackView.getExpandedBubble().getKey()).getKey());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400574 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
Mady Melloracb12152019-01-29 15:24:48 -0800575
576 // Dismiss that one
Lyn Han9f66c3b2020-03-05 23:59:29 -0800577 mBubbleController.removeBubble(
Pinyao Ting175a5b82020-06-15 23:41:14 +0000578 mBubbleData.getBubbleInStackWithKey(
579 stackView.getExpandedBubble().getKey()).getKey(),
Mark Renouf08bc42a2019-03-07 13:01:59 -0500580 BubbleController.DISMISS_USER_GESTURE);
Mady Melloracb12152019-01-29 15:24:48 -0800581
582 // Make sure state changes and collapse happens
Ned Burns00b4b2d2019-10-17 22:09:27 -0400583 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
Mady Melloracb12152019-01-29 15:24:48 -0800584 assertFalse(mBubbleController.hasBubbles());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400585
586 assertFalse(mSysUiStateBubblesExpanded);
Mady Melloracb12152019-01-29 15:24:48 -0800587 }
588
589 @Test
Mady Mellorb25f9062019-12-09 12:12:57 -0800590 public void testAutoExpand_fails_noFlag() {
Mady Mellore80930e2019-03-21 16:00:45 -0700591 assertFalse(mBubbleController.isStackExpanded());
Mady Mellor8d25b202019-06-25 13:59:28 -0700592 setMetadataFlags(mRow.getEntry(),
593 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, false /* enableFlag */);
Mady Mellore80930e2019-03-21 16:00:45 -0700594
595 // Add the auto expand bubble
Mady Mellor78133512020-01-31 08:45:52 -0800596 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellor8d25b202019-06-25 13:59:28 -0700597 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellore80930e2019-03-21 16:00:45 -0700598
599 // Expansion shouldn't change
600 verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
Ned Burns00b4b2d2019-10-17 22:09:27 -0400601 mRow.getEntry().getKey());
Mady Mellore80930e2019-03-21 16:00:45 -0700602 assertFalse(mBubbleController.isStackExpanded());
603
Joshua Tsujibe60a582020-03-23 17:17:26 -0400604 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellore80930e2019-03-21 16:00:45 -0700605 }
606
607 @Test
Mady Mellorb25f9062019-12-09 12:12:57 -0800608 public void testAutoExpand_succeeds_withFlag() {
Mady Mellor8d25b202019-06-25 13:59:28 -0700609 setMetadataFlags(mRow.getEntry(),
610 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, true /* enableFlag */);
Mady Mellore80930e2019-03-21 16:00:45 -0700611
612 // Add the auto expand bubble
Mady Mellor78133512020-01-31 08:45:52 -0800613 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellor8d25b202019-06-25 13:59:28 -0700614 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellore80930e2019-03-21 16:00:45 -0700615
616 // Expansion should change
617 verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
Ned Burns00b4b2d2019-10-17 22:09:27 -0400618 mRow.getEntry().getKey());
Mady Mellore80930e2019-03-21 16:00:45 -0700619 assertTrue(mBubbleController.isStackExpanded());
620
Joshua Tsujibe60a582020-03-23 17:17:26 -0400621 assertTrue(mSysUiStateBubblesExpanded);
Mady Mellore80930e2019-03-21 16:00:45 -0700622 }
623
Mady Mellor3ed46202019-03-26 20:22:35 -0700624 @Test
Mady Mellorb25f9062019-12-09 12:12:57 -0800625 public void testSuppressNotif_onInitialNotif() {
Mady Mellor8d25b202019-06-25 13:59:28 -0700626 setMetadataFlags(mRow.getEntry(),
627 Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, true /* enableFlag */);
Mady Mellor3ed46202019-03-26 20:22:35 -0700628
629 // Add the suppress notif bubble
Mady Mellor78133512020-01-31 08:45:52 -0800630 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellor8d25b202019-06-25 13:59:28 -0700631 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellor3ed46202019-03-26 20:22:35 -0700632
Mady Mellorce23c462019-06-17 17:30:07 -0700633 // Notif should be suppressed because we were foreground
Ned Burns00b4b2d2019-10-17 22:09:27 -0400634 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500635 mRow.getEntry()));
Mady Mellorb25f9062019-12-09 12:12:57 -0800636 // Dot + flyout is hidden because notif is suppressed
Lyn Han2f6e89d2020-04-15 10:01:01 -0700637 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
638 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showFlyout());
Mady Mellor3ed46202019-03-26 20:22:35 -0700639
Joshua Tsujibe60a582020-03-23 17:17:26 -0400640 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellor3ed46202019-03-26 20:22:35 -0700641 }
Mady Mellore80930e2019-03-21 16:00:45 -0700642
643 @Test
Mady Mellorb25f9062019-12-09 12:12:57 -0800644 public void testSuppressNotif_onUpdateNotif() {
645 mBubbleController.updateBubble(mRow.getEntry());
646
647 // Should not be suppressed
648 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500649 mRow.getEntry()));
Mady Mellorb25f9062019-12-09 12:12:57 -0800650 // Should show dot
Lyn Han2f6e89d2020-04-15 10:01:01 -0700651 assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Mady Mellorb25f9062019-12-09 12:12:57 -0800652
653 // Update to suppress notif
654 setMetadataFlags(mRow.getEntry(),
655 Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, true /* enableFlag */);
656 mBubbleController.updateBubble(mRow.getEntry());
657
658 // Notif should be suppressed
659 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500660 mRow.getEntry()));
Mady Mellorb25f9062019-12-09 12:12:57 -0800661 // Dot + flyout is hidden because notif is suppressed
Lyn Han2f6e89d2020-04-15 10:01:01 -0700662 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
663 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showFlyout());
Mady Mellorb25f9062019-12-09 12:12:57 -0800664
Joshua Tsujibe60a582020-03-23 17:17:26 -0400665 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorb25f9062019-12-09 12:12:57 -0800666 }
667
Mady Mellorb25f9062019-12-09 12:12:57 -0800668 @Test
Mark Renouffec45da2019-03-13 13:24:27 -0400669 public void testExpandStackAndSelectBubble_removedFirst() {
Ned Burns00b4b2d2019-10-17 22:09:27 -0400670 final String key = mRow.getEntry().getKey();
Mark Renouffec45da2019-03-13 13:24:27 -0400671
Mady Mellor78133512020-01-31 08:45:52 -0800672 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mark Renouff97ed462019-04-05 13:46:24 -0400673 mBubbleController.updateBubble(mRow.getEntry());
Mark Renouffec45da2019-03-13 13:24:27 -0400674
Mark Renouffec45da2019-03-13 13:24:27 -0400675 // Simulate notification cancellation.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400676 mRemoveInterceptor.onNotificationRemoveRequested(
Evan Laird04373662020-01-24 17:37:39 -0500677 mRow.getEntry().getKey(), mRow.getEntry(), REASON_APP_CANCEL);
Mark Renouffec45da2019-03-13 13:24:27 -0400678
Mady Mellor76343012020-05-13 11:02:50 -0700679 mBubbleController.expandStackAndSelectBubble(mRow.getEntry());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400680
681 assertTrue(mSysUiStateBubblesExpanded);
Mark Renouffec45da2019-03-13 13:24:27 -0400682 }
683
684 @Test
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800685 public void testMarkNewNotificationAsShowInShade() {
Mady Mellor78133512020-01-31 08:45:52 -0800686 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400687 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500688 mRow.getEntry()));
Mady Mellorb8aaf972019-11-26 10:28:00 -0800689
690 mTestableLooper.processAllMessages();
Lyn Han2f6e89d2020-04-15 10:01:01 -0700691 assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800692 }
693
Mark Renouf08bc42a2019-03-07 13:01:59 -0500694 @Test
Mady Mellorfc02cc32019-04-01 14:47:55 -0700695 public void testAddNotif_notBubble() {
Mady Mellor78133512020-01-31 08:45:52 -0800696 mEntryListener.onPendingEntryAdded(mNonBubbleNotifRow.getEntry());
Mady Mellorfc02cc32019-04-01 14:47:55 -0700697 mEntryListener.onPreEntryUpdated(mNonBubbleNotifRow.getEntry());
698
Mady Mellorfc02cc32019-04-01 14:47:55 -0700699 assertThat(mBubbleController.hasBubbles()).isFalse();
700 }
701
702 @Test
Mark Renouf08bc42a2019-03-07 13:01:59 -0500703 public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException {
Mark Renouff97ed462019-04-05 13:46:24 -0400704 mBubbleController.updateBubble(mRow.getEntry());
Pinyao Ting3c930612020-05-19 00:26:03 +0000705 mBubbleController.removeBubble(mRow.getEntry().getKey(), BubbleController.DISMISS_AGED);
Mark Renouf08bc42a2019-03-07 13:01:59 -0500706 verify(mDeleteIntent, never()).send();
707 }
708
709 @Test
710 public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException {
Mark Renouff97ed462019-04-05 13:46:24 -0400711 mBubbleController.updateBubble(mRow.getEntry());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400712 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000713 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Mark Renouf08bc42a2019-03-07 13:01:59 -0500714 verify(mDeleteIntent, times(1)).send();
715 }
716
717 @Test
718 public void testDeleteIntent_dismissStack() throws PendingIntent.CanceledException {
Mark Renouff97ed462019-04-05 13:46:24 -0400719 mBubbleController.updateBubble(mRow.getEntry());
720 mBubbleController.updateBubble(mRow2.getEntry());
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400721 mBubbleData.dismissAll(BubbleController.DISMISS_USER_GESTURE);
Mark Renouf08bc42a2019-03-07 13:01:59 -0500722 verify(mDeleteIntent, times(2)).send();
723 }
724
Mady Melloraa8fef22019-04-11 13:36:40 -0700725 @Test
726 public void testRemoveBubble_noLongerBubbleAfterUpdate()
727 throws PendingIntent.CanceledException {
728 mBubbleController.updateBubble(mRow.getEntry());
729 assertTrue(mBubbleController.hasBubbles());
730
Ned Burns00b4b2d2019-10-17 22:09:27 -0400731 mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
Mady Mellor76343012020-05-13 11:02:50 -0700732 NotificationListenerService.Ranking ranking = new RankingBuilder(
733 mRow.getEntry().getRanking()).setCanBubble(false).build();
734 mRow.getEntry().setRanking(ranking);
Mady Melloraa8fef22019-04-11 13:36:40 -0700735 mEntryListener.onPreEntryUpdated(mRow.getEntry());
736
737 assertFalse(mBubbleController.hasBubbles());
738 verify(mDeleteIntent, never()).send();
739 }
740
Mady Mellorc2ff0112019-03-28 14:18:06 -0700741 @Test
742 public void testRemoveBubble_succeeds_appCancel() {
Mady Mellor78133512020-01-31 08:45:52 -0800743 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700744 mBubbleController.updateBubble(mRow.getEntry());
745
746 assertTrue(mBubbleController.hasBubbles());
747
748 boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
Evan Laird04373662020-01-24 17:37:39 -0500749 mRow.getEntry().getKey(), mRow.getEntry(), REASON_APP_CANCEL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700750
751 // Cancels always remove so no need to intercept
752 assertFalse(intercepted);
Beverlya53fb0d2020-01-29 15:26:13 -0500753 }
754
755 @Test
756 public void testRemoveBubble_entryListenerRemove() {
757 mEntryListener.onPendingEntryAdded(mRow.getEntry());
758 mBubbleController.updateBubble(mRow.getEntry());
759
760 assertTrue(mBubbleController.hasBubbles());
761
762 // Removes the notification
Julia Reynolds138111f2020-02-26 11:17:39 -0500763 mEntryListener.onEntryRemoved(mRow.getEntry(), null, false, REASON_APP_CANCEL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700764 assertFalse(mBubbleController.hasBubbles());
765 }
766
767 @Test
Beverlya53fb0d2020-01-29 15:26:13 -0500768 public void removeBubble_clearAllIntercepted() {
Mady Mellor78133512020-01-31 08:45:52 -0800769 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700770 mBubbleController.updateBubble(mRow.getEntry());
771
772 assertTrue(mBubbleController.hasBubbles());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400773 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500774 mRow.getEntry()));
Mady Mellorc2ff0112019-03-28 14:18:06 -0700775
776 boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
Evan Laird04373662020-01-24 17:37:39 -0500777 mRow.getEntry().getKey(), mRow.getEntry(), REASON_CANCEL_ALL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700778
779 // Intercept!
780 assertTrue(intercepted);
781 // Should update show in shade state
Ned Burns00b4b2d2019-10-17 22:09:27 -0400782 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500783 mRow.getEntry()));
Mady Mellorc2ff0112019-03-28 14:18:06 -0700784 }
785
786 @Test
Beverlya53fb0d2020-01-29 15:26:13 -0500787 public void removeBubble_userDismissNotifIntercepted() {
Mady Mellor78133512020-01-31 08:45:52 -0800788 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700789 mBubbleController.updateBubble(mRow.getEntry());
790
791 assertTrue(mBubbleController.hasBubbles());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400792 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500793 mRow.getEntry()));
Mady Mellorc2ff0112019-03-28 14:18:06 -0700794
795 boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
Evan Laird04373662020-01-24 17:37:39 -0500796 mRow.getEntry().getKey(), mRow.getEntry(), REASON_CANCEL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700797
798 // Intercept!
799 assertTrue(intercepted);
800 // Should update show in shade state
Ned Burns00b4b2d2019-10-17 22:09:27 -0400801 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500802 mRow.getEntry()));
Mady Mellorc2ff0112019-03-28 14:18:06 -0700803 }
804
805 @Test
Lyn Han2f6e89d2020-04-15 10:01:01 -0700806 public void removeNotif_inOverflow_intercepted() {
807 // Get bubble with notif in shade.
808 mEntryListener.onPendingEntryAdded(mRow.getEntry());
809 mBubbleController.updateBubble(mRow.getEntry());
810 assertTrue(mBubbleController.hasBubbles());
811 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
812 mRow.getEntry()));
813
814 // Dismiss the bubble into overflow.
815 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000816 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700817 assertFalse(mBubbleController.hasBubbles());
818
819 boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
820 mRow.getEntry().getKey(), mRow.getEntry(), REASON_CANCEL);
821
822 // Notif is no longer a bubble, but still in overflow, so we intercept removal.
823 assertTrue(intercepted);
824 }
825
826 @Test
827 public void removeNotif_notInOverflow_notIntercepted() {
828 // Get bubble with notif in shade.
Mady Mellor78133512020-01-31 08:45:52 -0800829 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700830 mBubbleController.updateBubble(mRow.getEntry());
831
832 assertTrue(mBubbleController.hasBubbles());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400833 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500834 mRow.getEntry()));
Mady Mellorc2ff0112019-03-28 14:18:06 -0700835
Ned Burns00b4b2d2019-10-17 22:09:27 -0400836 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000837 mRow.getEntry().getKey(), BubbleController.DISMISS_NO_LONGER_BUBBLE);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700838 assertFalse(mBubbleController.hasBubbles());
839
Mady Mellorc2ff0112019-03-28 14:18:06 -0700840 boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
Evan Laird04373662020-01-24 17:37:39 -0500841 mRow.getEntry().getKey(), mRow.getEntry(), REASON_CANCEL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700842
Lyn Han2f6e89d2020-04-15 10:01:01 -0700843 // Notif is no longer a bubble, so we should not intercept removal.
Mady Mellorc2ff0112019-03-28 14:18:06 -0700844 assertFalse(intercepted);
845 }
846
Mady Mellorf44b6832020-01-14 13:26:14 -0800847 @Test
Lyn Han2f6e89d2020-04-15 10:01:01 -0700848 public void testOverflowBubble_maxReached_notInShade_bubbleRemoved() {
849 mBubbleController.updateBubble(
850 mRow.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
851 mBubbleController.updateBubble(
852 mRow2.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
853 mBubbleController.updateBubble(
854 mRow3.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
Pinyao Ting175a5b82020-06-15 23:41:14 +0000855 when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
856 .thenReturn(mRow.getEntry());
857 when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getEntry().getKey()))
858 .thenReturn(mRow2.getEntry());
859 when(mNotificationEntryManager.getPendingOrActiveNotif(mRow3.getEntry().getKey()))
860 .thenReturn(mRow3.getEntry());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700861 assertEquals(mBubbleData.getBubbles().size(), 3);
862
863 mBubbleData.setMaxOverflowBubbles(1);
864 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000865 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700866 assertEquals(mBubbleData.getBubbles().size(), 2);
867 assertEquals(mBubbleData.getOverflowBubbles().size(), 1);
868
869 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000870 mRow2.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700871 // Overflow max of 1 is reached; mRow is oldest, so it gets removed
872 verify(mNotificationEntryManager, times(1)).performRemoveNotification(
873 mRow.getEntry().getSbn(), REASON_CANCEL);
874 assertEquals(mBubbleData.getBubbles().size(), 1);
875 assertEquals(mBubbleData.getOverflowBubbles().size(), 1);
876 }
877
878 @Test
Mady Mellorf44b6832020-01-14 13:26:14 -0800879 public void testNotifyShadeSuppressionChange_notificationDismiss() {
880 BubbleController.NotificationSuppressionChangedListener listener =
881 mock(BubbleController.NotificationSuppressionChangedListener.class);
882 mBubbleData.setSuppressionChangedListener(listener);
883
Mady Mellor78133512020-01-31 08:45:52 -0800884 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorf44b6832020-01-14 13:26:14 -0800885
886 assertTrue(mBubbleController.hasBubbles());
887 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500888 mRow.getEntry()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800889
Evan Laird04373662020-01-24 17:37:39 -0500890 mRemoveInterceptor.onNotificationRemoveRequested(
891 mRow.getEntry().getKey(), mRow.getEntry(), REASON_CANCEL);
Mady Mellorf44b6832020-01-14 13:26:14 -0800892
893 // Should update show in shade state
894 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500895 mRow.getEntry()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800896
897 // Should notify delegate that shade state changed
898 verify(listener).onBubbleNotificationSuppressionChange(
Lyn Han2f6e89d2020-04-15 10:01:01 -0700899 mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800900 }
901
902 @Test
903 public void testNotifyShadeSuppressionChange_bubbleExpanded() {
904 BubbleController.NotificationSuppressionChangedListener listener =
905 mock(BubbleController.NotificationSuppressionChangedListener.class);
906 mBubbleData.setSuppressionChangedListener(listener);
907
Mady Mellor78133512020-01-31 08:45:52 -0800908 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorf44b6832020-01-14 13:26:14 -0800909
910 assertTrue(mBubbleController.hasBubbles());
911 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500912 mRow.getEntry()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800913
914 mBubbleData.setExpanded(true);
915
916 // Once a bubble is expanded the notif is suppressed
917 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500918 mRow.getEntry()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800919
920 // Should notify delegate that shade state changed
921 verify(listener).onBubbleNotificationSuppressionChange(
Lyn Han2f6e89d2020-04-15 10:01:01 -0700922 mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800923 }
924
Beverlya53fb0d2020-01-29 15:26:13 -0500925 @Test
926 public void testBubbleSummaryDismissal_suppressesSummaryAndBubbleFromShade() throws Exception {
927 // GIVEN a group summary with a bubble child
928 ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
929 ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
Pinyao Ting175a5b82020-06-15 23:41:14 +0000930 when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
931 .thenReturn(groupedBubble.getEntry());
Beverlya53fb0d2020-01-29 15:26:13 -0500932 mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
933 groupSummary.addChildNotification(groupedBubble);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700934 assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500935
936 // WHEN the summary is dismissed
937 mBubbleController.handleDismissalInterception(groupSummary.getEntry());
938
939 // THEN the summary and bubbled child are suppressed from the shade
940 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
941 groupedBubble.getEntry()));
942 assertTrue(mBubbleData.isSummarySuppressed(groupSummary.getEntry().getSbn().getGroupKey()));
943 }
944
945 @Test
946 public void testAppRemovesSummary_removesAllBubbleChildren() throws Exception {
947 // GIVEN a group summary with a bubble child
948 ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
949 ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
950 mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
Pinyao Ting175a5b82020-06-15 23:41:14 +0000951 when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
952 .thenReturn(groupedBubble.getEntry());
Beverlya53fb0d2020-01-29 15:26:13 -0500953 groupSummary.addChildNotification(groupedBubble);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700954 assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500955
956 // GIVEN the summary is dismissed
957 mBubbleController.handleDismissalInterception(groupSummary.getEntry());
958
959 // WHEN the summary is cancelled by the app
Julia Reynolds138111f2020-02-26 11:17:39 -0500960 mEntryListener.onEntryRemoved(groupSummary.getEntry(), null, false, REASON_APP_CANCEL);
Beverlya53fb0d2020-01-29 15:26:13 -0500961
962 // THEN the summary and its children are removed from bubble data
Lyn Han2f6e89d2020-04-15 10:01:01 -0700963 assertFalse(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500964 assertFalse(mBubbleData.isSummarySuppressed(
965 groupSummary.getEntry().getSbn().getGroupKey()));
966 }
967
968 @Test
969 public void testSummaryDismissal_marksBubblesHiddenFromShadeAndDismissesNonBubbledChildren()
970 throws Exception {
971 // GIVEN a group summary with two (non-bubble) children and one bubble child
972 ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
973 ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
Pinyao Ting175a5b82020-06-15 23:41:14 +0000974 when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
975 .thenReturn(groupedBubble.getEntry());
Beverlya53fb0d2020-01-29 15:26:13 -0500976 mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
977 groupSummary.addChildNotification(groupedBubble);
978
979 // WHEN the summary is dismissed
980 mBubbleController.handleDismissalInterception(groupSummary.getEntry());
981
982 // THEN only the NON-bubble children are dismissed
Kevin Han43077f92020-02-28 12:51:53 -0800983 List<ExpandableNotificationRow> childrenRows = groupSummary.getAttachedChildren();
Beverlya53fb0d2020-01-29 15:26:13 -0500984 verify(mNotificationEntryManager, times(1)).performRemoveNotification(
985 childrenRows.get(0).getEntry().getSbn(), REASON_GROUP_SUMMARY_CANCELED);
986 verify(mNotificationEntryManager, times(1)).performRemoveNotification(
987 childrenRows.get(1).getEntry().getSbn(), REASON_GROUP_SUMMARY_CANCELED);
988 verify(mNotificationEntryManager, never()).performRemoveNotification(
989 eq(groupedBubble.getEntry().getSbn()), anyInt());
990
991 // THEN the bubble child is suppressed from the shade
992 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
993 groupedBubble.getEntry()));
994
995 // THEN the summary is removed from GroupManager
996 verify(mNotificationGroupManager, times(1)).onEntryRemoved(groupSummary.getEntry());
997 }
998
Mady Mellore80930e2019-03-21 16:00:45 -0700999 /**
Aran Inkc4381c42020-02-06 13:11:53 -05001000 * Sets the bubble metadata flags for this entry. These ]flags are normally set by
Mady Mellor8d25b202019-06-25 13:59:28 -07001001 * NotificationManagerService when the notification is sent, however, these tests do not
1002 * go through that path so we set them explicitly when testing.
1003 */
1004 private void setMetadataFlags(NotificationEntry entry, int flag, boolean enableFlag) {
1005 Notification.BubbleMetadata bubbleMetadata =
Ned Burns00b4b2d2019-10-17 22:09:27 -04001006 entry.getSbn().getNotification().getBubbleMetadata();
Mady Mellor8d25b202019-06-25 13:59:28 -07001007 int flags = bubbleMetadata.getFlags();
1008 if (enableFlag) {
1009 flags |= flag;
1010 } else {
1011 flags &= ~flag;
1012 }
1013 bubbleMetadata.setFlags(flags);
1014 }
Mady Mellorebdbbb92018-11-15 14:36:48 -08001015}