RankingHelperTest.java revision 9394a8fc62817a34b85d91c0004c924166952936
1/* 2 * Copyright (C) 2014 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 */ 16package com.android.server.notification; 17 18import static android.app.NotificationManager.IMPORTANCE_DEFAULT; 19import static android.app.NotificationManager.IMPORTANCE_HIGH; 20import static android.app.NotificationManager.IMPORTANCE_LOW; 21 22import static junit.framework.Assert.assertNull; 23import static junit.framework.Assert.fail; 24 25import org.json.JSONArray; 26import org.json.JSONObject; 27import org.junit.Before; 28import org.junit.Test; 29import org.junit.runner.RunWith; 30 31import com.android.internal.util.FastXmlSerializer; 32 33import org.mockito.Mock; 34import org.mockito.MockitoAnnotations; 35import org.xmlpull.v1.XmlPullParser; 36import org.xmlpull.v1.XmlSerializer; 37 38import android.app.Notification; 39import android.app.NotificationChannelGroup; 40import android.content.Context; 41import android.app.NotificationChannel; 42import android.app.NotificationManager; 43import android.content.pm.ApplicationInfo; 44import android.content.pm.PackageManager; 45import android.graphics.Color; 46import android.media.AudioAttributes; 47import android.net.Uri; 48import android.os.Build; 49import android.os.UserHandle; 50import android.service.notification.StatusBarNotification; 51import android.support.test.InstrumentationRegistry; 52import android.support.test.runner.AndroidJUnit4; 53import android.test.suitebuilder.annotation.SmallTest; 54import android.util.ArrayMap; 55import android.util.Xml; 56 57import java.io.BufferedInputStream; 58import java.io.BufferedOutputStream; 59import java.io.ByteArrayInputStream; 60import java.io.ByteArrayOutputStream; 61import java.util.ArrayList; 62import java.util.Arrays; 63import java.util.HashMap; 64import java.util.List; 65import java.util.Map; 66import java.util.Objects; 67import java.util.concurrent.ThreadLocalRandom; 68 69import static org.junit.Assert.assertEquals; 70import static org.junit.Assert.assertFalse; 71import static org.junit.Assert.assertNotNull; 72import static org.junit.Assert.assertTrue; 73import static org.mockito.Matchers.anyInt; 74import static org.mockito.Matchers.anyString; 75import static org.mockito.Matchers.eq; 76import static org.mockito.Mockito.when; 77 78@SmallTest 79@RunWith(AndroidJUnit4.class) 80public class RankingHelperTest { 81 private static final String PKG = "com.android.server.notification"; 82 private static final int UID = 0; 83 private static final String UPDATED_PKG = "updatedPkg"; 84 private static final int UID2 = 1111111; 85 private static final String TEST_CHANNEL_ID = "test_channel_id"; 86 87 @Mock NotificationUsageStats mUsageStats; 88 @Mock RankingHandler mHandler; 89 @Mock PackageManager mPm; 90 91 private Notification mNotiGroupGSortA; 92 private Notification mNotiGroupGSortB; 93 private Notification mNotiNoGroup; 94 private Notification mNotiNoGroup2; 95 private Notification mNotiNoGroupSortA; 96 private NotificationRecord mRecordGroupGSortA; 97 private NotificationRecord mRecordGroupGSortB; 98 private NotificationRecord mRecordNoGroup; 99 private NotificationRecord mRecordNoGroup2; 100 private NotificationRecord mRecordNoGroupSortA; 101 private RankingHelper mHelper; 102 private AudioAttributes mAudioAttributes; 103 104 private Context getContext() { 105 return InstrumentationRegistry.getTargetContext(); 106 } 107 108 @Before 109 public void setUp() throws Exception { 110 MockitoAnnotations.initMocks(this); 111 UserHandle user = UserHandle.ALL; 112 113 mHelper = new RankingHelper(getContext(), mPm, mHandler, mUsageStats, 114 new String[] {ImportanceExtractor.class.getName()}); 115 116 mNotiGroupGSortA = new Notification.Builder(getContext(), TEST_CHANNEL_ID) 117 .setContentTitle("A") 118 .setGroup("G") 119 .setSortKey("A") 120 .setWhen(1205) 121 .build(); 122 mRecordGroupGSortA = new NotificationRecord(getContext(), new StatusBarNotification( 123 "package", "package", 1, null, 0, 0, mNotiGroupGSortA, user, 124 null, System.currentTimeMillis()), getDefaultChannel()); 125 126 mNotiGroupGSortB = new Notification.Builder(getContext(), TEST_CHANNEL_ID) 127 .setContentTitle("B") 128 .setGroup("G") 129 .setSortKey("B") 130 .setWhen(1200) 131 .build(); 132 mRecordGroupGSortB = new NotificationRecord(getContext(), new StatusBarNotification( 133 "package", "package", 1, null, 0, 0, mNotiGroupGSortB, user, 134 null, System.currentTimeMillis()), getDefaultChannel()); 135 136 mNotiNoGroup = new Notification.Builder(getContext(), TEST_CHANNEL_ID) 137 .setContentTitle("C") 138 .setWhen(1201) 139 .build(); 140 mRecordNoGroup = new NotificationRecord(getContext(), new StatusBarNotification( 141 "package", "package", 1, null, 0, 0, mNotiNoGroup, user, 142 null, System.currentTimeMillis()), getDefaultChannel()); 143 144 mNotiNoGroup2 = new Notification.Builder(getContext(), TEST_CHANNEL_ID) 145 .setContentTitle("D") 146 .setWhen(1202) 147 .build(); 148 mRecordNoGroup2 = new NotificationRecord(getContext(), new StatusBarNotification( 149 "package", "package", 1, null, 0, 0, mNotiNoGroup2, user, 150 null, System.currentTimeMillis()), getDefaultChannel()); 151 152 mNotiNoGroupSortA = new Notification.Builder(getContext(), TEST_CHANNEL_ID) 153 .setContentTitle("E") 154 .setWhen(1201) 155 .setSortKey("A") 156 .build(); 157 mRecordNoGroupSortA = new NotificationRecord(getContext(), new StatusBarNotification( 158 "package", "package", 1, null, 0, 0, mNotiNoGroupSortA, user, 159 null, System.currentTimeMillis()), getDefaultChannel()); 160 161 mAudioAttributes = new AudioAttributes.Builder() 162 .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) 163 .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) 164 .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED) 165 .build(); 166 167 final ApplicationInfo legacy = new ApplicationInfo(); 168 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 169 final ApplicationInfo upgrade = new ApplicationInfo(); 170 upgrade.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 171 when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy); 172 when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(upgrade); 173 when(mPm.getPackageUidAsUser(eq(PKG), anyInt())).thenReturn(UID); 174 } 175 176 private NotificationChannel getDefaultChannel() { 177 return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name", 178 IMPORTANCE_LOW); 179 } 180 181 private ByteArrayOutputStream writeXmlAndPurge(String pkg, int uid, boolean forBackup, 182 String... channelIds) 183 throws Exception { 184 XmlSerializer serializer = new FastXmlSerializer(); 185 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 186 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 187 serializer.startDocument(null, true); 188 serializer.startTag(null, "ranking"); 189 mHelper.writeXml(serializer, forBackup); 190 serializer.endTag(null, "ranking"); 191 serializer.endDocument(); 192 serializer.flush(); 193 194 for (String channelId : channelIds) { 195 mHelper.permanentlyDeleteNotificationChannel(pkg, uid, channelId); 196 } 197 return baos; 198 } 199 200 private void loadStreamXml(ByteArrayOutputStream stream) throws Exception { 201 XmlPullParser parser = Xml.newPullParser(); 202 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(stream.toByteArray())), 203 null); 204 parser.nextTag(); 205 mHelper.readXml(parser, false); 206 } 207 208 private void compareChannels(NotificationChannel expected, NotificationChannel actual) { 209 assertEquals(expected.getId(), actual.getId()); 210 assertEquals(expected.getName(), actual.getName()); 211 assertEquals(expected.getDescription(), actual.getDescription()); 212 assertEquals(expected.shouldVibrate(), actual.shouldVibrate()); 213 assertEquals(expected.shouldShowLights(), actual.shouldShowLights()); 214 assertEquals(expected.getImportance(), actual.getImportance()); 215 assertEquals(expected.getLockscreenVisibility(), actual.getLockscreenVisibility()); 216 assertEquals(expected.getSound(), actual.getSound()); 217 assertEquals(expected.canBypassDnd(), actual.canBypassDnd()); 218 assertTrue(Arrays.equals(expected.getVibrationPattern(), actual.getVibrationPattern())); 219 assertEquals(expected.getGroup(), actual.getGroup()); 220 assertEquals(expected.getAudioAttributes(), actual.getAudioAttributes()); 221 assertEquals(expected.getLightColor(), actual.getLightColor()); 222 } 223 224 private void compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual) { 225 assertEquals(expected.getId(), actual.getId()); 226 assertEquals(expected.getName(), actual.getName()); 227 } 228 229 @Test 230 public void testFindAfterRankingWithASplitGroup() throws Exception { 231 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(3); 232 notificationList.add(mRecordGroupGSortA); 233 notificationList.add(mRecordGroupGSortB); 234 notificationList.add(mRecordNoGroup); 235 notificationList.add(mRecordNoGroupSortA); 236 mHelper.sort(notificationList); 237 assertTrue(mHelper.indexOf(notificationList, mRecordGroupGSortA) >= 0); 238 assertTrue(mHelper.indexOf(notificationList, mRecordGroupGSortB) >= 0); 239 assertTrue(mHelper.indexOf(notificationList, mRecordNoGroup) >= 0); 240 assertTrue(mHelper.indexOf(notificationList, mRecordNoGroupSortA) >= 0); 241 } 242 243 @Test 244 public void testSortShouldNotThrowWithPlainNotifications() throws Exception { 245 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(2); 246 notificationList.add(mRecordNoGroup); 247 notificationList.add(mRecordNoGroup2); 248 mHelper.sort(notificationList); 249 } 250 251 @Test 252 public void testSortShouldNotThrowOneSorted() throws Exception { 253 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(2); 254 notificationList.add(mRecordNoGroup); 255 notificationList.add(mRecordNoGroupSortA); 256 mHelper.sort(notificationList); 257 } 258 259 @Test 260 public void testSortShouldNotThrowOneNotification() throws Exception { 261 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(1); 262 notificationList.add(mRecordNoGroup); 263 mHelper.sort(notificationList); 264 } 265 266 @Test 267 public void testSortShouldNotThrowOneSortKey() throws Exception { 268 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(1); 269 notificationList.add(mRecordGroupGSortB); 270 mHelper.sort(notificationList); 271 } 272 273 @Test 274 public void testSortShouldNotThrowOnEmptyList() throws Exception { 275 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(); 276 mHelper.sort(notificationList); 277 } 278 279 @Test 280 public void testChannelXml() throws Exception { 281 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 282 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 283 NotificationChannel channel1 = 284 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 285 NotificationChannel channel2 = 286 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 287 channel2.setDescription("descriptions for all"); 288 channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 289 channel2.enableLights(true); 290 channel2.setBypassDnd(true); 291 channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 292 channel2.enableVibration(true); 293 channel2.setGroup(ncg.getId()); 294 channel2.setVibrationPattern(new long[]{100, 67, 145, 156}); 295 channel2.setLightColor(Color.BLUE); 296 297 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 298 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 299 mHelper.createNotificationChannel(PKG, UID, channel1, true); 300 mHelper.createNotificationChannel(PKG, UID, channel2, false); 301 302 mHelper.setShowBadge(PKG, UID, true); 303 304 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(), 305 channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); 306 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID}); 307 308 loadStreamXml(baos); 309 310 assertTrue(mHelper.canShowBadge(PKG, UID)); 311 assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false)); 312 compareChannels(channel2, 313 mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); 314 assertNotNull(mHelper.getNotificationChannel( 315 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false)); 316 317 List<NotificationChannelGroup> actualGroups = 318 mHelper.getNotificationChannelGroups(PKG, UID, false).getList(); 319 boolean foundNcg = false; 320 for (NotificationChannelGroup actual : actualGroups) { 321 if (ncg.getId().equals(actual.getId())) { 322 foundNcg = true; 323 compareGroups(ncg, actual); 324 } else if (ncg2.getId().equals(actual.getId())) { 325 compareGroups(ncg2, actual); 326 } 327 } 328 assertTrue(foundNcg); 329 330 boolean foundChannel2Group = false; 331 for (NotificationChannelGroup actual : actualGroups) { 332 if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) { 333 foundChannel2Group = true; 334 break; 335 } 336 } 337 assertTrue(foundChannel2Group); 338 } 339 340 @Test 341 public void testChannelXml_backup() throws Exception { 342 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 343 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 344 NotificationChannel channel1 = 345 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 346 NotificationChannel channel2 = 347 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 348 NotificationChannel channel3 = 349 new NotificationChannel("id3", "name3", IMPORTANCE_LOW); 350 channel3.setGroup(ncg.getId()); 351 352 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 353 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 354 mHelper.createNotificationChannel(PKG, UID, channel1, true); 355 mHelper.createNotificationChannel(PKG, UID, channel2, false); 356 mHelper.createNotificationChannel(PKG, UID, channel3, true); 357 358 mHelper.deleteNotificationChannel(PKG, UID, channel1.getId()); 359 mHelper.deleteNotificationChannelGroup(PKG, UID, ncg.getId()); 360 assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); 361 362 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(), 363 channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); 364 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID}); 365 366 XmlPullParser parser = Xml.newPullParser(); 367 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), 368 null); 369 parser.nextTag(); 370 mHelper.readXml(parser, true); 371 372 assertNull(mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false)); 373 assertNull(mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false)); 374 assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG, UID)); 375 //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG, UID)); 376 assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); 377 } 378 379 @Test 380 public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception { 381 NotificationChannel channel1 = 382 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_DEFAULT); 383 384 mHelper.createNotificationChannel(PKG, UID, channel1, true); 385 386 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(), 387 NotificationChannel.DEFAULT_CHANNEL_ID); 388 389 loadStreamXml(baos); 390 391 final NotificationChannel updated = mHelper.getNotificationChannel(PKG, UID, 392 NotificationChannel.DEFAULT_CHANNEL_ID, false); 393 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance()); 394 assertFalse(updated.canBypassDnd()); 395 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, updated.getLockscreenVisibility()); 396 assertEquals(0, updated.getUserLockedFields()); 397 } 398 399 @Test 400 public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception { 401 NotificationChannel channel1 = 402 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_MIN); 403 mHelper.createNotificationChannel(PKG, UID, channel1, true); 404 405 final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID, 406 NotificationChannel.DEFAULT_CHANNEL_ID, false); 407 defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW); 408 mHelper.updateNotificationChannel(PKG, UID, defaultChannel); 409 410 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(), 411 NotificationChannel.DEFAULT_CHANNEL_ID); 412 413 loadStreamXml(baos); 414 415 assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel( 416 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance()); 417 } 418 419 @Test 420 public void testChannelXml_upgradeCreateDefaultChannel() throws Exception { 421 final String preupgradeXml = "<ranking version=\"1\">\n" 422 + "<package name=\"" + PKG 423 + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH 424 + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\"" 425 + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + UID + "\" />\n" 426 + "<package name=\"" + UPDATED_PKG + "\" uid=\"" + UID2 + "\" visibility=\"" 427 + Notification.VISIBILITY_PRIVATE + "\" />\n" 428 + "</ranking>"; 429 XmlPullParser parser = Xml.newPullParser(); 430 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), 431 null); 432 parser.nextTag(); 433 mHelper.readXml(parser, false); 434 435 final NotificationChannel updated1 = 436 mHelper.getNotificationChannel(PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); 437 assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance()); 438 assertTrue(updated1.canBypassDnd()); 439 assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility()); 440 assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE 441 | NotificationChannel.USER_LOCKED_PRIORITY 442 | NotificationChannel.USER_LOCKED_VISIBILITY, 443 updated1.getUserLockedFields()); 444 445 // STOPSHIP - this should be reversed after the STOPSHIP is removed in the tested code. 446 // No Default Channel created for updated packages 447 // assertEquals(null, mHelper.getNotificationChannel(UPDATED_PKG, UID2, 448 // NotificationChannel.DEFAULT_CHANNEL_ID, false)); 449 assertTrue(mHelper.getNotificationChannel(UPDATED_PKG, UID2, 450 NotificationChannel.DEFAULT_CHANNEL_ID, false) != null); 451 } 452 453 @Test 454 public void testChannelXml_upgradeDeletesDefaultChannel() throws Exception { 455 final NotificationChannel defaultChannel = mHelper.getNotificationChannel( 456 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); 457 assertTrue(defaultChannel != null); 458 ByteArrayOutputStream baos = 459 writeXmlAndPurge(PKG, UID, false, NotificationChannel.DEFAULT_CHANNEL_ID); 460 // Load package at higher sdk. 461 final ApplicationInfo upgraded = new ApplicationInfo(); 462 upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 463 when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded); 464 loadStreamXml(baos); 465 466 // STOPSHIP - this should be reversed after the STOPSHIP is removed in the tested code. 467 // Default Channel should be gone. 468 // assertEquals(null, mHelper.getNotificationChannel(PKG, UID, 469 // NotificationChannel.DEFAULT_CHANNEL_ID, false)); 470 assertTrue(mHelper.getNotificationChannel(UPDATED_PKG, UID2, 471 NotificationChannel.DEFAULT_CHANNEL_ID, false) != null); 472 } 473 474 @Test 475 public void testDeletesDefaultChannelAfterChannelIsCreated() throws Exception { 476 mHelper.createNotificationChannel(PKG, UID, 477 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true); 478 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, 479 NotificationChannel.DEFAULT_CHANNEL_ID, "bananas"); 480 481 // Load package at higher sdk. 482 final ApplicationInfo upgraded = new ApplicationInfo(); 483 upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 484 when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded); 485 loadStreamXml(baos); 486 487 // Default Channel should be gone. 488 assertEquals(null, mHelper.getNotificationChannel(PKG, UID, 489 NotificationChannel.DEFAULT_CHANNEL_ID, false)); 490 } 491 492 @Test 493 public void testLoadingOldChannelsDoesNotDeleteNewlyCreatedChannels() throws Exception { 494 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, 495 NotificationChannel.DEFAULT_CHANNEL_ID, "bananas"); 496 mHelper.createNotificationChannel(PKG, UID, 497 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true); 498 499 loadStreamXml(baos); 500 501 // Should still have the newly created channel that wasn't in the xml. 502 assertTrue(mHelper.getNotificationChannel(PKG, UID, "bananas", false) != null); 503 } 504 505 @Test 506 public void testCreateChannel_blocked() throws Exception { 507 mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_NONE); 508 509 mHelper.createNotificationChannel(PKG, UID, 510 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true); 511 } 512 513 514 @Test 515 public void testUpdate() throws Exception { 516 // no fields locked by user 517 final NotificationChannel channel = 518 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 519 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 520 channel.enableLights(true); 521 channel.setBypassDnd(true); 522 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 523 524 mHelper.createNotificationChannel(PKG, UID, channel, false); 525 526 // same id, try to update all fields 527 final NotificationChannel channel2 = 528 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 529 channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes); 530 channel2.enableLights(false); 531 channel2.setBypassDnd(false); 532 channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); 533 534 mHelper.updateNotificationChannel(PKG, UID, channel2); 535 536 // all fields should be changed 537 assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 538 } 539 540 @Test 541 public void testGetNotificationChannel_ReturnsNullForUnknownChannel() throws Exception { 542 assertEquals(null, mHelper.getNotificationChannel(PKG, UID, "garbage", false)); 543 } 544 545 @Test 546 public void testCreateChannel_CannotChangeHiddenFields() throws Exception { 547 final NotificationChannel channel = 548 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 549 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 550 channel.enableLights(true); 551 channel.setBypassDnd(true); 552 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 553 channel.setShowBadge(true); 554 int lockMask = 0; 555 for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { 556 lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; 557 } 558 channel.lockFields(lockMask); 559 560 mHelper.createNotificationChannel(PKG, UID, channel, true); 561 562 NotificationChannel savedChannel = 563 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 564 565 assertEquals(channel.getName(), savedChannel.getName()); 566 assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); 567 assertFalse(savedChannel.canBypassDnd()); 568 assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); 569 assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); 570 } 571 572 @Test 573 public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception { 574 final NotificationChannel channel = 575 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 576 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 577 channel.enableLights(true); 578 channel.setBypassDnd(true); 579 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 580 channel.setShowBadge(true); 581 int lockMask = 0; 582 for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { 583 lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; 584 } 585 channel.lockFields(lockMask); 586 587 mHelper.createNotificationChannel(PKG, UID, channel, true); 588 589 NotificationChannel savedChannel = 590 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 591 592 assertEquals(channel.getName(), savedChannel.getName()); 593 assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); 594 assertFalse(savedChannel.canBypassDnd()); 595 assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); 596 assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); 597 } 598 599 @Test 600 public void testDeleteNonExistentChannel() throws Exception { 601 mHelper.deleteNotificationChannelGroup(PKG, UID, "does not exist"); 602 } 603 604 @Test 605 public void testGetDeletedChannel() throws Exception { 606 NotificationChannel channel = 607 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 608 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 609 channel.enableLights(true); 610 channel.setBypassDnd(true); 611 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 612 channel.enableVibration(true); 613 channel.setVibrationPattern(new long[]{100, 67, 145, 156}); 614 615 mHelper.createNotificationChannel(PKG, UID, channel, true); 616 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 617 618 // Does not return deleted channel 619 NotificationChannel response = 620 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 621 assertNull(response); 622 623 // Returns deleted channel 624 response = mHelper.getNotificationChannel(PKG, UID, channel.getId(), true); 625 compareChannels(channel, response); 626 assertTrue(response.isDeleted()); 627 } 628 629 @Test 630 public void testGetDeletedChannels() throws Exception { 631 Map<String, NotificationChannel> channelMap = new HashMap<>(); 632 NotificationChannel channel = 633 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 634 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 635 channel.enableLights(true); 636 channel.setBypassDnd(true); 637 channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); 638 channel.enableVibration(true); 639 channel.setVibrationPattern(new long[]{100, 67, 145, 156}); 640 channelMap.put(channel.getId(), channel); 641 NotificationChannel channel2 = 642 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 643 channelMap.put(channel2.getId(), channel2); 644 mHelper.createNotificationChannel(PKG, UID, channel, true); 645 mHelper.createNotificationChannel(PKG, UID, channel2, true); 646 647 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 648 649 // Returns only non-deleted channels 650 List<NotificationChannel> channels = 651 mHelper.getNotificationChannels(PKG, UID, false).getList(); 652 assertEquals(2, channels.size()); // Default channel + non-deleted channel 653 for (NotificationChannel nc : channels) { 654 if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { 655 compareChannels(channel2, nc); 656 } 657 } 658 659 // Returns deleted channels too 660 channels = mHelper.getNotificationChannels(PKG, UID, true).getList(); 661 assertEquals(3, channels.size()); // Includes default channel 662 for (NotificationChannel nc : channels) { 663 if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { 664 compareChannels(channelMap.get(nc.getId()), nc); 665 } 666 } 667 } 668 669 @Test 670 public void testGetDeletedChannelCount() throws Exception { 671 NotificationChannel channel = 672 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 673 NotificationChannel channel2 = 674 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 675 NotificationChannel channel3 = 676 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 677 mHelper.createNotificationChannel(PKG, UID, channel, true); 678 mHelper.createNotificationChannel(PKG, UID, channel2, true); 679 mHelper.createNotificationChannel(PKG, UID, channel3, true); 680 681 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 682 mHelper.deleteNotificationChannel(PKG, UID, channel3.getId()); 683 684 assertEquals(2, mHelper.getDeletedChannelCount(PKG, UID)); 685 assertEquals(0, mHelper.getDeletedChannelCount("pkg2", UID2)); 686 } 687 688 @Test 689 public void testCreateDeletedChannel() throws Exception { 690 long[] vibration = new long[]{100, 67, 145, 156}; 691 NotificationChannel channel = 692 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 693 channel.setVibrationPattern(vibration); 694 695 mHelper.createNotificationChannel(PKG, UID, channel, true); 696 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 697 698 NotificationChannel newChannel = new NotificationChannel( 699 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); 700 newChannel.setVibrationPattern(new long[]{100}); 701 702 mHelper.createNotificationChannel(PKG, UID, newChannel, true); 703 704 // No long deleted, using old settings 705 compareChannels(channel, 706 mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false)); 707 } 708 709 @Test 710 public void testCreateChannel_defaultChannelId() throws Exception { 711 try { 712 mHelper.createNotificationChannel(PKG, UID, new NotificationChannel( 713 NotificationChannel.DEFAULT_CHANNEL_ID, "ha", IMPORTANCE_HIGH), true); 714 fail("Allowed to create default channel"); 715 } catch (IllegalArgumentException e) { 716 // pass 717 } 718 } 719 720 @Test 721 public void testCreateChannel_alreadyExists() throws Exception { 722 long[] vibration = new long[]{100, 67, 145, 156}; 723 NotificationChannel channel = 724 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 725 channel.setVibrationPattern(vibration); 726 727 mHelper.createNotificationChannel(PKG, UID, channel, true); 728 729 NotificationChannel newChannel = new NotificationChannel( 730 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); 731 newChannel.setVibrationPattern(new long[]{100}); 732 733 mHelper.createNotificationChannel(PKG, UID, newChannel, true); 734 735 // Old settings not overridden 736 compareChannels(channel, 737 mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false)); 738 } 739 740 @Test 741 public void testCreateChannel_addMissingSound() throws Exception { 742 final NotificationChannel channel = 743 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 744 mHelper.createNotificationChannel(PKG, UID, channel, true); 745 assertNotNull(mHelper.getNotificationChannel( 746 PKG, UID, channel.getId(), false).getSound()); 747 } 748 749 @Test 750 public void testCreateChannel_noOverrideSound() throws Exception { 751 Uri sound = new Uri.Builder().scheme("test").build(); 752 final NotificationChannel channel = new NotificationChannel("id2", "name2", 753 NotificationManager.IMPORTANCE_DEFAULT); 754 channel.setSound(sound, mAudioAttributes); 755 mHelper.createNotificationChannel(PKG, UID, channel, true); 756 assertEquals(sound, mHelper.getNotificationChannel( 757 PKG, UID, channel.getId(), false).getSound()); 758 } 759 760 @Test 761 public void testPermanentlyDeleteChannels() throws Exception { 762 NotificationChannel channel1 = 763 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 764 NotificationChannel channel2 = 765 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 766 767 mHelper.createNotificationChannel(PKG, UID, channel1, true); 768 mHelper.createNotificationChannel(PKG, UID, channel2, false); 769 770 mHelper.permanentlyDeleteNotificationChannels(PKG, UID); 771 772 // Only default channel remains 773 assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size()); 774 } 775 776 @Test 777 public void testDeleteGroup() throws Exception { 778 NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted"); 779 NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted"); 780 NotificationChannel nonGroupedNonDeletedChannel = 781 new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH); 782 NotificationChannel groupedButNotDeleted = 783 new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT); 784 groupedButNotDeleted.setGroup("not"); 785 NotificationChannel groupedAndDeleted = 786 new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT); 787 groupedAndDeleted.setGroup("totally"); 788 789 mHelper.createNotificationChannelGroup(PKG, UID, notDeleted, true); 790 mHelper.createNotificationChannelGroup(PKG, UID, deleted, true); 791 mHelper.createNotificationChannel(PKG, UID, nonGroupedNonDeletedChannel, true); 792 mHelper.createNotificationChannel(PKG, UID, groupedAndDeleted, true); 793 mHelper.createNotificationChannel(PKG, UID, groupedButNotDeleted, true); 794 795 mHelper.deleteNotificationChannelGroup(PKG, UID, deleted.getId()); 796 797 assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG, UID)); 798 assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG, UID)); 799 800 assertNull(mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), false)); 801 compareChannels(groupedAndDeleted, 802 mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), true)); 803 804 compareChannels(groupedButNotDeleted, 805 mHelper.getNotificationChannel(PKG, UID, groupedButNotDeleted.getId(), false)); 806 compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel( 807 PKG, UID, nonGroupedNonDeletedChannel.getId(), false)); 808 809 // notDeleted 810 assertEquals(1, mHelper.getNotificationChannelGroups(PKG, UID).size()); 811 } 812 813 @Test 814 public void testOnPackageChanged_packageRemoval() throws Exception { 815 // Deleted 816 NotificationChannel channel1 = 817 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 818 mHelper.createNotificationChannel(PKG, UID, channel1, true); 819 820 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 821 822 assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size()); 823 824 // Not deleted 825 mHelper.createNotificationChannel(PKG, UID, channel1, true); 826 827 mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 828 assertEquals(2, mHelper.getNotificationChannels(PKG, UID, false).getList().size()); 829 } 830 831 @Test 832 public void testOnPackageChanged_packageRemoval_importance() throws Exception { 833 mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_HIGH); 834 835 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 836 837 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); 838 } 839 840 @Test 841 public void testOnPackageChanged_packageRemoval_groups() throws Exception { 842 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 843 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 844 NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); 845 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 846 847 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 848 849 assertEquals(0, mHelper.getNotificationChannelGroups(PKG, UID, true).getList().size()); 850 } 851 852 @Test 853 public void testRecordDefaults() throws Exception { 854 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); 855 assertEquals(true, mHelper.canShowBadge(PKG, UID)); 856 assertEquals(1, mHelper.getNotificationChannels(PKG, UID, false).getList().size()); 857 } 858 859 @Test 860 public void testCreateGroup() throws Exception { 861 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 862 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 863 assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG, UID).iterator().next()); 864 } 865 866 @Test 867 public void testCannotCreateChannel_badGroup() throws Exception { 868 NotificationChannel channel1 = 869 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 870 channel1.setGroup("garbage"); 871 try { 872 mHelper.createNotificationChannel(PKG, UID, channel1, true); 873 fail("Created a channel with a bad group"); 874 } catch (IllegalArgumentException e) { 875 } 876 } 877 878 @Test 879 public void testCannotCreateChannel_goodGroup() throws Exception { 880 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 881 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 882 NotificationChannel channel1 = 883 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 884 channel1.setGroup(ncg.getId()); 885 mHelper.createNotificationChannel(PKG, UID, channel1, true); 886 887 assertEquals(ncg.getId(), 888 mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false).getGroup()); 889 } 890 891 @Test 892 public void testGetChannelGroups() throws Exception { 893 NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s"); 894 mHelper.createNotificationChannelGroup(PKG, UID, unused, true); 895 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 896 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 897 NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); 898 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 899 900 NotificationChannel channel1 = 901 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 902 channel1.setGroup(ncg.getId()); 903 mHelper.createNotificationChannel(PKG, UID, channel1, true); 904 NotificationChannel channel1a = 905 new NotificationChannel("id1a", "name1", NotificationManager.IMPORTANCE_HIGH); 906 channel1a.setGroup(ncg.getId()); 907 mHelper.createNotificationChannel(PKG, UID, channel1a, true); 908 909 NotificationChannel channel2 = 910 new NotificationChannel("id2", "name1", NotificationManager.IMPORTANCE_HIGH); 911 channel2.setGroup(ncg2.getId()); 912 mHelper.createNotificationChannel(PKG, UID, channel2, true); 913 914 NotificationChannel channel3 = 915 new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH); 916 mHelper.createNotificationChannel(PKG, UID, channel3, true); 917 918 List<NotificationChannelGroup> actual = 919 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 920 assertEquals(3, actual.size()); 921 for (NotificationChannelGroup group : actual) { 922 if (group.getId() == null) { 923 assertEquals(2, group.getChannels().size()); // misc channel too 924 assertTrue(channel3.getId().equals(group.getChannels().get(0).getId()) 925 || channel3.getId().equals(group.getChannels().get(1).getId())); 926 } else if (group.getId().equals(ncg.getId())) { 927 assertEquals(2, group.getChannels().size()); 928 if (group.getChannels().get(0).getId().equals(channel1.getId())) { 929 assertTrue(group.getChannels().get(1).getId().equals(channel1a.getId())); 930 } else if (group.getChannels().get(0).getId().equals(channel1a.getId())) { 931 assertTrue(group.getChannels().get(1).getId().equals(channel1.getId())); 932 } else { 933 fail("expected channel not found"); 934 } 935 } else if (group.getId().equals(ncg2.getId())) { 936 assertEquals(1, group.getChannels().size()); 937 assertEquals(channel2.getId(), group.getChannels().get(0).getId()); 938 } 939 } 940 } 941 942 @Test 943 public void testGetChannelGroups_noSideEffects() throws Exception { 944 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 945 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 946 947 NotificationChannel channel1 = 948 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 949 channel1.setGroup(ncg.getId()); 950 mHelper.createNotificationChannel(PKG, UID, channel1, true); 951 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 952 953 channel1.setImportance(IMPORTANCE_LOW); 954 mHelper.updateNotificationChannel(PKG, UID, channel1); 955 956 List<NotificationChannelGroup> actual = 957 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 958 959 assertEquals(2, actual.size()); 960 for (NotificationChannelGroup group : actual) { 961 if (Objects.equals(group.getId(), ncg.getId())) { 962 assertEquals(1, group.getChannels().size()); 963 } 964 } 965 } 966 967 @Test 968 public void testCreateChannel_updateName() throws Exception { 969 NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); 970 mHelper.createNotificationChannel(PKG, UID, nc, true); 971 NotificationChannel actual = mHelper.getNotificationChannel(PKG, UID, "id", false); 972 assertEquals("hello", actual.getName()); 973 974 nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH); 975 mHelper.createNotificationChannel(PKG, UID, nc, true); 976 977 actual = mHelper.getNotificationChannel(PKG, UID, "id", false); 978 assertEquals("goodbye", actual.getName()); 979 assertEquals(IMPORTANCE_DEFAULT, actual.getImportance()); 980 } 981 982 @Test 983 public void testDumpChannelsJson() throws Exception { 984 final ApplicationInfo upgrade = new ApplicationInfo(); 985 upgrade.targetSdkVersion = Build.VERSION_CODES.O; 986 try { 987 when(mPm.getApplicationInfoAsUser( 988 anyString(), anyInt(), anyInt())).thenReturn(upgrade); 989 } catch (PackageManager.NameNotFoundException e) { 990 } 991 ArrayMap<String, Integer> expectedChannels = new ArrayMap<>(); 992 int numPackages = ThreadLocalRandom.current().nextInt(1, 5); 993 for (int i = 0; i < numPackages; i++) { 994 String pkgName = "pkg" + i; 995 int numChannels = ThreadLocalRandom.current().nextInt(1, 10); 996 for (int j = 0; j < numChannels; j++) { 997 mHelper.createNotificationChannel(pkgName, UID, 998 new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true); 999 } 1000 expectedChannels.put(pkgName, numChannels); 1001 } 1002 1003 // delete the first channel of the first package 1004 String pkg = expectedChannels.keyAt(0); 1005 mHelper.deleteNotificationChannel("pkg" + 0, UID, "0"); 1006 // dump should not include deleted channels 1007 int count = expectedChannels.get(pkg); 1008 expectedChannels.put(pkg, count - 1); 1009 1010 JSONArray actual = mHelper.dumpChannelsJson(new NotificationManagerService.DumpFilter()); 1011 assertEquals(numPackages, actual.length()); 1012 for (int i = 0; i < numPackages; i++) { 1013 JSONObject object = actual.getJSONObject(i); 1014 assertTrue(expectedChannels.containsKey(object.get("packageName"))); 1015 assertEquals(expectedChannels.get(object.get("packageName")).intValue() + 1, 1016 object.getInt("channelCount")); 1017 } 1018 } 1019} 1020