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.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; 20 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; 21 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; 22 import static android.app.Notification.CATEGORY_CALL; 23 import static android.app.Notification.FLAG_AUTO_CANCEL; 24 import static android.app.Notification.FLAG_BUBBLE; 25 import static android.app.Notification.FLAG_FOREGROUND_SERVICE; 26 import static android.app.NotificationManager.EXTRA_BLOCKED_STATE; 27 import static android.app.NotificationManager.IMPORTANCE_DEFAULT; 28 import static android.app.NotificationManager.IMPORTANCE_HIGH; 29 import static android.app.NotificationManager.IMPORTANCE_LOW; 30 import static android.app.NotificationManager.IMPORTANCE_MAX; 31 import static android.app.NotificationManager.IMPORTANCE_NONE; 32 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; 33 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT; 34 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE; 35 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 36 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS; 37 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; 38 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; 39 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; 40 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; 41 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; 42 import static android.content.pm.PackageManager.FEATURE_WATCH; 43 import static android.content.pm.PackageManager.PERMISSION_DENIED; 44 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 45 import static android.os.Build.VERSION_CODES.O_MR1; 46 import static android.os.Build.VERSION_CODES.P; 47 import static android.service.notification.Adjustment.KEY_IMPORTANCE; 48 import static android.service.notification.Adjustment.KEY_USER_SENTIMENT; 49 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; 50 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; 51 52 import static junit.framework.Assert.assertEquals; 53 import static junit.framework.Assert.assertFalse; 54 import static junit.framework.Assert.assertNotNull; 55 import static junit.framework.Assert.assertNull; 56 import static junit.framework.Assert.assertTrue; 57 import static junit.framework.Assert.fail; 58 59 import static org.mockito.Matchers.anyBoolean; 60 import static org.mockito.Matchers.anyLong; 61 import static org.mockito.Matchers.anyString; 62 import static org.mockito.Matchers.eq; 63 import static org.mockito.Mockito.any; 64 import static org.mockito.Mockito.anyInt; 65 import static org.mockito.Mockito.doAnswer; 66 import static org.mockito.Mockito.doNothing; 67 import static org.mockito.Mockito.mock; 68 import static org.mockito.Mockito.never; 69 import static org.mockito.Mockito.reset; 70 import static org.mockito.Mockito.spy; 71 import static org.mockito.Mockito.timeout; 72 import static org.mockito.Mockito.times; 73 import static org.mockito.Mockito.verify; 74 import static org.mockito.Mockito.when; 75 76 import android.app.ActivityManager; 77 import android.app.AppOpsManager; 78 import android.app.AutomaticZenRule; 79 import android.app.IActivityManager; 80 import android.app.INotificationManager; 81 import android.app.ITransientNotification; 82 import android.app.IUriGrantsManager; 83 import android.app.Notification; 84 import android.app.Notification.MessagingStyle.Message; 85 import android.app.NotificationChannel; 86 import android.app.NotificationChannelGroup; 87 import android.app.NotificationManager; 88 import android.app.PendingIntent; 89 import android.app.Person; 90 import android.app.RemoteInput; 91 import android.app.admin.DevicePolicyManagerInternal; 92 import android.app.usage.UsageStatsManagerInternal; 93 import android.companion.ICompanionDeviceManager; 94 import android.content.ComponentName; 95 import android.content.ContentUris; 96 import android.content.Context; 97 import android.content.Intent; 98 import android.content.pm.ApplicationInfo; 99 import android.content.pm.IPackageManager; 100 import android.content.pm.PackageManager; 101 import android.content.pm.ParceledListSlice; 102 import android.content.pm.UserInfo; 103 import android.content.res.Resources; 104 import android.graphics.Color; 105 import android.graphics.drawable.Icon; 106 import android.media.AudioManager; 107 import android.net.Uri; 108 import android.os.Binder; 109 import android.os.Build; 110 import android.os.Bundle; 111 import android.os.IBinder; 112 import android.os.Process; 113 import android.os.RemoteException; 114 import android.os.SystemClock; 115 import android.os.UserHandle; 116 import android.os.UserManager; 117 import android.provider.DeviceConfig; 118 import android.provider.MediaStore; 119 import android.provider.Settings; 120 import android.service.notification.Adjustment; 121 import android.service.notification.NotificationListenerService; 122 import android.service.notification.NotificationStats; 123 import android.service.notification.StatusBarNotification; 124 import android.service.notification.ZenPolicy; 125 import android.telephony.TelephonyManager; 126 import android.test.suitebuilder.annotation.SmallTest; 127 import android.testing.AndroidTestingRunner; 128 import android.testing.TestableContext; 129 import android.testing.TestableLooper; 130 import android.testing.TestableLooper.RunWithLooper; 131 import android.testing.TestablePermissions; 132 import android.text.Html; 133 import android.util.ArrayMap; 134 import android.util.ArraySet; 135 import android.util.AtomicFile; 136 137 import androidx.annotation.Nullable; 138 import androidx.test.InstrumentationRegistry; 139 140 import com.android.internal.R; 141 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; 142 import com.android.internal.statusbar.NotificationVisibility; 143 import com.android.server.LocalServices; 144 import com.android.server.SystemService; 145 import com.android.server.UiServiceTestCase; 146 import com.android.server.lights.LightsManager; 147 import com.android.server.lights.LogicalLight; 148 import com.android.server.notification.NotificationManagerService.NotificationAssistants; 149 import com.android.server.notification.NotificationManagerService.NotificationListeners; 150 import com.android.server.uri.UriGrantsManagerInternal; 151 import com.android.server.wm.WindowManagerInternal; 152 153 import org.junit.After; 154 import org.junit.Before; 155 import org.junit.Test; 156 import org.junit.runner.RunWith; 157 import org.mockito.ArgumentCaptor; 158 import org.mockito.Mock; 159 import org.mockito.MockitoAnnotations; 160 import org.mockito.stubbing.Answer; 161 162 import java.io.BufferedInputStream; 163 import java.io.ByteArrayInputStream; 164 import java.io.File; 165 import java.io.FileOutputStream; 166 import java.util.ArrayList; 167 import java.util.Arrays; 168 import java.util.Collections; 169 import java.util.List; 170 import java.util.Map; 171 import java.util.function.Consumer; 172 173 @SmallTest 174 @RunWith(AndroidTestingRunner.class) 175 @RunWithLooper 176 public class NotificationManagerServiceTest extends UiServiceTestCase { 177 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId"; 178 private static final String CLEAR_DEVICE_CONFIG_KEY_CMD = 179 "device_config delete " + DeviceConfig.NAMESPACE_SYSTEMUI + " " 180 + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE; 181 private static final String SET_DEFAULT_ASSISTANT_DEVICE_CONFIG_CMD = 182 "device_config put " + DeviceConfig.NAMESPACE_SYSTEMUI + " " 183 + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE; 184 185 private final int mUid = Binder.getCallingUid(); 186 private TestableNotificationManagerService mService; 187 private INotificationManager mBinderService; 188 private NotificationManagerInternal mInternalService; 189 @Mock 190 private IPackageManager mPackageManager; 191 @Mock 192 private PackageManager mPackageManagerClient; 193 @Mock 194 private WindowManagerInternal mWindowManagerInternal; 195 private TestableContext mContext = spy(getContext()); 196 private final String PKG = mContext.getPackageName(); 197 private TestableLooper mTestableLooper; 198 @Mock 199 private RankingHelper mRankingHelper; 200 @Mock private PreferencesHelper mPreferencesHelper; 201 AtomicFile mPolicyFile; 202 File mFile; 203 @Mock 204 private NotificationUsageStats mUsageStats; 205 @Mock 206 private UsageStatsManagerInternal mAppUsageStats; 207 @Mock 208 private AudioManager mAudioManager; 209 @Mock 210 ActivityManager mActivityManager; 211 NotificationManagerService.WorkerHandler mHandler; 212 @Mock 213 Resources mResources; 214 215 private NotificationChannel mTestNotificationChannel = new NotificationChannel( 216 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 217 218 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0; 219 220 @Mock 221 private NotificationListeners mListeners; 222 @Mock private NotificationAssistants mAssistants; 223 @Mock private ConditionProviders mConditionProviders; 224 private ManagedServices.ManagedServiceInfo mListener; 225 @Mock private ICompanionDeviceManager mCompanionMgr; 226 @Mock SnoozeHelper mSnoozeHelper; 227 @Mock GroupHelper mGroupHelper; 228 @Mock 229 IBinder mPermOwner; 230 @Mock 231 IActivityManager mAm; 232 @Mock 233 IUriGrantsManager mUgm; 234 @Mock 235 UriGrantsManagerInternal mUgmInternal; 236 @Mock 237 AppOpsManager mAppOpsManager; 238 @Mock 239 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback 240 mNotificationAssistantAccessGrantedCallback; 241 @Mock 242 UserManager mUm; 243 244 // Use a Testable subclass so we can simulate calls from the system without failing. 245 private static class TestableNotificationManagerService extends NotificationManagerService { 246 int countSystemChecks = 0; 247 boolean isSystemUid = true; 248 int countLogSmartSuggestionsVisible = 0; 249 @Nullable 250 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback; 251 TestableNotificationManagerService(Context context)252 TestableNotificationManagerService(Context context) { 253 super(context); 254 } 255 256 @Override isCallingUidSystem()257 protected boolean isCallingUidSystem() { 258 countSystemChecks++; 259 return isSystemUid; 260 } 261 262 @Override isCallerSystemOrPhone()263 protected boolean isCallerSystemOrPhone() { 264 countSystemChecks++; 265 return isSystemUid; 266 } 267 268 @Override getCompanionManager()269 protected ICompanionDeviceManager getCompanionManager() { 270 return null; 271 } 272 273 @Override reportUserInteraction(NotificationRecord r)274 protected void reportUserInteraction(NotificationRecord r) { 275 return; 276 } 277 278 @Override handleSavePolicyFile()279 protected void handleSavePolicyFile() { 280 return; 281 } 282 283 @Override logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation)284 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) { 285 super.logSmartSuggestionsVisible(r, notificationLocation); 286 countLogSmartSuggestionsVisible++; 287 } 288 289 @Override setNotificationAssistantAccessGrantedForUserInternal( ComponentName assistant, int userId, boolean granted)290 protected void setNotificationAssistantAccessGrantedForUserInternal( 291 ComponentName assistant, int userId, boolean granted) { 292 if (mNotificationAssistantAccessGrantedCallback != null) { 293 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted); 294 return; 295 } 296 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted); 297 } 298 setNotificationAssistantAccessGrantedCallback( @ullable NotificationAssistantAccessGrantedCallback callback)299 private void setNotificationAssistantAccessGrantedCallback( 300 @Nullable NotificationAssistantAccessGrantedCallback callback) { 301 this.mNotificationAssistantAccessGrantedCallback = callback; 302 } 303 304 interface NotificationAssistantAccessGrantedCallback { onGranted(ComponentName assistant, int userId, boolean granted)305 void onGranted(ComponentName assistant, int userId, boolean granted); 306 } 307 308 @Override canLaunchInActivityView(Context context, PendingIntent pendingIntent, String packageName)309 protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent, 310 String packageName) { 311 // Tests for this not being true are in CTS NotificationManagerTest 312 return true; 313 } 314 } 315 316 private class TestableToastCallback extends ITransientNotification.Stub { 317 @Override show(IBinder windowToken)318 public void show(IBinder windowToken) { 319 } 320 321 @Override hide()322 public void hide() { 323 } 324 } 325 326 @Before setUp()327 public void setUp() throws Exception { 328 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( 329 "android.permission.WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG"); 330 331 MockitoAnnotations.initMocks(this); 332 333 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class); 334 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal); 335 LocalServices.removeServiceForTest(WindowManagerInternal.class); 336 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal); 337 338 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any()); 339 340 mService = new TestableNotificationManagerService(mContext); 341 342 // Use this testable looper. 343 mTestableLooper = TestableLooper.get(this); 344 mHandler = mService.new WorkerHandler(mTestableLooper.getLooper()); 345 // MockPackageManager - default returns ApplicationInfo with matching calling UID 346 mContext.setMockPackageManager(mPackageManagerClient); 347 final ApplicationInfo applicationInfo = new ApplicationInfo(); 348 applicationInfo.uid = mUid; 349 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())) 350 .thenReturn(applicationInfo); 351 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 352 .thenReturn(applicationInfo); 353 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid); 354 final LightsManager mockLightsManager = mock(LightsManager.class); 355 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class)); 356 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); 357 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 358 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner); 359 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG}); 360 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG}); 361 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class)); 362 363 // write to a test file; the system file isn't readable from tests 364 mFile = new File(mContext.getCacheDir(), "test.xml"); 365 mFile.createNewFile(); 366 final String preupgradeXml = "<notification-policy></notification-policy>"; 367 mPolicyFile = new AtomicFile(mFile); 368 FileOutputStream fos = mPolicyFile.startWrite(); 369 fos.write(preupgradeXml.getBytes()); 370 mPolicyFile.finishWrite(fos); 371 372 // Setup managed services 373 mListener = mListeners.new ManagedServiceInfo( 374 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0); 375 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 376 ManagedServices.Config listenerConfig = new ManagedServices.Config(); 377 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS; 378 when(mListeners.getConfig()).thenReturn(listenerConfig); 379 ManagedServices.Config assistantConfig = new ManagedServices.Config(); 380 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS; 381 when(mAssistants.getConfig()).thenReturn(assistantConfig); 382 ManagedServices.Config dndConfig = new ManagedServices.Config(); 383 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS; 384 when(mConditionProviders.getConfig()).thenReturn(dndConfig); 385 386 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true); 387 388 389 mService.init(mTestableLooper.getLooper(), 390 mPackageManager, mPackageManagerClient, mockLightsManager, 391 mListeners, mAssistants, mConditionProviders, 392 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, 393 mGroupHelper, mAm, mAppUsageStats, 394 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal, 395 mAppOpsManager, mUm, mock(TelephonyManager.class)); 396 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); 397 398 mService.setAudioManager(mAudioManager); 399 400 // Tests call directly into the Binder. 401 mBinderService = mService.getBinderService(); 402 mInternalService = mService.getInternalService(); 403 404 mBinderService.createNotificationChannels( 405 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 406 assertNotNull(mBinderService.getNotificationChannel( 407 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID)); 408 } 409 410 @After tearDown()411 public void tearDown() throws Exception { 412 mFile.delete(); 413 clearDeviceConfig(); 414 InstrumentationRegistry.getInstrumentation() 415 .getUiAutomation().dropShellPermissionIdentity(); 416 } 417 waitForIdle()418 public void waitForIdle() { 419 mTestableLooper.processAllMessages(); 420 } 421 setUpPrefsForBubbles(boolean globalEnabled, boolean pkgEnabled, boolean channelEnabled)422 private void setUpPrefsForBubbles(boolean globalEnabled, boolean pkgEnabled, 423 boolean channelEnabled) { 424 mService.setPreferencesHelper(mPreferencesHelper); 425 when(mPreferencesHelper.bubblesEnabled()).thenReturn(globalEnabled); 426 when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(pkgEnabled); 427 when(mPreferencesHelper.getNotificationChannel( 428 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn( 429 mTestNotificationChannel); 430 when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn( 431 mTestNotificationChannel.getImportance()); 432 mTestNotificationChannel.setAllowBubbles(channelEnabled); 433 } 434 generateSbn(String pkg, int uid, long postTime, int userId)435 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) { 436 Notification.Builder nb = new Notification.Builder(mContext, "a") 437 .setContentTitle("foo") 438 .setSmallIcon(android.R.drawable.sym_def_app_icon); 439 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, "tag", uid, 0, 440 nb.build(), new UserHandle(userId), null, postTime); 441 return sbn; 442 } 443 444 generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary)445 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, 446 String groupKey, boolean isSummary) { 447 return generateNotificationRecord(channel, id, groupKey, isSummary, false /* isBubble */); 448 } 449 generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary, boolean isBubble)450 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, 451 String groupKey, boolean isSummary, boolean isBubble) { 452 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 453 .setContentTitle("foo") 454 .setSmallIcon(android.R.drawable.sym_def_app_icon) 455 .setGroup(groupKey) 456 .setGroupSummary(isSummary); 457 if (isBubble) { 458 nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build()); 459 } 460 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0, 461 nb.build(), new UserHandle(mUid), null, 0); 462 return new NotificationRecord(mContext, sbn, channel); 463 } 464 generateNotificationRecord(NotificationChannel channel)465 private NotificationRecord generateNotificationRecord(NotificationChannel channel) { 466 return generateNotificationRecord(channel, null); 467 } 468 generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender)469 private NotificationRecord generateNotificationRecord(NotificationChannel channel, 470 Notification.TvExtender extender) { 471 return generateNotificationRecord(channel, extender, false /* isBubble */); 472 } 473 generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender, boolean isBubble)474 private NotificationRecord generateNotificationRecord(NotificationChannel channel, 475 Notification.TvExtender extender, boolean isBubble) { 476 if (channel == null) { 477 channel = mTestNotificationChannel; 478 } 479 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 480 .setContentTitle("foo") 481 .setSmallIcon(android.R.drawable.sym_def_app_icon); 482 if (extender != null) { 483 nb.extend(extender); 484 } 485 if (isBubble) { 486 nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build()); 487 } 488 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, 489 nb.build(), new UserHandle(mUid), null, 0); 490 return new NotificationRecord(mContext, sbn, channel); 491 } 492 getSignalExtractorSideEffects()493 private Map<String, Answer> getSignalExtractorSideEffects() { 494 Map<String, Answer> answers = new ArrayMap<>(); 495 496 answers.put("override group key", invocationOnMock -> { 497 ((NotificationRecord) invocationOnMock.getArguments()[0]) 498 .setOverrideGroupKey("bananas"); 499 return null; 500 }); 501 answers.put("override people", invocationOnMock -> { 502 ((NotificationRecord) invocationOnMock.getArguments()[0]) 503 .setPeopleOverride(new ArrayList<>()); 504 return null; 505 }); 506 answers.put("snooze criteria", invocationOnMock -> { 507 ((NotificationRecord) invocationOnMock.getArguments()[0]) 508 .setSnoozeCriteria(new ArrayList<>()); 509 return null; 510 }); 511 answers.put("notification channel", invocationOnMock -> { 512 ((NotificationRecord) invocationOnMock.getArguments()[0]) 513 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW)); 514 return null; 515 }); 516 answers.put("badging", invocationOnMock -> { 517 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0]; 518 r.setShowBadge(!r.canShowBadge()); 519 return null; 520 }); 521 answers.put("bubbles", invocationOnMock -> { 522 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0]; 523 r.setAllowBubble(!r.canBubble()); 524 return null; 525 }); 526 answers.put("package visibility", invocationOnMock -> { 527 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride( 528 Notification.VISIBILITY_SECRET); 529 return null; 530 }); 531 532 return answers; 533 } 534 clearDeviceConfig()535 private void clearDeviceConfig() { 536 DeviceConfig.resetToDefaults( 537 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI); 538 } 539 setDefaultAssistantInDeviceConfig(String componentName)540 private void setDefaultAssistantInDeviceConfig(String componentName) { 541 DeviceConfig.setProperty( 542 DeviceConfig.NAMESPACE_SYSTEMUI, 543 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE, 544 componentName, 545 false); 546 } 547 getBasicBubbleMetadataBuilder()548 private Notification.BubbleMetadata.Builder getBasicBubbleMetadataBuilder() { 549 PendingIntent pi = PendingIntent.getActivity(mContext, 0, new Intent(), 0); 550 return new Notification.BubbleMetadata.Builder() 551 .setIntent(pi) 552 .setIcon(Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon)); 553 } 554 addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)555 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel) 556 throws RemoteException { 557 558 // Notification that has bubble metadata 559 NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel, 1, 560 "BUBBLE_GROUP", false /* isSummary */, true /* isBubble */); 561 562 // Make the package foreground so that we're allowed to be a bubble 563 when(mActivityManager.getPackageImportance(nrBubble.sbn.getPackageName())).thenReturn( 564 IMPORTANCE_FOREGROUND); 565 566 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 567 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId()); 568 waitForIdle(); 569 570 // Make sure we are a bubble 571 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 572 assertEquals(1, notifsAfter.length); 573 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0); 574 575 // Plain notification without bubble metadata 576 NotificationRecord nrPlain = generateNotificationRecord(mTestNotificationChannel, 2, 577 "BUBBLE_GROUP", false /* isSummary */, false /* isBubble */); 578 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 579 nrPlain.sbn.getId(), nrPlain.sbn.getNotification(), nrPlain.sbn.getUserId()); 580 waitForIdle(); 581 582 notifsAfter = mBinderService.getActiveNotifications(PKG); 583 assertEquals(2, notifsAfter.length); 584 585 // Summary notification for both of those 586 NotificationRecord nrSummary = generateNotificationRecord(mTestNotificationChannel, 3, 587 "BUBBLE_GROUP", true /* isSummary */, false /* isBubble */); 588 if (summaryAutoCancel) { 589 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL; 590 } 591 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 592 nrSummary.sbn.getId(), nrSummary.sbn.getNotification(), nrSummary.sbn.getUserId()); 593 waitForIdle(); 594 595 notifsAfter = mBinderService.getActiveNotifications(PKG); 596 assertEquals(3, notifsAfter.length); 597 598 return nrSummary; 599 } 600 601 @Test testCreateNotificationChannels_SingleChannel()602 public void testCreateNotificationChannels_SingleChannel() throws Exception { 603 final NotificationChannel channel = 604 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 605 mBinderService.createNotificationChannels(PKG, 606 new ParceledListSlice(Arrays.asList(channel))); 607 final NotificationChannel createdChannel = 608 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 609 assertTrue(createdChannel != null); 610 } 611 612 @Test testCreateNotificationChannels_NullChannelThrowsException()613 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception { 614 try { 615 mBinderService.createNotificationChannels(PKG, 616 new ParceledListSlice(Arrays.asList((Object[])null))); 617 fail("Exception should be thrown immediately."); 618 } catch (NullPointerException e) { 619 // pass 620 } 621 } 622 623 @Test testCreateNotificationChannels_TwoChannels()624 public void testCreateNotificationChannels_TwoChannels() throws Exception { 625 final NotificationChannel channel1 = 626 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT); 627 final NotificationChannel channel2 = 628 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT); 629 mBinderService.createNotificationChannels(PKG, 630 new ParceledListSlice(Arrays.asList(channel1, channel2))); 631 assertTrue(mBinderService.getNotificationChannel( 632 PKG, mContext.getUserId(), PKG, "id1") != null); 633 assertTrue(mBinderService.getNotificationChannel( 634 PKG, mContext.getUserId(), PKG, "id2") != null); 635 } 636 637 @Test testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()638 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance() 639 throws Exception { 640 final NotificationChannel channel = 641 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 642 mBinderService.createNotificationChannels(PKG, 643 new ParceledListSlice(Arrays.asList(channel))); 644 645 // Recreating the channel doesn't throw, but ignores importance. 646 final NotificationChannel dupeChannel = 647 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 648 mBinderService.createNotificationChannels(PKG, 649 new ParceledListSlice(Arrays.asList(dupeChannel))); 650 final NotificationChannel createdChannel = 651 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 652 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); 653 } 654 655 @Test testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()656 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance() 657 throws Exception { 658 final NotificationChannel channel = 659 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 660 mBinderService.createNotificationChannels(PKG, 661 new ParceledListSlice(Arrays.asList(channel))); 662 663 // Recreating with a lower importance is allowed to modify the channel. 664 final NotificationChannel dupeChannel = 665 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); 666 mBinderService.createNotificationChannels(PKG, 667 new ParceledListSlice(Arrays.asList(dupeChannel))); 668 final NotificationChannel createdChannel = 669 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 670 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance()); 671 } 672 673 @Test testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()674 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated() 675 throws Exception { 676 final NotificationChannel channel = 677 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 678 mBinderService.createNotificationChannels(PKG, 679 new ParceledListSlice(Arrays.asList(channel))); 680 681 // The user modifies importance directly, can no longer be changed by the app. 682 final NotificationChannel updatedChannel = 683 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 684 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel); 685 686 // Recreating with a lower importance leaves channel unchanged. 687 final NotificationChannel dupeChannel = 688 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); 689 mBinderService.createNotificationChannels(PKG, 690 new ParceledListSlice(Arrays.asList(dupeChannel))); 691 final NotificationChannel createdChannel = 692 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 693 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance()); 694 } 695 696 @Test testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()697 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond() 698 throws Exception { 699 final NotificationChannel channel1 = 700 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 701 final NotificationChannel channel2 = 702 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 703 mBinderService.createNotificationChannels(PKG, 704 new ParceledListSlice(Arrays.asList(channel1, channel2))); 705 final NotificationChannel createdChannel = 706 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 707 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); 708 } 709 710 @Test testBlockedNotifications_suspended()711 public void testBlockedNotifications_suspended() throws Exception { 712 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true); 713 714 NotificationChannel channel = new NotificationChannel("id", "name", 715 IMPORTANCE_HIGH); 716 NotificationRecord r = generateNotificationRecord(channel); 717 718 // isBlocked is only used for user blocking, not app suspension 719 assertFalse(mService.isBlocked(r, mUsageStats)); 720 } 721 722 @Test testBlockedNotifications_blockedChannel()723 public void testBlockedNotifications_blockedChannel() throws Exception { 724 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 725 726 NotificationChannel channel = new NotificationChannel("id", "name", 727 NotificationManager.IMPORTANCE_NONE); 728 NotificationRecord r = generateNotificationRecord(channel); 729 assertTrue(mService.isBlocked(r, mUsageStats)); 730 verify(mUsageStats, times(1)).registerBlocked(eq(r)); 731 732 mBinderService.createNotificationChannels( 733 PKG, new ParceledListSlice(Arrays.asList(channel))); 734 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn; 735 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 736 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 737 waitForIdle(); 738 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 739 } 740 741 @Test testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()742 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService() 743 throws Exception { 744 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 745 746 NotificationChannel channel = new NotificationChannel("blocked", "name", 747 NotificationManager.IMPORTANCE_NONE); 748 mBinderService.createNotificationChannels( 749 PKG, new ParceledListSlice(Arrays.asList(channel))); 750 751 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn; 752 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 753 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 754 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 755 waitForIdle(); 756 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 757 assertEquals(IMPORTANCE_LOW, 758 mService.getNotificationRecord(sbn.getKey()).getImportance()); 759 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel( 760 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 761 } 762 763 @Test testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()764 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService() 765 throws Exception { 766 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 767 768 NotificationChannel channel = 769 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH); 770 mBinderService.createNotificationChannels( 771 PKG, new ParceledListSlice(Arrays.asList(channel))); 772 773 NotificationChannel update = 774 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); 775 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); 776 waitForIdle(); 777 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 778 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 779 780 StatusBarNotification sbn = generateNotificationRecord(channel).sbn; 781 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 782 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 783 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 784 waitForIdle(); 785 // The first time a foreground service notification is shown, we allow the channel 786 // to be updated to allow it to be seen. 787 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 788 assertEquals(IMPORTANCE_LOW, 789 mService.getNotificationRecord(sbn.getKey()).getImportance()); 790 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel( 791 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 792 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId()); 793 waitForIdle(); 794 795 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); 796 update.setFgServiceShown(true); 797 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); 798 waitForIdle(); 799 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 800 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 801 802 sbn = generateNotificationRecord(channel).sbn; 803 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 804 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 805 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 806 waitForIdle(); 807 // The second time it is shown, we keep the user's preference. 808 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 809 assertNull(mService.getNotificationRecord(sbn.getKey())); 810 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 811 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 812 } 813 814 @Test testBlockedNotifications_blockedChannelGroup()815 public void testBlockedNotifications_blockedChannelGroup() throws Exception { 816 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 817 mService.setPreferencesHelper(mPreferencesHelper); 818 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).thenReturn(true); 819 820 NotificationChannel channel = new NotificationChannel("id", "name", 821 NotificationManager.IMPORTANCE_HIGH); 822 channel.setGroup("something"); 823 NotificationRecord r = generateNotificationRecord(channel); 824 assertTrue(mService.isBlocked(r, mUsageStats)); 825 verify(mUsageStats, times(1)).registerBlocked(eq(r)); 826 } 827 828 @Test testEnqueuedBlockedNotifications_blockedApp()829 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception { 830 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 831 832 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); 833 834 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 835 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 836 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 837 waitForIdle(); 838 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 839 } 840 841 @Test testEnqueuedBlockedNotifications_blockedAppForegroundService()842 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception { 843 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 844 845 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); 846 847 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 848 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 849 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 850 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 851 waitForIdle(); 852 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 853 assertNull(mService.getNotificationRecord(sbn.getKey())); 854 } 855 856 /** 857 * Confirm the system user on automotive devices can use car categories 858 */ 859 @Test testEnqueuedRestrictedNotifications_asSystem()860 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception { 861 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 862 .thenReturn(true); 863 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 864 Notification.CATEGORY_CAR_WARNING, 865 Notification.CATEGORY_CAR_INFORMATION); 866 int id = 0; 867 for (String category: categories) { 868 final StatusBarNotification sbn = 869 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn; 870 sbn.getNotification().category = category; 871 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 872 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 873 } 874 waitForIdle(); 875 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length); 876 } 877 878 879 /** 880 * Confirm restricted notification categories only apply to automotive. 881 */ 882 @Test testEnqueuedRestrictedNotifications_notAutomotive()883 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception { 884 mService.isSystemUid = false; 885 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 886 .thenReturn(false); 887 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 888 Notification.CATEGORY_CAR_WARNING, 889 Notification.CATEGORY_CAR_INFORMATION); 890 int id = 0; 891 for (String category: categories) { 892 final StatusBarNotification sbn = 893 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn; 894 sbn.getNotification().category = category; 895 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 896 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 897 } 898 waitForIdle(); 899 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length); 900 } 901 902 /** 903 * Confirm if a non-system user tries to use the car categories on a automotive device that 904 * they will get a security exception 905 */ 906 @Test testEnqueuedRestrictedNotifications_badUser()907 public void testEnqueuedRestrictedNotifications_badUser() throws Exception { 908 mService.isSystemUid = false; 909 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 910 .thenReturn(true); 911 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 912 Notification.CATEGORY_CAR_WARNING, 913 Notification.CATEGORY_CAR_INFORMATION); 914 for (String category: categories) { 915 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 916 sbn.getNotification().category = category; 917 try { 918 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 919 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 920 fail("Calls from non system apps should not allow use of restricted categories"); 921 } catch (SecurityException e) { 922 // pass 923 } 924 } 925 waitForIdle(); 926 assertEquals(0, mBinderService.getActiveNotifications(PKG).length); 927 } 928 929 @Test testBlockedNotifications_blockedByAssistant()930 public void testBlockedNotifications_blockedByAssistant() throws Exception { 931 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 932 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 933 934 NotificationChannel channel = new NotificationChannel("id", "name", 935 NotificationManager.IMPORTANCE_HIGH); 936 NotificationRecord r = generateNotificationRecord(channel); 937 mService.addEnqueuedNotification(r); 938 939 Bundle bundle = new Bundle(); 940 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE); 941 Adjustment adjustment = new Adjustment( 942 r.sbn.getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier()); 943 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 944 945 NotificationManagerService.PostNotificationRunnable runnable = 946 mService.new PostNotificationRunnable(r.getKey()); 947 runnable.run(); 948 waitForIdle(); 949 950 verify(mUsageStats, never()).registerPostedByApp(any()); 951 } 952 953 @Test testEnqueueNotificationWithTag_PopulatesGetActiveNotifications()954 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception { 955 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, 956 generateNotificationRecord(null).getNotification(), 0); 957 waitForIdle(); 958 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 959 assertEquals(1, notifs.length); 960 assertEquals(1, mService.getNotificationRecordCount()); 961 } 962 963 @Test testCancelNotificationImmediatelyAfterEnqueue()964 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception { 965 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, 966 generateNotificationRecord(null).getNotification(), 0); 967 mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0); 968 waitForIdle(); 969 StatusBarNotification[] notifs = 970 mBinderService.getActiveNotifications(PKG); 971 assertEquals(0, notifs.length); 972 assertEquals(0, mService.getNotificationRecordCount()); 973 } 974 975 @Test testCancelNotificationWhilePostedAndEnqueued()976 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception { 977 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, 978 generateNotificationRecord(null).getNotification(), 0); 979 waitForIdle(); 980 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, 981 generateNotificationRecord(null).getNotification(), 0); 982 mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0); 983 waitForIdle(); 984 StatusBarNotification[] notifs = 985 mBinderService.getActiveNotifications(PKG); 986 assertEquals(0, notifs.length); 987 assertEquals(0, mService.getNotificationRecordCount()); 988 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 989 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture()); 990 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface()); 991 } 992 993 @Test testCancelNotificationsFromListenerImmediatelyAfterEnqueue()994 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception { 995 NotificationRecord r = generateNotificationRecord(null); 996 final StatusBarNotification sbn = r.sbn; 997 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 998 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 999 mBinderService.cancelNotificationsFromListener(null, null); 1000 waitForIdle(); 1001 StatusBarNotification[] notifs = 1002 mBinderService.getActiveNotifications(sbn.getPackageName()); 1003 assertEquals(0, notifs.length); 1004 assertEquals(0, mService.getNotificationRecordCount()); 1005 } 1006 1007 @Test testCancelAllNotificationsImmediatelyAfterEnqueue()1008 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception { 1009 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1010 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1011 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1012 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 1013 waitForIdle(); 1014 StatusBarNotification[] notifs = 1015 mBinderService.getActiveNotifications(sbn.getPackageName()); 1016 assertEquals(0, notifs.length); 1017 assertEquals(0, mService.getNotificationRecordCount()); 1018 } 1019 1020 @Test testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()1021 public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag() 1022 throws Exception { 1023 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1024 sbn.getNotification().flags = 1025 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; 1026 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1027 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1028 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId()); 1029 waitForIdle(); 1030 verify(mListeners, times(1)).notifyPostedLocked(any(), any()); 1031 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any()); 1032 } 1033 1034 @Test testUserInitiatedClearAll_noLeak()1035 public void testUserInitiatedClearAll_noLeak() throws Exception { 1036 final NotificationRecord n = generateNotificationRecord( 1037 mTestNotificationChannel, 1, "group", true); 1038 1039 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1040 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId()); 1041 waitForIdle(); 1042 1043 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1044 n.getUserId()); 1045 waitForIdle(); 1046 StatusBarNotification[] notifs = 1047 mBinderService.getActiveNotifications(n.sbn.getPackageName()); 1048 assertEquals(0, notifs.length); 1049 assertEquals(0, mService.getNotificationRecordCount()); 1050 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 1051 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture()); 1052 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface()); 1053 } 1054 1055 @Test testCancelAllNotificationsCancelsChildren()1056 public void testCancelAllNotificationsCancelsChildren() throws Exception { 1057 final NotificationRecord parent = generateNotificationRecord( 1058 mTestNotificationChannel, 1, "group1", true); 1059 final NotificationRecord child = generateNotificationRecord( 1060 mTestNotificationChannel, 2, "group1", false); 1061 1062 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1063 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId()); 1064 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1065 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId()); 1066 waitForIdle(); 1067 1068 mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId()); 1069 waitForIdle(); 1070 assertEquals(0, mService.getNotificationRecordCount()); 1071 } 1072 1073 @Test testCancelAllNotificationsMultipleEnqueuedDoesNotCrash()1074 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception { 1075 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1076 for (int i = 0; i < 10; i++) { 1077 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1078 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1079 } 1080 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 1081 waitForIdle(); 1082 1083 assertEquals(0, mService.getNotificationRecordCount()); 1084 } 1085 1086 @Test testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash()1087 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception { 1088 final NotificationRecord parent = generateNotificationRecord( 1089 mTestNotificationChannel, 1, "group1", true); 1090 final NotificationRecord parentAsChild = generateNotificationRecord( 1091 mTestNotificationChannel, 1, "group1", false); 1092 final NotificationRecord child = generateNotificationRecord( 1093 mTestNotificationChannel, 2, "group1", false); 1094 1095 // fully post parent notification 1096 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1097 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId()); 1098 waitForIdle(); 1099 1100 // enqueue the child several times 1101 for (int i = 0; i < 10; i++) { 1102 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1103 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId()); 1104 } 1105 // make the parent a child, which will cancel the child notification 1106 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1107 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(), 1108 parentAsChild.sbn.getUserId()); 1109 waitForIdle(); 1110 1111 assertEquals(0, mService.getNotificationRecordCount()); 1112 } 1113 1114 @Test testCancelAllNotifications_IgnoreForegroundService()1115 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception { 1116 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1117 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1118 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1119 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1120 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 1121 waitForIdle(); 1122 StatusBarNotification[] notifs = 1123 mBinderService.getActiveNotifications(sbn.getPackageName()); 1124 assertEquals(1, notifs.length); 1125 assertEquals(1, mService.getNotificationRecordCount()); 1126 } 1127 1128 @Test testCancelAllNotifications_IgnoreOtherPackages()1129 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception { 1130 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1131 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1132 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1133 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1134 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId()); 1135 waitForIdle(); 1136 StatusBarNotification[] notifs = 1137 mBinderService.getActiveNotifications(sbn.getPackageName()); 1138 assertEquals(1, notifs.length); 1139 assertEquals(1, mService.getNotificationRecordCount()); 1140 } 1141 1142 @Test testCancelAllNotifications_NullPkgRemovesAll()1143 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception { 1144 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1145 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1146 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1147 mBinderService.cancelAllNotifications(null, sbn.getUserId()); 1148 waitForIdle(); 1149 StatusBarNotification[] notifs = 1150 mBinderService.getActiveNotifications(sbn.getPackageName()); 1151 assertEquals(0, notifs.length); 1152 assertEquals(0, mService.getNotificationRecordCount()); 1153 } 1154 1155 @Test testCancelAllNotifications_NullPkgIgnoresUserAllNotifications()1156 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception { 1157 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1158 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1159 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL); 1160 // Null pkg is how we signal a user switch. 1161 mBinderService.cancelAllNotifications(null, sbn.getUserId()); 1162 waitForIdle(); 1163 StatusBarNotification[] notifs = 1164 mBinderService.getActiveNotifications(sbn.getPackageName()); 1165 assertEquals(1, notifs.length); 1166 assertEquals(1, mService.getNotificationRecordCount()); 1167 } 1168 1169 @Test testAppInitiatedCancelAllNotifications_CancelsNoClearFlag()1170 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception { 1171 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1172 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1173 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1174 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1175 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 1176 waitForIdle(); 1177 StatusBarNotification[] notifs = 1178 mBinderService.getActiveNotifications(sbn.getPackageName()); 1179 assertEquals(0, notifs.length); 1180 } 1181 1182 @Test testCancelAllNotifications_CancelsNoClearFlag()1183 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception { 1184 final NotificationRecord notif = generateNotificationRecord( 1185 mTestNotificationChannel, 1, "group", true); 1186 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1187 mService.addNotification(notif); 1188 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true, 1189 notif.getUserId(), 0, null); 1190 waitForIdle(); 1191 StatusBarNotification[] notifs = 1192 mBinderService.getActiveNotifications(notif.sbn.getPackageName()); 1193 assertEquals(0, notifs.length); 1194 } 1195 1196 @Test testUserInitiatedCancelAllOnClearAll_NoClearFlag()1197 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception { 1198 final NotificationRecord notif = generateNotificationRecord( 1199 mTestNotificationChannel, 1, "group", true); 1200 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1201 mService.addNotification(notif); 1202 1203 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1204 notif.getUserId()); 1205 waitForIdle(); 1206 StatusBarNotification[] notifs = 1207 mBinderService.getActiveNotifications(notif.sbn.getPackageName()); 1208 assertEquals(1, notifs.length); 1209 } 1210 1211 @Test testCancelAllCancelNotificationsFromListener_NoClearFlag()1212 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception { 1213 final NotificationRecord parent = generateNotificationRecord( 1214 mTestNotificationChannel, 1, "group", true); 1215 final NotificationRecord child = generateNotificationRecord( 1216 mTestNotificationChannel, 2, "group", false); 1217 final NotificationRecord child2 = generateNotificationRecord( 1218 mTestNotificationChannel, 3, "group", false); 1219 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1220 final NotificationRecord newGroup = generateNotificationRecord( 1221 mTestNotificationChannel, 4, "group2", false); 1222 mService.addNotification(parent); 1223 mService.addNotification(child); 1224 mService.addNotification(child2); 1225 mService.addNotification(newGroup); 1226 mService.getBinderService().cancelNotificationsFromListener(null, null); 1227 waitForIdle(); 1228 StatusBarNotification[] notifs = 1229 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1230 assertEquals(1, notifs.length); 1231 } 1232 1233 @Test testUserInitiatedCancelAllWithGroup_NoClearFlag()1234 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception { 1235 final NotificationRecord parent = generateNotificationRecord( 1236 mTestNotificationChannel, 1, "group", true); 1237 final NotificationRecord child = generateNotificationRecord( 1238 mTestNotificationChannel, 2, "group", false); 1239 final NotificationRecord child2 = generateNotificationRecord( 1240 mTestNotificationChannel, 3, "group", false); 1241 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1242 final NotificationRecord newGroup = generateNotificationRecord( 1243 mTestNotificationChannel, 4, "group2", false); 1244 mService.addNotification(parent); 1245 mService.addNotification(child); 1246 mService.addNotification(child2); 1247 mService.addNotification(newGroup); 1248 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1249 parent.getUserId()); 1250 waitForIdle(); 1251 StatusBarNotification[] notifs = 1252 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1253 assertEquals(1, notifs.length); 1254 } 1255 1256 @Test testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue()1257 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception { 1258 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1259 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1260 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 1261 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1262 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(), 1263 sbn.getUserId()); 1264 waitForIdle(); 1265 StatusBarNotification[] notifs = 1266 mBinderService.getActiveNotifications(sbn.getPackageName()); 1267 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE); 1268 } 1269 1270 @Test testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag()1271 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception { 1272 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1273 sbn.getNotification().flags = 1274 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; 1275 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1276 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1277 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT; 1278 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1279 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1280 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId()); 1281 waitForIdle(); 1282 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1283 assertEquals(0, mService.getNotificationRecordCount()); 1284 } 1285 1286 @Test testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()1287 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag() 1288 throws Exception { 1289 final NotificationRecord parent = generateNotificationRecord( 1290 mTestNotificationChannel, 1, "group", true); 1291 final NotificationRecord child = generateNotificationRecord( 1292 mTestNotificationChannel, 2, "group", false); 1293 final NotificationRecord child2 = generateNotificationRecord( 1294 mTestNotificationChannel, 3, "group", false); 1295 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1296 final NotificationRecord newGroup = generateNotificationRecord( 1297 mTestNotificationChannel, 4, "group2", false); 1298 mService.addNotification(parent); 1299 mService.addNotification(child); 1300 mService.addNotification(child2); 1301 mService.addNotification(newGroup); 1302 mService.getBinderService().cancelNotificationsFromListener(null, null); 1303 waitForIdle(); 1304 StatusBarNotification[] notifs = 1305 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1306 assertEquals(0, notifs.length); 1307 } 1308 1309 @Test testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()1310 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter() 1311 throws Exception { 1312 final NotificationRecord parent = generateNotificationRecord( 1313 mTestNotificationChannel, 1, "group", true); 1314 final NotificationRecord child = generateNotificationRecord( 1315 mTestNotificationChannel, 2, "group", false); 1316 final NotificationRecord child2 = generateNotificationRecord( 1317 mTestNotificationChannel, 3, "group", false); 1318 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1319 final NotificationRecord newGroup = generateNotificationRecord( 1320 mTestNotificationChannel, 4, "group2", false); 1321 mService.addNotification(parent); 1322 mService.addNotification(child); 1323 mService.addNotification(child2); 1324 mService.addNotification(newGroup); 1325 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(), 1326 child2.sbn.getKey(), newGroup.sbn.getKey()}; 1327 mService.getBinderService().cancelNotificationsFromListener(null, keys); 1328 waitForIdle(); 1329 StatusBarNotification[] notifs = 1330 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1331 assertEquals(1, notifs.length); 1332 } 1333 1334 @Test testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag()1335 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception { 1336 final NotificationRecord parent = generateNotificationRecord( 1337 mTestNotificationChannel, 1, "group", true); 1338 final NotificationRecord child = generateNotificationRecord( 1339 mTestNotificationChannel, 2, "group", false); 1340 final NotificationRecord child2 = generateNotificationRecord( 1341 mTestNotificationChannel, 3, "group", false); 1342 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1343 final NotificationRecord newGroup = generateNotificationRecord( 1344 mTestNotificationChannel, 4, "group2", false); 1345 mService.addNotification(parent); 1346 mService.addNotification(child); 1347 mService.addNotification(child2); 1348 mService.addNotification(newGroup); 1349 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1350 parent.getUserId()); 1351 waitForIdle(); 1352 StatusBarNotification[] notifs = 1353 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1354 assertEquals(0, notifs.length); 1355 } 1356 1357 @Test testFindGroupNotificationsLocked()1358 public void testFindGroupNotificationsLocked() throws Exception { 1359 // make sure the same notification can be found in both lists and returned 1360 final NotificationRecord group1 = generateNotificationRecord( 1361 mTestNotificationChannel, 1, "group1", true); 1362 mService.addEnqueuedNotification(group1); 1363 mService.addNotification(group1); 1364 1365 // should not be returned 1366 final NotificationRecord group2 = generateNotificationRecord( 1367 mTestNotificationChannel, 2, "group2", true); 1368 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 1369 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId()); 1370 waitForIdle(); 1371 1372 // should not be returned 1373 final NotificationRecord nonGroup = generateNotificationRecord( 1374 mTestNotificationChannel, 3, null, false); 1375 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 1376 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId()); 1377 waitForIdle(); 1378 1379 // same group, child, should be returned 1380 final NotificationRecord group1Child = generateNotificationRecord( 1381 mTestNotificationChannel, 4, "group1", false); 1382 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, group1Child.sbn.getId(), 1383 group1Child.sbn.getNotification(), group1Child.sbn.getUserId()); 1384 waitForIdle(); 1385 1386 List<NotificationRecord> inGroup1 = 1387 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(), 1388 group1.sbn.getUserId()); 1389 assertEquals(3, inGroup1.size()); 1390 for (NotificationRecord record : inGroup1) { 1391 assertTrue(record.getGroupKey().equals(group1.getGroupKey())); 1392 assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4); 1393 } 1394 } 1395 1396 @Test testCancelAllNotifications_CancelsNoClearFlagOnGoing()1397 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception { 1398 final NotificationRecord notif = generateNotificationRecord( 1399 mTestNotificationChannel, 1, "group", true); 1400 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1401 mService.addNotification(notif); 1402 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 1403 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null); 1404 waitForIdle(); 1405 StatusBarNotification[] notifs = 1406 mBinderService.getActiveNotifications(notif.sbn.getPackageName()); 1407 assertEquals(0, notifs.length); 1408 } 1409 1410 @Test testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()1411 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter() 1412 throws Exception { 1413 final NotificationRecord parent = generateNotificationRecord( 1414 mTestNotificationChannel, 1, "group", true); 1415 final NotificationRecord child = generateNotificationRecord( 1416 mTestNotificationChannel, 2, "group", false); 1417 final NotificationRecord child2 = generateNotificationRecord( 1418 mTestNotificationChannel, 3, "group", false); 1419 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1420 final NotificationRecord newGroup = generateNotificationRecord( 1421 mTestNotificationChannel, 4, "group2", false); 1422 mService.addNotification(parent); 1423 mService.addNotification(child); 1424 mService.addNotification(child2); 1425 mService.addNotification(newGroup); 1426 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(), 1427 child2.sbn.getKey(), newGroup.sbn.getKey()}; 1428 mService.getBinderService().cancelNotificationsFromListener(null, keys); 1429 waitForIdle(); 1430 StatusBarNotification[] notifs = 1431 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1432 assertEquals(0, notifs.length); 1433 } 1434 1435 @Test testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag()1436 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception { 1437 final StatusBarNotification sbn = generateNotificationRecord(null).sbn; 1438 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1439 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1440 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1441 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 1442 waitForIdle(); 1443 StatusBarNotification[] notifs = 1444 mBinderService.getActiveNotifications(sbn.getPackageName()); 1445 assertEquals(0, notifs.length); 1446 } 1447 1448 @Test testCancelAllNotifications_CancelsOnGoingFlag()1449 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception { 1450 final NotificationRecord notif = generateNotificationRecord( 1451 mTestNotificationChannel, 1, "group", true); 1452 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1453 mService.addNotification(notif); 1454 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true, 1455 notif.getUserId(), 0, null); 1456 waitForIdle(); 1457 StatusBarNotification[] notifs = 1458 mBinderService.getActiveNotifications(notif.sbn.getPackageName()); 1459 assertEquals(0, notifs.length); 1460 } 1461 1462 @Test testUserInitiatedCancelAllOnClearAll_OnGoingFlag()1463 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception { 1464 final NotificationRecord notif = generateNotificationRecord( 1465 mTestNotificationChannel, 1, "group", true); 1466 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1467 mService.addNotification(notif); 1468 1469 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1470 notif.getUserId()); 1471 waitForIdle(); 1472 StatusBarNotification[] notifs = 1473 mBinderService.getActiveNotifications(notif.sbn.getPackageName()); 1474 assertEquals(1, notifs.length); 1475 } 1476 1477 @Test testCancelAllCancelNotificationsFromListener_OnGoingFlag()1478 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception { 1479 final NotificationRecord parent = generateNotificationRecord( 1480 mTestNotificationChannel, 1, "group", true); 1481 final NotificationRecord child = generateNotificationRecord( 1482 mTestNotificationChannel, 2, "group", false); 1483 final NotificationRecord child2 = generateNotificationRecord( 1484 mTestNotificationChannel, 3, "group", false); 1485 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1486 final NotificationRecord newGroup = generateNotificationRecord( 1487 mTestNotificationChannel, 4, "group2", false); 1488 mService.addNotification(parent); 1489 mService.addNotification(child); 1490 mService.addNotification(child2); 1491 mService.addNotification(newGroup); 1492 mService.getBinderService().cancelNotificationsFromListener(null, null); 1493 waitForIdle(); 1494 StatusBarNotification[] notifs = 1495 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1496 assertEquals(1, notifs.length); 1497 } 1498 1499 @Test testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()1500 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter() 1501 throws Exception { 1502 final NotificationRecord parent = generateNotificationRecord( 1503 mTestNotificationChannel, 1, "group", true); 1504 final NotificationRecord child = generateNotificationRecord( 1505 mTestNotificationChannel, 2, "group", false); 1506 final NotificationRecord child2 = generateNotificationRecord( 1507 mTestNotificationChannel, 3, "group", false); 1508 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1509 final NotificationRecord newGroup = generateNotificationRecord( 1510 mTestNotificationChannel, 4, "group2", false); 1511 mService.addNotification(parent); 1512 mService.addNotification(child); 1513 mService.addNotification(child2); 1514 mService.addNotification(newGroup); 1515 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(), 1516 child2.sbn.getKey(), newGroup.sbn.getKey()}; 1517 mService.getBinderService().cancelNotificationsFromListener(null, keys); 1518 waitForIdle(); 1519 StatusBarNotification[] notifs = 1520 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1521 assertEquals(0, notifs.length); 1522 } 1523 1524 @Test testUserInitiatedCancelAllWithGroup_OnGoingFlag()1525 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception { 1526 final NotificationRecord parent = generateNotificationRecord( 1527 mTestNotificationChannel, 1, "group", true); 1528 final NotificationRecord child = generateNotificationRecord( 1529 mTestNotificationChannel, 2, "group", false); 1530 final NotificationRecord child2 = generateNotificationRecord( 1531 mTestNotificationChannel, 3, "group", false); 1532 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1533 final NotificationRecord newGroup = generateNotificationRecord( 1534 mTestNotificationChannel, 4, "group2", false); 1535 mService.addNotification(parent); 1536 mService.addNotification(child); 1537 mService.addNotification(child2); 1538 mService.addNotification(newGroup); 1539 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1540 parent.getUserId()); 1541 waitForIdle(); 1542 StatusBarNotification[] notifs = 1543 mBinderService.getActiveNotifications(parent.sbn.getPackageName()); 1544 assertEquals(1, notifs.length); 1545 } 1546 1547 @Test testTvExtenderChannelOverride_onTv()1548 public void testTvExtenderChannelOverride_onTv() throws Exception { 1549 mService.setIsTelevision(true); 1550 mService.setPreferencesHelper(mPreferencesHelper); 1551 when(mPreferencesHelper.getNotificationChannel( 1552 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn( 1553 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH)); 1554 1555 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); 1556 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, 1557 generateNotificationRecord(null, tv).getNotification(), 0); 1558 verify(mPreferencesHelper, times(1)).getNotificationChannel( 1559 anyString(), anyInt(), eq("foo"), anyBoolean()); 1560 } 1561 1562 @Test testTvExtenderChannelOverride_notOnTv()1563 public void testTvExtenderChannelOverride_notOnTv() throws Exception { 1564 mService.setIsTelevision(false); 1565 mService.setPreferencesHelper(mPreferencesHelper); 1566 when(mPreferencesHelper.getNotificationChannel( 1567 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn( 1568 mTestNotificationChannel); 1569 1570 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); 1571 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, 1572 generateNotificationRecord(null, tv).getNotification(), 0); 1573 verify(mPreferencesHelper, times(1)).getNotificationChannel( 1574 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean()); 1575 } 1576 1577 @Test testUpdateAppNotifyCreatorBlock()1578 public void testUpdateAppNotifyCreatorBlock() throws Exception { 1579 mService.setPreferencesHelper(mPreferencesHelper); 1580 1581 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true); 1582 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1583 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1584 1585 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED, 1586 captor.getValue().getAction()); 1587 assertEquals(PKG, captor.getValue().getPackage()); 1588 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true)); 1589 } 1590 1591 @Test testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting()1592 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception { 1593 mService.setPreferencesHelper(mPreferencesHelper); 1594 1595 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false); 1596 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 1597 } 1598 1599 @Test testUpdateAppNotifyCreatorUnblock()1600 public void testUpdateAppNotifyCreatorUnblock() throws Exception { 1601 mService.setPreferencesHelper(mPreferencesHelper); 1602 1603 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true); 1604 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1605 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1606 1607 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED, 1608 captor.getValue().getAction()); 1609 assertEquals(PKG, captor.getValue().getPackage()); 1610 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true)); 1611 } 1612 1613 @Test testUpdateChannelNotifyCreatorBlock()1614 public void testUpdateChannelNotifyCreatorBlock() throws Exception { 1615 mService.setPreferencesHelper(mPreferencesHelper); 1616 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 1617 eq(mTestNotificationChannel.getId()), anyBoolean())) 1618 .thenReturn(mTestNotificationChannel); 1619 1620 NotificationChannel updatedChannel = 1621 new NotificationChannel(mTestNotificationChannel.getId(), 1622 mTestNotificationChannel.getName(), IMPORTANCE_NONE); 1623 1624 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel); 1625 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1626 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1627 1628 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, 1629 captor.getValue().getAction()); 1630 assertEquals(PKG, captor.getValue().getPackage()); 1631 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra( 1632 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID)); 1633 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 1634 } 1635 1636 @Test testUpdateChannelNotifyCreatorUnblock()1637 public void testUpdateChannelNotifyCreatorUnblock() throws Exception { 1638 NotificationChannel existingChannel = 1639 new NotificationChannel(mTestNotificationChannel.getId(), 1640 mTestNotificationChannel.getName(), IMPORTANCE_NONE); 1641 mService.setPreferencesHelper(mPreferencesHelper); 1642 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 1643 eq(mTestNotificationChannel.getId()), anyBoolean())) 1644 .thenReturn(existingChannel); 1645 1646 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 1647 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1648 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1649 1650 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, 1651 captor.getValue().getAction()); 1652 assertEquals(PKG, captor.getValue().getPackage()); 1653 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra( 1654 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID)); 1655 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 1656 } 1657 1658 @Test testUpdateChannelNoNotifyCreatorOtherChanges()1659 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception { 1660 NotificationChannel existingChannel = 1661 new NotificationChannel(mTestNotificationChannel.getId(), 1662 mTestNotificationChannel.getName(), IMPORTANCE_MAX); 1663 mService.setPreferencesHelper(mPreferencesHelper); 1664 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 1665 eq(mTestNotificationChannel.getId()), anyBoolean())) 1666 .thenReturn(existingChannel); 1667 1668 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 1669 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 1670 } 1671 1672 @Test testUpdateGroupNotifyCreatorBlock()1673 public void testUpdateGroupNotifyCreatorBlock() throws Exception { 1674 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 1675 mService.setPreferencesHelper(mPreferencesHelper); 1676 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt())) 1677 .thenReturn(existing); 1678 1679 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name"); 1680 updated.setBlocked(true); 1681 1682 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated); 1683 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1684 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1685 1686 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED, 1687 captor.getValue().getAction()); 1688 assertEquals(PKG, captor.getValue().getPackage()); 1689 assertEquals(existing.getId(), captor.getValue().getStringExtra( 1690 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID)); 1691 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 1692 } 1693 1694 @Test testUpdateGroupNotifyCreatorUnblock()1695 public void testUpdateGroupNotifyCreatorUnblock() throws Exception { 1696 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 1697 existing.setBlocked(true); 1698 mService.setPreferencesHelper(mPreferencesHelper); 1699 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt())) 1700 .thenReturn(existing); 1701 1702 mBinderService.updateNotificationChannelGroupForPackage( 1703 PKG, 0, new NotificationChannelGroup("id", "name")); 1704 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 1705 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 1706 1707 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED, 1708 captor.getValue().getAction()); 1709 assertEquals(PKG, captor.getValue().getPackage()); 1710 assertEquals(existing.getId(), captor.getValue().getStringExtra( 1711 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID)); 1712 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 1713 } 1714 1715 @Test testUpdateGroupNoNotifyCreatorOtherChanges()1716 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception { 1717 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 1718 mService.setPreferencesHelper(mPreferencesHelper); 1719 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt())) 1720 .thenReturn(existing); 1721 1722 mBinderService.updateNotificationChannelGroupForPackage( 1723 PKG, 0, new NotificationChannelGroup("id", "new name")); 1724 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 1725 } 1726 1727 @Test testCreateChannelNotifyListener()1728 public void testCreateChannelNotifyListener() throws Exception { 1729 List<String> associations = new ArrayList<>(); 1730 associations.add("a"); 1731 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1732 mService.setPreferencesHelper(mPreferencesHelper); 1733 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 1734 eq(mTestNotificationChannel.getId()), anyBoolean())) 1735 .thenReturn(mTestNotificationChannel); 1736 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW); 1737 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 1738 eq(channel2.getId()), anyBoolean())) 1739 .thenReturn(channel2); 1740 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(), 1741 eq(channel2), anyBoolean(), anyBoolean())) 1742 .thenReturn(true); 1743 1744 reset(mListeners); 1745 mBinderService.createNotificationChannels(PKG, 1746 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2))); 1747 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 1748 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1749 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 1750 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 1751 eq(Process.myUserHandle()), eq(channel2), 1752 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 1753 } 1754 1755 @Test testCreateChannelGroupNotifyListener()1756 public void testCreateChannelGroupNotifyListener() throws Exception { 1757 List<String> associations = new ArrayList<>(); 1758 associations.add("a"); 1759 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1760 mService.setPreferencesHelper(mPreferencesHelper); 1761 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b"); 1762 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m"); 1763 1764 reset(mListeners); 1765 mBinderService.createNotificationChannelGroups(PKG, 1766 new ParceledListSlice(Arrays.asList(group1, group2))); 1767 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 1768 eq(Process.myUserHandle()), eq(group1), 1769 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 1770 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 1771 eq(Process.myUserHandle()), eq(group2), 1772 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 1773 } 1774 1775 @Test testUpdateChannelNotifyListener()1776 public void testUpdateChannelNotifyListener() throws Exception { 1777 List<String> associations = new ArrayList<>(); 1778 associations.add("a"); 1779 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1780 mService.setPreferencesHelper(mPreferencesHelper); 1781 mTestNotificationChannel.setLightColor(Color.CYAN); 1782 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 1783 eq(mTestNotificationChannel.getId()), anyBoolean())) 1784 .thenReturn(mTestNotificationChannel); 1785 1786 reset(mListeners); 1787 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 1788 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 1789 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1790 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 1791 } 1792 1793 @Test testDeleteChannelNotifyListener()1794 public void testDeleteChannelNotifyListener() throws Exception { 1795 List<String> associations = new ArrayList<>(); 1796 associations.add("a"); 1797 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1798 mService.setPreferencesHelper(mPreferencesHelper); 1799 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 1800 eq(mTestNotificationChannel.getId()), anyBoolean())) 1801 .thenReturn(mTestNotificationChannel); 1802 reset(mListeners); 1803 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId()); 1804 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 1805 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1806 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); 1807 } 1808 1809 @Test testDeleteChannelGroupNotifyListener()1810 public void testDeleteChannelGroupNotifyListener() throws Exception { 1811 List<String> associations = new ArrayList<>(); 1812 associations.add("a"); 1813 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1814 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c"); 1815 mService.setPreferencesHelper(mPreferencesHelper); 1816 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt())) 1817 .thenReturn(ncg); 1818 reset(mListeners); 1819 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId()); 1820 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 1821 eq(Process.myUserHandle()), eq(ncg), 1822 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); 1823 } 1824 1825 @Test testUpdateNotificationChannelFromPrivilegedListener_success()1826 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception { 1827 mService.setPreferencesHelper(mPreferencesHelper); 1828 List<String> associations = new ArrayList<>(); 1829 associations.add("a"); 1830 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1831 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 1832 eq(mTestNotificationChannel.getId()), anyBoolean())) 1833 .thenReturn(mTestNotificationChannel); 1834 1835 mBinderService.updateNotificationChannelFromPrivilegedListener( 1836 null, PKG, Process.myUserHandle(), mTestNotificationChannel); 1837 1838 verify(mPreferencesHelper, times(1)).updateNotificationChannel( 1839 anyString(), anyInt(), any(), anyBoolean()); 1840 1841 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 1842 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1843 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 1844 } 1845 1846 @Test testUpdateNotificationChannelFromPrivilegedListener_noAccess()1847 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception { 1848 mService.setPreferencesHelper(mPreferencesHelper); 1849 List<String> associations = new ArrayList<>(); 1850 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1851 1852 try { 1853 mBinderService.updateNotificationChannelFromPrivilegedListener( 1854 null, PKG, Process.myUserHandle(), mTestNotificationChannel); 1855 fail("listeners that don't have a companion device shouldn't be able to call this"); 1856 } catch (SecurityException e) { 1857 // pass 1858 } 1859 1860 verify(mPreferencesHelper, never()).updateNotificationChannel( 1861 anyString(), anyInt(), any(), anyBoolean()); 1862 1863 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 1864 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1865 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 1866 } 1867 1868 @Test testUpdateNotificationChannelFromPrivilegedListener_badUser()1869 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception { 1870 mService.setPreferencesHelper(mPreferencesHelper); 1871 List<String> associations = new ArrayList<>(); 1872 associations.add("a"); 1873 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1874 mListener = mock(ManagedServices.ManagedServiceInfo.class); 1875 mListener.component = new ComponentName(PKG, PKG); 1876 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 1877 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 1878 1879 try { 1880 mBinderService.updateNotificationChannelFromPrivilegedListener( 1881 null, PKG, UserHandle.ALL, mTestNotificationChannel); 1882 fail("incorrectly allowed a change to a user listener cannot see"); 1883 } catch (SecurityException e) { 1884 // pass 1885 } 1886 1887 verify(mPreferencesHelper, never()).updateNotificationChannel( 1888 anyString(), anyInt(), any(), anyBoolean()); 1889 1890 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 1891 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 1892 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 1893 } 1894 1895 @Test testGetNotificationChannelFromPrivilegedListener_cdm_success()1896 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception { 1897 mService.setPreferencesHelper(mPreferencesHelper); 1898 List<String> associations = new ArrayList<>(); 1899 associations.add("a"); 1900 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1901 1902 mBinderService.getNotificationChannelsFromPrivilegedListener( 1903 null, PKG, Process.myUserHandle()); 1904 1905 verify(mPreferencesHelper, times(1)).getNotificationChannels( 1906 anyString(), anyInt(), anyBoolean()); 1907 } 1908 1909 @Test testGetNotificationChannelFromPrivilegedListener_cdm_noAccess()1910 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception { 1911 mService.setPreferencesHelper(mPreferencesHelper); 1912 List<String> associations = new ArrayList<>(); 1913 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1914 1915 try { 1916 mBinderService.getNotificationChannelsFromPrivilegedListener( 1917 null, PKG, Process.myUserHandle()); 1918 fail("listeners that don't have a companion device shouldn't be able to call this"); 1919 } catch (SecurityException e) { 1920 // pass 1921 } 1922 1923 verify(mPreferencesHelper, never()).getNotificationChannels( 1924 anyString(), anyInt(), anyBoolean()); 1925 } 1926 1927 @Test testGetNotificationChannelFromPrivilegedListener_assistant_success()1928 public void testGetNotificationChannelFromPrivilegedListener_assistant_success() 1929 throws Exception { 1930 mService.setPreferencesHelper(mPreferencesHelper); 1931 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>()); 1932 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); 1933 1934 mBinderService.getNotificationChannelsFromPrivilegedListener( 1935 null, PKG, Process.myUserHandle()); 1936 1937 verify(mPreferencesHelper, times(1)).getNotificationChannels( 1938 anyString(), anyInt(), anyBoolean()); 1939 } 1940 1941 @Test testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()1942 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess() 1943 throws Exception { 1944 mService.setPreferencesHelper(mPreferencesHelper); 1945 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>()); 1946 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false); 1947 1948 try { 1949 mBinderService.getNotificationChannelsFromPrivilegedListener( 1950 null, PKG, Process.myUserHandle()); 1951 fail("listeners that don't have a companion device shouldn't be able to call this"); 1952 } catch (SecurityException e) { 1953 // pass 1954 } 1955 1956 verify(mPreferencesHelper, never()).getNotificationChannels( 1957 anyString(), anyInt(), anyBoolean()); 1958 } 1959 1960 @Test testGetNotificationChannelFromPrivilegedListener_badUser()1961 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception { 1962 mService.setPreferencesHelper(mPreferencesHelper); 1963 List<String> associations = new ArrayList<>(); 1964 associations.add("a"); 1965 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1966 mListener = mock(ManagedServices.ManagedServiceInfo.class); 1967 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 1968 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 1969 1970 try { 1971 mBinderService.getNotificationChannelsFromPrivilegedListener( 1972 null, PKG, Process.myUserHandle()); 1973 fail("listener getting channels from a user they cannot see"); 1974 } catch (SecurityException e) { 1975 // pass 1976 } 1977 1978 verify(mPreferencesHelper, never()).getNotificationChannels( 1979 anyString(), anyInt(), anyBoolean()); 1980 } 1981 1982 @Test testGetNotificationChannelGroupsFromPrivilegedListener_success()1983 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception { 1984 mService.setPreferencesHelper(mPreferencesHelper); 1985 List<String> associations = new ArrayList<>(); 1986 associations.add("a"); 1987 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 1988 1989 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 1990 null, PKG, Process.myUserHandle()); 1991 1992 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt()); 1993 } 1994 1995 @Test testGetNotificationChannelGroupsFromPrivilegedListener_noAccess()1996 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception { 1997 mService.setPreferencesHelper(mPreferencesHelper); 1998 List<String> associations = new ArrayList<>(); 1999 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 2000 2001 try { 2002 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 2003 null, PKG, Process.myUserHandle()); 2004 fail("listeners that don't have a companion device shouldn't be able to call this"); 2005 } catch (SecurityException e) { 2006 // pass 2007 } 2008 2009 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); 2010 } 2011 2012 @Test testGetNotificationChannelGroupsFromPrivilegedListener_badUser()2013 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception { 2014 mService.setPreferencesHelper(mPreferencesHelper); 2015 List<String> associations = new ArrayList<>(); 2016 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); 2017 mListener = mock(ManagedServices.ManagedServiceInfo.class); 2018 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 2019 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 2020 try { 2021 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 2022 null, PKG, Process.myUserHandle()); 2023 fail("listeners that don't have a companion device shouldn't be able to call this"); 2024 } catch (SecurityException e) { 2025 // pass 2026 } 2027 2028 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); 2029 } 2030 2031 @Test testHasCompanionDevice_failure()2032 public void testHasCompanionDevice_failure() throws Exception { 2033 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow( 2034 new IllegalArgumentException()); 2035 mService.hasCompanionDevice(mListener); 2036 } 2037 2038 @Test testHasCompanionDevice_noService()2039 public void testHasCompanionDevice_noService() { 2040 mService = new TestableNotificationManagerService(mContext); 2041 2042 assertFalse(mService.hasCompanionDevice(mListener)); 2043 } 2044 2045 @Test testSnoozeRunnable_snoozeNonGrouped()2046 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception { 2047 final NotificationRecord nonGrouped = generateNotificationRecord( 2048 mTestNotificationChannel, 1, null, false); 2049 final NotificationRecord grouped = generateNotificationRecord( 2050 mTestNotificationChannel, 2, "group", false); 2051 mService.addNotification(grouped); 2052 mService.addNotification(nonGrouped); 2053 2054 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2055 mService.new SnoozeNotificationRunnable( 2056 nonGrouped.getKey(), 100, null); 2057 snoozeNotificationRunnable.run(); 2058 2059 // only snooze the one notification 2060 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 2061 assertTrue(nonGrouped.getStats().hasSnoozed()); 2062 } 2063 2064 @Test testSnoozeRunnable_snoozeSummary_withChildren()2065 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception { 2066 final NotificationRecord parent = generateNotificationRecord( 2067 mTestNotificationChannel, 1, "group", true); 2068 final NotificationRecord child = generateNotificationRecord( 2069 mTestNotificationChannel, 2, "group", false); 2070 final NotificationRecord child2 = generateNotificationRecord( 2071 mTestNotificationChannel, 3, "group", false); 2072 mService.addNotification(parent); 2073 mService.addNotification(child); 2074 mService.addNotification(child2); 2075 2076 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2077 mService.new SnoozeNotificationRunnable( 2078 parent.getKey(), 100, null); 2079 snoozeNotificationRunnable.run(); 2080 2081 // snooze parent and children 2082 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong()); 2083 } 2084 2085 @Test testSnoozeRunnable_snoozeGroupChild_fellowChildren()2086 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception { 2087 final NotificationRecord parent = generateNotificationRecord( 2088 mTestNotificationChannel, 1, "group", true); 2089 final NotificationRecord child = generateNotificationRecord( 2090 mTestNotificationChannel, 2, "group", false); 2091 final NotificationRecord child2 = generateNotificationRecord( 2092 mTestNotificationChannel, 3, "group", false); 2093 mService.addNotification(parent); 2094 mService.addNotification(child); 2095 mService.addNotification(child2); 2096 2097 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2098 mService.new SnoozeNotificationRunnable( 2099 child2.getKey(), 100, null); 2100 snoozeNotificationRunnable.run(); 2101 2102 // only snooze the one child 2103 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 2104 } 2105 2106 @Test testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary()2107 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception { 2108 final NotificationRecord parent = generateNotificationRecord( 2109 mTestNotificationChannel, 1, "group", true); 2110 assertTrue(parent.sbn.getNotification().isGroupSummary()); 2111 final NotificationRecord child = generateNotificationRecord( 2112 mTestNotificationChannel, 2, "group", false); 2113 mService.addNotification(parent); 2114 mService.addNotification(child); 2115 2116 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2117 mService.new SnoozeNotificationRunnable( 2118 child.getKey(), 100, null); 2119 snoozeNotificationRunnable.run(); 2120 2121 // snooze child and summary 2122 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 2123 } 2124 2125 @Test testSnoozeRunnable_snoozeGroupChild_noOthersInGroup()2126 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception { 2127 final NotificationRecord child = generateNotificationRecord( 2128 mTestNotificationChannel, 2, "group", false); 2129 mService.addNotification(child); 2130 2131 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2132 mService.new SnoozeNotificationRunnable( 2133 child.getKey(), 100, null); 2134 snoozeNotificationRunnable.run(); 2135 2136 // snooze child only 2137 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 2138 } 2139 2140 @Test testPostGroupChild_unsnoozeParent()2141 public void testPostGroupChild_unsnoozeParent() throws Exception { 2142 final NotificationRecord child = generateNotificationRecord( 2143 mTestNotificationChannel, 2, "group", false); 2144 2145 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 2146 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId()); 2147 waitForIdle(); 2148 2149 verify(mSnoozeHelper, times(1)).repostGroupSummary( 2150 anyString(), anyInt(), eq(child.getGroupKey())); 2151 } 2152 2153 @Test testPostNonGroup_noUnsnoozing()2154 public void testPostNonGroup_noUnsnoozing() throws Exception { 2155 final NotificationRecord record = generateNotificationRecord( 2156 mTestNotificationChannel, 2, null, false); 2157 2158 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 2159 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId()); 2160 waitForIdle(); 2161 2162 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); 2163 } 2164 2165 @Test testPostGroupSummary_noUnsnoozing()2166 public void testPostGroupSummary_noUnsnoozing() throws Exception { 2167 final NotificationRecord parent = generateNotificationRecord( 2168 mTestNotificationChannel, 2, "group", true); 2169 2170 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 2171 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId()); 2172 waitForIdle(); 2173 2174 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); 2175 } 2176 2177 @Test testSetListenerAccessForUser()2178 public void testSetListenerAccessForUser() throws Exception { 2179 UserHandle user = UserHandle.of(10); 2180 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2181 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true); 2182 2183 2184 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 2185 verify(mListeners, times(1)).setPackageOrComponentEnabled( 2186 c.flattenToString(), user.getIdentifier(), true, true); 2187 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2188 c.flattenToString(), user.getIdentifier(), false, true); 2189 verify(mAssistants, never()).setPackageOrComponentEnabled( 2190 any(), anyInt(), anyBoolean(), anyBoolean()); 2191 } 2192 2193 @Test testSetAssistantAccessForUser()2194 public void testSetAssistantAccessForUser() throws Exception { 2195 UserHandle user = UserHandle.of(10); 2196 List<UserInfo> uis = new ArrayList<>(); 2197 UserInfo ui = new UserInfo(); 2198 ui.id = 10; 2199 uis.add(ui); 2200 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2201 when(mUm.getEnabledProfiles(10)).thenReturn(uis); 2202 2203 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true); 2204 2205 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 2206 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 2207 c.flattenToString(), user.getIdentifier(), true, true); 2208 verify(mAssistants).setUserSet(10, true); 2209 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2210 c.flattenToString(), user.getIdentifier(), false, true); 2211 verify(mListeners, never()).setPackageOrComponentEnabled( 2212 any(), anyInt(), anyBoolean(), anyBoolean()); 2213 } 2214 2215 @Test testGetAssistantAllowedForUser()2216 public void testGetAssistantAllowedForUser() throws Exception { 2217 UserHandle user = UserHandle.of(10); 2218 try { 2219 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier()); 2220 } catch (IllegalStateException e) { 2221 if (!e.getMessage().contains("At most one NotificationAssistant")) { 2222 throw e; 2223 } 2224 } 2225 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier()); 2226 } 2227 2228 @Test testGetAssistantAllowed()2229 public void testGetAssistantAllowed() throws Exception { 2230 try { 2231 mBinderService.getAllowedNotificationAssistant(); 2232 } catch (IllegalStateException e) { 2233 if (!e.getMessage().contains("At most one NotificationAssistant")) { 2234 throw e; 2235 } 2236 } 2237 verify(mAssistants, times(1)).getAllowedComponents(0); 2238 } 2239 2240 @Test testSetDndAccessForUser()2241 public void testSetDndAccessForUser() throws Exception { 2242 UserHandle user = UserHandle.of(10); 2243 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2244 mBinderService.setNotificationPolicyAccessGrantedForUser( 2245 c.getPackageName(), user.getIdentifier(), true); 2246 2247 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 2248 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2249 c.getPackageName(), user.getIdentifier(), true, true); 2250 verify(mAssistants, never()).setPackageOrComponentEnabled( 2251 any(), anyInt(), anyBoolean(), anyBoolean()); 2252 verify(mListeners, never()).setPackageOrComponentEnabled( 2253 any(), anyInt(), anyBoolean(), anyBoolean()); 2254 } 2255 2256 @Test testSetListenerAccess()2257 public void testSetListenerAccess() throws Exception { 2258 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2259 mBinderService.setNotificationListenerAccessGranted(c, true); 2260 2261 verify(mListeners, times(1)).setPackageOrComponentEnabled( 2262 c.flattenToString(), 0, true, true); 2263 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2264 c.flattenToString(), 0, false, true); 2265 verify(mAssistants, never()).setPackageOrComponentEnabled( 2266 any(), anyInt(), anyBoolean(), anyBoolean()); 2267 } 2268 2269 @Test testSetAssistantAccess()2270 public void testSetAssistantAccess() throws Exception { 2271 List<UserInfo> uis = new ArrayList<>(); 2272 UserInfo ui = new UserInfo(); 2273 ui.id = 0; 2274 uis.add(ui); 2275 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 2276 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2277 2278 mBinderService.setNotificationAssistantAccessGranted(c, true); 2279 2280 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 2281 c.flattenToString(), 0, true, true); 2282 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2283 c.flattenToString(), 0, false, true); 2284 verify(mListeners, never()).setPackageOrComponentEnabled( 2285 any(), anyInt(), anyBoolean(), anyBoolean()); 2286 } 2287 2288 @Test testSetAssistantAccess_multiProfile()2289 public void testSetAssistantAccess_multiProfile() throws Exception { 2290 List<UserInfo> uis = new ArrayList<>(); 2291 UserInfo ui = new UserInfo(); 2292 ui.id = 0; 2293 uis.add(ui); 2294 UserInfo ui10 = new UserInfo(); 2295 ui10.id = 10; 2296 uis.add(ui10); 2297 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 2298 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2299 2300 mBinderService.setNotificationAssistantAccessGranted(c, true); 2301 2302 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 2303 c.flattenToString(), 0, true, true); 2304 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 2305 c.flattenToString(), 10, true, true); 2306 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2307 c.flattenToString(), 0, false, true); 2308 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2309 c.flattenToString(), 10, false, true); 2310 verify(mListeners, never()).setPackageOrComponentEnabled( 2311 any(), anyInt(), anyBoolean(), anyBoolean()); 2312 } 2313 2314 @Test testSetAssistantAccess_nullWithAllowedAssistant()2315 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception { 2316 ArrayList<ComponentName> componentList = new ArrayList<>(); 2317 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2318 componentList.add(c); 2319 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 2320 List<UserInfo> uis = new ArrayList<>(); 2321 UserInfo ui = new UserInfo(); 2322 ui.id = 0; 2323 uis.add(ui); 2324 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 2325 2326 mBinderService.setNotificationAssistantAccessGranted(null, true); 2327 2328 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 2329 c.flattenToString(), 0, true, false); 2330 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2331 c.flattenToString(), 0, false, false); 2332 verify(mListeners, never()).setPackageOrComponentEnabled( 2333 any(), anyInt(), anyBoolean(), anyBoolean()); 2334 } 2335 2336 @Test testSetAssistantAccessForUser_nullWithAllowedAssistant()2337 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception { 2338 List<UserInfo> uis = new ArrayList<>(); 2339 UserInfo ui = new UserInfo(); 2340 ui.id = 10; 2341 uis.add(ui); 2342 UserHandle user = ui.getUserHandle(); 2343 ArrayList<ComponentName> componentList = new ArrayList<>(); 2344 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2345 componentList.add(c); 2346 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 2347 when(mUm.getEnabledProfiles(10)).thenReturn(uis); 2348 2349 mBinderService.setNotificationAssistantAccessGrantedForUser( 2350 null, user.getIdentifier(), true); 2351 2352 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 2353 c.flattenToString(), user.getIdentifier(), true, false); 2354 verify(mAssistants).setUserSet(10, true); 2355 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2356 c.flattenToString(), user.getIdentifier(), false, false); 2357 verify(mListeners, never()).setPackageOrComponentEnabled( 2358 any(), anyInt(), anyBoolean(), anyBoolean()); 2359 } 2360 2361 @Test testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()2362 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant() 2363 throws Exception { 2364 List<UserInfo> uis = new ArrayList<>(); 2365 UserInfo ui = new UserInfo(); 2366 ui.id = 0; 2367 uis.add(ui); 2368 UserInfo ui10 = new UserInfo(); 2369 ui10.id = 10; 2370 uis.add(ui10); 2371 UserHandle user = ui.getUserHandle(); 2372 ArrayList<ComponentName> componentList = new ArrayList<>(); 2373 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2374 componentList.add(c); 2375 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 2376 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 2377 2378 mBinderService.setNotificationAssistantAccessGrantedForUser( 2379 null, user.getIdentifier(), true); 2380 2381 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 2382 c.flattenToString(), user.getIdentifier(), true, false); 2383 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 2384 c.flattenToString(), ui10.id, true, false); 2385 verify(mAssistants).setUserSet(0, true); 2386 verify(mAssistants).setUserSet(10, true); 2387 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2388 c.flattenToString(), user.getIdentifier(), false, false); 2389 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2390 c.flattenToString(), ui10.id, false, false); 2391 verify(mListeners, never()).setPackageOrComponentEnabled( 2392 any(), anyInt(), anyBoolean(), anyBoolean()); 2393 } 2394 2395 @Test testSetDndAccess()2396 public void testSetDndAccess() throws Exception { 2397 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2398 2399 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 2400 2401 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2402 c.getPackageName(), 0, true, true); 2403 verify(mAssistants, never()).setPackageOrComponentEnabled( 2404 any(), anyInt(), anyBoolean(), anyBoolean()); 2405 verify(mListeners, never()).setPackageOrComponentEnabled( 2406 any(), anyInt(), anyBoolean(), anyBoolean()); 2407 } 2408 2409 @Test testSetListenerAccess_doesNothingOnLowRam()2410 public void testSetListenerAccess_doesNothingOnLowRam() throws Exception { 2411 when(mActivityManager.isLowRamDevice()).thenReturn(true); 2412 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2413 mBinderService.setNotificationListenerAccessGranted(c, true); 2414 2415 verify(mListeners, never()).setPackageOrComponentEnabled( 2416 anyString(), anyInt(), anyBoolean(), anyBoolean()); 2417 verify(mConditionProviders, never()).setPackageOrComponentEnabled( 2418 anyString(), anyInt(), anyBoolean(), anyBoolean()); 2419 verify(mAssistants, never()).setPackageOrComponentEnabled( 2420 any(), anyInt(), anyBoolean(), anyBoolean()); 2421 } 2422 2423 @Test testSetAssistantAccess_doesNothingOnLowRam()2424 public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception { 2425 when(mActivityManager.isLowRamDevice()).thenReturn(true); 2426 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2427 List<UserInfo> uis = new ArrayList<>(); 2428 UserInfo ui = new UserInfo(); 2429 ui.id = 0; 2430 uis.add(ui); 2431 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 2432 2433 mBinderService.setNotificationAssistantAccessGranted(c, true); 2434 2435 verify(mListeners, never()).setPackageOrComponentEnabled( 2436 anyString(), anyInt(), anyBoolean(), anyBoolean()); 2437 verify(mConditionProviders, never()).setPackageOrComponentEnabled( 2438 anyString(), anyInt(), anyBoolean(), anyBoolean()); 2439 verify(mAssistants, never()).setPackageOrComponentEnabled( 2440 any(), anyInt(), anyBoolean(), anyBoolean()); 2441 } 2442 2443 @Test testSetDndAccess_doesNothingOnLowRam()2444 public void testSetDndAccess_doesNothingOnLowRam() throws Exception { 2445 when(mActivityManager.isLowRamDevice()).thenReturn(true); 2446 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2447 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 2448 2449 verify(mListeners, never()).setPackageOrComponentEnabled( 2450 anyString(), anyInt(), anyBoolean(), anyBoolean()); 2451 verify(mConditionProviders, never()).setPackageOrComponentEnabled( 2452 anyString(), anyInt(), anyBoolean(), anyBoolean()); 2453 verify(mAssistants, never()).setPackageOrComponentEnabled( 2454 any(), anyInt(), anyBoolean(), anyBoolean()); 2455 } 2456 2457 @Test testSetListenerAccess_doesNothingOnLowRam_exceptWatch()2458 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 2459 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 2460 when(mActivityManager.isLowRamDevice()).thenReturn(true); 2461 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2462 2463 mBinderService.setNotificationListenerAccessGranted(c, true); 2464 2465 verify(mListeners, times(1)).setPackageOrComponentEnabled( 2466 c.flattenToString(), 0, true, true); 2467 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2468 c.flattenToString(), 0, false, true); 2469 verify(mAssistants, never()).setPackageOrComponentEnabled( 2470 any(), anyInt(), anyBoolean(), anyBoolean()); 2471 } 2472 2473 @Test testSetAssistantAccess_doesNothingOnLowRam_exceptWatch()2474 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 2475 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 2476 when(mActivityManager.isLowRamDevice()).thenReturn(true); 2477 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2478 List<UserInfo> uis = new ArrayList<>(); 2479 UserInfo ui = new UserInfo(); 2480 ui.id = 0; 2481 uis.add(ui); 2482 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 2483 2484 mBinderService.setNotificationAssistantAccessGranted(c, true); 2485 2486 verify(mListeners, never()).setPackageOrComponentEnabled( 2487 anyString(), anyInt(), anyBoolean(), anyBoolean()); 2488 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2489 c.flattenToString(), 0, false, true); 2490 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 2491 c.flattenToString(), 0, true, true); 2492 } 2493 2494 @Test testSetDndAccess_doesNothingOnLowRam_exceptWatch()2495 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 2496 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 2497 when(mActivityManager.isLowRamDevice()).thenReturn(true); 2498 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2499 2500 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 2501 2502 verify(mListeners, never()).setPackageOrComponentEnabled( 2503 anyString(), anyInt(), anyBoolean(), anyBoolean()); 2504 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2505 c.getPackageName(), 0, true, true); 2506 verify(mAssistants, never()).setPackageOrComponentEnabled( 2507 any(), anyInt(), anyBoolean(), anyBoolean()); 2508 } 2509 2510 @Test testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups()2511 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception { 2512 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 2513 mService.addEnqueuedNotification(r); 2514 NotificationManagerService.PostNotificationRunnable runnable = 2515 mService.new PostNotificationRunnable(r.getKey()); 2516 runnable.run(); 2517 waitForIdle(); 2518 2519 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 2520 } 2521 2522 @Test testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()2523 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups() 2524 throws Exception { 2525 NotificationRecord r = 2526 generateNotificationRecord(mTestNotificationChannel, 0, "group", false); 2527 mService.addNotification(r); 2528 2529 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 2530 mService.addEnqueuedNotification(r); 2531 NotificationManagerService.PostNotificationRunnable runnable = 2532 mService.new PostNotificationRunnable(r.getKey()); 2533 runnable.run(); 2534 waitForIdle(); 2535 2536 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 2537 } 2538 2539 @Test testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()2540 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups() 2541 throws Exception { 2542 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group", 2543 false); 2544 mService.addNotification(r); 2545 mService.addEnqueuedNotification(r); 2546 2547 NotificationManagerService.PostNotificationRunnable runnable = 2548 mService.new PostNotificationRunnable(r.getKey()); 2549 runnable.run(); 2550 waitForIdle(); 2551 2552 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean()); 2553 } 2554 2555 @Test testDontAutogroupIfCritical()2556 public void testDontAutogroupIfCritical() throws Exception { 2557 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 2558 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW); 2559 mService.addEnqueuedNotification(r); 2560 NotificationManagerService.PostNotificationRunnable runnable = 2561 mService.new PostNotificationRunnable(r.getKey()); 2562 runnable.run(); 2563 2564 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false); 2565 r.setCriticality(CriticalNotificationExtractor.CRITICAL); 2566 runnable = mService.new PostNotificationRunnable(r.getKey()); 2567 mService.addEnqueuedNotification(r); 2568 2569 runnable.run(); 2570 waitForIdle(); 2571 2572 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean()); 2573 } 2574 2575 @Test testNoFakeColorizedPermission()2576 public void testNoFakeColorizedPermission() throws Exception { 2577 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED); 2578 Notification.Builder nb = new Notification.Builder(mContext, 2579 mTestNotificationChannel.getId()) 2580 .setContentTitle("foo") 2581 .setColorized(true) 2582 .setFlag(Notification.FLAG_CAN_COLORIZE, true) 2583 .setSmallIcon(android.R.drawable.sym_def_app_icon); 2584 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, 2585 nb.build(), new UserHandle(mUid), null, 0); 2586 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 2587 2588 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 2589 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 2590 waitForIdle(); 2591 2592 NotificationRecord posted = mService.findNotificationLocked( 2593 PKG, null, nr.sbn.getId(), nr.sbn.getUserId()); 2594 2595 assertFalse(posted.getNotification().isColorized()); 2596 } 2597 2598 @Test testGetNotificationCountLocked()2599 public void testGetNotificationCountLocked() throws Exception { 2600 for (int i = 0; i < 20; i++) { 2601 NotificationRecord r = 2602 generateNotificationRecord(mTestNotificationChannel, i, null, false); 2603 mService.addEnqueuedNotification(r); 2604 } 2605 for (int i = 0; i < 20; i++) { 2606 NotificationRecord r = 2607 generateNotificationRecord(mTestNotificationChannel, i, null, false); 2608 mService.addNotification(r); 2609 } 2610 2611 // another package 2612 Notification n = 2613 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 2614 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2615 .build(); 2616 2617 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0, 2618 n, new UserHandle(mUid), null, 0); 2619 NotificationRecord otherPackage = 2620 new NotificationRecord(mContext, sbn, mTestNotificationChannel); 2621 mService.addEnqueuedNotification(otherPackage); 2622 mService.addNotification(otherPackage); 2623 2624 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match 2625 int userId = new UserHandle(mUid).getIdentifier(); 2626 assertEquals(40, 2627 mService.getNotificationCountLocked(PKG, userId, 0, null)); 2628 assertEquals(40, 2629 mService.getNotificationCountLocked(PKG, userId, 0, "tag2")); 2630 assertEquals(2, 2631 mService.getNotificationCountLocked("a", userId, 0, "banana")); 2632 2633 // exclude a known notification - it's excluded from only the posted list, not enqueued 2634 assertEquals(39, 2635 mService.getNotificationCountLocked(PKG, userId, 0, "tag")); 2636 } 2637 2638 @Test testAddAutogroup_requestsSort()2639 public void testAddAutogroup_requestsSort() throws Exception { 2640 RankingHandler rh = mock(RankingHandler.class); 2641 mService.setRankingHandler(rh); 2642 2643 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2644 mService.addNotification(r); 2645 mService.addAutogroupKeyLocked(r.getKey()); 2646 2647 verify(rh, times(1)).requestSort(); 2648 } 2649 2650 @Test testRemoveAutogroup_requestsSort()2651 public void testRemoveAutogroup_requestsSort() throws Exception { 2652 RankingHandler rh = mock(RankingHandler.class); 2653 mService.setRankingHandler(rh); 2654 2655 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2656 r.setOverrideGroupKey("TEST"); 2657 mService.addNotification(r); 2658 mService.removeAutogroupKeyLocked(r.getKey()); 2659 2660 verify(rh, times(1)).requestSort(); 2661 } 2662 2663 @Test testReaddAutogroup_noSort()2664 public void testReaddAutogroup_noSort() throws Exception { 2665 RankingHandler rh = mock(RankingHandler.class); 2666 mService.setRankingHandler(rh); 2667 2668 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2669 r.setOverrideGroupKey("TEST"); 2670 mService.addNotification(r); 2671 mService.addAutogroupKeyLocked(r.getKey()); 2672 2673 verify(rh, never()).requestSort(); 2674 } 2675 2676 @Test testHandleRankingSort_sendsUpdateOnSignalExtractorChange()2677 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception { 2678 mService.setPreferencesHelper(mPreferencesHelper); 2679 NotificationManagerService.WorkerHandler handler = mock( 2680 NotificationManagerService.WorkerHandler.class); 2681 mService.setHandler(handler); 2682 2683 Map<String, Answer> answers = getSignalExtractorSideEffects(); 2684 for (String message : answers.keySet()) { 2685 mService.clearNotifications(); 2686 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2687 mService.addNotification(r); 2688 2689 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r); 2690 2691 mService.handleRankingSort(); 2692 } 2693 verify(handler, times(answers.size())).scheduleSendRankingUpdate(); 2694 } 2695 2696 @Test testHandleRankingSort_noUpdateWhenNoSignalChange()2697 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception { 2698 mService.setRankingHelper(mRankingHelper); 2699 NotificationManagerService.WorkerHandler handler = mock( 2700 NotificationManagerService.WorkerHandler.class); 2701 mService.setHandler(handler); 2702 2703 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2704 mService.addNotification(r); 2705 2706 mService.handleRankingSort(); 2707 verify(handler, never()).scheduleSendRankingUpdate(); 2708 } 2709 2710 @Test testReadPolicyXml_readApprovedServicesFromXml()2711 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception { 2712 final String upgradeXml = "<notification-policy version=\"1\">" 2713 + "<ranking></ranking>" 2714 + "<enabled_listeners>" 2715 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 2716 + "</enabled_listeners>" 2717 + "<enabled_assistants>" 2718 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 2719 + "</enabled_assistants>" 2720 + "<dnd_apps>" 2721 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 2722 + "</dnd_apps>" 2723 + "</notification-policy>"; 2724 mService.readPolicyXml( 2725 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())), 2726 false, 2727 UserHandle.USER_ALL); 2728 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 2729 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 2730 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 2731 2732 // numbers are inflated for setup 2733 verify(mListeners, times(1)).migrateToXml(); 2734 verify(mConditionProviders, times(1)).migrateToXml(); 2735 verify(mAssistants, times(1)).migrateToXml(); 2736 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary(); 2737 } 2738 2739 @Test testReadPolicyXml_readApprovedServicesFromSettings()2740 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception { 2741 final String preupgradeXml = "<notification-policy version=\"1\">" 2742 + "<ranking></ranking>" 2743 + "</notification-policy>"; 2744 mService.readPolicyXml( 2745 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), 2746 false, 2747 UserHandle.USER_ALL); 2748 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt()); 2749 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt()); 2750 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt()); 2751 2752 // numbers are inflated for setup 2753 verify(mListeners, times(2)).migrateToXml(); 2754 verify(mConditionProviders, times(2)).migrateToXml(); 2755 verify(mAssistants, times(2)).migrateToXml(); 2756 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary(); 2757 } 2758 2759 @Test testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser()2760 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception { 2761 final String policyXml = "<notification-policy version=\"1\">" 2762 + "<ranking></ranking>" 2763 + "<enabled_listeners>" 2764 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 2765 + "</enabled_listeners>" 2766 + "<enabled_assistants>" 2767 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 2768 + "</enabled_assistants>" 2769 + "<dnd_apps>" 2770 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 2771 + "</dnd_apps>" 2772 + "</notification-policy>"; 2773 when(mUm.isManagedProfile(10)).thenReturn(true); 2774 mService.readPolicyXml( 2775 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())), 2776 true, 2777 10); 2778 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10)); 2779 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10)); 2780 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10)); 2781 } 2782 2783 @Test testReadPolicyXml_restoresManagedServicesForNonManagedUser()2784 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception { 2785 final String policyXml = "<notification-policy version=\"1\">" 2786 + "<ranking></ranking>" 2787 + "<enabled_listeners>" 2788 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 2789 + "</enabled_listeners>" 2790 + "<enabled_assistants>" 2791 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 2792 + "</enabled_assistants>" 2793 + "<dnd_apps>" 2794 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 2795 + "</dnd_apps>" 2796 + "</notification-policy>"; 2797 when(mUm.isManagedProfile(10)).thenReturn(false); 2798 mService.readPolicyXml( 2799 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())), 2800 true, 2801 10); 2802 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10)); 2803 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10)); 2804 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10)); 2805 } 2806 2807 @Test testLocaleChangedCallsUpdateDefaultZenModeRules()2808 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception { 2809 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 2810 mService.mZenModeHelper = mZenModeHelper; 2811 mService.mLocaleChangeReceiver.onReceive(mContext, 2812 new Intent(Intent.ACTION_LOCALE_CHANGED)); 2813 2814 verify(mZenModeHelper, times(1)).updateDefaultZenRules(); 2815 } 2816 2817 @Test testBumpFGImportance_noChannelChangePreOApp()2818 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception { 2819 String preOPkg = PKG_N_MR1; 2820 final ApplicationInfo legacy = new ApplicationInfo(); 2821 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 2822 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt())) 2823 .thenReturn(legacy); 2824 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt())) 2825 .thenReturn(Binder.getCallingUid()); 2826 getContext().setMockPackageManager(mPackageManagerClient); 2827 2828 Notification.Builder nb = new Notification.Builder(mContext, 2829 NotificationChannel.DEFAULT_CHANNEL_ID) 2830 .setContentTitle("foo") 2831 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2832 .setFlag(FLAG_FOREGROUND_SERVICE, true) 2833 .setPriority(Notification.PRIORITY_MIN); 2834 2835 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", 2836 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0); 2837 2838 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(), 2839 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2840 waitForIdle(); 2841 2842 assertEquals(IMPORTANCE_LOW, 2843 mService.getNotificationRecord(sbn.getKey()).getImportance()); 2844 2845 nb = new Notification.Builder(mContext) 2846 .setContentTitle("foo") 2847 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2848 .setFlag(FLAG_FOREGROUND_SERVICE, true) 2849 .setPriority(Notification.PRIORITY_MIN); 2850 2851 sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", Binder.getCallingUid(), 2852 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0); 2853 2854 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag", 2855 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2856 waitForIdle(); 2857 assertEquals(IMPORTANCE_LOW, 2858 mService.getNotificationRecord(sbn.getKey()).getImportance()); 2859 2860 NotificationChannel defaultChannel = mBinderService.getNotificationChannel( 2861 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID); 2862 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance()); 2863 } 2864 2865 @Test testStats_updatedOnDirectReply()2866 public void testStats_updatedOnDirectReply() throws Exception { 2867 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2868 mService.addNotification(r); 2869 2870 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey()); 2871 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied()); 2872 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.sbn)); 2873 } 2874 2875 @Test testStats_updatedOnUserExpansion()2876 public void testStats_updatedOnUserExpansion() throws Exception { 2877 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2878 mService.addNotification(r); 2879 2880 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true, 2881 NOTIFICATION_LOCATION_UNKNOWN); 2882 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true))); 2883 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 2884 2885 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false, 2886 NOTIFICATION_LOCATION_UNKNOWN); 2887 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false))); 2888 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 2889 } 2890 2891 @Test testStats_notUpdatedOnAutoExpansion()2892 public void testStats_notUpdatedOnAutoExpansion() throws Exception { 2893 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2894 mService.addNotification(r); 2895 2896 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 2897 NOTIFICATION_LOCATION_UNKNOWN); 2898 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 2899 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true))); 2900 2901 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false, 2902 NOTIFICATION_LOCATION_UNKNOWN); 2903 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 2904 verify(mAssistants).notifyAssistantExpansionChangedLocked( 2905 eq(r.sbn), eq(false), eq((false))); 2906 } 2907 2908 @Test testStats_updatedOnViewSettings()2909 public void testStats_updatedOnViewSettings() throws Exception { 2910 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2911 mService.addNotification(r); 2912 2913 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey()); 2914 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings()); 2915 } 2916 2917 @Test testStats_updatedOnVisibilityChanged()2918 public void testStats_updatedOnVisibilityChanged() throws Exception { 2919 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2920 mService.addNotification(r); 2921 2922 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true); 2923 mService.mNotificationDelegate.onNotificationVisibilityChanged( 2924 new NotificationVisibility[] {nv}, new NotificationVisibility[]{}); 2925 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen()); 2926 mService.mNotificationDelegate.onNotificationVisibilityChanged( 2927 new NotificationVisibility[] {}, new NotificationVisibility[]{nv}); 2928 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen()); 2929 } 2930 2931 @Test testStats_dismissalSurface()2932 public void testStats_dismissalSurface() throws Exception { 2933 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2934 mService.addNotification(r); 2935 2936 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true); 2937 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(), 2938 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD, 2939 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv); 2940 waitForIdle(); 2941 2942 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface()); 2943 } 2944 2945 @Test testStats_dismissalSentiment()2946 public void testStats_dismissalSentiment() throws Exception { 2947 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2948 mService.addNotification(r); 2949 2950 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true); 2951 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(), 2952 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD, 2953 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv); 2954 waitForIdle(); 2955 2956 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE, 2957 r.getStats().getDismissalSentiment()); 2958 } 2959 2960 @Test testApplyAdjustmentMultiUser()2961 public void testApplyAdjustmentMultiUser() throws Exception { 2962 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2963 mService.addNotification(r); 2964 NotificationManagerService.WorkerHandler handler = mock( 2965 NotificationManagerService.WorkerHandler.class); 2966 mService.setHandler(handler); 2967 2968 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false); 2969 2970 Bundle signals = new Bundle(); 2971 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 2972 USER_SENTIMENT_NEGATIVE); 2973 Adjustment adjustment = new Adjustment( 2974 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 2975 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 2976 2977 waitForIdle(); 2978 2979 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 2980 } 2981 2982 @Test testAssistantBlockingTriggersCancel()2983 public void testAssistantBlockingTriggersCancel() throws Exception { 2984 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 2985 mService.addNotification(r); 2986 NotificationManagerService.WorkerHandler handler = mock( 2987 NotificationManagerService.WorkerHandler.class); 2988 mService.setHandler(handler); 2989 2990 Bundle signals = new Bundle(); 2991 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE); 2992 Adjustment adjustment = new Adjustment( 2993 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 2994 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 2995 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 2996 2997 waitForIdle(); 2998 2999 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 3000 verify(handler, times(1)).scheduleCancelNotification(any()); 3001 } 3002 3003 @Test testApplyEnqueuedAdjustmentFromAssistant_singleUser()3004 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception { 3005 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3006 mService.addEnqueuedNotification(r); 3007 NotificationManagerService.WorkerHandler handler = mock( 3008 NotificationManagerService.WorkerHandler.class); 3009 mService.setHandler(handler); 3010 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 3011 3012 Bundle signals = new Bundle(); 3013 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3014 USER_SENTIMENT_NEGATIVE); 3015 Adjustment adjustment = new Adjustment( 3016 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3017 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 3018 3019 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment()); 3020 } 3021 3022 @Test testApplyEnqueuedAdjustmentFromAssistant_importance()3023 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception { 3024 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3025 mService.addEnqueuedNotification(r); 3026 NotificationManagerService.WorkerHandler handler = mock( 3027 NotificationManagerService.WorkerHandler.class); 3028 mService.setHandler(handler); 3029 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 3030 3031 Bundle signals = new Bundle(); 3032 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW); 3033 Adjustment adjustment = new Adjustment( 3034 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3035 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 3036 3037 assertEquals(IMPORTANCE_LOW, r.getImportance()); 3038 } 3039 3040 @Test testApplyEnqueuedAdjustmentFromAssistant_crossUser()3041 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception { 3042 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3043 mService.addEnqueuedNotification(r); 3044 NotificationManagerService.WorkerHandler handler = mock( 3045 NotificationManagerService.WorkerHandler.class); 3046 mService.setHandler(handler); 3047 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false); 3048 3049 Bundle signals = new Bundle(); 3050 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3051 USER_SENTIMENT_NEGATIVE); 3052 Adjustment adjustment = new Adjustment( 3053 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3054 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 3055 3056 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment()); 3057 3058 waitForIdle(); 3059 3060 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 3061 } 3062 3063 @Test testUserSentimentChangeTriggersUpdate()3064 public void testUserSentimentChangeTriggersUpdate() throws Exception { 3065 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3066 mService.addNotification(r); 3067 NotificationManagerService.WorkerHandler handler = mock( 3068 NotificationManagerService.WorkerHandler.class); 3069 mService.setHandler(handler); 3070 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 3071 3072 Bundle signals = new Bundle(); 3073 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3074 USER_SENTIMENT_NEGATIVE); 3075 Adjustment adjustment = new Adjustment( 3076 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3077 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 3078 3079 waitForIdle(); 3080 3081 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate(); 3082 } 3083 3084 @Test testTooLateAdjustmentTriggersUpdate()3085 public void testTooLateAdjustmentTriggersUpdate() throws Exception { 3086 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3087 mService.addNotification(r); 3088 NotificationManagerService.WorkerHandler handler = mock( 3089 NotificationManagerService.WorkerHandler.class); 3090 mService.setHandler(handler); 3091 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 3092 3093 Bundle signals = new Bundle(); 3094 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3095 USER_SENTIMENT_NEGATIVE); 3096 Adjustment adjustment = new Adjustment( 3097 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3098 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 3099 3100 waitForIdle(); 3101 3102 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate(); 3103 } 3104 3105 @Test testEnqueuedAdjustmentAppliesAdjustments()3106 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception { 3107 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3108 mService.addEnqueuedNotification(r); 3109 NotificationManagerService.WorkerHandler handler = mock( 3110 NotificationManagerService.WorkerHandler.class); 3111 mService.setHandler(handler); 3112 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 3113 3114 Bundle signals = new Bundle(); 3115 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3116 USER_SENTIMENT_NEGATIVE); 3117 Adjustment adjustment = new Adjustment( 3118 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3119 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 3120 3121 assertEquals(USER_SENTIMENT_NEGATIVE, 3122 r.getUserSentiment()); 3123 } 3124 3125 @Test testRestore()3126 public void testRestore() throws Exception { 3127 int systemChecks = mService.countSystemChecks; 3128 mBinderService.applyRestore(null, UserHandle.USER_SYSTEM); 3129 assertEquals(1, mService.countSystemChecks - systemChecks); 3130 } 3131 3132 @Test testBackup()3133 public void testBackup() throws Exception { 3134 int systemChecks = mService.countSystemChecks; 3135 mBinderService.getBackupPayload(1); 3136 assertEquals(1, mService.countSystemChecks - systemChecks); 3137 } 3138 3139 @Test updateUriPermissions_update()3140 public void updateUriPermissions_update() throws Exception { 3141 NotificationChannel c = new NotificationChannel( 3142 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 3143 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT); 3144 Message message1 = new Message("", 0, ""); 3145 message1.setData("", 3146 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1)); 3147 Message message2 = new Message("", 1, ""); 3148 message2.setData("", 3149 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2)); 3150 3151 Notification.Builder nbA = new Notification.Builder(mContext, c.getId()) 3152 .setContentTitle("foo") 3153 .setSmallIcon(android.R.drawable.sym_def_app_icon) 3154 .setStyle(new Notification.MessagingStyle("") 3155 .addMessage(message1) 3156 .addMessage(message2)); 3157 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification( 3158 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c); 3159 3160 // First post means we grant access to both 3161 reset(mUgm); 3162 reset(mUgmInternal); 3163 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder()); 3164 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), 3165 UserHandle.USER_SYSTEM); 3166 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 3167 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt()); 3168 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 3169 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt()); 3170 3171 Notification.Builder nbB = new Notification.Builder(mContext, c.getId()) 3172 .setContentTitle("foo") 3173 .setSmallIcon(android.R.drawable.sym_def_app_icon) 3174 .setStyle(new Notification.MessagingStyle("").addMessage(message2)); 3175 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG, 3176 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c); 3177 3178 // Update means we drop access to first 3179 reset(mUgmInternal); 3180 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(), 3181 UserHandle.USER_SYSTEM); 3182 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), 3183 eq(message1.getDataUri()), anyInt(), anyInt()); 3184 3185 // Update back means we grant access to first again 3186 reset(mUgm); 3187 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(), 3188 UserHandle.USER_SYSTEM); 3189 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 3190 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt()); 3191 3192 // And update to empty means we drop everything 3193 reset(mUgmInternal); 3194 mService.updateUriPermissions(null, recordB, mContext.getPackageName(), 3195 UserHandle.USER_SYSTEM); 3196 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null), 3197 anyInt(), anyInt()); 3198 } 3199 3200 @Test testVisitUris()3201 public void testVisitUris() throws Exception { 3202 final Uri audioContents = Uri.parse("content://com.example/audio"); 3203 final Uri backgroundImage = Uri.parse("content://com.example/background"); 3204 3205 Bundle extras = new Bundle(); 3206 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents); 3207 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString()); 3208 3209 Notification n = new Notification.Builder(mContext, "a") 3210 .setContentTitle("notification with uris") 3211 .setSmallIcon(android.R.drawable.sym_def_app_icon) 3212 .addExtras(extras) 3213 .build(); 3214 3215 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 3216 n.visitUris(visitor); 3217 verify(visitor, times(1)).accept(eq(audioContents)); 3218 verify(visitor, times(1)).accept(eq(backgroundImage)); 3219 } 3220 3221 @Test testSetNotificationPolicy_preP_setOldFields()3222 public void testSetNotificationPolicy_preP_setOldFields() { 3223 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 3224 mService.mZenModeHelper = mZenModeHelper; 3225 NotificationManager.Policy userPolicy = 3226 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 3227 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 3228 3229 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 3230 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 3231 3232 int expected = SUPPRESSED_EFFECT_BADGE 3233 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 3234 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS 3235 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 3236 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 3237 3238 assertEquals(expected, actual); 3239 } 3240 3241 @Test testSetNotificationPolicy_preP_setNewFields()3242 public void testSetNotificationPolicy_preP_setNewFields() { 3243 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 3244 mService.mZenModeHelper = mZenModeHelper; 3245 NotificationManager.Policy userPolicy = 3246 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 3247 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 3248 3249 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 3250 SUPPRESSED_EFFECT_NOTIFICATION_LIST); 3251 3252 int expected = SUPPRESSED_EFFECT_BADGE; 3253 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 3254 3255 assertEquals(expected, actual); 3256 } 3257 3258 @Test testSetNotificationPolicy_preP_setOldNewFields()3259 public void testSetNotificationPolicy_preP_setOldNewFields() { 3260 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 3261 mService.mZenModeHelper = mZenModeHelper; 3262 NotificationManager.Policy userPolicy = 3263 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 3264 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 3265 3266 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 3267 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 3268 3269 int expected = 3270 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK; 3271 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 3272 3273 assertEquals(expected, actual); 3274 } 3275 3276 @Test testSetNotificationPolicy_P_setOldFields()3277 public void testSetNotificationPolicy_P_setOldFields() { 3278 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 3279 mService.mZenModeHelper = mZenModeHelper; 3280 NotificationManager.Policy userPolicy = 3281 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 3282 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 3283 3284 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 3285 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 3286 3287 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 3288 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT 3289 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 3290 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 3291 3292 assertEquals(expected, actual); 3293 } 3294 3295 @Test testSetNotificationPolicy_P_setNewFields()3296 public void testSetNotificationPolicy_P_setNewFields() { 3297 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 3298 mService.mZenModeHelper = mZenModeHelper; 3299 NotificationManager.Policy userPolicy = 3300 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 3301 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 3302 3303 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 3304 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT 3305 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 3306 3307 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF 3308 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS 3309 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 3310 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 3311 3312 assertEquals(expected, actual); 3313 } 3314 3315 @Test testSetNotificationPolicy_P_setOldNewFields()3316 public void testSetNotificationPolicy_P_setOldNewFields() { 3317 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 3318 mService.mZenModeHelper = mZenModeHelper; 3319 NotificationManager.Policy userPolicy = 3320 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 3321 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 3322 3323 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 3324 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 3325 3326 int expected = SUPPRESSED_EFFECT_STATUS_BAR; 3327 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 3328 3329 assertEquals(expected, actual); 3330 3331 appPolicy = new NotificationManager.Policy(0, 0, 0, 3332 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT 3333 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 3334 3335 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT 3336 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 3337 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 3338 3339 assertEquals(expected, actual); 3340 } 3341 3342 @Test testVisualDifference_foreground()3343 public void testVisualDifference_foreground() { 3344 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3345 .setContentTitle("foo"); 3346 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3347 nb1.build(), new UserHandle(mUid), null, 0); 3348 NotificationRecord r1 = 3349 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3350 3351 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3352 .setFlag(FLAG_FOREGROUND_SERVICE, true) 3353 .setContentTitle("bar"); 3354 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3355 nb2.build(), new UserHandle(mUid), null, 0); 3356 NotificationRecord r2 = 3357 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3358 3359 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 3360 } 3361 3362 @Test testVisualDifference_diffTitle()3363 public void testVisualDifference_diffTitle() { 3364 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3365 .setContentTitle("foo"); 3366 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3367 nb1.build(), new UserHandle(mUid), null, 0); 3368 NotificationRecord r1 = 3369 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3370 3371 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3372 .setContentTitle("bar"); 3373 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3374 nb2.build(), new UserHandle(mUid), null, 0); 3375 NotificationRecord r2 = 3376 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3377 3378 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 3379 } 3380 3381 @Test testVisualDifference_inboxStyle()3382 public void testVisualDifference_inboxStyle() { 3383 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3384 .setStyle(new Notification.InboxStyle() 3385 .addLine("line1").addLine("line2")); 3386 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3387 nb1.build(), new UserHandle(mUid), null, 0); 3388 NotificationRecord r1 = 3389 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3390 3391 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3392 .setStyle(new Notification.InboxStyle() 3393 .addLine("line1").addLine("line2_changed")); 3394 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3395 nb2.build(), new UserHandle(mUid), null, 0); 3396 NotificationRecord r2 = 3397 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3398 3399 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed 3400 3401 Notification.Builder nb3 = new Notification.Builder(mContext, "") 3402 .setStyle(new Notification.InboxStyle() 3403 .addLine("line1")); 3404 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3405 nb3.build(), new UserHandle(mUid), null, 0); 3406 NotificationRecord r3 = 3407 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class)); 3408 3409 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed 3410 3411 Notification.Builder nb4 = new Notification.Builder(mContext, "") 3412 .setStyle(new Notification.InboxStyle() 3413 .addLine("line1").addLine("line2").addLine("line3")); 3414 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3415 nb4.build(), new UserHandle(mUid), null, 0); 3416 NotificationRecord r4 = 3417 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class)); 3418 3419 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed 3420 3421 Notification.Builder nb5 = new Notification.Builder(mContext, "") 3422 .setContentText("not an inbox"); 3423 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3424 nb5.build(), new UserHandle(mUid), null, 0); 3425 NotificationRecord r5 = 3426 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class)); 3427 3428 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed 3429 } 3430 3431 @Test testVisualDifference_diffText()3432 public void testVisualDifference_diffText() { 3433 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3434 .setContentText("foo"); 3435 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3436 nb1.build(), new UserHandle(mUid), null, 0); 3437 NotificationRecord r1 = 3438 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3439 3440 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3441 .setContentText("bar"); 3442 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3443 nb2.build(), new UserHandle(mUid), null, 0); 3444 NotificationRecord r2 = 3445 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3446 3447 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 3448 } 3449 3450 @Test testVisualDifference_sameText()3451 public void testVisualDifference_sameText() { 3452 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3453 .setContentText("foo"); 3454 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3455 nb1.build(), new UserHandle(mUid), null, 0); 3456 NotificationRecord r1 = 3457 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3458 3459 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3460 .setContentText("foo"); 3461 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3462 nb2.build(), new UserHandle(mUid), null, 0); 3463 NotificationRecord r2 = 3464 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3465 3466 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 3467 } 3468 3469 @Test testVisualDifference_sameTextButStyled()3470 public void testVisualDifference_sameTextButStyled() { 3471 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3472 .setContentText(Html.fromHtml("<b>foo</b>")); 3473 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3474 nb1.build(), new UserHandle(mUid), null, 0); 3475 NotificationRecord r1 = 3476 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3477 3478 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3479 .setContentText(Html.fromHtml("<b>foo</b>")); 3480 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3481 nb2.build(), new UserHandle(mUid), null, 0); 3482 NotificationRecord r2 = 3483 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3484 3485 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 3486 } 3487 3488 @Test testVisualDifference_diffTextButStyled()3489 public void testVisualDifference_diffTextButStyled() { 3490 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3491 .setContentText(Html.fromHtml("<b>foo</b>")); 3492 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3493 nb1.build(), new UserHandle(mUid), null, 0); 3494 NotificationRecord r1 = 3495 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3496 3497 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3498 .setContentText(Html.fromHtml("<b>bar</b>")); 3499 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3500 nb2.build(), new UserHandle(mUid), null, 0); 3501 NotificationRecord r2 = 3502 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3503 3504 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 3505 } 3506 3507 @Test testVisualDifference_diffProgress()3508 public void testVisualDifference_diffProgress() { 3509 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3510 .setProgress(100, 90, false); 3511 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3512 nb1.build(), new UserHandle(mUid), null, 0); 3513 NotificationRecord r1 = 3514 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3515 3516 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3517 .setProgress(100, 100, false); 3518 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3519 nb2.build(), new UserHandle(mUid), null, 0); 3520 NotificationRecord r2 = 3521 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3522 3523 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 3524 } 3525 3526 @Test testVisualDifference_diffProgressNotDone()3527 public void testVisualDifference_diffProgressNotDone() { 3528 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3529 .setProgress(100, 90, false); 3530 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3531 nb1.build(), new UserHandle(mUid), null, 0); 3532 NotificationRecord r1 = 3533 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3534 3535 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3536 .setProgress(100, 91, false); 3537 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3538 nb2.build(), new UserHandle(mUid), null, 0); 3539 NotificationRecord r2 = 3540 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3541 3542 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 3543 } 3544 3545 @Test testVisualDifference_sameProgressStillDone()3546 public void testVisualDifference_sameProgressStillDone() { 3547 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3548 .setProgress(100, 100, false); 3549 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3550 nb1.build(), new UserHandle(mUid), null, 0); 3551 NotificationRecord r1 = 3552 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3553 3554 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3555 .setProgress(100, 100, false); 3556 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3557 nb2.build(), new UserHandle(mUid), null, 0); 3558 NotificationRecord r2 = 3559 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3560 3561 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 3562 } 3563 3564 @Test testVisualDifference_summary()3565 public void testVisualDifference_summary() { 3566 Notification.Builder nb1 = new Notification.Builder(mContext, "") 3567 .setGroup("bananas") 3568 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 3569 .setContentText("foo"); 3570 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3571 nb1.build(), new UserHandle(mUid), null, 0); 3572 NotificationRecord r1 = 3573 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 3574 3575 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3576 .setGroup("bananas") 3577 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 3578 .setContentText("bar"); 3579 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3580 nb2.build(), new UserHandle(mUid), null, 0); 3581 NotificationRecord r2 = 3582 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3583 3584 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 3585 } 3586 3587 @Test testVisualDifference_summaryNewNotification()3588 public void testVisualDifference_summaryNewNotification() { 3589 Notification.Builder nb2 = new Notification.Builder(mContext, "") 3590 .setGroup("bananas") 3591 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 3592 .setContentText("bar"); 3593 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 3594 nb2.build(), new UserHandle(mUid), null, 0); 3595 NotificationRecord r2 = 3596 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 3597 3598 assertFalse(mService.isVisuallyInterruptive(null, r2)); 3599 } 3600 3601 @Test testHideAndUnhideNotificationsOnSuspendedPackageBroadcast()3602 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() { 3603 // post 2 notification from this package 3604 final NotificationRecord notif1 = generateNotificationRecord( 3605 mTestNotificationChannel, 1, null, true); 3606 final NotificationRecord notif2 = generateNotificationRecord( 3607 mTestNotificationChannel, 2, null, false); 3608 mService.addNotification(notif1); 3609 mService.addNotification(notif2); 3610 3611 // on broadcast, hide the 2 notifications 3612 mService.simulatePackageSuspendBroadcast(true, PKG); 3613 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class); 3614 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 3615 assertEquals(2, captorHide.getValue().size()); 3616 3617 // on broadcast, unhide the 2 notifications 3618 mService.simulatePackageSuspendBroadcast(false, PKG); 3619 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class); 3620 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 3621 assertEquals(2, captorUnhide.getValue().size()); 3622 } 3623 3624 @Test testNoNotificationsHiddenOnSuspendedPackageBroadcast()3625 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() { 3626 // post 2 notification from this package 3627 final NotificationRecord notif1 = generateNotificationRecord( 3628 mTestNotificationChannel, 1, null, true); 3629 final NotificationRecord notif2 = generateNotificationRecord( 3630 mTestNotificationChannel, 2, null, false); 3631 mService.addNotification(notif1); 3632 mService.addNotification(notif2); 3633 3634 // on broadcast, nothing is hidden since no notifications are of package "test_package" 3635 mService.simulatePackageSuspendBroadcast(true, "test_package"); 3636 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 3637 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 3638 assertEquals(0, captor.getValue().size()); 3639 } 3640 3641 @Test testHideAndUnhideNotificationsOnDistractingPackageBroadcast()3642 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() { 3643 // Post 2 notifications from 2 packages 3644 NotificationRecord pkgA = new NotificationRecord(mContext, 3645 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 3646 mService.addNotification(pkgA); 3647 NotificationRecord pkgB = new NotificationRecord(mContext, 3648 generateSbn("b", 1001, 9, 0), mTestNotificationChannel); 3649 mService.addNotification(pkgB); 3650 3651 // on broadcast, hide one of the packages 3652 mService.simulatePackageDistractionBroadcast( 3653 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"}); 3654 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class); 3655 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 3656 assertEquals(1, captorHide.getValue().size()); 3657 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName()); 3658 3659 // on broadcast, unhide the package 3660 mService.simulatePackageDistractionBroadcast( 3661 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"}); 3662 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class); 3663 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 3664 assertEquals(1, captorUnhide.getValue().size()); 3665 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName()); 3666 } 3667 3668 @Test testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg()3669 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() { 3670 // Post 2 notifications from 2 packages 3671 NotificationRecord pkgA = new NotificationRecord(mContext, 3672 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 3673 mService.addNotification(pkgA); 3674 NotificationRecord pkgB = new NotificationRecord(mContext, 3675 generateSbn("b", 1001, 9, 0), mTestNotificationChannel); 3676 mService.addNotification(pkgB); 3677 3678 // on broadcast, hide one of the packages 3679 mService.simulatePackageDistractionBroadcast( 3680 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"}); 3681 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class); 3682 3683 // should be called only once. 3684 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 3685 assertEquals(2, captorHide.getValue().size()); 3686 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName()); 3687 assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName()); 3688 3689 // on broadcast, unhide the package 3690 mService.simulatePackageDistractionBroadcast( 3691 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"}); 3692 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class); 3693 3694 // should be called only once. 3695 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 3696 assertEquals(2, captorUnhide.getValue().size()); 3697 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName()); 3698 assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName()); 3699 } 3700 3701 @Test testNoNotificationsHiddenOnDistractingPackageBroadcast()3702 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() { 3703 // post notification from this package 3704 final NotificationRecord notif1 = generateNotificationRecord( 3705 mTestNotificationChannel, 1, null, true); 3706 mService.addNotification(notif1); 3707 3708 // on broadcast, nothing is hidden since no notifications are of package "test_package" 3709 mService.simulatePackageDistractionBroadcast( 3710 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"}); 3711 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 3712 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 3713 assertEquals(0, captor.getValue().size()); 3714 } 3715 3716 @Test testCanUseManagedServicesLowRamNoWatchNullPkg()3717 public void testCanUseManagedServicesLowRamNoWatchNullPkg() { 3718 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 3719 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3720 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3721 .thenReturn(new String[] {"a", "b", "c"}); 3722 when(mContext.getResources()).thenReturn(mResources); 3723 3724 assertEquals(false, mService.canUseManagedServices(null, 0, null)); 3725 } 3726 3727 @Test testCanUseManagedServicesLowRamNoWatchValidPkg()3728 public void testCanUseManagedServicesLowRamNoWatchValidPkg() { 3729 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 3730 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3731 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3732 .thenReturn(new String[] {"a", "b", "c"}); 3733 when(mContext.getResources()).thenReturn(mResources); 3734 3735 assertEquals(true, mService.canUseManagedServices("b", 0, null)); 3736 } 3737 3738 @Test testCanUseManagedServicesLowRamNoWatchNoValidPkg()3739 public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() { 3740 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 3741 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3742 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3743 .thenReturn(new String[] {"a", "b", "c"}); 3744 when(mContext.getResources()).thenReturn(mResources); 3745 3746 assertEquals(false, mService.canUseManagedServices("d", 0, null)); 3747 } 3748 3749 @Test testCanUseManagedServicesLowRamWatchNoValidPkg()3750 public void testCanUseManagedServicesLowRamWatchNoValidPkg() { 3751 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 3752 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3753 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3754 .thenReturn(new String[] {"a", "b", "c"}); 3755 when(mContext.getResources()).thenReturn(mResources); 3756 3757 assertEquals(true, mService.canUseManagedServices("d", 0, null)); 3758 } 3759 3760 @Test testCanUseManagedServicesNoLowRamNoWatchValidPkg()3761 public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() { 3762 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 3763 when(mActivityManager.isLowRamDevice()).thenReturn(false); 3764 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3765 .thenReturn(new String[] {"a", "b", "c"}); 3766 when(mContext.getResources()).thenReturn(mResources); 3767 3768 assertEquals(true, mService.canUseManagedServices("d", 0 , null)); 3769 } 3770 3771 @Test testCanUseManagedServicesNoLowRamWatchValidPkg()3772 public void testCanUseManagedServicesNoLowRamWatchValidPkg() { 3773 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 3774 when(mActivityManager.isLowRamDevice()).thenReturn(false); 3775 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices)) 3776 .thenReturn(new String[] {"a", "b", "c"}); 3777 when(mContext.getResources()).thenReturn(mResources); 3778 3779 assertEquals(true, mService.canUseManagedServices("d", 0, null)); 3780 } 3781 3782 @Test testCanUseManagedServices_hasPermission()3783 public void testCanUseManagedServices_hasPermission() throws Exception { 3784 when(mPackageManager.checkPermission("perm", "pkg", 0)) 3785 .thenReturn(PackageManager.PERMISSION_GRANTED); 3786 3787 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm")); 3788 } 3789 3790 @Test testCanUseManagedServices_noPermission()3791 public void testCanUseManagedServices_noPermission() throws Exception { 3792 when(mPackageManager.checkPermission("perm", "pkg", 0)) 3793 .thenReturn(PackageManager.PERMISSION_DENIED); 3794 3795 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm")); 3796 } 3797 3798 @Test testCanUseManagedServices_permDoesNotMatter()3799 public void testCanUseManagedServices_permDoesNotMatter() { 3800 assertEquals(true, mService.canUseManagedServices("pkg", 0, null)); 3801 } 3802 3803 @Test testOnNotificationVisibilityChanged_triggersInterruptionUsageStat()3804 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() { 3805 final NotificationRecord r = generateNotificationRecord( 3806 mTestNotificationChannel, 1, null, true); 3807 r.setTextChanged(true); 3808 mService.addNotification(r); 3809 3810 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[] 3811 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}, 3812 new NotificationVisibility[]{}); 3813 3814 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt()); 3815 } 3816 3817 @Test testSetNotificationsShownFromListener_triggersInterruptionUsageStat()3818 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat() 3819 throws RemoteException { 3820 final NotificationRecord r = generateNotificationRecord( 3821 mTestNotificationChannel, 1, null, true); 3822 r.setTextChanged(true); 3823 mService.addNotification(r); 3824 3825 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()}); 3826 3827 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt()); 3828 } 3829 3830 @Test testMaybeRecordInterruptionLocked_doesNotRecordTwice()3831 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice() 3832 throws RemoteException { 3833 final NotificationRecord r = generateNotificationRecord( 3834 mTestNotificationChannel, 1, null, true); 3835 r.setInterruptive(true); 3836 mService.addNotification(r); 3837 3838 mService.maybeRecordInterruptionLocked(r); 3839 mService.maybeRecordInterruptionLocked(r); 3840 3841 verify(mAppUsageStats, times(1)).reportInterruptiveNotification( 3842 anyString(), anyString(), anyInt()); 3843 } 3844 3845 @Test testBubble()3846 public void testBubble() throws Exception { 3847 mBinderService.setBubblesAllowed(PKG, mUid, false); 3848 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid)); 3849 } 3850 3851 @Test testUserApprovedBubblesForPackage()3852 public void testUserApprovedBubblesForPackage() throws Exception { 3853 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid)); 3854 mBinderService.setBubblesAllowed(PKG, mUid, true); 3855 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid)); 3856 assertTrue(mBinderService.areBubblesAllowedForPackage(PKG, mUid)); 3857 } 3858 3859 @Test testUserRejectsBubblesForPackage()3860 public void testUserRejectsBubblesForPackage() throws Exception { 3861 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid)); 3862 mBinderService.setBubblesAllowed(PKG, mUid, false); 3863 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid)); 3864 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid)); 3865 } 3866 3867 @Test testIsCallerInstantApp_primaryUser()3868 public void testIsCallerInstantApp_primaryUser() throws Exception { 3869 ApplicationInfo info = new ApplicationInfo(); 3870 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 3871 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info); 3872 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 3873 3874 assertTrue(mService.isCallerInstantApp(45770, 0)); 3875 3876 info.privateFlags = 0; 3877 assertFalse(mService.isCallerInstantApp(575370, 0)); 3878 } 3879 3880 @Test testIsCallerInstantApp_secondaryUser()3881 public void testIsCallerInstantApp_secondaryUser() throws Exception { 3882 ApplicationInfo info = new ApplicationInfo(); 3883 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 3884 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info); 3885 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null); 3886 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 3887 3888 assertTrue(mService.isCallerInstantApp(68638450, 10)); 3889 } 3890 3891 @Test testIsCallerInstantApp_userAllNotification()3892 public void testIsCallerInstantApp_userAllNotification() throws Exception { 3893 ApplicationInfo info = new ApplicationInfo(); 3894 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 3895 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(UserHandle.USER_SYSTEM))) 3896 .thenReturn(info); 3897 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 3898 3899 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL)); 3900 3901 info.privateFlags = 0; 3902 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL )); 3903 } 3904 3905 @Test testResolveNotificationUid_sameApp_nonSystemUser()3906 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception { 3907 ApplicationInfo info = new ApplicationInfo(); 3908 info.uid = Binder.getCallingUid(); 3909 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info); 3910 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null); 3911 3912 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10); 3913 3914 assertEquals(info.uid, actualUid); 3915 } 3916 3917 @Test testResolveNotificationUid_sameApp()3918 public void testResolveNotificationUid_sameApp() throws Exception { 3919 ApplicationInfo info = new ApplicationInfo(); 3920 info.uid = Binder.getCallingUid(); 3921 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info); 3922 3923 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0); 3924 3925 assertEquals(info.uid, actualUid); 3926 } 3927 3928 @Test testResolveNotificationUid_sameAppDiffPackage()3929 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception { 3930 ApplicationInfo info = new ApplicationInfo(); 3931 info.uid = Binder.getCallingUid(); 3932 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info); 3933 3934 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0); 3935 3936 assertEquals(info.uid, actualUid); 3937 } 3938 3939 @Test testResolveNotificationUid_sameAppWrongUid()3940 public void testResolveNotificationUid_sameAppWrongUid() throws Exception { 3941 ApplicationInfo info = new ApplicationInfo(); 3942 info.uid = 1356347; 3943 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info); 3944 3945 try { 3946 mService.resolveNotificationUid("caller", "caller", 9, 0); 3947 fail("Incorrect uid didn't throw security exception"); 3948 } catch (SecurityException e) { 3949 // yay 3950 } 3951 } 3952 3953 @Test testResolveNotificationUid_delegateAllowed()3954 public void testResolveNotificationUid_delegateAllowed() throws Exception { 3955 int expectedUid = 123; 3956 3957 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid); 3958 mService.setPreferencesHelper(mPreferencesHelper); 3959 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt())) 3960 .thenReturn(true); 3961 3962 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0)); 3963 } 3964 3965 @Test testResolveNotificationUid_androidAllowed()3966 public void testResolveNotificationUid_androidAllowed() throws Exception { 3967 int expectedUid = 123; 3968 3969 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid); 3970 // no delegate 3971 3972 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0)); 3973 } 3974 3975 @Test testResolveNotificationUid_delegateNotAllowed()3976 public void testResolveNotificationUid_delegateNotAllowed() throws Exception { 3977 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123); 3978 // no delegate 3979 3980 try { 3981 mService.resolveNotificationUid("caller", "target", 9, 0); 3982 fail("Incorrect uid didn't throw security exception"); 3983 } catch (SecurityException e) { 3984 // yay 3985 } 3986 } 3987 3988 @Test testRemoveForegroundServiceFlagFromNotification_enqueued()3989 public void testRemoveForegroundServiceFlagFromNotification_enqueued() { 3990 Notification n = new Notification.Builder(mContext, "").build(); 3991 n.flags |= FLAG_FOREGROUND_SERVICE; 3992 3993 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 3994 n, new UserHandle(mUid), null, 0); 3995 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 3996 3997 mService.addEnqueuedNotification(r); 3998 3999 mInternalService.removeForegroundServiceFlagFromNotification( 4000 PKG, r.sbn.getId(), r.sbn.getUserId()); 4001 4002 waitForIdle(); 4003 4004 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any()); 4005 } 4006 4007 @Test testRemoveForegroundServiceFlagFromNotification_posted()4008 public void testRemoveForegroundServiceFlagFromNotification_posted() { 4009 Notification n = new Notification.Builder(mContext, "").build(); 4010 n.flags |= FLAG_FOREGROUND_SERVICE; 4011 4012 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 4013 n, new UserHandle(mUid), null, 0); 4014 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4015 4016 mService.addNotification(r); 4017 4018 mInternalService.removeForegroundServiceFlagFromNotification( 4019 PKG, r.sbn.getId(), r.sbn.getUserId()); 4020 4021 waitForIdle(); 4022 4023 ArgumentCaptor<NotificationRecord> captor = 4024 ArgumentCaptor.forClass(NotificationRecord.class); 4025 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any()); 4026 4027 assertEquals(0, captor.getValue().getNotification().flags); 4028 } 4029 4030 @Test testAllowForegroundToasts()4031 public void testAllowForegroundToasts() throws Exception { 4032 final String testPackage = "testPackageName"; 4033 assertEquals(0, mService.mToastQueue.size()); 4034 mService.isSystemUid = false; 4035 4036 // package is not suspended 4037 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 4038 .thenReturn(false); 4039 4040 // notifications from this package are blocked by the user 4041 mService.setPreferencesHelper(mPreferencesHelper); 4042 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); 4043 4044 // this app is in the foreground 4045 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND); 4046 4047 // enqueue toast -> toast should still enqueue 4048 ((INotificationManager)mService.mService).enqueueToast(testPackage, 4049 new TestableToastCallback(), 2000, 0); 4050 assertEquals(1, mService.mToastQueue.size()); 4051 } 4052 4053 @Test testDisallowToastsFromSuspendedPackages()4054 public void testDisallowToastsFromSuspendedPackages() throws Exception { 4055 final String testPackage = "testPackageName"; 4056 assertEquals(0, mService.mToastQueue.size()); 4057 mService.isSystemUid = false; 4058 4059 // package is suspended 4060 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 4061 .thenReturn(true); 4062 4063 // notifications from this package are NOT blocked by the user 4064 mService.setPreferencesHelper(mPreferencesHelper); 4065 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW); 4066 4067 // enqueue toast -> no toasts enqueued 4068 ((INotificationManager)mService.mService).enqueueToast(testPackage, 4069 new TestableToastCallback(), 2000, 0); 4070 assertEquals(0, mService.mToastQueue.size()); 4071 } 4072 4073 @Test testDisallowToastsFromBlockedApps()4074 public void testDisallowToastsFromBlockedApps() throws Exception { 4075 final String testPackage = "testPackageName"; 4076 assertEquals(0, mService.mToastQueue.size()); 4077 mService.isSystemUid = false; 4078 4079 // package is not suspended 4080 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 4081 .thenReturn(false); 4082 4083 // notifications from this package are blocked by the user 4084 mService.setPreferencesHelper(mPreferencesHelper); 4085 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); 4086 4087 // this app is NOT in the foreground 4088 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE); 4089 4090 // enqueue toast -> no toasts enqueued 4091 ((INotificationManager)mService.mService).enqueueToast(testPackage, 4092 new TestableToastCallback(), 2000, 0); 4093 assertEquals(0, mService.mToastQueue.size()); 4094 } 4095 4096 @Test testAlwaysAllowSystemToasts()4097 public void testAlwaysAllowSystemToasts() throws Exception { 4098 final String testPackage = "testPackageName"; 4099 assertEquals(0, mService.mToastQueue.size()); 4100 mService.isSystemUid = true; 4101 4102 // package is suspended 4103 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 4104 .thenReturn(true); 4105 4106 // notifications from this package ARE blocked by the user 4107 mService.setPreferencesHelper(mPreferencesHelper); 4108 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); 4109 4110 // this app is NOT in the foreground 4111 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE); 4112 4113 // enqueue toast -> system toast can still be enqueued 4114 ((INotificationManager)mService.mService).enqueueToast(testPackage, 4115 new TestableToastCallback(), 2000, 0); 4116 assertEquals(1, mService.mToastQueue.size()); 4117 } 4118 4119 @Test testOnNotificationSmartReplySent()4120 public void testOnNotificationSmartReplySent() { 4121 final int replyIndex = 2; 4122 final String reply = "Hello"; 4123 final boolean modifiedBeforeSending = true; 4124 final boolean generatedByAssistant = true; 4125 4126 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 4127 r.setSuggestionsGeneratedByAssistant(generatedByAssistant); 4128 mService.addNotification(r); 4129 4130 mService.mNotificationDelegate.onNotificationSmartReplySent( 4131 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN, 4132 modifiedBeforeSending); 4133 verify(mAssistants).notifyAssistantSuggestedReplySent( 4134 eq(r.sbn), eq(reply), eq(generatedByAssistant)); 4135 } 4136 4137 @Test testOnNotificationActionClick()4138 public void testOnNotificationActionClick() { 4139 final int actionIndex = 2; 4140 final Notification.Action action = 4141 new Notification.Action.Builder(null, "text", null).build(); 4142 final boolean generatedByAssistant = false; 4143 4144 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 4145 mService.addNotification(r); 4146 4147 NotificationVisibility notificationVisibility = 4148 NotificationVisibility.obtain(r.getKey(), 1, 2, true); 4149 mService.mNotificationDelegate.onNotificationActionClick( 4150 10, 10, r.getKey(), actionIndex, action, notificationVisibility, 4151 generatedByAssistant); 4152 verify(mAssistants).notifyAssistantActionClicked( 4153 eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant)); 4154 } 4155 4156 @Test testLogSmartSuggestionsVisible_triggerOnExpandAndVisible()4157 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() { 4158 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 4159 mService.addNotification(r); 4160 4161 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 4162 NOTIFICATION_LOCATION_UNKNOWN); 4163 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] { 4164 NotificationVisibility.obtain(r.getKey(), 0, 0, true) 4165 }; 4166 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility, 4167 new NotificationVisibility[0]); 4168 4169 assertEquals(1, mService.countLogSmartSuggestionsVisible); 4170 } 4171 4172 @Test testLogSmartSuggestionsVisible_noTriggerOnExpand()4173 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() { 4174 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 4175 mService.addNotification(r); 4176 4177 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 4178 NOTIFICATION_LOCATION_UNKNOWN); 4179 4180 assertEquals(0, mService.countLogSmartSuggestionsVisible); 4181 } 4182 4183 @Test testLogSmartSuggestionsVisible_noTriggerOnVisible()4184 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() { 4185 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 4186 mService.addNotification(r); 4187 4188 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{ 4189 NotificationVisibility.obtain(r.getKey(), 0, 0, true) 4190 }; 4191 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility, 4192 new NotificationVisibility[0]); 4193 4194 assertEquals(0, mService.countLogSmartSuggestionsVisible); 4195 } 4196 4197 @Test testReportSeen_delegated()4198 public void testReportSeen_delegated() { 4199 Notification.Builder nb = 4200 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 4201 .setContentTitle("foo") 4202 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4203 4204 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0, 4205 nb.build(), new UserHandle(mUid), null, 0); 4206 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4207 4208 mService.reportSeen(r); 4209 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt()); 4210 4211 } 4212 4213 @Test testReportSeen_notDelegated()4214 public void testReportSeen_notDelegated() { 4215 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 4216 4217 mService.reportSeen(r); 4218 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt()); 4219 } 4220 4221 @Test testNotificationStats_notificationError()4222 public void testNotificationStats_notificationError() { 4223 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 4224 mService.addNotification(r); 4225 4226 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, 4227 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(), 4228 new UserHandle(mUid), null, 0); 4229 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4230 mService.addEnqueuedNotification(update); 4231 assertNull(update.sbn.getNotification().getSmallIcon()); 4232 4233 NotificationManagerService.PostNotificationRunnable runnable = 4234 mService.new PostNotificationRunnable(update.getKey()); 4235 runnable.run(); 4236 waitForIdle(); 4237 4238 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 4239 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture()); 4240 assertNotNull(captor.getValue()); 4241 } 4242 4243 @Test testCanNotifyAsUser_crossUser()4244 public void testCanNotifyAsUser_crossUser() throws Exception { 4245 // same user no problem 4246 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId()); 4247 4248 // cross user, no permission, problem 4249 try { 4250 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); 4251 fail("Should not be callable cross user without cross user permission"); 4252 } catch (SecurityException e) { 4253 // good 4254 } 4255 4256 // cross user, with permission, no problem 4257 TestablePermissions perms = mContext.getTestablePermissions(); 4258 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); 4259 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); 4260 } 4261 4262 @Test testgetNotificationChannels_crossUser()4263 public void testgetNotificationChannels_crossUser() throws Exception { 4264 // same user no problem 4265 mBinderService.getNotificationChannels("src", "target", mContext.getUserId()); 4266 4267 // cross user, no permission, problem 4268 try { 4269 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); 4270 fail("Should not be callable cross user without cross user permission"); 4271 } catch (SecurityException e) { 4272 // good 4273 } 4274 4275 // cross user, with permission, no problem 4276 TestablePermissions perms = mContext.getTestablePermissions(); 4277 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); 4278 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); 4279 } 4280 4281 @Test setDefaultAssistantForUser_fromConfigXml()4282 public void setDefaultAssistantForUser_fromConfigXml() { 4283 clearDeviceConfig(); 4284 ComponentName xmlConfig = new ComponentName("config", "xml"); 4285 when(mResources 4286 .getString( 4287 com.android.internal.R.string.config_defaultAssistantAccessComponent)) 4288 .thenReturn(xmlConfig.flattenToString()); 4289 when(mContext.getResources()).thenReturn(mResources); 4290 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0))) 4291 .thenReturn(Collections.singleton(xmlConfig)); 4292 mService.setNotificationAssistantAccessGrantedCallback( 4293 mNotificationAssistantAccessGrantedCallback); 4294 4295 mService.setDefaultAssistantForUser(0); 4296 4297 verify(mNotificationAssistantAccessGrantedCallback) 4298 .onGranted(eq(xmlConfig), eq(0), eq(true)); 4299 } 4300 4301 @Test setDefaultAssistantForUser_fromDeviceConfig()4302 public void setDefaultAssistantForUser_fromDeviceConfig() { 4303 ComponentName xmlConfig = new ComponentName("xml", "config"); 4304 ComponentName deviceConfig = new ComponentName("device", "config"); 4305 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString()); 4306 when(mResources 4307 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent)) 4308 .thenReturn(xmlConfig.flattenToString()); 4309 when(mContext.getResources()).thenReturn(mResources); 4310 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0))) 4311 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig))); 4312 mService.setNotificationAssistantAccessGrantedCallback( 4313 mNotificationAssistantAccessGrantedCallback); 4314 4315 mService.setDefaultAssistantForUser(0); 4316 4317 verify(mNotificationAssistantAccessGrantedCallback) 4318 .onGranted(eq(deviceConfig), eq(0), eq(true)); 4319 } 4320 4321 @Test setDefaultAssistantForUser_deviceConfigInvalid()4322 public void setDefaultAssistantForUser_deviceConfigInvalid() { 4323 ComponentName xmlConfig = new ComponentName("xml", "config"); 4324 ComponentName deviceConfig = new ComponentName("device", "config"); 4325 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString()); 4326 when(mResources 4327 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent)) 4328 .thenReturn(xmlConfig.flattenToString()); 4329 when(mContext.getResources()).thenReturn(mResources); 4330 // Only xmlConfig is valid, deviceConfig is not. 4331 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0))) 4332 .thenReturn(Collections.singleton(xmlConfig)); 4333 mService.setNotificationAssistantAccessGrantedCallback( 4334 mNotificationAssistantAccessGrantedCallback); 4335 4336 mService.setDefaultAssistantForUser(0); 4337 4338 verify(mNotificationAssistantAccessGrantedCallback) 4339 .onGranted(eq(xmlConfig), eq(0), eq(true)); 4340 } 4341 4342 @Test testFlagBubble()4343 public void testFlagBubble() throws RemoteException { 4344 // Bubbles are allowed! 4345 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4346 4347 // Notif with bubble metadata but not our other misc requirements 4348 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 4349 null /* tvExtender */, true /* isBubble */); 4350 4351 // Say we're foreground 4352 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( 4353 IMPORTANCE_FOREGROUND); 4354 4355 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 4356 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4357 waitForIdle(); 4358 4359 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 4360 assertEquals(1, notifs.length); 4361 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0); 4362 assertTrue(mService.getNotificationRecord( 4363 nr.sbn.getKey()).getNotification().isBubbleNotification()); 4364 } 4365 4366 @Test testFlagBubble_noFlag_appNotAllowed()4367 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException { 4368 // Bubbles are allowed! 4369 setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */); 4370 4371 // Notif with bubble metadata but not our other misc requirements 4372 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 4373 null /* tvExtender */, true /* isBubble */); 4374 4375 // Say we're foreground 4376 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( 4377 IMPORTANCE_FOREGROUND); 4378 4379 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 4380 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4381 waitForIdle(); 4382 4383 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 4384 assertEquals(1, notifs.length); 4385 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0); 4386 assertFalse(mService.getNotificationRecord( 4387 nr.sbn.getKey()).getNotification().isBubbleNotification()); 4388 } 4389 4390 @Test testFlagBubbleNotifs_flag_appForeground()4391 public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException { 4392 // Bubbles are allowed! 4393 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4394 4395 // Notif with bubble metadata but not our other misc requirements 4396 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 4397 null /* tvExtender */, true /* isBubble */); 4398 4399 // Say we're foreground 4400 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( 4401 IMPORTANCE_FOREGROUND); 4402 4403 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 4404 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4405 waitForIdle(); 4406 4407 // yes allowed, yes foreground, yes bubble 4408 assertTrue(mService.getNotificationRecord( 4409 nr.sbn.getKey()).getNotification().isBubbleNotification()); 4410 } 4411 4412 @Test testFlagBubbleNotifs_noFlag_appNotForeground()4413 public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException { 4414 // Bubbles are allowed! 4415 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4416 4417 // Notif with bubble metadata but not our other misc requirements 4418 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 4419 null /* tvExtender */, true /* isBubble */); 4420 4421 // Make sure we're NOT foreground 4422 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( 4423 IMPORTANCE_VISIBLE); 4424 4425 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 4426 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4427 waitForIdle(); 4428 4429 // yes allowed but NOT foreground, no bubble 4430 assertFalse(mService.getNotificationRecord( 4431 nr.sbn.getKey()).getNotification().isBubbleNotification()); 4432 } 4433 4434 @Test testFlagBubbleNotifs_flag_previousForegroundFlag()4435 public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException { 4436 // Bubbles are allowed! 4437 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4438 4439 // Notif with bubble metadata but not our other misc requirements 4440 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel, 4441 null /* tvExtender */, true /* isBubble */); 4442 4443 // Send notif when we're foreground 4444 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn( 4445 IMPORTANCE_FOREGROUND); 4446 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 4447 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId()); 4448 waitForIdle(); 4449 4450 // yes allowed, yes foreground, yes bubble 4451 assertTrue(mService.getNotificationRecord( 4452 nr1.sbn.getKey()).getNotification().isBubbleNotification()); 4453 4454 // Send a new update when we're not foreground 4455 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel, 4456 null /* tvExtender */, true /* isBubble */); 4457 4458 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn( 4459 IMPORTANCE_VISIBLE); 4460 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 4461 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId()); 4462 waitForIdle(); 4463 4464 // yes allowed, previously foreground / flagged, yes bubble 4465 assertTrue(mService.getNotificationRecord( 4466 nr2.sbn.getKey()).getNotification().isBubbleNotification()); 4467 4468 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG); 4469 assertEquals(1, notifs2.length); 4470 assertEquals(1, mService.getNotificationRecordCount()); 4471 } 4472 4473 @Test testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()4474 public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval() 4475 throws RemoteException { 4476 // Bubbles are allowed! 4477 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4478 4479 // Notif with bubble metadata but not our other misc requirements 4480 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel, 4481 null /* tvExtender */, true /* isBubble */); 4482 4483 // Send notif when we're foreground 4484 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn( 4485 IMPORTANCE_FOREGROUND); 4486 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 4487 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId()); 4488 waitForIdle(); 4489 4490 // yes allowed, yes foreground, yes bubble 4491 assertTrue(mService.getNotificationRecord( 4492 nr1.sbn.getKey()).getNotification().isBubbleNotification()); 4493 4494 // Remove the bubble 4495 mBinderService.cancelNotificationWithTag(PKG, "tag", nr1.sbn.getId(), 4496 nr1.sbn.getUserId()); 4497 waitForIdle(); 4498 4499 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 4500 assertEquals(0, notifs.length); 4501 assertEquals(0, mService.getNotificationRecordCount()); 4502 4503 // Send a new update when we're not foreground 4504 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel, 4505 null /* tvExtender */, true /* isBubble */); 4506 4507 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn( 4508 IMPORTANCE_VISIBLE); 4509 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 4510 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId()); 4511 waitForIdle(); 4512 4513 // yes allowed, but was removed & no foreground, so no bubble 4514 assertFalse(mService.getNotificationRecord( 4515 nr2.sbn.getKey()).getNotification().isBubbleNotification()); 4516 4517 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG); 4518 assertEquals(1, notifs2.length); 4519 assertEquals(1, mService.getNotificationRecordCount()); 4520 } 4521 4522 @Test testFlagBubbleNotifs_flag_messaging()4523 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException { 4524 // Bubbles are allowed! 4525 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4526 4527 // Give it bubble metadata 4528 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); 4529 // Give it a person 4530 Person person = new Person.Builder() 4531 .setName("bubblebot") 4532 .build(); 4533 // It needs remote input to be bubble-able 4534 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); 4535 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); 4536 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); 4537 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", 4538 inputIntent).addRemoteInput(remoteInput) 4539 .build(); 4540 // Make it messaging style 4541 Notification.Builder nb = new Notification.Builder(mContext, 4542 mTestNotificationChannel.getId()) 4543 .setContentTitle("foo") 4544 .setBubbleMetadata(data) 4545 .setStyle(new Notification.MessagingStyle(person) 4546 .setConversationTitle("Bubble Chat") 4547 .addMessage("Hello?", 4548 SystemClock.currentThreadTimeMillis() - 300000, person) 4549 .addMessage("Is it me you're looking for?", 4550 SystemClock.currentThreadTimeMillis(), person) 4551 ) 4552 .setActions(replyAction) 4553 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4554 4555 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 4556 nb.build(), new UserHandle(mUid), null, 0); 4557 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4558 4559 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 4560 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4561 waitForIdle(); 4562 4563 // yes allowed, yes messaging, yes bubble 4564 assertTrue(mService.getNotificationRecord( 4565 sbn.getKey()).getNotification().isBubbleNotification()); 4566 } 4567 4568 @Test testFlagBubbleNotifs_flag_phonecall()4569 public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException { 4570 // Bubbles are allowed! 4571 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4572 4573 // Give it bubble metadata 4574 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); 4575 // Give it a person 4576 Person person = new Person.Builder() 4577 .setName("bubblebot") 4578 .build(); 4579 // Make it a phone call 4580 Notification.Builder nb = new Notification.Builder(mContext, 4581 mTestNotificationChannel.getId()) 4582 .setCategory(CATEGORY_CALL) 4583 .addPerson(person) 4584 .setContentTitle("foo") 4585 .setBubbleMetadata(data) 4586 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4587 4588 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 4589 nb.build(), new UserHandle(mUid), null, 0); 4590 // Make sure it has foreground service 4591 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 4592 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4593 4594 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 4595 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4596 waitForIdle(); 4597 4598 // yes phone call, yes person, yes foreground service, yes bubble 4599 assertTrue(mService.getNotificationRecord( 4600 sbn.getKey()).getNotification().isBubbleNotification()); 4601 } 4602 4603 @Test testFlagBubbleNotifs_noFlag_phonecall_noForegroundService()4604 public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException { 4605 // Bubbles are allowed! 4606 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4607 4608 // Give it bubble metadata 4609 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); 4610 // Give it a person 4611 Person person = new Person.Builder() 4612 .setName("bubblebot") 4613 .build(); 4614 // Make it a phone call 4615 Notification.Builder nb = new Notification.Builder(mContext, 4616 mTestNotificationChannel.getId()) 4617 .setCategory(CATEGORY_CALL) 4618 .addPerson(person) 4619 .setContentTitle("foo") 4620 .setBubbleMetadata(data) 4621 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4622 4623 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 4624 nb.build(), new UserHandle(mUid), null, 0); 4625 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4626 4627 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 4628 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4629 waitForIdle(); 4630 4631 // yes phone call, yes person, NO foreground service, no bubble 4632 assertFalse(mService.getNotificationRecord( 4633 sbn.getKey()).getNotification().isBubbleNotification()); 4634 } 4635 4636 @Test testFlagBubbleNotifs_noFlag_phonecall_noPerson()4637 public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException { 4638 // Bubbles are allowed! 4639 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4640 4641 // Give it bubble metadata 4642 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); 4643 // Make it a phone call 4644 Notification.Builder nb = new Notification.Builder(mContext, 4645 mTestNotificationChannel.getId()) 4646 .setCategory(CATEGORY_CALL) 4647 .setContentTitle("foo") 4648 .setBubbleMetadata(data) 4649 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4650 4651 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 4652 nb.build(), new UserHandle(mUid), null, 0); 4653 // Make sure it has foreground service 4654 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 4655 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4656 4657 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 4658 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4659 waitForIdle(); 4660 4661 // yes phone call, yes foreground service, BUT NO person, no bubble 4662 assertFalse(mService.getNotificationRecord( 4663 sbn.getKey()).getNotification().isBubbleNotification()); 4664 } 4665 4666 @Test testFlagBubbleNotifs_noFlag_phonecall_noCategory()4667 public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException { 4668 // Bubbles are allowed! 4669 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4670 4671 // Give it bubble metadata 4672 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); 4673 // Give it a person 4674 Person person = new Person.Builder() 4675 .setName("bubblebot") 4676 .build(); 4677 // No category 4678 Notification.Builder nb = new Notification.Builder(mContext, 4679 mTestNotificationChannel.getId()) 4680 .addPerson(person) 4681 .setContentTitle("foo") 4682 .setBubbleMetadata(data) 4683 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4684 4685 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 4686 nb.build(), new UserHandle(mUid), null, 0); 4687 // Make sure it has foreground service 4688 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 4689 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4690 4691 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 4692 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4693 waitForIdle(); 4694 4695 // yes person, yes foreground service, BUT NO call, no bubble 4696 assertFalse(mService.getNotificationRecord( 4697 sbn.getKey()).getNotification().isBubbleNotification()); 4698 } 4699 4700 @Test testFlagBubbleNotifs_noFlag_messaging_appNotAllowed()4701 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException { 4702 // Bubbles are NOT allowed! 4703 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */); 4704 4705 // Give it bubble metadata 4706 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); 4707 // Give it a person 4708 Person person = new Person.Builder() 4709 .setName("bubblebot") 4710 .build(); 4711 // Make it messaging style 4712 Notification.Builder nb = new Notification.Builder(mContext, 4713 mTestNotificationChannel.getId()) 4714 .setContentTitle("foo") 4715 .setBubbleMetadata(data) 4716 .setStyle(new Notification.MessagingStyle(person) 4717 .setConversationTitle("Bubble Chat") 4718 .addMessage("Hello?", 4719 SystemClock.currentThreadTimeMillis() - 300000, person) 4720 .addMessage("Is it me you're looking for?", 4721 SystemClock.currentThreadTimeMillis(), person) 4722 ) 4723 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4724 4725 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 4726 nb.build(), new UserHandle(mUid), null, 0); 4727 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4728 4729 // Post the notification 4730 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 4731 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4732 waitForIdle(); 4733 4734 // not allowed, no bubble 4735 assertFalse(mService.getNotificationRecord( 4736 sbn.getKey()).getNotification().isBubbleNotification()); 4737 } 4738 4739 @Test testFlagBubbleNotifs_noFlag_notBubble()4740 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException { 4741 // Bubbles are allowed! 4742 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 4743 4744 // Notif WITHOUT bubble metadata 4745 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 4746 4747 // Post the notification 4748 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 4749 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4750 waitForIdle(); 4751 4752 // no bubble metadata, no bubble 4753 assertFalse(mService.getNotificationRecord( 4754 nr.sbn.getKey()).getNotification().isBubbleNotification()); 4755 } 4756 4757 @Test testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed()4758 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException { 4759 // Bubbles are allowed except on this channel 4760 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */); 4761 4762 // Give it bubble metadata 4763 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); 4764 // Give it a person 4765 Person person = new Person.Builder() 4766 .setName("bubblebot") 4767 .build(); 4768 // Make it messaging style 4769 Notification.Builder nb = new Notification.Builder(mContext, 4770 mTestNotificationChannel.getId()) 4771 .setContentTitle("foo") 4772 .setBubbleMetadata(data) 4773 .setStyle(new Notification.MessagingStyle(person) 4774 .setConversationTitle("Bubble Chat") 4775 .addMessage("Hello?", 4776 SystemClock.currentThreadTimeMillis() - 300000, person) 4777 .addMessage("Is it me you're looking for?", 4778 SystemClock.currentThreadTimeMillis(), person) 4779 ) 4780 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4781 4782 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 4783 nb.build(), new UserHandle(mUid), null, 0); 4784 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4785 4786 // Post the notification 4787 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 4788 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4789 waitForIdle(); 4790 4791 // channel not allowed, no bubble 4792 assertFalse(mService.getNotificationRecord( 4793 sbn.getKey()).getNotification().isBubbleNotification()); 4794 } 4795 4796 @Test testFlagBubbleNotifs_noFlag_phonecall_notAllowed()4797 public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException { 4798 // Bubbles are not allowed! 4799 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */); 4800 4801 // Give it bubble metadata 4802 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); 4803 // Give it a person 4804 Person person = new Person.Builder() 4805 .setName("bubblebot") 4806 .build(); 4807 // Make it a phone call 4808 Notification.Builder nb = new Notification.Builder(mContext, 4809 mTestNotificationChannel.getId()) 4810 .setCategory(CATEGORY_CALL) 4811 .addPerson(person) 4812 .setContentTitle("foo") 4813 .setBubbleMetadata(data) 4814 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4815 4816 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 4817 nb.build(), new UserHandle(mUid), null, 0); 4818 // Make sure it has foreground service 4819 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 4820 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4821 4822 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 4823 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4824 waitForIdle(); 4825 4826 // yes phone call, yes person, yes foreground service, but not allowed, no bubble 4827 assertFalse(mService.getNotificationRecord( 4828 sbn.getKey()).getNotification().isBubbleNotification()); 4829 } 4830 4831 @Test testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed()4832 public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException { 4833 // Bubbles are allowed, but not on channel. 4834 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */); 4835 4836 // Give it bubble metadata 4837 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); 4838 // Give it a person 4839 Person person = new Person.Builder() 4840 .setName("bubblebot") 4841 .build(); 4842 // Make it a phone call 4843 Notification.Builder nb = new Notification.Builder(mContext, 4844 mTestNotificationChannel.getId()) 4845 .setCategory(CATEGORY_CALL) 4846 .addPerson(person) 4847 .setContentTitle("foo") 4848 .setBubbleMetadata(data) 4849 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4850 4851 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 4852 nb.build(), new UserHandle(mUid), null, 0); 4853 // Make sure it has foreground service 4854 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 4855 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4856 4857 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 4858 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 4859 waitForIdle(); 4860 4861 // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble 4862 assertFalse(mService.getNotificationRecord( 4863 sbn.getKey()).getNotification().isBubbleNotification()); 4864 } 4865 4866 @Test testCancelAllNotifications_cancelsBubble()4867 public void testCancelAllNotifications_cancelsBubble() throws Exception { 4868 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 4869 nr.sbn.getNotification().flags |= FLAG_BUBBLE; 4870 mService.addNotification(nr); 4871 4872 mBinderService.cancelAllNotifications(PKG, nr.sbn.getUserId()); 4873 waitForIdle(); 4874 4875 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 4876 assertEquals(0, notifs.length); 4877 assertEquals(0, mService.getNotificationRecordCount()); 4878 } 4879 4880 @Test testAppCancelNotifications_cancelsBubbles()4881 public void testAppCancelNotifications_cancelsBubbles() throws Exception { 4882 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); 4883 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE; 4884 4885 // Post the notification 4886 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 4887 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId()); 4888 waitForIdle(); 4889 4890 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 4891 assertEquals(1, notifs.length); 4892 assertEquals(1, mService.getNotificationRecordCount()); 4893 4894 mBinderService.cancelNotificationWithTag(PKG, null, nrBubble.sbn.getId(), 4895 nrBubble.sbn.getUserId()); 4896 waitForIdle(); 4897 4898 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG); 4899 assertEquals(0, notifs2.length); 4900 assertEquals(0, mService.getNotificationRecordCount()); 4901 } 4902 4903 @Test testCancelAllNotificationsFromListener_ignoresBubbles()4904 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception { 4905 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel); 4906 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); 4907 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE; 4908 4909 mService.addNotification(nrNormal); 4910 mService.addNotification(nrBubble); 4911 4912 mService.getBinderService().cancelNotificationsFromListener(null, null); 4913 waitForIdle(); 4914 4915 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 4916 assertEquals(1, notifs.length); 4917 assertEquals(1, mService.getNotificationRecordCount()); 4918 } 4919 4920 @Test testCancelNotificationsFromListener_ignoresBubbles()4921 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception { 4922 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel); 4923 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); 4924 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE; 4925 4926 mService.addNotification(nrNormal); 4927 mService.addNotification(nrBubble); 4928 4929 String[] keys = {nrNormal.sbn.getKey(), nrBubble.sbn.getKey()}; 4930 mService.getBinderService().cancelNotificationsFromListener(null, keys); 4931 waitForIdle(); 4932 4933 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 4934 assertEquals(1, notifs.length); 4935 assertEquals(1, mService.getNotificationRecordCount()); 4936 } 4937 4938 @Test testGetAllowedAssistantAdjustments()4939 public void testGetAllowedAssistantAdjustments() throws Exception { 4940 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null); 4941 assertNotNull(capabilities); 4942 4943 for (int i = capabilities.size() - 1; i >= 0; i--) { 4944 String capability = capabilities.get(i); 4945 mBinderService.disallowAssistantAdjustment(capability); 4946 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size()); 4947 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null); 4948 assertNotNull(currentCapabilities); 4949 assertFalse(currentCapabilities.contains(capability)); 4950 } 4951 } 4952 4953 @Test testAdjustRestrictedKey()4954 public void testAdjustRestrictedKey() throws Exception { 4955 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 4956 mService.addNotification(r); 4957 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 4958 4959 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true); 4960 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false); 4961 4962 Bundle signals = new Bundle(); 4963 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW); 4964 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE); 4965 Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals, 4966 "", r.getUser().getIdentifier()); 4967 4968 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 4969 r.applyAdjustments(); 4970 4971 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance()); 4972 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment()); 4973 } 4974 4975 @Test testAutomaticZenRuleValidation_policyFilterAgreement()4976 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception { 4977 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) 4978 .thenReturn(true); 4979 mService.setZenHelper(mock(ZenModeHelper.class)); 4980 ComponentName owner = new ComponentName(mContext, this.getClass()); 4981 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build(); 4982 boolean isEnabled = true; 4983 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 4984 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled); 4985 4986 try { 4987 mBinderService.addAutomaticZenRule(rule); 4988 fail("Zen policy only applies to priority only mode"); 4989 } catch (IllegalArgumentException e) { 4990 // yay 4991 } 4992 4993 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 4994 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled); 4995 mBinderService.addAutomaticZenRule(rule); 4996 4997 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 4998 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled); 4999 mBinderService.addAutomaticZenRule(rule); 5000 } 5001 5002 @Test testAreNotificationsEnabledForPackage_crossUser()5003 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception { 5004 try { 5005 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), 5006 mUid + UserHandle.PER_USER_RANGE); 5007 fail("Cannot call cross user without permission"); 5008 } catch (SecurityException e) { 5009 // pass 5010 } 5011 5012 // cross user, with permission, no problem 5013 TestablePermissions perms = mContext.getTestablePermissions(); 5014 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); 5015 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), 5016 mUid + UserHandle.PER_USER_RANGE); 5017 } 5018 5019 @Test testAreBubblesAllowedForPackage_crossUser()5020 public void testAreBubblesAllowedForPackage_crossUser() throws Exception { 5021 try { 5022 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(), 5023 mUid + UserHandle.PER_USER_RANGE); 5024 fail("Cannot call cross user without permission"); 5025 } catch (SecurityException e) { 5026 // pass 5027 } 5028 5029 // cross user, with permission, no problem 5030 TestablePermissions perms = mContext.getTestablePermissions(); 5031 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); 5032 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(), 5033 mUid + UserHandle.PER_USER_RANGE); 5034 } 5035 5036 @Test testNotificationBubbleChanged_false()5037 public void testNotificationBubbleChanged_false() throws Exception { 5038 // Bubbles are allowed! 5039 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 5040 5041 // Notif with bubble metadata but not our other misc requirements 5042 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 5043 null /* tvExtender */, true /* isBubble */); 5044 5045 // Say we're foreground 5046 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( 5047 IMPORTANCE_FOREGROUND); 5048 5049 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 5050 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 5051 waitForIdle(); 5052 5053 // Reset as this is called when the notif is first sent 5054 reset(mListeners); 5055 5056 // First we were a bubble 5057 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 5058 assertEquals(1, notifsBefore.length); 5059 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0); 5060 5061 // Notify we're not a bubble 5062 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false); 5063 waitForIdle(); 5064 5065 // Make sure we are not a bubble 5066 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 5067 assertEquals(1, notifsAfter.length); 5068 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 5069 } 5070 5071 @Test testNotificationBubbleChanged_true()5072 public void testNotificationBubbleChanged_true() throws Exception { 5073 // Bubbles are allowed! 5074 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 5075 5076 // Plain notification that has bubble metadata 5077 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 5078 null /* tvExtender */, true /* isBubble */); 5079 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 5080 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 5081 waitForIdle(); 5082 5083 // Would be a normal notification because wouldn't have met requirements to bubble 5084 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 5085 assertEquals(1, notifsBefore.length); 5086 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); 5087 5088 // Make the package foreground so that we're allowed to be a bubble 5089 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( 5090 IMPORTANCE_FOREGROUND); 5091 5092 // Reset as this is called when the notif is first sent 5093 reset(mListeners); 5094 5095 // Notify we are now a bubble 5096 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true); 5097 waitForIdle(); 5098 5099 // Make sure we are a bubble 5100 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 5101 assertEquals(1, notifsAfter.length); 5102 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0); 5103 } 5104 5105 @Test testNotificationBubbleChanged_true_notAllowed()5106 public void testNotificationBubbleChanged_true_notAllowed() throws Exception { 5107 // Bubbles are allowed! 5108 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 5109 5110 // Notif that is not a bubble 5111 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 5112 null /* tvExtender */, true /* isBubble */); 5113 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 5114 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 5115 waitForIdle(); 5116 5117 // Reset as this is called when the notif is first sent 5118 reset(mListeners); 5119 5120 // Would be a normal notification because wouldn't have met requirements to bubble 5121 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 5122 assertEquals(1, notifsBefore.length); 5123 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); 5124 5125 // Notify we are now a bubble 5126 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true); 5127 waitForIdle(); 5128 5129 // We still wouldn't be a bubble because the notification didn't meet requirements 5130 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 5131 assertEquals(1, notifsAfter.length); 5132 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 5133 } 5134 5135 @Test testNotificationBubbles_disabled_lowRamDevice()5136 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception { 5137 // Bubbles are allowed! 5138 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 5139 5140 // Plain notification that has bubble metadata 5141 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 5142 null /* tvExtender */, true /* isBubble */); 5143 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 5144 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 5145 waitForIdle(); 5146 5147 // Would be a normal notification because wouldn't have met requirements to bubble 5148 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 5149 assertEquals(1, notifsBefore.length); 5150 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); 5151 5152 // Make the package foreground so that we're allowed to be a bubble 5153 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( 5154 IMPORTANCE_FOREGROUND); 5155 5156 // And we are low ram 5157 when(mActivityManager.isLowRamDevice()).thenReturn(true); 5158 5159 // We wouldn't be a bubble because the notification didn't meet requirements (low ram) 5160 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 5161 assertEquals(1, notifsAfter.length); 5162 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 5163 } 5164 5165 @Test testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()5166 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground() 5167 throws Exception { 5168 // Bubbles are allowed! 5169 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 5170 5171 // Give it bubble metadata 5172 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder() 5173 .setSuppressNotification(true) 5174 .setAutoExpandBubble(true).build(); 5175 // Give it a person 5176 Person person = new Person.Builder() 5177 .setName("bubblebot") 5178 .build(); 5179 // It needs remote input to be bubble-able 5180 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); 5181 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); 5182 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); 5183 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", 5184 inputIntent).addRemoteInput(remoteInput) 5185 .build(); 5186 // Make it messaging style 5187 Notification.Builder nb = new Notification.Builder(mContext, 5188 mTestNotificationChannel.getId()) 5189 .setContentTitle("foo") 5190 .setBubbleMetadata(data) 5191 .setStyle(new Notification.MessagingStyle(person) 5192 .setConversationTitle("Bubble Chat") 5193 .addMessage("Hello?", 5194 SystemClock.currentThreadTimeMillis() - 300000, person) 5195 .addMessage("Is it me you're looking for?", 5196 SystemClock.currentThreadTimeMillis(), person) 5197 ) 5198 .setActions(replyAction) 5199 .setSmallIcon(android.R.drawable.sym_def_app_icon); 5200 5201 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 5202 nb.build(), new UserHandle(mUid), null, 0); 5203 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 5204 5205 // Ensure we're not foreground 5206 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( 5207 IMPORTANCE_VISIBLE); 5208 5209 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 5210 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 5211 waitForIdle(); 5212 5213 // yes allowed, yes messaging, yes bubble 5214 Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification(); 5215 assertTrue(notif.isBubbleNotification()); 5216 5217 // Our flags should have failed since we're not foreground 5218 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble()); 5219 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed()); 5220 } 5221 5222 @Test testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()5223 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground() 5224 throws RemoteException { 5225 // Bubbles are allowed! 5226 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 5227 5228 // Give it bubble metadata 5229 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder() 5230 .setSuppressNotification(true) 5231 .setAutoExpandBubble(true).build(); 5232 // Give it a person 5233 Person person = new Person.Builder() 5234 .setName("bubblebot") 5235 .build(); 5236 // It needs remote input to be bubble-able 5237 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); 5238 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); 5239 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); 5240 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", 5241 inputIntent).addRemoteInput(remoteInput) 5242 .build(); 5243 // Make it messaging style 5244 Notification.Builder nb = new Notification.Builder(mContext, 5245 mTestNotificationChannel.getId()) 5246 .setContentTitle("foo") 5247 .setBubbleMetadata(data) 5248 .setStyle(new Notification.MessagingStyle(person) 5249 .setConversationTitle("Bubble Chat") 5250 .addMessage("Hello?", 5251 SystemClock.currentThreadTimeMillis() - 300000, person) 5252 .addMessage("Is it me you're looking for?", 5253 SystemClock.currentThreadTimeMillis(), person) 5254 ) 5255 .setActions(replyAction) 5256 .setSmallIcon(android.R.drawable.sym_def_app_icon); 5257 5258 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, 5259 nb.build(), new UserHandle(mUid), null, 0); 5260 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 5261 5262 // Ensure we are in the foreground 5263 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( 5264 IMPORTANCE_FOREGROUND); 5265 5266 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 5267 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); 5268 waitForIdle(); 5269 5270 // yes allowed, yes messaging, yes bubble 5271 Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification(); 5272 assertTrue(notif.isBubbleNotification()); 5273 5274 // Our flags should have failed since we are foreground 5275 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble()); 5276 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed()); 5277 } 5278 5279 @Test testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()5280 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed() 5281 throws Exception { 5282 // Bubbles are allowed! 5283 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 5284 5285 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded( 5286 true /* summaryAutoCancel */); 5287 5288 // Dismiss summary 5289 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2, 5290 true); 5291 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, nrSummary.sbn.getTag(), 5292 nrSummary.sbn.getId(), nrSummary.getUserId(), nrSummary.getKey(), 5293 NotificationStats.DISMISSAL_SHADE, 5294 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv); 5295 waitForIdle(); 5296 5297 // The bubble should still exist 5298 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 5299 assertEquals(1, notifsAfter.length); 5300 } 5301 5302 @Test testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()5303 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked() 5304 throws Exception { 5305 // Bubbles are allowed! 5306 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); 5307 5308 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded( 5309 true /* summaryAutoCancel */); 5310 5311 // Click summary 5312 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2, 5313 true); 5314 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(), 5315 nrSummary.getKey(), nv); 5316 waitForIdle(); 5317 5318 // The bubble should still exist 5319 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 5320 assertEquals(1, notifsAfter.length); 5321 } 5322 } 5323