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