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