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