blob: 96e868d2a618073e5f32bbdbc10b3c130200750b [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;
Heemin Seogafb3dbc2019-11-04 16:05:19 -080047import android.content.res.Resources;
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;
Joshua Tsujidd4d9f92019-05-13 13:57:38 -040053import android.service.notification.ZenModeConfig;
Mady Mellorebdbbb92018-11-15 14:36:48 -080054import android.testing.AndroidTestingRunner;
55import android.testing.TestableLooper;
56import android.view.WindowManager;
Mady Mellorebdbbb92018-11-15 14:36:48 -080057
Brett Chabot84151d92019-02-27 15:37:59 -080058import androidx.test.filters.SmallTest;
59
Dave Mankoff2aff6c32019-10-14 17:40:37 -040060import com.android.internal.colorextraction.ColorExtractor;
Heemin Seogafb3dbc2019-11-04 16:05:19 -080061import com.android.systemui.SystemUIFactory;
Mady Mellorebdbbb92018-11-15 14:36:48 -080062import com.android.systemui.SysuiTestCase;
Dave Mankoff2aff6c32019-10-14 17:40:37 -040063import com.android.systemui.colorextraction.SysuiColorExtractor;
Ned Burnsaaeb44b2020-02-12 23:48:26 -050064import com.android.systemui.dump.DumpManager;
Joshua Tsujibe60a582020-03-23 17:17:26 -040065import com.android.systemui.model.SysUiState;
Mady Mellorc55b4122019-06-07 18:14:02 -070066import com.android.systemui.plugins.statusbar.StatusBarStateController;
Joshua Tsujibe60a582020-03-23 17:17:26 -040067import com.android.systemui.shared.system.QuickStepContract;
Beverlya53fb0d2020-01-29 15:26:13 -050068import com.android.systemui.statusbar.FeatureFlags;
Mark Renoufc19b4732019-06-26 12:08:33 -040069import com.android.systemui.statusbar.NotificationLockscreenUserManager;
Mady Mellorc2ff0112019-03-28 14:18:06 -070070import com.android.systemui.statusbar.NotificationRemoveInterceptor;
Heemin Seogafb3dbc2019-11-04 16:05:19 -080071import com.android.systemui.statusbar.SuperStatusBarViewFactory;
Lucas Dupine25c4872019-07-29 13:51:35 -070072import com.android.systemui.statusbar.SysuiStatusBarStateController;
Ned Burns01e38212019-01-03 16:32:52 -050073import com.android.systemui.statusbar.notification.NotificationEntryListener;
74import com.android.systemui.statusbar.notification.NotificationEntryManager;
Mady Mellorc55b4122019-06-07 18:14:02 -070075import com.android.systemui.statusbar.notification.NotificationFilter;
Beverlya53fb0d2020-01-29 15:26:13 -050076import com.android.systemui.statusbar.notification.collection.NotifPipeline;
Mady Mellor8d25b202019-06-25 13:59:28 -070077import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Dave Mankoff56fe9e42020-01-08 15:42:06 -050078import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
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;
Dave Mankoff56fe9e42020-01-08 15:42:06 -050081import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
Mady Mellorebdbbb92018-11-15 14:36:48 -080082import com.android.systemui.statusbar.phone.DozeParameters;
Lucas Dupine25c4872019-07-29 13:51:35 -070083import com.android.systemui.statusbar.phone.KeyguardBypassController;
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -050084import com.android.systemui.statusbar.phone.LockscreenLockIconController;
Ned Burns296aec162019-09-04 17:30:59 -040085import com.android.systemui.statusbar.phone.NotificationGroupManager;
wilsonshihe8321942019-10-18 18:39:46 +080086import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
Fabian Kozynskib00c70b2020-04-03 12:41:31 -040087import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
Mady Mellor7f234902019-10-20 12:06:29 -070088import com.android.systemui.statusbar.phone.ShadeController;
Lucas Dupinbd7366d2019-09-25 13:39:21 -070089import com.android.systemui.statusbar.policy.BatteryController;
Lyn Hanf1c9b8b2019-03-14 16:49:48 -070090import com.android.systemui.statusbar.policy.ConfigurationController;
Mady Melloraa8fef22019-04-11 13:36:40 -070091import com.android.systemui.statusbar.policy.HeadsUpManager;
Joshua Tsujidd4d9f92019-05-13 13:57:38 -040092import com.android.systemui.statusbar.policy.ZenModeController;
Joshua Tsuji7155bf12020-02-13 16:14:29 -050093import com.android.systemui.util.FloatingContentCoordinator;
Heemin Seogafb3dbc2019-11-04 16:05:19 -080094import com.android.systemui.util.InjectionInflationController;
Mady Mellorebdbbb92018-11-15 14:36:48 -080095
Lyn Han89274b42020-03-25 00:56:26 -070096import com.google.common.collect.ImmutableList;
97
Mady Mellorebdbbb92018-11-15 14:36:48 -080098import org.junit.Before;
99import org.junit.Test;
100import org.junit.runner.RunWith;
Ned Burns01e38212019-01-03 16:32:52 -0500101import org.mockito.ArgumentCaptor;
102import org.mockito.Captor;
Mady Mellorebdbbb92018-11-15 14:36:48 -0800103import org.mockito.Mock;
104import org.mockito.MockitoAnnotations;
105
Beverlya53fb0d2020-01-29 15:26:13 -0500106import java.util.List;
107
108/**
109 * Tests the NotificationEntryManager setup with BubbleController.
110 * The {@link NotifPipeline} setup with BubbleController is tested in
111 * {@link NewNotifPipelineBubbleControllerTest}.
112 */
Mady Mellorebdbbb92018-11-15 14:36:48 -0800113@SmallTest
114@RunWith(AndroidTestingRunner.class)
115@TestableLooper.RunWithLooper(setAsMainLooper = true)
116public class BubbleControllerTest extends SysuiTestCase {
Mady Mellorebdbbb92018-11-15 14:36:48 -0800117 @Mock
Ned Burns01e38212019-01-03 16:32:52 -0500118 private NotificationEntryManager mNotificationEntryManager;
119 @Mock
Mady Mellor22f2f072019-04-18 13:26:18 -0700120 private NotificationGroupManager mNotificationGroupManager;
121 @Mock
Mady Mellorebdbbb92018-11-15 14:36:48 -0800122 private WindowManager mWindowManager;
123 @Mock
124 private IActivityManager mActivityManager;
125 @Mock
126 private DozeParameters mDozeParameters;
Lyn Hanf1c9b8b2019-03-14 16:49:48 -0700127 @Mock
128 private ConfigurationController mConfigurationController;
Joshua Tsujidd4d9f92019-05-13 13:57:38 -0400129 @Mock
130 private ZenModeController mZenModeController;
131 @Mock
132 private ZenModeConfig mZenModeConfig;
Mady Mellor80c25b22019-06-17 14:40:37 -0700133 @Mock
134 private FaceManager mFaceManager;
Mark Renoufc19b4732019-06-26 12:08:33 -0400135 @Mock
136 private NotificationLockscreenUserManager mLockscreenUserManager;
Mady Mellorf474e0d2019-08-01 11:08:40 -0700137 @Mock
Lucas Dupine25c4872019-07-29 13:51:35 -0700138 private SysuiStatusBarStateController mStatusBarStateController;
139 @Mock
140 private KeyguardBypassController mKeyguardBypassController;
Joshua Tsuji7155bf12020-02-13 16:14:29 -0500141 @Mock
142 private FloatingContentCoordinator mFloatingContentCoordinator;
Pinyao Tingee191b12020-04-29 18:35:39 -0700143 @Mock
144 private BubbleDataRepository mDataRepository;
Lyn Hanf1c9b8b2019-03-14 16:49:48 -0700145
Joshua Tsujibe60a582020-03-23 17:17:26 -0400146 private SysUiState mSysUiState;
147 private boolean mSysUiStateBubblesExpanded;
148
Ned Burns01e38212019-01-03 16:32:52 -0500149 @Captor
150 private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
Mady Mellorc2ff0112019-03-28 14:18:06 -0700151 @Captor
152 private ArgumentCaptor<NotificationRemoveInterceptor> mRemoveInterceptorCaptor;
Mady Mellorebdbbb92018-11-15 14:36:48 -0800153
154 private TestableBubbleController mBubbleController;
wilsonshihe8321942019-10-18 18:39:46 +0800155 private NotificationShadeWindowController mNotificationShadeWindowController;
Ned Burns01e38212019-01-03 16:32:52 -0500156 private NotificationEntryListener mEntryListener;
Mady Mellorc2ff0112019-03-28 14:18:06 -0700157 private NotificationRemoveInterceptor mRemoveInterceptor;
Mady Mellorebdbbb92018-11-15 14:36:48 -0800158
159 private NotificationTestHelper mNotificationTestHelper;
160 private ExpandableNotificationRow mRow;
161 private ExpandableNotificationRow mRow2;
Lyn Han2f6e89d2020-04-15 10:01:01 -0700162 private ExpandableNotificationRow mRow3;
Mady Mellorfc02cc32019-04-01 14:47:55 -0700163 private ExpandableNotificationRow mNonBubbleNotifRow;
Mady Mellorebdbbb92018-11-15 14:36:48 -0800164
Mady Mellorb4991e62019-01-10 15:14:51 -0800165 @Mock
Mady Melloracb12152019-01-29 15:24:48 -0800166 private BubbleController.BubbleExpandListener mBubbleExpandListener;
Mark Renouf6b2331c2019-03-21 13:40:08 -0400167 @Mock
Mark Renouf08bc42a2019-03-07 13:01:59 -0500168 private PendingIntent mDeleteIntent;
Dave Mankoff2aff6c32019-10-14 17:40:37 -0400169 @Mock
170 private SysuiColorExtractor mColorExtractor;
171 @Mock
172 ColorExtractor.GradientColors mGradientColors;
Heemin Seogafb3dbc2019-11-04 16:05:19 -0800173 @Mock
174 private Resources mResources;
Mady Mellor7f234902019-10-20 12:06:29 -0700175 @Mock
Heemin Seogba6337f2019-12-10 15:34:37 -0800176 private ShadeController mShadeController;
Aran Inkaa4dfa72019-11-18 16:49:07 -0500177 @Mock
Dave Mankoff56fe9e42020-01-08 15:42:06 -0500178 private NotificationRowComponent mNotificationRowComponent;
Beverlya53fb0d2020-01-29 15:26:13 -0500179 @Mock
180 private NotifPipeline mNotifPipeline;
181 @Mock
182 private FeatureFlags mFeatureFlagsOldPipeline;
183 @Mock
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500184 private DumpManager mDumpManager;
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500185 @Mock
186 private LockscreenLockIconController mLockIconController;
Fabian Kozynskib00c70b2020-04-03 12:41:31 -0400187 @Mock
188 private NotificationShadeWindowView mNotificationShadeWindowView;
Mark Renouf08bc42a2019-03-07 13:01:59 -0500189
Heemin Seogafb3dbc2019-11-04 16:05:19 -0800190 private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
Mady Mellorcfd06c12019-02-13 14:32:12 -0800191 private BubbleData mBubbleData;
192
Mady Mellorb8aaf972019-11-26 10:28:00 -0800193 private TestableLooper mTestableLooper;
194
Mady Mellorebdbbb92018-11-15 14:36:48 -0800195 @Before
196 public void setUp() throws Exception {
197 MockitoAnnotations.initMocks(this);
Mady Mellorb8aaf972019-11-26 10:28:00 -0800198
199 mTestableLooper = TestableLooper.get(this);
200
Mady Mellor80c25b22019-06-17 14:40:37 -0700201 mContext.addMockSystemService(FaceManager.class, mFaceManager);
Dave Mankoff2aff6c32019-10-14 17:40:37 -0400202 when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800203
Heemin Seogafb3dbc2019-11-04 16:05:19 -0800204 mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
Dave Mankoff56fe9e42020-01-08 15:42:06 -0500205 new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()),
206 new NotificationRowComponent.Builder() {
207 @Override
208 public NotificationRowComponent.Builder activatableNotificationView(
209 ActivatableNotificationView view) {
210 return this;
211 }
212
213 @Override
214 public NotificationRowComponent build() {
215 return mNotificationRowComponent;
216 }
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500217 },
218 mLockIconController);
Heemin Seogafb3dbc2019-11-04 16:05:19 -0800219
Mady Mellorebdbbb92018-11-15 14:36:48 -0800220 // Bubbles get added to status bar window view
wilsonshihe8321942019-10-18 18:39:46 +0800221 mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
222 mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
Lucas Dupind73410a2020-02-18 12:54:41 -0800223 mConfigurationController, mKeyguardBypassController, mColorExtractor,
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500224 mDumpManager);
Fabian Kozynskib00c70b2020-04-03 12:41:31 -0400225 mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
wilsonshihe8321942019-10-18 18:39:46 +0800226 mNotificationShadeWindowController.attach();
Mady Mellorebdbbb92018-11-15 14:36:48 -0800227
228 // Need notifications for bubbles
Kevin Hana7c21be2020-04-01 17:58:35 -0700229 mNotificationTestHelper = new NotificationTestHelper(
230 mContext,
231 mDependency,
232 TestableLooper.get(this));
Mark Renouf08bc42a2019-03-07 13:01:59 -0500233 mRow = mNotificationTestHelper.createBubble(mDeleteIntent);
234 mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700235 mRow3 = mNotificationTestHelper.createBubble(mDeleteIntent);
Mady Mellorfc02cc32019-04-01 14:47:55 -0700236 mNonBubbleNotifRow = mNotificationTestHelper.createRow();
Mady Mellor3ed46202019-03-26 20:22:35 -0700237
Ned Burns01e38212019-01-03 16:32:52 -0500238 // Return non-null notification data from the NEM
Evan Laird181de622019-10-24 09:53:02 -0400239 when(mNotificationEntryManager
240 .getActiveNotificationUnfiltered(mRow.getEntry().getKey())).thenReturn(
241 mRow.getEntry());
Ned Burns01e38212019-01-03 16:32:52 -0500242
Joshua Tsujidd4d9f92019-05-13 13:57:38 -0400243 mZenModeConfig.suppressedVisualEffects = 0;
244 when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
245
Joshua Tsujibe60a582020-03-23 17:17:26 -0400246 mSysUiState = new SysUiState();
247 mSysUiState.addCallback(sysUiFlags ->
248 mSysUiStateBubblesExpanded =
249 (sysUiFlags & QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED) != 0);
250
Beverly Taid1e175c2020-03-10 16:37:04 +0000251 TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
252 new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
253 mock(PowerManager.class),
254 mock(IDreamManager.class),
255 mock(AmbientDisplayConfiguration.class),
Mady Mellorc55b4122019-06-07 18:14:02 -0700256 mock(NotificationFilter.class),
Lucas Dupinbd7366d2019-09-25 13:39:21 -0700257 mock(StatusBarStateController.class),
Beverly Taid1e175c2020-03-10 16:37:04 +0000258 mock(BatteryController.class),
259 mock(HeadsUpManager.class),
260 mock(Handler.class)
261 );
Mark Renouf71a3af62019-04-08 15:02:54 -0400262 mBubbleData = new BubbleData(mContext);
Beverlya53fb0d2020-01-29 15:26:13 -0500263 when(mFeatureFlagsOldPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500264 mBubbleController = new TestableBubbleController(
265 mContext,
wilsonshihe8321942019-10-18 18:39:46 +0800266 mNotificationShadeWindowController,
Mady Mellor7f234902019-10-20 12:06:29 -0700267 mStatusBarStateController,
268 mShadeController,
Mady Mellor22f2f072019-04-18 13:26:18 -0700269 mBubbleData,
270 mConfigurationController,
271 interruptionStateProvider,
272 mZenModeController,
273 mLockscreenUserManager,
Mady Mellor7f234902019-10-20 12:06:29 -0700274 mNotificationGroupManager,
Beverlya53fb0d2020-01-29 15:26:13 -0500275 mNotificationEntryManager,
276 mNotifPipeline,
277 mFeatureFlagsOldPipeline,
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500278 mDumpManager,
Joshua Tsujibe60a582020-03-23 17:17:26 -0400279 mFloatingContentCoordinator,
Pinyao Tingee191b12020-04-29 18:35:39 -0700280 mDataRepository,
Mady Mellor9adfe6a2020-03-30 17:23:26 -0700281 mSysUiState,
Mady Mellor59a7b982020-05-11 15:19:59 -0700282 mock(INotificationManager.class),
283 mWindowManager);
Mady Melloracb12152019-01-29 15:24:48 -0800284 mBubbleController.setExpandListener(mBubbleExpandListener);
Ned Burns01e38212019-01-03 16:32:52 -0500285
286 // Get a reference to the BubbleController's entry listener
287 verify(mNotificationEntryManager, atLeastOnce())
288 .addNotificationEntryListener(mEntryListenerCaptor.capture());
289 mEntryListener = mEntryListenerCaptor.getValue();
Mady Mellorc2ff0112019-03-28 14:18:06 -0700290 // And the remove interceptor
291 verify(mNotificationEntryManager, atLeastOnce())
Evan Laird04373662020-01-24 17:37:39 -0500292 .addNotificationRemoveInterceptor(mRemoveInterceptorCaptor.capture());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700293 mRemoveInterceptor = mRemoveInterceptorCaptor.getValue();
Mady Mellorebdbbb92018-11-15 14:36:48 -0800294 }
295
296 @Test
Mady Mellorebdbbb92018-11-15 14:36:48 -0800297 public void testAddBubble() {
Mark Renouff97ed462019-04-05 13:46:24 -0400298 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800299 assertTrue(mBubbleController.hasBubbles());
Mady Melloracb12152019-01-29 15:24:48 -0800300
Joshua Tsujibe60a582020-03-23 17:17:26 -0400301 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800302 }
303
304 @Test
305 public void testHasBubbles() {
306 assertFalse(mBubbleController.hasBubbles());
Mark Renouff97ed462019-04-05 13:46:24 -0400307 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800308 assertTrue(mBubbleController.hasBubbles());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400309 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800310 }
311
312 @Test
313 public void testRemoveBubble() {
Mark Renouff97ed462019-04-05 13:46:24 -0400314 mBubbleController.updateBubble(mRow.getEntry());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700315 assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Mady Mellorebdbbb92018-11-15 14:36:48 -0800316 assertTrue(mBubbleController.hasBubbles());
Beverly85d4c192019-09-30 11:40:39 -0400317 verify(mNotificationEntryManager).updateNotifications(any());
Mady Melloracb12152019-01-29 15:24:48 -0800318
Ned Burns00b4b2d2019-10-17 22:09:27 -0400319 mBubbleController.removeBubble(
Beverlya53fb0d2020-01-29 15:26:13 -0500320 mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700321 assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Beverly85d4c192019-09-30 11:40:39 -0400322 verify(mNotificationEntryManager, times(2)).updateNotifications(anyString());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400323
324 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800325 }
326
327 @Test
Lyn Han89274b42020-03-25 00:56:26 -0700328 public void testPromoteBubble_autoExpand() {
329 mBubbleController.updateBubble(mRow2.getEntry());
330 mBubbleController.updateBubble(mRow.getEntry());
331 mBubbleController.removeBubble(
332 mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
333
334 Bubble b = mBubbleData.getOverflowBubbleWithKey(mRow.getEntry().getKey());
335 assertThat(mBubbleData.getOverflowBubbles()).isEqualTo(ImmutableList.of(b));
Lyn Han2f6e89d2020-04-15 10:01:01 -0700336 verify(mNotificationEntryManager, never()).performRemoveNotification(
337 eq(mRow.getEntry().getSbn()), anyInt());
338 assertFalse(mRow.getEntry().isBubble());
Lyn Han89274b42020-03-25 00:56:26 -0700339
Lyn Han2f6e89d2020-04-15 10:01:01 -0700340 Bubble b2 = mBubbleData.getBubbleInStackWithKey(mRow2.getEntry().getKey());
Lyn Han89274b42020-03-25 00:56:26 -0700341 assertThat(mBubbleData.getSelectedBubble()).isEqualTo(b2);
342
343 mBubbleController.promoteBubbleFromOverflow(b);
344 assertThat(mBubbleData.getSelectedBubble()).isEqualTo(b);
345 }
346
347 @Test
Lyn Han2f6e89d2020-04-15 10:01:01 -0700348 public void testCancelOverflowBubble() {
349 mBubbleController.updateBubble(mRow2.getEntry());
350 mBubbleController.updateBubble(mRow.getEntry(), /* suppressFlyout */
351 false, /* showInShade */ true);
Ned Burns00b4b2d2019-10-17 22:09:27 -0400352 mBubbleController.removeBubble(
Beverlya53fb0d2020-01-29 15:26:13 -0500353 mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700354
Lyn Han2f6e89d2020-04-15 10:01:01 -0700355 mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_NOTIF_CANCEL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700356 verify(mNotificationEntryManager, times(1)).performRemoveNotification(
Beverlya53fb0d2020-01-29 15:26:13 -0500357 eq(mRow.getEntry().getSbn()), anyInt());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700358 assertThat(mBubbleData.getOverflowBubbles()).isEmpty();
359 assertFalse(mRow.getEntry().isBubble());
360 }
Joshua Tsujibe60a582020-03-23 17:17:26 -0400361
Lyn Han2f6e89d2020-04-15 10:01:01 -0700362 @Test
363 public void testUserChange_doesNotRemoveNotif() {
364 mBubbleController.updateBubble(mRow.getEntry());
365 assertTrue(mBubbleController.hasBubbles());
366
367 mBubbleController.removeBubble(
368 mRow.getEntry(), BubbleController.DISMISS_USER_CHANGED);
369 verify(mNotificationEntryManager, never()).performRemoveNotification(
370 eq(mRow.getEntry().getSbn()), anyInt());
371 assertFalse(mBubbleController.hasBubbles());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400372 assertFalse(mSysUiStateBubblesExpanded);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700373 assertTrue(mRow.getEntry().isBubble());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700374 }
375
376 @Test
Mady Mellorebdbbb92018-11-15 14:36:48 -0800377 public void testDismissStack() {
Mark Renouff97ed462019-04-05 13:46:24 -0400378 mBubbleController.updateBubble(mRow.getEntry());
Beverly85d4c192019-09-30 11:40:39 -0400379 verify(mNotificationEntryManager, times(1)).updateNotifications(any());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700380 assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Mark Renouff97ed462019-04-05 13:46:24 -0400381 mBubbleController.updateBubble(mRow2.getEntry());
Beverly85d4c192019-09-30 11:40:39 -0400382 verify(mNotificationEntryManager, times(2)).updateNotifications(any());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700383 assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow2.getEntry().getKey()));
Mady Mellorebdbbb92018-11-15 14:36:48 -0800384 assertTrue(mBubbleController.hasBubbles());
385
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400386 mBubbleData.dismissAll(BubbleController.DISMISS_USER_GESTURE);
Beverly85d4c192019-09-30 11:40:39 -0400387 verify(mNotificationEntryManager, times(3)).updateNotifications(any());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700388 assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
389 assertNull(mBubbleData.getBubbleInStackWithKey(mRow2.getEntry().getKey()));
Joshua Tsujibe60a582020-03-23 17:17:26 -0400390
391 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800392 }
393
394 @Test
Mady Melloracb12152019-01-29 15:24:48 -0800395 public void testExpandCollapseStack() {
Mady Mellorebdbbb92018-11-15 14:36:48 -0800396 assertFalse(mBubbleController.isStackExpanded());
Mady Melloracb12152019-01-29 15:24:48 -0800397
398 // Mark it as a bubble and add it explicitly
Mady Mellor78133512020-01-31 08:45:52 -0800399 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mark Renouff97ed462019-04-05 13:46:24 -0400400 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800401
Mady Mellorce23c462019-06-17 17:30:07 -0700402 // We should have bubbles & their notifs should not be suppressed
Mady Melloracb12152019-01-29 15:24:48 -0800403 assertTrue(mBubbleController.hasBubbles());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400404 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500405 mRow.getEntry()));
Mady Melloracb12152019-01-29 15:24:48 -0800406
407 // Expand the stack
Mady Mellorebdbbb92018-11-15 14:36:48 -0800408 BubbleStackView stackView = mBubbleController.getStackView();
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400409 mBubbleData.setExpanded(true);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800410 assertTrue(mBubbleController.isStackExpanded());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400411 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800412
Joshua Tsujibe60a582020-03-23 17:17:26 -0400413 assertTrue(mSysUiStateBubblesExpanded);
414
Mady Mellorce23c462019-06-17 17:30:07 -0700415 // Make sure the notif is suppressed
Ned Burns00b4b2d2019-10-17 22:09:27 -0400416 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500417 mRow.getEntry()));
Mady Melloracb12152019-01-29 15:24:48 -0800418
419 // Collapse
Mark Renouf71a3af62019-04-08 15:02:54 -0400420 mBubbleController.collapseStack();
Ned Burns00b4b2d2019-10-17 22:09:27 -0400421 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800422 assertFalse(mBubbleController.isStackExpanded());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400423
424 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800425 }
426
427 @Test
Mady Melloracb12152019-01-29 15:24:48 -0800428 public void testCollapseAfterChangingExpandedBubble() {
429 // Mark it as a bubble and add it explicitly
Mady Mellor78133512020-01-31 08:45:52 -0800430 mEntryListener.onPendingEntryAdded(mRow.getEntry());
431 mEntryListener.onPendingEntryAdded(mRow2.getEntry());
Mark Renouff97ed462019-04-05 13:46:24 -0400432 mBubbleController.updateBubble(mRow.getEntry());
433 mBubbleController.updateBubble(mRow2.getEntry());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800434
Mady Mellorce23c462019-06-17 17:30:07 -0700435 // We should have bubbles & their notifs should not be suppressed
Mady Melloracb12152019-01-29 15:24:48 -0800436 assertTrue(mBubbleController.hasBubbles());
Mady Mellorce23c462019-06-17 17:30:07 -0700437 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500438 mRow.getEntry()));
Ned Burns00b4b2d2019-10-17 22:09:27 -0400439 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500440 mRow2.getEntry()));
Mady Melloracb12152019-01-29 15:24:48 -0800441
442 // Expand
Mady Mellorebdbbb92018-11-15 14:36:48 -0800443 BubbleStackView stackView = mBubbleController.getStackView();
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400444 mBubbleData.setExpanded(true);
Mady Mellorebdbbb92018-11-15 14:36:48 -0800445 assertTrue(mBubbleController.isStackExpanded());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400446 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
Mady Mellorebdbbb92018-11-15 14:36:48 -0800447
Joshua Tsujibe60a582020-03-23 17:17:26 -0400448 assertTrue(mSysUiStateBubblesExpanded);
449
Mark Renoufba5ab512019-05-02 15:21:01 -0400450 // Last added is the one that is expanded
Mady Mellorb8aaf972019-11-26 10:28:00 -0800451 assertEquals(mRow2.getEntry(), mBubbleData.getSelectedBubble().getEntry());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400452 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500453 mRow2.getEntry()));
Mark Renouf71a3af62019-04-08 15:02:54 -0400454
Mark Renoufba5ab512019-05-02 15:21:01 -0400455 // Switch which bubble is expanded
Lyn Han2f6e89d2020-04-15 10:01:01 -0700456 mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800457 mBubbleData.setExpanded(true);
Lyn Han9f66c3b2020-03-05 23:59:29 -0800458 assertEquals(mRow.getEntry(),
Lyn Han2f6e89d2020-04-15 10:01:01 -0700459 mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400460 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500461 mRow.getEntry()));
Mark Renoufba5ab512019-05-02 15:21:01 -0400462
Mady Melloracb12152019-01-29 15:24:48 -0800463 // collapse for previous bubble
Ned Burns00b4b2d2019-10-17 22:09:27 -0400464 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
Mady Melloracb12152019-01-29 15:24:48 -0800465 // expand for selected bubble
Ned Burns00b4b2d2019-10-17 22:09:27 -0400466 verify(mBubbleExpandListener).onBubbleExpandChanged(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
Lyn Han9f66c3b2020-03-05 23:59:29 -0800559 assertEquals(mRow2.getEntry(),
Lyn Han2f6e89d2020-04-15 10:01:01 -0700560 mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
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(
Lyn Han2f6e89d2020-04-15 10:01:01 -0700566 mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry(),
Mark Renouf08bc42a2019-03-07 13:01:59 -0500567 BubbleController.DISMISS_USER_GESTURE);
Ned Burns00b4b2d2019-10-17 22:09:27 -0400568 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
Mady Melloracb12152019-01-29 15:24:48 -0800569
Mark Renoufba5ab512019-05-02 15:21:01 -0400570 // Make sure first bubble is selected
Lyn Han9f66c3b2020-03-05 23:59:29 -0800571 assertEquals(mRow.getEntry(),
Lyn Han2f6e89d2020-04-15 10:01:01 -0700572 mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400573 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
Mady Melloracb12152019-01-29 15:24:48 -0800574
575 // Dismiss that one
Lyn Han9f66c3b2020-03-05 23:59:29 -0800576 mBubbleController.removeBubble(
Lyn Han2f6e89d2020-04-15 10:01:01 -0700577 mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry(),
Mark Renouf08bc42a2019-03-07 13:01:59 -0500578 BubbleController.DISMISS_USER_GESTURE);
Mady Melloracb12152019-01-29 15:24:48 -0800579
580 // Make sure state changes and collapse happens
Ned Burns00b4b2d2019-10-17 22:09:27 -0400581 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
Mady Melloracb12152019-01-29 15:24:48 -0800582 assertFalse(mBubbleController.hasBubbles());
Joshua Tsujibe60a582020-03-23 17:17:26 -0400583
584 assertFalse(mSysUiStateBubblesExpanded);
Mady Melloracb12152019-01-29 15:24:48 -0800585 }
586
587 @Test
Mady Mellorb25f9062019-12-09 12:12:57 -0800588 public void testAutoExpand_fails_noFlag() {
Mady Mellore80930e2019-03-21 16:00:45 -0700589 assertFalse(mBubbleController.isStackExpanded());
Mady Mellor8d25b202019-06-25 13:59:28 -0700590 setMetadataFlags(mRow.getEntry(),
591 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, false /* enableFlag */);
Mady Mellore80930e2019-03-21 16:00:45 -0700592
593 // Add the auto expand bubble
Mady Mellor78133512020-01-31 08:45:52 -0800594 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellor8d25b202019-06-25 13:59:28 -0700595 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellore80930e2019-03-21 16:00:45 -0700596
597 // Expansion shouldn't change
598 verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
Ned Burns00b4b2d2019-10-17 22:09:27 -0400599 mRow.getEntry().getKey());
Mady Mellore80930e2019-03-21 16:00:45 -0700600 assertFalse(mBubbleController.isStackExpanded());
601
Joshua Tsujibe60a582020-03-23 17:17:26 -0400602 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellore80930e2019-03-21 16:00:45 -0700603 }
604
605 @Test
Mady Mellorb25f9062019-12-09 12:12:57 -0800606 public void testAutoExpand_succeeds_withFlag() {
Mady Mellor8d25b202019-06-25 13:59:28 -0700607 setMetadataFlags(mRow.getEntry(),
608 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, true /* enableFlag */);
Mady Mellore80930e2019-03-21 16:00:45 -0700609
610 // Add the auto expand bubble
Mady Mellor78133512020-01-31 08:45:52 -0800611 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellor8d25b202019-06-25 13:59:28 -0700612 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellore80930e2019-03-21 16:00:45 -0700613
614 // Expansion should change
615 verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
Ned Burns00b4b2d2019-10-17 22:09:27 -0400616 mRow.getEntry().getKey());
Mady Mellore80930e2019-03-21 16:00:45 -0700617 assertTrue(mBubbleController.isStackExpanded());
618
Joshua Tsujibe60a582020-03-23 17:17:26 -0400619 assertTrue(mSysUiStateBubblesExpanded);
Mady Mellore80930e2019-03-21 16:00:45 -0700620 }
621
Mady Mellor3ed46202019-03-26 20:22:35 -0700622 @Test
Mady Mellorb25f9062019-12-09 12:12:57 -0800623 public void testSuppressNotif_onInitialNotif() {
Mady Mellor8d25b202019-06-25 13:59:28 -0700624 setMetadataFlags(mRow.getEntry(),
625 Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, true /* enableFlag */);
Mady Mellor3ed46202019-03-26 20:22:35 -0700626
627 // Add the suppress notif bubble
Mady Mellor78133512020-01-31 08:45:52 -0800628 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellor8d25b202019-06-25 13:59:28 -0700629 mBubbleController.updateBubble(mRow.getEntry());
Mady Mellor3ed46202019-03-26 20:22:35 -0700630
Mady Mellorce23c462019-06-17 17:30:07 -0700631 // Notif should be suppressed because we were foreground
Ned Burns00b4b2d2019-10-17 22:09:27 -0400632 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500633 mRow.getEntry()));
Mady Mellorb25f9062019-12-09 12:12:57 -0800634 // Dot + flyout is hidden because notif is suppressed
Lyn Han2f6e89d2020-04-15 10:01:01 -0700635 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
636 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showFlyout());
Mady Mellor3ed46202019-03-26 20:22:35 -0700637
Joshua Tsujibe60a582020-03-23 17:17:26 -0400638 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellor3ed46202019-03-26 20:22:35 -0700639 }
Mady Mellore80930e2019-03-21 16:00:45 -0700640
641 @Test
Mady Mellorb25f9062019-12-09 12:12:57 -0800642 public void testSuppressNotif_onUpdateNotif() {
643 mBubbleController.updateBubble(mRow.getEntry());
644
645 // Should not be suppressed
646 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500647 mRow.getEntry()));
Mady Mellorb25f9062019-12-09 12:12:57 -0800648 // Should show dot
Lyn Han2f6e89d2020-04-15 10:01:01 -0700649 assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Mady Mellorb25f9062019-12-09 12:12:57 -0800650
651 // Update to suppress notif
652 setMetadataFlags(mRow.getEntry(),
653 Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, true /* enableFlag */);
654 mBubbleController.updateBubble(mRow.getEntry());
655
656 // Notif should be suppressed
657 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500658 mRow.getEntry()));
Mady Mellorb25f9062019-12-09 12:12:57 -0800659 // Dot + flyout is hidden because notif is suppressed
Lyn Han2f6e89d2020-04-15 10:01:01 -0700660 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
661 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showFlyout());
Mady Mellorb25f9062019-12-09 12:12:57 -0800662
Joshua Tsujibe60a582020-03-23 17:17:26 -0400663 assertFalse(mSysUiStateBubblesExpanded);
Mady Mellorb25f9062019-12-09 12:12:57 -0800664 }
665
Mady Mellorb25f9062019-12-09 12:12:57 -0800666 @Test
Mark Renouffec45da2019-03-13 13:24:27 -0400667 public void testExpandStackAndSelectBubble_removedFirst() {
Ned Burns00b4b2d2019-10-17 22:09:27 -0400668 final String key = mRow.getEntry().getKey();
Mark Renouffec45da2019-03-13 13:24:27 -0400669
Mady Mellor78133512020-01-31 08:45:52 -0800670 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mark Renouff97ed462019-04-05 13:46:24 -0400671 mBubbleController.updateBubble(mRow.getEntry());
Mark Renouffec45da2019-03-13 13:24:27 -0400672
Mark Renouffec45da2019-03-13 13:24:27 -0400673 // Simulate notification cancellation.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400674 mRemoveInterceptor.onNotificationRemoveRequested(
Evan Laird04373662020-01-24 17:37:39 -0500675 mRow.getEntry().getKey(), mRow.getEntry(), REASON_APP_CANCEL);
Mark Renouffec45da2019-03-13 13:24:27 -0400676
677 mBubbleController.expandStackAndSelectBubble(key);
Joshua Tsujibe60a582020-03-23 17:17:26 -0400678
679 assertTrue(mSysUiStateBubblesExpanded);
Mark Renouffec45da2019-03-13 13:24:27 -0400680 }
681
682 @Test
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800683 public void testMarkNewNotificationAsShowInShade() {
Mady Mellor78133512020-01-31 08:45:52 -0800684 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400685 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500686 mRow.getEntry()));
Mady Mellorb8aaf972019-11-26 10:28:00 -0800687
688 mTestableLooper.processAllMessages();
Lyn Han2f6e89d2020-04-15 10:01:01 -0700689 assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800690 }
691
Mark Renouf08bc42a2019-03-07 13:01:59 -0500692 @Test
Mady Mellorfc02cc32019-04-01 14:47:55 -0700693 public void testAddNotif_notBubble() {
Mady Mellor78133512020-01-31 08:45:52 -0800694 mEntryListener.onPendingEntryAdded(mNonBubbleNotifRow.getEntry());
Mady Mellorfc02cc32019-04-01 14:47:55 -0700695 mEntryListener.onPreEntryUpdated(mNonBubbleNotifRow.getEntry());
696
Mady Mellorfc02cc32019-04-01 14:47:55 -0700697 assertThat(mBubbleController.hasBubbles()).isFalse();
698 }
699
700 @Test
Mark Renouf08bc42a2019-03-07 13:01:59 -0500701 public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException {
Mark Renouff97ed462019-04-05 13:46:24 -0400702 mBubbleController.updateBubble(mRow.getEntry());
Beverlya53fb0d2020-01-29 15:26:13 -0500703 mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_AGED);
Mark Renouf08bc42a2019-03-07 13:01:59 -0500704 verify(mDeleteIntent, never()).send();
705 }
706
707 @Test
708 public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException {
Mark Renouff97ed462019-04-05 13:46:24 -0400709 mBubbleController.updateBubble(mRow.getEntry());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400710 mBubbleController.removeBubble(
Beverlya53fb0d2020-01-29 15:26:13 -0500711 mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
Mark Renouf08bc42a2019-03-07 13:01:59 -0500712 verify(mDeleteIntent, times(1)).send();
713 }
714
715 @Test
716 public void testDeleteIntent_dismissStack() throws PendingIntent.CanceledException {
Mark Renouff97ed462019-04-05 13:46:24 -0400717 mBubbleController.updateBubble(mRow.getEntry());
718 mBubbleController.updateBubble(mRow2.getEntry());
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400719 mBubbleData.dismissAll(BubbleController.DISMISS_USER_GESTURE);
Mark Renouf08bc42a2019-03-07 13:01:59 -0500720 verify(mDeleteIntent, times(2)).send();
721 }
722
Mady Melloraa8fef22019-04-11 13:36:40 -0700723 @Test
724 public void testRemoveBubble_noLongerBubbleAfterUpdate()
725 throws PendingIntent.CanceledException {
726 mBubbleController.updateBubble(mRow.getEntry());
727 assertTrue(mBubbleController.hasBubbles());
728
Ned Burns00b4b2d2019-10-17 22:09:27 -0400729 mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
Mady Melloraa8fef22019-04-11 13:36:40 -0700730 mEntryListener.onPreEntryUpdated(mRow.getEntry());
731
732 assertFalse(mBubbleController.hasBubbles());
733 verify(mDeleteIntent, never()).send();
734 }
735
Mady Mellorc2ff0112019-03-28 14:18:06 -0700736 @Test
737 public void testRemoveBubble_succeeds_appCancel() {
Mady Mellor78133512020-01-31 08:45:52 -0800738 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700739 mBubbleController.updateBubble(mRow.getEntry());
740
741 assertTrue(mBubbleController.hasBubbles());
742
743 boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
Evan Laird04373662020-01-24 17:37:39 -0500744 mRow.getEntry().getKey(), mRow.getEntry(), REASON_APP_CANCEL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700745
746 // Cancels always remove so no need to intercept
747 assertFalse(intercepted);
Beverlya53fb0d2020-01-29 15:26:13 -0500748 }
749
750 @Test
751 public void testRemoveBubble_entryListenerRemove() {
752 mEntryListener.onPendingEntryAdded(mRow.getEntry());
753 mBubbleController.updateBubble(mRow.getEntry());
754
755 assertTrue(mBubbleController.hasBubbles());
756
757 // Removes the notification
Julia Reynolds138111f2020-02-26 11:17:39 -0500758 mEntryListener.onEntryRemoved(mRow.getEntry(), null, false, REASON_APP_CANCEL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700759 assertFalse(mBubbleController.hasBubbles());
760 }
761
762 @Test
Beverlya53fb0d2020-01-29 15:26:13 -0500763 public void removeBubble_clearAllIntercepted() {
Mady Mellor78133512020-01-31 08:45:52 -0800764 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700765 mBubbleController.updateBubble(mRow.getEntry());
766
767 assertTrue(mBubbleController.hasBubbles());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400768 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500769 mRow.getEntry()));
Mady Mellorc2ff0112019-03-28 14:18:06 -0700770
771 boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
Evan Laird04373662020-01-24 17:37:39 -0500772 mRow.getEntry().getKey(), mRow.getEntry(), REASON_CANCEL_ALL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700773
774 // Intercept!
775 assertTrue(intercepted);
776 // Should update show in shade state
Ned Burns00b4b2d2019-10-17 22:09:27 -0400777 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500778 mRow.getEntry()));
Mady Mellorc2ff0112019-03-28 14:18:06 -0700779 }
780
781 @Test
Beverlya53fb0d2020-01-29 15:26:13 -0500782 public void removeBubble_userDismissNotifIntercepted() {
Mady Mellor78133512020-01-31 08:45:52 -0800783 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700784 mBubbleController.updateBubble(mRow.getEntry());
785
786 assertTrue(mBubbleController.hasBubbles());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400787 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500788 mRow.getEntry()));
Mady Mellorc2ff0112019-03-28 14:18:06 -0700789
790 boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
Evan Laird04373662020-01-24 17:37:39 -0500791 mRow.getEntry().getKey(), mRow.getEntry(), REASON_CANCEL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700792
793 // Intercept!
794 assertTrue(intercepted);
795 // Should update show in shade state
Ned Burns00b4b2d2019-10-17 22:09:27 -0400796 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500797 mRow.getEntry()));
Mady Mellorc2ff0112019-03-28 14:18:06 -0700798 }
799
800 @Test
Lyn Han2f6e89d2020-04-15 10:01:01 -0700801 public void removeNotif_inOverflow_intercepted() {
802 // Get bubble with notif in shade.
803 mEntryListener.onPendingEntryAdded(mRow.getEntry());
804 mBubbleController.updateBubble(mRow.getEntry());
805 assertTrue(mBubbleController.hasBubbles());
806 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
807 mRow.getEntry()));
808
809 // Dismiss the bubble into overflow.
810 mBubbleController.removeBubble(
811 mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
812 assertFalse(mBubbleController.hasBubbles());
813
814 boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
815 mRow.getEntry().getKey(), mRow.getEntry(), REASON_CANCEL);
816
817 // Notif is no longer a bubble, but still in overflow, so we intercept removal.
818 assertTrue(intercepted);
819 }
820
821 @Test
822 public void removeNotif_notInOverflow_notIntercepted() {
823 // Get bubble with notif in shade.
Mady Mellor78133512020-01-31 08:45:52 -0800824 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorc2ff0112019-03-28 14:18:06 -0700825 mBubbleController.updateBubble(mRow.getEntry());
826
827 assertTrue(mBubbleController.hasBubbles());
Ned Burns00b4b2d2019-10-17 22:09:27 -0400828 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500829 mRow.getEntry()));
Mady Mellorc2ff0112019-03-28 14:18:06 -0700830
Ned Burns00b4b2d2019-10-17 22:09:27 -0400831 mBubbleController.removeBubble(
Lyn Han2f6e89d2020-04-15 10:01:01 -0700832 mRow.getEntry(), BubbleController.DISMISS_NO_LONGER_BUBBLE);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700833 assertFalse(mBubbleController.hasBubbles());
834
Mady Mellorc2ff0112019-03-28 14:18:06 -0700835 boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
Evan Laird04373662020-01-24 17:37:39 -0500836 mRow.getEntry().getKey(), mRow.getEntry(), REASON_CANCEL);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700837
Lyn Han2f6e89d2020-04-15 10:01:01 -0700838 // Notif is no longer a bubble, so we should not intercept removal.
Mady Mellorc2ff0112019-03-28 14:18:06 -0700839 assertFalse(intercepted);
840 }
841
Mady Mellorf44b6832020-01-14 13:26:14 -0800842 @Test
Lyn Han2f6e89d2020-04-15 10:01:01 -0700843 public void testOverflowBubble_maxReached_notInShade_bubbleRemoved() {
844 mBubbleController.updateBubble(
845 mRow.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
846 mBubbleController.updateBubble(
847 mRow2.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
848 mBubbleController.updateBubble(
849 mRow3.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
850 assertEquals(mBubbleData.getBubbles().size(), 3);
851
852 mBubbleData.setMaxOverflowBubbles(1);
853 mBubbleController.removeBubble(
854 mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
855 assertEquals(mBubbleData.getBubbles().size(), 2);
856 assertEquals(mBubbleData.getOverflowBubbles().size(), 1);
857
858 mBubbleController.removeBubble(
859 mRow2.getEntry(), BubbleController.DISMISS_USER_GESTURE);
860 // Overflow max of 1 is reached; mRow is oldest, so it gets removed
861 verify(mNotificationEntryManager, times(1)).performRemoveNotification(
862 mRow.getEntry().getSbn(), REASON_CANCEL);
863 assertEquals(mBubbleData.getBubbles().size(), 1);
864 assertEquals(mBubbleData.getOverflowBubbles().size(), 1);
865 }
866
867 @Test
Mady Mellorf44b6832020-01-14 13:26:14 -0800868 public void testNotifyShadeSuppressionChange_notificationDismiss() {
869 BubbleController.NotificationSuppressionChangedListener listener =
870 mock(BubbleController.NotificationSuppressionChangedListener.class);
871 mBubbleData.setSuppressionChangedListener(listener);
872
Mady Mellor78133512020-01-31 08:45:52 -0800873 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorf44b6832020-01-14 13:26:14 -0800874
875 assertTrue(mBubbleController.hasBubbles());
876 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500877 mRow.getEntry()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800878
Evan Laird04373662020-01-24 17:37:39 -0500879 mRemoveInterceptor.onNotificationRemoveRequested(
880 mRow.getEntry().getKey(), mRow.getEntry(), REASON_CANCEL);
Mady Mellorf44b6832020-01-14 13:26:14 -0800881
882 // Should update show in shade state
883 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500884 mRow.getEntry()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800885
886 // Should notify delegate that shade state changed
887 verify(listener).onBubbleNotificationSuppressionChange(
Lyn Han2f6e89d2020-04-15 10:01:01 -0700888 mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800889 }
890
891 @Test
892 public void testNotifyShadeSuppressionChange_bubbleExpanded() {
893 BubbleController.NotificationSuppressionChangedListener listener =
894 mock(BubbleController.NotificationSuppressionChangedListener.class);
895 mBubbleData.setSuppressionChangedListener(listener);
896
Mady Mellor78133512020-01-31 08:45:52 -0800897 mEntryListener.onPendingEntryAdded(mRow.getEntry());
Mady Mellorf44b6832020-01-14 13:26:14 -0800898
899 assertTrue(mBubbleController.hasBubbles());
900 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500901 mRow.getEntry()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800902
903 mBubbleData.setExpanded(true);
904
905 // Once a bubble is expanded the notif is suppressed
906 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
Beverlyed8aea22020-01-22 16:52:47 -0500907 mRow.getEntry()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800908
909 // Should notify delegate that shade state changed
910 verify(listener).onBubbleNotificationSuppressionChange(
Lyn Han2f6e89d2020-04-15 10:01:01 -0700911 mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Mady Mellorf44b6832020-01-14 13:26:14 -0800912 }
913
Beverlya53fb0d2020-01-29 15:26:13 -0500914 @Test
915 public void testBubbleSummaryDismissal_suppressesSummaryAndBubbleFromShade() throws Exception {
916 // GIVEN a group summary with a bubble child
917 ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
918 ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
919 mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
920 groupSummary.addChildNotification(groupedBubble);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700921 assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500922
923 // WHEN the summary is dismissed
924 mBubbleController.handleDismissalInterception(groupSummary.getEntry());
925
926 // THEN the summary and bubbled child are suppressed from the shade
927 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
928 groupedBubble.getEntry()));
929 assertTrue(mBubbleData.isSummarySuppressed(groupSummary.getEntry().getSbn().getGroupKey()));
930 }
931
932 @Test
933 public void testAppRemovesSummary_removesAllBubbleChildren() throws Exception {
934 // GIVEN a group summary with a bubble child
935 ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
936 ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
937 mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
938 groupSummary.addChildNotification(groupedBubble);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700939 assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500940
941 // GIVEN the summary is dismissed
942 mBubbleController.handleDismissalInterception(groupSummary.getEntry());
943
944 // WHEN the summary is cancelled by the app
Julia Reynolds138111f2020-02-26 11:17:39 -0500945 mEntryListener.onEntryRemoved(groupSummary.getEntry(), null, false, REASON_APP_CANCEL);
Beverlya53fb0d2020-01-29 15:26:13 -0500946
947 // THEN the summary and its children are removed from bubble data
Lyn Han2f6e89d2020-04-15 10:01:01 -0700948 assertFalse(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500949 assertFalse(mBubbleData.isSummarySuppressed(
950 groupSummary.getEntry().getSbn().getGroupKey()));
951 }
952
953 @Test
954 public void testSummaryDismissal_marksBubblesHiddenFromShadeAndDismissesNonBubbledChildren()
955 throws Exception {
956 // GIVEN a group summary with two (non-bubble) children and one bubble child
957 ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
958 ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
959 mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
960 groupSummary.addChildNotification(groupedBubble);
961
962 // WHEN the summary is dismissed
963 mBubbleController.handleDismissalInterception(groupSummary.getEntry());
964
965 // THEN only the NON-bubble children are dismissed
Kevin Han43077f92020-02-28 12:51:53 -0800966 List<ExpandableNotificationRow> childrenRows = groupSummary.getAttachedChildren();
Beverlya53fb0d2020-01-29 15:26:13 -0500967 verify(mNotificationEntryManager, times(1)).performRemoveNotification(
968 childrenRows.get(0).getEntry().getSbn(), REASON_GROUP_SUMMARY_CANCELED);
969 verify(mNotificationEntryManager, times(1)).performRemoveNotification(
970 childrenRows.get(1).getEntry().getSbn(), REASON_GROUP_SUMMARY_CANCELED);
971 verify(mNotificationEntryManager, never()).performRemoveNotification(
972 eq(groupedBubble.getEntry().getSbn()), anyInt());
973
974 // THEN the bubble child is suppressed from the shade
975 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
976 groupedBubble.getEntry()));
977
978 // THEN the summary is removed from GroupManager
979 verify(mNotificationGroupManager, times(1)).onEntryRemoved(groupSummary.getEntry());
980 }
981
Mady Mellore80930e2019-03-21 16:00:45 -0700982 /**
Aran Inkc4381c42020-02-06 13:11:53 -0500983 * Sets the bubble metadata flags for this entry. These ]flags are normally set by
Mady Mellor8d25b202019-06-25 13:59:28 -0700984 * NotificationManagerService when the notification is sent, however, these tests do not
985 * go through that path so we set them explicitly when testing.
986 */
987 private void setMetadataFlags(NotificationEntry entry, int flag, boolean enableFlag) {
988 Notification.BubbleMetadata bubbleMetadata =
Ned Burns00b4b2d2019-10-17 22:09:27 -0400989 entry.getSbn().getNotification().getBubbleMetadata();
Mady Mellor8d25b202019-06-25 13:59:28 -0700990 int flags = bubbleMetadata.getFlags();
991 if (enableFlag) {
992 flags |= flag;
993 } else {
994 flags &= ~flag;
995 }
996 bubbleMetadata.setFlags(flags);
997 }
Mady Mellorebdbbb92018-11-15 14:36:48 -0800998}