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 */ 16 package com.android.server.notification; 17 18 import static android.app.NotificationManager.IMPORTANCE_DEFAULT; 19 import static android.app.NotificationManager.IMPORTANCE_HIGH; 20 import static android.app.NotificationManager.IMPORTANCE_LOW; 21 import static android.app.NotificationManager.IMPORTANCE_MAX; 22 import static android.app.NotificationManager.IMPORTANCE_NONE; 23 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; 24 25 import static junit.framework.Assert.assertNull; 26 import static junit.framework.Assert.fail; 27 28 import android.app.Notification; 29 import android.app.NotificationChannel; 30 import android.app.NotificationChannelGroup; 31 import android.app.NotificationManager; 32 import android.content.ContentProvider; 33 import android.content.Context; 34 import android.content.IContentProvider; 35 import android.content.pm.ApplicationInfo; 36 import android.content.pm.PackageManager; 37 import android.content.res.Resources; 38 import android.graphics.Color; 39 import android.media.AudioAttributes; 40 import android.net.Uri; 41 import android.os.Build; 42 import android.os.UserHandle; 43 import android.provider.Settings; 44 import android.provider.Settings.Secure; 45 import android.service.notification.StatusBarNotification; 46 import android.support.test.InstrumentationRegistry; 47 import android.support.test.runner.AndroidJUnit4; 48 import android.test.suitebuilder.annotation.SmallTest; 49 import android.testing.TestableContentResolver; 50 import android.util.ArrayMap; 51 import android.util.Xml; 52 53 import com.android.internal.util.FastXmlSerializer; 54 55 import org.json.JSONArray; 56 import org.json.JSONObject; 57 import org.junit.Before; 58 import org.junit.Test; 59 import org.junit.runner.RunWith; 60 import org.mockito.Mock; 61 import org.mockito.MockitoAnnotations; 62 import org.xmlpull.v1.XmlPullParser; 63 import org.xmlpull.v1.XmlSerializer; 64 65 import java.io.BufferedInputStream; 66 import java.io.BufferedOutputStream; 67 import java.io.ByteArrayInputStream; 68 import java.io.ByteArrayOutputStream; 69 import java.util.ArrayList; 70 import java.util.Arrays; 71 import java.util.HashMap; 72 import java.util.List; 73 import java.util.Map; 74 import java.util.Objects; 75 import java.util.concurrent.ThreadLocalRandom; 76 77 import static org.junit.Assert.assertEquals; 78 import static org.junit.Assert.assertFalse; 79 import static org.junit.Assert.assertNotNull; 80 import static org.junit.Assert.assertTrue; 81 import static org.mockito.ArgumentMatchers.any; 82 import static org.mockito.Matchers.anyInt; 83 import static org.mockito.Matchers.anyString; 84 import static org.mockito.Matchers.eq; 85 import static org.mockito.Mockito.mock; 86 import static org.mockito.Mockito.never; 87 import static org.mockito.Mockito.times; 88 import static org.mockito.Mockito.verify; 89 import static org.mockito.Mockito.when; 90 91 @SmallTest 92 @RunWith(AndroidJUnit4.class) 93 public class RankingHelperTest extends NotificationTestCase { 94 private static final String PKG = "com.android.server.notification"; 95 private static final int UID = 0; 96 private static final UserHandle USER = UserHandle.of(0); 97 private static final String UPDATED_PKG = "updatedPkg"; 98 private static final int UID2 = 1111; 99 private static final UserHandle USER2 = UserHandle.of(10); 100 private static final String TEST_CHANNEL_ID = "test_channel_id"; 101 private static final String TEST_AUTHORITY = "test"; 102 private static final Uri SOUND_URI = 103 Uri.parse("content://" + TEST_AUTHORITY + "/internal/audio/media/10"); 104 private static final Uri CANONICAL_SOUND_URI = 105 Uri.parse("content://" + TEST_AUTHORITY 106 + "/internal/audio/media/10?title=Test&canonical=1"); 107 108 @Mock NotificationUsageStats mUsageStats; 109 @Mock RankingHandler mHandler; 110 @Mock PackageManager mPm; 111 @Mock IContentProvider mTestIContentProvider; 112 @Mock Context mContext; 113 114 private Notification mNotiGroupGSortA; 115 private Notification mNotiGroupGSortB; 116 private Notification mNotiNoGroup; 117 private Notification mNotiNoGroup2; 118 private Notification mNotiNoGroupSortA; 119 private NotificationRecord mRecordGroupGSortA; 120 private NotificationRecord mRecordGroupGSortB; 121 private NotificationRecord mRecordNoGroup; 122 private NotificationRecord mRecordNoGroup2; 123 private NotificationRecord mRecordNoGroupSortA; 124 private RankingHelper mHelper; 125 private AudioAttributes mAudioAttributes; 126 127 @Before 128 public void setUp() throws Exception { 129 MockitoAnnotations.initMocks(this); 130 UserHandle user = UserHandle.ALL; 131 132 final ApplicationInfo legacy = new ApplicationInfo(); 133 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 134 final ApplicationInfo upgrade = new ApplicationInfo(); 135 upgrade.targetSdkVersion = Build.VERSION_CODES.O; 136 when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy); 137 when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(upgrade); 138 when(mPm.getPackageUidAsUser(eq(PKG), anyInt())).thenReturn(UID); 139 when(mPm.getPackageUidAsUser(eq(UPDATED_PKG), anyInt())).thenReturn(UID2); 140 when(mContext.getResources()).thenReturn( 141 InstrumentationRegistry.getContext().getResources()); 142 when(mContext.getContentResolver()).thenReturn( 143 InstrumentationRegistry.getContext().getContentResolver()); 144 when(mContext.getPackageManager()).thenReturn(mPm); 145 when(mContext.getApplicationInfo()).thenReturn(legacy); 146 // most tests assume badging is enabled 147 TestableContentResolver contentResolver = getContext().getContentResolver(); 148 contentResolver.setFallbackToExisting(false); 149 Secure.putIntForUser(contentResolver, 150 Secure.NOTIFICATION_BADGING, 1, UserHandle.getUserId(UID)); 151 152 ContentProvider testContentProvider = mock(ContentProvider.class); 153 when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider); 154 contentResolver.addProvider(TEST_AUTHORITY, testContentProvider); 155 156 when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI))) 157 .thenReturn(CANONICAL_SOUND_URI); 158 when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI))) 159 .thenReturn(CANONICAL_SOUND_URI); 160 when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI))) 161 .thenReturn(SOUND_URI); 162 163 mHelper = new RankingHelper(getContext(), mPm, mHandler, mUsageStats, 164 new String[] {ImportanceExtractor.class.getName()}); 165 166 mNotiGroupGSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID) 167 .setContentTitle("A") 168 .setGroup("G") 169 .setSortKey("A") 170 .setWhen(1205) 171 .build(); 172 mRecordGroupGSortA = new NotificationRecord(mContext, new StatusBarNotification( 173 PKG, PKG, 1, null, 0, 0, mNotiGroupGSortA, user, 174 null, System.currentTimeMillis()), getDefaultChannel()); 175 176 mNotiGroupGSortB = new Notification.Builder(mContext, TEST_CHANNEL_ID) 177 .setContentTitle("B") 178 .setGroup("G") 179 .setSortKey("B") 180 .setWhen(1200) 181 .build(); 182 mRecordGroupGSortB = new NotificationRecord(mContext, new StatusBarNotification( 183 PKG, PKG, 1, null, 0, 0, mNotiGroupGSortB, user, 184 null, System.currentTimeMillis()), getDefaultChannel()); 185 186 mNotiNoGroup = new Notification.Builder(mContext, TEST_CHANNEL_ID) 187 .setContentTitle("C") 188 .setWhen(1201) 189 .build(); 190 mRecordNoGroup = new NotificationRecord(mContext, new StatusBarNotification( 191 PKG, PKG, 1, null, 0, 0, mNotiNoGroup, user, 192 null, System.currentTimeMillis()), getDefaultChannel()); 193 194 mNotiNoGroup2 = new Notification.Builder(mContext, TEST_CHANNEL_ID) 195 .setContentTitle("D") 196 .setWhen(1202) 197 .build(); 198 mRecordNoGroup2 = new NotificationRecord(mContext, new StatusBarNotification( 199 PKG, PKG, 1, null, 0, 0, mNotiNoGroup2, user, 200 null, System.currentTimeMillis()), getDefaultChannel()); 201 202 mNotiNoGroupSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID) 203 .setContentTitle("E") 204 .setWhen(1201) 205 .setSortKey("A") 206 .build(); 207 mRecordNoGroupSortA = new NotificationRecord(mContext, new StatusBarNotification( 208 PKG, PKG, 1, null, 0, 0, mNotiNoGroupSortA, user, 209 null, System.currentTimeMillis()), getDefaultChannel()); 210 211 mAudioAttributes = new AudioAttributes.Builder() 212 .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) 213 .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) 214 .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED) 215 .build(); 216 } 217 218 private NotificationChannel getDefaultChannel() { 219 return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name", 220 IMPORTANCE_LOW); 221 } 222 223 private ByteArrayOutputStream writeXmlAndPurge(String pkg, int uid, boolean forBackup, 224 String... channelIds) 225 throws Exception { 226 XmlSerializer serializer = new FastXmlSerializer(); 227 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 228 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 229 serializer.startDocument(null, true); 230 mHelper.writeXml(serializer, forBackup); 231 serializer.endDocument(); 232 serializer.flush(); 233 for (String channelId : channelIds) { 234 mHelper.permanentlyDeleteNotificationChannel(pkg, uid, channelId); 235 } 236 return baos; 237 } 238 239 private void loadStreamXml(ByteArrayOutputStream stream, boolean forRestore) throws Exception { 240 loadByteArrayXml(stream.toByteArray(), forRestore); 241 } 242 243 private void loadByteArrayXml(byte[] byteArray, boolean forRestore) throws Exception { 244 XmlPullParser parser = Xml.newPullParser(); 245 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(byteArray)), null); 246 parser.nextTag(); 247 mHelper.readXml(parser, forRestore); 248 } 249 250 private void compareChannels(NotificationChannel expected, NotificationChannel actual) { 251 assertEquals(expected.getId(), actual.getId()); 252 assertEquals(expected.getName(), actual.getName()); 253 assertEquals(expected.getDescription(), actual.getDescription()); 254 assertEquals(expected.shouldVibrate(), actual.shouldVibrate()); 255 assertEquals(expected.shouldShowLights(), actual.shouldShowLights()); 256 assertEquals(expected.getImportance(), actual.getImportance()); 257 assertEquals(expected.getLockscreenVisibility(), actual.getLockscreenVisibility()); 258 assertEquals(expected.getSound(), actual.getSound()); 259 assertEquals(expected.canBypassDnd(), actual.canBypassDnd()); 260 assertTrue(Arrays.equals(expected.getVibrationPattern(), actual.getVibrationPattern())); 261 assertEquals(expected.getGroup(), actual.getGroup()); 262 assertEquals(expected.getAudioAttributes(), actual.getAudioAttributes()); 263 assertEquals(expected.getLightColor(), actual.getLightColor()); 264 } 265 266 private void compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual) { 267 assertEquals(expected.getId(), actual.getId()); 268 assertEquals(expected.getName(), actual.getName()); 269 } 270 271 private NotificationChannel getChannel() { 272 return new NotificationChannel("id", "name", IMPORTANCE_LOW); 273 } 274 275 @Test 276 public void testFindAfterRankingWithASplitGroup() throws Exception { 277 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(3); 278 notificationList.add(mRecordGroupGSortA); 279 notificationList.add(mRecordGroupGSortB); 280 notificationList.add(mRecordNoGroup); 281 notificationList.add(mRecordNoGroupSortA); 282 mHelper.sort(notificationList); 283 assertTrue(mHelper.indexOf(notificationList, mRecordGroupGSortA) >= 0); 284 assertTrue(mHelper.indexOf(notificationList, mRecordGroupGSortB) >= 0); 285 assertTrue(mHelper.indexOf(notificationList, mRecordNoGroup) >= 0); 286 assertTrue(mHelper.indexOf(notificationList, mRecordNoGroupSortA) >= 0); 287 } 288 289 @Test 290 public void testSortShouldNotThrowWithPlainNotifications() throws Exception { 291 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(2); 292 notificationList.add(mRecordNoGroup); 293 notificationList.add(mRecordNoGroup2); 294 mHelper.sort(notificationList); 295 } 296 297 @Test 298 public void testSortShouldNotThrowOneSorted() throws Exception { 299 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(2); 300 notificationList.add(mRecordNoGroup); 301 notificationList.add(mRecordNoGroupSortA); 302 mHelper.sort(notificationList); 303 } 304 305 @Test 306 public void testSortShouldNotThrowOneNotification() throws Exception { 307 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(1); 308 notificationList.add(mRecordNoGroup); 309 mHelper.sort(notificationList); 310 } 311 312 @Test 313 public void testSortShouldNotThrowOneSortKey() throws Exception { 314 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(1); 315 notificationList.add(mRecordGroupGSortB); 316 mHelper.sort(notificationList); 317 } 318 319 @Test 320 public void testSortShouldNotThrowOnEmptyList() throws Exception { 321 ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(); 322 mHelper.sort(notificationList); 323 } 324 325 @Test 326 public void testChannelXml() throws Exception { 327 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 328 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 329 NotificationChannel channel1 = 330 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 331 NotificationChannel channel2 = 332 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 333 channel2.setDescription("descriptions for all"); 334 channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 335 channel2.enableLights(true); 336 channel2.setBypassDnd(true); 337 channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 338 channel2.enableVibration(true); 339 channel2.setGroup(ncg.getId()); 340 channel2.setVibrationPattern(new long[]{100, 67, 145, 156}); 341 channel2.setLightColor(Color.BLUE); 342 343 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 344 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 345 mHelper.createNotificationChannel(PKG, UID, channel1, true); 346 mHelper.createNotificationChannel(PKG, UID, channel2, false); 347 348 mHelper.setShowBadge(PKG, UID, true); 349 350 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(), 351 channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); 352 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID}); 353 354 loadStreamXml(baos, false); 355 356 assertTrue(mHelper.canShowBadge(PKG, UID)); 357 assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false)); 358 compareChannels(channel2, 359 mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); 360 361 List<NotificationChannelGroup> actualGroups = 362 mHelper.getNotificationChannelGroups(PKG, UID, false).getList(); 363 boolean foundNcg = false; 364 for (NotificationChannelGroup actual : actualGroups) { 365 if (ncg.getId().equals(actual.getId())) { 366 foundNcg = true; 367 compareGroups(ncg, actual); 368 } else if (ncg2.getId().equals(actual.getId())) { 369 compareGroups(ncg2, actual); 370 } 371 } 372 assertTrue(foundNcg); 373 374 boolean foundChannel2Group = false; 375 for (NotificationChannelGroup actual : actualGroups) { 376 if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) { 377 foundChannel2Group = true; 378 break; 379 } 380 } 381 assertTrue(foundChannel2Group); 382 } 383 384 @Test 385 public void testChannelXmlForBackup() throws Exception { 386 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 387 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 388 NotificationChannel channel1 = 389 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 390 NotificationChannel channel2 = 391 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 392 channel2.setDescription("descriptions for all"); 393 channel2.setSound(SOUND_URI, mAudioAttributes); 394 channel2.enableLights(true); 395 channel2.setBypassDnd(true); 396 channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 397 channel2.enableVibration(false); 398 channel2.setGroup(ncg.getId()); 399 channel2.setLightColor(Color.BLUE); 400 NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH); 401 channel3.enableVibration(true); 402 403 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 404 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 405 mHelper.createNotificationChannel(PKG, UID, channel1, true); 406 mHelper.createNotificationChannel(PKG, UID, channel2, false); 407 mHelper.createNotificationChannel(PKG, UID, channel3, false); 408 mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true); 409 410 mHelper.setShowBadge(PKG, UID, true); 411 412 mHelper.setImportance(UPDATED_PKG, UID2, IMPORTANCE_NONE); 413 414 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(), 415 channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); 416 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG, UPDATED_PKG}, 417 new int[]{UID, UID2}); 418 419 mHelper.setShowBadge(UPDATED_PKG, UID2, true); 420 421 loadStreamXml(baos, true); 422 423 assertEquals(IMPORTANCE_NONE, mHelper.getImportance(UPDATED_PKG, UID2)); 424 assertTrue(mHelper.canShowBadge(PKG, UID)); 425 assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false)); 426 compareChannels(channel2, 427 mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); 428 compareChannels(channel3, 429 mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false)); 430 431 List<NotificationChannelGroup> actualGroups = 432 mHelper.getNotificationChannelGroups(PKG, UID, false).getList(); 433 boolean foundNcg = false; 434 for (NotificationChannelGroup actual : actualGroups) { 435 if (ncg.getId().equals(actual.getId())) { 436 foundNcg = true; 437 compareGroups(ncg, actual); 438 } else if (ncg2.getId().equals(actual.getId())) { 439 compareGroups(ncg2, actual); 440 } 441 } 442 assertTrue(foundNcg); 443 444 boolean foundChannel2Group = false; 445 for (NotificationChannelGroup actual : actualGroups) { 446 if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) { 447 foundChannel2Group = true; 448 break; 449 } 450 } 451 assertTrue(foundChannel2Group); 452 } 453 454 @Test 455 public void testBackupXml_backupCanonicalizedSoundUri() throws Exception { 456 NotificationChannel channel = 457 new NotificationChannel("id", "name", IMPORTANCE_LOW); 458 channel.setSound(SOUND_URI, mAudioAttributes); 459 mHelper.createNotificationChannel(PKG, UID, channel, true); 460 461 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId()); 462 463 // Testing that in restore we are given the canonical version 464 loadStreamXml(baos, true); 465 verify(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI)); 466 } 467 468 @Test 469 public void testRestoreXml_withExistentCanonicalizedSoundUri() throws Exception { 470 Uri localUri = Uri.parse("content://" + TEST_AUTHORITY + "/local/url"); 471 Uri canonicalBasedOnLocal = localUri.buildUpon() 472 .appendQueryParameter("title", "Test") 473 .appendQueryParameter("canonical", "1") 474 .build(); 475 when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI))) 476 .thenReturn(canonicalBasedOnLocal); 477 when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI))) 478 .thenReturn(localUri); 479 when(mTestIContentProvider.uncanonicalize(any(), eq(canonicalBasedOnLocal))) 480 .thenReturn(localUri); 481 482 NotificationChannel channel = 483 new NotificationChannel("id", "name", IMPORTANCE_LOW); 484 channel.setSound(SOUND_URI, mAudioAttributes); 485 mHelper.createNotificationChannel(PKG, UID, channel, true); 486 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId()); 487 488 loadStreamXml(baos, true); 489 490 NotificationChannel actualChannel = mHelper.getNotificationChannel( 491 PKG, UID, channel.getId(), false); 492 assertEquals(localUri, actualChannel.getSound()); 493 } 494 495 @Test 496 public void testRestoreXml_withNonExistentCanonicalizedSoundUri() throws Exception { 497 Thread.sleep(3000); 498 when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI))) 499 .thenReturn(null); 500 when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI))) 501 .thenReturn(null); 502 503 NotificationChannel channel = 504 new NotificationChannel("id", "name", IMPORTANCE_LOW); 505 channel.setSound(SOUND_URI, mAudioAttributes); 506 mHelper.createNotificationChannel(PKG, UID, channel, true); 507 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId()); 508 509 loadStreamXml(baos, true); 510 511 NotificationChannel actualChannel = mHelper.getNotificationChannel( 512 PKG, UID, channel.getId(), false); 513 assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound()); 514 } 515 516 517 /** 518 * Although we don't make backups with uncanonicalized uris anymore, we used to, so we have to 519 * handle its restore properly. 520 */ 521 @Test 522 public void testRestoreXml_withUncanonicalizedNonLocalSoundUri() throws Exception { 523 // Not a local uncanonicalized uri, simulating that it fails to exist locally 524 when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI))).thenReturn(null); 525 String id = "id"; 526 String backupWithUncanonicalizedSoundUri = "<ranking version=\"1\">\n" 527 + "<package name=\"com.android.server.notification\" show_badge=\"true\">\n" 528 + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" " 529 + "sound=\"" + SOUND_URI + "\" " 530 + "usage=\"6\" content_type=\"0\" flags=\"1\" show_badge=\"true\" />\n" 531 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" usage=\"5\" " 532 + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" 533 + "</package>\n" 534 + "</ranking>\n"; 535 536 loadByteArrayXml(backupWithUncanonicalizedSoundUri.getBytes(), true); 537 538 NotificationChannel actualChannel = mHelper.getNotificationChannel(PKG, UID, id, false); 539 assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound()); 540 } 541 542 @Test 543 public void testBackupRestoreXml_withNullSoundUri() throws Exception { 544 NotificationChannel channel = 545 new NotificationChannel("id", "name", IMPORTANCE_LOW); 546 channel.setSound(null, mAudioAttributes); 547 mHelper.createNotificationChannel(PKG, UID, channel, true); 548 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId()); 549 550 loadStreamXml(baos, true); 551 552 NotificationChannel actualChannel = mHelper.getNotificationChannel( 553 PKG, UID, channel.getId(), false); 554 assertEquals(null, actualChannel.getSound()); 555 } 556 557 @Test 558 public void testChannelXml_backup() throws Exception { 559 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 560 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 561 NotificationChannel channel1 = 562 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 563 NotificationChannel channel2 = 564 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 565 NotificationChannel channel3 = 566 new NotificationChannel("id3", "name3", IMPORTANCE_LOW); 567 channel3.setGroup(ncg.getId()); 568 569 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 570 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 571 mHelper.createNotificationChannel(PKG, UID, channel1, true); 572 mHelper.createNotificationChannel(PKG, UID, channel2, false); 573 mHelper.createNotificationChannel(PKG, UID, channel3, true); 574 575 mHelper.deleteNotificationChannel(PKG, UID, channel1.getId()); 576 mHelper.deleteNotificationChannelGroup(PKG, UID, ncg.getId()); 577 assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); 578 579 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(), 580 channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); 581 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID}); 582 583 XmlPullParser parser = Xml.newPullParser(); 584 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), 585 null); 586 parser.nextTag(); 587 mHelper.readXml(parser, true); 588 589 assertNull(mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false)); 590 assertNull(mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false)); 591 assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG, UID)); 592 //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG, UID)); 593 assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); 594 } 595 596 @Test 597 public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception { 598 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, 599 NotificationChannel.DEFAULT_CHANNEL_ID); 600 601 loadStreamXml(baos, false); 602 603 final NotificationChannel updated = mHelper.getNotificationChannel(PKG, UID, 604 NotificationChannel.DEFAULT_CHANNEL_ID, false); 605 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance()); 606 assertFalse(updated.canBypassDnd()); 607 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, updated.getLockscreenVisibility()); 608 assertEquals(0, updated.getUserLockedFields()); 609 } 610 611 @Test 612 public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception { 613 final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID, 614 NotificationChannel.DEFAULT_CHANNEL_ID, false); 615 defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW); 616 mHelper.updateNotificationChannel(PKG, UID, defaultChannel, true); 617 618 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, 619 NotificationChannel.DEFAULT_CHANNEL_ID); 620 621 loadStreamXml(baos, false); 622 623 assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel( 624 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance()); 625 } 626 627 @Test 628 public void testChannelXml_upgradeCreateDefaultChannel() throws Exception { 629 final String preupgradeXml = "<ranking version=\"1\">\n" 630 + "<package name=\"" + PKG 631 + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH 632 + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\"" 633 + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + UID + "\" />\n" 634 + "<package name=\"" + UPDATED_PKG + "\" uid=\"" + UID2 + "\" visibility=\"" 635 + Notification.VISIBILITY_PRIVATE + "\" />\n" 636 + "</ranking>"; 637 XmlPullParser parser = Xml.newPullParser(); 638 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), 639 null); 640 parser.nextTag(); 641 mHelper.readXml(parser, false); 642 643 final NotificationChannel updated1 = 644 mHelper.getNotificationChannel(PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); 645 assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance()); 646 assertTrue(updated1.canBypassDnd()); 647 assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility()); 648 assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE 649 | NotificationChannel.USER_LOCKED_PRIORITY 650 | NotificationChannel.USER_LOCKED_VISIBILITY, 651 updated1.getUserLockedFields()); 652 653 // No Default Channel created for updated packages 654 assertEquals(null, mHelper.getNotificationChannel(UPDATED_PKG, UID2, 655 NotificationChannel.DEFAULT_CHANNEL_ID, false)); 656 } 657 658 @Test 659 public void testChannelXml_upgradeDeletesDefaultChannel() throws Exception { 660 final NotificationChannel defaultChannel = mHelper.getNotificationChannel( 661 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); 662 assertTrue(defaultChannel != null); 663 ByteArrayOutputStream baos = 664 writeXmlAndPurge(PKG, UID, false, NotificationChannel.DEFAULT_CHANNEL_ID); 665 // Load package at higher sdk. 666 final ApplicationInfo upgraded = new ApplicationInfo(); 667 upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 668 when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded); 669 loadStreamXml(baos, false); 670 671 // Default Channel should be gone. 672 assertEquals(null, mHelper.getNotificationChannel(PKG, UID, 673 NotificationChannel.DEFAULT_CHANNEL_ID, false)); 674 } 675 676 @Test 677 public void testDeletesDefaultChannelAfterChannelIsCreated() throws Exception { 678 mHelper.createNotificationChannel(PKG, UID, 679 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true); 680 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, 681 NotificationChannel.DEFAULT_CHANNEL_ID, "bananas"); 682 683 // Load package at higher sdk. 684 final ApplicationInfo upgraded = new ApplicationInfo(); 685 upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 686 when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded); 687 loadStreamXml(baos, false); 688 689 // Default Channel should be gone. 690 assertEquals(null, mHelper.getNotificationChannel(PKG, UID, 691 NotificationChannel.DEFAULT_CHANNEL_ID, false)); 692 } 693 694 @Test 695 public void testLoadingOldChannelsDoesNotDeleteNewlyCreatedChannels() throws Exception { 696 ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, 697 NotificationChannel.DEFAULT_CHANNEL_ID, "bananas"); 698 mHelper.createNotificationChannel(PKG, UID, 699 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true); 700 701 loadStreamXml(baos, false); 702 703 // Should still have the newly created channel that wasn't in the xml. 704 assertTrue(mHelper.getNotificationChannel(PKG, UID, "bananas", false) != null); 705 } 706 707 @Test 708 public void testCreateChannel_blocked() throws Exception { 709 mHelper.setImportance(PKG, UID, IMPORTANCE_NONE); 710 711 mHelper.createNotificationChannel(PKG, UID, 712 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true); 713 } 714 715 @Test 716 public void testCreateChannel_badImportance() throws Exception { 717 try { 718 mHelper.createNotificationChannel(PKG, UID, 719 new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE - 1), true); 720 fail("Was allowed to create a channel with invalid importance"); 721 } catch (IllegalArgumentException e) { 722 // yay 723 } 724 try { 725 mHelper.createNotificationChannel(PKG, UID, 726 new NotificationChannel("bananas", "bananas", IMPORTANCE_UNSPECIFIED), true); 727 fail("Was allowed to create a channel with invalid importance"); 728 } catch (IllegalArgumentException e) { 729 // yay 730 } 731 try { 732 mHelper.createNotificationChannel(PKG, UID, 733 new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX + 1), true); 734 fail("Was allowed to create a channel with invalid importance"); 735 } catch (IllegalArgumentException e) { 736 // yay 737 } 738 mHelper.createNotificationChannel(PKG, UID, 739 new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true); 740 mHelper.createNotificationChannel(PKG, UID, 741 new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true); 742 } 743 744 745 @Test 746 public void testUpdate() throws Exception { 747 // no fields locked by user 748 final NotificationChannel channel = 749 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 750 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 751 channel.enableLights(true); 752 channel.setBypassDnd(true); 753 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 754 755 mHelper.createNotificationChannel(PKG, UID, channel, false); 756 757 // same id, try to update all fields 758 final NotificationChannel channel2 = 759 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 760 channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes); 761 channel2.enableLights(false); 762 channel2.setBypassDnd(false); 763 channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); 764 765 mHelper.updateNotificationChannel(PKG, UID, channel2, true); 766 767 // all fields should be changed 768 assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); 769 770 verify(mHandler, times(1)).requestSort(); 771 } 772 773 @Test 774 public void testUpdate_preUpgrade_updatesAppFields() throws Exception { 775 mHelper.setImportance(PKG, UID, IMPORTANCE_UNSPECIFIED); 776 assertTrue(mHelper.canShowBadge(PKG, UID)); 777 assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID)); 778 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, 779 mHelper.getPackageVisibility(PKG, UID)); 780 781 NotificationChannel defaultChannel = mHelper.getNotificationChannel( 782 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); 783 784 defaultChannel.setShowBadge(false); 785 defaultChannel.setImportance(IMPORTANCE_NONE); 786 defaultChannel.setBypassDnd(true); 787 defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 788 789 mHelper.updateNotificationChannel(PKG, UID, defaultChannel, true); 790 791 // ensure app level fields are changed 792 assertFalse(mHelper.canShowBadge(PKG, UID)); 793 assertEquals(Notification.PRIORITY_MAX, mHelper.getPackagePriority(PKG, UID)); 794 assertEquals(Notification.VISIBILITY_SECRET, mHelper.getPackageVisibility(PKG, UID)); 795 assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG, UID)); 796 } 797 798 @Test 799 public void testUpdate_postUpgrade_noUpdateAppFields() throws Exception { 800 final NotificationChannel channel = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 801 802 mHelper.createNotificationChannel(PKG, UID, channel, false); 803 assertTrue(mHelper.canShowBadge(PKG, UID)); 804 assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID)); 805 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, 806 mHelper.getPackageVisibility(PKG, UID)); 807 808 channel.setShowBadge(false); 809 channel.setImportance(IMPORTANCE_NONE); 810 channel.setBypassDnd(true); 811 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 812 813 mHelper.updateNotificationChannel(PKG, UID, channel, true); 814 815 // ensure app level fields are not changed 816 assertTrue(mHelper.canShowBadge(PKG, UID)); 817 assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID)); 818 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, 819 mHelper.getPackageVisibility(PKG, UID)); 820 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); 821 } 822 823 @Test 824 public void testGetNotificationChannel_ReturnsNullForUnknownChannel() throws Exception { 825 assertEquals(null, mHelper.getNotificationChannel(PKG, UID, "garbage", false)); 826 } 827 828 @Test 829 public void testCreateChannel_CannotChangeHiddenFields() throws Exception { 830 final NotificationChannel channel = 831 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 832 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 833 channel.enableLights(true); 834 channel.setBypassDnd(true); 835 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 836 channel.setShowBadge(true); 837 int lockMask = 0; 838 for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { 839 lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; 840 } 841 channel.lockFields(lockMask); 842 843 mHelper.createNotificationChannel(PKG, UID, channel, true); 844 845 NotificationChannel savedChannel = 846 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 847 848 assertEquals(channel.getName(), savedChannel.getName()); 849 assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); 850 assertFalse(savedChannel.canBypassDnd()); 851 assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); 852 assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); 853 854 verify(mHandler, never()).requestSort(); 855 } 856 857 @Test 858 public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception { 859 final NotificationChannel channel = 860 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 861 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 862 channel.enableLights(true); 863 channel.setBypassDnd(true); 864 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 865 channel.setShowBadge(true); 866 int lockMask = 0; 867 for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { 868 lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; 869 } 870 channel.lockFields(lockMask); 871 872 mHelper.createNotificationChannel(PKG, UID, channel, true); 873 874 NotificationChannel savedChannel = 875 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 876 877 assertEquals(channel.getName(), savedChannel.getName()); 878 assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); 879 assertFalse(savedChannel.canBypassDnd()); 880 assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); 881 assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); 882 } 883 884 @Test 885 public void testClearLockedFields() throws Exception { 886 final NotificationChannel channel = getChannel(); 887 mHelper.clearLockedFields(channel); 888 assertEquals(0, channel.getUserLockedFields()); 889 890 channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY 891 | NotificationChannel.USER_LOCKED_IMPORTANCE); 892 mHelper.clearLockedFields(channel); 893 assertEquals(0, channel.getUserLockedFields()); 894 } 895 896 @Test 897 public void testLockFields_soundAndVibration() throws Exception { 898 mHelper.createNotificationChannel(PKG, UID, getChannel(), true); 899 900 final NotificationChannel update1 = getChannel(); 901 update1.setSound(new Uri.Builder().scheme("test").build(), 902 new AudioAttributes.Builder().build()); 903 update1.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); // should be ignored 904 mHelper.updateNotificationChannel(PKG, UID, update1, true); 905 assertEquals(NotificationChannel.USER_LOCKED_SOUND, 906 mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) 907 .getUserLockedFields()); 908 909 NotificationChannel update2 = getChannel(); 910 update2.enableVibration(true); 911 mHelper.updateNotificationChannel(PKG, UID, update2, true); 912 assertEquals(NotificationChannel.USER_LOCKED_SOUND 913 | NotificationChannel.USER_LOCKED_VIBRATION, 914 mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) 915 .getUserLockedFields()); 916 } 917 918 @Test 919 public void testLockFields_vibrationAndLights() throws Exception { 920 mHelper.createNotificationChannel(PKG, UID, getChannel(), true); 921 922 final NotificationChannel update1 = getChannel(); 923 update1.setVibrationPattern(new long[]{7945, 46 ,246}); 924 mHelper.updateNotificationChannel(PKG, UID, update1, true); 925 assertEquals(NotificationChannel.USER_LOCKED_VIBRATION, 926 mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) 927 .getUserLockedFields()); 928 929 final NotificationChannel update2 = getChannel(); 930 update2.enableLights(true); 931 mHelper.updateNotificationChannel(PKG, UID, update2, true); 932 assertEquals(NotificationChannel.USER_LOCKED_VIBRATION 933 | NotificationChannel.USER_LOCKED_LIGHTS, 934 mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) 935 .getUserLockedFields()); 936 } 937 938 @Test 939 public void testLockFields_lightsAndImportance() throws Exception { 940 mHelper.createNotificationChannel(PKG, UID, getChannel(), true); 941 942 final NotificationChannel update1 = getChannel(); 943 update1.setLightColor(Color.GREEN); 944 mHelper.updateNotificationChannel(PKG, UID, update1, true); 945 assertEquals(NotificationChannel.USER_LOCKED_LIGHTS, 946 mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) 947 .getUserLockedFields()); 948 949 final NotificationChannel update2 = getChannel(); 950 update2.setImportance(IMPORTANCE_DEFAULT); 951 mHelper.updateNotificationChannel(PKG, UID, update2, true); 952 assertEquals(NotificationChannel.USER_LOCKED_LIGHTS 953 | NotificationChannel.USER_LOCKED_IMPORTANCE, 954 mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) 955 .getUserLockedFields()); 956 } 957 958 @Test 959 public void testLockFields_visibilityAndDndAndBadge() throws Exception { 960 mHelper.createNotificationChannel(PKG, UID, getChannel(), true); 961 assertEquals(0, 962 mHelper.getNotificationChannel(PKG, UID, getChannel().getId(), false) 963 .getUserLockedFields()); 964 965 final NotificationChannel update1 = getChannel(); 966 update1.setBypassDnd(true); 967 mHelper.updateNotificationChannel(PKG, UID, update1, true); 968 assertEquals(NotificationChannel.USER_LOCKED_PRIORITY, 969 mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) 970 .getUserLockedFields()); 971 972 final NotificationChannel update2 = getChannel(); 973 update2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 974 mHelper.updateNotificationChannel(PKG, UID, update2, true); 975 assertEquals(NotificationChannel.USER_LOCKED_PRIORITY 976 | NotificationChannel.USER_LOCKED_VISIBILITY, 977 mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) 978 .getUserLockedFields()); 979 980 final NotificationChannel update3 = getChannel(); 981 update3.setShowBadge(false); 982 mHelper.updateNotificationChannel(PKG, UID, update3, true); 983 assertEquals(NotificationChannel.USER_LOCKED_PRIORITY 984 | NotificationChannel.USER_LOCKED_VISIBILITY 985 | NotificationChannel.USER_LOCKED_SHOW_BADGE, 986 mHelper.getNotificationChannel(PKG, UID, update3.getId(), false) 987 .getUserLockedFields()); 988 } 989 990 @Test 991 public void testDeleteNonExistentChannel() throws Exception { 992 mHelper.deleteNotificationChannelGroup(PKG, UID, "does not exist"); 993 } 994 995 @Test 996 public void testGetDeletedChannel() throws Exception { 997 NotificationChannel channel = getChannel(); 998 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 999 channel.enableLights(true); 1000 channel.setBypassDnd(true); 1001 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1002 channel.enableVibration(true); 1003 channel.setVibrationPattern(new long[]{100, 67, 145, 156}); 1004 1005 mHelper.createNotificationChannel(PKG, UID, channel, true); 1006 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 1007 1008 // Does not return deleted channel 1009 NotificationChannel response = 1010 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); 1011 assertNull(response); 1012 1013 // Returns deleted channel 1014 response = mHelper.getNotificationChannel(PKG, UID, channel.getId(), true); 1015 compareChannels(channel, response); 1016 assertTrue(response.isDeleted()); 1017 } 1018 1019 @Test 1020 public void testGetDeletedChannels() throws Exception { 1021 Map<String, NotificationChannel> channelMap = new HashMap<>(); 1022 NotificationChannel channel = 1023 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1024 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 1025 channel.enableLights(true); 1026 channel.setBypassDnd(true); 1027 channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); 1028 channel.enableVibration(true); 1029 channel.setVibrationPattern(new long[]{100, 67, 145, 156}); 1030 channelMap.put(channel.getId(), channel); 1031 NotificationChannel channel2 = 1032 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 1033 channelMap.put(channel2.getId(), channel2); 1034 mHelper.createNotificationChannel(PKG, UID, channel, true); 1035 mHelper.createNotificationChannel(PKG, UID, channel2, true); 1036 1037 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 1038 1039 // Returns only non-deleted channels 1040 List<NotificationChannel> channels = 1041 mHelper.getNotificationChannels(PKG, UID, false).getList(); 1042 assertEquals(2, channels.size()); // Default channel + non-deleted channel 1043 for (NotificationChannel nc : channels) { 1044 if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { 1045 compareChannels(channel2, nc); 1046 } 1047 } 1048 1049 // Returns deleted channels too 1050 channels = mHelper.getNotificationChannels(PKG, UID, true).getList(); 1051 assertEquals(3, channels.size()); // Includes default channel 1052 for (NotificationChannel nc : channels) { 1053 if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { 1054 compareChannels(channelMap.get(nc.getId()), nc); 1055 } 1056 } 1057 } 1058 1059 @Test 1060 public void testGetDeletedChannelCount() throws Exception { 1061 NotificationChannel channel = 1062 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1063 NotificationChannel channel2 = 1064 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 1065 NotificationChannel channel3 = 1066 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 1067 mHelper.createNotificationChannel(PKG, UID, channel, true); 1068 mHelper.createNotificationChannel(PKG, UID, channel2, true); 1069 mHelper.createNotificationChannel(PKG, UID, channel3, true); 1070 1071 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 1072 mHelper.deleteNotificationChannel(PKG, UID, channel3.getId()); 1073 1074 assertEquals(2, mHelper.getDeletedChannelCount(PKG, UID)); 1075 assertEquals(0, mHelper.getDeletedChannelCount("pkg2", UID2)); 1076 } 1077 1078 @Test 1079 public void testCreateDeletedChannel() throws Exception { 1080 long[] vibration = new long[]{100, 67, 145, 156}; 1081 NotificationChannel channel = 1082 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1083 channel.setVibrationPattern(vibration); 1084 1085 mHelper.createNotificationChannel(PKG, UID, channel, true); 1086 mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); 1087 1088 NotificationChannel newChannel = new NotificationChannel( 1089 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); 1090 newChannel.setVibrationPattern(new long[]{100}); 1091 1092 mHelper.createNotificationChannel(PKG, UID, newChannel, true); 1093 1094 // No long deleted, using old settings 1095 compareChannels(channel, 1096 mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false)); 1097 } 1098 1099 @Test 1100 public void testOnlyHasDefaultChannel() throws Exception { 1101 assertTrue(mHelper.onlyHasDefaultChannel(PKG, UID)); 1102 assertFalse(mHelper.onlyHasDefaultChannel(UPDATED_PKG, UID2)); 1103 1104 mHelper.createNotificationChannel(PKG, UID, getChannel(), true); 1105 assertFalse(mHelper.onlyHasDefaultChannel(PKG, UID)); 1106 } 1107 1108 @Test 1109 public void testCreateChannel_defaultChannelId() throws Exception { 1110 try { 1111 mHelper.createNotificationChannel(PKG, UID, new NotificationChannel( 1112 NotificationChannel.DEFAULT_CHANNEL_ID, "ha", IMPORTANCE_HIGH), true); 1113 fail("Allowed to create default channel"); 1114 } catch (IllegalArgumentException e) { 1115 // pass 1116 } 1117 } 1118 1119 @Test 1120 public void testCreateChannel_alreadyExists() throws Exception { 1121 long[] vibration = new long[]{100, 67, 145, 156}; 1122 NotificationChannel channel = 1123 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1124 channel.setVibrationPattern(vibration); 1125 1126 mHelper.createNotificationChannel(PKG, UID, channel, true); 1127 1128 NotificationChannel newChannel = new NotificationChannel( 1129 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); 1130 newChannel.setVibrationPattern(new long[]{100}); 1131 1132 mHelper.createNotificationChannel(PKG, UID, newChannel, true); 1133 1134 // Old settings not overridden 1135 compareChannels(channel, 1136 mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false)); 1137 } 1138 1139 @Test 1140 public void testCreateChannel_noOverrideSound() throws Exception { 1141 Uri sound = new Uri.Builder().scheme("test").build(); 1142 final NotificationChannel channel = new NotificationChannel("id2", "name2", 1143 NotificationManager.IMPORTANCE_DEFAULT); 1144 channel.setSound(sound, mAudioAttributes); 1145 mHelper.createNotificationChannel(PKG, UID, channel, true); 1146 assertEquals(sound, mHelper.getNotificationChannel( 1147 PKG, UID, channel.getId(), false).getSound()); 1148 } 1149 1150 @Test 1151 public void testPermanentlyDeleteChannels() throws Exception { 1152 NotificationChannel channel1 = 1153 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1154 NotificationChannel channel2 = 1155 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1156 1157 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1158 mHelper.createNotificationChannel(PKG, UID, channel2, false); 1159 1160 mHelper.permanentlyDeleteNotificationChannels(PKG, UID); 1161 1162 // Only default channel remains 1163 assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size()); 1164 } 1165 1166 @Test 1167 public void testDeleteGroup() throws Exception { 1168 NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted"); 1169 NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted"); 1170 NotificationChannel nonGroupedNonDeletedChannel = 1171 new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH); 1172 NotificationChannel groupedButNotDeleted = 1173 new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT); 1174 groupedButNotDeleted.setGroup("not"); 1175 NotificationChannel groupedAndDeleted = 1176 new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT); 1177 groupedAndDeleted.setGroup("totally"); 1178 1179 mHelper.createNotificationChannelGroup(PKG, UID, notDeleted, true); 1180 mHelper.createNotificationChannelGroup(PKG, UID, deleted, true); 1181 mHelper.createNotificationChannel(PKG, UID, nonGroupedNonDeletedChannel, true); 1182 mHelper.createNotificationChannel(PKG, UID, groupedAndDeleted, true); 1183 mHelper.createNotificationChannel(PKG, UID, groupedButNotDeleted, true); 1184 1185 mHelper.deleteNotificationChannelGroup(PKG, UID, deleted.getId()); 1186 1187 assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG, UID)); 1188 assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG, UID)); 1189 1190 assertNull(mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), false)); 1191 compareChannels(groupedAndDeleted, 1192 mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), true)); 1193 1194 compareChannels(groupedButNotDeleted, 1195 mHelper.getNotificationChannel(PKG, UID, groupedButNotDeleted.getId(), false)); 1196 compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel( 1197 PKG, UID, nonGroupedNonDeletedChannel.getId(), false)); 1198 1199 // notDeleted 1200 assertEquals(1, mHelper.getNotificationChannelGroups(PKG, UID).size()); 1201 1202 verify(mHandler, never()).requestSort(); 1203 } 1204 1205 @Test 1206 public void testOnUserRemoved() throws Exception { 1207 int[] user0Uids = {98, 235, 16, 3782}; 1208 int[] user1Uids = new int[user0Uids.length]; 1209 for (int i = 0; i < user0Uids.length; i++) { 1210 user1Uids[i] = UserHandle.PER_USER_RANGE + user0Uids[i]; 1211 1212 final ApplicationInfo legacy = new ApplicationInfo(); 1213 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 1214 when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy); 1215 1216 // create records with the default channel for all user 0 and user 1 uids 1217 mHelper.getImportance(PKG, user0Uids[i]); 1218 mHelper.getImportance(PKG, user1Uids[i]); 1219 } 1220 1221 mHelper.onUserRemoved(1); 1222 1223 // user 0 records remain 1224 for (int i = 0; i < user0Uids.length; i++) { 1225 assertEquals(1, 1226 mHelper.getNotificationChannels(PKG, user0Uids[i], false).getList().size()); 1227 } 1228 // user 1 records are gone 1229 for (int i = 0; i < user1Uids.length; i++) { 1230 assertEquals(0, 1231 mHelper.getNotificationChannels(PKG, user1Uids[i], false).getList().size()); 1232 } 1233 } 1234 1235 @Test 1236 public void testOnPackageChanged_packageRemoval() throws Exception { 1237 // Deleted 1238 NotificationChannel channel1 = 1239 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1240 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1241 1242 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 1243 1244 assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size()); 1245 1246 // Not deleted 1247 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1248 1249 mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 1250 assertEquals(2, mHelper.getNotificationChannels(PKG, UID, false).getList().size()); 1251 } 1252 1253 @Test 1254 public void testOnPackageChanged_packageRemoval_importance() throws Exception { 1255 mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_HIGH); 1256 1257 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 1258 1259 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); 1260 } 1261 1262 @Test 1263 public void testOnPackageChanged_packageRemoval_groups() throws Exception { 1264 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1265 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1266 NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); 1267 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 1268 1269 mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); 1270 1271 assertEquals(0, mHelper.getNotificationChannelGroups(PKG, UID, true).getList().size()); 1272 } 1273 1274 @Test 1275 public void testOnPackageChange_downgradeTargetSdk() throws Exception { 1276 // create channel as api 26 1277 mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true); 1278 1279 // install new app version targeting 25 1280 final ApplicationInfo legacy = new ApplicationInfo(); 1281 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 1282 when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(legacy); 1283 mHelper.onPackagesChanged( 1284 false, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2}); 1285 1286 // make sure the default channel was readded 1287 //assertEquals(2, mHelper.getNotificationChannels(UPDATED_PKG, UID2, false).getList().size()); 1288 assertNotNull(mHelper.getNotificationChannel( 1289 UPDATED_PKG, UID2, NotificationChannel.DEFAULT_CHANNEL_ID, false)); 1290 } 1291 1292 @Test 1293 public void testRecordDefaults() throws Exception { 1294 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); 1295 assertEquals(true, mHelper.canShowBadge(PKG, UID)); 1296 assertEquals(1, mHelper.getNotificationChannels(PKG, UID, false).getList().size()); 1297 } 1298 1299 @Test 1300 public void testCreateGroup() throws Exception { 1301 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1302 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1303 assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG, UID).iterator().next()); 1304 verify(mHandler, never()).requestSort(); 1305 } 1306 1307 @Test 1308 public void testCannotCreateChannel_badGroup() throws Exception { 1309 NotificationChannel channel1 = 1310 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1311 channel1.setGroup("garbage"); 1312 try { 1313 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1314 fail("Created a channel with a bad group"); 1315 } catch (IllegalArgumentException e) { 1316 } 1317 } 1318 1319 @Test 1320 public void testCannotCreateChannel_goodGroup() throws Exception { 1321 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1322 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1323 NotificationChannel channel1 = 1324 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1325 channel1.setGroup(ncg.getId()); 1326 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1327 1328 assertEquals(ncg.getId(), 1329 mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false).getGroup()); 1330 } 1331 1332 @Test 1333 public void testGetChannelGroups() throws Exception { 1334 NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s"); 1335 mHelper.createNotificationChannelGroup(PKG, UID, unused, true); 1336 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1337 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1338 NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); 1339 mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); 1340 1341 NotificationChannel channel1 = 1342 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1343 channel1.setGroup(ncg.getId()); 1344 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1345 NotificationChannel channel1a = 1346 new NotificationChannel("id1a", "name1", NotificationManager.IMPORTANCE_HIGH); 1347 channel1a.setGroup(ncg.getId()); 1348 mHelper.createNotificationChannel(PKG, UID, channel1a, true); 1349 1350 NotificationChannel channel2 = 1351 new NotificationChannel("id2", "name1", NotificationManager.IMPORTANCE_HIGH); 1352 channel2.setGroup(ncg2.getId()); 1353 mHelper.createNotificationChannel(PKG, UID, channel2, true); 1354 1355 NotificationChannel channel3 = 1356 new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH); 1357 mHelper.createNotificationChannel(PKG, UID, channel3, true); 1358 1359 List<NotificationChannelGroup> actual = 1360 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 1361 assertEquals(3, actual.size()); 1362 for (NotificationChannelGroup group : actual) { 1363 if (group.getId() == null) { 1364 assertEquals(2, group.getChannels().size()); // misc channel too 1365 assertTrue(channel3.getId().equals(group.getChannels().get(0).getId()) 1366 || channel3.getId().equals(group.getChannels().get(1).getId())); 1367 } else if (group.getId().equals(ncg.getId())) { 1368 assertEquals(2, group.getChannels().size()); 1369 if (group.getChannels().get(0).getId().equals(channel1.getId())) { 1370 assertTrue(group.getChannels().get(1).getId().equals(channel1a.getId())); 1371 } else if (group.getChannels().get(0).getId().equals(channel1a.getId())) { 1372 assertTrue(group.getChannels().get(1).getId().equals(channel1.getId())); 1373 } else { 1374 fail("expected channel not found"); 1375 } 1376 } else if (group.getId().equals(ncg2.getId())) { 1377 assertEquals(1, group.getChannels().size()); 1378 assertEquals(channel2.getId(), group.getChannels().get(0).getId()); 1379 } 1380 } 1381 } 1382 1383 @Test 1384 public void testGetChannelGroups_noSideEffects() throws Exception { 1385 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 1386 mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); 1387 1388 NotificationChannel channel1 = 1389 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1390 channel1.setGroup(ncg.getId()); 1391 mHelper.createNotificationChannel(PKG, UID, channel1, true); 1392 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 1393 1394 channel1.setImportance(IMPORTANCE_LOW); 1395 mHelper.updateNotificationChannel(PKG, UID, channel1, true); 1396 1397 List<NotificationChannelGroup> actual = 1398 mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); 1399 1400 assertEquals(2, actual.size()); 1401 for (NotificationChannelGroup group : actual) { 1402 if (Objects.equals(group.getId(), ncg.getId())) { 1403 assertEquals(1, group.getChannels().size()); 1404 } 1405 } 1406 } 1407 1408 @Test 1409 public void testCreateChannel_updateName() throws Exception { 1410 NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); 1411 mHelper.createNotificationChannel(PKG, UID, nc, true); 1412 NotificationChannel actual = mHelper.getNotificationChannel(PKG, UID, "id", false); 1413 assertEquals("hello", actual.getName()); 1414 1415 nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH); 1416 mHelper.createNotificationChannel(PKG, UID, nc, true); 1417 1418 actual = mHelper.getNotificationChannel(PKG, UID, "id", false); 1419 assertEquals("goodbye", actual.getName()); 1420 assertEquals(IMPORTANCE_DEFAULT, actual.getImportance()); 1421 1422 verify(mHandler, times(1)).requestSort(); 1423 } 1424 1425 @Test 1426 public void testDumpChannelsJson() throws Exception { 1427 final ApplicationInfo upgrade = new ApplicationInfo(); 1428 upgrade.targetSdkVersion = Build.VERSION_CODES.O; 1429 try { 1430 when(mPm.getApplicationInfoAsUser( 1431 anyString(), anyInt(), anyInt())).thenReturn(upgrade); 1432 } catch (PackageManager.NameNotFoundException e) { 1433 } 1434 ArrayMap<String, Integer> expectedChannels = new ArrayMap<>(); 1435 int numPackages = ThreadLocalRandom.current().nextInt(1, 5); 1436 for (int i = 0; i < numPackages; i++) { 1437 String pkgName = "pkg" + i; 1438 int numChannels = ThreadLocalRandom.current().nextInt(1, 10); 1439 for (int j = 0; j < numChannels; j++) { 1440 mHelper.createNotificationChannel(pkgName, UID, 1441 new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true); 1442 } 1443 expectedChannels.put(pkgName, numChannels); 1444 } 1445 1446 // delete the first channel of the first package 1447 String pkg = expectedChannels.keyAt(0); 1448 mHelper.deleteNotificationChannel("pkg" + 0, UID, "0"); 1449 // dump should not include deleted channels 1450 int count = expectedChannels.get(pkg); 1451 expectedChannels.put(pkg, count - 1); 1452 1453 JSONArray actual = mHelper.dumpChannelsJson(new NotificationManagerService.DumpFilter()); 1454 assertEquals(numPackages, actual.length()); 1455 for (int i = 0; i < numPackages; i++) { 1456 JSONObject object = actual.getJSONObject(i); 1457 assertTrue(expectedChannels.containsKey(object.get("packageName"))); 1458 assertEquals(expectedChannels.get(object.get("packageName")).intValue(), 1459 object.getInt("channelCount")); 1460 } 1461 } 1462 1463 @Test 1464 public void testBadgingOverrideTrue() throws Exception { 1465 Secure.putIntForUser(getContext().getContentResolver(), 1466 Secure.NOTIFICATION_BADGING, 1, 1467 USER.getIdentifier()); 1468 mHelper.updateBadgingEnabled(); // would be called by settings observer 1469 assertTrue(mHelper.badgingEnabled(USER)); 1470 } 1471 1472 @Test 1473 public void testBadgingOverrideFalse() throws Exception { 1474 Secure.putIntForUser(getContext().getContentResolver(), 1475 Secure.NOTIFICATION_BADGING, 0, 1476 USER.getIdentifier()); 1477 mHelper.updateBadgingEnabled(); // would be called by settings observer 1478 assertFalse(mHelper.badgingEnabled(USER)); 1479 } 1480 1481 @Test 1482 public void testBadgingForUserAll() throws Exception { 1483 try { 1484 mHelper.badgingEnabled(UserHandle.ALL); 1485 } catch (Exception e) { 1486 fail("just don't throw"); 1487 } 1488 } 1489 1490 @Test 1491 public void testBadgingOverrideUserIsolation() throws Exception { 1492 Secure.putIntForUser(getContext().getContentResolver(), 1493 Secure.NOTIFICATION_BADGING, 0, 1494 USER.getIdentifier()); 1495 Secure.putIntForUser(getContext().getContentResolver(), 1496 Secure.NOTIFICATION_BADGING, 1, 1497 USER2.getIdentifier()); 1498 mHelper.updateBadgingEnabled(); // would be called by settings observer 1499 assertFalse(mHelper.badgingEnabled(USER)); 1500 assertTrue(mHelper.badgingEnabled(USER2)); 1501 } 1502 1503 @Test 1504 public void testOnLocaleChanged_updatesDefaultChannels() throws Exception { 1505 String newLabel = "bananas!"; 1506 final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID, 1507 NotificationChannel.DEFAULT_CHANNEL_ID, false); 1508 assertFalse(newLabel.equals(defaultChannel.getName())); 1509 1510 Resources res = mock(Resources.class); 1511 when(mContext.getResources()).thenReturn(res); 1512 when(res.getString(com.android.internal.R.string.default_notification_channel_label)) 1513 .thenReturn(newLabel); 1514 1515 mHelper.onLocaleChanged(mContext, USER.getIdentifier()); 1516 1517 assertEquals(newLabel, mHelper.getNotificationChannel(PKG, UID, 1518 NotificationChannel.DEFAULT_CHANNEL_ID, false).getName()); 1519 } 1520 } 1521