RankingHelperTest.java revision 2c98e18ce5f82ee8a93fcaa30c038fe0ab52f253
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 testCreateChannel_blocked() throws Exception { 494 mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_NONE); 495 496 mHelper.createNotificationChannel(PKG, UID, 497 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true); 498 } 499 500 @Test 501 public void testUpdate_userLockedImportance() throws Exception { 502 // all fields locked by user 503 final NotificationChannel channel = 504 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 505 channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE); 506 507 mHelper.createNotificationChannel(PKG, UID, channel, false); 508 509 // same id, try to update 510 final NotificationChannel channel2 = 511 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 512 513 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 514 515 // no fields should be changed 516 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 517 } 518 519 @Test 520 public void testUpdate_userLockedVisibility() throws Exception { 521 // all fields locked by user 522 final NotificationChannel channel = 523 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 524 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 525 channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY); 526 527 mHelper.createNotificationChannel(PKG, UID, channel, false); 528 529 // same id, try to update 530 final NotificationChannel channel2 = 531 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 532 channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); 533 534 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 535 536 // no fields should be changed 537 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 538 } 539 540 @Test 541 public void testUpdate_userLockedVibration() throws Exception { 542 // all fields locked by user 543 final NotificationChannel channel = 544 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 545 channel.enableLights(false); 546 channel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION); 547 548 mHelper.createNotificationChannel(PKG, UID, channel, false); 549 550 // same id, try to update 551 final NotificationChannel channel2 = 552 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 553 channel2.enableVibration(true); 554 channel2.setVibrationPattern(new long[]{100}); 555 556 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 557 558 // no fields should be changed 559 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 560 } 561 562 @Test 563 public void testUpdate_userLockedLights() throws Exception { 564 // all fields locked by user 565 final NotificationChannel channel = 566 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 567 channel.enableLights(false); 568 channel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS); 569 570 mHelper.createNotificationChannel(PKG, UID, channel, false); 571 572 // same id, try to update 573 final NotificationChannel channel2 = 574 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 575 channel2.enableLights(true); 576 577 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 578 579 // no fields should be changed 580 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 581 } 582 583 @Test 584 public void testUpdate_userLockedPriority() throws Exception { 585 // all fields locked by user 586 final NotificationChannel channel = 587 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 588 channel.setBypassDnd(true); 589 channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); 590 591 mHelper.createNotificationChannel(PKG, UID, channel, false); 592 593 // same id, try to update all fields 594 final NotificationChannel channel2 = 595 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 596 channel2.setBypassDnd(false); 597 598 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 599 600 // no fields should be changed 601 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 602 } 603 604 @Test 605 public void testUpdate_userLockedRingtone() throws Exception { 606 // all fields locked by user 607 final NotificationChannel channel = 608 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 609 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 610 channel.lockFields(NotificationChannel.USER_LOCKED_SOUND); 611 612 mHelper.createNotificationChannel(PKG, UID, channel, false); 613 614 // same id, try to update all fields 615 final NotificationChannel channel2 = 616 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 617 channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes); 618 619 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 620 621 // no fields should be changed 622 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 623 } 624 625 @Test 626 public void testUpdate_userLockedBadge() throws Exception { 627 final NotificationChannel channel = 628 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 629 channel.setShowBadge(true); 630 channel.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE); 631 632 mHelper.createNotificationChannel(PKG, UID, channel, false); 633 634 final NotificationChannel channel2 = 635 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 636 channel2.setShowBadge(false); 637 638 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel2); 639 640 // no fields should be changed 641 assertEquals(channel, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 642 } 643 644 @Test 645 public void testUpdate() throws Exception { 646 // no fields locked by user 647 final NotificationChannel channel = 648 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 649 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 650 channel.enableLights(true); 651 channel.setBypassDnd(true); 652 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 653 654 mHelper.createNotificationChannel(PKG, UID, channel, false); 655 656 // same id, try to update all fields 657 final NotificationChannel channel2 = 658 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 659 channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes); 660 channel2.enableLights(false); 661 channel2.setBypassDnd(false); 662 channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); 663 664 mHelper.updateNotificationChannel(PKG, UID, channel2); 665 666 // all fields should be changed 667 assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 668 } 669 670 @Test 671 public void testGetNotificationChannel_ReturnsNullForUnknownChannel() throws Exception { 672 assertEquals(null, mHelper.getNotificationChannel(PKG, UID, "garbage", false)); 673 } 674 675 @Test 676 public void testCreateChannel_CannotChangeHiddenFields() throws Exception { 677 final NotificationChannel channel = 678 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 679 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 680 channel.enableLights(true); 681 channel.setBypassDnd(true); 682 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 683 channel.setShowBadge(true); 684 int lockMask = 0; 685 for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { 686 lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; 687 } 688 channel.lockFields(lockMask); 689 690 mHelper.createNotificationChannel(PKG, UID, channel, true); 691 692 NotificationChannel savedChannel = 693 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 694 695 assertEquals(channel.getName(), savedChannel.getName()); 696 assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); 697 assertFalse(savedChannel.canBypassDnd()); 698 assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); 699 assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); 700 } 701 702 @Test 703 public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception { 704 final NotificationChannel channel = 705 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 706 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 707 channel.enableLights(true); 708 channel.setBypassDnd(true); 709 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 710 channel.setShowBadge(true); 711 int lockMask = 0; 712 for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { 713 lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; 714 } 715 channel.lockFields(lockMask); 716 717 mHelper.createNotificationChannel(PKG, UID, channel, true); 718 719 NotificationChannel savedChannel = 720 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 721 722 assertEquals(channel.getName(), savedChannel.getName()); 723 assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); 724 assertFalse(savedChannel.canBypassDnd()); 725 assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); 726 assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); 727 } 728 729 @Test 730 public void testDeleteNonExistentChannel() throws Exception { 731 mHelper.deleteNotificationChannelGroup(PKG, UID, "does not exist"); 732 } 733 734 @Test 735 public void testGetDeletedChannel() throws Exception { 736 NotificationChannel channel = 737 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 738 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 739 channel.enableLights(true); 740 channel.setBypassDnd(true); 741 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 742 channel.enableVibration(true); 743 channel.setVibrationPattern(new long[]{100, 67, 145, 156}); 744 745 mHelper.createNotificationChannel(PKG, UID, channel, true); 746 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 747 748 // Does not return deleted channel 749 NotificationChannel response = 750 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 751 assertNull(response); 752 753 // Returns deleted channel 754 response = mHelper.getNotificationChannel(PKG, UID, channel.getId(), true); 755 compareChannels(channel, response); 756 assertTrue(response.isDeleted()); 757 } 758 759 @Test 760 public void testGetDeletedChannels() throws Exception { 761 Map<String, NotificationChannel> channelMap = new HashMap<>(); 762 NotificationChannel channel = 763 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 764 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 765 channel.enableLights(true); 766 channel.setBypassDnd(true); 767 channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); 768 channel.enableVibration(true); 769 channel.setVibrationPattern(new long[]{100, 67, 145, 156}); 770 channelMap.put(channel.getId(), channel); 771 NotificationChannel channel2 = 772 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 773 channelMap.put(channel2.getId(), channel2); 774 mHelper.createNotificationChannel(PKG, UID, channel, true); 775 mHelper.createNotificationChannel(PKG, UID, channel2, true); 776 777 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 778 779 // Returns only non-deleted channels 780 List<NotificationChannel> channels = 781 mHelper.getNotificationChannels(PKG, UID, false).getList(); 782 assertEquals(2, channels.size()); // Default channel + non-deleted channel 783 for (NotificationChannel nc : channels) { 784 if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { 785 compareChannels(channel2, nc); 786 } 787 } 788 789 // Returns deleted channels too 790 channels = mHelper.getNotificationChannels(PKG, UID, true).getList(); 791 assertEquals(3, channels.size()); // Includes default channel 792 for (NotificationChannel nc : channels) { 793 if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { 794 compareChannels(channelMap.get(nc.getId()), nc); 795 } 796 } 797 } 798 799 @Test 800 public void testGetDeletedChannelCount() throws Exception { 801 NotificationChannel channel = 802 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 803 NotificationChannel channel2 = 804 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 805 NotificationChannel channel3 = 806 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 807 mHelper.createNotificationChannel(PKG, UID, channel, true); 808 mHelper.createNotificationChannel(PKG, UID, channel2, true); 809 mHelper.createNotificationChannel(PKG, UID, channel3, true); 810 811 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 812 mHelper.deleteNotificationChannel(PKG, UID, channel3.getId()); 813 814 assertEquals(2, mHelper.getDeletedChannelCount(PKG, UID)); 815 assertEquals(0, mHelper.getDeletedChannelCount("pkg2", UID2)); 816 } 817 818 @Test 819 public void testUpdateDeletedChannels() throws Exception { 820 NotificationChannel channel = 821 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 822 mHelper.createNotificationChannel(PKG, UID, channel, true); 823 824 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 825 826 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 827 try { 828 mHelper.updateNotificationChannel(PKG, UID, channel); 829 fail("Updated deleted channel"); 830 } catch (IllegalArgumentException e) { 831 // :) 832 } 833 834 try { 835 mHelper.updateNotificationChannelFromAssistant(PKG, UID, channel); 836 fail("Updated deleted channel"); 837 } catch (IllegalArgumentException e) { 838 // :) 839 } 840 } 841 842 @Test 843 public void testCreateDeletedChannel() throws Exception { 844 long[] vibration = new long[]{100, 67, 145, 156}; 845 NotificationChannel channel = 846 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 847 channel.setVibrationPattern(vibration); 848 849 mHelper.createNotificationChannel(PKG, UID, channel, true); 850 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 851 852 NotificationChannel newChannel = new NotificationChannel( 853 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); 854 newChannel.setVibrationPattern(new long[]{100}); 855 856 mHelper.createNotificationChannel(PKG, UID, newChannel, true); 857 858 // No long deleted, using old settings 859 compareChannels(channel, 860 mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false)); 861 } 862 863 @Test 864 public void testCreateChannel_defaultChannelId() throws Exception { 865 try { 866 mHelper.createNotificationChannel(PKG, UID, new NotificationChannel( 867 NotificationChannel.DEFAULT_CHANNEL_ID, "ha", IMPORTANCE_HIGH), true); 868 fail("Allowed to create default channel"); 869 } catch (IllegalArgumentException e) { 870 // pass 871 } 872 } 873 874 @Test 875 public void testCreateChannel_alreadyExists() throws Exception { 876 long[] vibration = new long[]{100, 67, 145, 156}; 877 NotificationChannel channel = 878 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 879 channel.setVibrationPattern(vibration); 880 881 mHelper.createNotificationChannel(PKG, UID, channel, true); 882 883 NotificationChannel newChannel = new NotificationChannel( 884 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); 885 newChannel.setVibrationPattern(new long[]{100}); 886 887 mHelper.createNotificationChannel(PKG, UID, newChannel, true); 888 889 // Old settings not overridden 890 compareChannels(channel, 891 mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false)); 892 } 893 894 @Test 895 public void testCreateChannel_addMissingSound() throws Exception { 896 final NotificationChannel channel = 897 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 898 mHelper.createNotificationChannel(PKG, UID, channel, true); 899 assertNotNull(mHelper.getNotificationChannel( 900 PKG, UID, channel.getId(), false).getSound()); 901 } 902 903 @Test 904 public void testCreateChannel_noOverrideSound() throws Exception { 905 Uri sound = new Uri.Builder().scheme("test").build(); 906 final NotificationChannel channel = new NotificationChannel("id2", "name2", 907 NotificationManager.IMPORTANCE_DEFAULT); 908 channel.setSound(sound, mAudioAttributes); 909 mHelper.createNotificationChannel(PKG, UID, channel, true); 910 assertEquals(sound, mHelper.getNotificationChannel( 911 PKG, UID, channel.getId(), false).getSound()); 912 } 913 914 @Test 915 public void testPermanentlyDeleteChannels() throws Exception { 916 NotificationChannel channel1 = 917 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 918 NotificationChannel channel2 = 919 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 920 921 mHelper.createNotificationChannel(PKG, UID, channel1, true); 922 mHelper.createNotificationChannel(PKG, UID, channel2, false); 923 924 mHelper.permanentlyDeleteNotificationChannels(PKG, UID); 925 926 // Only default channel remains 927 assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size()); 928 } 929 930 @Test 931 public void testDeleteGroup() throws Exception { 932 NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted"); 933 NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted"); 934 NotificationChannel nonGroupedNonDeletedChannel = 935 new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH); 936 NotificationChannel groupedButNotDeleted = 937 new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT); 938 groupedButNotDeleted.setGroup("not"); 939 NotificationChannel groupedAndDeleted = 940 new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT); 941 groupedAndDeleted.setGroup("totally"); 942 943 mHelper.createNotificationChannelGroup(PKG, UID, notDeleted, true); 944 mHelper.createNotificationChannelGroup(PKG, UID, deleted, true); 945 mHelper.createNotificationChannel(PKG, UID, nonGroupedNonDeletedChannel, true); 946 mHelper.createNotificationChannel(PKG, UID, groupedAndDeleted, true); 947 mHelper.createNotificationChannel(PKG, UID, groupedButNotDeleted, true); 948 949 mHelper.deleteNotificationChannelGroup(PKG, UID, deleted.getId()); 950 951 assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG, UID)); 952 assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG, UID)); 953 954 assertNull(mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), false)); 955 compareChannels(groupedAndDeleted, 956 mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), true)); 957 958 compareChannels(groupedButNotDeleted, 959 mHelper.getNotificationChannel(PKG, UID, groupedButNotDeleted.getId(), false)); 960 compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel( 961 PKG, UID, nonGroupedNonDeletedChannel.getId(), false)); 962 963 // notDeleted 964 assertEquals(1, mHelper.getNotificationChannelGroups(PKG, UID).size()); 965 } 966 967 @Test 968 public void testOnPackageChanged_packageRemoval() throws Exception { 969 // Deleted 970 NotificationChannel channel1 = 971 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 972 mHelper.createNotificationChannel(PKG, UID, channel1, true); 973 974 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 975 976 assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size()); 977 978 // Not deleted 979 mHelper.createNotificationChannel(PKG, UID, channel1, true); 980 981 mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 982 assertEquals(2, mHelper.getNotificationChannels(PKG, UID, false).getList().size()); 983 } 984 985 @Test 986 public void testOnPackageChanged_packageRemoval_importance() throws Exception { 987 mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_HIGH); 988 989 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 990 991 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); 992 } 993 994 @Test 995 public void testOnPackageChanged_packageRemoval_groups() throws Exception { 996 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 997 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 998 NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); 999 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 1000 1001 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 1002 1003 assertEquals(0, mHelper.getNotificationChannelGroups(PKG, UID, true).getList().size()); 1004 } 1005 1006 @Test 1007 public void testRecordDefaults() throws Exception { 1008 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); 1009 assertEquals(true, mHelper.canShowBadge(PKG, UID)); 1010 assertEquals(1, mHelper.getNotificationChannels(PKG, UID, false).getList().size()); 1011 } 1012 1013 @Test 1014 public void testCreateGroup() throws Exception { 1015 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1016 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1017 assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG, UID).iterator().next()); 1018 } 1019 1020 @Test 1021 public void testCannotCreateChannel_badGroup() throws Exception { 1022 NotificationChannel channel1 = 1023 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1024 channel1.setGroup("garbage"); 1025 try { 1026 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1027 fail("Created a channel with a bad group"); 1028 } catch (IllegalArgumentException e) { 1029 } 1030 } 1031 1032 @Test 1033 public void testCannotCreateChannel_goodGroup() throws Exception { 1034 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1035 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1036 NotificationChannel channel1 = 1037 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1038 channel1.setGroup(ncg.getId()); 1039 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1040 1041 assertEquals(ncg.getId(), 1042 mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false).getGroup()); 1043 } 1044 1045 @Test 1046 public void testGetChannelGroups() throws Exception { 1047 NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s"); 1048 mHelper.createNotificationChannelGroup(PKG, UID, unused, true); 1049 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1050 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1051 NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); 1052 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 1053 1054 NotificationChannel channel1 = 1055 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1056 channel1.setGroup(ncg.getId()); 1057 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1058 NotificationChannel channel1a = 1059 new NotificationChannel("id1a", "name1", NotificationManager.IMPORTANCE_HIGH); 1060 channel1a.setGroup(ncg.getId()); 1061 mHelper.createNotificationChannel(PKG, UID, channel1a, true); 1062 1063 NotificationChannel channel2 = 1064 new NotificationChannel("id2", "name1", NotificationManager.IMPORTANCE_HIGH); 1065 channel2.setGroup(ncg2.getId()); 1066 mHelper.createNotificationChannel(PKG, UID, channel2, true); 1067 1068 NotificationChannel channel3 = 1069 new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH); 1070 mHelper.createNotificationChannel(PKG, UID, channel3, true); 1071 1072 List<NotificationChannelGroup> actual = 1073 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 1074 assertEquals(3, actual.size()); 1075 for (NotificationChannelGroup group : actual) { 1076 if (group.getId() == null) { 1077 assertEquals(2, group.getChannels().size()); // misc channel too 1078 assertTrue(channel3.getId().equals(group.getChannels().get(0).getId()) 1079 || channel3.getId().equals(group.getChannels().get(1).getId())); 1080 } else if (group.getId().equals(ncg.getId())) { 1081 assertEquals(2, group.getChannels().size()); 1082 if (group.getChannels().get(0).getId().equals(channel1.getId())) { 1083 assertTrue(group.getChannels().get(1).getId().equals(channel1a.getId())); 1084 } else if (group.getChannels().get(0).getId().equals(channel1a.getId())) { 1085 assertTrue(group.getChannels().get(1).getId().equals(channel1.getId())); 1086 } else { 1087 fail("expected channel not found"); 1088 } 1089 } else if (group.getId().equals(ncg2.getId())) { 1090 assertEquals(1, group.getChannels().size()); 1091 assertEquals(channel2.getId(), group.getChannels().get(0).getId()); 1092 } 1093 } 1094 } 1095 1096 @Test 1097 public void testGetChannelGroups_noSideEffects() throws Exception { 1098 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1099 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1100 1101 NotificationChannel channel1 = 1102 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1103 channel1.setGroup(ncg.getId()); 1104 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1105 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 1106 1107 channel1.setImportance(IMPORTANCE_LOW); 1108 mHelper.updateNotificationChannel(PKG, UID, channel1); 1109 1110 List<NotificationChannelGroup> actual = 1111 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 1112 1113 assertEquals(2, actual.size()); 1114 for (NotificationChannelGroup group : actual) { 1115 if (Objects.equals(group.getId(), ncg.getId())) { 1116 assertEquals(1, group.getChannels().size()); 1117 } 1118 } 1119 } 1120 1121 @Test 1122 public void testCreateChannel_updateName() throws Exception { 1123 NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); 1124 mHelper.createNotificationChannel(PKG, UID, nc, true); 1125 NotificationChannel actual = mHelper.getNotificationChannel(PKG, UID, "id", false); 1126 assertEquals("hello", actual.getName()); 1127 1128 nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH); 1129 mHelper.createNotificationChannel(PKG, UID, nc, true); 1130 1131 actual = mHelper.getNotificationChannel(PKG, UID, "id", false); 1132 assertEquals("goodbye", actual.getName()); 1133 assertEquals(IMPORTANCE_DEFAULT, actual.getImportance()); 1134 } 1135 1136 @Test 1137 public void testDumpChannelsJson() throws Exception { 1138 final ApplicationInfo upgrade = new ApplicationInfo(); 1139 upgrade.targetSdkVersion = Build.VERSION_CODES.O; 1140 try { 1141 when(mPm.getApplicationInfoAsUser( 1142 anyString(), anyInt(), anyInt())).thenReturn(upgrade); 1143 } catch (PackageManager.NameNotFoundException e) { 1144 } 1145 ArrayMap<String, Integer> expectedChannels = new ArrayMap<>(); 1146 int numPackages = ThreadLocalRandom.current().nextInt(1, 5); 1147 for (int i = 0; i < numPackages; i++) { 1148 String pkgName = "pkg" + i; 1149 int numChannels = ThreadLocalRandom.current().nextInt(1, 10); 1150 for (int j = 0; j < numChannels; j++) { 1151 mHelper.createNotificationChannel(pkgName, UID, 1152 new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true); 1153 } 1154 expectedChannels.put(pkgName, numChannels); 1155 } 1156 1157 // delete the first channel of the first package 1158 String pkg = expectedChannels.keyAt(0); 1159 mHelper.deleteNotificationChannel("pkg" + 0, UID, "0"); 1160 // dump should not include deleted channels 1161 int count = expectedChannels.get(pkg); 1162 expectedChannels.put(pkg, count - 1); 1163 1164 JSONArray actual = mHelper.dumpChannelsJson(new NotificationManagerService.DumpFilter()); 1165 assertEquals(numPackages, actual.length()); 1166 for (int i = 0; i < numPackages; i++) { 1167 JSONObject object = actual.getJSONObject(i); 1168 assertTrue(expectedChannels.containsKey(object.get("packageName"))); 1169 assertEquals(expectedChannels.get(object.get("packageName")).intValue() + 1, 1170 object.getInt("channelCount")); 1171 } 1172 } 1173} 1174