blob: 885dff39f7b393d980288679dfdd5a89fdbd77ae [file] [log] [blame]
Kevin01a53cb2018-11-09 18:19:54 -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.statusbar.phone;
18
Julia Reynolds138111f2020-02-26 11:17:39 -050019import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
Kevin Han933dc7c2020-01-29 11:17:46 -080020import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
21
Kevin01a53cb2018-11-09 18:19:54 -080022import static org.junit.Assert.assertFalse;
23import static org.junit.Assert.assertTrue;
Kevin Han933dc7c2020-01-29 11:17:46 -080024import static org.mockito.ArgumentMatchers.any;
25import static org.mockito.ArgumentMatchers.eq;
Kevin4b8bbda2018-11-19 14:36:31 -080026import static org.mockito.Mockito.doReturn;
Selim Cinekc3fec682019-06-06 18:11:07 -070027import static org.mockito.Mockito.mock;
Kevin4b8bbda2018-11-19 14:36:31 -080028import static org.mockito.Mockito.spy;
Kevin01a53cb2018-11-09 18:19:54 -080029import static org.mockito.Mockito.verify;
30import static org.mockito.Mockito.when;
31
32import android.app.Notification;
Kevin4b8bbda2018-11-19 14:36:31 -080033import android.service.notification.StatusBarNotification;
Kevin01a53cb2018-11-09 18:19:54 -080034import android.testing.AndroidTestingRunner;
35import android.testing.TestableLooper;
36
Brett Chabot84151d92019-02-27 15:37:59 -080037import androidx.test.filters.SmallTest;
38
Kevin01a53cb2018-11-09 18:19:54 -080039import com.android.systemui.SysuiTestCase;
Lucas Dupind236ee32019-10-08 15:33:59 -070040import com.android.systemui.bubbles.BubbleController;
Selim Cinekc3fec682019-06-06 18:11:07 -070041import com.android.systemui.plugins.statusbar.StatusBarStateController;
Gus Prevasd65c2db2018-12-18 17:13:38 -050042import com.android.systemui.statusbar.notification.NotificationEntryListener;
Ned Burns3d6b3962018-12-07 21:26:00 -050043import com.android.systemui.statusbar.notification.NotificationEntryManager;
Ned Burnsf81c4c42019-01-07 14:10:43 -050044import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Steve Elliottd38a70f2020-05-11 14:01:08 -040045import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
Kevin Han933dc7c2020-01-29 11:17:46 -080046import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback;
47import com.android.systemui.statusbar.notification.row.RowContentBindParams;
48import com.android.systemui.statusbar.notification.row.RowContentBindStage;
Kevin01a53cb2018-11-09 18:19:54 -080049import com.android.systemui.statusbar.policy.HeadsUpManager;
50
51import org.junit.Before;
52import org.junit.Rule;
53import org.junit.Test;
54import org.junit.runner.RunWith;
Ned Burns3d6b3962018-12-07 21:26:00 -050055import org.mockito.ArgumentCaptor;
56import org.mockito.Captor;
57import org.mockito.Mock;
Kevin Han933dc7c2020-01-29 11:17:46 -080058import org.mockito.MockitoAnnotations;
Kevin01a53cb2018-11-09 18:19:54 -080059import org.mockito.junit.MockitoJUnit;
60import org.mockito.junit.MockitoRule;
61
62import java.util.HashMap;
63
64@SmallTest
65@RunWith(AndroidTestingRunner.class)
66@TestableLooper.RunWithLooper
67public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {
Ned Burns3d6b3962018-12-07 21:26:00 -050068 @Rule public MockitoRule rule = MockitoJUnit.rule();
Kevin01a53cb2018-11-09 18:19:54 -080069
70 private NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
71 private NotificationGroupManager mGroupManager;
Kevin01a53cb2018-11-09 18:19:54 -080072 private HeadsUpManager mHeadsUpManager;
Ned Burns3d6b3962018-12-07 21:26:00 -050073 @Mock private NotificationEntryManager mNotificationEntryManager;
Kevin Han933dc7c2020-01-29 11:17:46 -080074 @Mock private RowContentBindStage mBindStage;
75 @Captor private ArgumentCaptor<NotificationEntryListener> mListenerCaptor;
Gus Prevasd65c2db2018-12-18 17:13:38 -050076 private NotificationEntryListener mNotificationEntryListener;
Ned Burnsf81c4c42019-01-07 14:10:43 -050077 private final HashMap<String, NotificationEntry> mPendingEntries = new HashMap<>();
Kevin01a53cb2018-11-09 18:19:54 -080078 private final NotificationGroupTestHelper mGroupTestHelper =
79 new NotificationGroupTestHelper(mContext);
80
81
82 @Before
83 public void setup() {
Kevin Han933dc7c2020-01-29 11:17:46 -080084 MockitoAnnotations.initMocks(this);
Lucas Dupind236ee32019-10-08 15:33:59 -070085 mDependency.injectMockDependency(BubbleController.class);
Kevin01a53cb2018-11-09 18:19:54 -080086 mHeadsUpManager = new HeadsUpManager(mContext) {};
87
Ned Burns3d6b3962018-12-07 21:26:00 -050088 when(mNotificationEntryManager.getPendingNotificationsIterator())
89 .thenReturn(mPendingEntries.values());
90
Steve Elliottd38a70f2020-05-11 14:01:08 -040091 mGroupManager = new NotificationGroupManager(
92 mock(StatusBarStateController.class),
93 () -> mock(PeopleNotificationIdentifier.class));
Kevin01a53cb2018-11-09 18:19:54 -080094 mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
95 mGroupManager.setHeadsUpManager(mHeadsUpManager);
96
Kevin Han933dc7c2020-01-29 11:17:46 -080097 when(mBindStage.getStageParams(any())).thenReturn(new RowContentBindParams());
98
99 mGroupAlertTransferHelper = new NotificationGroupAlertTransferHelper(mBindStage);
Kevin01a53cb2018-11-09 18:19:54 -0800100 mGroupAlertTransferHelper.setHeadsUpManager(mHeadsUpManager);
Kevin01a53cb2018-11-09 18:19:54 -0800101
Ned Burns3d6b3962018-12-07 21:26:00 -0500102 mGroupAlertTransferHelper.bind(mNotificationEntryManager, mGroupManager);
Gus Prevasd65c2db2018-12-18 17:13:38 -0500103 verify(mNotificationEntryManager).addNotificationEntryListener(mListenerCaptor.capture());
104 mNotificationEntryListener = mListenerCaptor.getValue();
Kevin01a53cb2018-11-09 18:19:54 -0800105 mHeadsUpManager.addListener(mGroupAlertTransferHelper);
Kevin01a53cb2018-11-09 18:19:54 -0800106 }
107
108 @Test
109 public void testSuppressedSummaryHeadsUpTransfersToChild() {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500110 NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification();
Kevin01a53cb2018-11-09 18:19:54 -0800111 mHeadsUpManager.showNotification(summaryEntry);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500112 NotificationEntry childEntry = mGroupTestHelper.createChildNotification();
Kevin01a53cb2018-11-09 18:19:54 -0800113
Kevin Han933dc7c2020-01-29 11:17:46 -0800114 RowContentBindParams params = new RowContentBindParams();
115 params.requireContentViews(FLAG_CONTENT_VIEW_HEADS_UP);
116 when(mBindStage.getStageParams(eq(childEntry))).thenReturn(params);
117
Kevin01a53cb2018-11-09 18:19:54 -0800118 // Summary will be suppressed because there is only one child.
119 mGroupManager.onEntryAdded(summaryEntry);
120 mGroupManager.onEntryAdded(childEntry);
121
122 // A suppressed summary should transfer its alert state to the child.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400123 assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
124 assertTrue(mHeadsUpManager.isAlerting(childEntry.getKey()));
Kevin01a53cb2018-11-09 18:19:54 -0800125 }
126
127 @Test
128 public void testSuppressedSummaryHeadsUpTransfersToChildButBackAgain() {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500129 NotificationEntry summaryEntry =
Kevin01a53cb2018-11-09 18:19:54 -0800130 mGroupTestHelper.createSummaryNotification(Notification.GROUP_ALERT_SUMMARY);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500131 NotificationEntry childEntry =
Kevin01a53cb2018-11-09 18:19:54 -0800132 mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500133 NotificationEntry childEntry2 =
Kevin01a53cb2018-11-09 18:19:54 -0800134 mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY);
135 mHeadsUpManager.showNotification(summaryEntry);
136 // Trigger a transfer of alert state from summary to child.
137 mGroupManager.onEntryAdded(summaryEntry);
138 mGroupManager.onEntryAdded(childEntry);
139
140 // Add second child notification so that summary is no longer suppressed.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400141 mPendingEntries.put(childEntry2.getKey(), childEntry2);
Gus Prevasd65c2db2018-12-18 17:13:38 -0500142 mNotificationEntryListener.onPendingEntryAdded(childEntry2);
Kevin01a53cb2018-11-09 18:19:54 -0800143 mGroupManager.onEntryAdded(childEntry2);
144
145 // The alert state should transfer back to the summary as there is now more than one
146 // child and the summary should no longer be suppressed.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400147 assertTrue(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
148 assertFalse(mHeadsUpManager.isAlerting(childEntry.getKey()));
Kevin01a53cb2018-11-09 18:19:54 -0800149 }
150
151 @Test
152 public void testSuppressedSummaryHeadsUpDoesntTransferBackOnDozingChanged() {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500153 NotificationEntry summaryEntry =
Kevin01a53cb2018-11-09 18:19:54 -0800154 mGroupTestHelper.createSummaryNotification(Notification.GROUP_ALERT_SUMMARY);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500155 NotificationEntry childEntry =
Kevin01a53cb2018-11-09 18:19:54 -0800156 mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500157 NotificationEntry childEntry2 =
Kevin01a53cb2018-11-09 18:19:54 -0800158 mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY);
159 mHeadsUpManager.showNotification(summaryEntry);
160 // Trigger a transfer of alert state from summary to child.
161 mGroupManager.onEntryAdded(summaryEntry);
162 mGroupManager.onEntryAdded(childEntry);
163
164 // Set dozing to true.
165 mGroupAlertTransferHelper.onDozingChanged(true);
166
167 // Add second child notification so that summary is no longer suppressed.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400168 mPendingEntries.put(childEntry2.getKey(), childEntry2);
Gus Prevasd65c2db2018-12-18 17:13:38 -0500169 mNotificationEntryListener.onPendingEntryAdded(childEntry2);
Kevin01a53cb2018-11-09 18:19:54 -0800170 mGroupManager.onEntryAdded(childEntry2);
171
172 // Dozing changed so no reason to re-alert summary.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400173 assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
Kevin01a53cb2018-11-09 18:19:54 -0800174 }
175
176 @Test
177 public void testSuppressedSummaryHeadsUpTransferDoesNotAlertChildIfUninflated() {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500178 NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification();
Kevin01a53cb2018-11-09 18:19:54 -0800179 mHeadsUpManager.showNotification(summaryEntry);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500180 NotificationEntry childEntry = mGroupTestHelper.createChildNotification();
Kevin Han933dc7c2020-01-29 11:17:46 -0800181 RowContentBindParams params = new RowContentBindParams();
182 when(mBindStage.getStageParams(eq(childEntry))).thenReturn(params);
Kevin01a53cb2018-11-09 18:19:54 -0800183
184 mGroupManager.onEntryAdded(summaryEntry);
185 mGroupManager.onEntryAdded(childEntry);
186
187 // Alert is immediately removed from summary, but we do not show child yet either as its
188 // content is not inflated.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400189 assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
190 assertFalse(mHeadsUpManager.isAlerting(childEntry.getKey()));
Kevin4b8bbda2018-11-19 14:36:31 -0800191 assertTrue(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
Kevin01a53cb2018-11-09 18:19:54 -0800192 }
193
194 @Test
195 public void testSuppressedSummaryHeadsUpTransferAlertsChildOnInflation() {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500196 NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification();
Kevin01a53cb2018-11-09 18:19:54 -0800197 mHeadsUpManager.showNotification(summaryEntry);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500198 NotificationEntry childEntry = mGroupTestHelper.createChildNotification();
Kevin Han933dc7c2020-01-29 11:17:46 -0800199 RowContentBindParams params = new RowContentBindParams();
200 when(mBindStage.getStageParams(eq(childEntry))).thenReturn(params);
Kevin01a53cb2018-11-09 18:19:54 -0800201
202 mGroupManager.onEntryAdded(summaryEntry);
203 mGroupManager.onEntryAdded(childEntry);
204
Kevin Han933dc7c2020-01-29 11:17:46 -0800205 // Child entry finishes its inflation.
206 ArgumentCaptor<BindCallback> callbackCaptor = ArgumentCaptor.forClass(BindCallback.class);
207 verify(mBindStage).requestRebind(eq(childEntry), callbackCaptor.capture());
208 callbackCaptor.getValue().onBindFinished(childEntry);
Kevin01a53cb2018-11-09 18:19:54 -0800209
210 // Alert is immediately removed from summary, and we show child as its content is inflated.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400211 assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
212 assertTrue(mHeadsUpManager.isAlerting(childEntry.getKey()));
Kevin01a53cb2018-11-09 18:19:54 -0800213 }
214
215 @Test
216 public void testSuppressedSummaryHeadsUpTransferBackAbortsChildInflation() {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500217 NotificationEntry summaryEntry =
Kevin01a53cb2018-11-09 18:19:54 -0800218 mGroupTestHelper.createSummaryNotification(Notification.GROUP_ALERT_SUMMARY);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500219 NotificationEntry childEntry =
Kevin01a53cb2018-11-09 18:19:54 -0800220 mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY);
Kevin Han933dc7c2020-01-29 11:17:46 -0800221 RowContentBindParams params = new RowContentBindParams();
222 when(mBindStage.getStageParams(eq(childEntry))).thenReturn(params);
223
Ned Burnsf81c4c42019-01-07 14:10:43 -0500224 NotificationEntry childEntry2 =
Kevin01a53cb2018-11-09 18:19:54 -0800225 mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY);
226 mHeadsUpManager.showNotification(summaryEntry);
227 // Trigger a transfer of alert state from summary to child.
228 mGroupManager.onEntryAdded(summaryEntry);
229 mGroupManager.onEntryAdded(childEntry);
230
231 // Add second child notification so that summary is no longer suppressed.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400232 mPendingEntries.put(childEntry2.getKey(), childEntry2);
Gus Prevasd65c2db2018-12-18 17:13:38 -0500233 mNotificationEntryListener.onPendingEntryAdded(childEntry2);
Kevin01a53cb2018-11-09 18:19:54 -0800234 mGroupManager.onEntryAdded(childEntry2);
235
236 // Child entry finishes its inflation.
Kevin Han933dc7c2020-01-29 11:17:46 -0800237 ArgumentCaptor<BindCallback> callbackCaptor = ArgumentCaptor.forClass(BindCallback.class);
238 verify(mBindStage).requestRebind(eq(childEntry), callbackCaptor.capture());
239 callbackCaptor.getValue().onBindFinished(childEntry);
Kevin01a53cb2018-11-09 18:19:54 -0800240
Kevin Han273bb0d2020-03-20 10:44:40 -0700241 assertTrue((params.getContentViews() & FLAG_CONTENT_VIEW_HEADS_UP) == 0);
Ned Burns00b4b2d2019-10-17 22:09:27 -0400242 assertFalse(mHeadsUpManager.isAlerting(childEntry.getKey()));
Kevin01a53cb2018-11-09 18:19:54 -0800243 }
Kevin4b8bbda2018-11-19 14:36:31 -0800244
245 @Test
246 public void testCleanUpPendingAlertInfo() {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500247 NotificationEntry summaryEntry =
Kevin4b8bbda2018-11-19 14:36:31 -0800248 mGroupTestHelper.createSummaryNotification(Notification.GROUP_ALERT_SUMMARY);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500249 NotificationEntry childEntry =
Kevin4b8bbda2018-11-19 14:36:31 -0800250 mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY);
Kevin Han933dc7c2020-01-29 11:17:46 -0800251 RowContentBindParams params = new RowContentBindParams();
252 when(mBindStage.getStageParams(eq(childEntry))).thenReturn(params);
253
Kevin4b8bbda2018-11-19 14:36:31 -0800254 mHeadsUpManager.showNotification(summaryEntry);
255 // Trigger a transfer of alert state from summary to child.
256 mGroupManager.onEntryAdded(summaryEntry);
257 mGroupManager.onEntryAdded(childEntry);
258
Julia Reynolds138111f2020-02-26 11:17:39 -0500259 mNotificationEntryListener.onEntryRemoved(
260 childEntry, null, false, UNDEFINED_DISMISS_REASON);
Kevin4b8bbda2018-11-19 14:36:31 -0800261
262 assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
263 }
264
265 @Test
266 public void testUpdateGroupChangeDoesNotTransfer() {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500267 NotificationEntry summaryEntry =
Kevin4b8bbda2018-11-19 14:36:31 -0800268 mGroupTestHelper.createSummaryNotification(Notification.GROUP_ALERT_SUMMARY);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500269 NotificationEntry childEntry =
Kevin4b8bbda2018-11-19 14:36:31 -0800270 mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY);
Kevin Han933dc7c2020-01-29 11:17:46 -0800271 RowContentBindParams params = new RowContentBindParams();
272 when(mBindStage.getStageParams(eq(childEntry))).thenReturn(params);
273
Kevin4b8bbda2018-11-19 14:36:31 -0800274 mHeadsUpManager.showNotification(summaryEntry);
275 // Trigger a transfer of alert state from summary to child.
276 mGroupManager.onEntryAdded(summaryEntry);
277 mGroupManager.onEntryAdded(childEntry);
278
279 // Notify that entry changed groups.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400280 StatusBarNotification oldNotification = childEntry.getSbn();
281 StatusBarNotification newSbn = spy(childEntry.getSbn().clone());
Kevin4b8bbda2018-11-19 14:36:31 -0800282 doReturn("other_group").when(newSbn).getGroupKey();
Ned Burns00b4b2d2019-10-17 22:09:27 -0400283 childEntry.setSbn(newSbn);
Kevin4b8bbda2018-11-19 14:36:31 -0800284 mGroupManager.onEntryUpdated(childEntry, oldNotification);
285
286 assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
287 }
288
289 @Test
290 public void testUpdateChildToSummaryDoesNotTransfer() {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500291 NotificationEntry summaryEntry =
Kevin4b8bbda2018-11-19 14:36:31 -0800292 mGroupTestHelper.createSummaryNotification(Notification.GROUP_ALERT_SUMMARY);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500293 NotificationEntry childEntry =
Ned Burnsae90a9e2019-08-26 17:11:26 -0400294 mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY, 47);
Kevin Han933dc7c2020-01-29 11:17:46 -0800295 RowContentBindParams params = new RowContentBindParams();
296 when(mBindStage.getStageParams(eq(childEntry))).thenReturn(params);
297
Kevin4b8bbda2018-11-19 14:36:31 -0800298 mHeadsUpManager.showNotification(summaryEntry);
299 // Trigger a transfer of alert state from summary to child.
300 mGroupManager.onEntryAdded(summaryEntry);
301 mGroupManager.onEntryAdded(childEntry);
302
303 // Update that child to a summary.
Ned Burns00b4b2d2019-10-17 22:09:27 -0400304 StatusBarNotification oldNotification = childEntry.getSbn();
305 childEntry.setSbn(
Ned Burnsae90a9e2019-08-26 17:11:26 -0400306 mGroupTestHelper.createSummaryNotification(
Ned Burns00b4b2d2019-10-17 22:09:27 -0400307 Notification.GROUP_ALERT_SUMMARY, 47).getSbn());
Kevin4b8bbda2018-11-19 14:36:31 -0800308 mGroupManager.onEntryUpdated(childEntry, oldNotification);
309
310 assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
311 }
Kevin01a53cb2018-11-09 18:19:54 -0800312}