blob: ead95ca1665e2b8a97baffae739a2b4e6edbda6b [file] [log] [blame]
Beverlya53fb0d2020-01-29 15:26:13 -05001/*
2 * Copyright (C) 2020 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
19import static android.app.Notification.FLAG_BUBBLE;
20import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
21
22import static com.google.common.truth.Truth.assertThat;
23
24import static org.junit.Assert.assertEquals;
25import static org.junit.Assert.assertFalse;
26import static org.junit.Assert.assertNotNull;
27import static org.junit.Assert.assertNull;
28import static org.junit.Assert.assertTrue;
Beverlya53fb0d2020-01-29 15:26:13 -050029import static org.mockito.ArgumentMatchers.anyInt;
30import static org.mockito.ArgumentMatchers.anyString;
31import static org.mockito.ArgumentMatchers.eq;
32import static org.mockito.Mockito.atLeastOnce;
33import static org.mockito.Mockito.mock;
34import static org.mockito.Mockito.never;
35import static org.mockito.Mockito.times;
36import static org.mockito.Mockito.verify;
37import static org.mockito.Mockito.when;
38
39import android.app.IActivityManager;
Mady Mellor9adfe6a2020-03-30 17:23:26 -070040import android.app.INotificationManager;
Beverlya53fb0d2020-01-29 15:26:13 -050041import android.app.Notification;
42import android.app.PendingIntent;
Beverlya53fb0d2020-01-29 15:26:13 -050043import android.content.res.Resources;
Beverly Taid1e175c2020-03-10 16:37:04 +000044import android.hardware.display.AmbientDisplayConfiguration;
Beverlya53fb0d2020-01-29 15:26:13 -050045import android.hardware.face.FaceManager;
Beverly Taid1e175c2020-03-10 16:37:04 +000046import android.os.Handler;
47import android.os.PowerManager;
48import android.service.dreams.IDreamManager;
Mady Mellor76343012020-05-13 11:02:50 -070049import android.service.notification.NotificationListenerService;
Beverlya53fb0d2020-01-29 15:26:13 -050050import android.service.notification.ZenModeConfig;
51import android.testing.AndroidTestingRunner;
52import android.testing.TestableLooper;
53import android.view.WindowManager;
54
55import androidx.test.filters.SmallTest;
56
57import com.android.internal.colorextraction.ColorExtractor;
Beverlya53fb0d2020-01-29 15:26:13 -050058import com.android.systemui.SystemUIFactory;
59import com.android.systemui.SysuiTestCase;
60import com.android.systemui.colorextraction.SysuiColorExtractor;
Ned Burnsaaeb44b2020-02-12 23:48:26 -050061import com.android.systemui.dump.DumpManager;
Joshua Tsujibe60a582020-03-23 17:17:26 -040062import com.android.systemui.model.SysUiState;
Beverlya53fb0d2020-01-29 15:26:13 -050063import com.android.systemui.plugins.statusbar.StatusBarStateController;
64import com.android.systemui.statusbar.FeatureFlags;
65import com.android.systemui.statusbar.NotificationLockscreenUserManager;
Mady Mellor76343012020-05-13 11:02:50 -070066import com.android.systemui.statusbar.RankingBuilder;
Beverlya53fb0d2020-01-29 15:26:13 -050067import com.android.systemui.statusbar.SuperStatusBarViewFactory;
68import com.android.systemui.statusbar.SysuiStatusBarStateController;
69import com.android.systemui.statusbar.notification.NotificationEntryManager;
70import com.android.systemui.statusbar.notification.NotificationFilter;
Beverlya53fb0d2020-01-29 15:26:13 -050071import com.android.systemui.statusbar.notification.collection.NotifPipeline;
72import com.android.systemui.statusbar.notification.collection.NotificationEntry;
73import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
74import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
75import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
76import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
77import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
78import com.android.systemui.statusbar.phone.DozeParameters;
79import com.android.systemui.statusbar.phone.KeyguardBypassController;
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -050080import com.android.systemui.statusbar.phone.LockscreenLockIconController;
Beverlya53fb0d2020-01-29 15:26:13 -050081import com.android.systemui.statusbar.phone.NotificationGroupManager;
82import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
Fabian Kozynskib00c70b2020-04-03 12:41:31 -040083import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
Beverlya53fb0d2020-01-29 15:26:13 -050084import com.android.systemui.statusbar.phone.ShadeController;
85import com.android.systemui.statusbar.policy.BatteryController;
86import com.android.systemui.statusbar.policy.ConfigurationController;
87import com.android.systemui.statusbar.policy.HeadsUpManager;
88import com.android.systemui.statusbar.policy.ZenModeController;
Joshua Tsuji7155bf12020-02-13 16:14:29 -050089import com.android.systemui.util.FloatingContentCoordinator;
Beverlya53fb0d2020-01-29 15:26:13 -050090import com.android.systemui.util.InjectionInflationController;
91
92import org.junit.Before;
93import org.junit.Test;
94import org.junit.runner.RunWith;
95import org.mockito.ArgumentCaptor;
96import org.mockito.Captor;
97import org.mockito.Mock;
98import org.mockito.MockitoAnnotations;
99
100import java.util.List;
101
102/**
103 * Tests the NotifPipeline setup with BubbleController.
104 * The NotificationEntryManager setup with BubbleController is tested in
105 * {@link BubbleControllerTest}.
106 */
107@SmallTest
108@RunWith(AndroidTestingRunner.class)
109@TestableLooper.RunWithLooper(setAsMainLooper = true)
110public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
111 @Mock
112 private NotificationEntryManager mNotificationEntryManager;
113 @Mock
114 private NotificationGroupManager mNotificationGroupManager;
115 @Mock
116 private BubbleController.NotifCallback mNotifCallback;
117 @Mock
118 private WindowManager mWindowManager;
119 @Mock
120 private IActivityManager mActivityManager;
121 @Mock
122 private DozeParameters mDozeParameters;
123 @Mock
124 private ConfigurationController mConfigurationController;
125 @Mock
126 private ZenModeController mZenModeController;
127 @Mock
128 private ZenModeConfig mZenModeConfig;
129 @Mock
130 private FaceManager mFaceManager;
131 @Mock
132 private NotificationLockscreenUserManager mLockscreenUserManager;
133 @Mock
134 private SysuiStatusBarStateController mStatusBarStateController;
135 @Mock
136 private KeyguardBypassController mKeyguardBypassController;
Joshua Tsuji7155bf12020-02-13 16:14:29 -0500137 @Mock
138 private FloatingContentCoordinator mFloatingContentCoordinator;
Fabian Kozynskib00c70b2020-04-03 12:41:31 -0400139 @Mock
Pinyao Tingee191b12020-04-29 18:35:39 -0700140 private BubbleDataRepository mDataRepository;
141 @Mock
Fabian Kozynskib00c70b2020-04-03 12:41:31 -0400142 private NotificationShadeWindowView mNotificationShadeWindowView;
Joshua Tsujibe60a582020-03-23 17:17:26 -0400143
144 private SysUiState mSysUiState = new SysUiState();
145
Beverlya53fb0d2020-01-29 15:26:13 -0500146 @Captor
147 private ArgumentCaptor<NotifCollectionListener> mNotifListenerCaptor;
Beverlya53fb0d2020-01-29 15:26:13 -0500148 private TestableBubbleController mBubbleController;
149 private NotificationShadeWindowController mNotificationShadeWindowController;
150 private NotifCollectionListener mEntryListener;
Beverlya53fb0d2020-01-29 15:26:13 -0500151 private NotificationTestHelper mNotificationTestHelper;
152 private ExpandableNotificationRow mRow;
153 private ExpandableNotificationRow mRow2;
154 private ExpandableNotificationRow mNonBubbleNotifRow;
Beverlya53fb0d2020-01-29 15:26:13 -0500155 @Mock
Beverlya53fb0d2020-01-29 15:26:13 -0500156 private BubbleController.BubbleExpandListener mBubbleExpandListener;
157 @Mock
158 private PendingIntent mDeleteIntent;
159 @Mock
160 private SysuiColorExtractor mColorExtractor;
161 @Mock
162 ColorExtractor.GradientColors mGradientColors;
163 @Mock
164 private Resources mResources;
165 @Mock
166 private ShadeController mShadeController;
167 @Mock
168 private NotificationRowComponent mNotificationRowComponent;
169 @Mock
170 private NotifPipeline mNotifPipeline;
171 @Mock
172 private FeatureFlags mFeatureFlagsNewPipeline;
173 @Mock
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500174 private DumpManager mDumpManager;
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500175 @Mock
176 private LockscreenLockIconController mLockIconController;
Beverlya53fb0d2020-01-29 15:26:13 -0500177
178 private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
179 private BubbleData mBubbleData;
180
181 private TestableLooper mTestableLooper;
182
183 @Before
184 public void setUp() throws Exception {
185 MockitoAnnotations.initMocks(this);
186
187 mTestableLooper = TestableLooper.get(this);
188
189 mContext.addMockSystemService(FaceManager.class, mFaceManager);
190 when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
191
192 mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
193 new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()),
194 new NotificationRowComponent.Builder() {
195 @Override
196 public NotificationRowComponent.Builder activatableNotificationView(
197 ActivatableNotificationView view) {
198 return this;
199 }
200
201 @Override
202 public NotificationRowComponent build() {
203 return mNotificationRowComponent;
204 }
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500205 },
206 mLockIconController);
Beverlya53fb0d2020-01-29 15:26:13 -0500207
208 // Bubbles get added to status bar window view
209 mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
210 mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
Lucas Dupind73410a2020-02-18 12:54:41 -0800211 mConfigurationController, mKeyguardBypassController, mColorExtractor,
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500212 mDumpManager);
Fabian Kozynskib00c70b2020-04-03 12:41:31 -0400213 mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
Beverlya53fb0d2020-01-29 15:26:13 -0500214 mNotificationShadeWindowController.attach();
215
216 // Need notifications for bubbles
Kevin Hana7c21be2020-04-01 17:58:35 -0700217 mNotificationTestHelper = new NotificationTestHelper(
218 mContext,
219 mDependency,
220 TestableLooper.get(this));
Beverlya53fb0d2020-01-29 15:26:13 -0500221 mRow = mNotificationTestHelper.createBubble(mDeleteIntent);
222 mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent);
223 mNonBubbleNotifRow = mNotificationTestHelper.createRow();
224
225 mZenModeConfig.suppressedVisualEffects = 0;
226 when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
227
Beverly Taid1e175c2020-03-10 16:37:04 +0000228 TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
229 new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
230 mock(PowerManager.class),
231 mock(IDreamManager.class),
232 mock(AmbientDisplayConfiguration.class),
Beverlya53fb0d2020-01-29 15:26:13 -0500233 mock(NotificationFilter.class),
234 mock(StatusBarStateController.class),
Beverly Taid1e175c2020-03-10 16:37:04 +0000235 mock(BatteryController.class),
236 mock(HeadsUpManager.class),
237 mock(Handler.class)
238 );
Beverlya53fb0d2020-01-29 15:26:13 -0500239 mBubbleData = new BubbleData(mContext);
240 when(mFeatureFlagsNewPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500241 mBubbleController = new TestableBubbleController(
242 mContext,
Beverlya53fb0d2020-01-29 15:26:13 -0500243 mNotificationShadeWindowController,
244 mStatusBarStateController,
245 mShadeController,
246 mBubbleData,
247 mConfigurationController,
248 interruptionStateProvider,
249 mZenModeController,
250 mLockscreenUserManager,
251 mNotificationGroupManager,
252 mNotificationEntryManager,
253 mNotifPipeline,
254 mFeatureFlagsNewPipeline,
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500255 mDumpManager,
Joshua Tsujibe60a582020-03-23 17:17:26 -0400256 mFloatingContentCoordinator,
Pinyao Tingee191b12020-04-29 18:35:39 -0700257 mDataRepository,
Mady Mellor9adfe6a2020-03-30 17:23:26 -0700258 mSysUiState,
Mady Mellor59a7b982020-05-11 15:19:59 -0700259 mock(INotificationManager.class),
260 mWindowManager);
Beverlya53fb0d2020-01-29 15:26:13 -0500261 mBubbleController.addNotifCallback(mNotifCallback);
Beverlya53fb0d2020-01-29 15:26:13 -0500262 mBubbleController.setExpandListener(mBubbleExpandListener);
263
264 // Get a reference to the BubbleController's entry listener
265 verify(mNotifPipeline, atLeastOnce())
266 .addCollectionListener(mNotifListenerCaptor.capture());
267 mEntryListener = mNotifListenerCaptor.getValue();
268 }
269
270 @Test
271 public void testAddBubble() {
272 mBubbleController.updateBubble(mRow.getEntry());
273 assertTrue(mBubbleController.hasBubbles());
Beverlya53fb0d2020-01-29 15:26:13 -0500274 }
275
276 @Test
277 public void testHasBubbles() {
278 assertFalse(mBubbleController.hasBubbles());
279 mBubbleController.updateBubble(mRow.getEntry());
280 assertTrue(mBubbleController.hasBubbles());
281 }
282
283 @Test
284 public void testRemoveBubble() {
285 mBubbleController.updateBubble(mRow.getEntry());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700286 assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500287 assertTrue(mBubbleController.hasBubbles());
288 verify(mNotifCallback, times(1)).invalidateNotifications(anyString());
Beverlya53fb0d2020-01-29 15:26:13 -0500289
Pinyao Ting3c930612020-05-19 00:26:03 +0000290 mBubbleController.removeBubble(
291 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700292 assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500293 verify(mNotifCallback, times(2)).invalidateNotifications(anyString());
Beverlya53fb0d2020-01-29 15:26:13 -0500294 }
295
296 @Test
Lyn Han2f6e89d2020-04-15 10:01:01 -0700297 public void testRemoveBubble_withDismissedNotif_inOverflow() {
Beverlya53fb0d2020-01-29 15:26:13 -0500298 mEntryListener.onEntryAdded(mRow.getEntry());
299 mBubbleController.updateBubble(mRow.getEntry());
300
301 assertTrue(mBubbleController.hasBubbles());
302 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry()));
303
304 // Make it look like dismissed notif
Lyn Han2f6e89d2020-04-15 10:01:01 -0700305 mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).setSuppressNotification(true);
Beverlya53fb0d2020-01-29 15:26:13 -0500306
307 // Now remove the bubble
Pinyao Ting3c930612020-05-19 00:26:03 +0000308 mBubbleController.removeBubble(
309 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700310 assertTrue(mBubbleData.hasOverflowBubbleWithKey(mRow.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500311
Lyn Han2f6e89d2020-04-15 10:01:01 -0700312 // We don't remove the notification since the bubble is still in overflow.
313 verify(mNotifCallback, never()).removeNotification(eq(mRow.getEntry()), anyInt());
314 assertFalse(mBubbleController.hasBubbles());
315 }
316
317 @Test
318 public void testRemoveBubble_withDismissedNotif_notInOverflow() {
319 mEntryListener.onEntryAdded(mRow.getEntry());
320 mBubbleController.updateBubble(mRow.getEntry());
321
322 assertTrue(mBubbleController.hasBubbles());
323 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry()));
324
325 // Make it look like dismissed notif
326 mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).setSuppressNotification(true);
327
328 // Now remove the bubble
Pinyao Ting3c930612020-05-19 00:26:03 +0000329 mBubbleController.removeBubble(
330 mRow.getEntry().getKey(), BubbleController.DISMISS_NOTIF_CANCEL);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700331 assertFalse(mBubbleData.hasOverflowBubbleWithKey(mRow.getEntry().getKey()));
332
333 // Since the notif is dismissed and not in overflow, once the bubble is removed,
334 // removeNotification gets called to really remove the notif
Beverlya53fb0d2020-01-29 15:26:13 -0500335 verify(mNotifCallback, times(1)).removeNotification(eq(mRow.getEntry()), anyInt());
336 assertFalse(mBubbleController.hasBubbles());
337 }
338
339 @Test
340 public void testDismissStack() {
341 mBubbleController.updateBubble(mRow.getEntry());
342 verify(mNotifCallback, times(1)).invalidateNotifications(anyString());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700343 assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500344 mBubbleController.updateBubble(mRow2.getEntry());
Lyn Han9f66c3b2020-03-05 23:59:29 -0800345 verify(mNotifCallback, times(2)).invalidateNotifications(anyString());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700346 assertNotNull(mBubbleData.getBubbleInStackWithKey(mRow2.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500347 assertTrue(mBubbleController.hasBubbles());
348
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400349 mBubbleData.dismissAll(BubbleController.DISMISS_USER_GESTURE);
Beverlya53fb0d2020-01-29 15:26:13 -0500350 verify(mNotifCallback, times(3)).invalidateNotifications(anyString());
Lyn Han2f6e89d2020-04-15 10:01:01 -0700351 assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
352 assertNull(mBubbleData.getBubbleInStackWithKey(mRow2.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500353 }
354
355 @Test
356 public void testExpandCollapseStack() {
357 assertFalse(mBubbleController.isStackExpanded());
358
359 // Mark it as a bubble and add it explicitly
360 mEntryListener.onEntryAdded(mRow.getEntry());
361 mBubbleController.updateBubble(mRow.getEntry());
362
363 // We should have bubbles & their notifs should not be suppressed
364 assertTrue(mBubbleController.hasBubbles());
365 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
366 mRow.getEntry()));
Beverlya53fb0d2020-01-29 15:26:13 -0500367
368 // Expand the stack
369 BubbleStackView stackView = mBubbleController.getStackView();
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400370 mBubbleData.setExpanded(true);
Beverlya53fb0d2020-01-29 15:26:13 -0500371 assertTrue(mBubbleController.isStackExpanded());
372 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
Beverlya53fb0d2020-01-29 15:26:13 -0500373
374 // Make sure the notif is suppressed
375 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry()));
376
377 // Collapse
378 mBubbleController.collapseStack();
379 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
380 assertFalse(mBubbleController.isStackExpanded());
Beverlya53fb0d2020-01-29 15:26:13 -0500381 }
382
383 @Test
384 public void testCollapseAfterChangingExpandedBubble() {
385 // Mark it as a bubble and add it explicitly
386 mEntryListener.onEntryAdded(mRow.getEntry());
387 mEntryListener.onEntryAdded(mRow2.getEntry());
388 mBubbleController.updateBubble(mRow.getEntry());
389 mBubbleController.updateBubble(mRow2.getEntry());
390
391 // We should have bubbles & their notifs should not be suppressed
392 assertTrue(mBubbleController.hasBubbles());
393 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
394 mRow.getEntry()));
395 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
396 mRow2.getEntry()));
397
398 // Expand
399 BubbleStackView stackView = mBubbleController.getStackView();
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400400 mBubbleData.setExpanded(true);
Beverlya53fb0d2020-01-29 15:26:13 -0500401 assertTrue(mBubbleController.isStackExpanded());
402 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
403
404 // Last added is the one that is expanded
405 assertEquals(mRow2.getEntry(), mBubbleData.getSelectedBubble().getEntry());
406 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow2.getEntry()));
407
408 // Switch which bubble is expanded
Lyn Han2f6e89d2020-04-15 10:01:01 -0700409 mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500410 mBubbleData.setExpanded(true);
Lyn Han9f66c3b2020-03-05 23:59:29 -0800411 assertEquals(mRow.getEntry(),
Lyn Han2f6e89d2020-04-15 10:01:01 -0700412 mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
Beverlya53fb0d2020-01-29 15:26:13 -0500413 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
414 mRow.getEntry()));
415
416 // collapse for previous bubble
417 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
418 // expand for selected bubble
419 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
420
421 // Collapse
422 mBubbleController.collapseStack();
423 assertFalse(mBubbleController.isStackExpanded());
424 }
425
426 @Test
427 public void testExpansionRemovesShowInShadeAndDot() {
428 // Mark it as a bubble and add it explicitly
429 mEntryListener.onEntryAdded(mRow.getEntry());
430 mBubbleController.updateBubble(mRow.getEntry());
431
432 // We should have bubbles & their notifs should not be suppressed
433 assertTrue(mBubbleController.hasBubbles());
434 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry()));
435
436 mTestableLooper.processAllMessages();
Lyn Han2f6e89d2020-04-15 10:01:01 -0700437 assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Beverlya53fb0d2020-01-29 15:26:13 -0500438
439 // Expand
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400440 mBubbleData.setExpanded(true);
Beverlya53fb0d2020-01-29 15:26:13 -0500441 assertTrue(mBubbleController.isStackExpanded());
442 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
443
444 // Notif is suppressed after expansion
445 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
446 mRow.getEntry()));
447 // Notif shouldn't show dot after expansion
Lyn Han2f6e89d2020-04-15 10:01:01 -0700448 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Beverlya53fb0d2020-01-29 15:26:13 -0500449 }
450
451 @Test
452 public void testUpdateWhileExpanded_DoesntChangeShowInShadeAndDot() {
453 // Mark it as a bubble and add it explicitly
454 mEntryListener.onEntryAdded(mRow.getEntry());
455 mBubbleController.updateBubble(mRow.getEntry());
456
457 // We should have bubbles & their notifs should not be suppressed
458 assertTrue(mBubbleController.hasBubbles());
459 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
460 mRow.getEntry()));
461
462 mTestableLooper.processAllMessages();
Lyn Han2f6e89d2020-04-15 10:01:01 -0700463 assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Beverlya53fb0d2020-01-29 15:26:13 -0500464
465 // Expand
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400466 mBubbleData.setExpanded(true);
Beverlya53fb0d2020-01-29 15:26:13 -0500467 assertTrue(mBubbleController.isStackExpanded());
468 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
469
470 // Notif is suppressed after expansion
471 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
472 mRow.getEntry()));
473 // Notif shouldn't show dot after expansion
Lyn Han2f6e89d2020-04-15 10:01:01 -0700474 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Beverlya53fb0d2020-01-29 15:26:13 -0500475
476 // Send update
477 mEntryListener.onEntryUpdated(mRow.getEntry());
478
479 // Nothing should have changed
480 // Notif is suppressed after expansion
481 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
482 mRow.getEntry()));
483 // Notif shouldn't show dot after expansion
Lyn Han2f6e89d2020-04-15 10:01:01 -0700484 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Beverlya53fb0d2020-01-29 15:26:13 -0500485 }
486
487 @Test
488 public void testRemoveLastExpandedCollapses() {
489 // Mark it as a bubble and add it explicitly
490 mEntryListener.onEntryAdded(mRow.getEntry());
491 mEntryListener.onEntryAdded(mRow2.getEntry());
492 mBubbleController.updateBubble(mRow.getEntry());
493 mBubbleController.updateBubble(mRow2.getEntry());
Beverlya53fb0d2020-01-29 15:26:13 -0500494
495 // Expand
496 BubbleStackView stackView = mBubbleController.getStackView();
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400497 mBubbleData.setExpanded(true);
Beverlya53fb0d2020-01-29 15:26:13 -0500498
499 assertTrue(mBubbleController.isStackExpanded());
500 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
501
502 // Last added is the one that is expanded
Lyn Han9f66c3b2020-03-05 23:59:29 -0800503 assertEquals(mRow2.getEntry(),
Lyn Han2f6e89d2020-04-15 10:01:01 -0700504 mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
Beverlya53fb0d2020-01-29 15:26:13 -0500505 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
506 mRow2.getEntry()));
507
508 // Dismiss currently expanded
Lyn Han9f66c3b2020-03-05 23:59:29 -0800509 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000510 mBubbleData.getBubbleInStackWithKey(
511 stackView.getExpandedBubble().getKey()).getEntry().getKey(),
Beverlya53fb0d2020-01-29 15:26:13 -0500512 BubbleController.DISMISS_USER_GESTURE);
513 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
514
515 // Make sure first bubble is selected
Lyn Han9f66c3b2020-03-05 23:59:29 -0800516 assertEquals(mRow.getEntry(),
Lyn Han2f6e89d2020-04-15 10:01:01 -0700517 mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
Beverlya53fb0d2020-01-29 15:26:13 -0500518 verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
519
520 // Dismiss that one
Lyn Han9f66c3b2020-03-05 23:59:29 -0800521 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000522 mBubbleData.getBubbleInStackWithKey(
523 stackView.getExpandedBubble().getKey()).getEntry().getKey(),
Beverlya53fb0d2020-01-29 15:26:13 -0500524 BubbleController.DISMISS_USER_GESTURE);
525
526 // Make sure state changes and collapse happens
527 verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
Beverlya53fb0d2020-01-29 15:26:13 -0500528 assertFalse(mBubbleController.hasBubbles());
529 }
530
531 @Test
532 public void testAutoExpand_fails_noFlag() {
533 assertFalse(mBubbleController.isStackExpanded());
534 setMetadataFlags(mRow.getEntry(),
535 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, false /* enableFlag */);
536
537 // Add the auto expand bubble
538 mEntryListener.onEntryAdded(mRow.getEntry());
539 mBubbleController.updateBubble(mRow.getEntry());
540
541 // Expansion shouldn't change
542 verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
543 mRow.getEntry().getKey());
544 assertFalse(mBubbleController.isStackExpanded());
Beverlya53fb0d2020-01-29 15:26:13 -0500545 }
546
547 @Test
548 public void testAutoExpand_succeeds_withFlag() {
549 setMetadataFlags(mRow.getEntry(),
550 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, true /* enableFlag */);
551
552 // Add the auto expand bubble
553 mEntryListener.onEntryAdded(mRow.getEntry());
554 mBubbleController.updateBubble(mRow.getEntry());
555
556 // Expansion should change
557 verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
558 mRow.getEntry().getKey());
559 assertTrue(mBubbleController.isStackExpanded());
Beverlya53fb0d2020-01-29 15:26:13 -0500560 }
561
562 @Test
563 public void testSuppressNotif_onInitialNotif() {
564 setMetadataFlags(mRow.getEntry(),
565 Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, true /* enableFlag */);
566
567 // Add the suppress notif bubble
568 mEntryListener.onEntryAdded(mRow.getEntry());
569 mBubbleController.updateBubble(mRow.getEntry());
570
571 // Notif should be suppressed because we were foreground
572 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
573 mRow.getEntry()));
574 // Dot + flyout is hidden because notif is suppressed
Lyn Han2f6e89d2020-04-15 10:01:01 -0700575 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
576 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showFlyout());
Beverlya53fb0d2020-01-29 15:26:13 -0500577 }
578
579 @Test
580 public void testSuppressNotif_onUpdateNotif() {
581 mBubbleController.updateBubble(mRow.getEntry());
582
583 // Should not be suppressed
584 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
585 mRow.getEntry()));
586 // Should show dot
Lyn Han2f6e89d2020-04-15 10:01:01 -0700587 assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Beverlya53fb0d2020-01-29 15:26:13 -0500588
589 // Update to suppress notif
590 setMetadataFlags(mRow.getEntry(),
591 Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, true /* enableFlag */);
592 mBubbleController.updateBubble(mRow.getEntry());
593
594 // Notif should be suppressed
595 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
596 mRow.getEntry()));
597 // Dot + flyout is hidden because notif is suppressed
Lyn Han2f6e89d2020-04-15 10:01:01 -0700598 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
599 assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showFlyout());
Beverlya53fb0d2020-01-29 15:26:13 -0500600 }
601
602 @Test
603 public void testMarkNewNotificationAsShowInShade() {
604 mEntryListener.onEntryAdded(mRow.getEntry());
605 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
606 mRow.getEntry()));
607
608 mTestableLooper.processAllMessages();
Lyn Han2f6e89d2020-04-15 10:01:01 -0700609 assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).showDot());
Beverlya53fb0d2020-01-29 15:26:13 -0500610 }
611
612 @Test
613 public void testAddNotif_notBubble() {
614 mEntryListener.onEntryAdded(mNonBubbleNotifRow.getEntry());
615 mEntryListener.onEntryUpdated(mNonBubbleNotifRow.getEntry());
616
Beverlya53fb0d2020-01-29 15:26:13 -0500617 assertThat(mBubbleController.hasBubbles()).isFalse();
618 }
619
620 @Test
621 public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException {
622 mBubbleController.updateBubble(mRow.getEntry());
Pinyao Ting3c930612020-05-19 00:26:03 +0000623 mBubbleController.removeBubble(mRow.getEntry().getKey(), BubbleController.DISMISS_AGED);
Beverlya53fb0d2020-01-29 15:26:13 -0500624 verify(mDeleteIntent, never()).send();
625 }
626
627 @Test
628 public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException {
629 mBubbleController.updateBubble(mRow.getEntry());
630 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000631 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Beverlya53fb0d2020-01-29 15:26:13 -0500632 verify(mDeleteIntent, times(1)).send();
633 }
634
635 @Test
636 public void testDeleteIntent_dismissStack() throws PendingIntent.CanceledException {
637 mBubbleController.updateBubble(mRow.getEntry());
638 mBubbleController.updateBubble(mRow2.getEntry());
Joshua Tsuji7dd88b02020-03-27 17:43:09 -0400639 mBubbleData.dismissAll(BubbleController.DISMISS_USER_GESTURE);
Beverlya53fb0d2020-01-29 15:26:13 -0500640 verify(mDeleteIntent, times(2)).send();
641 }
642
643 @Test
644 public void testRemoveBubble_noLongerBubbleAfterUpdate()
645 throws PendingIntent.CanceledException {
646 mBubbleController.updateBubble(mRow.getEntry());
647 assertTrue(mBubbleController.hasBubbles());
648
649 mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
Mady Mellor76343012020-05-13 11:02:50 -0700650 NotificationListenerService.Ranking ranking = new RankingBuilder(
651 mRow.getEntry().getRanking()).setCanBubble(false).build();
652 mRow.getEntry().setRanking(ranking);
Beverlya53fb0d2020-01-29 15:26:13 -0500653 mEntryListener.onEntryUpdated(mRow.getEntry());
654
655 assertFalse(mBubbleController.hasBubbles());
656 verify(mDeleteIntent, never()).send();
657 }
658
659 @Test
660 public void testRemoveBubble_entryListenerRemove() {
661 mEntryListener.onEntryAdded(mRow.getEntry());
662 mBubbleController.updateBubble(mRow.getEntry());
663
664 assertTrue(mBubbleController.hasBubbles());
665
666 // Removes the notification
667 mEntryListener.onEntryRemoved(mRow.getEntry(), 0);
668 assertFalse(mBubbleController.hasBubbles());
669 }
670
671 @Test
Lyn Han9f66c3b2020-03-05 23:59:29 -0800672 public void removeBubble_intercepted() {
Beverlya53fb0d2020-01-29 15:26:13 -0500673 mEntryListener.onEntryAdded(mRow.getEntry());
674 mBubbleController.updateBubble(mRow.getEntry());
675
676 assertTrue(mBubbleController.hasBubbles());
677 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
678 mRow.getEntry()));
679
680 boolean intercepted = mBubbleController.handleDismissalInterception(mRow.getEntry());
681
682 // Intercept!
683 assertTrue(intercepted);
684 // Should update show in shade state
685 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry()));
686 }
687
688 @Test
Lyn Han2f6e89d2020-04-15 10:01:01 -0700689 public void removeBubble_dismissIntoOverflow_intercepted() {
Beverlya53fb0d2020-01-29 15:26:13 -0500690 mEntryListener.onEntryAdded(mRow.getEntry());
691 mBubbleController.updateBubble(mRow.getEntry());
692
693 assertTrue(mBubbleController.hasBubbles());
694 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
695 mRow.getEntry()));
696
697 // Dismiss the bubble
698 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000699 mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
Beverlya53fb0d2020-01-29 15:26:13 -0500700 assertFalse(mBubbleController.hasBubbles());
701
702 // Dismiss the notification
703 boolean intercepted = mBubbleController.handleDismissalInterception(mRow.getEntry());
704
Lyn Han2f6e89d2020-04-15 10:01:01 -0700705 // Intercept dismissal since bubble is going into overflow
706 assertTrue(intercepted);
707 }
708
709 @Test
710 public void removeBubble_notIntercepted() {
711 mEntryListener.onEntryAdded(mRow.getEntry());
712 mBubbleController.updateBubble(mRow.getEntry());
713
714 assertTrue(mBubbleController.hasBubbles());
715 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
716 mRow.getEntry()));
717
718 // Dismiss the bubble
719 mBubbleController.removeBubble(
Pinyao Ting3c930612020-05-19 00:26:03 +0000720 mRow.getEntry().getKey(), BubbleController.DISMISS_NOTIF_CANCEL);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700721 assertFalse(mBubbleController.hasBubbles());
722
723 // Dismiss the notification
724 boolean intercepted = mBubbleController.handleDismissalInterception(mRow.getEntry());
725
726 // Not a bubble anymore so we don't intercept dismissal.
Beverlya53fb0d2020-01-29 15:26:13 -0500727 assertFalse(intercepted);
728 }
729
730 @Test
731 public void testNotifyShadeSuppressionChange_notificationDismiss() {
732 BubbleController.NotificationSuppressionChangedListener listener =
733 mock(BubbleController.NotificationSuppressionChangedListener.class);
734 mBubbleData.setSuppressionChangedListener(listener);
735
736 mEntryListener.onEntryAdded(mRow.getEntry());
737
738 assertTrue(mBubbleController.hasBubbles());
739 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
740 mRow.getEntry()));
741
742 mBubbleController.handleDismissalInterception(mRow.getEntry());
743
744 // Should update show in shade state
745 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
746 mRow.getEntry()));
747
748 // Should notify delegate that shade state changed
749 verify(listener).onBubbleNotificationSuppressionChange(
Lyn Han2f6e89d2020-04-15 10:01:01 -0700750 mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500751 }
752
753 @Test
754 public void testNotifyShadeSuppressionChange_bubbleExpanded() {
755 BubbleController.NotificationSuppressionChangedListener listener =
756 mock(BubbleController.NotificationSuppressionChangedListener.class);
757 mBubbleData.setSuppressionChangedListener(listener);
758
759 mEntryListener.onEntryAdded(mRow.getEntry());
760
761 assertTrue(mBubbleController.hasBubbles());
762 assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
763 mRow.getEntry()));
764
765 mBubbleData.setExpanded(true);
766
767 // Once a bubble is expanded the notif is suppressed
768 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
769 mRow.getEntry()));
770
771 // Should notify delegate that shade state changed
772 verify(listener).onBubbleNotificationSuppressionChange(
Lyn Han2f6e89d2020-04-15 10:01:01 -0700773 mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500774 }
775
776 @Test
777 public void testBubbleSummaryDismissal_suppressesSummaryAndBubbleFromShade() throws Exception {
778 // GIVEN a group summary with a bubble child
779 ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
780 ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
781 mEntryListener.onEntryAdded(groupedBubble.getEntry());
782 groupSummary.addChildNotification(groupedBubble);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700783 assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500784
785 // WHEN the summary is dismissed
786 mBubbleController.handleDismissalInterception(groupSummary.getEntry());
787
788 // THEN the summary and bubbled child are suppressed from the shade
789 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
790 groupedBubble.getEntry()));
791 assertTrue(mBubbleData.isSummarySuppressed(groupSummary.getEntry().getSbn().getGroupKey()));
792 }
793
794 @Test
795 public void testAppRemovesSummary_removesAllBubbleChildren() throws Exception {
796 // GIVEN a group summary with a bubble child
797 ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
798 ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
799 mEntryListener.onEntryAdded(groupedBubble.getEntry());
800 groupSummary.addChildNotification(groupedBubble);
Lyn Han2f6e89d2020-04-15 10:01:01 -0700801 assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500802
803 // GIVEN the summary is dismissed
804 mBubbleController.handleDismissalInterception(groupSummary.getEntry());
805
806 // WHEN the summary is cancelled by the app
807 mEntryListener.onEntryRemoved(groupSummary.getEntry(), 0);
808
809 // THEN the summary and its children are removed from bubble data
Lyn Han2f6e89d2020-04-15 10:01:01 -0700810 assertFalse(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500811 assertFalse(mBubbleData.isSummarySuppressed(
812 groupSummary.getEntry().getSbn().getGroupKey()));
813 }
814
815 @Test
816 public void testSummaryDismissalMarksBubblesHiddenFromShadeAndDismissesNonBubbledChildren()
817 throws Exception {
818 // GIVEN a group summary with two (non-bubble) children and one bubble child
819 ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
820 ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
821 mEntryListener.onEntryAdded(groupedBubble.getEntry());
822 groupSummary.addChildNotification(groupedBubble);
823
824 // WHEN the summary is dismissed
825 mBubbleController.handleDismissalInterception(groupSummary.getEntry());
826
827 // THEN only the NON-bubble children are dismissed
Kevin Han43077f92020-02-28 12:51:53 -0800828 List<ExpandableNotificationRow> childrenRows = groupSummary.getAttachedChildren();
Beverlya53fb0d2020-01-29 15:26:13 -0500829 verify(mNotifCallback, times(1)).removeNotification(
830 childrenRows.get(0).getEntry(), REASON_GROUP_SUMMARY_CANCELED);
831 verify(mNotifCallback, times(1)).removeNotification(
832 childrenRows.get(1).getEntry(), REASON_GROUP_SUMMARY_CANCELED);
833 verify(mNotifCallback, never()).removeNotification(eq(groupedBubble.getEntry()), anyInt());
834
835 // THEN the bubble child still exists as a bubble and is suppressed from the shade
Lyn Han2f6e89d2020-04-15 10:01:01 -0700836 assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
Beverlya53fb0d2020-01-29 15:26:13 -0500837 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
838 groupedBubble.getEntry()));
839
840 // THEN the summary is also suppressed from the shade
841 assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
842 groupSummary.getEntry()));
843 }
844
Beverlya53fb0d2020-01-29 15:26:13 -0500845 /**
846 * Sets the bubble metadata flags for this entry. These flags are normally set by
847 * NotificationManagerService when the notification is sent, however, these tests do not
848 * go through that path so we set them explicitly when testing.
849 */
850 private void setMetadataFlags(NotificationEntry entry, int flag, boolean enableFlag) {
851 Notification.BubbleMetadata bubbleMetadata =
852 entry.getSbn().getNotification().getBubbleMetadata();
853 int flags = bubbleMetadata.getFlags();
854 if (enableFlag) {
855 flags |= flag;
856 } else {
857 flags &= ~flag;
858 }
859 bubbleMetadata.setFlags(flags);
860 }
861}