1 /* 2 * Copyright (C) 2016 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 package com.android.server.notification; 17 18 import static android.app.Notification.FLAG_AUTO_CANCEL; 19 import static android.app.Notification.FLAG_BUBBLE; 20 import static android.app.Notification.FLAG_CAN_COLORIZE; 21 import static android.app.Notification.FLAG_FOREGROUND_SERVICE; 22 import static android.app.Notification.FLAG_NO_CLEAR; 23 import static android.app.Notification.FLAG_ONGOING_EVENT; 24 25 import static com.android.server.notification.GroupHelper.BASE_FLAGS; 26 27 import static junit.framework.Assert.assertEquals; 28 29 import static org.mockito.Matchers.anyInt; 30 import static org.mockito.Matchers.anyString; 31 import static org.mockito.Matchers.eq; 32 import static org.mockito.Mockito.never; 33 import static org.mockito.Mockito.times; 34 import static org.mockito.Mockito.verify; 35 import static org.mockito.Mockito.verifyZeroInteractions; 36 37 import android.annotation.SuppressLint; 38 import android.app.Notification; 39 import android.os.UserHandle; 40 import android.service.notification.StatusBarNotification; 41 import android.test.suitebuilder.annotation.SmallTest; 42 import android.util.ArrayMap; 43 44 import androidx.test.runner.AndroidJUnit4; 45 46 import com.android.server.UiServiceTestCase; 47 48 import org.junit.Before; 49 import org.junit.Test; 50 import org.junit.runner.RunWith; 51 import org.mockito.Mock; 52 import org.mockito.Mockito; 53 import org.mockito.MockitoAnnotations; 54 55 import java.util.ArrayList; 56 import java.util.List; 57 58 @SmallTest 59 @SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the class. 60 @RunWith(AndroidJUnit4.class) 61 public class GroupHelperTest extends UiServiceTestCase { 62 private @Mock GroupHelper.Callback mCallback; 63 64 private final static int AUTOGROUP_AT_COUNT = 7; 65 private GroupHelper mGroupHelper; 66 67 @Before setUp()68 public void setUp() { 69 MockitoAnnotations.initMocks(this); 70 71 mGroupHelper = new GroupHelper(AUTOGROUP_AT_COUNT, mCallback); 72 } 73 getSbn(String pkg, int id, String tag, UserHandle user, String groupKey)74 private StatusBarNotification getSbn(String pkg, int id, String tag, 75 UserHandle user, String groupKey) { 76 Notification.Builder nb = new Notification.Builder(getContext(), "test_channel_id") 77 .setContentTitle("A") 78 .setWhen(1205); 79 if (groupKey != null) { 80 nb.setGroup(groupKey); 81 } 82 return new StatusBarNotification(pkg, pkg, id, tag, 0, 0, nb.build(), user, null, 83 System.currentTimeMillis()); 84 } 85 getSbn(String pkg, int id, String tag, UserHandle user)86 private StatusBarNotification getSbn(String pkg, int id, String tag, 87 UserHandle user) { 88 return getSbn(pkg, id, tag, user, null); 89 } 90 91 @Test testGetAutogroupSummaryFlags_noChildren()92 public void testGetAutogroupSummaryFlags_noChildren() { 93 ArrayMap<String, Integer> children = new ArrayMap<>(); 94 95 assertEquals(BASE_FLAGS, mGroupHelper.getAutogroupSummaryFlags(children)); 96 } 97 98 @Test testGetAutogroupSummaryFlags_oneOngoing()99 public void testGetAutogroupSummaryFlags_oneOngoing() { 100 ArrayMap<String, Integer> children = new ArrayMap<>(); 101 children.put("a", 0); 102 children.put("b", FLAG_ONGOING_EVENT); 103 children.put("c", FLAG_BUBBLE); 104 105 assertEquals(FLAG_ONGOING_EVENT | BASE_FLAGS, 106 mGroupHelper.getAutogroupSummaryFlags(children)); 107 } 108 109 @Test testGetAutogroupSummaryFlags_oneOngoingNoClear()110 public void testGetAutogroupSummaryFlags_oneOngoingNoClear() { 111 ArrayMap<String, Integer> children = new ArrayMap<>(); 112 children.put("a", 0); 113 children.put("b", FLAG_ONGOING_EVENT|FLAG_NO_CLEAR); 114 children.put("c", FLAG_BUBBLE); 115 116 assertEquals(FLAG_NO_CLEAR | FLAG_ONGOING_EVENT | BASE_FLAGS, 117 mGroupHelper.getAutogroupSummaryFlags(children)); 118 } 119 120 @Test testGetAutogroupSummaryFlags_oneOngoingBubble()121 public void testGetAutogroupSummaryFlags_oneOngoingBubble() { 122 ArrayMap<String, Integer> children = new ArrayMap<>(); 123 children.put("a", 0); 124 children.put("b", FLAG_ONGOING_EVENT | FLAG_BUBBLE); 125 children.put("c", FLAG_BUBBLE); 126 127 assertEquals(FLAG_ONGOING_EVENT | BASE_FLAGS, 128 mGroupHelper.getAutogroupSummaryFlags(children)); 129 } 130 131 @Test testGetAutogroupSummaryFlags_multipleOngoing()132 public void testGetAutogroupSummaryFlags_multipleOngoing() { 133 ArrayMap<String, Integer> children = new ArrayMap<>(); 134 children.put("a", 0); 135 children.put("b", FLAG_ONGOING_EVENT); 136 children.put("c", FLAG_BUBBLE); 137 children.put("d", FLAG_ONGOING_EVENT); 138 139 assertEquals(FLAG_ONGOING_EVENT | BASE_FLAGS, 140 mGroupHelper.getAutogroupSummaryFlags(children)); 141 } 142 143 @Test testGetAutogroupSummaryFlags_oneAutoCancel()144 public void testGetAutogroupSummaryFlags_oneAutoCancel() { 145 ArrayMap<String, Integer> children = new ArrayMap<>(); 146 children.put("a", 0); 147 children.put("b", FLAG_AUTO_CANCEL); 148 children.put("c", FLAG_BUBBLE); 149 150 assertEquals(BASE_FLAGS, 151 mGroupHelper.getAutogroupSummaryFlags(children)); 152 } 153 154 @Test testGetAutogroupSummaryFlags_allAutoCancel()155 public void testGetAutogroupSummaryFlags_allAutoCancel() { 156 ArrayMap<String, Integer> children = new ArrayMap<>(); 157 children.put("a", FLAG_AUTO_CANCEL); 158 children.put("b", FLAG_AUTO_CANCEL | FLAG_CAN_COLORIZE); 159 children.put("c", FLAG_AUTO_CANCEL); 160 children.put("d", FLAG_AUTO_CANCEL | FLAG_FOREGROUND_SERVICE); 161 162 assertEquals(FLAG_AUTO_CANCEL | BASE_FLAGS, 163 mGroupHelper.getAutogroupSummaryFlags(children)); 164 } 165 166 @Test testGetAutogroupSummaryFlags_allAutoCancelOneOngoing()167 public void testGetAutogroupSummaryFlags_allAutoCancelOneOngoing() { 168 ArrayMap<String, Integer> children = new ArrayMap<>(); 169 children.put("a", FLAG_AUTO_CANCEL); 170 children.put("b", FLAG_AUTO_CANCEL | FLAG_CAN_COLORIZE); 171 children.put("c", FLAG_AUTO_CANCEL); 172 children.put("d", FLAG_AUTO_CANCEL | FLAG_FOREGROUND_SERVICE | FLAG_ONGOING_EVENT); 173 174 assertEquals(FLAG_AUTO_CANCEL| FLAG_ONGOING_EVENT | BASE_FLAGS, 175 mGroupHelper.getAutogroupSummaryFlags(children)); 176 } 177 178 @Test testNoGroup_postingUnderLimit()179 public void testNoGroup_postingUnderLimit() { 180 final String pkg = "package"; 181 for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) { 182 mGroupHelper.onNotificationPosted(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM), 183 false); 184 } 185 verifyZeroInteractions(mCallback); 186 } 187 188 @Test testNoGroup_multiPackage()189 public void testNoGroup_multiPackage() { 190 final String pkg = "package"; 191 final String pkg2 = "package2"; 192 for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) { 193 mGroupHelper.onNotificationPosted(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM), 194 false); 195 } 196 mGroupHelper.onNotificationPosted( 197 getSbn(pkg2, AUTOGROUP_AT_COUNT, "four", UserHandle.SYSTEM), false); 198 verifyZeroInteractions(mCallback); 199 } 200 201 @Test testNoGroup_multiUser()202 public void testNoGroup_multiUser() { 203 final String pkg = "package"; 204 for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) { 205 mGroupHelper.onNotificationPosted(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM), 206 false); 207 } 208 mGroupHelper.onNotificationPosted( 209 getSbn(pkg, AUTOGROUP_AT_COUNT, "four", UserHandle.of(7)), false); 210 verifyZeroInteractions(mCallback); 211 } 212 213 @Test testNoGroup_someAreGrouped()214 public void testNoGroup_someAreGrouped() { 215 final String pkg = "package"; 216 for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) { 217 mGroupHelper.onNotificationPosted( 218 getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM), false); 219 } 220 mGroupHelper.onNotificationPosted( 221 getSbn(pkg, AUTOGROUP_AT_COUNT, "four", UserHandle.SYSTEM, "a"), false); 222 verifyZeroInteractions(mCallback); 223 } 224 225 @Test testAddSummary()226 public void testAddSummary() { 227 final String pkg = "package"; 228 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 229 mGroupHelper.onNotificationPosted( 230 getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM), false); 231 } 232 verify(mCallback, times(1)).addAutoGroupSummary( 233 anyInt(), eq(pkg), anyString(), eq(BASE_FLAGS)); 234 verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); 235 verify(mCallback, never()).removeAutoGroup(anyString()); 236 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 237 verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); 238 } 239 240 @Test testAddSummary_oneChildOngoing_summaryOngoing()241 public void testAddSummary_oneChildOngoing_summaryOngoing() { 242 final String pkg = "package"; 243 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 244 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 245 if (i == 0) { 246 sbn.getNotification().flags |= FLAG_ONGOING_EVENT; 247 } 248 mGroupHelper.onNotificationPosted(sbn, false); 249 } 250 verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), 251 eq(BASE_FLAGS | FLAG_ONGOING_EVENT)); 252 verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); 253 verify(mCallback, never()).removeAutoGroup(anyString()); 254 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 255 verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); 256 } 257 258 @Test testAddSummary_oneChildAutoCancel_summaryNotAutoCancel()259 public void testAddSummary_oneChildAutoCancel_summaryNotAutoCancel() { 260 final String pkg = "package"; 261 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 262 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 263 if (i == 0) { 264 sbn.getNotification().flags |= FLAG_AUTO_CANCEL; 265 } 266 mGroupHelper.onNotificationPosted(sbn, false); 267 } 268 verify(mCallback, times(1)).addAutoGroupSummary( 269 anyInt(), eq(pkg), anyString(), eq(BASE_FLAGS)); 270 verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); 271 verify(mCallback, never()).removeAutoGroup(anyString()); 272 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 273 verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); 274 } 275 276 @Test testAddSummary_allChildrenAutoCancel_summaryAutoCancel()277 public void testAddSummary_allChildrenAutoCancel_summaryAutoCancel() { 278 final String pkg = "package"; 279 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 280 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 281 sbn.getNotification().flags |= FLAG_AUTO_CANCEL; 282 mGroupHelper.onNotificationPosted(sbn, false); 283 } 284 verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), 285 eq(BASE_FLAGS | FLAG_AUTO_CANCEL)); 286 verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); 287 verify(mCallback, never()).removeAutoGroup(anyString()); 288 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 289 verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); 290 } 291 292 @Test testAddSummary_summaryAutoCancelNoClear()293 public void testAddSummary_summaryAutoCancelNoClear() { 294 final String pkg = "package"; 295 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 296 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 297 sbn.getNotification().flags |= FLAG_AUTO_CANCEL; 298 if (i == 0) { 299 sbn.getNotification().flags |= FLAG_NO_CLEAR; 300 } 301 mGroupHelper.onNotificationPosted(sbn, false); 302 } 303 verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), 304 eq(BASE_FLAGS | FLAG_AUTO_CANCEL | FLAG_NO_CLEAR)); 305 verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); 306 verify(mCallback, never()).removeAutoGroup(anyString()); 307 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 308 verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); 309 } 310 311 @Test testAutoGrouped_allOngoing_updateChildNotOngoing()312 public void testAutoGrouped_allOngoing_updateChildNotOngoing() { 313 final String pkg = "package"; 314 315 // Post AUTOGROUP_AT_COUNT ongoing notifications 316 ArrayList<StatusBarNotification> notifications = new ArrayList<>(); 317 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 318 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 319 sbn.getNotification().flags |= FLAG_ONGOING_EVENT; 320 notifications.add(sbn); 321 } 322 323 for (StatusBarNotification sbn: notifications) { 324 mGroupHelper.onNotificationPosted(sbn, false); 325 } 326 327 // One notification is no longer ongoing 328 notifications.get(0).getNotification().flags &= ~FLAG_ONGOING_EVENT; 329 mGroupHelper.onNotificationPosted(notifications.get(0), true); 330 331 // Summary should keep FLAG_ONGOING_EVENT if any child has it 332 verify(mCallback).updateAutogroupSummary( 333 anyInt(), anyString(), eq(BASE_FLAGS | FLAG_ONGOING_EVENT)); 334 } 335 336 @Test testAutoGrouped_singleOngoing_removeOngoingChild()337 public void testAutoGrouped_singleOngoing_removeOngoingChild() { 338 final String pkg = "package"; 339 340 // Post AUTOGROUP_AT_COUNT ongoing notifications 341 ArrayList<StatusBarNotification> notifications = new ArrayList<>(); 342 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 343 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 344 if (i == 0) { 345 sbn.getNotification().flags |= FLAG_ONGOING_EVENT; 346 } 347 notifications.add(sbn); 348 } 349 350 for (StatusBarNotification sbn: notifications) { 351 mGroupHelper.onNotificationPosted(sbn, false); 352 } 353 354 // remove ongoing 355 mGroupHelper.onNotificationRemoved(notifications.get(0)); 356 357 // Summary is no longer ongoing 358 verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), eq(BASE_FLAGS)); 359 } 360 361 @Test testAutoGrouped_noOngoing_updateOngoingChild()362 public void testAutoGrouped_noOngoing_updateOngoingChild() { 363 final String pkg = "package"; 364 365 // Post AUTOGROUP_AT_COUNT ongoing notifications 366 ArrayList<StatusBarNotification> notifications = new ArrayList<>(); 367 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 368 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 369 notifications.add(sbn); 370 } 371 372 for (StatusBarNotification sbn: notifications) { 373 mGroupHelper.onNotificationPosted(sbn, false); 374 } 375 376 // update to ongoing 377 notifications.get(0).getNotification().flags |= FLAG_ONGOING_EVENT; 378 mGroupHelper.onNotificationPosted(notifications.get(0), true); 379 380 // Summary is now ongoing 381 verify(mCallback).updateAutogroupSummary( 382 anyInt(), anyString(), eq(BASE_FLAGS | FLAG_ONGOING_EVENT)); 383 } 384 385 @Test testAutoGrouped_noOngoing_addOngoingChild()386 public void testAutoGrouped_noOngoing_addOngoingChild() { 387 final String pkg = "package"; 388 389 // Post AUTOGROUP_AT_COUNT ongoing notifications 390 ArrayList<StatusBarNotification> notifications = new ArrayList<>(); 391 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 392 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 393 notifications.add(sbn); 394 } 395 396 for (StatusBarNotification sbn: notifications) { 397 mGroupHelper.onNotificationPosted(sbn, false); 398 } 399 400 // add ongoing 401 StatusBarNotification sbn = getSbn(pkg, AUTOGROUP_AT_COUNT + 1, null, UserHandle.SYSTEM); 402 sbn.getNotification().flags |= FLAG_ONGOING_EVENT; 403 mGroupHelper.onNotificationPosted(sbn, true); 404 405 // Summary is now ongoing 406 verify(mCallback).updateAutogroupSummary( 407 anyInt(), anyString(), eq(BASE_FLAGS | FLAG_ONGOING_EVENT)); 408 } 409 410 @Test testAutoGrouped_singleOngoing_appGroupOngoingChild()411 public void testAutoGrouped_singleOngoing_appGroupOngoingChild() { 412 final String pkg = "package"; 413 414 // Post AUTOGROUP_AT_COUNT ongoing notifications 415 ArrayList<StatusBarNotification> notifications = new ArrayList<>(); 416 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 417 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 418 if (i == 0) { 419 sbn.getNotification().flags |= FLAG_ONGOING_EVENT; 420 } 421 notifications.add(sbn); 422 } 423 424 for (StatusBarNotification sbn: notifications) { 425 mGroupHelper.onNotificationPosted(sbn, false); 426 } 427 428 // app group the ongoing child 429 StatusBarNotification sbn = getSbn(pkg, 0, "0", UserHandle.SYSTEM, "app group now"); 430 mGroupHelper.onNotificationPosted(sbn, true); 431 432 // Summary is no longer ongoing 433 verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), eq(BASE_FLAGS)); 434 } 435 436 @Test testAutoGrouped_singleOngoing_removeNonOngoingChild()437 public void testAutoGrouped_singleOngoing_removeNonOngoingChild() { 438 final String pkg = "package"; 439 440 // Post AUTOGROUP_AT_COUNT ongoing notifications 441 ArrayList<StatusBarNotification> notifications = new ArrayList<>(); 442 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 443 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 444 if (i == 0) { 445 sbn.getNotification().flags |= FLAG_ONGOING_EVENT; 446 } 447 notifications.add(sbn); 448 } 449 450 for (StatusBarNotification sbn: notifications) { 451 mGroupHelper.onNotificationPosted(sbn, false); 452 } 453 454 // remove ongoing 455 mGroupHelper.onNotificationRemoved(notifications.get(1)); 456 457 // Summary is still ongoing 458 verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); 459 } 460 461 @Test testAutoGrouped_allAutoCancel_updateChildNotAutoCancel()462 public void testAutoGrouped_allAutoCancel_updateChildNotAutoCancel() { 463 final String pkg = "package"; 464 465 // Post AUTOGROUP_AT_COUNT ongoing notifications 466 ArrayList<StatusBarNotification> notifications = new ArrayList<>(); 467 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 468 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 469 sbn.getNotification().flags |= FLAG_AUTO_CANCEL; 470 notifications.add(sbn); 471 } 472 473 for (StatusBarNotification sbn: notifications) { 474 mGroupHelper.onNotificationPosted(sbn, false); 475 } 476 477 // One notification is no longer autocancelable 478 notifications.get(0).getNotification().flags &= ~FLAG_AUTO_CANCEL; 479 mGroupHelper.onNotificationPosted(notifications.get(0), true); 480 481 // Summary should no longer be autocancelable 482 verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), eq(BASE_FLAGS)); 483 } 484 485 @Test testAutoGrouped_almostAllAutoCancel_updateChildAutoCancel()486 public void testAutoGrouped_almostAllAutoCancel_updateChildAutoCancel() { 487 final String pkg = "package"; 488 489 // Post AUTOGROUP_AT_COUNT ongoing notifications 490 ArrayList<StatusBarNotification> notifications = new ArrayList<>(); 491 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 492 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 493 if (i != 0) { 494 sbn.getNotification().flags |= FLAG_AUTO_CANCEL; 495 } 496 notifications.add(sbn); 497 } 498 499 for (StatusBarNotification sbn: notifications) { 500 mGroupHelper.onNotificationPosted(sbn, false); 501 } 502 503 // Missing notification is now autocancelable 504 notifications.get(0).getNotification().flags |= FLAG_AUTO_CANCEL; 505 mGroupHelper.onNotificationPosted(notifications.get(0), true); 506 507 // Summary should now autocancelable 508 verify(mCallback).updateAutogroupSummary( 509 anyInt(), anyString(), eq(BASE_FLAGS | FLAG_AUTO_CANCEL)); 510 } 511 512 @Test testAutoGrouped_allAutoCancel_updateChildAppGrouped()513 public void testAutoGrouped_allAutoCancel_updateChildAppGrouped() { 514 final String pkg = "package"; 515 516 // Post AUTOGROUP_AT_COUNT ongoing notifications 517 ArrayList<StatusBarNotification> notifications = new ArrayList<>(); 518 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 519 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 520 sbn.getNotification().flags |= FLAG_AUTO_CANCEL; 521 notifications.add(sbn); 522 } 523 524 for (StatusBarNotification sbn: notifications) { 525 mGroupHelper.onNotificationPosted(sbn, false); 526 } 527 528 // One notification is now grouped by app 529 StatusBarNotification sbn = getSbn(pkg, 0, "0", UserHandle.SYSTEM, "app group now"); 530 mGroupHelper.onNotificationPosted(sbn, true); 531 532 // Summary should be still be autocancelable 533 verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); 534 } 535 536 @Test testAutoGrouped_allAutoCancel_removeChild()537 public void testAutoGrouped_allAutoCancel_removeChild() { 538 final String pkg = "package"; 539 540 // Post AUTOGROUP_AT_COUNT ongoing notifications 541 ArrayList<StatusBarNotification> notifications = new ArrayList<>(); 542 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 543 StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 544 sbn.getNotification().flags |= FLAG_AUTO_CANCEL; 545 notifications.add(sbn); 546 } 547 548 for (StatusBarNotification sbn: notifications) { 549 mGroupHelper.onNotificationPosted(sbn, false); 550 } 551 552 mGroupHelper.onNotificationRemoved(notifications.get(0)); 553 554 // Summary should still be autocancelable 555 verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); 556 } 557 558 @Test testDropToZeroRemoveGroup()559 public void testDropToZeroRemoveGroup() { 560 final String pkg = "package"; 561 List<StatusBarNotification> posted = new ArrayList<>(); 562 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 563 final StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 564 posted.add(sbn); 565 mGroupHelper.onNotificationPosted(sbn, false); 566 } 567 verify(mCallback, times(1)).addAutoGroupSummary( 568 anyInt(), eq(pkg), anyString(), eq(BASE_FLAGS)); 569 verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); 570 verify(mCallback, never()).removeAutoGroup(anyString()); 571 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 572 Mockito.reset(mCallback); 573 574 for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) { 575 mGroupHelper.onNotificationRemoved(posted.remove(0)); 576 } 577 verify(mCallback, never()).removeAutoGroup(anyString()); 578 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 579 Mockito.reset(mCallback); 580 581 mGroupHelper.onNotificationRemoved(posted.remove(0)); 582 verify(mCallback, never()).removeAutoGroup(anyString()); 583 verify(mCallback, times(1)).removeAutoGroupSummary(anyInt(), anyString()); 584 } 585 586 @Test testAppStartsGrouping()587 public void testAppStartsGrouping() { 588 final String pkg = "package"; 589 List<StatusBarNotification> posted = new ArrayList<>(); 590 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 591 final StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 592 posted.add(sbn); 593 mGroupHelper.onNotificationPosted(sbn, false); 594 } 595 verify(mCallback, times(1)).addAutoGroupSummary( 596 anyInt(), eq(pkg), anyString(), eq(BASE_FLAGS)); 597 verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); 598 verify(mCallback, never()).removeAutoGroup(anyString()); 599 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 600 Mockito.reset(mCallback); 601 602 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 603 final StatusBarNotification sbn = 604 getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM, "app group"); 605 sbn.setOverrideGroupKey("autogrouped"); 606 mGroupHelper.onNotificationPosted(sbn, true); 607 verify(mCallback, times(1)).removeAutoGroup(sbn.getKey()); 608 if (i < AUTOGROUP_AT_COUNT - 1) { 609 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 610 } 611 } 612 verify(mCallback, times(1)).removeAutoGroupSummary(anyInt(), anyString()); 613 } 614 615 @Test testNewNotificationsAddedToAutogroup_ifOriginalNotificationsCanceled()616 public void testNewNotificationsAddedToAutogroup_ifOriginalNotificationsCanceled() { 617 final String pkg = "package"; 618 List<StatusBarNotification> posted = new ArrayList<>(); 619 for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { 620 final StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); 621 posted.add(sbn); 622 mGroupHelper.onNotificationPosted(sbn, false); 623 } 624 verify(mCallback, times(1)).addAutoGroupSummary( 625 anyInt(), eq(pkg), anyString(), eq(BASE_FLAGS)); 626 verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); 627 verify(mCallback, never()).removeAutoGroup(anyString()); 628 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 629 Mockito.reset(mCallback); 630 631 for (int i = posted.size() - 2; i >= 0; i--) { 632 mGroupHelper.onNotificationRemoved(posted.remove(i)); 633 } 634 verify(mCallback, never()).removeAutoGroup(anyString()); 635 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 636 Mockito.reset(mCallback); 637 638 // only one child remains 639 assertEquals(1, mGroupHelper.getNotGroupedByAppCount(UserHandle.USER_SYSTEM, pkg)); 640 641 // Add new notification; it should be autogrouped even though the total count is 642 // < AUTOGROUP_AT_COUNT 643 final StatusBarNotification sbn = getSbn(pkg, 5, String.valueOf(5), UserHandle.SYSTEM); 644 posted.add(sbn); 645 mGroupHelper.onNotificationPosted(sbn, true); 646 verify(mCallback, times(1)).addAutoGroup(sbn.getKey()); 647 verify(mCallback, never()).removeAutoGroup(anyString()); 648 verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); 649 verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), eq(BASE_FLAGS)); 650 verify(mCallback, never()).addAutoGroupSummary( 651 anyInt(), anyString(), anyString(), anyInt()); 652 } 653 } 654