RankingHelperTest.java revision 8e0eb372c9c5c941609daca554c92a44ee61c063
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.shouldVibrate(), actual.shouldVibrate()); 212 assertEquals(expected.shouldShowLights(), actual.shouldShowLights()); 213 assertEquals(expected.getImportance(), actual.getImportance()); 214 assertEquals(expected.getLockscreenVisibility(), actual.getLockscreenVisibility()); 215 assertEquals(expected.getSound(), actual.getSound()); 216 assertEquals(expected.canBypassDnd(), actual.canBypassDnd()); 217 assertTrue(Arrays.equals(expected.getVibrationPattern(), actual.getVibrationPattern())); 218 assertEquals(expected.getGroup(), actual.getGroup()); 219 assertEquals(expected.getAudioAttributes(), actual.getAudioAttributes()); 220 assertEquals(expected.getLightColor(), actual.getLightColor()); 221 } 222 223 private void compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual) { 224 assertEquals(expected.getId(), actual.getId()); 225 assertEquals(expected.getName(), actual.getName()); 226 } 227 228 @Test 229 public void testFindAfterRankingWithASplitGroup() throws Exception { 230 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(3); 231 notificationList.add(mRecordGroupGSortA); 232 notificationList.add(mRecordGroupGSortB); 233 notificationList.add(mRecordNoGroup); 234 notificationList.add(mRecordNoGroupSortA); 235 mHelper.sort(notificationList); 236 assertTrue(mHelper.indexOf(notificationList, mRecordGroupGSortA) >= 0); 237 assertTrue(mHelper.indexOf(notificationList, mRecordGroupGSortB) >= 0); 238 assertTrue(mHelper.indexOf(notificationList, mRecordNoGroup) >= 0); 239 assertTrue(mHelper.indexOf(notificationList, mRecordNoGroupSortA) >= 0); 240 } 241 242 @Test 243 public void testSortShouldNotThrowWithPlainNotifications() throws Exception { 244 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(2); 245 notificationList.add(mRecordNoGroup); 246 notificationList.add(mRecordNoGroup2); 247 mHelper.sort(notificationList); 248 } 249 250 @Test 251 public void testSortShouldNotThrowOneSorted() throws Exception { 252 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(2); 253 notificationList.add(mRecordNoGroup); 254 notificationList.add(mRecordNoGroupSortA); 255 mHelper.sort(notificationList); 256 } 257 258 @Test 259 public void testSortShouldNotThrowOneNotification() throws Exception { 260 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(1); 261 notificationList.add(mRecordNoGroup); 262 mHelper.sort(notificationList); 263 } 264 265 @Test 266 public void testSortShouldNotThrowOneSortKey() throws Exception { 267 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(1); 268 notificationList.add(mRecordGroupGSortB); 269 mHelper.sort(notificationList); 270 } 271 272 @Test 273 public void testSortShouldNotThrowOnEmptyList() throws Exception { 274 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(); 275 mHelper.sort(notificationList); 276 } 277 278 @Test 279 public void testChannelXml() throws Exception { 280 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 281 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 282 NotificationChannel channel1 = 283 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 284 NotificationChannel channel2 = 285 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 286 channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 287 channel2.enableLights(true); 288 channel2.setBypassDnd(true); 289 channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 290 channel2.enableVibration(true); 291 channel2.setGroup(ncg.getId()); 292 channel2.setVibrationPattern(new long[]{100, 67, 145, 156}); 293 channel2.setLightColor(Color.BLUE); 294 295 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 296 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 297 mHelper.createNotificationChannel(PKG, UID, channel1, true); 298 mHelper.createNotificationChannel(PKG, UID, channel2, false); 299 300 mHelper.setShowBadge(PKG, UID, true); 301 302 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(), 303 channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); 304 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID}); 305 306 loadStreamXml(baos); 307 308 assertTrue(mHelper.canShowBadge(PKG, UID)); 309 assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false)); 310 compareChannels(channel2, 311 mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); 312 assertNotNull(mHelper.getNotificationChannel( 313 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false)); 314 315 List<NotificationChannelGroup> actualGroups = 316 mHelper.getNotificationChannelGroups(PKG, UID, false).getList(); 317 boolean foundNcg = false; 318 for (NotificationChannelGroup actual : actualGroups) { 319 if (ncg.getId().equals(actual.getId())) { 320 foundNcg = true; 321 compareGroups(ncg, actual); 322 } else if (ncg2.getId().equals(actual.getId())) { 323 compareGroups(ncg2, actual); 324 } 325 } 326 assertTrue(foundNcg); 327 328 boolean foundChannel2Group = false; 329 for (NotificationChannelGroup actual : actualGroups) { 330 if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) { 331 foundChannel2Group = true; 332 break; 333 } 334 } 335 assertTrue(foundChannel2Group); 336 } 337 338 @Test 339 public void testChannelXml_backup() throws Exception { 340 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 341 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 342 NotificationChannel channel1 = 343 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 344 NotificationChannel channel2 = 345 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 346 NotificationChannel channel3 = 347 new NotificationChannel("id3", "name3", IMPORTANCE_LOW); 348 channel3.setGroup(ncg.getId()); 349 350 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 351 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 352 mHelper.createNotificationChannel(PKG, UID, channel1, true); 353 mHelper.createNotificationChannel(PKG, UID, channel2, false); 354 mHelper.createNotificationChannel(PKG, UID, channel3, true); 355 356 mHelper.deleteNotificationChannel(PKG, UID, channel1.getId()); 357 mHelper.deleteNotificationChannelGroup(PKG, UID, ncg.getId()); 358 assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); 359 360 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(), 361 channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); 362 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID}); 363 364 XmlPullParser parser = Xml.newPullParser(); 365 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), 366 null); 367 parser.nextTag(); 368 mHelper.readXml(parser, true); 369 370 assertNull(mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false)); 371 assertNull(mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false)); 372 assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG, UID)); 373 //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG, UID)); 374 assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); 375 } 376 377 @Test 378 public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception { 379 NotificationChannel channel1 = 380 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_DEFAULT); 381 382 mHelper.createNotificationChannel(PKG, UID, channel1, true); 383 384 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(), 385 NotificationChannel.DEFAULT_CHANNEL_ID); 386 387 loadStreamXml(baos); 388 389 final NotificationChannel updated = mHelper.getNotificationChannel(PKG, UID, 390 NotificationChannel.DEFAULT_CHANNEL_ID, false); 391 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance()); 392 assertFalse(updated.canBypassDnd()); 393 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, updated.getLockscreenVisibility()); 394 assertEquals(0, updated.getUserLockedFields()); 395 } 396 397 @Test 398 public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception { 399 NotificationChannel channel1 = 400 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_MIN); 401 mHelper.createNotificationChannel(PKG, UID, channel1, true); 402 403 final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID, 404 NotificationChannel.DEFAULT_CHANNEL_ID, false); 405 defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW); 406 mHelper.updateNotificationChannel(PKG, UID, defaultChannel); 407 408 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(), 409 NotificationChannel.DEFAULT_CHANNEL_ID); 410 411 loadStreamXml(baos); 412 413 assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel( 414 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance()); 415 } 416 417 @Test 418 public void testChannelXml_upgradeCreateDefaultChannel() throws Exception { 419 final String preupgradeXml = "<ranking version=\"1\">\n" 420 + "<package name=\"" + PKG 421 + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH 422 + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\"" 423 + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + UID + "\" />\n" 424 + "<package name=\"" + UPDATED_PKG + "\" uid=\"" + UID2 + "\" visibility=\"" 425 + Notification.VISIBILITY_PRIVATE + "\" />\n" 426 + "</ranking>"; 427 XmlPullParser parser = Xml.newPullParser(); 428 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), 429 null); 430 parser.nextTag(); 431 mHelper.readXml(parser, false); 432 433 final NotificationChannel updated1 = 434 mHelper.getNotificationChannel(PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); 435 assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance()); 436 assertTrue(updated1.canBypassDnd()); 437 assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility()); 438 assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE 439 | NotificationChannel.USER_LOCKED_PRIORITY 440 | NotificationChannel.USER_LOCKED_VISIBILITY, 441 updated1.getUserLockedFields()); 442 443 // STOPSHIP - this should be reversed after the STOPSHIP is removed in the tested code. 444 // No Default Channel created for updated packages 445 // assertEquals(null, mHelper.getNotificationChannel(UPDATED_PKG, UID2, 446 // NotificationChannel.DEFAULT_CHANNEL_ID, false)); 447 assertTrue(mHelper.getNotificationChannel(UPDATED_PKG, UID2, 448 NotificationChannel.DEFAULT_CHANNEL_ID, false) != null); 449 } 450 451 @Test 452 public void testChannelXml_upgradeDeletesDefaultChannel() throws Exception { 453 final NotificationChannel defaultChannel = mHelper.getNotificationChannel( 454 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); 455 assertTrue(defaultChannel != null); 456 ByteArrayOutputStream baos = 457 writeXmlAndPurge(PKG, UID, false, NotificationChannel.DEFAULT_CHANNEL_ID); 458 // Load package at higher sdk. 459 final ApplicationInfo upgraded = new ApplicationInfo(); 460 upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 461 when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded); 462 loadStreamXml(baos); 463 464 // STOPSHIP - this should be reversed after the STOPSHIP is removed in the tested code. 465 // Default Channel should be gone. 466 // assertEquals(null, mHelper.getNotificationChannel(PKG, UID, 467 // NotificationChannel.DEFAULT_CHANNEL_ID, false)); 468 assertTrue(mHelper.getNotificationChannel(UPDATED_PKG, UID2, 469 NotificationChannel.DEFAULT_CHANNEL_ID, false) != null); 470 } 471 472 @Test 473 public void testDeletesDefaultChannelAfterChannelIsCreated() throws Exception { 474 mHelper.createNotificationChannel(PKG, UID, 475 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true); 476 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, 477 NotificationChannel.DEFAULT_CHANNEL_ID, "bananas"); 478 479 // Load package at higher sdk. 480 final ApplicationInfo upgraded = new ApplicationInfo(); 481 upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 482 when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded); 483 loadStreamXml(baos); 484 485 // Default Channel should be gone. 486 assertEquals(null, mHelper.getNotificationChannel(PKG, UID, 487 NotificationChannel.DEFAULT_CHANNEL_ID, false)); 488 } 489 490 @Test 491 public void testCreateChannel_blocked() throws Exception { 492 mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_NONE); 493 494 mHelper.createNotificationChannel(PKG, UID, 495 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true); 496 } 497 498 @Test 499 public void testUpdate_userLockedImportance() throws Exception { 500 // all fields locked by user 501 final NotificationChannel channel = 502 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 503 channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE); 504 505 mHelper.createNotificationChannel(PKG, UID, channel, false); 506 507 // same id, try to update 508 final NotificationChannel channel2 = 509 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 510 511 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 512 513 // no fields should be changed 514 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 515 } 516 517 @Test 518 public void testUpdate_userLockedVisibility() throws Exception { 519 // all fields locked by user 520 final NotificationChannel channel = 521 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 522 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 523 channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY); 524 525 mHelper.createNotificationChannel(PKG, UID, channel, false); 526 527 // same id, try to update 528 final NotificationChannel channel2 = 529 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 530 channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); 531 532 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 533 534 // no fields should be changed 535 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 536 } 537 538 @Test 539 public void testUpdate_userLockedVibration() throws Exception { 540 // all fields locked by user 541 final NotificationChannel channel = 542 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 543 channel.enableLights(false); 544 channel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION); 545 546 mHelper.createNotificationChannel(PKG, UID, channel, false); 547 548 // same id, try to update 549 final NotificationChannel channel2 = 550 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 551 channel2.enableVibration(true); 552 channel2.setVibrationPattern(new long[]{100}); 553 554 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 555 556 // no fields should be changed 557 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 558 } 559 560 @Test 561 public void testUpdate_userLockedLights() throws Exception { 562 // all fields locked by user 563 final NotificationChannel channel = 564 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 565 channel.enableLights(false); 566 channel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS); 567 568 mHelper.createNotificationChannel(PKG, UID, channel, false); 569 570 // same id, try to update 571 final NotificationChannel channel2 = 572 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 573 channel2.enableLights(true); 574 575 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 576 577 // no fields should be changed 578 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 579 } 580 581 @Test 582 public void testUpdate_userLockedPriority() throws Exception { 583 // all fields locked by user 584 final NotificationChannel channel = 585 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 586 channel.setBypassDnd(true); 587 channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); 588 589 mHelper.createNotificationChannel(PKG, UID, channel, false); 590 591 // same id, try to update all fields 592 final NotificationChannel channel2 = 593 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 594 channel2.setBypassDnd(false); 595 596 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 597 598 // no fields should be changed 599 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 600 } 601 602 @Test 603 public void testUpdate_userLockedRingtone() throws Exception { 604 // all fields locked by user 605 final NotificationChannel channel = 606 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 607 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 608 channel.lockFields(NotificationChannel.USER_LOCKED_SOUND); 609 610 mHelper.createNotificationChannel(PKG, UID, channel, false); 611 612 // same id, try to update all fields 613 final NotificationChannel channel2 = 614 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 615 channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes); 616 617 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 618 619 // no fields should be changed 620 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 621 } 622 623 @Test 624 public void testUpdate_userLockedBadge() throws Exception { 625 final NotificationChannel channel = 626 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 627 channel.setShowBadge(true); 628 channel.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE); 629 630 mHelper.createNotificationChannel(PKG, UID, channel, false); 631 632 final NotificationChannel channel2 = 633 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 634 channel2.setShowBadge(false); 635 636 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 637 638 // no fields should be changed 639 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 640 } 641 642 @Test 643 public void testUpdate() throws Exception { 644 // no fields locked by user 645 final NotificationChannel channel = 646 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 647 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 648 channel.enableLights(true); 649 channel.setBypassDnd(true); 650 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 651 652 mHelper.createNotificationChannel(PKG, UID, channel, false); 653 654 // same id, try to update all fields 655 final NotificationChannel channel2 = 656 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 657 channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes); 658 channel2.enableLights(false); 659 channel2.setBypassDnd(false); 660 channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); 661 662 mHelper.updateNotificationChannel(PKG, UID, channel2); 663 664 // all fields should be changed 665 assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 666 } 667 668 @Test 669 public void testGetNotificationChannel_ReturnsNullForUnknownChannel() throws Exception { 670 assertEquals(null, mHelper.getNotificationChannel(PKG, UID, "garbage", false)); 671 } 672 673 @Test 674 public void testCreateChannel_CannotChangeHiddenFields() throws Exception { 675 final NotificationChannel channel = 676 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 677 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 678 channel.enableLights(true); 679 channel.setBypassDnd(true); 680 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 681 channel.setShowBadge(true); 682 int lockMask = 0; 683 for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { 684 lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; 685 } 686 channel.lockFields(lockMask); 687 688 mHelper.createNotificationChannel(PKG, UID, channel, true); 689 690 NotificationChannel savedChannel = 691 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 692 693 assertEquals(channel.getName(), savedChannel.getName()); 694 assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); 695 assertFalse(savedChannel.canBypassDnd()); 696 assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); 697 assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); 698 } 699 700 @Test 701 public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception { 702 final NotificationChannel channel = 703 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 704 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 705 channel.enableLights(true); 706 channel.setBypassDnd(true); 707 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 708 channel.setShowBadge(true); 709 int lockMask = 0; 710 for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { 711 lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; 712 } 713 channel.lockFields(lockMask); 714 715 mHelper.createNotificationChannel(PKG, UID, channel, true); 716 717 NotificationChannel savedChannel = 718 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 719 720 assertEquals(channel.getName(), savedChannel.getName()); 721 assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); 722 assertFalse(savedChannel.canBypassDnd()); 723 assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); 724 assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); 725 } 726 727 @Test 728 public void testDeleteNonExistentChannel() throws Exception { 729 mHelper.deleteNotificationChannelGroup(PKG, UID, "does not exist"); 730 } 731 732 @Test 733 public void testGetDeletedChannel() throws Exception { 734 NotificationChannel channel = 735 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 736 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 737 channel.enableLights(true); 738 channel.setBypassDnd(true); 739 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 740 channel.enableVibration(true); 741 channel.setVibrationPattern(new long[]{100, 67, 145, 156}); 742 743 mHelper.createNotificationChannel(PKG, UID, channel, true); 744 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 745 746 // Does not return deleted channel 747 NotificationChannel response = 748 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 749 assertNull(response); 750 751 // Returns deleted channel 752 response = mHelper.getNotificationChannel(PKG, UID, channel.getId(), true); 753 compareChannels(channel, response); 754 assertTrue(response.isDeleted()); 755 } 756 757 @Test 758 public void testGetDeletedChannels() throws Exception { 759 Map<String, NotificationChannel> channelMap = new HashMap<>(); 760 NotificationChannel channel = 761 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 762 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 763 channel.enableLights(true); 764 channel.setBypassDnd(true); 765 channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); 766 channel.enableVibration(true); 767 channel.setVibrationPattern(new long[]{100, 67, 145, 156}); 768 channelMap.put(channel.getId(), channel); 769 NotificationChannel channel2 = 770 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 771 channelMap.put(channel2.getId(), channel2); 772 mHelper.createNotificationChannel(PKG, UID, channel, true); 773 mHelper.createNotificationChannel(PKG, UID, channel2, true); 774 775 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 776 777 // Returns only non-deleted channels 778 List<NotificationChannel> channels = 779 mHelper.getNotificationChannels(PKG, UID, false).getList(); 780 assertEquals(2, channels.size()); // Default channel + non-deleted channel 781 for (NotificationChannel nc : channels) { 782 if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { 783 compareChannels(channel2, nc); 784 } 785 } 786 787 // Returns deleted channels too 788 channels = mHelper.getNotificationChannels(PKG, UID, true).getList(); 789 assertEquals(3, channels.size()); // Includes default channel 790 for (NotificationChannel nc : channels) { 791 if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { 792 compareChannels(channelMap.get(nc.getId()), nc); 793 } 794 } 795 } 796 797 @Test 798 public void testGetDeletedChannelCount() throws Exception { 799 NotificationChannel channel = 800 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 801 NotificationChannel channel2 = 802 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 803 NotificationChannel channel3 = 804 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 805 mHelper.createNotificationChannel(PKG, UID, channel, true); 806 mHelper.createNotificationChannel(PKG, UID, channel2, true); 807 mHelper.createNotificationChannel(PKG, UID, channel3, true); 808 809 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 810 mHelper.deleteNotificationChannel(PKG, UID, channel3.getId()); 811 812 assertEquals(2, mHelper.getDeletedChannelCount(PKG, UID)); 813 assertEquals(0, mHelper.getDeletedChannelCount("pkg2", UID2)); 814 } 815 816 @Test 817 public void testUpdateDeletedChannels() throws Exception { 818 NotificationChannel channel = 819 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 820 mHelper.createNotificationChannel(PKG, UID, channel, true); 821 822 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 823 824 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 825 try { 826 mHelper.updateNotificationChannel(PKG, UID, channel); 827 fail("Updated deleted channel"); 828 } catch (IllegalArgumentException e) { 829 // :) 830 } 831 832 try { 833 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel); 834 fail("Updated deleted channel"); 835 } catch (IllegalArgumentException e) { 836 // :) 837 } 838 } 839 840 @Test 841 public void testCreateDeletedChannel() throws Exception { 842 long[] vibration = new long[]{100, 67, 145, 156}; 843 NotificationChannel channel = 844 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 845 channel.setVibrationPattern(vibration); 846 847 mHelper.createNotificationChannel(PKG, UID, channel, true); 848 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 849 850 NotificationChannel newChannel = new NotificationChannel( 851 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); 852 newChannel.setVibrationPattern(new long[]{100}); 853 854 mHelper.createNotificationChannel(PKG, UID, newChannel, true); 855 856 // No long deleted, using old settings 857 compareChannels(channel, 858 mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false)); 859 } 860 861 @Test 862 public void testCreateChannel_defaultChannelId() throws Exception { 863 try { 864 mHelper.createNotificationChannel(PKG, UID, new NotificationChannel( 865 NotificationChannel.DEFAULT_CHANNEL_ID, "ha", IMPORTANCE_HIGH), true); 866 fail("Allowed to create default channel"); 867 } catch (IllegalArgumentException e) { 868 // pass 869 } 870 } 871 872 @Test 873 public void testCreateChannel_alreadyExists() throws Exception { 874 long[] vibration = new long[]{100, 67, 145, 156}; 875 NotificationChannel channel = 876 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 877 channel.setVibrationPattern(vibration); 878 879 mHelper.createNotificationChannel(PKG, UID, channel, true); 880 881 NotificationChannel newChannel = new NotificationChannel( 882 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); 883 newChannel.setVibrationPattern(new long[]{100}); 884 885 mHelper.createNotificationChannel(PKG, UID, newChannel, true); 886 887 // Old settings not overridden 888 compareChannels(channel, 889 mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false)); 890 } 891 892 @Test 893 public void testCreateChannel_addMissingSound() throws Exception { 894 final NotificationChannel channel = 895 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 896 mHelper.createNotificationChannel(PKG, UID, channel, true); 897 assertNotNull(mHelper.getNotificationChannel( 898 PKG, UID, channel.getId(), false).getSound()); 899 } 900 901 @Test 902 public void testCreateChannel_noOverrideSound() throws Exception { 903 Uri sound = new Uri.Builder().scheme("test").build(); 904 final NotificationChannel channel = new NotificationChannel("id2", "name2", 905 NotificationManager.IMPORTANCE_DEFAULT); 906 channel.setSound(sound, mAudioAttributes); 907 mHelper.createNotificationChannel(PKG, UID, channel, true); 908 assertEquals(sound, mHelper.getNotificationChannel( 909 PKG, UID, channel.getId(), false).getSound()); 910 } 911 912 @Test 913 public void testPermanentlyDeleteChannels() throws Exception { 914 NotificationChannel channel1 = 915 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 916 NotificationChannel channel2 = 917 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 918 919 mHelper.createNotificationChannel(PKG, UID, channel1, true); 920 mHelper.createNotificationChannel(PKG, UID, channel2, false); 921 922 mHelper.permanentlyDeleteNotificationChannels(PKG, UID); 923 924 // Only default channel remains 925 assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size()); 926 } 927 928 @Test 929 public void testDeleteGroup() throws Exception { 930 NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted"); 931 NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted"); 932 NotificationChannel nonGroupedNonDeletedChannel = 933 new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH); 934 NotificationChannel groupedButNotDeleted = 935 new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT); 936 groupedButNotDeleted.setGroup("not"); 937 NotificationChannel groupedAndDeleted = 938 new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT); 939 groupedAndDeleted.setGroup("totally"); 940 941 mHelper.createNotificationChannelGroup(PKG, UID, notDeleted, true); 942 mHelper.createNotificationChannelGroup(PKG, UID, deleted, true); 943 mHelper.createNotificationChannel(PKG, UID, nonGroupedNonDeletedChannel, true); 944 mHelper.createNotificationChannel(PKG, UID, groupedAndDeleted, true); 945 mHelper.createNotificationChannel(PKG, UID, groupedButNotDeleted, true); 946 947 mHelper.deleteNotificationChannelGroup(PKG, UID, deleted.getId()); 948 949 assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG, UID)); 950 assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG, UID)); 951 952 assertNull(mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), false)); 953 compareChannels(groupedAndDeleted, 954 mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), true)); 955 956 compareChannels(groupedButNotDeleted, 957 mHelper.getNotificationChannel(PKG, UID, groupedButNotDeleted.getId(), false)); 958 compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel( 959 PKG, UID, nonGroupedNonDeletedChannel.getId(), false)); 960 961 // notDeleted 962 assertEquals(1, mHelper.getNotificationChannelGroups(PKG, UID).size()); 963 } 964 965 @Test 966 public void testOnPackageChanged_packageRemoval() throws Exception { 967 // Deleted 968 NotificationChannel channel1 = 969 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 970 mHelper.createNotificationChannel(PKG, UID, channel1, true); 971 972 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 973 974 assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size()); 975 976 // Not deleted 977 mHelper.createNotificationChannel(PKG, UID, channel1, true); 978 979 mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 980 assertEquals(2, mHelper.getNotificationChannels(PKG, UID, false).getList().size()); 981 } 982 983 @Test 984 public void testOnPackageChanged_packageRemoval_importance() throws Exception { 985 mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_HIGH); 986 987 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 988 989 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); 990 } 991 992 @Test 993 public void testOnPackageChanged_packageRemoval_groups() throws Exception { 994 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 995 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 996 NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); 997 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 998 999 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 1000 1001 assertEquals(0, mHelper.getNotificationChannelGroups(PKG, UID, true).getList().size()); 1002 } 1003 1004 @Test 1005 public void testRecordDefaults() throws Exception { 1006 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); 1007 assertEquals(true, mHelper.canShowBadge(PKG, UID)); 1008 assertEquals(1, mHelper.getNotificationChannels(PKG, UID, false).getList().size()); 1009 } 1010 1011 @Test 1012 public void testCreateGroup() throws Exception { 1013 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1014 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1015 assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG, UID).iterator().next()); 1016 } 1017 1018 @Test 1019 public void testCannotCreateChannel_badGroup() throws Exception { 1020 NotificationChannel channel1 = 1021 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1022 channel1.setGroup("garbage"); 1023 try { 1024 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1025 fail("Created a channel with a bad group"); 1026 } catch (IllegalArgumentException e) { 1027 } 1028 } 1029 1030 @Test 1031 public void testCannotCreateChannel_goodGroup() throws Exception { 1032 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1033 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1034 NotificationChannel channel1 = 1035 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1036 channel1.setGroup(ncg.getId()); 1037 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1038 1039 assertEquals(ncg.getId(), 1040 mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false).getGroup()); 1041 } 1042 1043 @Test 1044 public void testGetChannelGroups() throws Exception { 1045 NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s"); 1046 mHelper.createNotificationChannelGroup(PKG, UID, unused, true); 1047 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1048 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1049 NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); 1050 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 1051 1052 NotificationChannel channel1 = 1053 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1054 channel1.setGroup(ncg.getId()); 1055 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1056 NotificationChannel channel1a = 1057 new NotificationChannel("id1a", "name1", NotificationManager.IMPORTANCE_HIGH); 1058 channel1a.setGroup(ncg.getId()); 1059 mHelper.createNotificationChannel(PKG, UID, channel1a, true); 1060 1061 NotificationChannel channel2 = 1062 new NotificationChannel("id2", "name1", NotificationManager.IMPORTANCE_HIGH); 1063 channel2.setGroup(ncg2.getId()); 1064 mHelper.createNotificationChannel(PKG, UID, channel2, true); 1065 1066 NotificationChannel channel3 = 1067 new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH); 1068 mHelper.createNotificationChannel(PKG, UID, channel3, true); 1069 1070 List<NotificationChannelGroup> actual = 1071 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 1072 assertEquals(3, actual.size()); 1073 for (NotificationChannelGroup group : actual) { 1074 if (group.getId() == null) { 1075 assertEquals(2, group.getChannels().size()); // misc channel too 1076 assertTrue(channel3.getId().equals(group.getChannels().get(0).getId()) 1077 || channel3.getId().equals(group.getChannels().get(1).getId())); 1078 } else if (group.getId().equals(ncg.getId())) { 1079 assertEquals(2, group.getChannels().size()); 1080 if (group.getChannels().get(0).getId().equals(channel1.getId())) { 1081 assertTrue(group.getChannels().get(1).getId().equals(channel1a.getId())); 1082 } else if (group.getChannels().get(0).getId().equals(channel1a.getId())) { 1083 assertTrue(group.getChannels().get(1).getId().equals(channel1.getId())); 1084 } else { 1085 fail("expected channel not found"); 1086 } 1087 } else if (group.getId().equals(ncg2.getId())) { 1088 assertEquals(1, group.getChannels().size()); 1089 assertEquals(channel2.getId(), group.getChannels().get(0).getId()); 1090 } 1091 } 1092 } 1093 1094 @Test 1095 public void testGetChannelGroups_noSideEffects() throws Exception { 1096 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1097 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1098 1099 NotificationChannel channel1 = 1100 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1101 channel1.setGroup(ncg.getId()); 1102 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1103 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 1104 1105 channel1.setImportance(IMPORTANCE_LOW); 1106 mHelper.updateNotificationChannel(PKG, UID, channel1); 1107 1108 List<NotificationChannelGroup> actual = 1109 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 1110 1111 assertEquals(2, actual.size()); 1112 for (NotificationChannelGroup group : actual) { 1113 if (Objects.equals(group.getId(), ncg.getId())) { 1114 assertEquals(1, group.getChannels().size()); 1115 } 1116 } 1117 } 1118 1119 @Test 1120 public void testCreateChannel_updateName() throws Exception { 1121 NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); 1122 mHelper.createNotificationChannel(PKG, UID, nc, true); 1123 NotificationChannel actual = mHelper.getNotificationChannel(PKG, UID, "id", false); 1124 assertEquals("hello", actual.getName()); 1125 1126 nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH); 1127 mHelper.createNotificationChannel(PKG, UID, nc, true); 1128 1129 actual = mHelper.getNotificationChannel(PKG, UID, "id", false); 1130 assertEquals("goodbye", actual.getName()); 1131 assertEquals(IMPORTANCE_DEFAULT, actual.getImportance()); 1132 } 1133 1134 @Test 1135 public void testDumpChannelsJson() throws Exception { 1136 final ApplicationInfo upgrade = new ApplicationInfo(); 1137 upgrade.targetSdkVersion = Build.VERSION_CODES.O; 1138 try { 1139 when(mPm.getApplicationInfoAsUser( 1140 anyString(), anyInt(), anyInt())).thenReturn(upgrade); 1141 } catch (PackageManager.NameNotFoundException e) { 1142 } 1143 ArrayMap<String, Integer> expectedChannels = new ArrayMap<>(); 1144 int numPackages = ThreadLocalRandom.current().nextInt(1, 5); 1145 for (int i = 0; i < numPackages; i++) { 1146 String pkgName = "pkg" + i; 1147 int numChannels = ThreadLocalRandom.current().nextInt(1, 10); 1148 for (int j = 0; j < numChannels; j++) { 1149 mHelper.createNotificationChannel(pkgName, UID, 1150 new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true); 1151 } 1152 expectedChannels.put(pkgName, numChannels); 1153 } 1154 1155 // delete the first channel of the first package 1156 String pkg = expectedChannels.keyAt(0); 1157 mHelper.deleteNotificationChannel("pkg" + 0, UID, "0"); 1158 // dump should not include deleted channels 1159 int count = expectedChannels.get(pkg); 1160 expectedChannels.put(pkg, count - 1); 1161 1162 JSONArray actual = mHelper.dumpChannelsJson(new NotificationManagerService.DumpFilter()); 1163 assertEquals(numPackages, actual.length()); 1164 for (int i = 0; i < numPackages; i++) { 1165 JSONObject object = actual.getJSONObject(i); 1166 assertTrue(expectedChannels.containsKey(object.get("packageName"))); 1167 assertEquals(expectedChannels.get(object.get("packageName")).intValue() + 1, 1168 object.getInt("channelCount")); 1169 } 1170 } 1171} 1172