1 /* 2 * Copyright (C) 2016 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 17 package com.android.server.notification; 18 19 import static android.app.Notification.FLAG_FOREGROUND_SERVICE; 20 import static android.app.NotificationManager.EXTRA_BLOCKED_STATE; 21 import static android.app.NotificationManager.IMPORTANCE_HIGH; 22 import static android.app.NotificationManager.IMPORTANCE_LOW; 23 import static android.app.NotificationManager.IMPORTANCE_MAX; 24 import static android.app.NotificationManager.IMPORTANCE_NONE; 25 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; 26 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT; 27 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE; 28 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 29 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS; 30 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; 31 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; 32 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; 33 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; 34 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; 35 import static android.content.pm.PackageManager.FEATURE_WATCH; 36 import static android.content.pm.PackageManager.PERMISSION_DENIED; 37 import static android.os.Build.VERSION_CODES.O_MR1; 38 import static android.os.Build.VERSION_CODES.P; 39 40 import static junit.framework.Assert.assertEquals; 41 import static junit.framework.Assert.assertFalse; 42 import static junit.framework.Assert.assertNotNull; 43 import static junit.framework.Assert.assertNull; 44 import static junit.framework.Assert.assertTrue; 45 import static junit.framework.Assert.fail; 46 47 import static org.mockito.Matchers.anyBoolean; 48 import static org.mockito.Matchers.anyLong; 49 import static org.mockito.Matchers.anyString; 50 import static org.mockito.Matchers.eq; 51 import static org.mockito.Mockito.any; 52 import static org.mockito.Mockito.anyInt; 53 import static org.mockito.Mockito.atLeastOnce; 54 import static org.mockito.Mockito.doAnswer; 55 import static org.mockito.Mockito.mock; 56 import static org.mockito.Mockito.never; 57 import static org.mockito.Mockito.reset; 58 import static org.mockito.Mockito.spy; 59 import static org.mockito.Mockito.timeout; 60 import static org.mockito.Mockito.times; 61 import static org.mockito.Mockito.verify; 62 import static org.mockito.Mockito.when; 63 64 import android.app.ActivityManager; 65 import android.app.IActivityManager; 66 import android.app.INotificationManager; 67 import android.app.Notification; 68 import android.app.Notification.MessagingStyle.Message; 69 import android.app.NotificationChannel; 70 import android.app.NotificationChannelGroup; 71 import android.app.NotificationManager; 72 import android.app.admin.DeviceAdminInfo; 73 import android.app.admin.DevicePolicyManagerInternal; 74 import android.app.usage.UsageStatsManagerInternal; 75 import android.companion.ICompanionDeviceManager; 76 import android.content.ComponentName; 77 import android.content.ContentUris; 78 import android.content.Context; 79 import android.content.Intent; 80 import android.content.pm.ApplicationInfo; 81 import android.content.pm.IPackageManager; 82 import android.content.pm.PackageManager; 83 import android.content.pm.ParceledListSlice; 84 import android.content.res.Resources; 85 import android.graphics.Color; 86 import android.media.AudioAttributes; 87 import android.media.AudioManager; 88 import android.net.Uri; 89 import android.os.Binder; 90 import android.os.Build; 91 import android.os.Bundle; 92 import android.os.IBinder; 93 import android.os.Process; 94 import android.os.RemoteException; 95 import android.os.UserHandle; 96 import android.provider.MediaStore; 97 import android.provider.Settings.Secure; 98 import android.service.notification.Adjustment; 99 import android.service.notification.INotificationListener; 100 import android.service.notification.NotificationListenerService; 101 import android.service.notification.NotificationStats; 102 import android.service.notification.NotifyingApp; 103 import android.service.notification.StatusBarNotification; 104 import android.test.suitebuilder.annotation.SmallTest; 105 import android.testing.AndroidTestingRunner; 106 import android.testing.TestableContext; 107 import android.testing.TestableLooper; 108 import android.testing.TestableLooper.RunWithLooper; 109 import android.text.Html; 110 import android.util.ArrayMap; 111 import android.util.AtomicFile; 112 113 import com.android.internal.R; 114 import com.android.internal.statusbar.NotificationVisibility; 115 import com.android.server.UiServiceTestCase; 116 import com.android.server.lights.Light; 117 import com.android.server.lights.LightsManager; 118 import com.android.server.notification.NotificationManagerService.NotificationAssistants; 119 import com.android.server.notification.NotificationManagerService.NotificationListeners; 120 121 import org.junit.After; 122 import org.junit.Before; 123 import org.junit.Test; 124 import org.junit.runner.RunWith; 125 import org.mockito.ArgumentCaptor; 126 import org.mockito.Mock; 127 import org.mockito.MockitoAnnotations; 128 import org.mockito.stubbing.Answer; 129 130 import java.io.BufferedInputStream; 131 import java.io.ByteArrayInputStream; 132 import java.io.File; 133 import java.io.FileInputStream; 134 import java.io.FileOutputStream; 135 import java.util.ArrayList; 136 import java.util.Arrays; 137 import java.util.HashSet; 138 import java.util.List; 139 import java.util.Map; 140 import java.util.Set; 141 142 @SmallTest 143 @RunWith(AndroidTestingRunner.class) 144 @RunWithLooper 145 public class NotificationManagerServiceTest extends UiServiceTestCase { 146 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId"; 147 private final int mUid = Binder.getCallingUid(); 148 private TestableNotificationManagerService mService; 149 private INotificationManager mBinderService; 150 private NotificationManagerInternal mInternalService; 151 @Mock 152 private IPackageManager mPackageManager; 153 @Mock 154 private PackageManager mPackageManagerClient; 155 private TestableContext mContext = spy(getContext()); 156 private final String PKG = mContext.getPackageName(); 157 private TestableLooper mTestableLooper; 158 @Mock 159 private RankingHelper mRankingHelper; 160 AtomicFile mPolicyFile; 161 File mFile; 162 @Mock 163 private NotificationUsageStats mUsageStats; 164 @Mock 165 private UsageStatsManagerInternal mAppUsageStats; 166 @Mock 167 private AudioManager mAudioManager; 168 @Mock 169 ActivityManager mActivityManager; 170 NotificationManagerService.WorkerHandler mHandler; 171 @Mock 172 Resources mResources; 173 174 private NotificationChannel mTestNotificationChannel = new NotificationChannel( 175 TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT); 176 @Mock 177 private NotificationListeners mListeners; 178 @Mock private NotificationAssistants mAssistants; 179 @Mock private ConditionProviders mConditionProviders; 180 private ManagedServices.ManagedServiceInfo mListener; 181 @Mock private ICompanionDeviceManager mCompanionMgr; 182 @Mock SnoozeHelper mSnoozeHelper; 183 @Mock GroupHelper mGroupHelper; 184 @Mock 185 IBinder mPermOwner; 186 @Mock 187 IActivityManager mAm; 188 189 // Use a Testable subclass so we can simulate calls from the system without failing. 190 private static class TestableNotificationManagerService extends NotificationManagerService { 191 int countSystemChecks = 0; 192 193 public TestableNotificationManagerService(Context context) { 194 super(context); 195 } 196 197 @Override 198 protected boolean isCallingUidSystem() { 199 countSystemChecks++; 200 return true; 201 } 202 203 @Override 204 protected boolean isCallerSystemOrPhone() { 205 countSystemChecks++; 206 return true; 207 } 208 209 @Override 210 protected ICompanionDeviceManager getCompanionManager() { 211 return null; 212 } 213 214 @Override 215 protected void reportSeen(NotificationRecord r) { 216 return; 217 } 218 219 @Override 220 protected void reportUserInteraction(NotificationRecord r) { 221 return; 222 } 223 } 224 225 @Before 226 public void setUp() throws Exception { 227 MockitoAnnotations.initMocks(this); 228 229 // most tests assume badging is enabled 230 Secure.putIntForUser(getContext().getContentResolver(), 231 Secure.NOTIFICATION_BADGING, 1, 232 UserHandle.getUserHandleForUid(mUid).getIdentifier()); 233 234 mService = new TestableNotificationManagerService(mContext); 235 236 // Use this testable looper. 237 mTestableLooper = TestableLooper.get(this); 238 mHandler = mService.new WorkerHandler(mTestableLooper.getLooper()); 239 // MockPackageManager - default returns ApplicationInfo with matching calling UID 240 mContext.setMockPackageManager(mPackageManagerClient); 241 final ApplicationInfo applicationInfo = new ApplicationInfo(); 242 applicationInfo.uid = mUid; 243 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())) 244 .thenReturn(applicationInfo); 245 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 246 .thenReturn(applicationInfo); 247 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid); 248 final LightsManager mockLightsManager = mock(LightsManager.class); 249 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class)); 250 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); 251 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 252 when(mAm.newUriPermissionOwner(anyString())).thenReturn(mPermOwner); 253 254 // write to a test file; the system file isn't readable from tests 255 mFile = new File(mContext.getCacheDir(), "test.xml"); 256 mFile.createNewFile(); 257 final String preupgradeXml = "<notification-policy></notification-policy>"; 258 mPolicyFile = new AtomicFile(mFile); 259 FileOutputStream fos = mPolicyFile.startWrite(); 260 fos.write(preupgradeXml.getBytes()); 261 mPolicyFile.finishWrite(fos); 262 FileInputStream fStream = new FileInputStream(mFile); 263 264 // Setup managed services 265 mListener = mListeners.new ManagedServiceInfo( 266 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0); 267 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 268 ManagedServices.Config listenerConfig = new ManagedServices.Config(); 269 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS; 270 when(mListeners.getConfig()).thenReturn(listenerConfig); 271 ManagedServices.Config assistantConfig = new ManagedServices.Config(); 272 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS; 273 when(mAssistants.getConfig()).thenReturn(assistantConfig); 274 ManagedServices.Config dndConfig = new ManagedServices.Config(); 275 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS; 276 when(mConditionProviders.getConfig()).thenReturn(dndConfig); 277 278 try { 279 mService.init(mTestableLooper.getLooper(), 280 mPackageManager, mPackageManagerClient, mockLightsManager, 281 mListeners, mAssistants, mConditionProviders, 282 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, 283 mGroupHelper, mAm, mAppUsageStats, 284 mock(DevicePolicyManagerInternal.class)); 285 } catch (SecurityException e) { 286 if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { 287 throw e; 288 } 289 } 290 mService.setAudioManager(mAudioManager); 291 292 // Tests call directly into the Binder. 293 mBinderService = mService.getBinderService(); 294 mInternalService = mService.getInternalService(); 295 296 mBinderService.createNotificationChannels( 297 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 298 assertNotNull(mBinderService.getNotificationChannel(PKG, TEST_CHANNEL_ID)); 299 } 300 301 @After 302 public void tearDown() throws Exception { 303 mFile.delete(); 304 } 305 306 public void waitForIdle() { 307 mTestableLooper.processAllMessages(); 308 } 309 310 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) { 311 Notification.Builder nb = new Notification.Builder(mContext, "a") 312 .setContentTitle("foo") 313 .setSmallIcon(android.R.drawable.sym_def_app_icon); 314 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, "tag", uid, 0, 315 nb.build(), new UserHandle(userId), null, postTime); 316 return sbn; 317 } 318 319 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, 320 String groupKey, boolean isSummary) { 321 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 322 .setContentTitle("foo") 323 .setSmallIcon(android.R.drawable.sym_def_app_icon) 324 .setGroup(groupKey) 325 .setGroupSummary(isSummary); 326 327 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0, 328 nb.build(), new UserHandle(mUid), null, 0); 329 return new NotificationRecord(mContext, sbn, channel); 330 } 331 332 private NotificationRecord generateNotificationRecord(NotificationChannel channel) { 333 return generateNotificationRecord(channel, null); 334 } 335 336 private NotificationRecord generateNotificationRecord(NotificationChannel channel, 337 Notification.TvExtender extender) { 338 if (channel == null) { 339 channel = mTestNotificationChannel; 340 } 341 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 342 .setContentTitle("foo") 343 .setSmallIcon(android.R.drawable.sym_def_app_icon); 344 if (extender != null) { 345 nb.extend(extender); 346 } 347 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, 348 nb.build(), new UserHandle(mUid), null, 0); 349 return new NotificationRecord(mContext, sbn, channel); 350 } 351 352 private Map<String, Answer> getSignalExtractorSideEffects() { 353 Map<String, Answer> answers = new ArrayMap<>(); 354 355 answers.put("override group key", invocationOnMock -> { 356 ((NotificationRecord) invocationOnMock.getArguments()[0]) 357 .setOverrideGroupKey("bananas"); 358 return null; 359 }); 360 answers.put("override people", invocationOnMock -> { 361 ((NotificationRecord) invocationOnMock.getArguments()[0]) 362 .setPeopleOverride(new ArrayList<>()); 363 return null; 364 }); 365 answers.put("snooze criteria", invocationOnMock -> { 366 ((NotificationRecord) invocationOnMock.getArguments()[0]) 367 .setSnoozeCriteria(new ArrayList<>()); 368 return null; 369 }); 370 answers.put("notification channel", invocationOnMock -> { 371 ((NotificationRecord) invocationOnMock.getArguments()[0]) 372 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW)); 373 return null; 374 }); 375 answers.put("badging", invocationOnMock -> { 376 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0]; 377 r.setShowBadge(!r.canShowBadge()); 378 return null; 379 }); 380 answers.put("package visibility", invocationOnMock -> { 381 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride( 382 Notification.VISIBILITY_SECRET); 383 return null; 384 }); 385 386 return answers; 387 } 388 389 @Test 390 public void testCreateNotificationChannels_SingleChannel() throws Exception { 391 final NotificationChannel channel = 392 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT); 393 mBinderService.createNotificationChannels(PKG, 394 new ParceledListSlice(Arrays.asList(channel))); 395 final NotificationChannel createdChannel = 396 mBinderService.getNotificationChannel(PKG, "id"); 397 assertTrue(createdChannel != null); 398 } 399 400 @Test 401 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception { 402 try { 403 mBinderService.createNotificationChannels(PKG, 404 new ParceledListSlice(Arrays.asList((Object[])null))); 405 fail("Exception should be thrown immediately."); 406 } catch (NullPointerException e) { 407 // pass 408 } 409 } 410 411 @Test 412 public void testCreateNotificationChannels_TwoChannels() throws Exception { 413 final NotificationChannel channel1 = 414 new NotificationChannel("id1", "name", NotificationManager.IMPORTANCE_DEFAULT); 415 final NotificationChannel channel2 = 416 new NotificationChannel("id2", "name", NotificationManager.IMPORTANCE_DEFAULT); 417 mBinderService.createNotificationChannels(PKG, 418 new ParceledListSlice(Arrays.asList(channel1, channel2))); 419 assertTrue(mBinderService.getNotificationChannel(PKG, "id1") != null); 420 assertTrue(mBinderService.getNotificationChannel(PKG, "id2") != null); 421 } 422 423 @Test 424 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance() 425 throws Exception { 426 final NotificationChannel channel = 427 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT); 428 mBinderService.createNotificationChannels(PKG, 429 new ParceledListSlice(Arrays.asList(channel))); 430 431 // Recreating the channel doesn't throw, but ignores importance. 432 final NotificationChannel dupeChannel = 433 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 434 mBinderService.createNotificationChannels(PKG, 435 new ParceledListSlice(Arrays.asList(dupeChannel))); 436 final NotificationChannel createdChannel = 437 mBinderService.getNotificationChannel(PKG, "id"); 438 assertEquals(NotificationManager.IMPORTANCE_DEFAULT, createdChannel.getImportance()); 439 } 440 441 @Test 442 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance() 443 throws Exception { 444 final NotificationChannel channel = 445 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT); 446 mBinderService.createNotificationChannels(PKG, 447 new ParceledListSlice(Arrays.asList(channel))); 448 449 // Recreating with a lower importance is allowed to modify the channel. 450 final NotificationChannel dupeChannel = 451 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); 452 mBinderService.createNotificationChannels(PKG, 453 new ParceledListSlice(Arrays.asList(dupeChannel))); 454 final NotificationChannel createdChannel = 455 mBinderService.getNotificationChannel(PKG, "id"); 456 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance()); 457 } 458 459 @Test 460 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated() 461 throws Exception { 462 final NotificationChannel channel = 463 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT); 464 mBinderService.createNotificationChannels(PKG, 465 new ParceledListSlice(Arrays.asList(channel))); 466 467 // The user modifies importance directly, can no longer be changed by the app. 468 final NotificationChannel updatedChannel = 469 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 470 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel); 471 472 // Recreating with a lower importance leaves channel unchanged. 473 final NotificationChannel dupeChannel = 474 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); 475 mBinderService.createNotificationChannels(PKG, 476 new ParceledListSlice(Arrays.asList(dupeChannel))); 477 final NotificationChannel createdChannel = 478 mBinderService.getNotificationChannel(PKG, "id"); 479 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance()); 480 } 481 482 @Test 483 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond() 484 throws Exception { 485 final NotificationChannel channel1 = 486 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT); 487 final NotificationChannel channel2 = 488 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 489 mBinderService.createNotificationChannels(PKG, 490 new ParceledListSlice(Arrays.asList(channel1, channel2))); 491 final NotificationChannel createdChannel = 492 mBinderService.getNotificationChannel(PKG, "id"); 493 assertEquals(NotificationManager.IMPORTANCE_DEFAULT, createdChannel.getImportance()); 494 } 495 496 @Test 497 public void testBlockedNotifications_suspended() throws Exception { 498 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true); 499 500 NotificationChannel channel = new NotificationChannel("id", "name", 501 IMPORTANCE_HIGH); 502 NotificationRecord r = generateNotificationRecord(channel); 503 assertTrue(mService.isBlocked(r, mUsageStats)); 504 verify(mUsageStats, times(1)).registerSuspendedByAdmin(eq(r)); 505 } 506 507 @Test 508 public void testBlockedNotifications_blockedChannel() throws Exception { 509 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 510 511 NotificationChannel channel = new NotificationChannel("id", "name", 512 NotificationManager.IMPORTANCE_NONE); 513 NotificationRecord r = generateNotificationRecord(channel); 514 assertTrue(mService.isBlocked(r, mUsageStats)); 515 verify(mUsageStats, times(1)).registerBlocked(eq(r)); 516 517 mBinderService.createNotificationChannels( 518 PKG, new ParceledListSlice(Arrays.asList(channel))); 519 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn; 520 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 521 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 522 waitForIdle(); 523 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 524 } 525 526 @Test 527 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService() 528 throws Exception { 529 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 530 531 NotificationChannel channel = new NotificationChannel("blocked", "name", 532 NotificationManager.IMPORTANCE_NONE); 533 mBinderService.createNotificationChannels( 534 PKG, new ParceledListSlice(Arrays.asList(channel))); 535 536 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn; 537 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 538 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 539 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 540 waitForIdle(); 541 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 542 assertEquals(IMPORTANCE_LOW, 543 mService.getNotificationRecord(sbn.getKey()).getImportance()); 544 assertEquals(IMPORTANCE_LOW, 545 mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); 546 } 547 548 @Test 549 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService() 550 throws Exception { 551 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 552 553 NotificationChannel channel = 554 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH); 555 mBinderService.createNotificationChannels( 556 PKG, new ParceledListSlice(Arrays.asList(channel))); 557 558 NotificationChannel update = 559 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); 560 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); 561 waitForIdle(); 562 assertEquals(IMPORTANCE_NONE, 563 mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); 564 565 StatusBarNotification sbn = generateNotificationRecord(channel).sbn; 566 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 567 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 568 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 569 waitForIdle(); 570 // The first time a foreground service notification is shown, we allow the channel 571 // to be updated to allow it to be seen. 572 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 573 assertEquals(IMPORTANCE_LOW, 574 mService.getNotificationRecord(sbn.getKey()).getImportance()); 575 assertEquals(IMPORTANCE_LOW, 576 mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); 577 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId()); 578 waitForIdle(); 579 580 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); 581 update.setFgServiceShown(true); 582 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); 583 waitForIdle(); 584 assertEquals(IMPORTANCE_NONE, 585 mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); 586 587 sbn = generateNotificationRecord(channel).sbn; 588 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 589 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 590 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 591 waitForIdle(); 592 // The second time it is shown, we keep the user's preference. 593 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 594 assertNull(mService.getNotificationRecord(sbn.getKey())); 595 assertEquals(IMPORTANCE_NONE, 596 mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); 597 } 598 599 @Test 600 public void testBlockedNotifications_blockedChannelGroup() throws Exception { 601 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 602 mService.setRankingHelper(mRankingHelper); 603 when(mRankingHelper.isGroupBlocked(anyString(), anyInt(), anyString())).thenReturn(true); 604 605 NotificationChannel channel = new NotificationChannel("id", "name", 606 NotificationManager.IMPORTANCE_HIGH); 607 channel.setGroup("something"); 608 NotificationRecord r = generateNotificationRecord(channel); 609 assertTrue(mService.isBlocked(r, mUsageStats)); 610 verify(mUsageStats, times(1)).registerBlocked(eq(r)); 611 } 612 613 @Test 614 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception { 615 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 616 617 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); 618 619 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 620 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 621 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 622 waitForIdle(); 623 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 624 } 625 626 @Test 627 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception { 628 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 629 630 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); 631 632 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 633 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 634 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 635 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 636 waitForIdle(); 637 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 638 assertNull(mService.getNotificationRecord(sbn.getKey())); 639 } 640 641 @Test 642 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception { 643 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0, 644 generateNotificationRecord(null).getNotification(), 0); 645 waitForIdle(); 646 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 647 assertEquals(1, notifs.length); 648 assertEquals(1, mService.getNotificationRecordCount()); 649 } 650 651 @Test 652 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception { 653 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0, 654 generateNotificationRecord(null).getNotification(), 0); 655 mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0); 656 waitForIdle(); 657 StatusBarNotification[] notifs = 658 mBinderService.getActiveNotifications(PKG); 659 assertEquals(0, notifs.length); 660 assertEquals(0, mService.getNotificationRecordCount()); 661 } 662 663 @Test 664 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception { 665 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0, 666 generateNotificationRecord(null).getNotification(), 0); 667 waitForIdle(); 668 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0, 669 generateNotificationRecord(null).getNotification(), 0); 670 mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0); 671 waitForIdle(); 672 StatusBarNotification[] notifs = 673 mBinderService.getActiveNotifications(PKG); 674 assertEquals(0, notifs.length); 675 assertEquals(0, mService.getNotificationRecordCount()); 676 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 677 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture()); 678 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface()); 679 } 680 681 @Test 682 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception { 683 NotificationRecord r = generateNotificationRecord(null); 684 final StatusBarNotification sbn = r.sbn; 685 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 686 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 687 mBinderService.cancelNotificationsFromListener(null, null); 688 waitForIdle(); 689 StatusBarNotification[] notifs = 690 mBinderService.getActiveNotifications(sbn.getPackageName()); 691 assertEquals(0, notifs.length); 692 assertEquals(0, mService.getNotificationRecordCount()); 693 } 694 695 @Test 696 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception { 697 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 698 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 699 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 700 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 701 waitForIdle(); 702 StatusBarNotification[] notifs = 703 mBinderService.getActiveNotifications(sbn.getPackageName()); 704 assertEquals(0, notifs.length); 705 assertEquals(0, mService.getNotificationRecordCount()); 706 } 707 708 @Test 709 public void testUserInitiatedClearAll_noLeak() throws Exception { 710 final NotificationRecord n = generateNotificationRecord( 711 mTestNotificationChannel, 1, "group", true); 712 713 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 714 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId()); 715 waitForIdle(); 716 717 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 718 n.getUserId()); 719 waitForIdle(); 720 StatusBarNotification[] notifs = 721 mBinderService.getActiveNotifications(n.sbn.getPackageName()); 722 assertEquals(0, notifs.length); 723 assertEquals(0, mService.getNotificationRecordCount()); 724 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 725 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture()); 726 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface()); 727 } 728 729 @Test 730 public void testCancelAllNotificationsCancelsChildren() throws Exception { 731 final NotificationRecord parent = generateNotificationRecord( 732 mTestNotificationChannel, 1, "group1", true); 733 final NotificationRecord child = generateNotificationRecord( 734 mTestNotificationChannel, 2, "group1", false); 735 736 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 737 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId()); 738 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 739 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId()); 740 waitForIdle(); 741 742 mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId()); 743 waitForIdle(); 744 assertEquals(0, mService.getNotificationRecordCount()); 745 } 746 747 @Test 748 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception { 749 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 750 for (int i = 0; i < 10; i++) { 751 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 752 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 753 } 754 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 755 waitForIdle(); 756 757 assertEquals(0, mService.getNotificationRecordCount()); 758 } 759 760 @Test 761 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception { 762 final NotificationRecord parent = generateNotificationRecord( 763 mTestNotificationChannel, 1, "group1", true); 764 final NotificationRecord parentAsChild = generateNotificationRecord( 765 mTestNotificationChannel, 1, "group1", false); 766 final NotificationRecord child = generateNotificationRecord( 767 mTestNotificationChannel, 2, "group1", false); 768 769 // fully post parent notification 770 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 771 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId()); 772 waitForIdle(); 773 774 // enqueue the child several times 775 for (int i = 0; i < 10; i++) { 776 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 777 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId()); 778 } 779 // make the parent a child, which will cancel the child notification 780 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 781 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(), 782 parentAsChild.sbn.getUserId()); 783 waitForIdle(); 784 785 assertEquals(0, mService.getNotificationRecordCount()); 786 } 787 788 @Test 789 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception { 790 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 791 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 792 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 793 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 794 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 795 waitForIdle(); 796 StatusBarNotification[] notifs = 797 mBinderService.getActiveNotifications(sbn.getPackageName()); 798 assertEquals(1, notifs.length); 799 assertEquals(1, mService.getNotificationRecordCount()); 800 } 801 802 @Test 803 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception { 804 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 805 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 806 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 807 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 808 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId()); 809 waitForIdle(); 810 StatusBarNotification[] notifs = 811 mBinderService.getActiveNotifications(sbn.getPackageName()); 812 assertEquals(1, notifs.length); 813 assertEquals(1, mService.getNotificationRecordCount()); 814 } 815 816 @Test 817 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception { 818 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 819 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 820 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 821 mBinderService.cancelAllNotifications(null, sbn.getUserId()); 822 waitForIdle(); 823 StatusBarNotification[] notifs = 824 mBinderService.getActiveNotifications(sbn.getPackageName()); 825 assertEquals(0, notifs.length); 826 assertEquals(0, mService.getNotificationRecordCount()); 827 } 828 829 @Test 830 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception { 831 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 832 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 833 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL); 834 // Null pkg is how we signal a user switch. 835 mBinderService.cancelAllNotifications(null, sbn.getUserId()); 836 waitForIdle(); 837 StatusBarNotification[] notifs = 838 mBinderService.getActiveNotifications(sbn.getPackageName()); 839 assertEquals(1, notifs.length); 840 assertEquals(1, mService.getNotificationRecordCount()); 841 } 842 843 @Test 844 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception { 845 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 846 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR; 847 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 848 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 849 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 850 waitForIdle(); 851 StatusBarNotification[] notifs = 852 mBinderService.getActiveNotifications(sbn.getPackageName()); 853 assertEquals(0, notifs.length); 854 } 855 856 @Test 857 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception { 858 final NotificationRecord notif = generateNotificationRecord( 859 mTestNotificationChannel, 1, "group", true); 860 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 861 mService.addNotification(notif); 862 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true, 863 notif.getUserId(), 0, null); 864 waitForIdle(); 865 StatusBarNotification[] notifs = 866 mBinderService.getActiveNotifications(notif.sbn.getPackageName()); 867 assertEquals(0, notifs.length); 868 } 869 870 @Test 871 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception { 872 final NotificationRecord notif = generateNotificationRecord( 873 mTestNotificationChannel, 1, "group", true); 874 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 875 mService.addNotification(notif); 876 877 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 878 notif.getUserId()); 879 waitForIdle(); 880 StatusBarNotification[] notifs = 881 mBinderService.getActiveNotifications(notif.sbn.getPackageName()); 882 assertEquals(1, notifs.length); 883 } 884 885 @Test 886 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception { 887 final NotificationRecord parent = generateNotificationRecord( 888 mTestNotificationChannel, 1, "group", true); 889 final NotificationRecord child = generateNotificationRecord( 890 mTestNotificationChannel, 2, "group", false); 891 final NotificationRecord child2 = generateNotificationRecord( 892 mTestNotificationChannel, 3, "group", false); 893 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 894 final NotificationRecord newGroup = generateNotificationRecord( 895 mTestNotificationChannel, 4, "group2", false); 896 mService.addNotification(parent); 897 mService.addNotification(child); 898 mService.addNotification(child2); 899 mService.addNotification(newGroup); 900 mService.getBinderService().cancelNotificationsFromListener(null, null); 901 waitForIdle(); 902 StatusBarNotification[] notifs = 903 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 904 assertEquals(1, notifs.length); 905 } 906 907 @Test 908 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception { 909 final NotificationRecord parent = generateNotificationRecord( 910 mTestNotificationChannel, 1, "group", true); 911 final NotificationRecord child = generateNotificationRecord( 912 mTestNotificationChannel, 2, "group", false); 913 final NotificationRecord child2 = generateNotificationRecord( 914 mTestNotificationChannel, 3, "group", false); 915 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 916 final NotificationRecord newGroup = generateNotificationRecord( 917 mTestNotificationChannel, 4, "group2", false); 918 mService.addNotification(parent); 919 mService.addNotification(child); 920 mService.addNotification(child2); 921 mService.addNotification(newGroup); 922 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 923 parent.getUserId()); 924 waitForIdle(); 925 StatusBarNotification[] notifs = 926 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 927 assertEquals(1, notifs.length); 928 } 929 930 @Test 931 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception { 932 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 933 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 934 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, 935 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 936 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(), 937 sbn.getUserId()); 938 waitForIdle(); 939 StatusBarNotification[] notifs = 940 mBinderService.getActiveNotifications(sbn.getPackageName()); 941 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE); 942 } 943 944 @Test 945 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception { 946 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 947 sbn.getNotification().flags = 948 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; 949 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 950 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 951 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT; 952 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 953 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 954 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId()); 955 waitForIdle(); 956 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 957 assertEquals(0, mService.getNotificationRecordCount()); 958 } 959 960 @Test 961 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag() 962 throws Exception { 963 final NotificationRecord parent = generateNotificationRecord( 964 mTestNotificationChannel, 1, "group", true); 965 final NotificationRecord child = generateNotificationRecord( 966 mTestNotificationChannel, 2, "group", false); 967 final NotificationRecord child2 = generateNotificationRecord( 968 mTestNotificationChannel, 3, "group", false); 969 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 970 final NotificationRecord newGroup = generateNotificationRecord( 971 mTestNotificationChannel, 4, "group2", false); 972 mService.addNotification(parent); 973 mService.addNotification(child); 974 mService.addNotification(child2); 975 mService.addNotification(newGroup); 976 mService.getBinderService().cancelNotificationsFromListener(null, null); 977 waitForIdle(); 978 StatusBarNotification[] notifs = 979 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 980 assertEquals(0, notifs.length); 981 } 982 983 @Test 984 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter() 985 throws Exception { 986 final NotificationRecord parent = generateNotificationRecord( 987 mTestNotificationChannel, 1, "group", true); 988 final NotificationRecord child = generateNotificationRecord( 989 mTestNotificationChannel, 2, "group", false); 990 final NotificationRecord child2 = generateNotificationRecord( 991 mTestNotificationChannel, 3, "group", false); 992 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 993 final NotificationRecord newGroup = generateNotificationRecord( 994 mTestNotificationChannel, 4, "group2", false); 995 mService.addNotification(parent); 996 mService.addNotification(child); 997 mService.addNotification(child2); 998 mService.addNotification(newGroup); 999 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(), 1000 child2.sbn.getKey(), newGroup.sbn.getKey()}; 1001 mService.getBinderService().cancelNotificationsFromListener(null, keys); 1002 waitForIdle(); 1003 StatusBarNotification[] notifs = 1004 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1005 assertEquals(1, notifs.length); 1006 } 1007 1008 @Test 1009 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception { 1010 final NotificationRecord parent = generateNotificationRecord( 1011 mTestNotificationChannel, 1, "group", true); 1012 final NotificationRecord child = generateNotificationRecord( 1013 mTestNotificationChannel, 2, "group", false); 1014 final NotificationRecord child2 = generateNotificationRecord( 1015 mTestNotificationChannel, 3, "group", false); 1016 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1017 final NotificationRecord newGroup = generateNotificationRecord( 1018 mTestNotificationChannel, 4, "group2", false); 1019 mService.addNotification(parent); 1020 mService.addNotification(child); 1021 mService.addNotification(child2); 1022 mService.addNotification(newGroup); 1023 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1024 parent.getUserId()); 1025 waitForIdle(); 1026 StatusBarNotification[] notifs = 1027 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1028 assertEquals(0, notifs.length); 1029 } 1030 1031 @Test 1032 public void testFindGroupNotificationsLocked() throws Exception { 1033 // make sure the same notification can be found in both lists and returned 1034 final NotificationRecord group1 = generateNotificationRecord( 1035 mTestNotificationChannel, 1, "group1", true); 1036 mService.addEnqueuedNotification(group1); 1037 mService.addNotification(group1); 1038 1039 // should not be returned 1040 final NotificationRecord group2 = generateNotificationRecord( 1041 mTestNotificationChannel, 2, "group2", true); 1042 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, 1043 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId()); 1044 waitForIdle(); 1045 1046 // should not be returned 1047 final NotificationRecord nonGroup = generateNotificationRecord( 1048 mTestNotificationChannel, 3, null, false); 1049 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, 1050 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId()); 1051 waitForIdle(); 1052 1053 // same group, child, should be returned 1054 final NotificationRecord group1Child = generateNotificationRecord( 1055 mTestNotificationChannel, 4, "group1", false); 1056 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, group1Child.sbn.getId(), 1057 group1Child.sbn.getNotification(), group1Child.sbn.getUserId()); 1058 waitForIdle(); 1059 1060 List<NotificationRecord> inGroup1 = 1061 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(), 1062 group1.sbn.getUserId()); 1063 assertEquals(3, inGroup1.size()); 1064 for (NotificationRecord record : inGroup1) { 1065 assertTrue(record.getGroupKey().equals(group1.getGroupKey())); 1066 assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4); 1067 } 1068 } 1069 1070 @Test 1071 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception { 1072 final NotificationRecord notif = generateNotificationRecord( 1073 mTestNotificationChannel, 1, "group", true); 1074 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1075 mService.addNotification(notif); 1076 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 1077 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null); 1078 waitForIdle(); 1079 StatusBarNotification[] notifs = 1080 mBinderService.getActiveNotifications(notif.sbn.getPackageName()); 1081 assertEquals(0, notifs.length); 1082 } 1083 1084 @Test 1085 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter() 1086 throws Exception { 1087 final NotificationRecord parent = generateNotificationRecord( 1088 mTestNotificationChannel, 1, "group", true); 1089 final NotificationRecord child = generateNotificationRecord( 1090 mTestNotificationChannel, 2, "group", false); 1091 final NotificationRecord child2 = generateNotificationRecord( 1092 mTestNotificationChannel, 3, "group", false); 1093 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1094 final NotificationRecord newGroup = generateNotificationRecord( 1095 mTestNotificationChannel, 4, "group2", false); 1096 mService.addNotification(parent); 1097 mService.addNotification(child); 1098 mService.addNotification(child2); 1099 mService.addNotification(newGroup); 1100 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(), 1101 child2.sbn.getKey(), newGroup.sbn.getKey()}; 1102 mService.getBinderService().cancelNotificationsFromListener(null, keys); 1103 waitForIdle(); 1104 StatusBarNotification[] notifs = 1105 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1106 assertEquals(0, notifs.length); 1107 } 1108 1109 @Test 1110 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception { 1111 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1112 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1113 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 1114 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1115 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 1116 waitForIdle(); 1117 StatusBarNotification[] notifs = 1118 mBinderService.getActiveNotifications(sbn.getPackageName()); 1119 assertEquals(0, notifs.length); 1120 } 1121 1122 @Test 1123 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception { 1124 final NotificationRecord notif = generateNotificationRecord( 1125 mTestNotificationChannel, 1, "group", true); 1126 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1127 mService.addNotification(notif); 1128 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true, 1129 notif.getUserId(), 0, null); 1130 waitForIdle(); 1131 StatusBarNotification[] notifs = 1132 mBinderService.getActiveNotifications(notif.sbn.getPackageName()); 1133 assertEquals(0, notifs.length); 1134 } 1135 1136 @Test 1137 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception { 1138 final NotificationRecord notif = generateNotificationRecord( 1139 mTestNotificationChannel, 1, "group", true); 1140 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1141 mService.addNotification(notif); 1142 1143 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1144 notif.getUserId()); 1145 waitForIdle(); 1146 StatusBarNotification[] notifs = 1147 mBinderService.getActiveNotifications(notif.sbn.getPackageName()); 1148 assertEquals(1, notifs.length); 1149 } 1150 1151 @Test 1152 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception { 1153 final NotificationRecord parent = generateNotificationRecord( 1154 mTestNotificationChannel, 1, "group", true); 1155 final NotificationRecord child = generateNotificationRecord( 1156 mTestNotificationChannel, 2, "group", false); 1157 final NotificationRecord child2 = generateNotificationRecord( 1158 mTestNotificationChannel, 3, "group", false); 1159 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1160 final NotificationRecord newGroup = generateNotificationRecord( 1161 mTestNotificationChannel, 4, "group2", false); 1162 mService.addNotification(parent); 1163 mService.addNotification(child); 1164 mService.addNotification(child2); 1165 mService.addNotification(newGroup); 1166 mService.getBinderService().cancelNotificationsFromListener(null, null); 1167 waitForIdle(); 1168 StatusBarNotification[] notifs = 1169 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1170 assertEquals(1, notifs.length); 1171 } 1172 1173 @Test 1174 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter() 1175 throws Exception { 1176 final NotificationRecord parent = generateNotificationRecord( 1177 mTestNotificationChannel, 1, "group", true); 1178 final NotificationRecord child = generateNotificationRecord( 1179 mTestNotificationChannel, 2, "group", false); 1180 final NotificationRecord child2 = generateNotificationRecord( 1181 mTestNotificationChannel, 3, "group", false); 1182 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1183 final NotificationRecord newGroup = generateNotificationRecord( 1184 mTestNotificationChannel, 4, "group2", false); 1185 mService.addNotification(parent); 1186 mService.addNotification(child); 1187 mService.addNotification(child2); 1188 mService.addNotification(newGroup); 1189 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(), 1190 child2.sbn.getKey(), newGroup.sbn.getKey()}; 1191 mService.getBinderService().cancelNotificationsFromListener(null, keys); 1192 waitForIdle(); 1193 StatusBarNotification[] notifs = 1194 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1195 assertEquals(0, notifs.length); 1196 } 1197 1198 @Test 1199 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception { 1200 final NotificationRecord parent = generateNotificationRecord( 1201 mTestNotificationChannel, 1, "group", true); 1202 final NotificationRecord child = generateNotificationRecord( 1203 mTestNotificationChannel, 2, "group", false); 1204 final NotificationRecord child2 = generateNotificationRecord( 1205 mTestNotificationChannel, 3, "group", false); 1206 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1207 final NotificationRecord newGroup = generateNotificationRecord( 1208 mTestNotificationChannel, 4, "group2", false); 1209 mService.addNotification(parent); 1210 mService.addNotification(child); 1211 mService.addNotification(child2); 1212 mService.addNotification(newGroup); 1213 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1214 parent.getUserId()); 1215 waitForIdle(); 1216 StatusBarNotification[] notifs = 1217 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1218 assertEquals(1, notifs.length); 1219 } 1220 1221 @Test 1222 public void testTvExtenderChannelOverride_onTv() throws Exception { 1223 mService.setIsTelevision(true); 1224 mService.setRankingHelper(mRankingHelper); 1225 when(mRankingHelper.getNotificationChannel( 1226 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn( 1227 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH)); 1228 1229 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); 1230 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0, 1231 generateNotificationRecord(null, tv).getNotification(), 0); 1232 verify(mRankingHelper, times(1)).getNotificationChannel( 1233 anyString(), anyInt(), eq("foo"), anyBoolean()); 1234 } 1235 1236 @Test 1237 public void testTvExtenderChannelOverride_notOnTv() throws Exception { 1238 mService.setIsTelevision(false); 1239 mService.setRankingHelper(mRankingHelper); 1240 when(mRankingHelper.getNotificationChannel( 1241 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn( 1242 mTestNotificationChannel); 1243 1244 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); 1245 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0, 1246 generateNotificationRecord(null, tv).getNotification(), 0); 1247 verify(mRankingHelper, times(1)).getNotificationChannel( 1248 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean()); 1249 } 1250 1251 @Test 1252 public void testUpdateAppNotifyCreatorBlock() throws Exception { 1253 mService.setRankingHelper(mRankingHelper); 1254 1255 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false); 1256 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1257 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1258 1259 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED, 1260 captor.getValue().getAction()); 1261 assertEquals(PKG, captor.getValue().getPackage()); 1262 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 1263 } 1264 1265 @Test 1266 public void testUpdateAppNotifyCreatorUnblock() throws Exception { 1267 mService.setRankingHelper(mRankingHelper); 1268 1269 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true); 1270 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1271 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1272 1273 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED, 1274 captor.getValue().getAction()); 1275 assertEquals(PKG, captor.getValue().getPackage()); 1276 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true)); 1277 } 1278 1279 @Test 1280 public void testUpdateChannelNotifyCreatorBlock() throws Exception { 1281 mService.setRankingHelper(mRankingHelper); 1282 when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(), 1283 eq(mTestNotificationChannel.getId()), anyBoolean())) 1284 .thenReturn(mTestNotificationChannel); 1285 1286 NotificationChannel updatedChannel = 1287 new NotificationChannel(mTestNotificationChannel.getId(), 1288 mTestNotificationChannel.getName(), IMPORTANCE_NONE); 1289 1290 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel); 1291 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1292 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1293 1294 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, 1295 captor.getValue().getAction()); 1296 assertEquals(PKG, captor.getValue().getPackage()); 1297 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra( 1298 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID)); 1299 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 1300 } 1301 1302 @Test 1303 public void testUpdateChannelNotifyCreatorUnblock() throws Exception { 1304 NotificationChannel existingChannel = 1305 new NotificationChannel(mTestNotificationChannel.getId(), 1306 mTestNotificationChannel.getName(), IMPORTANCE_NONE); 1307 mService.setRankingHelper(mRankingHelper); 1308 when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(), 1309 eq(mTestNotificationChannel.getId()), anyBoolean())) 1310 .thenReturn(existingChannel); 1311 1312 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 1313 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1314 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1315 1316 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, 1317 captor.getValue().getAction()); 1318 assertEquals(PKG, captor.getValue().getPackage()); 1319 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra( 1320 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID)); 1321 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 1322 } 1323 1324 @Test 1325 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception { 1326 NotificationChannel existingChannel = 1327 new NotificationChannel(mTestNotificationChannel.getId(), 1328 mTestNotificationChannel.getName(), IMPORTANCE_MAX); 1329 mService.setRankingHelper(mRankingHelper); 1330 when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(), 1331 eq(mTestNotificationChannel.getId()), anyBoolean())) 1332 .thenReturn(existingChannel); 1333 1334 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 1335 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 1336 } 1337 1338 @Test 1339 public void testUpdateGroupNotifyCreatorBlock() throws Exception { 1340 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 1341 mService.setRankingHelper(mRankingHelper); 1342 when(mRankingHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt())) 1343 .thenReturn(existing); 1344 1345 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name"); 1346 updated.setBlocked(true); 1347 1348 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated); 1349 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1350 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1351 1352 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED, 1353 captor.getValue().getAction()); 1354 assertEquals(PKG, captor.getValue().getPackage()); 1355 assertEquals(existing.getId(), captor.getValue().getStringExtra( 1356 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID)); 1357 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 1358 } 1359 1360 @Test 1361 public void testUpdateGroupNotifyCreatorUnblock() throws Exception { 1362 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 1363 existing.setBlocked(true); 1364 mService.setRankingHelper(mRankingHelper); 1365 when(mRankingHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt())) 1366 .thenReturn(existing); 1367 1368 mBinderService.updateNotificationChannelGroupForPackage( 1369 PKG, 0, new NotificationChannelGroup("id", "name")); 1370 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1371 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1372 1373 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED, 1374 captor.getValue().getAction()); 1375 assertEquals(PKG, captor.getValue().getPackage()); 1376 assertEquals(existing.getId(), captor.getValue().getStringExtra( 1377 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID)); 1378 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 1379 } 1380 1381 @Test 1382 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception { 1383 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 1384 mService.setRankingHelper(mRankingHelper); 1385 when(mRankingHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt())) 1386 .thenReturn(existing); 1387 1388 mBinderService.updateNotificationChannelGroupForPackage( 1389 PKG, 0, new NotificationChannelGroup("id", "new name")); 1390 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 1391 } 1392 1393 @Test 1394 public void testCreateChannelNotifyListener() throws Exception { 1395 List<String> associations = new ArrayList<>(); 1396 associations.add("a"); 1397 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1398 mService.setRankingHelper(mRankingHelper); 1399 when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(), 1400 eq(mTestNotificationChannel.getId()), anyBoolean())) 1401 .thenReturn(mTestNotificationChannel); 1402 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW); 1403 when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(), 1404 eq(channel2.getId()), anyBoolean())) 1405 .thenReturn(channel2); 1406 1407 reset(mListeners); 1408 mBinderService.createNotificationChannels(PKG, 1409 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2))); 1410 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 1411 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1412 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 1413 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 1414 eq(Process.myUserHandle()), eq(channel2), 1415 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 1416 } 1417 1418 @Test 1419 public void testCreateChannelGroupNotifyListener() throws Exception { 1420 List<String> associations = new ArrayList<>(); 1421 associations.add("a"); 1422 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1423 mService.setRankingHelper(mRankingHelper); 1424 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b"); 1425 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m"); 1426 1427 reset(mListeners); 1428 mBinderService.createNotificationChannelGroups(PKG, 1429 new ParceledListSlice(Arrays.asList(group1, group2))); 1430 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 1431 eq(Process.myUserHandle()), eq(group1), 1432 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 1433 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 1434 eq(Process.myUserHandle()), eq(group2), 1435 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 1436 } 1437 1438 @Test 1439 public void testUpdateChannelNotifyListener() throws Exception { 1440 List<String> associations = new ArrayList<>(); 1441 associations.add("a"); 1442 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1443 mService.setRankingHelper(mRankingHelper); 1444 mTestNotificationChannel.setLightColor(Color.CYAN); 1445 when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(), 1446 eq(mTestNotificationChannel.getId()), anyBoolean())) 1447 .thenReturn(mTestNotificationChannel); 1448 1449 reset(mListeners); 1450 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 1451 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 1452 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1453 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 1454 } 1455 1456 @Test 1457 public void testDeleteChannelNotifyListener() throws Exception { 1458 List<String> associations = new ArrayList<>(); 1459 associations.add("a"); 1460 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1461 mService.setRankingHelper(mRankingHelper); 1462 when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(), 1463 eq(mTestNotificationChannel.getId()), anyBoolean())) 1464 .thenReturn(mTestNotificationChannel); 1465 reset(mListeners); 1466 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId()); 1467 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 1468 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1469 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); 1470 } 1471 1472 @Test 1473 public void testDeleteChannelGroupNotifyListener() throws Exception { 1474 List<String> associations = new ArrayList<>(); 1475 associations.add("a"); 1476 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1477 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c"); 1478 mService.setRankingHelper(mRankingHelper); 1479 when(mRankingHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt())) 1480 .thenReturn(ncg); 1481 reset(mListeners); 1482 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId()); 1483 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 1484 eq(Process.myUserHandle()), eq(ncg), 1485 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); 1486 } 1487 1488 @Test 1489 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception { 1490 mService.setRankingHelper(mRankingHelper); 1491 List<String> associations = new ArrayList<>(); 1492 associations.add("a"); 1493 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1494 when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(), 1495 eq(mTestNotificationChannel.getId()), anyBoolean())) 1496 .thenReturn(mTestNotificationChannel); 1497 1498 mBinderService.updateNotificationChannelFromPrivilegedListener( 1499 null, PKG, Process.myUserHandle(), mTestNotificationChannel); 1500 1501 verify(mRankingHelper, times(1)).updateNotificationChannel( 1502 anyString(), anyInt(), any(), anyBoolean()); 1503 1504 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 1505 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1506 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 1507 } 1508 1509 @Test 1510 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception { 1511 mService.setRankingHelper(mRankingHelper); 1512 List<String> associations = new ArrayList<>(); 1513 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1514 1515 try { 1516 mBinderService.updateNotificationChannelFromPrivilegedListener( 1517 null, PKG, Process.myUserHandle(), mTestNotificationChannel); 1518 fail("listeners that don't have a companion device shouldn't be able to call this"); 1519 } catch (SecurityException e) { 1520 // pass 1521 } 1522 1523 verify(mRankingHelper, never()).updateNotificationChannel( 1524 anyString(), anyInt(), any(), anyBoolean()); 1525 1526 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 1527 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1528 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 1529 } 1530 1531 @Test 1532 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception { 1533 mService.setRankingHelper(mRankingHelper); 1534 List<String> associations = new ArrayList<>(); 1535 associations.add("a"); 1536 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1537 mListener = mock(ManagedServices.ManagedServiceInfo.class); 1538 mListener.component = new ComponentName(PKG, PKG); 1539 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 1540 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 1541 1542 try { 1543 mBinderService.updateNotificationChannelFromPrivilegedListener( 1544 null, PKG, UserHandle.ALL, mTestNotificationChannel); 1545 fail("incorrectly allowed a change to a user listener cannot see"); 1546 } catch (SecurityException e) { 1547 // pass 1548 } 1549 1550 verify(mRankingHelper, never()).updateNotificationChannel( 1551 anyString(), anyInt(), any(), anyBoolean()); 1552 1553 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 1554 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1555 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 1556 } 1557 1558 @Test 1559 public void testGetNotificationChannelFromPrivilegedListener_success() throws Exception { 1560 mService.setRankingHelper(mRankingHelper); 1561 List<String> associations = new ArrayList<>(); 1562 associations.add("a"); 1563 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1564 1565 mBinderService.getNotificationChannelsFromPrivilegedListener( 1566 null, PKG, Process.myUserHandle()); 1567 1568 verify(mRankingHelper, times(1)).getNotificationChannels( 1569 anyString(), anyInt(), anyBoolean()); 1570 } 1571 1572 @Test 1573 public void testGetNotificationChannelFromPrivilegedListener_noAccess() throws Exception { 1574 mService.setRankingHelper(mRankingHelper); 1575 List<String> associations = new ArrayList<>(); 1576 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1577 1578 try { 1579 mBinderService.getNotificationChannelsFromPrivilegedListener( 1580 null, PKG, Process.myUserHandle()); 1581 fail("listeners that don't have a companion device shouldn't be able to call this"); 1582 } catch (SecurityException e) { 1583 // pass 1584 } 1585 1586 verify(mRankingHelper, never()).getNotificationChannels( 1587 anyString(), anyInt(), anyBoolean()); 1588 } 1589 1590 @Test 1591 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception { 1592 mService.setRankingHelper(mRankingHelper); 1593 List<String> associations = new ArrayList<>(); 1594 associations.add("a"); 1595 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1596 mListener = mock(ManagedServices.ManagedServiceInfo.class); 1597 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 1598 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 1599 1600 try { 1601 mBinderService.getNotificationChannelsFromPrivilegedListener( 1602 null, PKG, Process.myUserHandle()); 1603 fail("listener getting channels from a user they cannot see"); 1604 } catch (SecurityException e) { 1605 // pass 1606 } 1607 1608 verify(mRankingHelper, never()).getNotificationChannels( 1609 anyString(), anyInt(), anyBoolean()); 1610 } 1611 1612 @Test 1613 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception { 1614 mService.setRankingHelper(mRankingHelper); 1615 List<String> associations = new ArrayList<>(); 1616 associations.add("a"); 1617 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1618 1619 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 1620 null, PKG, Process.myUserHandle()); 1621 1622 verify(mRankingHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt()); 1623 } 1624 1625 @Test 1626 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception { 1627 mService.setRankingHelper(mRankingHelper); 1628 List<String> associations = new ArrayList<>(); 1629 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1630 1631 try { 1632 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 1633 null, PKG, Process.myUserHandle()); 1634 fail("listeners that don't have a companion device shouldn't be able to call this"); 1635 } catch (SecurityException e) { 1636 // pass 1637 } 1638 1639 verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); 1640 } 1641 1642 @Test 1643 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception { 1644 mService.setRankingHelper(mRankingHelper); 1645 List<String> associations = new ArrayList<>(); 1646 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1647 mListener = mock(ManagedServices.ManagedServiceInfo.class); 1648 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 1649 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 1650 1651 try { 1652 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 1653 null, PKG, Process.myUserHandle()); 1654 fail("listeners that don't have a companion device shouldn't be able to call this"); 1655 } catch (SecurityException e) { 1656 // pass 1657 } 1658 1659 verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); 1660 } 1661 1662 @Test 1663 public void testHasCompanionDevice_failure() throws Exception { 1664 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow( 1665 new IllegalArgumentException()); 1666 mService.hasCompanionDevice(mListener); 1667 } 1668 1669 @Test 1670 public void testHasCompanionDevice_noService() throws Exception { 1671 mService = new TestableNotificationManagerService(mContext); 1672 1673 assertFalse(mService.hasCompanionDevice(mListener)); 1674 } 1675 1676 @Test 1677 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception { 1678 final NotificationRecord nonGrouped = generateNotificationRecord( 1679 mTestNotificationChannel, 1, null, false); 1680 final NotificationRecord grouped = generateNotificationRecord( 1681 mTestNotificationChannel, 2, "group", false); 1682 mService.addNotification(grouped); 1683 mService.addNotification(nonGrouped); 1684 1685 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 1686 mService.new SnoozeNotificationRunnable( 1687 nonGrouped.getKey(), 100, null); 1688 snoozeNotificationRunnable.run(); 1689 1690 // only snooze the one notification 1691 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 1692 assertTrue(nonGrouped.getStats().hasSnoozed()); 1693 } 1694 1695 @Test 1696 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception { 1697 final NotificationRecord parent = generateNotificationRecord( 1698 mTestNotificationChannel, 1, "group", true); 1699 final NotificationRecord child = generateNotificationRecord( 1700 mTestNotificationChannel, 2, "group", false); 1701 final NotificationRecord child2 = generateNotificationRecord( 1702 mTestNotificationChannel, 3, "group", false); 1703 mService.addNotification(parent); 1704 mService.addNotification(child); 1705 mService.addNotification(child2); 1706 1707 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 1708 mService.new SnoozeNotificationRunnable( 1709 parent.getKey(), 100, null); 1710 snoozeNotificationRunnable.run(); 1711 1712 // snooze parent and children 1713 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong()); 1714 } 1715 1716 @Test 1717 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception { 1718 final NotificationRecord parent = generateNotificationRecord( 1719 mTestNotificationChannel, 1, "group", true); 1720 final NotificationRecord child = generateNotificationRecord( 1721 mTestNotificationChannel, 2, "group", false); 1722 final NotificationRecord child2 = generateNotificationRecord( 1723 mTestNotificationChannel, 3, "group", false); 1724 mService.addNotification(parent); 1725 mService.addNotification(child); 1726 mService.addNotification(child2); 1727 1728 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 1729 mService.new SnoozeNotificationRunnable( 1730 child2.getKey(), 100, null); 1731 snoozeNotificationRunnable.run(); 1732 1733 // only snooze the one child 1734 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 1735 } 1736 1737 @Test 1738 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception { 1739 final NotificationRecord parent = generateNotificationRecord( 1740 mTestNotificationChannel, 1, "group", true); 1741 assertTrue(parent.sbn.getNotification().isGroupSummary()); 1742 final NotificationRecord child = generateNotificationRecord( 1743 mTestNotificationChannel, 2, "group", false); 1744 mService.addNotification(parent); 1745 mService.addNotification(child); 1746 1747 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 1748 mService.new SnoozeNotificationRunnable( 1749 child.getKey(), 100, null); 1750 snoozeNotificationRunnable.run(); 1751 1752 // snooze child and summary 1753 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 1754 } 1755 1756 @Test 1757 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception { 1758 final NotificationRecord child = generateNotificationRecord( 1759 mTestNotificationChannel, 2, "group", false); 1760 mService.addNotification(child); 1761 1762 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 1763 mService.new SnoozeNotificationRunnable( 1764 child.getKey(), 100, null); 1765 snoozeNotificationRunnable.run(); 1766 1767 // snooze child only 1768 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 1769 } 1770 1771 @Test 1772 public void testPostGroupChild_unsnoozeParent() throws Exception { 1773 final NotificationRecord child = generateNotificationRecord( 1774 mTestNotificationChannel, 2, "group", false); 1775 1776 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, 1777 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId()); 1778 waitForIdle(); 1779 1780 verify(mSnoozeHelper, times(1)).repostGroupSummary( 1781 anyString(), anyInt(), eq(child.getGroupKey())); 1782 } 1783 1784 @Test 1785 public void testPostNonGroup_noUnsnoozing() throws Exception { 1786 final NotificationRecord record = generateNotificationRecord( 1787 mTestNotificationChannel, 2, null, false); 1788 1789 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, 1790 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId()); 1791 waitForIdle(); 1792 1793 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); 1794 } 1795 1796 @Test 1797 public void testPostGroupSummary_noUnsnoozing() throws Exception { 1798 final NotificationRecord parent = generateNotificationRecord( 1799 mTestNotificationChannel, 2, "group", true); 1800 1801 mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, 1802 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId()); 1803 waitForIdle(); 1804 1805 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); 1806 } 1807 1808 @Test 1809 public void testSetListenerAccessForUser() throws Exception { 1810 UserHandle user = UserHandle.of(10); 1811 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1812 try { 1813 mBinderService.setNotificationListenerAccessGrantedForUser( 1814 c, user.getIdentifier(), true); 1815 } catch (SecurityException e) { 1816 if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { 1817 throw e; 1818 } 1819 } 1820 1821 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 1822 verify(mListeners, times(1)).setPackageOrComponentEnabled( 1823 c.flattenToString(), user.getIdentifier(), true, true); 1824 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 1825 c.flattenToString(), user.getIdentifier(), false, true); 1826 verify(mAssistants, never()).setPackageOrComponentEnabled( 1827 any(), anyInt(), anyBoolean(), anyBoolean()); 1828 } 1829 1830 @Test 1831 public void testSetAssistantAccessForUser() throws Exception { 1832 UserHandle user = UserHandle.of(10); 1833 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1834 try { 1835 mBinderService.setNotificationAssistantAccessGrantedForUser( 1836 c, user.getIdentifier(), true); 1837 } catch (SecurityException e) { 1838 if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { 1839 throw e; 1840 } 1841 } 1842 1843 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 1844 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 1845 c.flattenToString(), user.getIdentifier(), true, true); 1846 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 1847 c.flattenToString(), user.getIdentifier(), false, true); 1848 verify(mListeners, never()).setPackageOrComponentEnabled( 1849 any(), anyInt(), anyBoolean(), anyBoolean()); 1850 } 1851 1852 @Test 1853 public void testSetDndAccessForUser() throws Exception { 1854 UserHandle user = UserHandle.of(10); 1855 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1856 try { 1857 mBinderService.setNotificationPolicyAccessGrantedForUser( 1858 c.getPackageName(), user.getIdentifier(), true); 1859 } catch (SecurityException e) { 1860 if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { 1861 throw e; 1862 } 1863 } 1864 1865 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 1866 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 1867 c.getPackageName(), user.getIdentifier(), true, true); 1868 verify(mAssistants, never()).setPackageOrComponentEnabled( 1869 any(), anyInt(), anyBoolean(), anyBoolean()); 1870 verify(mListeners, never()).setPackageOrComponentEnabled( 1871 any(), anyInt(), anyBoolean(), anyBoolean()); 1872 } 1873 1874 @Test 1875 public void testSetListenerAccess() throws Exception { 1876 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1877 try { 1878 mBinderService.setNotificationListenerAccessGranted(c, true); 1879 } catch (SecurityException e) { 1880 if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { 1881 throw e; 1882 } 1883 } 1884 1885 verify(mListeners, times(1)).setPackageOrComponentEnabled( 1886 c.flattenToString(), 0, true, true); 1887 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 1888 c.flattenToString(), 0, false, true); 1889 verify(mAssistants, never()).setPackageOrComponentEnabled( 1890 any(), anyInt(), anyBoolean(), anyBoolean()); 1891 } 1892 1893 @Test 1894 public void testSetAssistantAccess() throws Exception { 1895 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1896 try { 1897 mBinderService.setNotificationAssistantAccessGranted(c, true); 1898 } catch (SecurityException e) { 1899 if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { 1900 throw e; 1901 } 1902 } 1903 1904 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 1905 c.flattenToString(), 0, true, true); 1906 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 1907 c.flattenToString(), 0, false, true); 1908 verify(mListeners, never()).setPackageOrComponentEnabled( 1909 any(), anyInt(), anyBoolean(), anyBoolean()); 1910 } 1911 1912 @Test 1913 public void testSetDndAccess() throws Exception { 1914 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1915 try { 1916 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 1917 } catch (SecurityException e) { 1918 if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { 1919 throw e; 1920 } 1921 } 1922 1923 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 1924 c.getPackageName(), 0, true, true); 1925 verify(mAssistants, never()).setPackageOrComponentEnabled( 1926 any(), anyInt(), anyBoolean(), anyBoolean()); 1927 verify(mListeners, never()).setPackageOrComponentEnabled( 1928 any(), anyInt(), anyBoolean(), anyBoolean()); 1929 } 1930 1931 @Test 1932 public void testSetListenerAccess_doesNothingOnLowRam() throws Exception { 1933 when(mActivityManager.isLowRamDevice()).thenReturn(true); 1934 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1935 mBinderService.setNotificationListenerAccessGranted(c, true); 1936 1937 verify(mListeners, never()).setPackageOrComponentEnabled( 1938 anyString(), anyInt(), anyBoolean(), anyBoolean()); 1939 verify(mConditionProviders, never()).setPackageOrComponentEnabled( 1940 anyString(), anyInt(), anyBoolean(), anyBoolean()); 1941 verify(mAssistants, never()).setPackageOrComponentEnabled( 1942 any(), anyInt(), anyBoolean(), anyBoolean()); 1943 } 1944 1945 @Test 1946 public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception { 1947 when(mActivityManager.isLowRamDevice()).thenReturn(true); 1948 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1949 mBinderService.setNotificationAssistantAccessGranted(c, true); 1950 1951 verify(mListeners, never()).setPackageOrComponentEnabled( 1952 anyString(), anyInt(), anyBoolean(), anyBoolean()); 1953 verify(mConditionProviders, never()).setPackageOrComponentEnabled( 1954 anyString(), anyInt(), anyBoolean(), anyBoolean()); 1955 verify(mAssistants, never()).setPackageOrComponentEnabled( 1956 any(), anyInt(), anyBoolean(), anyBoolean()); 1957 } 1958 1959 @Test 1960 public void testSetDndAccess_doesNothingOnLowRam() throws Exception { 1961 when(mActivityManager.isLowRamDevice()).thenReturn(true); 1962 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1963 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 1964 1965 verify(mListeners, never()).setPackageOrComponentEnabled( 1966 anyString(), anyInt(), anyBoolean(), anyBoolean()); 1967 verify(mConditionProviders, never()).setPackageOrComponentEnabled( 1968 anyString(), anyInt(), anyBoolean(), anyBoolean()); 1969 verify(mAssistants, never()).setPackageOrComponentEnabled( 1970 any(), anyInt(), anyBoolean(), anyBoolean()); 1971 } 1972 1973 @Test 1974 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 1975 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 1976 when(mActivityManager.isLowRamDevice()).thenReturn(true); 1977 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1978 try { 1979 mBinderService.setNotificationListenerAccessGranted(c, true); 1980 } catch (SecurityException e) { 1981 if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { 1982 throw e; 1983 } 1984 } 1985 1986 verify(mListeners, times(1)).setPackageOrComponentEnabled( 1987 c.flattenToString(), 0, true, true); 1988 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 1989 c.flattenToString(), 0, false, true); 1990 verify(mAssistants, never()).setPackageOrComponentEnabled( 1991 any(), anyInt(), anyBoolean(), anyBoolean()); 1992 } 1993 1994 @Test 1995 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 1996 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 1997 when(mActivityManager.isLowRamDevice()).thenReturn(true); 1998 ComponentName c = ComponentName.unflattenFromString("package/Component"); 1999 try { 2000 mBinderService.setNotificationAssistantAccessGranted(c, true); 2001 } catch (SecurityException e) { 2002 if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { 2003 throw e; 2004 } 2005 } 2006 2007 verify(mListeners, never()).setPackageOrComponentEnabled( 2008 anyString(), anyInt(), anyBoolean(), anyBoolean()); 2009 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2010 c.flattenToString(), 0, false, true); 2011 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 2012 c.flattenToString(), 0, true, true); 2013 } 2014 2015 @Test 2016 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 2017 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 2018 when(mActivityManager.isLowRamDevice()).thenReturn(true); 2019 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2020 try { 2021 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 2022 } catch (SecurityException e) { 2023 if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { 2024 throw e; 2025 } 2026 } 2027 2028 verify(mListeners, never()).setPackageOrComponentEnabled( 2029 anyString(), anyInt(), anyBoolean(), anyBoolean()); 2030 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2031 c.getPackageName(), 0, true, true); 2032 verify(mAssistants, never()).setPackageOrComponentEnabled( 2033 any(), anyInt(), anyBoolean(), anyBoolean()); 2034 } 2035 2036 @Test 2037 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception { 2038 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 2039 mService.addEnqueuedNotification(r); 2040 NotificationManagerService.PostNotificationRunnable runnable = 2041 mService.new PostNotificationRunnable(r.getKey()); 2042 runnable.run(); 2043 waitForIdle(); 2044 2045 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 2046 } 2047 2048 @Test 2049 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups() 2050 throws Exception { 2051 NotificationRecord r = 2052 generateNotificationRecord(mTestNotificationChannel, 0, "group", false); 2053 mService.addNotification(r); 2054 2055 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 2056 mService.addEnqueuedNotification(r); 2057 NotificationManagerService.PostNotificationRunnable runnable = 2058 mService.new PostNotificationRunnable(r.getKey()); 2059 runnable.run(); 2060 waitForIdle(); 2061 2062 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 2063 } 2064 2065 @Test 2066 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups() 2067 throws Exception { 2068 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group", 2069 false); 2070 mService.addNotification(r); 2071 mService.addEnqueuedNotification(r); 2072 2073 NotificationManagerService.PostNotificationRunnable runnable = 2074 mService.new PostNotificationRunnable(r.getKey()); 2075 runnable.run(); 2076 waitForIdle(); 2077 2078 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean()); 2079 } 2080 2081 @Test 2082 public void testNoFakeColorizedPermission() throws Exception { 2083 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED); 2084 Notification.Builder nb = new Notification.Builder(mContext, 2085 mTestNotificationChannel.getId()) 2086 .setContentTitle("foo") 2087 .setColorized(true) 2088 .setFlag(Notification.FLAG_CAN_COLORIZE, true) 2089 .setSmallIcon(android.R.drawable.sym_def_app_icon); 2090 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, 2091 nb.build(), new UserHandle(mUid), null, 0); 2092 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 2093 2094 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 2095 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 2096 waitForIdle(); 2097 2098 NotificationRecord posted = mService.findNotificationLocked( 2099 PKG, null, nr.sbn.getId(), nr.sbn.getUserId()); 2100 2101 assertFalse(posted.getNotification().isColorized()); 2102 } 2103 2104 @Test 2105 public void testGetNotificationCountLocked() throws Exception { 2106 for (int i = 0; i < 20; i++) { 2107 NotificationRecord r = 2108 generateNotificationRecord(mTestNotificationChannel, i, null, false); 2109 mService.addEnqueuedNotification(r); 2110 } 2111 for (int i = 0; i < 20; i++) { 2112 NotificationRecord r = 2113 generateNotificationRecord(mTestNotificationChannel, i, null, false); 2114 mService.addNotification(r); 2115 } 2116 2117 // another package 2118 Notification n = 2119 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 2120 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2121 .build(); 2122 2123 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0, 2124 n, new UserHandle(mUid), null, 0); 2125 NotificationRecord otherPackage = 2126 new NotificationRecord(mContext, sbn, mTestNotificationChannel); 2127 mService.addEnqueuedNotification(otherPackage); 2128 mService.addNotification(otherPackage); 2129 2130 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match 2131 int userId = new UserHandle(mUid).getIdentifier(); 2132 assertEquals(40, 2133 mService.getNotificationCountLocked(PKG, userId, 0, null)); 2134 assertEquals(40, 2135 mService.getNotificationCountLocked(PKG, userId, 0, "tag2")); 2136 assertEquals(2, 2137 mService.getNotificationCountLocked("a", userId, 0, "banana")); 2138 2139 // exclude a known notification - it's excluded from only the posted list, not enqueued 2140 assertEquals(39, 2141 mService.getNotificationCountLocked(PKG, userId, 0, "tag")); 2142 } 2143 2144 @Test 2145 public void testAddAutogroup_requestsSort() throws Exception { 2146 RankingHandler rh = mock(RankingHandler.class); 2147 mService.setRankingHandler(rh); 2148 2149 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2150 mService.addNotification(r); 2151 mService.addAutogroupKeyLocked(r.getKey()); 2152 2153 verify(rh, times(1)).requestSort(); 2154 } 2155 2156 @Test 2157 public void testRemoveAutogroup_requestsSort() throws Exception { 2158 RankingHandler rh = mock(RankingHandler.class); 2159 mService.setRankingHandler(rh); 2160 2161 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2162 r.setOverrideGroupKey("TEST"); 2163 mService.addNotification(r); 2164 mService.removeAutogroupKeyLocked(r.getKey()); 2165 2166 verify(rh, times(1)).requestSort(); 2167 } 2168 2169 @Test 2170 public void testReaddAutogroup_noSort() throws Exception { 2171 RankingHandler rh = mock(RankingHandler.class); 2172 mService.setRankingHandler(rh); 2173 2174 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2175 r.setOverrideGroupKey("TEST"); 2176 mService.addNotification(r); 2177 mService.addAutogroupKeyLocked(r.getKey()); 2178 2179 verify(rh, never()).requestSort(); 2180 } 2181 2182 @Test 2183 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception { 2184 mService.setRankingHelper(mRankingHelper); 2185 NotificationManagerService.WorkerHandler handler = mock( 2186 NotificationManagerService.WorkerHandler.class); 2187 mService.setHandler(handler); 2188 2189 Map<String, Answer> answers = getSignalExtractorSideEffects(); 2190 for (String message : answers.keySet()) { 2191 mService.clearNotifications(); 2192 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2193 mService.addNotification(r); 2194 2195 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r); 2196 2197 mService.handleRankingSort(); 2198 } 2199 verify(handler, times(answers.size())).scheduleSendRankingUpdate(); 2200 } 2201 2202 @Test 2203 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception { 2204 mService.setRankingHelper(mRankingHelper); 2205 NotificationManagerService.WorkerHandler handler = mock( 2206 NotificationManagerService.WorkerHandler.class); 2207 mService.setHandler(handler); 2208 2209 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2210 mService.addNotification(r); 2211 2212 mService.handleRankingSort(); 2213 verify(handler, never()).scheduleSendRankingUpdate(); 2214 } 2215 2216 @Test 2217 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception { 2218 final String upgradeXml = "<notification-policy version=\"1\">" 2219 + "<ranking></ranking>" 2220 + "<enabled_listeners>" 2221 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 2222 + "</enabled_listeners>" 2223 + "<enabled_assistants>" 2224 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 2225 + "</enabled_assistants>" 2226 + "<dnd_apps>" 2227 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 2228 + "</dnd_apps>" 2229 + "</notification-policy>"; 2230 mService.readPolicyXml( 2231 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())), false); 2232 verify(mListeners, times(1)).readXml(any(), any()); 2233 verify(mConditionProviders, times(1)).readXml(any(), any()); 2234 verify(mAssistants, times(1)).readXml(any(), any()); 2235 2236 // numbers are inflated for setup 2237 verify(mListeners, times(1)).migrateToXml(); 2238 verify(mConditionProviders, times(1)).migrateToXml(); 2239 verify(mAssistants, times(1)).migrateToXml(); 2240 verify(mAssistants, times(2)).ensureAssistant(); 2241 } 2242 2243 @Test 2244 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception { 2245 final String preupgradeXml = "<notification-policy version=\"1\">" 2246 + "<ranking></ranking>" 2247 + "</notification-policy>"; 2248 mService.readPolicyXml( 2249 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), false); 2250 verify(mListeners, never()).readXml(any(), any()); 2251 verify(mConditionProviders, never()).readXml(any(), any()); 2252 verify(mAssistants, never()).readXml(any(), any()); 2253 2254 // numbers are inflated for setup 2255 verify(mListeners, times(2)).migrateToXml(); 2256 verify(mConditionProviders, times(2)).migrateToXml(); 2257 verify(mAssistants, times(2)).migrateToXml(); 2258 verify(mAssistants, times(2)).ensureAssistant(); 2259 } 2260 2261 2262 @Test 2263 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception { 2264 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 2265 mService.mZenModeHelper = mZenModeHelper; 2266 mService.mLocaleChangeReceiver.onReceive(mContext, 2267 new Intent(Intent.ACTION_LOCALE_CHANGED)); 2268 2269 verify(mZenModeHelper, times(1)).updateDefaultZenRules(); 2270 } 2271 2272 @Test 2273 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception { 2274 String preOPkg = PKG_N_MR1; 2275 int preOUid = 145; 2276 final ApplicationInfo legacy = new ApplicationInfo(); 2277 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 2278 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt())) 2279 .thenReturn(legacy); 2280 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt())).thenReturn(preOUid); 2281 getContext().setMockPackageManager(mPackageManagerClient); 2282 2283 Notification.Builder nb = new Notification.Builder(mContext, 2284 NotificationChannel.DEFAULT_CHANNEL_ID) 2285 .setContentTitle("foo") 2286 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2287 .setFlag(FLAG_FOREGROUND_SERVICE, true) 2288 .setPriority(Notification.PRIORITY_MIN); 2289 2290 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", preOUid, 2291 0, nb.build(), new UserHandle(preOUid), null, 0); 2292 2293 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag", 2294 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2295 waitForIdle(); 2296 assertEquals(IMPORTANCE_LOW, 2297 mService.getNotificationRecord(sbn.getKey()).getImportance()); 2298 2299 nb = new Notification.Builder(mContext) 2300 .setContentTitle("foo") 2301 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2302 .setFlag(FLAG_FOREGROUND_SERVICE, true) 2303 .setPriority(Notification.PRIORITY_MIN); 2304 2305 sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", preOUid, 2306 0, nb.build(), new UserHandle(preOUid), null, 0); 2307 2308 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag", 2309 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2310 waitForIdle(); 2311 assertEquals(IMPORTANCE_LOW, 2312 mService.getNotificationRecord(sbn.getKey()).getImportance()); 2313 2314 NotificationChannel defaultChannel = mBinderService.getNotificationChannel( 2315 preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID); 2316 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance()); 2317 } 2318 2319 @Test 2320 public void testStats_updatedOnDirectReply() throws Exception { 2321 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2322 mService.addNotification(r); 2323 2324 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey()); 2325 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied()); 2326 } 2327 2328 @Test 2329 public void testStats_updatedOnUserExpansion() throws Exception { 2330 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2331 mService.addNotification(r); 2332 2333 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true); 2334 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 2335 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false); 2336 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 2337 } 2338 2339 @Test 2340 public void testStats_notUpdatedOnAutoExpansion() throws Exception { 2341 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2342 mService.addNotification(r); 2343 2344 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true); 2345 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 2346 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false); 2347 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 2348 } 2349 2350 @Test 2351 public void testStats_updatedOnViewSettings() throws Exception { 2352 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2353 mService.addNotification(r); 2354 2355 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey()); 2356 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings()); 2357 } 2358 2359 @Test 2360 public void testStats_updatedOnVisibilityChanged() throws Exception { 2361 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2362 mService.addNotification(r); 2363 2364 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true); 2365 mService.mNotificationDelegate.onNotificationVisibilityChanged( 2366 new NotificationVisibility[] {nv}, new NotificationVisibility[]{}); 2367 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen()); 2368 mService.mNotificationDelegate.onNotificationVisibilityChanged( 2369 new NotificationVisibility[] {}, new NotificationVisibility[]{nv}); 2370 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen()); 2371 } 2372 2373 @Test 2374 public void testStats_dismissalSurface() throws Exception { 2375 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2376 mService.addNotification(r); 2377 2378 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true); 2379 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(), 2380 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD, nv); 2381 waitForIdle(); 2382 2383 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface()); 2384 } 2385 2386 @Test 2387 public void testUserSentimentChangeTriggersUpdate() throws Exception { 2388 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2389 mService.addNotification(r); 2390 NotificationManagerService.WorkerHandler handler = mock( 2391 NotificationManagerService.WorkerHandler.class); 2392 mService.setHandler(handler); 2393 2394 Bundle signals = new Bundle(); 2395 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 2396 NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE); 2397 Adjustment adjustment = new Adjustment( 2398 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 2399 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 2400 2401 waitForIdle(); 2402 2403 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate(); 2404 } 2405 2406 @Test 2407 public void testRecents() throws Exception { 2408 Set<NotifyingApp> expected = new HashSet<>(); 2409 2410 final NotificationRecord oldest = new NotificationRecord(mContext, 2411 generateSbn("p", 1000, 9, 0), mTestNotificationChannel); 2412 mService.logRecentLocked(oldest); 2413 for (int i = 1; i <= 5; i++) { 2414 NotificationRecord r = new NotificationRecord(mContext, 2415 generateSbn("p" + i, i, i*100, 0), mTestNotificationChannel); 2416 expected.add(new NotifyingApp() 2417 .setPackage(r.sbn.getPackageName()) 2418 .setUid(r.sbn.getUid()) 2419 .setLastNotified(r.sbn.getPostTime())); 2420 mService.logRecentLocked(r); 2421 } 2422 2423 List<NotifyingApp> apps = mBinderService.getRecentNotifyingAppsForUser(0).getList(); 2424 assertTrue(apps.size() == 5); 2425 for (NotifyingApp actual : apps) { 2426 assertTrue("got unexpected result: " + actual, expected.contains(actual)); 2427 } 2428 } 2429 2430 @Test 2431 public void testRecentsNoDuplicatePackages() throws Exception { 2432 final NotificationRecord p1 = new NotificationRecord(mContext, generateSbn("p", 1, 1000, 0), 2433 mTestNotificationChannel); 2434 final NotificationRecord p2 = new NotificationRecord(mContext, generateSbn("p", 1, 2000, 0), 2435 mTestNotificationChannel); 2436 2437 mService.logRecentLocked(p1); 2438 mService.logRecentLocked(p2); 2439 2440 List<NotifyingApp> apps = mBinderService.getRecentNotifyingAppsForUser(0).getList(); 2441 assertTrue(apps.size() == 1); 2442 NotifyingApp expected = new NotifyingApp().setPackage("p").setUid(1).setLastNotified(2000); 2443 assertEquals(expected, apps.get(0)); 2444 } 2445 2446 @Test 2447 public void testRecentsWithDuplicatePackage() throws Exception { 2448 Set<NotifyingApp> expected = new HashSet<>(); 2449 2450 final NotificationRecord oldest = new NotificationRecord(mContext, 2451 generateSbn("p", 1000, 9, 0), mTestNotificationChannel); 2452 mService.logRecentLocked(oldest); 2453 for (int i = 1; i <= 5; i++) { 2454 NotificationRecord r = new NotificationRecord(mContext, 2455 generateSbn("p" + i, i, i*100, 0), mTestNotificationChannel); 2456 expected.add(new NotifyingApp() 2457 .setPackage(r.sbn.getPackageName()) 2458 .setUid(r.sbn.getUid()) 2459 .setLastNotified(r.sbn.getPostTime())); 2460 mService.logRecentLocked(r); 2461 } 2462 NotificationRecord r = new NotificationRecord(mContext, 2463 generateSbn("p" + 3, 3, 300000, 0), mTestNotificationChannel); 2464 expected.remove(new NotifyingApp() 2465 .setPackage(r.sbn.getPackageName()) 2466 .setUid(3) 2467 .setLastNotified(300)); 2468 NotifyingApp newest = new NotifyingApp() 2469 .setPackage(r.sbn.getPackageName()) 2470 .setUid(r.sbn.getUid()) 2471 .setLastNotified(r.sbn.getPostTime()); 2472 expected.add(newest); 2473 mService.logRecentLocked(r); 2474 2475 List<NotifyingApp> apps = mBinderService.getRecentNotifyingAppsForUser(0).getList(); 2476 assertTrue(apps.size() == 5); 2477 for (NotifyingApp actual : apps) { 2478 assertTrue("got unexpected result: " + actual, expected.contains(actual)); 2479 } 2480 assertEquals(newest, apps.get(0)); 2481 } 2482 2483 @Test 2484 public void testRecentsMultiuser() throws Exception { 2485 final NotificationRecord user1 = new NotificationRecord(mContext, 2486 generateSbn("p", 1000, 9, 1), mTestNotificationChannel); 2487 mService.logRecentLocked(user1); 2488 2489 final NotificationRecord user2 = new NotificationRecord(mContext, 2490 generateSbn("p2", 100000, 9999, 2), mTestNotificationChannel); 2491 mService.logRecentLocked(user2); 2492 2493 assertEquals(0, mBinderService.getRecentNotifyingAppsForUser(0).getList().size()); 2494 assertEquals(1, mBinderService.getRecentNotifyingAppsForUser(1).getList().size()); 2495 assertEquals(1, mBinderService.getRecentNotifyingAppsForUser(2).getList().size()); 2496 2497 assertTrue(mBinderService.getRecentNotifyingAppsForUser(2).getList().contains( 2498 new NotifyingApp() 2499 .setPackage(user2.sbn.getPackageName()) 2500 .setUid(user2.sbn.getUid()) 2501 .setLastNotified(user2.sbn.getPostTime()))); 2502 } 2503 2504 @Test 2505 public void testRestore() throws Exception { 2506 int systemChecks = mService.countSystemChecks; 2507 mBinderService.applyRestore(null, UserHandle.USER_SYSTEM); 2508 assertEquals(1, mService.countSystemChecks - systemChecks); 2509 } 2510 2511 @Test 2512 public void testBackup() throws Exception { 2513 int systemChecks = mService.countSystemChecks; 2514 mBinderService.getBackupPayload(1); 2515 assertEquals(1, mService.countSystemChecks - systemChecks); 2516 } 2517 2518 @Test 2519 public void updateUriPermissions_update() throws Exception { 2520 NotificationChannel c = new NotificationChannel( 2521 TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT); 2522 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT); 2523 Message message1 = new Message("", 0, ""); 2524 message1.setData("", 2525 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1)); 2526 Message message2 = new Message("", 1, ""); 2527 message2.setData("", 2528 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2)); 2529 2530 Notification.Builder nbA = new Notification.Builder(mContext, c.getId()) 2531 .setContentTitle("foo") 2532 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2533 .setStyle(new Notification.MessagingStyle("") 2534 .addMessage(message1) 2535 .addMessage(message2)); 2536 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification( 2537 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c); 2538 2539 // First post means we grant access to both 2540 reset(mAm); 2541 when(mAm.newUriPermissionOwner(any())).thenReturn(new Binder()); 2542 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), 2543 UserHandle.USER_SYSTEM); 2544 verify(mAm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 2545 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt()); 2546 verify(mAm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 2547 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt()); 2548 2549 Notification.Builder nbB = new Notification.Builder(mContext, c.getId()) 2550 .setContentTitle("foo") 2551 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2552 .setStyle(new Notification.MessagingStyle("").addMessage(message2)); 2553 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG, 2554 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c); 2555 2556 // Update means we drop access to first 2557 reset(mAm); 2558 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(), 2559 UserHandle.USER_SYSTEM); 2560 verify(mAm, times(1)).revokeUriPermissionFromOwner(any(), eq(message1.getDataUri()), 2561 anyInt(), anyInt()); 2562 2563 // Update back means we grant access to first again 2564 reset(mAm); 2565 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(), 2566 UserHandle.USER_SYSTEM); 2567 verify(mAm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 2568 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt()); 2569 2570 // And update to empty means we drop everything 2571 reset(mAm); 2572 mService.updateUriPermissions(null, recordB, mContext.getPackageName(), 2573 UserHandle.USER_SYSTEM); 2574 verify(mAm, times(1)).revokeUriPermissionFromOwner(any(), eq(null), 2575 anyInt(), anyInt()); 2576 } 2577 2578 @Test 2579 public void testSetNotificationPolicy_preP_setOldFields() { 2580 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 2581 mService.mZenModeHelper = mZenModeHelper; 2582 NotificationManager.Policy userPolicy = 2583 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 2584 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 2585 2586 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 2587 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 2588 2589 int expected = SUPPRESSED_EFFECT_BADGE 2590 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 2591 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS 2592 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 2593 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 2594 2595 assertEquals(expected, actual); 2596 } 2597 2598 @Test 2599 public void testSetNotificationPolicy_preP_setNewFields() { 2600 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 2601 mService.mZenModeHelper = mZenModeHelper; 2602 NotificationManager.Policy userPolicy = 2603 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 2604 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 2605 2606 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 2607 SUPPRESSED_EFFECT_NOTIFICATION_LIST); 2608 2609 int expected = SUPPRESSED_EFFECT_BADGE; 2610 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 2611 2612 assertEquals(expected, actual); 2613 } 2614 2615 @Test 2616 public void testSetNotificationPolicy_preP_setOldNewFields() { 2617 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 2618 mService.mZenModeHelper = mZenModeHelper; 2619 NotificationManager.Policy userPolicy = 2620 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 2621 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 2622 2623 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 2624 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 2625 2626 int expected = 2627 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK; 2628 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 2629 2630 assertEquals(expected, actual); 2631 } 2632 2633 @Test 2634 public void testSetNotificationPolicy_P_setOldFields() { 2635 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 2636 mService.mZenModeHelper = mZenModeHelper; 2637 NotificationManager.Policy userPolicy = 2638 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 2639 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 2640 2641 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 2642 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 2643 2644 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 2645 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT 2646 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 2647 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 2648 2649 assertEquals(expected, actual); 2650 } 2651 2652 @Test 2653 public void testSetNotificationPolicy_P_setNewFields() { 2654 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 2655 mService.mZenModeHelper = mZenModeHelper; 2656 NotificationManager.Policy userPolicy = 2657 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 2658 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 2659 2660 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 2661 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT 2662 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 2663 2664 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF 2665 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS 2666 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 2667 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 2668 2669 assertEquals(expected, actual); 2670 } 2671 2672 @Test 2673 public void testSetNotificationPolicy_P_setOldNewFields() { 2674 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 2675 mService.mZenModeHelper = mZenModeHelper; 2676 NotificationManager.Policy userPolicy = 2677 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 2678 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 2679 2680 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 2681 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 2682 2683 int expected = SUPPRESSED_EFFECT_STATUS_BAR; 2684 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 2685 2686 assertEquals(expected, actual); 2687 2688 appPolicy = new NotificationManager.Policy(0, 0, 0, 2689 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT 2690 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 2691 2692 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT 2693 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 2694 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 2695 2696 assertEquals(expected, actual); 2697 } 2698 2699 @Test 2700 public void testVisualDifference_foreground() { 2701 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2702 .setContentTitle("foo"); 2703 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2704 nb1.build(), new UserHandle(mUid), null, 0); 2705 NotificationRecord r1 = 2706 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2707 2708 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2709 .setFlag(FLAG_FOREGROUND_SERVICE, true) 2710 .setContentTitle("bar"); 2711 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2712 nb2.build(), new UserHandle(mUid), null, 0); 2713 NotificationRecord r2 = 2714 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2715 2716 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 2717 } 2718 2719 @Test 2720 public void testVisualDifference_diffTitle() { 2721 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2722 .setContentTitle("foo"); 2723 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2724 nb1.build(), new UserHandle(mUid), null, 0); 2725 NotificationRecord r1 = 2726 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2727 2728 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2729 .setContentTitle("bar"); 2730 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2731 nb2.build(), new UserHandle(mUid), null, 0); 2732 NotificationRecord r2 = 2733 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2734 2735 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 2736 } 2737 2738 @Test 2739 public void testVisualDifference_inboxStyle() { 2740 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2741 .setStyle(new Notification.InboxStyle() 2742 .addLine("line1").addLine("line2")); 2743 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2744 nb1.build(), new UserHandle(mUid), null, 0); 2745 NotificationRecord r1 = 2746 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2747 2748 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2749 .setStyle(new Notification.InboxStyle() 2750 .addLine("line1").addLine("line2_changed")); 2751 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2752 nb2.build(), new UserHandle(mUid), null, 0); 2753 NotificationRecord r2 = 2754 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2755 2756 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed 2757 2758 Notification.Builder nb3 = new Notification.Builder(mContext, "") 2759 .setStyle(new Notification.InboxStyle() 2760 .addLine("line1")); 2761 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2762 nb3.build(), new UserHandle(mUid), null, 0); 2763 NotificationRecord r3 = 2764 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class)); 2765 2766 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed 2767 2768 Notification.Builder nb4 = new Notification.Builder(mContext, "") 2769 .setStyle(new Notification.InboxStyle() 2770 .addLine("line1").addLine("line2").addLine("line3")); 2771 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2772 nb4.build(), new UserHandle(mUid), null, 0); 2773 NotificationRecord r4 = 2774 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class)); 2775 2776 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed 2777 2778 Notification.Builder nb5 = new Notification.Builder(mContext, "") 2779 .setContentText("not an inbox"); 2780 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2781 nb5.build(), new UserHandle(mUid), null, 0); 2782 NotificationRecord r5 = 2783 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class)); 2784 2785 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed 2786 } 2787 2788 @Test 2789 public void testVisualDifference_diffText() { 2790 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2791 .setContentText("foo"); 2792 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2793 nb1.build(), new UserHandle(mUid), null, 0); 2794 NotificationRecord r1 = 2795 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2796 2797 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2798 .setContentText("bar"); 2799 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2800 nb2.build(), new UserHandle(mUid), null, 0); 2801 NotificationRecord r2 = 2802 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2803 2804 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 2805 } 2806 2807 @Test 2808 public void testVisualDifference_sameText() { 2809 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2810 .setContentText("foo"); 2811 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2812 nb1.build(), new UserHandle(mUid), null, 0); 2813 NotificationRecord r1 = 2814 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2815 2816 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2817 .setContentText("foo"); 2818 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2819 nb2.build(), new UserHandle(mUid), null, 0); 2820 NotificationRecord r2 = 2821 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2822 2823 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 2824 } 2825 2826 @Test 2827 public void testVisualDifference_sameTextButStyled() { 2828 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2829 .setContentText(Html.fromHtml("<b>foo</b>")); 2830 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2831 nb1.build(), new UserHandle(mUid), null, 0); 2832 NotificationRecord r1 = 2833 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2834 2835 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2836 .setContentText(Html.fromHtml("<b>foo</b>")); 2837 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2838 nb2.build(), new UserHandle(mUid), null, 0); 2839 NotificationRecord r2 = 2840 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2841 2842 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 2843 } 2844 2845 @Test 2846 public void testVisualDifference_diffTextButStyled() { 2847 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2848 .setContentText(Html.fromHtml("<b>foo</b>")); 2849 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2850 nb1.build(), new UserHandle(mUid), null, 0); 2851 NotificationRecord r1 = 2852 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2853 2854 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2855 .setContentText(Html.fromHtml("<b>bar</b>")); 2856 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2857 nb2.build(), new UserHandle(mUid), null, 0); 2858 NotificationRecord r2 = 2859 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2860 2861 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 2862 } 2863 2864 @Test 2865 public void testVisualDifference_diffProgress() { 2866 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2867 .setProgress(100, 90, false); 2868 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2869 nb1.build(), new UserHandle(mUid), null, 0); 2870 NotificationRecord r1 = 2871 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2872 2873 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2874 .setProgress(100, 100, false); 2875 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2876 nb2.build(), new UserHandle(mUid), null, 0); 2877 NotificationRecord r2 = 2878 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2879 2880 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 2881 } 2882 2883 @Test 2884 public void testVisualDifference_diffProgressNotDone() { 2885 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2886 .setProgress(100, 90, false); 2887 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2888 nb1.build(), new UserHandle(mUid), null, 0); 2889 NotificationRecord r1 = 2890 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2891 2892 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2893 .setProgress(100, 91, false); 2894 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2895 nb2.build(), new UserHandle(mUid), null, 0); 2896 NotificationRecord r2 = 2897 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2898 2899 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 2900 } 2901 2902 @Test 2903 public void testVisualDifference_sameProgressStillDone() { 2904 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2905 .setProgress(100, 100, false); 2906 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2907 nb1.build(), new UserHandle(mUid), null, 0); 2908 NotificationRecord r1 = 2909 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2910 2911 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2912 .setProgress(100, 100, false); 2913 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2914 nb2.build(), new UserHandle(mUid), null, 0); 2915 NotificationRecord r2 = 2916 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2917 2918 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 2919 } 2920 2921 @Test 2922 public void testVisualDifference_summary() { 2923 Notification.Builder nb1 = new Notification.Builder(mContext, "") 2924 .setGroup("bananas") 2925 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 2926 .setContentText("foo"); 2927 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2928 nb1.build(), new UserHandle(mUid), null, 0); 2929 NotificationRecord r1 = 2930 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 2931 2932 Notification.Builder nb2 = new Notification.Builder(mContext, "") 2933 .setGroup("bananas") 2934 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 2935 .setContentText("bar"); 2936 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 2937 nb2.build(), new UserHandle(mUid), null, 0); 2938 NotificationRecord r2 = 2939 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 2940 2941 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 2942 } 2943 2944 @Test 2945 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() { 2946 // post 2 notification from this package 2947 final NotificationRecord notif1 = generateNotificationRecord( 2948 mTestNotificationChannel, 1, null, true); 2949 final NotificationRecord notif2 = generateNotificationRecord( 2950 mTestNotificationChannel, 2, null, false); 2951 mService.addNotification(notif1); 2952 mService.addNotification(notif2); 2953 2954 // on broadcast, hide the 2 notifications 2955 mService.simulatePackageSuspendBroadcast(true, PKG); 2956 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class); 2957 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 2958 assertEquals(2, captorHide.getValue().size()); 2959 2960 // on broadcast, unhide the 2 notifications 2961 mService.simulatePackageSuspendBroadcast(false, PKG); 2962 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class); 2963 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 2964 assertEquals(2, captorUnhide.getValue().size()); 2965 } 2966 2967 @Test 2968 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() { 2969 // post 2 notification from this package 2970 final NotificationRecord notif1 = generateNotificationRecord( 2971 mTestNotificationChannel, 1, null, true); 2972 final NotificationRecord notif2 = generateNotificationRecord( 2973 mTestNotificationChannel, 2, null, false); 2974 mService.addNotification(notif1); 2975 mService.addNotification(notif2); 2976 2977 // on broadcast, nothing is hidden since no notifications are of package "test_package" 2978 mService.simulatePackageSuspendBroadcast(true, "test_package"); 2979 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 2980 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 2981 assertEquals(0, captor.getValue().size()); 2982 } 2983 2984 @Test 2985 public void testCanUseManagedServicesLowRamNoWatchNullPkg() { 2986 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 2987 when(mActivityManager.isLowRamDevice()).thenReturn(true); 2988 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 2989 .thenReturn(new String[] {"a", "b", "c"}); 2990 when(mContext.getResources()).thenReturn(mResources); 2991 2992 assertEquals(false, mService.canUseManagedServices(null)); 2993 } 2994 2995 @Test 2996 public void testCanUseManagedServicesLowRamNoWatchValidPkg() { 2997 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 2998 when(mActivityManager.isLowRamDevice()).thenReturn(true); 2999 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3000 .thenReturn(new String[] {"a", "b", "c"}); 3001 when(mContext.getResources()).thenReturn(mResources); 3002 3003 assertEquals(true, mService.canUseManagedServices("b")); 3004 } 3005 3006 @Test 3007 public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() { 3008 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 3009 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3010 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3011 .thenReturn(new String[] {"a", "b", "c"}); 3012 when(mContext.getResources()).thenReturn(mResources); 3013 3014 assertEquals(false, mService.canUseManagedServices("d")); 3015 } 3016 3017 @Test 3018 public void testCanUseManagedServicesLowRamWatchNoValidPkg() { 3019 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 3020 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3021 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3022 .thenReturn(new String[] {"a", "b", "c"}); 3023 when(mContext.getResources()).thenReturn(mResources); 3024 3025 assertEquals(true, mService.canUseManagedServices("d")); 3026 } 3027 3028 @Test 3029 public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() { 3030 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 3031 when(mActivityManager.isLowRamDevice()).thenReturn(false); 3032 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3033 .thenReturn(new String[] {"a", "b", "c"}); 3034 when(mContext.getResources()).thenReturn(mResources); 3035 3036 assertEquals(true, mService.canUseManagedServices("d")); 3037 } 3038 3039 @Test 3040 public void testCanUseManagedServicesNoLowRamWatchValidPkg() { 3041 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 3042 when(mActivityManager.isLowRamDevice()).thenReturn(false); 3043 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3044 .thenReturn(new String[] {"a", "b", "c"}); 3045 when(mContext.getResources()).thenReturn(mResources); 3046 3047 assertEquals(true, mService.canUseManagedServices("d")); 3048 } 3049 3050 @Test 3051 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() { 3052 final NotificationRecord r = generateNotificationRecord( 3053 mTestNotificationChannel, 1, null, true); 3054 r.setTextChanged(true); 3055 mService.addNotification(r); 3056 3057 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[] 3058 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}, 3059 new NotificationVisibility[]{}); 3060 3061 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt()); 3062 } 3063 3064 @Test 3065 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat() 3066 throws RemoteException { 3067 final NotificationRecord r = generateNotificationRecord( 3068 mTestNotificationChannel, 1, null, true); 3069 r.setTextChanged(true); 3070 mService.addNotification(r); 3071 3072 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()}); 3073 3074 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt()); 3075 } 3076 3077 @Test 3078 public void testMybeRecordInterruptionLocked_doesNotRecordTwice() 3079 throws RemoteException { 3080 final NotificationRecord r = generateNotificationRecord( 3081 mTestNotificationChannel, 1, null, true); 3082 r.setInterruptive(true); 3083 mService.addNotification(r); 3084 3085 mService.maybeRecordInterruptionLocked(r); 3086 mService.maybeRecordInterruptionLocked(r); 3087 3088 verify(mAppUsageStats, times(1)).reportInterruptiveNotification( 3089 anyString(), anyString(), anyInt()); 3090 } 3091 } 3092