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