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_VISIBLE; 21 import static android.app.Notification.FLAG_AUTO_CANCEL; 22 import static android.app.Notification.FLAG_BUBBLE; 23 import static android.app.Notification.FLAG_FOREGROUND_SERVICE; 24 import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE; 25 import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL; 26 import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE; 27 import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED; 28 import static android.app.NotificationManager.EXTRA_BLOCKED_STATE; 29 import static android.app.NotificationManager.IMPORTANCE_DEFAULT; 30 import static android.app.NotificationManager.IMPORTANCE_HIGH; 31 import static android.app.NotificationManager.IMPORTANCE_LOW; 32 import static android.app.NotificationManager.IMPORTANCE_MAX; 33 import static android.app.NotificationManager.IMPORTANCE_NONE; 34 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; 35 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS; 36 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS; 37 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT; 38 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE; 39 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 40 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS; 41 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; 42 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; 43 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; 44 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; 45 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; 46 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; 47 import static android.content.pm.PackageManager.FEATURE_WATCH; 48 import static android.content.pm.PackageManager.PERMISSION_DENIED; 49 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 50 import static android.os.Build.VERSION_CODES.O_MR1; 51 import static android.os.Build.VERSION_CODES.P; 52 import static android.os.UserHandle.USER_SYSTEM; 53 import static android.service.notification.Adjustment.KEY_IMPORTANCE; 54 import static android.service.notification.Adjustment.KEY_USER_SENTIMENT; 55 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; 56 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; 57 58 import static junit.framework.Assert.assertEquals; 59 import static junit.framework.Assert.assertFalse; 60 import static junit.framework.Assert.assertNotNull; 61 import static junit.framework.Assert.assertNull; 62 import static junit.framework.Assert.assertTrue; 63 import static junit.framework.Assert.fail; 64 65 import static org.mockito.ArgumentMatchers.isNull; 66 import static org.mockito.Matchers.anyBoolean; 67 import static org.mockito.Matchers.anyLong; 68 import static org.mockito.Matchers.anyString; 69 import static org.mockito.Matchers.eq; 70 import static org.mockito.Mockito.any; 71 import static org.mockito.Mockito.anyInt; 72 import static org.mockito.Mockito.clearInvocations; 73 import static org.mockito.Mockito.doAnswer; 74 import static org.mockito.Mockito.doNothing; 75 import static org.mockito.Mockito.doThrow; 76 import static org.mockito.Mockito.mock; 77 import static org.mockito.Mockito.never; 78 import static org.mockito.Mockito.reset; 79 import static org.mockito.Mockito.spy; 80 import static org.mockito.Mockito.timeout; 81 import static org.mockito.Mockito.times; 82 import static org.mockito.Mockito.verify; 83 import static org.mockito.Mockito.when; 84 85 import android.app.ActivityManager; 86 import android.app.ActivityManagerInternal; 87 import android.app.AlarmManager; 88 import android.app.AppOpsManager; 89 import android.app.AutomaticZenRule; 90 import android.app.IActivityManager; 91 import android.app.INotificationManager; 92 import android.app.ITransientNotification; 93 import android.app.IUriGrantsManager; 94 import android.app.Notification; 95 import android.app.Notification.MessagingStyle.Message; 96 import android.app.NotificationChannel; 97 import android.app.NotificationChannelGroup; 98 import android.app.NotificationManager; 99 import android.app.PendingIntent; 100 import android.app.Person; 101 import android.app.RemoteInput; 102 import android.app.StatsManager; 103 import android.app.admin.DevicePolicyManagerInternal; 104 import android.app.usage.UsageStatsManagerInternal; 105 import android.companion.ICompanionDeviceManager; 106 import android.content.ComponentName; 107 import android.content.ContentUris; 108 import android.content.Context; 109 import android.content.Intent; 110 import android.content.pm.ActivityInfo; 111 import android.content.pm.ApplicationInfo; 112 import android.content.pm.IPackageManager; 113 import android.content.pm.LauncherApps; 114 import android.content.pm.PackageManager; 115 import android.content.pm.PackageManagerInternal; 116 import android.content.pm.ParceledListSlice; 117 import android.content.pm.ShortcutInfo; 118 import android.content.pm.ShortcutServiceInternal; 119 import android.content.pm.UserInfo; 120 import android.content.res.Resources; 121 import android.graphics.Color; 122 import android.graphics.drawable.Icon; 123 import android.media.AudioManager; 124 import android.net.Uri; 125 import android.os.Binder; 126 import android.os.Build; 127 import android.os.Bundle; 128 import android.os.IBinder; 129 import android.os.Parcel; 130 import android.os.Process; 131 import android.os.RemoteException; 132 import android.os.SystemClock; 133 import android.os.UserHandle; 134 import android.os.UserManager; 135 import android.provider.DeviceConfig; 136 import android.provider.MediaStore; 137 import android.provider.Settings; 138 import android.service.notification.Adjustment; 139 import android.service.notification.ConversationChannelWrapper; 140 import android.service.notification.NotificationListenerService; 141 import android.service.notification.NotificationStats; 142 import android.service.notification.StatusBarNotification; 143 import android.service.notification.ZenPolicy; 144 import android.telephony.TelephonyManager; 145 import android.test.suitebuilder.annotation.SmallTest; 146 import android.testing.AndroidTestingRunner; 147 import android.testing.TestableContext; 148 import android.testing.TestableLooper; 149 import android.testing.TestableLooper.RunWithLooper; 150 import android.testing.TestablePermissions; 151 import android.testing.TestableResources; 152 import android.text.Html; 153 import android.text.TextUtils; 154 import android.util.ArrayMap; 155 import android.util.ArraySet; 156 import android.util.AtomicFile; 157 import android.util.Xml; 158 import android.widget.RemoteViews; 159 160 import androidx.annotation.Nullable; 161 import androidx.test.InstrumentationRegistry; 162 163 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; 164 import com.android.internal.logging.InstanceIdSequence; 165 import com.android.internal.logging.InstanceIdSequenceFake; 166 import com.android.internal.statusbar.NotificationVisibility; 167 import com.android.internal.util.FastXmlSerializer; 168 import com.android.server.DeviceIdleInternal; 169 import com.android.server.LocalServices; 170 import com.android.server.SystemService; 171 import com.android.server.UiServiceTestCase; 172 import com.android.server.lights.LightsManager; 173 import com.android.server.lights.LogicalLight; 174 import com.android.server.notification.NotificationManagerService.NotificationAssistants; 175 import com.android.server.notification.NotificationManagerService.NotificationListeners; 176 import com.android.server.pm.PackageManagerService; 177 import com.android.server.statusbar.StatusBarManagerInternal; 178 import com.android.server.uri.UriGrantsManagerInternal; 179 import com.android.server.wm.ActivityTaskManagerInternal; 180 import com.android.server.wm.WindowManagerInternal; 181 182 import org.junit.After; 183 import org.junit.Before; 184 import org.junit.Test; 185 import org.junit.runner.RunWith; 186 import org.mockito.ArgumentCaptor; 187 import org.mockito.Mock; 188 import org.mockito.MockitoAnnotations; 189 import org.mockito.stubbing.Answer; 190 import org.xmlpull.v1.XmlPullParser; 191 import org.xmlpull.v1.XmlSerializer; 192 193 import java.io.BufferedInputStream; 194 import java.io.BufferedOutputStream; 195 import java.io.ByteArrayInputStream; 196 import java.io.ByteArrayOutputStream; 197 import java.io.File; 198 import java.io.FileOutputStream; 199 import java.util.ArrayList; 200 import java.util.Arrays; 201 import java.util.Collections; 202 import java.util.List; 203 import java.util.Map; 204 import java.util.Set; 205 import java.util.function.Consumer; 206 207 208 @SmallTest 209 @RunWith(AndroidTestingRunner.class) 210 @RunWithLooper 211 public class NotificationManagerServiceTest extends UiServiceTestCase { 212 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId"; 213 214 private final int mUid = Binder.getCallingUid(); 215 private TestableNotificationManagerService mService; 216 private INotificationManager mBinderService; 217 private NotificationManagerInternal mInternalService; 218 private ShortcutHelper mShortcutHelper; 219 @Mock 220 private IPackageManager mPackageManager; 221 @Mock 222 private PackageManager mPackageManagerClient; 223 @Mock 224 private WindowManagerInternal mWindowManagerInternal; 225 private TestableContext mContext = spy(getContext()); 226 private final String PKG = mContext.getPackageName(); 227 private TestableLooper mTestableLooper; 228 @Mock 229 private RankingHelper mRankingHelper; 230 @Mock private PreferencesHelper mPreferencesHelper; 231 AtomicFile mPolicyFile; 232 File mFile; 233 @Mock 234 private NotificationUsageStats mUsageStats; 235 @Mock 236 private UsageStatsManagerInternal mAppUsageStats; 237 @Mock 238 private AudioManager mAudioManager; 239 @Mock 240 private LauncherApps mLauncherApps; 241 @Mock 242 private ShortcutServiceInternal mShortcutServiceInternal; 243 @Mock 244 ActivityManager mActivityManager; 245 @Mock 246 Resources mResources; 247 @Mock 248 RankingHandler mRankingHandler; 249 @Mock 250 protected PackageManagerInternal mPackageManagerInternal; 251 252 private static final int MAX_POST_DELAY = 1000; 253 254 private NotificationChannel mTestNotificationChannel = new NotificationChannel( 255 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 256 257 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0; 258 259 private static final String VALID_CONVO_SHORTCUT_ID = "shortcut"; 260 261 @Mock 262 private NotificationListeners mListeners; 263 @Mock private NotificationAssistants mAssistants; 264 @Mock private ConditionProviders mConditionProviders; 265 private ManagedServices.ManagedServiceInfo mListener; 266 @Mock private ICompanionDeviceManager mCompanionMgr; 267 @Mock SnoozeHelper mSnoozeHelper; 268 @Mock GroupHelper mGroupHelper; 269 @Mock 270 IBinder mPermOwner; 271 @Mock 272 IActivityManager mAm; 273 @Mock 274 ActivityTaskManagerInternal mAtm; 275 @Mock 276 IUriGrantsManager mUgm; 277 @Mock 278 UriGrantsManagerInternal mUgmInternal; 279 @Mock 280 AppOpsManager mAppOpsManager; 281 @Mock 282 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback 283 mNotificationAssistantAccessGrantedCallback; 284 @Mock 285 UserManager mUm; 286 @Mock 287 NotificationHistoryManager mHistoryManager; 288 @Mock 289 StatsManager mStatsManager; 290 @Mock 291 AlarmManager mAlarmManager; 292 NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); 293 private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( 294 1 << 30); 295 @Mock 296 StatusBarManagerInternal mStatusBar; 297 private final FakeSystemClock mSystemClock = new FakeSystemClock(); 298 299 // Use a Testable subclass so we can simulate calls from the system without failing. 300 private static class TestableNotificationManagerService extends NotificationManagerService { 301 int countSystemChecks = 0; 302 boolean isSystemUid = true; 303 int countLogSmartSuggestionsVisible = 0; 304 // If true, don't enqueue the PostNotificationRunnables, just trap them 305 boolean trapEnqueuedNotifications = false; 306 final ArrayList<NotificationManagerService.PostNotificationRunnable> trappedRunnables = 307 new ArrayList<>(); 308 @Nullable 309 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback; 310 TestableNotificationManagerService( Context context, NotificationRecordLogger logger, InjectableSystemClock systemClock, InstanceIdSequence notificationInstanceIdSequence)311 TestableNotificationManagerService( 312 Context context, 313 NotificationRecordLogger logger, 314 InjectableSystemClock systemClock, 315 InstanceIdSequence notificationInstanceIdSequence) { 316 super(context, logger, systemClock, notificationInstanceIdSequence); 317 } 318 getRankingHelper()319 RankingHelper getRankingHelper() { 320 return mRankingHelper; 321 } 322 323 @Override isCallingUidSystem()324 protected boolean isCallingUidSystem() { 325 countSystemChecks++; 326 return isSystemUid; 327 } 328 329 @Override isCallerSystemOrPhone()330 protected boolean isCallerSystemOrPhone() { 331 countSystemChecks++; 332 return isSystemUid; 333 } 334 335 @Override getCompanionManager()336 protected ICompanionDeviceManager getCompanionManager() { 337 return null; 338 } 339 340 @Override reportUserInteraction(NotificationRecord r)341 protected void reportUserInteraction(NotificationRecord r) { 342 return; 343 } 344 345 @Override handleSavePolicyFile()346 protected void handleSavePolicyFile() { 347 return; 348 } 349 350 @Override logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation)351 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) { 352 super.logSmartSuggestionsVisible(r, notificationLocation); 353 countLogSmartSuggestionsVisible++; 354 } 355 356 @Override setNotificationAssistantAccessGrantedForUserInternal( ComponentName assistant, int userId, boolean granted)357 protected void setNotificationAssistantAccessGrantedForUserInternal( 358 ComponentName assistant, int userId, boolean granted) { 359 if (mNotificationAssistantAccessGrantedCallback != null) { 360 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted); 361 return; 362 } 363 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted); 364 } 365 366 @Override getStringArrayResource(int key)367 protected String[] getStringArrayResource(int key) { 368 return new String[] {PKG_O}; 369 } 370 371 @Override postPostNotificationRunnableMaybeDelayedLocked(NotificationRecord record, PostNotificationRunnable runnable)372 protected void postPostNotificationRunnableMaybeDelayedLocked(NotificationRecord record, 373 PostNotificationRunnable runnable) { 374 if (trapEnqueuedNotifications) { 375 trappedRunnables.add(runnable); 376 return; 377 } 378 379 super.postPostNotificationRunnableMaybeDelayedLocked(record, runnable); 380 } 381 drainTrappedRunnableQueue()382 void drainTrappedRunnableQueue() { 383 for (Runnable r : trappedRunnables) { 384 getWorkHandler().post(r); 385 } 386 } 387 setNotificationAssistantAccessGrantedCallback( @ullable NotificationAssistantAccessGrantedCallback callback)388 private void setNotificationAssistantAccessGrantedCallback( 389 @Nullable NotificationAssistantAccessGrantedCallback callback) { 390 this.mNotificationAssistantAccessGrantedCallback = callback; 391 } 392 393 interface NotificationAssistantAccessGrantedCallback { onGranted(ComponentName assistant, int userId, boolean granted)394 void onGranted(ComponentName assistant, int userId, boolean granted); 395 } 396 } 397 398 private class TestableToastCallback extends ITransientNotification.Stub { 399 @Override show(IBinder windowToken)400 public void show(IBinder windowToken) { 401 } 402 403 @Override hide()404 public void hide() { 405 } 406 } 407 408 @Before setUp()409 public void setUp() throws Exception { 410 // Shell permisssions will override permissions of our app, so add all necessary permissions 411 // for this test here: 412 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( 413 "android.permission.WRITE_DEVICE_CONFIG", 414 "android.permission.READ_DEVICE_CONFIG", 415 "android.permission.READ_CONTACTS"); 416 417 MockitoAnnotations.initMocks(this); 418 419 DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class); 420 when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L); 421 ActivityManagerInternal activityManagerInternal = mock(ActivityManagerInternal.class); 422 423 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class); 424 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal); 425 LocalServices.removeServiceForTest(WindowManagerInternal.class); 426 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal); 427 LocalServices.removeServiceForTest(StatusBarManagerInternal.class); 428 LocalServices.addService(StatusBarManagerInternal.class, mStatusBar); 429 LocalServices.removeServiceForTest(DeviceIdleInternal.class); 430 LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal); 431 LocalServices.removeServiceForTest(ActivityManagerInternal.class); 432 LocalServices.addService(ActivityManagerInternal.class, activityManagerInternal); 433 mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager); 434 435 436 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any()); 437 438 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, 439 mSystemClock, mNotificationInstanceIdSequence); 440 441 // Use this testable looper. 442 mTestableLooper = TestableLooper.get(this); 443 // MockPackageManager - default returns ApplicationInfo with matching calling UID 444 mContext.setMockPackageManager(mPackageManagerClient); 445 446 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())) 447 .thenAnswer((Answer<ApplicationInfo>) invocation -> { 448 Object[] args = invocation.getArguments(); 449 return getApplicationInfo((String) args[0], mUid); 450 }); 451 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 452 .thenAnswer((Answer<ApplicationInfo>) invocation -> { 453 Object[] args = invocation.getArguments(); 454 return getApplicationInfo((String) args[0], mUid); 455 }); 456 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid); 457 final LightsManager mockLightsManager = mock(LightsManager.class); 458 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class)); 459 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); 460 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 461 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner); 462 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG}); 463 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG}); 464 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class)); 465 466 // write to a test file; the system file isn't readable from tests 467 mFile = new File(mContext.getCacheDir(), "test.xml"); 468 mFile.createNewFile(); 469 final String preupgradeXml = "<notification-policy></notification-policy>"; 470 mPolicyFile = new AtomicFile(mFile); 471 FileOutputStream fos = mPolicyFile.startWrite(); 472 fos.write(preupgradeXml.getBytes()); 473 mPolicyFile.finishWrite(fos); 474 475 // Setup managed services 476 mListener = mListeners.new ManagedServiceInfo( 477 null, new ComponentName(PKG, "test_class"), 478 UserHandle.getUserId(mUid), true, null, 0); 479 ComponentName defaultComponent = ComponentName.unflattenFromString("config/device"); 480 ArraySet<ComponentName> components = new ArraySet<>(); 481 components.add(defaultComponent); 482 when(mListeners.getDefaultComponents()).thenReturn(components); 483 when(mConditionProviders.getDefaultPackages()) 484 .thenReturn(new ArraySet<>(Arrays.asList("config"))); 485 when(mAssistants.getDefaultComponents()).thenReturn(components); 486 when(mAssistants.queryPackageForServices( 487 anyString(), anyInt(), anyInt())).thenReturn(components); 488 when(mListeners.checkServiceTokenLocked(null)).thenReturn(mListener); 489 ManagedServices.Config listenerConfig = new ManagedServices.Config(); 490 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS; 491 when(mListeners.getConfig()).thenReturn(listenerConfig); 492 ManagedServices.Config assistantConfig = new ManagedServices.Config(); 493 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS; 494 when(mAssistants.getConfig()).thenReturn(assistantConfig); 495 ManagedServices.Config dndConfig = new ManagedServices.Config(); 496 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS; 497 when(mConditionProviders.getConfig()).thenReturn(dndConfig); 498 499 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true); 500 501 mService.init(mService.new WorkerHandler(mTestableLooper.getLooper()), 502 mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager, 503 mListeners, mAssistants, mConditionProviders, 504 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, 505 mGroupHelper, mAm, mAtm, mAppUsageStats, 506 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal, 507 mAppOpsManager, mUm, mHistoryManager, mStatsManager, 508 mock(TelephonyManager.class), 509 mock(ActivityManagerInternal.class)); 510 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); 511 512 mService.setAudioManager(mAudioManager); 513 514 mShortcutHelper = mService.getShortcutHelper(); 515 mShortcutHelper.setLauncherApps(mLauncherApps); 516 mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal); 517 518 // Pretend the shortcut exists 519 List<ShortcutInfo> shortcutInfos = new ArrayList<>(); 520 ShortcutInfo info = mock(ShortcutInfo.class); 521 when(info.getPackage()).thenReturn(PKG); 522 when(info.getId()).thenReturn(VALID_CONVO_SHORTCUT_ID); 523 when(info.getUserId()).thenReturn(USER_SYSTEM); 524 when(info.isLongLived()).thenReturn(true); 525 when(info.isEnabled()).thenReturn(true); 526 shortcutInfos.add(info); 527 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos); 528 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), 529 anyString(), anyInt(), any())).thenReturn(true); 530 531 // Set the testable bubble extractor 532 RankingHelper rankingHelper = mService.getRankingHelper(); 533 BubbleExtractor extractor = rankingHelper.findExtractor(BubbleExtractor.class); 534 extractor.setActivityManager(mActivityManager); 535 536 // Tests call directly into the Binder. 537 mBinderService = mService.getBinderService(); 538 mInternalService = mService.getInternalService(); 539 540 mBinderService.createNotificationChannels( 541 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 542 mBinderService.createNotificationChannels( 543 PKG_P, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 544 mBinderService.createNotificationChannels( 545 PKG_O, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 546 assertNotNull(mBinderService.getNotificationChannel( 547 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID)); 548 clearInvocations(mRankingHandler); 549 } 550 551 @After assertNotificationRecordLoggerCallsValid()552 public void assertNotificationRecordLoggerCallsValid() { 553 for (NotificationRecordLoggerFake.CallRecord call : mNotificationRecordLogger.getCalls()) { 554 if (call.wasLogged) { 555 assertNotNull(call.event); 556 } 557 } 558 } 559 560 @After tearDown()561 public void tearDown() throws Exception { 562 if (mFile != null) mFile.delete(); 563 clearDeviceConfig(); 564 mService.unregisterDeviceConfigChange(); 565 InstrumentationRegistry.getInstrumentation() 566 .getUiAutomation().dropShellPermissionIdentity(); 567 } 568 generateResetComponentValues()569 private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() { 570 ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>(); 571 changed.put(true, new ArrayList<>()); 572 changed.put(false, new ArrayList<>()); 573 return changed; 574 } getApplicationInfo(String pkg, int uid)575 private ApplicationInfo getApplicationInfo(String pkg, int uid) { 576 final ApplicationInfo applicationInfo = new ApplicationInfo(); 577 applicationInfo.uid = uid; 578 switch (pkg) { 579 case PKG_N_MR1: 580 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1; 581 break; 582 case PKG_O: 583 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O; 584 break; 585 case PKG_P: 586 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P; 587 break; 588 default: 589 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; 590 break; 591 } 592 return applicationInfo; 593 } 594 waitForIdle()595 public void waitForIdle() { 596 mTestableLooper.processAllMessages(); 597 } 598 setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled, int pkgPref, boolean channelEnabled)599 private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled, 600 int pkgPref, boolean channelEnabled) { 601 Settings.Global.putInt(mContext.getContentResolver(), 602 Settings.Global.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0); 603 mService.mPreferencesHelper.updateBubblesEnabled(); 604 assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled()); 605 try { 606 mBinderService.setBubblesAllowed(pkg, uid, pkgPref); 607 } catch (RemoteException e) { 608 e.printStackTrace(); 609 } 610 mTestNotificationChannel.setAllowBubbles(channelEnabled); 611 } 612 generateSbn(String pkg, int uid, long postTime, int userId)613 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) { 614 Notification.Builder nb = new Notification.Builder(mContext, "a") 615 .setContentTitle("foo") 616 .setSmallIcon(android.R.drawable.sym_def_app_icon); 617 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, 618 "tag" + System.currentTimeMillis(), uid, 0, 619 nb.build(), new UserHandle(userId), null, postTime); 620 return sbn; 621 } 622 generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary)623 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, 624 String groupKey, boolean isSummary) { 625 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 626 .setContentTitle("foo") 627 .setSmallIcon(android.R.drawable.sym_def_app_icon) 628 .setGroup(groupKey) 629 .setGroupSummary(isSummary); 630 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, 631 "tag" + System.currentTimeMillis(), mUid, 0, 632 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 633 return new NotificationRecord(mContext, sbn, channel); 634 } 635 generateNotificationRecord(NotificationChannel channel)636 private NotificationRecord generateNotificationRecord(NotificationChannel channel) { 637 return generateNotificationRecord(channel, null); 638 } 639 generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender)640 private NotificationRecord generateNotificationRecord(NotificationChannel channel, 641 Notification.TvExtender extender) { 642 if (channel == null) { 643 channel = mTestNotificationChannel; 644 } 645 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 646 .setContentTitle("foo") 647 .setSmallIcon(android.R.drawable.sym_def_app_icon); 648 if (extender != null) { 649 nb.extend(extender); 650 } 651 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 652 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 653 return new NotificationRecord(mContext, sbn, channel); 654 } 655 generateNotificationRecord(NotificationChannel channel, int userId)656 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) { 657 if (channel == null) { 658 channel = mTestNotificationChannel; 659 } 660 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 661 .setContentTitle("foo") 662 .setSmallIcon(android.R.drawable.sym_def_app_icon); 663 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, 664 nb.build(), new UserHandle(userId), null, 0); 665 return new NotificationRecord(mContext, sbn, channel); 666 } 667 generateMessageBubbleNotifRecord(NotificationChannel channel, String tag)668 private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel, 669 String tag) { 670 return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false); 671 } 672 generateMessageBubbleNotifRecord(boolean addMetadata, NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary)673 private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata, 674 NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) { 675 if (channel == null) { 676 channel = mTestNotificationChannel; 677 } 678 if (tag == null) { 679 tag = "tag"; 680 } 681 Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary); 682 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, 683 tag, mUid, 0, 684 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 685 return new NotificationRecord(mContext, sbn, channel); 686 } 687 getSignalExtractorSideEffects()688 private Map<String, Answer> getSignalExtractorSideEffects() { 689 Map<String, Answer> answers = new ArrayMap<>(); 690 691 answers.put("override group key", invocationOnMock -> { 692 ((NotificationRecord) invocationOnMock.getArguments()[0]) 693 .setOverrideGroupKey("bananas"); 694 return null; 695 }); 696 answers.put("override people", invocationOnMock -> { 697 ((NotificationRecord) invocationOnMock.getArguments()[0]) 698 .setPeopleOverride(new ArrayList<>()); 699 return null; 700 }); 701 answers.put("snooze criteria", invocationOnMock -> { 702 ((NotificationRecord) invocationOnMock.getArguments()[0]) 703 .setSnoozeCriteria(new ArrayList<>()); 704 return null; 705 }); 706 answers.put("notification channel", invocationOnMock -> { 707 ((NotificationRecord) invocationOnMock.getArguments()[0]) 708 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW)); 709 return null; 710 }); 711 answers.put("badging", invocationOnMock -> { 712 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0]; 713 r.setShowBadge(!r.canShowBadge()); 714 return null; 715 }); 716 answers.put("bubbles", invocationOnMock -> { 717 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0]; 718 r.setAllowBubble(!r.canBubble()); 719 return null; 720 }); 721 answers.put("package visibility", invocationOnMock -> { 722 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride( 723 Notification.VISIBILITY_SECRET); 724 return null; 725 }); 726 727 return answers; 728 } 729 clearDeviceConfig()730 private void clearDeviceConfig() { 731 DeviceConfig.resetToDefaults( 732 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI); 733 } 734 setDefaultAssistantInDeviceConfig(String componentName)735 private void setDefaultAssistantInDeviceConfig(String componentName) { 736 DeviceConfig.setProperty( 737 DeviceConfig.NAMESPACE_SYSTEMUI, 738 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE, 739 componentName, 740 false); 741 } 742 getMessageStyleNotifBuilder(boolean addBubbleMetadata, String groupKey, boolean isSummary)743 private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata, 744 String groupKey, boolean isSummary) { 745 // Give it a person 746 Person person = new Person.Builder() 747 .setName("bubblebot") 748 .build(); 749 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); 750 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); 751 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); 752 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", 753 inputIntent).addRemoteInput(remoteInput) 754 .build(); 755 // Make it messaging style 756 Notification.Builder nb = new Notification.Builder(mContext, 757 mTestNotificationChannel.getId()) 758 .setContentTitle("foo") 759 .setStyle(new Notification.MessagingStyle(person) 760 .setConversationTitle("Bubble Chat") 761 .addMessage("Hello?", 762 SystemClock.currentThreadTimeMillis() - 300000, person) 763 .addMessage("Is it me you're looking for?", 764 SystemClock.currentThreadTimeMillis(), person) 765 ) 766 .setActions(replyAction) 767 .setSmallIcon(android.R.drawable.sym_def_app_icon) 768 .setShortcutId(VALID_CONVO_SHORTCUT_ID) 769 .setGroupSummary(isSummary); 770 if (groupKey != null) { 771 nb.setGroup(groupKey); 772 } 773 if (addBubbleMetadata) { 774 nb.setBubbleMetadata(getBubbleMetadata()); 775 } 776 return nb; 777 } 778 getBubbleMetadata()779 private Notification.BubbleMetadata getBubbleMetadata() { 780 PendingIntent pendingIntent = mock(PendingIntent.class); 781 Intent intent = mock(Intent.class); 782 when(pendingIntent.getIntent()).thenReturn(intent); 783 784 ActivityInfo info = new ActivityInfo(); 785 info.resizeMode = RESIZE_MODE_RESIZEABLE; 786 when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info); 787 788 return new Notification.BubbleMetadata.Builder( 789 pendingIntent, 790 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon)) 791 .build(); 792 } 793 addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)794 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel) 795 throws RemoteException { 796 797 String groupKey = "BUBBLE_GROUP"; 798 799 // Notification that has bubble metadata 800 NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */, 801 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */); 802 803 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.getSbn().getTag(), 804 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(), 805 nrBubble.getSbn().getUserId()); 806 waitForIdle(); 807 808 // Make sure we are a bubble 809 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 810 assertEquals(1, notifsAfter.length); 811 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0); 812 813 // Notification without bubble metadata 814 NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */, 815 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */); 816 817 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.getSbn().getTag(), 818 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(), 819 nrPlain.getSbn().getUserId()); 820 waitForIdle(); 821 822 notifsAfter = mBinderService.getActiveNotifications(PKG); 823 assertEquals(2, notifsAfter.length); 824 825 // Summary notification for both of those 826 NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */, 827 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */); 828 829 if (summaryAutoCancel) { 830 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL; 831 } 832 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.getSbn().getTag(), 833 nrSummary.getSbn().getId(), nrSummary.getSbn().getNotification(), 834 nrSummary.getSbn().getUserId()); 835 waitForIdle(); 836 837 notifsAfter = mBinderService.getActiveNotifications(PKG); 838 assertEquals(3, notifsAfter.length); 839 840 return nrSummary; 841 } 842 843 @Test testLimitTimeOutBroadcast()844 public void testLimitTimeOutBroadcast() { 845 NotificationChannel channel = new NotificationChannel("id", "name", 846 NotificationManager.IMPORTANCE_HIGH); 847 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 848 .setContentTitle("foo") 849 .setSmallIcon(android.R.drawable.sym_def_app_icon) 850 .setTimeoutAfter(1); 851 852 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 853 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 854 NotificationRecord r = new NotificationRecord(mContext, sbn, channel); 855 856 mService.scheduleTimeoutLocked(r); 857 ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class); 858 verify(mAlarmManager).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture()); 859 assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME, 860 captor.getValue().getIntent().getPackage()); 861 } 862 863 @Test testDefaultAssistant_overrideDefault()864 public void testDefaultAssistant_overrideDefault() { 865 final int userId = 0; 866 final String testComponent = "package/class"; 867 final List<UserInfo> userInfos = new ArrayList<>(); 868 userInfos.add(new UserInfo(0, "", 0)); 869 final ArraySet<ComponentName> validAssistants = new ArraySet<>(); 870 validAssistants.add(ComponentName.unflattenFromString(testComponent)); 871 when(mActivityManager.isLowRamDevice()).thenReturn(false); 872 when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt())) 873 .thenReturn(validAssistants); 874 when(mAssistants.getDefaultComponents()).thenReturn(validAssistants); 875 when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos); 876 877 mService.setDefaultAssistantForUser(userId); 878 879 verify(mAssistants).setPackageOrComponentEnabled( 880 eq(testComponent), eq(userId), eq(true), eq(true)); 881 } 882 883 @Test testCreateNotificationChannels_SingleChannel()884 public void testCreateNotificationChannels_SingleChannel() throws Exception { 885 final NotificationChannel channel = 886 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 887 mBinderService.createNotificationChannels(PKG, 888 new ParceledListSlice(Arrays.asList(channel))); 889 final NotificationChannel createdChannel = 890 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 891 assertTrue(createdChannel != null); 892 } 893 894 @Test testCreateNotificationChannels_NullChannelThrowsException()895 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception { 896 try { 897 mBinderService.createNotificationChannels(PKG, 898 new ParceledListSlice(Arrays.asList((Object[])null))); 899 fail("Exception should be thrown immediately."); 900 } catch (NullPointerException e) { 901 // pass 902 } 903 } 904 905 @Test testCreateNotificationChannels_TwoChannels()906 public void testCreateNotificationChannels_TwoChannels() throws Exception { 907 final NotificationChannel channel1 = 908 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT); 909 final NotificationChannel channel2 = 910 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT); 911 mBinderService.createNotificationChannels(PKG, 912 new ParceledListSlice(Arrays.asList(channel1, channel2))); 913 assertTrue(mBinderService.getNotificationChannel( 914 PKG, mContext.getUserId(), PKG, "id1") != null); 915 assertTrue(mBinderService.getNotificationChannel( 916 PKG, mContext.getUserId(), PKG, "id2") != null); 917 } 918 919 @Test testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()920 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance() 921 throws Exception { 922 final NotificationChannel channel = 923 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 924 mBinderService.createNotificationChannels(PKG, 925 new ParceledListSlice(Arrays.asList(channel))); 926 927 // Recreating the channel doesn't throw, but ignores importance. 928 final NotificationChannel dupeChannel = 929 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 930 mBinderService.createNotificationChannels(PKG, 931 new ParceledListSlice(Arrays.asList(dupeChannel))); 932 final NotificationChannel createdChannel = 933 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 934 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); 935 } 936 937 @Test testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()938 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance() 939 throws Exception { 940 final NotificationChannel channel = 941 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 942 mBinderService.createNotificationChannels(PKG, 943 new ParceledListSlice(Arrays.asList(channel))); 944 945 // Recreating with a lower importance is allowed to modify the channel. 946 final NotificationChannel dupeChannel = 947 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); 948 mBinderService.createNotificationChannels(PKG, 949 new ParceledListSlice(Arrays.asList(dupeChannel))); 950 final NotificationChannel createdChannel = 951 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 952 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance()); 953 } 954 955 @Test testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()956 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated() 957 throws Exception { 958 final NotificationChannel channel = 959 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 960 mBinderService.createNotificationChannels(PKG, 961 new ParceledListSlice(Arrays.asList(channel))); 962 963 // The user modifies importance directly, can no longer be changed by the app. 964 final NotificationChannel updatedChannel = 965 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 966 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel); 967 968 // Recreating with a lower importance leaves channel unchanged. 969 final NotificationChannel dupeChannel = 970 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); 971 mBinderService.createNotificationChannels(PKG, 972 new ParceledListSlice(Arrays.asList(dupeChannel))); 973 final NotificationChannel createdChannel = 974 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 975 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance()); 976 } 977 978 @Test testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()979 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond() 980 throws Exception { 981 final NotificationChannel channel1 = 982 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 983 final NotificationChannel channel2 = 984 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 985 mBinderService.createNotificationChannels(PKG, 986 new ParceledListSlice(Arrays.asList(channel1, channel2))); 987 final NotificationChannel createdChannel = 988 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 989 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); 990 } 991 992 @Test testBlockedNotifications_suspended()993 public void testBlockedNotifications_suspended() throws Exception { 994 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true); 995 996 NotificationChannel channel = new NotificationChannel("id", "name", 997 IMPORTANCE_HIGH); 998 NotificationRecord r = generateNotificationRecord(channel); 999 1000 // isBlocked is only used for user blocking, not app suspension 1001 assertFalse(mService.isBlocked(r, mUsageStats)); 1002 } 1003 1004 @Test testBlockedNotifications_blockedChannel()1005 public void testBlockedNotifications_blockedChannel() throws Exception { 1006 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1007 1008 NotificationChannel channel = new NotificationChannel("id", "name", 1009 NotificationManager.IMPORTANCE_NONE); 1010 NotificationRecord r = generateNotificationRecord(channel); 1011 assertTrue(mService.isBlocked(r, mUsageStats)); 1012 verify(mUsageStats, times(1)).registerBlocked(eq(r)); 1013 1014 mBinderService.createNotificationChannels( 1015 PKG, new ParceledListSlice(Arrays.asList(channel))); 1016 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn(); 1017 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1018 "testBlockedNotifications_blockedChannel", 1019 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1020 waitForIdle(); 1021 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1022 } 1023 1024 @Test testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()1025 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService() 1026 throws Exception { 1027 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1028 1029 NotificationChannel channel = new NotificationChannel("blocked", "name", 1030 NotificationManager.IMPORTANCE_NONE); 1031 mBinderService.createNotificationChannels( 1032 PKG, new ParceledListSlice(Arrays.asList(channel))); 1033 1034 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn(); 1035 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1036 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 1037 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1038 waitForIdle(); 1039 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1040 assertEquals(IMPORTANCE_LOW, 1041 mService.getNotificationRecord(sbn.getKey()).getImportance()); 1042 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel( 1043 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1044 } 1045 1046 @Test testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()1047 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService() 1048 throws Exception { 1049 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1050 1051 NotificationChannel channel = 1052 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH); 1053 mBinderService.createNotificationChannels( 1054 PKG, new ParceledListSlice(Arrays.asList(channel))); 1055 1056 NotificationChannel update = 1057 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); 1058 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); 1059 waitForIdle(); 1060 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 1061 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1062 1063 StatusBarNotification sbn = generateNotificationRecord(channel).getSbn(); 1064 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1065 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 1066 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1067 waitForIdle(); 1068 // The first time a foreground service notification is shown, we allow the channel 1069 // to be updated to allow it to be seen. 1070 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1071 assertEquals(IMPORTANCE_LOW, 1072 mService.getNotificationRecord(sbn.getKey()).getImportance()); 1073 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel( 1074 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1075 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); 1076 waitForIdle(); 1077 1078 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); 1079 update.setFgServiceShown(true); 1080 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); 1081 waitForIdle(); 1082 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 1083 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1084 1085 sbn = generateNotificationRecord(channel).getSbn(); 1086 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1087 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1088 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService", 1089 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1090 waitForIdle(); 1091 // The second time it is shown, we keep the user's preference. 1092 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1093 assertNull(mService.getNotificationRecord(sbn.getKey())); 1094 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 1095 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1096 } 1097 1098 @Test testBlockedNotifications_blockedChannelGroup()1099 public void testBlockedNotifications_blockedChannelGroup() throws Exception { 1100 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1101 mService.setPreferencesHelper(mPreferencesHelper); 1102 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())). 1103 thenReturn(true); 1104 1105 NotificationChannel channel = new NotificationChannel("id", "name", 1106 NotificationManager.IMPORTANCE_HIGH); 1107 channel.setGroup("something"); 1108 NotificationRecord r = generateNotificationRecord(channel); 1109 assertTrue(mService.isBlocked(r, mUsageStats)); 1110 verify(mUsageStats, times(1)).registerBlocked(eq(r)); 1111 } 1112 1113 @Test testEnqueuedBlockedNotifications_blockedApp()1114 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception { 1115 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1116 1117 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); 1118 1119 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1120 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1121 "testEnqueuedBlockedNotifications_blockedApp", 1122 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1123 waitForIdle(); 1124 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1125 } 1126 1127 @Test testEnqueuedBlockedNotifications_blockedAppForegroundService()1128 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception { 1129 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1130 1131 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); 1132 1133 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1134 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1135 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1136 "testEnqueuedBlockedNotifications_blockedAppForegroundService", 1137 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1138 waitForIdle(); 1139 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1140 assertNull(mService.getNotificationRecord(sbn.getKey())); 1141 } 1142 1143 /** 1144 * Confirm the system user on automotive devices can use car categories 1145 */ 1146 @Test testEnqueuedRestrictedNotifications_asSystem()1147 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception { 1148 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 1149 .thenReturn(true); 1150 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 1151 Notification.CATEGORY_CAR_WARNING, 1152 Notification.CATEGORY_CAR_INFORMATION); 1153 int id = 0; 1154 for (String category: categories) { 1155 final StatusBarNotification sbn = 1156 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn(); 1157 sbn.getNotification().category = category; 1158 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1159 "testEnqueuedRestrictedNotifications_asSystem", 1160 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1161 } 1162 waitForIdle(); 1163 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length); 1164 } 1165 1166 1167 /** 1168 * Confirm restricted notification categories only apply to automotive. 1169 */ 1170 @Test testEnqueuedRestrictedNotifications_notAutomotive()1171 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception { 1172 mService.isSystemUid = false; 1173 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 1174 .thenReturn(false); 1175 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 1176 Notification.CATEGORY_CAR_WARNING, 1177 Notification.CATEGORY_CAR_INFORMATION); 1178 int id = 0; 1179 for (String category: categories) { 1180 final StatusBarNotification sbn = 1181 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn(); 1182 sbn.getNotification().category = category; 1183 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1184 "testEnqueuedRestrictedNotifications_notAutomotive", 1185 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1186 } 1187 waitForIdle(); 1188 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length); 1189 } 1190 1191 /** 1192 * Confirm if a non-system user tries to use the car categories on a automotive device that 1193 * they will get a security exception 1194 */ 1195 @Test testEnqueuedRestrictedNotifications_badUser()1196 public void testEnqueuedRestrictedNotifications_badUser() throws Exception { 1197 mService.isSystemUid = false; 1198 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 1199 .thenReturn(true); 1200 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 1201 Notification.CATEGORY_CAR_WARNING, 1202 Notification.CATEGORY_CAR_INFORMATION); 1203 for (String category: categories) { 1204 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1205 sbn.getNotification().category = category; 1206 try { 1207 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1208 "testEnqueuedRestrictedNotifications_badUser", 1209 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1210 fail("Calls from non system apps should not allow use of restricted categories"); 1211 } catch (SecurityException e) { 1212 // pass 1213 } 1214 } 1215 waitForIdle(); 1216 assertEquals(0, mBinderService.getActiveNotifications(PKG).length); 1217 } 1218 1219 @Test testEnqueuedRestrictedNotifications_asSuwApp()1220 public void testEnqueuedRestrictedNotifications_asSuwApp() throws Exception { 1221 LocalServices.removeServiceForTest(PackageManagerInternal.class); 1222 LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal); 1223 when(mPackageManagerInternal.getSetupWizardPackageName()).thenReturn(PKG); 1224 1225 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 1226 .thenReturn(true); 1227 1228 final StatusBarNotification sbn = 1229 generateNotificationRecord(mTestNotificationChannel, 0, "", false).getSbn(); 1230 sbn.getNotification().category = Notification.CATEGORY_CAR_INFORMATION; 1231 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1232 "testEnqueuedRestrictedNotifications_asSuwApp", 1233 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1234 1235 waitForIdle(); 1236 assertEquals(1, mBinderService.getActiveNotifications(PKG).length); 1237 } 1238 1239 @Test testBlockedNotifications_blockedByAssistant()1240 public void testBlockedNotifications_blockedByAssistant() throws Exception { 1241 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1242 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 1243 1244 NotificationChannel channel = new NotificationChannel("id", "name", 1245 NotificationManager.IMPORTANCE_HIGH); 1246 NotificationRecord r = generateNotificationRecord(channel); 1247 mService.addEnqueuedNotification(r); 1248 1249 Bundle bundle = new Bundle(); 1250 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE); 1251 Adjustment adjustment = new Adjustment( 1252 r.getSbn().getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier()); 1253 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 1254 1255 NotificationManagerService.PostNotificationRunnable runnable = 1256 mService.new PostNotificationRunnable(r.getKey()); 1257 runnable.run(); 1258 waitForIdle(); 1259 1260 verify(mUsageStats, never()).registerPostedByApp(any()); 1261 } 1262 1263 @Test testEnqueueNotificationWithTag_PopulatesGetActiveNotifications()1264 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception { 1265 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1266 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1267 generateNotificationRecord(null).getNotification(), 0); 1268 waitForIdle(); 1269 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 1270 assertEquals(1, notifs.length); 1271 assertEquals(1, mService.getNotificationRecordCount()); 1272 } 1273 1274 @Test testEnqueueNotificationWithTag_WritesExpectedLogs()1275 public void testEnqueueNotificationWithTag_WritesExpectedLogs() throws Exception { 1276 final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog"; 1277 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1278 generateNotificationRecord(null).getNotification(), 0); 1279 waitForIdle(); 1280 assertEquals(1, mNotificationRecordLogger.numCalls()); 1281 1282 NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0); 1283 assertTrue(call.wasLogged); 1284 assertEquals(NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED, 1285 call.event); 1286 assertNotNull(call.r); 1287 assertNull(call.old); 1288 assertEquals(0, call.position); 1289 assertEquals(0, call.buzzBeepBlink); 1290 assertEquals(PKG, call.r.getSbn().getPackageName()); 1291 assertEquals(0, call.r.getSbn().getId()); 1292 assertEquals(tag, call.r.getSbn().getTag()); 1293 assertEquals(1, call.getInstanceId()); // Fake instance IDs are assigned in order 1294 } 1295 1296 @Test testEnqueueNotificationWithTag_LogsOnMajorUpdates()1297 public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception { 1298 final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates"; 1299 Notification original = new Notification.Builder(mContext, 1300 mTestNotificationChannel.getId()) 1301 .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); 1302 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0); 1303 Notification update = new Notification.Builder(mContext, 1304 mTestNotificationChannel.getId()) 1305 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1306 .setCategory(Notification.CATEGORY_ALARM).build(); 1307 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0); 1308 waitForIdle(); 1309 assertEquals(2, mNotificationRecordLogger.numCalls()); 1310 1311 assertTrue(mNotificationRecordLogger.get(0).wasLogged); 1312 assertEquals( 1313 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED, 1314 mNotificationRecordLogger.event(0)); 1315 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 1316 1317 assertTrue(mNotificationRecordLogger.get(1).wasLogged); 1318 assertEquals( 1319 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED, 1320 mNotificationRecordLogger.event(1)); 1321 // Instance ID doesn't change on update of an active notification 1322 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); 1323 } 1324 1325 @Test testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate()1326 public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate() throws Exception { 1327 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate"; 1328 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1329 generateNotificationRecord(null).getNotification(), 0); 1330 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1331 generateNotificationRecord(null).getNotification(), 0); 1332 waitForIdle(); 1333 assertEquals(2, mNotificationRecordLogger.numCalls()); 1334 assertTrue(mNotificationRecordLogger.get(0).wasLogged); 1335 assertEquals( 1336 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED, 1337 mNotificationRecordLogger.event(0)); 1338 assertFalse(mNotificationRecordLogger.get(1).wasLogged); 1339 assertNull(mNotificationRecordLogger.event(1)); 1340 } 1341 1342 @Test testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate()1343 public void testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate() throws Exception { 1344 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate"; 1345 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1346 generateNotificationRecord(null).getNotification(), 1347 0); 1348 final Notification notif = generateNotificationRecord(null).getNotification(); 1349 notif.extras.putString(Notification.EXTRA_TITLE, "Changed title"); 1350 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notif, 0); 1351 waitForIdle(); 1352 assertEquals(2, mNotificationRecordLogger.numCalls()); 1353 assertEquals( 1354 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED, 1355 mNotificationRecordLogger.event(0)); 1356 assertNull(mNotificationRecordLogger.event(1)); 1357 } 1358 1359 @Test testEnqueueNotificationWithTag_LogsAgainAfterCancel()1360 public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception { 1361 final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel"; 1362 Notification notification = new Notification.Builder(mContext, 1363 mTestNotificationChannel.getId()) 1364 .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); 1365 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0); 1366 waitForIdle(); 1367 mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0); 1368 waitForIdle(); 1369 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0); 1370 waitForIdle(); 1371 assertEquals(3, mNotificationRecordLogger.numCalls()); 1372 1373 assertEquals( 1374 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED, 1375 mNotificationRecordLogger.event(0)); 1376 assertTrue(mNotificationRecordLogger.get(0).wasLogged); 1377 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 1378 1379 assertEquals( 1380 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL, 1381 mNotificationRecordLogger.event(1)); 1382 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); 1383 1384 assertEquals( 1385 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED, 1386 mNotificationRecordLogger.event(2)); 1387 assertTrue(mNotificationRecordLogger.get(2).wasLogged); 1388 // New instance ID because notification was canceled before re-post 1389 assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId()); 1390 } 1391 1392 @Test testCancelNonexistentNotification()1393 public void testCancelNonexistentNotification() throws Exception { 1394 mBinderService.cancelNotificationWithTag(PKG, PKG, 1395 "testCancelNonexistentNotification", 0, 0); 1396 waitForIdle(); 1397 // The notification record logger doesn't even get called when a nonexistent notification 1398 // is cancelled, because that happens very frequently and is not interesting. 1399 assertEquals(0, mNotificationRecordLogger.numCalls()); 1400 } 1401 1402 @Test testCancelNotificationImmediatelyAfterEnqueue()1403 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception { 1404 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1405 "testCancelNotificationImmediatelyAfterEnqueue", 0, 1406 generateNotificationRecord(null).getNotification(), 0); 1407 mBinderService.cancelNotificationWithTag(PKG, PKG, 1408 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0); 1409 waitForIdle(); 1410 StatusBarNotification[] notifs = 1411 mBinderService.getActiveNotifications(PKG); 1412 assertEquals(0, notifs.length); 1413 assertEquals(0, mService.getNotificationRecordCount()); 1414 } 1415 1416 @Test testPostCancelPostNotifiesListeners()1417 public void testPostCancelPostNotifiesListeners() throws Exception { 1418 // WHEN a notification is posted 1419 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1420 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), 1421 sbn.getNotification(), sbn.getUserId()); 1422 mSystemClock.advanceTime(1); 1423 // THEN it is canceled 1424 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); 1425 mSystemClock.advanceTime(1); 1426 // THEN it is posted again (before the cancel has a chance to finish) 1427 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), 1428 sbn.getNotification(), sbn.getUserId()); 1429 // THEN the later enqueue isn't swallowed by the cancel. I.e., ordering is respected 1430 waitForIdle(); 1431 1432 // The final enqueue made it to the listener instead of being canceled 1433 StatusBarNotification[] notifs = 1434 mBinderService.getActiveNotifications(PKG); 1435 assertEquals(1, notifs.length); 1436 assertEquals(1, mService.getNotificationRecordCount()); 1437 } 1438 1439 @Test testChangeSystemTimeAfterPost_thenCancel_noFgs()1440 public void testChangeSystemTimeAfterPost_thenCancel_noFgs() throws Exception { 1441 // GIVEN time X 1442 mSystemClock.setCurrentTimeMillis(10000); 1443 1444 // GIVEN a notification is posted 1445 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1446 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), 1447 sbn.getNotification(), sbn.getUserId()); 1448 mSystemClock.advanceTime(1); 1449 waitForIdle(); 1450 1451 // THEN the system time is changed to an earlier time 1452 mSystemClock.setCurrentTimeMillis(5000); 1453 1454 // THEN a cancel is requested 1455 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); 1456 waitForIdle(); 1457 1458 // It should work 1459 StatusBarNotification[] notifs = 1460 mBinderService.getActiveNotifications(PKG); 1461 assertEquals(0, notifs.length); 1462 assertEquals(0, mService.getNotificationRecordCount()); 1463 } 1464 1465 @Test testChangeSystemTimeAfterPost_thenCancel_fgs()1466 public void testChangeSystemTimeAfterPost_thenCancel_fgs() throws Exception { 1467 // GIVEN time X 1468 mSystemClock.setCurrentTimeMillis(10000); 1469 1470 // GIVEN a notification is posted 1471 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1472 sbn.getNotification().flags = 1473 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; 1474 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), 1475 sbn.getNotification(), sbn.getUserId()); 1476 mSystemClock.advanceTime(1); 1477 waitForIdle(); 1478 1479 // THEN the system time is changed to an earlier time 1480 mSystemClock.setCurrentTimeMillis(5000); 1481 1482 // THEN a cancel is requested 1483 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); 1484 waitForIdle(); 1485 1486 // It should work 1487 StatusBarNotification[] notifs = 1488 mBinderService.getActiveNotifications(PKG); 1489 assertEquals(0, notifs.length); 1490 assertEquals(0, mService.getNotificationRecordCount()); 1491 } 1492 1493 @Test testCancelNotificationWhilePostedAndEnqueued()1494 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception { 1495 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1496 "testCancelNotificationWhilePostedAndEnqueued", 0, 1497 generateNotificationRecord(null).getNotification(), 0); 1498 waitForIdle(); 1499 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1500 "testCancelNotificationWhilePostedAndEnqueued", 0, 1501 generateNotificationRecord(null).getNotification(), 0); 1502 mBinderService.cancelNotificationWithTag(PKG, PKG, 1503 "testCancelNotificationWhilePostedAndEnqueued", 0, 0); 1504 waitForIdle(); 1505 StatusBarNotification[] notifs = 1506 mBinderService.getActiveNotifications(PKG); 1507 assertEquals(0, notifs.length); 1508 assertEquals(0, mService.getNotificationRecordCount()); 1509 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 1510 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture()); 1511 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface()); 1512 } 1513 1514 @Test testDelayCancelWhenEnqueuedHasNotPosted()1515 public void testDelayCancelWhenEnqueuedHasNotPosted() throws Exception { 1516 // Don't allow PostNotificationRunnables to execute so we can set up problematic state 1517 mService.trapEnqueuedNotifications = true; 1518 // GIVEN an enqueued notification 1519 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1520 "testDelayCancelWhenEnqueuedHasNotPosted", 0, 1521 generateNotificationRecord(null).getNotification(), 0); 1522 mSystemClock.advanceTime(1); 1523 // WHEN a cancel is requested before it has posted 1524 mBinderService.cancelNotificationWithTag(PKG, PKG, 1525 "testDelayCancelWhenEnqueuedHasNotPosted", 0, 0); 1526 1527 waitForIdle(); 1528 1529 // THEN the cancel notification runnable is captured and associated with that record 1530 ArrayMap<NotificationRecord, 1531 ArrayList<NotificationManagerService.CancelNotificationRunnable>> delayed = 1532 mService.mDelayedCancelations; 1533 Set<NotificationRecord> keySet = delayed.keySet(); 1534 assertEquals(1, keySet.size()); 1535 } 1536 1537 @Test testDelayedCancelsExecuteAfterPost()1538 public void testDelayedCancelsExecuteAfterPost() throws Exception { 1539 // Don't allow PostNotificationRunnables to execute so we can set up problematic state 1540 mService.trapEnqueuedNotifications = true; 1541 // GIVEN an enqueued notification 1542 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1543 "testDelayCancelWhenEnqueuedHasNotPosted", 0, 1544 generateNotificationRecord(null).getNotification(), 0); 1545 mSystemClock.advanceTime(1); 1546 // WHEN a cancel is requested before it has posted 1547 mBinderService.cancelNotificationWithTag(PKG, PKG, 1548 "testDelayCancelWhenEnqueuedHasNotPosted", 0, 0); 1549 1550 waitForIdle(); 1551 1552 // We're now in a state with an a notification awaiting PostNotificationRunnable to execute 1553 // WHEN the PostNotificationRunnable is allowed to execute 1554 mService.drainTrappedRunnableQueue(); 1555 waitForIdle(); 1556 1557 // THEN the cancel executes and the notification is removed 1558 StatusBarNotification[] notifs = 1559 mBinderService.getActiveNotifications(PKG); 1560 assertEquals(0, notifs.length); 1561 assertEquals(0, mService.getNotificationRecordCount()); 1562 } 1563 1564 @Test testCancelNotificationsFromListenerImmediatelyAfterEnqueue()1565 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception { 1566 NotificationRecord r = generateNotificationRecord(null); 1567 final StatusBarNotification sbn = r.getSbn(); 1568 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1569 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue", 1570 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1571 mBinderService.cancelNotificationsFromListener(null, null); 1572 waitForIdle(); 1573 StatusBarNotification[] notifs = 1574 mBinderService.getActiveNotifications(sbn.getPackageName()); 1575 assertEquals(0, notifs.length); 1576 assertEquals(0, mService.getNotificationRecordCount()); 1577 } 1578 1579 @Test testCancelAllNotificationsImmediatelyAfterEnqueue()1580 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception { 1581 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1582 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1583 "testCancelAllNotificationsImmediatelyAfterEnqueue", 1584 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1585 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 1586 waitForIdle(); 1587 StatusBarNotification[] notifs = 1588 mBinderService.getActiveNotifications(sbn.getPackageName()); 1589 assertEquals(0, notifs.length); 1590 assertEquals(0, mService.getNotificationRecordCount()); 1591 } 1592 1593 @Test testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()1594 public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag() 1595 throws Exception { 1596 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1597 sbn.getNotification().flags = 1598 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; 1599 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1600 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1601 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); 1602 waitForIdle(); 1603 verify(mListeners, times(1)).notifyPostedLocked(any(), any()); 1604 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any()); 1605 } 1606 1607 @Test testUserInitiatedClearAll_noLeak()1608 public void testUserInitiatedClearAll_noLeak() throws Exception { 1609 final NotificationRecord n = generateNotificationRecord( 1610 mTestNotificationChannel, 1, "group", true); 1611 1612 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1613 "testUserInitiatedClearAll_noLeak", 1614 n.getSbn().getId(), n.getSbn().getNotification(), n.getSbn().getUserId()); 1615 waitForIdle(); 1616 1617 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1618 n.getUserId()); 1619 waitForIdle(); 1620 StatusBarNotification[] notifs = 1621 mBinderService.getActiveNotifications(n.getSbn().getPackageName()); 1622 assertEquals(0, notifs.length); 1623 assertEquals(0, mService.getNotificationRecordCount()); 1624 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 1625 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture()); 1626 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface()); 1627 } 1628 1629 @Test testCancelAllNotificationsCancelsChildren()1630 public void testCancelAllNotificationsCancelsChildren() throws Exception { 1631 final NotificationRecord parent = generateNotificationRecord( 1632 mTestNotificationChannel, 1, "group1", true); 1633 final NotificationRecord child = generateNotificationRecord( 1634 mTestNotificationChannel, 2, "group1", false); 1635 1636 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1637 "testCancelAllNotificationsCancelsChildren", 1638 parent.getSbn().getId(), parent.getSbn().getNotification(), 1639 parent.getSbn().getUserId()); 1640 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1641 "testCancelAllNotificationsCancelsChildren", 1642 child.getSbn().getId(), child.getSbn().getNotification(), 1643 child.getSbn().getUserId()); 1644 waitForIdle(); 1645 1646 mBinderService.cancelAllNotifications(PKG, parent.getSbn().getUserId()); 1647 waitForIdle(); 1648 assertEquals(0, mService.getNotificationRecordCount()); 1649 } 1650 1651 @Test testCancelAllNotificationsMultipleEnqueuedDoesNotCrash()1652 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception { 1653 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1654 for (int i = 0; i < 10; i++) { 1655 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1656 "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash", 1657 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1658 } 1659 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 1660 waitForIdle(); 1661 1662 assertEquals(0, mService.getNotificationRecordCount()); 1663 } 1664 1665 @Test testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash()1666 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception { 1667 final NotificationRecord parent = generateNotificationRecord( 1668 mTestNotificationChannel, 1, "group1", true); 1669 final NotificationRecord parentAsChild = generateNotificationRecord( 1670 mTestNotificationChannel, 1, "group1", false); 1671 final NotificationRecord child = generateNotificationRecord( 1672 mTestNotificationChannel, 2, "group1", false); 1673 1674 // fully post parent notification 1675 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1676 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", 1677 parent.getSbn().getId(), parent.getSbn().getNotification(), 1678 parent.getSbn().getUserId()); 1679 waitForIdle(); 1680 1681 // enqueue the child several times 1682 for (int i = 0; i < 10; i++) { 1683 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1684 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", 1685 child.getSbn().getId(), child.getSbn().getNotification(), 1686 child.getSbn().getUserId()); 1687 } 1688 // make the parent a child, which will cancel the child notification 1689 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1690 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", 1691 parentAsChild.getSbn().getId(), parentAsChild.getSbn().getNotification(), 1692 parentAsChild.getSbn().getUserId()); 1693 waitForIdle(); 1694 1695 assertEquals(0, mService.getNotificationRecordCount()); 1696 } 1697 1698 @Test testAutobundledSummary_notificationAdded()1699 public void testAutobundledSummary_notificationAdded() { 1700 NotificationRecord summary = 1701 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true); 1702 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY; 1703 mService.addNotification(summary); 1704 mService.mSummaryByGroupKey.put("pkg", summary); 1705 mService.mAutobundledSummaries.put(0, new ArrayMap<>()); 1706 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey()); 1707 mService.updateAutobundledSummaryFlags(0, "pkg", true, false); 1708 1709 assertTrue(summary.getSbn().isOngoing()); 1710 } 1711 1712 @Test testAutobundledSummary_notificationRemoved()1713 public void testAutobundledSummary_notificationRemoved() { 1714 NotificationRecord summary = 1715 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true); 1716 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY; 1717 summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 1718 mService.addNotification(summary); 1719 mService.mAutobundledSummaries.put(0, new ArrayMap<>()); 1720 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey()); 1721 mService.mSummaryByGroupKey.put("pkg", summary); 1722 1723 mService.updateAutobundledSummaryFlags(0, "pkg", false, false); 1724 1725 assertFalse(summary.getSbn().isOngoing()); 1726 } 1727 1728 @Test testCancelAllNotifications_IgnoreForegroundService()1729 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception { 1730 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1731 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1732 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1733 "testCancelAllNotifications_IgnoreForegroundService", 1734 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1735 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 1736 waitForIdle(); 1737 StatusBarNotification[] notifs = 1738 mBinderService.getActiveNotifications(sbn.getPackageName()); 1739 assertEquals(1, notifs.length); 1740 assertEquals(1, mService.getNotificationRecordCount()); 1741 } 1742 1743 @Test testCancelAllNotifications_IgnoreOtherPackages()1744 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception { 1745 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1746 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1747 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1748 "testCancelAllNotifications_IgnoreOtherPackages", 1749 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1750 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId()); 1751 waitForIdle(); 1752 StatusBarNotification[] notifs = 1753 mBinderService.getActiveNotifications(sbn.getPackageName()); 1754 assertEquals(1, notifs.length); 1755 assertEquals(1, mService.getNotificationRecordCount()); 1756 } 1757 1758 @Test testCancelAllNotifications_NullPkgRemovesAll()1759 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception { 1760 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1761 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1762 "testCancelAllNotifications_NullPkgRemovesAll", 1763 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1764 mBinderService.cancelAllNotifications(null, sbn.getUserId()); 1765 waitForIdle(); 1766 StatusBarNotification[] notifs = 1767 mBinderService.getActiveNotifications(sbn.getPackageName()); 1768 assertEquals(0, notifs.length); 1769 assertEquals(0, mService.getNotificationRecordCount()); 1770 } 1771 1772 @Test testCancelAllNotifications_NullPkgIgnoresUserAllNotifications()1773 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception { 1774 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1775 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1776 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications", 1777 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL); 1778 // Null pkg is how we signal a user switch. 1779 mBinderService.cancelAllNotifications(null, sbn.getUserId()); 1780 waitForIdle(); 1781 StatusBarNotification[] notifs = 1782 mBinderService.getActiveNotifications(sbn.getPackageName()); 1783 assertEquals(1, notifs.length); 1784 assertEquals(1, mService.getNotificationRecordCount()); 1785 } 1786 1787 @Test testAppInitiatedCancelAllNotifications_CancelsNoClearFlag()1788 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception { 1789 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1790 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1791 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1792 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag", 1793 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1794 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 1795 waitForIdle(); 1796 StatusBarNotification[] notifs = 1797 mBinderService.getActiveNotifications(sbn.getPackageName()); 1798 assertEquals(0, notifs.length); 1799 } 1800 1801 @Test testCancelAllNotifications_CancelsNoClearFlag()1802 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception { 1803 final NotificationRecord notif = generateNotificationRecord( 1804 mTestNotificationChannel, 1, "group", true); 1805 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1806 mService.addNotification(notif); 1807 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true, 1808 notif.getUserId(), 0, null); 1809 waitForIdle(); 1810 StatusBarNotification[] notifs = 1811 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 1812 assertEquals(0, notifs.length); 1813 } 1814 1815 @Test testUserInitiatedCancelAllOnClearAll_NoClearFlag()1816 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception { 1817 final NotificationRecord notif = generateNotificationRecord( 1818 mTestNotificationChannel, 1, "group", true); 1819 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1820 mService.addNotification(notif); 1821 1822 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1823 notif.getUserId()); 1824 waitForIdle(); 1825 StatusBarNotification[] notifs = 1826 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 1827 assertEquals(1, notifs.length); 1828 } 1829 1830 @Test testCancelAllCancelNotificationsFromListener_NoClearFlag()1831 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception { 1832 final NotificationRecord parent = generateNotificationRecord( 1833 mTestNotificationChannel, 1, "group", true); 1834 final NotificationRecord child = generateNotificationRecord( 1835 mTestNotificationChannel, 2, "group", false); 1836 final NotificationRecord child2 = generateNotificationRecord( 1837 mTestNotificationChannel, 3, "group", false); 1838 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1839 final NotificationRecord newGroup = generateNotificationRecord( 1840 mTestNotificationChannel, 4, "group2", false); 1841 mService.addNotification(parent); 1842 mService.addNotification(child); 1843 mService.addNotification(child2); 1844 mService.addNotification(newGroup); 1845 mService.getBinderService().cancelNotificationsFromListener(null, null); 1846 waitForIdle(); 1847 StatusBarNotification[] notifs = 1848 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 1849 assertEquals(1, notifs.length); 1850 } 1851 1852 @Test testUserInitiatedCancelAllWithGroup_NoClearFlag()1853 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception { 1854 final NotificationRecord parent = generateNotificationRecord( 1855 mTestNotificationChannel, 1, "group", true); 1856 final NotificationRecord child = generateNotificationRecord( 1857 mTestNotificationChannel, 2, "group", false); 1858 final NotificationRecord child2 = generateNotificationRecord( 1859 mTestNotificationChannel, 3, "group", false); 1860 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 1861 final NotificationRecord newGroup = generateNotificationRecord( 1862 mTestNotificationChannel, 4, "group2", false); 1863 mService.addNotification(parent); 1864 mService.addNotification(child); 1865 mService.addNotification(child2); 1866 mService.addNotification(newGroup); 1867 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1868 parent.getUserId()); 1869 waitForIdle(); 1870 StatusBarNotification[] notifs = 1871 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 1872 assertEquals(1, notifs.length); 1873 } 1874 1875 @Test testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue()1876 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception { 1877 Notification n = 1878 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 1879 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1880 .build(); 1881 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0, 1882 n, UserHandle.getUserHandleForUid(mUid), null, 0); 1883 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1884 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 1885 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1886 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(), 1887 sbn.getUserId()); 1888 waitForIdle(); 1889 StatusBarNotification[] notifs = 1890 mBinderService.getActiveNotifications(sbn.getPackageName()); 1891 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE); 1892 } 1893 1894 @Test testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag()1895 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception { 1896 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1897 sbn.getNotification().flags = 1898 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; 1899 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 1900 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1901 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT; 1902 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 1903 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1904 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), 1905 sbn.getUserId()); 1906 waitForIdle(); 1907 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1908 assertEquals(0, mService.getNotificationRecordCount()); 1909 } 1910 1911 @Test testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()1912 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag() 1913 throws Exception { 1914 final NotificationRecord parent = generateNotificationRecord( 1915 mTestNotificationChannel, 1, "group", true); 1916 final NotificationRecord child = generateNotificationRecord( 1917 mTestNotificationChannel, 2, "group", false); 1918 final NotificationRecord child2 = generateNotificationRecord( 1919 mTestNotificationChannel, 3, "group", false); 1920 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1921 final NotificationRecord newGroup = generateNotificationRecord( 1922 mTestNotificationChannel, 4, "group2", false); 1923 mService.addNotification(parent); 1924 mService.addNotification(child); 1925 mService.addNotification(child2); 1926 mService.addNotification(newGroup); 1927 mService.getBinderService().cancelNotificationsFromListener(null, null); 1928 waitForIdle(); 1929 StatusBarNotification[] notifs = 1930 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 1931 assertEquals(0, notifs.length); 1932 } 1933 1934 @Test testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()1935 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter() 1936 throws Exception { 1937 final NotificationRecord parent = generateNotificationRecord( 1938 mTestNotificationChannel, 1, "group", true); 1939 final NotificationRecord child = generateNotificationRecord( 1940 mTestNotificationChannel, 2, "group", false); 1941 final NotificationRecord child2 = generateNotificationRecord( 1942 mTestNotificationChannel, 3, "group", false); 1943 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1944 final NotificationRecord newGroup = generateNotificationRecord( 1945 mTestNotificationChannel, 4, "group2", false); 1946 mService.addNotification(parent); 1947 mService.addNotification(child); 1948 mService.addNotification(child2); 1949 mService.addNotification(newGroup); 1950 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 1951 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 1952 mService.getBinderService().cancelNotificationsFromListener(null, keys); 1953 waitForIdle(); 1954 StatusBarNotification[] notifs = 1955 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 1956 assertEquals(1, notifs.length); 1957 } 1958 1959 @Test testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag()1960 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception { 1961 final NotificationRecord parent = generateNotificationRecord( 1962 mTestNotificationChannel, 1, "group", true); 1963 final NotificationRecord child = generateNotificationRecord( 1964 mTestNotificationChannel, 2, "group", false); 1965 final NotificationRecord child2 = generateNotificationRecord( 1966 mTestNotificationChannel, 3, "group", false); 1967 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1968 final NotificationRecord newGroup = generateNotificationRecord( 1969 mTestNotificationChannel, 4, "group2", false); 1970 mService.addNotification(parent); 1971 mService.addNotification(child); 1972 mService.addNotification(child2); 1973 mService.addNotification(newGroup); 1974 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 1975 parent.getUserId()); 1976 waitForIdle(); 1977 StatusBarNotification[] notifs = 1978 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 1979 assertEquals(0, notifs.length); 1980 } 1981 1982 @Test testGroupInstanceIds()1983 public void testGroupInstanceIds() throws Exception { 1984 final NotificationRecord group1 = generateNotificationRecord( 1985 mTestNotificationChannel, 1, "group1", true); 1986 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 1987 group1.getSbn().getId(), group1.getSbn().getNotification(), 1988 group1.getSbn().getUserId()); 1989 waitForIdle(); 1990 1991 // same group, child, should be returned 1992 final NotificationRecord group1Child = generateNotificationRecord( 1993 mTestNotificationChannel, 2, "group1", false); 1994 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 1995 group1Child.getSbn().getId(), 1996 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId()); 1997 waitForIdle(); 1998 1999 assertEquals(2, mNotificationRecordLogger.numCalls()); 2000 assertEquals(mNotificationRecordLogger.get(0).getInstanceId(), 2001 mNotificationRecordLogger.get(1).groupInstanceId.getId()); 2002 } 2003 2004 @Test testFindGroupNotificationsLocked()2005 public void testFindGroupNotificationsLocked() throws Exception { 2006 // make sure the same notification can be found in both lists and returned 2007 final NotificationRecord group1 = generateNotificationRecord( 2008 mTestNotificationChannel, 1, "group1", true); 2009 mService.addEnqueuedNotification(group1); 2010 mService.addNotification(group1); 2011 2012 // should not be returned 2013 final NotificationRecord group2 = generateNotificationRecord( 2014 mTestNotificationChannel, 2, "group2", true); 2015 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 2016 group2.getSbn().getId(), group2.getSbn().getNotification(), 2017 group2.getSbn().getUserId()); 2018 waitForIdle(); 2019 2020 // should not be returned 2021 final NotificationRecord nonGroup = generateNotificationRecord( 2022 mTestNotificationChannel, 3, null, false); 2023 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 2024 nonGroup.getSbn().getId(), nonGroup.getSbn().getNotification(), 2025 nonGroup.getSbn().getUserId()); 2026 waitForIdle(); 2027 2028 // same group, child, should be returned 2029 final NotificationRecord group1Child = generateNotificationRecord( 2030 mTestNotificationChannel, 4, "group1", false); 2031 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 2032 group1Child.getSbn().getId(), 2033 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId()); 2034 waitForIdle(); 2035 2036 List<NotificationRecord> inGroup1 = 2037 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(), 2038 group1.getSbn().getUserId()); 2039 assertEquals(3, inGroup1.size()); 2040 for (NotificationRecord record : inGroup1) { 2041 assertTrue(record.getGroupKey().equals(group1.getGroupKey())); 2042 assertTrue(record.getSbn().getId() == 1 || record.getSbn().getId() == 4); 2043 } 2044 } 2045 2046 @Test testCancelAllNotifications_CancelsNoClearFlagOnGoing()2047 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception { 2048 final NotificationRecord notif = generateNotificationRecord( 2049 mTestNotificationChannel, 1, "group", true); 2050 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 2051 mService.addNotification(notif); 2052 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 2053 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null); 2054 waitForIdle(); 2055 StatusBarNotification[] notifs = 2056 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 2057 assertEquals(0, notifs.length); 2058 } 2059 2060 @Test testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()2061 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter() 2062 throws Exception { 2063 final NotificationRecord parent = generateNotificationRecord( 2064 mTestNotificationChannel, 1, "group", true); 2065 final NotificationRecord child = generateNotificationRecord( 2066 mTestNotificationChannel, 2, "group", false); 2067 final NotificationRecord child2 = generateNotificationRecord( 2068 mTestNotificationChannel, 3, "group", false); 2069 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 2070 final NotificationRecord newGroup = generateNotificationRecord( 2071 mTestNotificationChannel, 4, "group2", false); 2072 mService.addNotification(parent); 2073 mService.addNotification(child); 2074 mService.addNotification(child2); 2075 mService.addNotification(newGroup); 2076 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2077 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2078 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2079 waitForIdle(); 2080 StatusBarNotification[] notifs = 2081 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2082 assertEquals(0, notifs.length); 2083 } 2084 2085 @Test testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag()2086 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception { 2087 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2088 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 2089 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2090 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag", 2091 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2092 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2093 waitForIdle(); 2094 StatusBarNotification[] notifs = 2095 mBinderService.getActiveNotifications(sbn.getPackageName()); 2096 assertEquals(0, notifs.length); 2097 } 2098 2099 @Test testCancelAllNotifications_CancelsOnGoingFlag()2100 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception { 2101 final NotificationRecord notif = generateNotificationRecord( 2102 mTestNotificationChannel, 1, "group", true); 2103 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 2104 mService.addNotification(notif); 2105 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true, 2106 notif.getUserId(), 0, null); 2107 waitForIdle(); 2108 StatusBarNotification[] notifs = 2109 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 2110 assertEquals(0, notifs.length); 2111 } 2112 2113 @Test testUserInitiatedCancelAllOnClearAll_OnGoingFlag()2114 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception { 2115 final NotificationRecord notif = generateNotificationRecord( 2116 mTestNotificationChannel, 1, "group", true); 2117 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 2118 mService.addNotification(notif); 2119 2120 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 2121 notif.getUserId()); 2122 waitForIdle(); 2123 StatusBarNotification[] notifs = 2124 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 2125 assertEquals(1, notifs.length); 2126 } 2127 2128 @Test testCancelAllCancelNotificationsFromListener_OnGoingFlag()2129 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception { 2130 final NotificationRecord parent = generateNotificationRecord( 2131 mTestNotificationChannel, 1, "group", true); 2132 final NotificationRecord child = generateNotificationRecord( 2133 mTestNotificationChannel, 2, "group", false); 2134 final NotificationRecord child2 = generateNotificationRecord( 2135 mTestNotificationChannel, 3, "group", false); 2136 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 2137 final NotificationRecord newGroup = generateNotificationRecord( 2138 mTestNotificationChannel, 4, "group2", false); 2139 mService.addNotification(parent); 2140 mService.addNotification(child); 2141 mService.addNotification(child2); 2142 mService.addNotification(newGroup); 2143 mService.getBinderService().cancelNotificationsFromListener(null, null); 2144 waitForIdle(); 2145 StatusBarNotification[] notifs = 2146 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2147 assertEquals(1, notifs.length); 2148 } 2149 2150 @Test testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()2151 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter() 2152 throws Exception { 2153 final NotificationRecord parent = generateNotificationRecord( 2154 mTestNotificationChannel, 1, "group", true); 2155 final NotificationRecord child = generateNotificationRecord( 2156 mTestNotificationChannel, 2, "group", false); 2157 final NotificationRecord child2 = generateNotificationRecord( 2158 mTestNotificationChannel, 3, "group", false); 2159 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 2160 final NotificationRecord newGroup = generateNotificationRecord( 2161 mTestNotificationChannel, 4, "group2", false); 2162 mService.addNotification(parent); 2163 mService.addNotification(child); 2164 mService.addNotification(child2); 2165 mService.addNotification(newGroup); 2166 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2167 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2168 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2169 waitForIdle(); 2170 StatusBarNotification[] notifs = 2171 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2172 assertEquals(0, notifs.length); 2173 } 2174 2175 @Test testUserInitiatedCancelAllWithGroup_OnGoingFlag()2176 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception { 2177 final NotificationRecord parent = generateNotificationRecord( 2178 mTestNotificationChannel, 1, "group", true); 2179 final NotificationRecord child = generateNotificationRecord( 2180 mTestNotificationChannel, 2, "group", false); 2181 final NotificationRecord child2 = generateNotificationRecord( 2182 mTestNotificationChannel, 3, "group", false); 2183 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 2184 final NotificationRecord newGroup = generateNotificationRecord( 2185 mTestNotificationChannel, 4, "group2", false); 2186 mService.addNotification(parent); 2187 mService.addNotification(child); 2188 mService.addNotification(child2); 2189 mService.addNotification(newGroup); 2190 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 2191 parent.getUserId()); 2192 waitForIdle(); 2193 StatusBarNotification[] notifs = 2194 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2195 assertEquals(1, notifs.length); 2196 } 2197 2198 @Test testTvExtenderChannelOverride_onTv()2199 public void testTvExtenderChannelOverride_onTv() throws Exception { 2200 mService.setIsTelevision(true); 2201 mService.setPreferencesHelper(mPreferencesHelper); 2202 when(mPreferencesHelper.getNotificationChannel( 2203 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn( 2204 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH)); 2205 2206 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); 2207 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0, 2208 generateNotificationRecord(null, tv).getNotification(), 0); 2209 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel( 2210 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean()); 2211 } 2212 2213 @Test testTvExtenderChannelOverride_notOnTv()2214 public void testTvExtenderChannelOverride_notOnTv() throws Exception { 2215 mService.setIsTelevision(false); 2216 mService.setPreferencesHelper(mPreferencesHelper); 2217 when(mPreferencesHelper.getNotificationChannel( 2218 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn( 2219 mTestNotificationChannel); 2220 2221 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); 2222 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv", 2223 0, generateNotificationRecord(null, tv).getNotification(), 0); 2224 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel( 2225 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null), 2226 anyBoolean(), anyBoolean()); 2227 } 2228 2229 @Test testUpdateAppNotifyCreatorBlock()2230 public void testUpdateAppNotifyCreatorBlock() throws Exception { 2231 mService.setPreferencesHelper(mPreferencesHelper); 2232 2233 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true); 2234 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 2235 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 2236 2237 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED, 2238 captor.getValue().getAction()); 2239 assertEquals(PKG, captor.getValue().getPackage()); 2240 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true)); 2241 } 2242 2243 @Test testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting()2244 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception { 2245 mService.setPreferencesHelper(mPreferencesHelper); 2246 2247 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false); 2248 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 2249 } 2250 2251 @Test testUpdateAppNotifyCreatorUnblock()2252 public void testUpdateAppNotifyCreatorUnblock() throws Exception { 2253 mService.setPreferencesHelper(mPreferencesHelper); 2254 2255 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true); 2256 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 2257 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 2258 2259 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED, 2260 captor.getValue().getAction()); 2261 assertEquals(PKG, captor.getValue().getPackage()); 2262 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true)); 2263 } 2264 2265 @Test testUpdateChannelNotifyCreatorBlock()2266 public void testUpdateChannelNotifyCreatorBlock() throws Exception { 2267 mService.setPreferencesHelper(mPreferencesHelper); 2268 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 2269 eq(mTestNotificationChannel.getId()), anyBoolean())) 2270 .thenReturn(mTestNotificationChannel); 2271 2272 NotificationChannel updatedChannel = 2273 new NotificationChannel(mTestNotificationChannel.getId(), 2274 mTestNotificationChannel.getName(), IMPORTANCE_NONE); 2275 2276 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel); 2277 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 2278 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 2279 2280 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, 2281 captor.getValue().getAction()); 2282 assertEquals(PKG, captor.getValue().getPackage()); 2283 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra( 2284 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID)); 2285 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 2286 } 2287 2288 @Test testUpdateChannelNotifyCreatorUnblock()2289 public void testUpdateChannelNotifyCreatorUnblock() throws Exception { 2290 NotificationChannel existingChannel = 2291 new NotificationChannel(mTestNotificationChannel.getId(), 2292 mTestNotificationChannel.getName(), IMPORTANCE_NONE); 2293 mService.setPreferencesHelper(mPreferencesHelper); 2294 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 2295 eq(mTestNotificationChannel.getId()), anyBoolean())) 2296 .thenReturn(existingChannel); 2297 2298 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 2299 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 2300 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 2301 2302 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, 2303 captor.getValue().getAction()); 2304 assertEquals(PKG, captor.getValue().getPackage()); 2305 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra( 2306 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID)); 2307 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 2308 } 2309 2310 @Test testUpdateChannelNoNotifyCreatorOtherChanges()2311 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception { 2312 NotificationChannel existingChannel = 2313 new NotificationChannel(mTestNotificationChannel.getId(), 2314 mTestNotificationChannel.getName(), IMPORTANCE_MAX); 2315 mService.setPreferencesHelper(mPreferencesHelper); 2316 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 2317 eq(mTestNotificationChannel.getId()), anyBoolean())) 2318 .thenReturn(existingChannel); 2319 2320 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 2321 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 2322 } 2323 2324 @Test testUpdateGroupNotifyCreatorBlock()2325 public void testUpdateGroupNotifyCreatorBlock() throws Exception { 2326 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 2327 mService.setPreferencesHelper(mPreferencesHelper); 2328 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), 2329 eq(PKG), anyInt())) 2330 .thenReturn(existing); 2331 2332 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name"); 2333 updated.setBlocked(true); 2334 2335 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated); 2336 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 2337 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 2338 2339 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED, 2340 captor.getValue().getAction()); 2341 assertEquals(PKG, captor.getValue().getPackage()); 2342 assertEquals(existing.getId(), captor.getValue().getStringExtra( 2343 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID)); 2344 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 2345 } 2346 2347 @Test testUpdateGroupNotifyCreatorUnblock()2348 public void testUpdateGroupNotifyCreatorUnblock() throws Exception { 2349 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 2350 existing.setBlocked(true); 2351 mService.setPreferencesHelper(mPreferencesHelper); 2352 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), 2353 eq(PKG), anyInt())) 2354 .thenReturn(existing); 2355 2356 mBinderService.updateNotificationChannelGroupForPackage( 2357 PKG, 0, new NotificationChannelGroup("id", "name")); 2358 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 2359 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 2360 2361 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED, 2362 captor.getValue().getAction()); 2363 assertEquals(PKG, captor.getValue().getPackage()); 2364 assertEquals(existing.getId(), captor.getValue().getStringExtra( 2365 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID)); 2366 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 2367 } 2368 2369 @Test testUpdateGroupNoNotifyCreatorOtherChanges()2370 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception { 2371 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 2372 mService.setPreferencesHelper(mPreferencesHelper); 2373 when(mPreferencesHelper.getNotificationChannelGroup( 2374 eq(existing.getId()), eq(PKG), anyInt())) 2375 .thenReturn(existing); 2376 2377 mBinderService.updateNotificationChannelGroupForPackage( 2378 PKG, 0, new NotificationChannelGroup("id", "new name")); 2379 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 2380 } 2381 2382 @Test testCreateChannelNotifyListener()2383 public void testCreateChannelNotifyListener() throws Exception { 2384 List<String> associations = new ArrayList<>(); 2385 associations.add("a"); 2386 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2387 .thenReturn(associations); 2388 mService.setPreferencesHelper(mPreferencesHelper); 2389 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 2390 eq(mTestNotificationChannel.getId()), anyBoolean())) 2391 .thenReturn(mTestNotificationChannel); 2392 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW); 2393 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 2394 eq(channel2.getId()), anyBoolean())) 2395 .thenReturn(channel2); 2396 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(), 2397 eq(channel2), anyBoolean(), anyBoolean())) 2398 .thenReturn(true); 2399 2400 reset(mListeners); 2401 mBinderService.createNotificationChannels(PKG, 2402 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2))); 2403 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 2404 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 2405 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 2406 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 2407 eq(Process.myUserHandle()), eq(channel2), 2408 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 2409 } 2410 2411 @Test testCreateChannelGroupNotifyListener()2412 public void testCreateChannelGroupNotifyListener() throws Exception { 2413 List<String> associations = new ArrayList<>(); 2414 associations.add("a"); 2415 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2416 .thenReturn(associations); 2417 mService.setPreferencesHelper(mPreferencesHelper); 2418 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b"); 2419 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m"); 2420 2421 reset(mListeners); 2422 mBinderService.createNotificationChannelGroups(PKG, 2423 new ParceledListSlice(Arrays.asList(group1, group2))); 2424 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 2425 eq(Process.myUserHandle()), eq(group1), 2426 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 2427 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 2428 eq(Process.myUserHandle()), eq(group2), 2429 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 2430 } 2431 2432 @Test testUpdateChannelNotifyListener()2433 public void testUpdateChannelNotifyListener() throws Exception { 2434 List<String> associations = new ArrayList<>(); 2435 associations.add("a"); 2436 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2437 .thenReturn(associations); 2438 mService.setPreferencesHelper(mPreferencesHelper); 2439 mTestNotificationChannel.setLightColor(Color.CYAN); 2440 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 2441 eq(mTestNotificationChannel.getId()), anyBoolean())) 2442 .thenReturn(mTestNotificationChannel); 2443 2444 reset(mListeners); 2445 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 2446 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 2447 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 2448 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 2449 } 2450 2451 @Test testDeleteChannelNotifyListener()2452 public void testDeleteChannelNotifyListener() throws Exception { 2453 List<String> associations = new ArrayList<>(); 2454 associations.add("a"); 2455 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2456 .thenReturn(associations); 2457 mService.setPreferencesHelper(mPreferencesHelper); 2458 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 2459 eq(mTestNotificationChannel.getId()), anyBoolean())) 2460 .thenReturn(mTestNotificationChannel); 2461 reset(mListeners); 2462 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId()); 2463 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 2464 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 2465 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); 2466 } 2467 2468 @Test testDeleteChannelGroupNotifyListener()2469 public void testDeleteChannelGroupNotifyListener() throws Exception { 2470 List<String> associations = new ArrayList<>(); 2471 associations.add("a"); 2472 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2473 .thenReturn(associations); 2474 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c"); 2475 mService.setPreferencesHelper(mPreferencesHelper); 2476 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt())) 2477 .thenReturn(ncg); 2478 reset(mListeners); 2479 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId()); 2480 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 2481 eq(Process.myUserHandle()), eq(ncg), 2482 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); 2483 } 2484 2485 @Test testUpdateNotificationChannelFromPrivilegedListener_success()2486 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception { 2487 mService.setPreferencesHelper(mPreferencesHelper); 2488 List<String> associations = new ArrayList<>(); 2489 associations.add("a"); 2490 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2491 .thenReturn(associations); 2492 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 2493 eq(mTestNotificationChannel.getId()), anyBoolean())) 2494 .thenReturn(mTestNotificationChannel); 2495 2496 mBinderService.updateNotificationChannelFromPrivilegedListener( 2497 null, PKG, Process.myUserHandle(), mTestNotificationChannel); 2498 2499 verify(mPreferencesHelper, times(1)).updateNotificationChannel( 2500 anyString(), anyInt(), any(), anyBoolean()); 2501 2502 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 2503 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 2504 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 2505 } 2506 2507 @Test testUpdateNotificationChannelFromPrivilegedListener_noAccess()2508 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception { 2509 mService.setPreferencesHelper(mPreferencesHelper); 2510 List<String> associations = new ArrayList<>(); 2511 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2512 .thenReturn(associations); 2513 2514 try { 2515 mBinderService.updateNotificationChannelFromPrivilegedListener( 2516 null, PKG, Process.myUserHandle(), mTestNotificationChannel); 2517 fail("listeners that don't have a companion device shouldn't be able to call this"); 2518 } catch (SecurityException e) { 2519 // pass 2520 } 2521 2522 verify(mPreferencesHelper, never()).updateNotificationChannel( 2523 anyString(), anyInt(), any(), anyBoolean()); 2524 2525 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 2526 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 2527 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 2528 } 2529 2530 @Test testUpdateNotificationChannelFromPrivilegedListener_badUser()2531 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception { 2532 mService.setPreferencesHelper(mPreferencesHelper); 2533 List<String> associations = new ArrayList<>(); 2534 associations.add("a"); 2535 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2536 .thenReturn(associations); 2537 mListener = mock(ManagedServices.ManagedServiceInfo.class); 2538 mListener.component = new ComponentName(PKG, PKG); 2539 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 2540 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 2541 2542 try { 2543 mBinderService.updateNotificationChannelFromPrivilegedListener( 2544 null, PKG, UserHandle.ALL, mTestNotificationChannel); 2545 fail("incorrectly allowed a change to a user listener cannot see"); 2546 } catch (SecurityException e) { 2547 // pass 2548 } 2549 2550 verify(mPreferencesHelper, never()).updateNotificationChannel( 2551 anyString(), anyInt(), any(), anyBoolean()); 2552 2553 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 2554 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 2555 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 2556 } 2557 2558 @Test testGetNotificationChannelFromPrivilegedListener_cdm_success()2559 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception { 2560 mService.setPreferencesHelper(mPreferencesHelper); 2561 List<String> associations = new ArrayList<>(); 2562 associations.add("a"); 2563 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2564 .thenReturn(associations); 2565 2566 mBinderService.getNotificationChannelsFromPrivilegedListener( 2567 null, PKG, Process.myUserHandle()); 2568 2569 verify(mPreferencesHelper, times(1)).getNotificationChannels( 2570 anyString(), anyInt(), anyBoolean()); 2571 } 2572 2573 @Test testGetNotificationChannelFromPrivilegedListener_cdm_noAccess()2574 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception { 2575 mService.setPreferencesHelper(mPreferencesHelper); 2576 List<String> associations = new ArrayList<>(); 2577 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2578 .thenReturn(associations); 2579 2580 try { 2581 mBinderService.getNotificationChannelsFromPrivilegedListener( 2582 null, PKG, Process.myUserHandle()); 2583 fail("listeners that don't have a companion device shouldn't be able to call this"); 2584 } catch (SecurityException e) { 2585 // pass 2586 } 2587 2588 verify(mPreferencesHelper, never()).getNotificationChannels( 2589 anyString(), anyInt(), anyBoolean()); 2590 } 2591 2592 @Test testGetNotificationChannelFromPrivilegedListener_assistant_success()2593 public void testGetNotificationChannelFromPrivilegedListener_assistant_success() 2594 throws Exception { 2595 mService.setPreferencesHelper(mPreferencesHelper); 2596 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2597 .thenReturn(new ArrayList<>()); 2598 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); 2599 2600 mBinderService.getNotificationChannelsFromPrivilegedListener( 2601 null, PKG, Process.myUserHandle()); 2602 2603 verify(mPreferencesHelper, times(1)).getNotificationChannels( 2604 anyString(), anyInt(), anyBoolean()); 2605 } 2606 2607 @Test testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()2608 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess() 2609 throws Exception { 2610 mService.setPreferencesHelper(mPreferencesHelper); 2611 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2612 .thenReturn(new ArrayList<>()); 2613 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false); 2614 2615 try { 2616 mBinderService.getNotificationChannelsFromPrivilegedListener( 2617 null, PKG, Process.myUserHandle()); 2618 fail("listeners that don't have a companion device shouldn't be able to call this"); 2619 } catch (SecurityException e) { 2620 // pass 2621 } 2622 2623 verify(mPreferencesHelper, never()).getNotificationChannels( 2624 anyString(), anyInt(), anyBoolean()); 2625 } 2626 2627 @Test testGetNotificationChannelFromPrivilegedListener_badUser()2628 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception { 2629 mService.setPreferencesHelper(mPreferencesHelper); 2630 List<String> associations = new ArrayList<>(); 2631 associations.add("a"); 2632 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2633 .thenReturn(associations); 2634 mListener = mock(ManagedServices.ManagedServiceInfo.class); 2635 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 2636 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 2637 2638 try { 2639 mBinderService.getNotificationChannelsFromPrivilegedListener( 2640 null, PKG, Process.myUserHandle()); 2641 fail("listener getting channels from a user they cannot see"); 2642 } catch (SecurityException e) { 2643 // pass 2644 } 2645 2646 verify(mPreferencesHelper, never()).getNotificationChannels( 2647 anyString(), anyInt(), anyBoolean()); 2648 } 2649 2650 @Test testGetNotificationChannelGroupsFromPrivilegedListener_success()2651 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception { 2652 mService.setPreferencesHelper(mPreferencesHelper); 2653 List<String> associations = new ArrayList<>(); 2654 associations.add("a"); 2655 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2656 .thenReturn(associations); 2657 2658 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 2659 null, PKG, Process.myUserHandle()); 2660 2661 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt()); 2662 } 2663 2664 @Test testGetNotificationChannelGroupsFromPrivilegedListener_noAccess()2665 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception { 2666 mService.setPreferencesHelper(mPreferencesHelper); 2667 List<String> associations = new ArrayList<>(); 2668 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2669 .thenReturn(associations); 2670 2671 try { 2672 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 2673 null, PKG, Process.myUserHandle()); 2674 fail("listeners that don't have a companion device shouldn't be able to call this"); 2675 } catch (SecurityException e) { 2676 // pass 2677 } 2678 2679 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); 2680 } 2681 2682 @Test testGetNotificationChannelGroupsFromPrivilegedListener_badUser()2683 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception { 2684 mService.setPreferencesHelper(mPreferencesHelper); 2685 List<String> associations = new ArrayList<>(); 2686 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 2687 .thenReturn(associations); 2688 mListener = mock(ManagedServices.ManagedServiceInfo.class); 2689 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 2690 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 2691 try { 2692 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 2693 null, PKG, Process.myUserHandle()); 2694 fail("listeners that don't have a companion device shouldn't be able to call this"); 2695 } catch (SecurityException e) { 2696 // pass 2697 } 2698 2699 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); 2700 } 2701 2702 @Test testHasCompanionDevice_failure()2703 public void testHasCompanionDevice_failure() throws Exception { 2704 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow( 2705 new IllegalArgumentException()); 2706 mService.hasCompanionDevice(mListener); 2707 } 2708 2709 @Test testHasCompanionDevice_noService()2710 public void testHasCompanionDevice_noService() { 2711 mService = 2712 new TestableNotificationManagerService(mContext, mNotificationRecordLogger, 2713 mSystemClock, mNotificationInstanceIdSequence); 2714 2715 assertFalse(mService.hasCompanionDevice(mListener)); 2716 } 2717 2718 @Test testSnoozeRunnable_reSnoozeASingleSnoozedNotification()2719 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception { 2720 final NotificationRecord notification = generateNotificationRecord( 2721 mTestNotificationChannel, 1, null, true); 2722 mService.addNotification(notification); 2723 when(mSnoozeHelper.getNotification(any())).thenReturn(notification); 2724 2725 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2726 mService.new SnoozeNotificationRunnable( 2727 notification.getKey(), 100, null); 2728 snoozeNotificationRunnable.run(); 2729 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 = 2730 mService.new SnoozeNotificationRunnable( 2731 notification.getKey(), 100, null); 2732 snoozeNotificationRunnable.run(); 2733 2734 // snooze twice 2735 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 2736 } 2737 2738 @Test testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey()2739 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception { 2740 final NotificationRecord notification = generateNotificationRecord( 2741 mTestNotificationChannel, 1, "group", true); 2742 mService.addNotification(notification); 2743 when(mSnoozeHelper.getNotification(any())).thenReturn(notification); 2744 2745 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2746 mService.new SnoozeNotificationRunnable( 2747 notification.getKey(), 100, null); 2748 snoozeNotificationRunnable.run(); 2749 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 = 2750 mService.new SnoozeNotificationRunnable( 2751 notification.getKey(), 100, null); 2752 snoozeNotificationRunnable.run(); 2753 2754 // snooze twice 2755 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 2756 } 2757 2758 @Test testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey()2759 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception { 2760 final NotificationRecord notification = generateNotificationRecord( 2761 mTestNotificationChannel, 1, "group", true); 2762 final NotificationRecord notification2 = generateNotificationRecord( 2763 mTestNotificationChannel, 2, "group", true); 2764 mService.addNotification(notification); 2765 mService.addNotification(notification2); 2766 when(mSnoozeHelper.getNotification(any())).thenReturn(notification); 2767 when(mSnoozeHelper.getNotifications( 2768 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>()); 2769 2770 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2771 mService.new SnoozeNotificationRunnable( 2772 notification.getKey(), 100, null); 2773 snoozeNotificationRunnable.run(); 2774 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt())) 2775 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2))); 2776 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 = 2777 mService.new SnoozeNotificationRunnable( 2778 notification.getKey(), 100, null); 2779 snoozeNotificationRunnable.run(); 2780 2781 // snooze twice 2782 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong()); 2783 } 2784 2785 @Test testSnoozeRunnable_snoozeNonGrouped()2786 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception { 2787 final NotificationRecord nonGrouped = generateNotificationRecord( 2788 mTestNotificationChannel, 1, null, false); 2789 final NotificationRecord grouped = generateNotificationRecord( 2790 mTestNotificationChannel, 2, "group", false); 2791 mService.addNotification(grouped); 2792 mService.addNotification(nonGrouped); 2793 2794 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2795 mService.new SnoozeNotificationRunnable( 2796 nonGrouped.getKey(), 100, null); 2797 snoozeNotificationRunnable.run(); 2798 2799 // only snooze the one notification 2800 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 2801 assertTrue(nonGrouped.getStats().hasSnoozed()); 2802 2803 assertEquals(2, mNotificationRecordLogger.numCalls()); 2804 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 2805 mNotificationRecordLogger.event(0)); 2806 assertEquals( 2807 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 2808 mNotificationRecordLogger.event(1)); 2809 } 2810 2811 @Test testSnoozeRunnable_snoozeSummary_withChildren()2812 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception { 2813 final NotificationRecord parent = generateNotificationRecord( 2814 mTestNotificationChannel, 1, "group", true); 2815 final NotificationRecord child = generateNotificationRecord( 2816 mTestNotificationChannel, 2, "group", false); 2817 final NotificationRecord child2 = generateNotificationRecord( 2818 mTestNotificationChannel, 3, "group", false); 2819 mService.addNotification(parent); 2820 mService.addNotification(child); 2821 mService.addNotification(child2); 2822 2823 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2824 mService.new SnoozeNotificationRunnable( 2825 parent.getKey(), 100, null); 2826 snoozeNotificationRunnable.run(); 2827 2828 // snooze parent and children 2829 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong()); 2830 } 2831 2832 @Test testSnoozeRunnable_snoozeGroupChild_fellowChildren()2833 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception { 2834 final NotificationRecord parent = generateNotificationRecord( 2835 mTestNotificationChannel, 1, "group", true); 2836 final NotificationRecord child = generateNotificationRecord( 2837 mTestNotificationChannel, 2, "group", false); 2838 final NotificationRecord child2 = generateNotificationRecord( 2839 mTestNotificationChannel, 3, "group", false); 2840 mService.addNotification(parent); 2841 mService.addNotification(child); 2842 mService.addNotification(child2); 2843 2844 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2845 mService.new SnoozeNotificationRunnable( 2846 child2.getKey(), 100, null); 2847 snoozeNotificationRunnable.run(); 2848 2849 // only snooze the one child 2850 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 2851 2852 assertEquals(2, mNotificationRecordLogger.numCalls()); 2853 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 2854 mNotificationRecordLogger.event(0)); 2855 assertEquals(NotificationRecordLogger.NotificationCancelledEvent 2856 .NOTIFICATION_CANCEL_SNOOZED, mNotificationRecordLogger.event(1)); 2857 } 2858 2859 @Test testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary()2860 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception { 2861 final NotificationRecord parent = generateNotificationRecord( 2862 mTestNotificationChannel, 1, "group", true); 2863 assertTrue(parent.getSbn().getNotification().isGroupSummary()); 2864 final NotificationRecord child = generateNotificationRecord( 2865 mTestNotificationChannel, 2, "group", false); 2866 mService.addNotification(parent); 2867 mService.addNotification(child); 2868 2869 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2870 mService.new SnoozeNotificationRunnable( 2871 child.getKey(), 100, null); 2872 snoozeNotificationRunnable.run(); 2873 2874 // snooze child and summary 2875 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 2876 2877 assertEquals(4, mNotificationRecordLogger.numCalls()); 2878 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 2879 mNotificationRecordLogger.event(0)); 2880 assertEquals( 2881 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 2882 mNotificationRecordLogger.event(1)); 2883 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 2884 mNotificationRecordLogger.event(2)); 2885 assertEquals( 2886 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 2887 mNotificationRecordLogger.event(3)); 2888 } 2889 2890 @Test testSnoozeRunnable_snoozeGroupChild_noOthersInGroup()2891 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception { 2892 final NotificationRecord child = generateNotificationRecord( 2893 mTestNotificationChannel, 2, "group", false); 2894 mService.addNotification(child); 2895 2896 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2897 mService.new SnoozeNotificationRunnable( 2898 child.getKey(), 100, null); 2899 snoozeNotificationRunnable.run(); 2900 2901 // snooze child only 2902 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 2903 2904 assertEquals(2, mNotificationRecordLogger.numCalls()); 2905 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 2906 mNotificationRecordLogger.event(0)); 2907 assertEquals( 2908 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 2909 mNotificationRecordLogger.event(1)); 2910 } 2911 2912 @Test testPostGroupChild_unsnoozeParent()2913 public void testPostGroupChild_unsnoozeParent() throws Exception { 2914 final NotificationRecord child = generateNotificationRecord( 2915 mTestNotificationChannel, 2, "group", false); 2916 2917 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing", 2918 child.getSbn().getId(), child.getSbn().getNotification(), 2919 child.getSbn().getUserId()); 2920 waitForIdle(); 2921 2922 verify(mSnoozeHelper, times(1)).repostGroupSummary( 2923 anyString(), anyInt(), eq(child.getGroupKey())); 2924 } 2925 2926 @Test testPostNonGroup_noUnsnoozing()2927 public void testPostNonGroup_noUnsnoozing() throws Exception { 2928 final NotificationRecord record = generateNotificationRecord( 2929 mTestNotificationChannel, 2, null, false); 2930 2931 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing", 2932 record.getSbn().getId(), record.getSbn().getNotification(), 2933 record.getSbn().getUserId()); 2934 waitForIdle(); 2935 2936 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); 2937 } 2938 2939 @Test testPostGroupSummary_noUnsnoozing()2940 public void testPostGroupSummary_noUnsnoozing() throws Exception { 2941 final NotificationRecord parent = generateNotificationRecord( 2942 mTestNotificationChannel, 2, "group", true); 2943 2944 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing", 2945 parent.getSbn().getId(), parent.getSbn().getNotification(), 2946 parent.getSbn().getUserId()); 2947 waitForIdle(); 2948 2949 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); 2950 } 2951 2952 @Test testSystemNotificationListenerCanUnsnooze()2953 public void testSystemNotificationListenerCanUnsnooze() throws Exception { 2954 final NotificationRecord nr = generateNotificationRecord( 2955 mTestNotificationChannel, 2, "group", false); 2956 2957 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2958 "testSystemNotificationListenerCanUnsnooze", 2959 nr.getSbn().getId(), nr.getSbn().getNotification(), 2960 nr.getSbn().getUserId()); 2961 waitForIdle(); 2962 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 2963 mService.new SnoozeNotificationRunnable( 2964 nr.getKey(), 100, null); 2965 snoozeNotificationRunnable.run(); 2966 2967 ManagedServices.ManagedServiceInfo listener = mListeners.new ManagedServiceInfo( 2968 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0); 2969 listener.isSystem = true; 2970 when(mListeners.checkServiceTokenLocked(any())).thenReturn(listener); 2971 2972 mBinderService.unsnoozeNotificationFromSystemListener(null, nr.getKey()); 2973 waitForIdle(); 2974 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 2975 assertEquals(1, notifs.length); 2976 assertNotNull(notifs[0].getKey());//mService.getNotificationRecord(nr.getSbn().getKey())); 2977 } 2978 2979 @Test testSetListenerAccessForUser()2980 public void testSetListenerAccessForUser() throws Exception { 2981 UserHandle user = UserHandle.of(10); 2982 ComponentName c = ComponentName.unflattenFromString("package/Component"); 2983 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true); 2984 2985 2986 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 2987 verify(mListeners, times(1)).setPackageOrComponentEnabled( 2988 c.flattenToString(), user.getIdentifier(), true, true); 2989 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 2990 c.flattenToString(), user.getIdentifier(), false, true); 2991 verify(mAssistants, never()).setPackageOrComponentEnabled( 2992 any(), anyInt(), anyBoolean(), anyBoolean()); 2993 } 2994 2995 @Test testSetAssistantAccessForUser()2996 public void testSetAssistantAccessForUser() throws Exception { 2997 UserHandle user = UserHandle.of(10); 2998 List<UserInfo> uis = new ArrayList<>(); 2999 UserInfo ui = new UserInfo(); 3000 ui.id = 10; 3001 uis.add(ui); 3002 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3003 when(mUm.getEnabledProfiles(10)).thenReturn(uis); 3004 3005 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true); 3006 3007 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 3008 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 3009 c.flattenToString(), user.getIdentifier(), true, true); 3010 verify(mAssistants).setUserSet(10, true); 3011 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3012 c.flattenToString(), user.getIdentifier(), false, true); 3013 verify(mListeners, never()).setPackageOrComponentEnabled( 3014 any(), anyInt(), anyBoolean(), anyBoolean()); 3015 } 3016 3017 @Test testGetAssistantAllowedForUser()3018 public void testGetAssistantAllowedForUser() throws Exception { 3019 UserHandle user = UserHandle.of(10); 3020 try { 3021 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier()); 3022 } catch (IllegalStateException e) { 3023 if (!e.getMessage().contains("At most one NotificationAssistant")) { 3024 throw e; 3025 } 3026 } 3027 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier()); 3028 } 3029 3030 @Test testGetAssistantAllowed()3031 public void testGetAssistantAllowed() throws Exception { 3032 try { 3033 mBinderService.getAllowedNotificationAssistant(); 3034 } catch (IllegalStateException e) { 3035 if (!e.getMessage().contains("At most one NotificationAssistant")) { 3036 throw e; 3037 } 3038 } 3039 verify(mAssistants, times(1)).getAllowedComponents(0); 3040 } 3041 3042 @Test testSetDndAccessForUser()3043 public void testSetDndAccessForUser() throws Exception { 3044 UserHandle user = UserHandle.of(10); 3045 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3046 mBinderService.setNotificationPolicyAccessGrantedForUser( 3047 c.getPackageName(), user.getIdentifier(), true); 3048 3049 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 3050 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3051 c.getPackageName(), user.getIdentifier(), true, true); 3052 verify(mAssistants, never()).setPackageOrComponentEnabled( 3053 any(), anyInt(), anyBoolean(), anyBoolean()); 3054 verify(mListeners, never()).setPackageOrComponentEnabled( 3055 any(), anyInt(), anyBoolean(), anyBoolean()); 3056 } 3057 3058 @Test testSetListenerAccess()3059 public void testSetListenerAccess() throws Exception { 3060 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3061 mBinderService.setNotificationListenerAccessGranted(c, true); 3062 3063 verify(mListeners, times(1)).setPackageOrComponentEnabled( 3064 c.flattenToString(), 0, true, true); 3065 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3066 c.flattenToString(), 0, false, true); 3067 verify(mAssistants, never()).setPackageOrComponentEnabled( 3068 any(), anyInt(), anyBoolean(), anyBoolean()); 3069 } 3070 3071 @Test testSetAssistantAccess()3072 public void testSetAssistantAccess() throws Exception { 3073 List<UserInfo> uis = new ArrayList<>(); 3074 UserInfo ui = new UserInfo(); 3075 ui.id = 0; 3076 uis.add(ui); 3077 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 3078 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3079 3080 mBinderService.setNotificationAssistantAccessGranted(c, true); 3081 3082 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 3083 c.flattenToString(), 0, true, true); 3084 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3085 c.flattenToString(), 0, false, true); 3086 verify(mListeners, never()).setPackageOrComponentEnabled( 3087 any(), anyInt(), anyBoolean(), anyBoolean()); 3088 } 3089 3090 @Test testSetAssistantAccess_multiProfile()3091 public void testSetAssistantAccess_multiProfile() throws Exception { 3092 List<UserInfo> uis = new ArrayList<>(); 3093 UserInfo ui = new UserInfo(); 3094 ui.id = 0; 3095 uis.add(ui); 3096 UserInfo ui10 = new UserInfo(); 3097 ui10.id = 10; 3098 uis.add(ui10); 3099 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 3100 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3101 3102 mBinderService.setNotificationAssistantAccessGranted(c, true); 3103 3104 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 3105 c.flattenToString(), 0, true, true); 3106 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 3107 c.flattenToString(), 10, true, true); 3108 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3109 c.flattenToString(), 0, false, true); 3110 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3111 c.flattenToString(), 10, false, true); 3112 verify(mListeners, never()).setPackageOrComponentEnabled( 3113 any(), anyInt(), anyBoolean(), anyBoolean()); 3114 } 3115 3116 @Test testSetAssistantAccess_nullWithAllowedAssistant()3117 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception { 3118 ArrayList<ComponentName> componentList = new ArrayList<>(); 3119 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3120 componentList.add(c); 3121 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 3122 List<UserInfo> uis = new ArrayList<>(); 3123 UserInfo ui = new UserInfo(); 3124 ui.id = 0; 3125 uis.add(ui); 3126 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 3127 3128 mBinderService.setNotificationAssistantAccessGranted(null, true); 3129 3130 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 3131 c.flattenToString(), 0, true, false); 3132 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3133 c.flattenToString(), 0, false, false); 3134 verify(mListeners, never()).setPackageOrComponentEnabled( 3135 any(), anyInt(), anyBoolean(), anyBoolean()); 3136 } 3137 3138 @Test testSetAssistantAccessForUser_nullWithAllowedAssistant()3139 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception { 3140 List<UserInfo> uis = new ArrayList<>(); 3141 UserInfo ui = new UserInfo(); 3142 ui.id = 10; 3143 uis.add(ui); 3144 UserHandle user = ui.getUserHandle(); 3145 ArrayList<ComponentName> componentList = new ArrayList<>(); 3146 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3147 componentList.add(c); 3148 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 3149 when(mUm.getEnabledProfiles(10)).thenReturn(uis); 3150 3151 mBinderService.setNotificationAssistantAccessGrantedForUser( 3152 null, user.getIdentifier(), true); 3153 3154 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 3155 c.flattenToString(), user.getIdentifier(), true, false); 3156 verify(mAssistants).setUserSet(10, true); 3157 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3158 c.flattenToString(), user.getIdentifier(), false, false); 3159 verify(mListeners, never()).setPackageOrComponentEnabled( 3160 any(), anyInt(), anyBoolean(), anyBoolean()); 3161 } 3162 3163 @Test testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()3164 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant() 3165 throws Exception { 3166 List<UserInfo> uis = new ArrayList<>(); 3167 UserInfo ui = new UserInfo(); 3168 ui.id = 0; 3169 uis.add(ui); 3170 UserInfo ui10 = new UserInfo(); 3171 ui10.id = 10; 3172 uis.add(ui10); 3173 UserHandle user = ui.getUserHandle(); 3174 ArrayList<ComponentName> componentList = new ArrayList<>(); 3175 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3176 componentList.add(c); 3177 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 3178 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 3179 3180 mBinderService.setNotificationAssistantAccessGrantedForUser( 3181 null, user.getIdentifier(), true); 3182 3183 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 3184 c.flattenToString(), user.getIdentifier(), true, false); 3185 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 3186 c.flattenToString(), ui10.id, true, false); 3187 verify(mAssistants).setUserSet(0, true); 3188 verify(mAssistants).setUserSet(10, true); 3189 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3190 c.flattenToString(), user.getIdentifier(), false, false); 3191 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3192 c.flattenToString(), ui10.id, false, false); 3193 verify(mListeners, never()).setPackageOrComponentEnabled( 3194 any(), anyInt(), anyBoolean(), anyBoolean()); 3195 } 3196 3197 @Test testSetDndAccess()3198 public void testSetDndAccess() throws Exception { 3199 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3200 3201 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 3202 3203 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3204 c.getPackageName(), 0, true, true); 3205 verify(mAssistants, never()).setPackageOrComponentEnabled( 3206 any(), anyInt(), anyBoolean(), anyBoolean()); 3207 verify(mListeners, never()).setPackageOrComponentEnabled( 3208 any(), anyInt(), anyBoolean(), anyBoolean()); 3209 } 3210 3211 @Test testSetListenerAccess_onLowRam()3212 public void testSetListenerAccess_onLowRam() throws Exception { 3213 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3214 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3215 mBinderService.setNotificationListenerAccessGranted(c, true); 3216 3217 verify(mListeners).setPackageOrComponentEnabled( 3218 anyString(), anyInt(), anyBoolean(), anyBoolean()); 3219 verify(mConditionProviders).setPackageOrComponentEnabled( 3220 anyString(), anyInt(), anyBoolean(), anyBoolean()); 3221 verify(mAssistants).migrateToXml(); 3222 verify(mAssistants).resetDefaultAssistantsIfNecessary(); 3223 } 3224 3225 @Test testSetAssistantAccess_onLowRam()3226 public void testSetAssistantAccess_onLowRam() throws Exception { 3227 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3228 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3229 List<UserInfo> uis = new ArrayList<>(); 3230 UserInfo ui = new UserInfo(); 3231 ui.id = 0; 3232 uis.add(ui); 3233 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 3234 3235 mBinderService.setNotificationAssistantAccessGranted(c, true); 3236 3237 verify(mListeners).migrateToXml(); 3238 verify(mConditionProviders).setPackageOrComponentEnabled( 3239 anyString(), anyInt(), anyBoolean(), anyBoolean()); 3240 verify(mAssistants).migrateToXml(); 3241 verify(mAssistants).resetDefaultAssistantsIfNecessary(); 3242 } 3243 3244 @Test testSetDndAccess_onLowRam()3245 public void testSetDndAccess_onLowRam() throws Exception { 3246 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3247 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3248 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 3249 3250 verify(mListeners).migrateToXml(); 3251 verify(mConditionProviders).setPackageOrComponentEnabled( 3252 anyString(), anyInt(), anyBoolean(), anyBoolean()); 3253 verify(mAssistants).migrateToXml(); 3254 verify(mAssistants).resetDefaultAssistantsIfNecessary(); 3255 } 3256 3257 @Test testSetListenerAccess_doesNothingOnLowRam_exceptWatch()3258 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 3259 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 3260 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3261 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3262 3263 mBinderService.setNotificationListenerAccessGranted(c, true); 3264 3265 verify(mListeners, times(1)).setPackageOrComponentEnabled( 3266 c.flattenToString(), 0, true, true); 3267 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3268 c.flattenToString(), 0, false, true); 3269 verify(mAssistants, never()).setPackageOrComponentEnabled( 3270 any(), anyInt(), anyBoolean(), anyBoolean()); 3271 } 3272 3273 @Test testSetAssistantAccess_doesNothingOnLowRam_exceptWatch()3274 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 3275 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 3276 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3277 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3278 List<UserInfo> uis = new ArrayList<>(); 3279 UserInfo ui = new UserInfo(); 3280 ui.id = 0; 3281 uis.add(ui); 3282 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 3283 3284 mBinderService.setNotificationAssistantAccessGranted(c, true); 3285 3286 verify(mListeners, never()).setPackageOrComponentEnabled( 3287 anyString(), anyInt(), anyBoolean(), anyBoolean()); 3288 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3289 c.flattenToString(), 0, false, true); 3290 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 3291 c.flattenToString(), 0, true, true); 3292 } 3293 3294 @Test testSetDndAccess_doesNothingOnLowRam_exceptWatch()3295 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 3296 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 3297 when(mActivityManager.isLowRamDevice()).thenReturn(true); 3298 ComponentName c = ComponentName.unflattenFromString("package/Component"); 3299 3300 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 3301 3302 verify(mListeners, never()).setPackageOrComponentEnabled( 3303 anyString(), anyInt(), anyBoolean(), anyBoolean()); 3304 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 3305 c.getPackageName(), 0, true, true); 3306 verify(mAssistants, never()).setPackageOrComponentEnabled( 3307 any(), anyInt(), anyBoolean(), anyBoolean()); 3308 } 3309 3310 @Test testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups()3311 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception { 3312 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 3313 mService.addEnqueuedNotification(r); 3314 NotificationManagerService.PostNotificationRunnable runnable = 3315 mService.new PostNotificationRunnable(r.getKey()); 3316 runnable.run(); 3317 waitForIdle(); 3318 3319 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 3320 } 3321 3322 @Test testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()3323 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups() 3324 throws Exception { 3325 NotificationRecord r = 3326 generateNotificationRecord(mTestNotificationChannel, 0, "group", false); 3327 mService.addNotification(r); 3328 3329 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 3330 mService.addEnqueuedNotification(r); 3331 NotificationManagerService.PostNotificationRunnable runnable = 3332 mService.new PostNotificationRunnable(r.getKey()); 3333 runnable.run(); 3334 waitForIdle(); 3335 3336 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 3337 } 3338 3339 @Test testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()3340 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups() 3341 throws Exception { 3342 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group", 3343 false); 3344 mService.addNotification(r); 3345 mService.addEnqueuedNotification(r); 3346 3347 NotificationManagerService.PostNotificationRunnable runnable = 3348 mService.new PostNotificationRunnable(r.getKey()); 3349 runnable.run(); 3350 waitForIdle(); 3351 3352 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean()); 3353 } 3354 3355 @Test testDontAutogroupIfCritical()3356 public void testDontAutogroupIfCritical() throws Exception { 3357 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 3358 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW); 3359 mService.addEnqueuedNotification(r); 3360 NotificationManagerService.PostNotificationRunnable runnable = 3361 mService.new PostNotificationRunnable(r.getKey()); 3362 runnable.run(); 3363 3364 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false); 3365 r.setCriticality(CriticalNotificationExtractor.CRITICAL); 3366 runnable = mService.new PostNotificationRunnable(r.getKey()); 3367 mService.addEnqueuedNotification(r); 3368 3369 runnable.run(); 3370 waitForIdle(); 3371 3372 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean()); 3373 } 3374 3375 @Test testNoFakeColorizedPermission()3376 public void testNoFakeColorizedPermission() throws Exception { 3377 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED); 3378 Notification.Builder nb = new Notification.Builder(mContext, 3379 mTestNotificationChannel.getId()) 3380 .setContentTitle("foo") 3381 .setColorized(true) 3382 .setFlag(Notification.FLAG_CAN_COLORIZE, true) 3383 .setSmallIcon(android.R.drawable.sym_def_app_icon); 3384 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 3385 "testNoFakeColorizedPermission", mUid, 0, 3386 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 3387 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 3388 3389 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 3390 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 3391 waitForIdle(); 3392 3393 NotificationRecord posted = mService.findNotificationLocked( 3394 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 3395 3396 assertFalse(posted.getNotification().isColorized()); 3397 } 3398 3399 @Test testGetNotificationCountLocked()3400 public void testGetNotificationCountLocked() { 3401 String sampleTagToExclude = null; 3402 int sampleIdToExclude = 0; 3403 for (int i = 0; i < 20; i++) { 3404 NotificationRecord r = 3405 generateNotificationRecord(mTestNotificationChannel, i, null, false); 3406 mService.addEnqueuedNotification(r); 3407 3408 } 3409 for (int i = 0; i < 20; i++) { 3410 NotificationRecord r = 3411 generateNotificationRecord(mTestNotificationChannel, i, null, false); 3412 mService.addNotification(r); 3413 sampleTagToExclude = r.getSbn().getTag(); 3414 sampleIdToExclude = i; 3415 } 3416 3417 // another package 3418 Notification n = 3419 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 3420 .setSmallIcon(android.R.drawable.sym_def_app_icon) 3421 .build(); 3422 3423 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0, 3424 n, UserHandle.getUserHandleForUid(mUid), null, 0); 3425 NotificationRecord otherPackage = 3426 new NotificationRecord(mContext, sbn, mTestNotificationChannel); 3427 mService.addEnqueuedNotification(otherPackage); 3428 mService.addNotification(otherPackage); 3429 3430 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match 3431 // anything that's currently enqueued or posted 3432 int userId = UserHandle.getUserId(mUid); 3433 assertEquals(40, 3434 mService.getNotificationCountLocked(PKG, userId, 0, null)); 3435 assertEquals(40, 3436 mService.getNotificationCountLocked(PKG, userId, 0, "tag2")); 3437 3438 // return all for package "a" - "banana" tag isn't used 3439 assertEquals(2, 3440 mService.getNotificationCountLocked("a", userId, 0, "banana")); 3441 3442 // exclude a known notification - it's excluded from only the posted list, not enqueued 3443 assertEquals(39, mService.getNotificationCountLocked( 3444 PKG, userId, sampleIdToExclude, sampleTagToExclude)); 3445 } 3446 3447 @Test testAddAutogroup_requestsSort()3448 public void testAddAutogroup_requestsSort() throws Exception { 3449 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3450 mService.addNotification(r); 3451 mService.addAutogroupKeyLocked(r.getKey()); 3452 3453 verify(mRankingHandler, times(1)).requestSort(); 3454 } 3455 3456 @Test testRemoveAutogroup_requestsSort()3457 public void testRemoveAutogroup_requestsSort() throws Exception { 3458 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3459 r.setOverrideGroupKey("TEST"); 3460 mService.addNotification(r); 3461 mService.removeAutogroupKeyLocked(r.getKey()); 3462 3463 verify(mRankingHandler, times(1)).requestSort(); 3464 } 3465 3466 @Test testReaddAutogroup_noSort()3467 public void testReaddAutogroup_noSort() throws Exception { 3468 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3469 r.setOverrideGroupKey("TEST"); 3470 mService.addNotification(r); 3471 mService.addAutogroupKeyLocked(r.getKey()); 3472 3473 verify(mRankingHandler, never()).requestSort(); 3474 } 3475 3476 @Test testHandleRankingSort_sendsUpdateOnSignalExtractorChange()3477 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception { 3478 mService.setPreferencesHelper(mPreferencesHelper); 3479 NotificationManagerService.WorkerHandler handler = mock( 3480 NotificationManagerService.WorkerHandler.class); 3481 mService.setHandler(handler); 3482 3483 Map<String, Answer> answers = getSignalExtractorSideEffects(); 3484 for (String message : answers.keySet()) { 3485 mService.clearNotifications(); 3486 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3487 mService.addNotification(r); 3488 3489 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r); 3490 3491 mService.handleRankingSort(); 3492 } 3493 verify(handler, times(answers.size())).scheduleSendRankingUpdate(); 3494 } 3495 3496 @Test testHandleRankingSort_noUpdateWhenNoSignalChange()3497 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception { 3498 mService.setRankingHelper(mRankingHelper); 3499 NotificationManagerService.WorkerHandler handler = mock( 3500 NotificationManagerService.WorkerHandler.class); 3501 mService.setHandler(handler); 3502 3503 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3504 mService.addNotification(r); 3505 3506 mService.handleRankingSort(); 3507 verify(handler, never()).scheduleSendRankingUpdate(); 3508 } 3509 3510 @Test testReadPolicyXml_readApprovedServicesFromXml()3511 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception { 3512 final String upgradeXml = "<notification-policy version=\"1\">" 3513 + "<ranking></ranking>" 3514 + "<enabled_listeners>" 3515 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 3516 + "</enabled_listeners>" 3517 + "<enabled_assistants>" 3518 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 3519 + "</enabled_assistants>" 3520 + "<dnd_apps>" 3521 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 3522 + "</dnd_apps>" 3523 + "</notification-policy>"; 3524 mService.readPolicyXml( 3525 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())), 3526 false, 3527 UserHandle.USER_ALL); 3528 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 3529 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 3530 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 3531 3532 // numbers are inflated for setup 3533 verify(mListeners, times(1)).migrateToXml(); 3534 verify(mConditionProviders, times(1)).migrateToXml(); 3535 verify(mAssistants, times(1)).migrateToXml(); 3536 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary(); 3537 } 3538 3539 @Test testReadPolicyXml_readSnoozedNotificationsFromXml()3540 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception { 3541 final String upgradeXml = "<notification-policy version=\"1\">" 3542 + "<snoozed-notifications>></snoozed-notifications>" 3543 + "</notification-policy>"; 3544 mService.readPolicyXml( 3545 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())), 3546 false, 3547 UserHandle.USER_ALL); 3548 verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class), anyLong()); 3549 } 3550 3551 @Test testReadPolicyXml_readApprovedServicesFromSettings()3552 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception { 3553 final String preupgradeXml = "<notification-policy version=\"1\">" 3554 + "<ranking></ranking>" 3555 + "</notification-policy>"; 3556 mService.readPolicyXml( 3557 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), 3558 false, 3559 UserHandle.USER_ALL); 3560 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt()); 3561 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt()); 3562 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt()); 3563 3564 // numbers are inflated for setup 3565 verify(mListeners, times(2)).migrateToXml(); 3566 verify(mConditionProviders, times(2)).migrateToXml(); 3567 verify(mAssistants, times(2)).migrateToXml(); 3568 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary(); 3569 } 3570 3571 @Test testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser()3572 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception { 3573 final String policyXml = "<notification-policy version=\"1\">" 3574 + "<ranking></ranking>" 3575 + "<enabled_listeners>" 3576 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 3577 + "</enabled_listeners>" 3578 + "<enabled_assistants>" 3579 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 3580 + "</enabled_assistants>" 3581 + "<dnd_apps>" 3582 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 3583 + "</dnd_apps>" 3584 + "</notification-policy>"; 3585 when(mUm.isManagedProfile(10)).thenReturn(true); 3586 mService.readPolicyXml( 3587 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())), 3588 true, 3589 10); 3590 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10)); 3591 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10)); 3592 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10)); 3593 } 3594 3595 @Test testReadPolicyXml_restoresManagedServicesForNonManagedUser()3596 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception { 3597 final String policyXml = "<notification-policy version=\"1\">" 3598 + "<ranking></ranking>" 3599 + "<enabled_listeners>" 3600 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 3601 + "</enabled_listeners>" 3602 + "<enabled_assistants>" 3603 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 3604 + "</enabled_assistants>" 3605 + "<dnd_apps>" 3606 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 3607 + "</dnd_apps>" 3608 + "</notification-policy>"; 3609 when(mUm.isManagedProfile(10)).thenReturn(false); 3610 mService.readPolicyXml( 3611 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())), 3612 true, 3613 10); 3614 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10)); 3615 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10)); 3616 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10)); 3617 } 3618 3619 @Test testLocaleChangedCallsUpdateDefaultZenModeRules()3620 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception { 3621 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 3622 mService.mZenModeHelper = mZenModeHelper; 3623 mService.mLocaleChangeReceiver.onReceive(mContext, 3624 new Intent(Intent.ACTION_LOCALE_CHANGED)); 3625 3626 verify(mZenModeHelper, times(1)).updateDefaultZenRules(); 3627 } 3628 3629 @Test testBumpFGImportance_noChannelChangePreOApp()3630 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception { 3631 String preOPkg = PKG_N_MR1; 3632 final ApplicationInfo legacy = new ApplicationInfo(); 3633 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 3634 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt())) 3635 .thenReturn(legacy); 3636 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt())) 3637 .thenReturn(Binder.getCallingUid()); 3638 getContext().setMockPackageManager(mPackageManagerClient); 3639 3640 Notification.Builder nb = new Notification.Builder(mContext, 3641 NotificationChannel.DEFAULT_CHANNEL_ID) 3642 .setContentTitle("foo") 3643 .setSmallIcon(android.R.drawable.sym_def_app_icon) 3644 .setFlag(FLAG_FOREGROUND_SERVICE, true) 3645 .setPriority(Notification.PRIORITY_MIN); 3646 3647 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, 3648 "testBumpFGImportance_noChannelChangePreOApp", 3649 Binder.getCallingUid(), 0, nb.build(), 3650 UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0); 3651 3652 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(), 3653 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId()); 3654 waitForIdle(); 3655 3656 assertEquals(IMPORTANCE_LOW, 3657 mService.getNotificationRecord(sbn.getKey()).getImportance()); 3658 3659 nb = new Notification.Builder(mContext) 3660 .setContentTitle("foo") 3661 .setSmallIcon(android.R.drawable.sym_def_app_icon) 3662 .setFlag(FLAG_FOREGROUND_SERVICE, true) 3663 .setPriority(Notification.PRIORITY_MIN); 3664 3665 sbn = new StatusBarNotification(preOPkg, preOPkg, 9, 3666 "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(), 3667 0, nb.build(), UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0); 3668 3669 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, 3670 "testBumpFGImportance_noChannelChangePreOApp", 3671 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 3672 waitForIdle(); 3673 assertEquals(IMPORTANCE_LOW, 3674 mService.getNotificationRecord(sbn.getKey()).getImportance()); 3675 3676 NotificationChannel defaultChannel = mBinderService.getNotificationChannel( 3677 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID); 3678 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance()); 3679 } 3680 3681 @Test testStats_updatedOnDirectReply()3682 public void testStats_updatedOnDirectReply() throws Exception { 3683 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3684 mService.addNotification(r); 3685 3686 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey()); 3687 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied()); 3688 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.getSbn())); 3689 3690 assertEquals(1, mNotificationRecordLogger.numCalls()); 3691 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DIRECT_REPLIED, 3692 mNotificationRecordLogger.event(0)); 3693 } 3694 3695 @Test testStats_updatedOnUserExpansion()3696 public void testStats_updatedOnUserExpansion() throws Exception { 3697 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3698 mService.addNotification(r); 3699 3700 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true, 3701 NOTIFICATION_LOCATION_UNKNOWN); 3702 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true), 3703 eq((true))); 3704 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 3705 3706 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false, 3707 NOTIFICATION_LOCATION_UNKNOWN); 3708 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true), 3709 eq((false))); 3710 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 3711 3712 assertEquals(2, mNotificationRecordLogger.numCalls()); 3713 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_OPEN_USER, 3714 mNotificationRecordLogger.event(0)); 3715 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_CLOSE_USER, 3716 mNotificationRecordLogger.event(1)); 3717 } 3718 3719 @Test testStats_notUpdatedOnAutoExpansion()3720 public void testStats_notUpdatedOnAutoExpansion() throws Exception { 3721 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3722 mService.addNotification(r); 3723 3724 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 3725 NOTIFICATION_LOCATION_UNKNOWN); 3726 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 3727 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(false), 3728 eq((true))); 3729 3730 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false, 3731 NOTIFICATION_LOCATION_UNKNOWN); 3732 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 3733 verify(mAssistants).notifyAssistantExpansionChangedLocked( 3734 eq(r.getSbn()), eq(false), eq((false))); 3735 } 3736 3737 @Test testStats_updatedOnViewSettings()3738 public void testStats_updatedOnViewSettings() throws Exception { 3739 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3740 mService.addNotification(r); 3741 3742 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey()); 3743 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings()); 3744 } 3745 3746 @Test testStats_updatedOnVisibilityChanged()3747 public void testStats_updatedOnVisibilityChanged() throws Exception { 3748 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3749 mService.addNotification(r); 3750 3751 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true); 3752 mService.mNotificationDelegate.onNotificationVisibilityChanged( 3753 new NotificationVisibility[] {nv}, new NotificationVisibility[]{}); 3754 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(true)); 3755 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen()); 3756 mService.mNotificationDelegate.onNotificationVisibilityChanged( 3757 new NotificationVisibility[] {}, new NotificationVisibility[]{nv}); 3758 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(false)); 3759 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen()); 3760 } 3761 3762 @Test testStats_dismissalSurface()3763 public void testStats_dismissalSurface() throws Exception { 3764 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3765 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 3766 mService.addNotification(r); 3767 3768 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true); 3769 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(), 3770 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD, 3771 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv); 3772 waitForIdle(); 3773 3774 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface()); 3775 3776 // Using mService.addNotification() does not generate a NotificationRecordLogger log, 3777 // so we only get the cancel notification. 3778 assertEquals(1, mNotificationRecordLogger.numCalls()); 3779 3780 assertEquals( 3781 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD, 3782 mNotificationRecordLogger.event(0)); 3783 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 3784 } 3785 3786 @Test testStats_dismissalSentiment()3787 public void testStats_dismissalSentiment() throws Exception { 3788 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3789 mService.addNotification(r); 3790 3791 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true); 3792 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(), 3793 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD, 3794 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv); 3795 waitForIdle(); 3796 3797 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE, 3798 r.getStats().getDismissalSentiment()); 3799 } 3800 3801 @Test testApplyAdjustmentMultiUser()3802 public void testApplyAdjustmentMultiUser() throws Exception { 3803 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3804 mService.addNotification(r); 3805 NotificationManagerService.WorkerHandler handler = mock( 3806 NotificationManagerService.WorkerHandler.class); 3807 mService.setHandler(handler); 3808 3809 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false); 3810 3811 Bundle signals = new Bundle(); 3812 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3813 USER_SENTIMENT_NEGATIVE); 3814 Adjustment adjustment = new Adjustment( 3815 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3816 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 3817 3818 waitForIdle(); 3819 3820 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 3821 } 3822 3823 @Test testAssistantBlockingTriggersCancel()3824 public void testAssistantBlockingTriggersCancel() throws Exception { 3825 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3826 mService.addNotification(r); 3827 NotificationManagerService.WorkerHandler handler = mock( 3828 NotificationManagerService.WorkerHandler.class); 3829 mService.setHandler(handler); 3830 3831 Bundle signals = new Bundle(); 3832 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE); 3833 Adjustment adjustment = new Adjustment( 3834 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3835 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 3836 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 3837 3838 waitForIdle(); 3839 3840 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 3841 verify(handler, times(1)).scheduleCancelNotification(any()); 3842 } 3843 3844 @Test testApplyEnqueuedAdjustmentFromAssistant_singleUser()3845 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception { 3846 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3847 mService.addEnqueuedNotification(r); 3848 NotificationManagerService.WorkerHandler handler = mock( 3849 NotificationManagerService.WorkerHandler.class); 3850 mService.setHandler(handler); 3851 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 3852 3853 Bundle signals = new Bundle(); 3854 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3855 USER_SENTIMENT_NEGATIVE); 3856 Adjustment adjustment = new Adjustment( 3857 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3858 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 3859 3860 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment()); 3861 } 3862 3863 @Test testApplyEnqueuedAdjustmentFromAssistant_importance()3864 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception { 3865 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3866 mService.addEnqueuedNotification(r); 3867 NotificationManagerService.WorkerHandler handler = mock( 3868 NotificationManagerService.WorkerHandler.class); 3869 mService.setHandler(handler); 3870 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 3871 3872 Bundle signals = new Bundle(); 3873 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW); 3874 Adjustment adjustment = new Adjustment( 3875 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3876 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 3877 3878 assertEquals(IMPORTANCE_LOW, r.getImportance()); 3879 } 3880 3881 @Test testApplyEnqueuedAdjustmentFromAssistant_crossUser()3882 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception { 3883 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3884 mService.addEnqueuedNotification(r); 3885 NotificationManagerService.WorkerHandler handler = mock( 3886 NotificationManagerService.WorkerHandler.class); 3887 mService.setHandler(handler); 3888 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false); 3889 3890 Bundle signals = new Bundle(); 3891 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3892 USER_SENTIMENT_NEGATIVE); 3893 Adjustment adjustment = new Adjustment( 3894 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3895 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 3896 3897 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment()); 3898 3899 waitForIdle(); 3900 3901 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 3902 } 3903 3904 @Test testUserSentimentChangeTriggersUpdate()3905 public void testUserSentimentChangeTriggersUpdate() throws Exception { 3906 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3907 mService.addNotification(r); 3908 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 3909 3910 Bundle signals = new Bundle(); 3911 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3912 USER_SENTIMENT_NEGATIVE); 3913 Adjustment adjustment = new Adjustment( 3914 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3915 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 3916 3917 waitForIdle(); 3918 3919 verify(mRankingHandler, timeout(300).times(1)).requestSort(); 3920 } 3921 3922 @Test testTooLateAdjustmentTriggersUpdate()3923 public void testTooLateAdjustmentTriggersUpdate() throws Exception { 3924 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3925 mService.addNotification(r); 3926 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 3927 3928 Bundle signals = new Bundle(); 3929 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3930 USER_SENTIMENT_NEGATIVE); 3931 Adjustment adjustment = new Adjustment( 3932 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3933 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 3934 3935 waitForIdle(); 3936 3937 verify(mRankingHandler, times(1)).requestSort(); 3938 } 3939 3940 @Test testEnqueuedAdjustmentAppliesAdjustments()3941 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception { 3942 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 3943 mService.addEnqueuedNotification(r); 3944 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 3945 3946 Bundle signals = new Bundle(); 3947 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 3948 USER_SENTIMENT_NEGATIVE); 3949 Adjustment adjustment = new Adjustment( 3950 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 3951 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 3952 3953 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment()); 3954 } 3955 3956 @Test testRestore()3957 public void testRestore() throws Exception { 3958 int systemChecks = mService.countSystemChecks; 3959 mBinderService.applyRestore(null, USER_SYSTEM); 3960 assertEquals(1, mService.countSystemChecks - systemChecks); 3961 } 3962 3963 @Test testBackupEmptySound()3964 public void testBackupEmptySound() throws Exception { 3965 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); 3966 channel.setSound(Uri.EMPTY, null); 3967 3968 XmlSerializer serializer = new FastXmlSerializer(); 3969 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 3970 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 3971 channel.writeXmlForBackup(serializer, getContext()); 3972 3973 XmlPullParser parser = Xml.newPullParser(); 3974 parser.setInput(new BufferedInputStream( 3975 new ByteArrayInputStream(baos.toByteArray())), null); 3976 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); 3977 restored.populateFromXmlForRestore(parser, getContext()); 3978 3979 assertNull(restored.getSound()); 3980 } 3981 3982 @Test testBackup()3983 public void testBackup() throws Exception { 3984 int systemChecks = mService.countSystemChecks; 3985 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt())) 3986 .thenReturn(new ArraySet<>()); 3987 mBinderService.getBackupPayload(1); 3988 assertEquals(1, mService.countSystemChecks - systemChecks); 3989 } 3990 3991 @Test testEmptyVibration_noException()3992 public void testEmptyVibration_noException() throws Exception { 3993 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); 3994 channel.setVibrationPattern(new long[0]); 3995 3996 XmlSerializer serializer = new FastXmlSerializer(); 3997 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 3998 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 3999 channel.writeXml(serializer); 4000 } 4001 4002 @Test updateUriPermissions_update()4003 public void updateUriPermissions_update() throws Exception { 4004 NotificationChannel c = new NotificationChannel( 4005 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 4006 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT); 4007 Message message1 = new Message("", 0, ""); 4008 message1.setData("", 4009 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1)); 4010 Message message2 = new Message("", 1, ""); 4011 message2.setData("", 4012 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2)); 4013 4014 Notification.Builder nbA = new Notification.Builder(mContext, c.getId()) 4015 .setContentTitle("foo") 4016 .setSmallIcon(android.R.drawable.sym_def_app_icon) 4017 .setStyle(new Notification.MessagingStyle("") 4018 .addMessage(message1) 4019 .addMessage(message2)); 4020 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification( 4021 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid), 4022 null, 0), c); 4023 4024 // First post means we grant access to both 4025 reset(mUgm); 4026 reset(mUgmInternal); 4027 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder()); 4028 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), 4029 USER_SYSTEM); 4030 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 4031 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt()); 4032 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 4033 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt()); 4034 4035 Notification.Builder nbB = new Notification.Builder(mContext, c.getId()) 4036 .setContentTitle("foo") 4037 .setSmallIcon(android.R.drawable.sym_def_app_icon) 4038 .setStyle(new Notification.MessagingStyle("").addMessage(message2)); 4039 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG, 4040 PKG, 0, "tag", mUid, 0, nbB.build(), UserHandle.getUserHandleForUid(mUid), null, 0), 4041 c); 4042 4043 // Update means we drop access to first 4044 reset(mUgmInternal); 4045 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(), 4046 USER_SYSTEM); 4047 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), 4048 eq(message1.getDataUri()), anyInt(), anyInt(), eq(null), eq(-1)); 4049 4050 // Update back means we grant access to first again 4051 reset(mUgm); 4052 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(), 4053 USER_SYSTEM); 4054 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 4055 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt()); 4056 4057 // And update to empty means we drop everything 4058 reset(mUgmInternal); 4059 mService.updateUriPermissions(null, recordB, mContext.getPackageName(), 4060 USER_SYSTEM); 4061 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null), 4062 anyInt(), anyInt()); 4063 } 4064 4065 @Test updateUriPermissions_posterDoesNotOwnUri()4066 public void updateUriPermissions_posterDoesNotOwnUri() throws Exception { 4067 NotificationChannel c = new NotificationChannel( 4068 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 4069 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT); 4070 Message message1 = new Message("", 0, ""); 4071 message1.setData("", 4072 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1)); 4073 4074 Notification.Builder nbA = new Notification.Builder(mContext, c.getId()) 4075 .setContentTitle("foo") 4076 .setSmallIcon(android.R.drawable.sym_def_app_icon) 4077 .setStyle(new Notification.MessagingStyle("") 4078 .addMessage(message1)); 4079 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification( 4080 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid), 4081 null, 0), c); 4082 4083 doThrow(new SecurityException("no access")).when(mUgm) 4084 .grantUriPermissionFromOwner( 4085 any(), anyInt(), any(), any(), anyInt(), anyInt(), anyInt()); 4086 4087 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder()); 4088 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), USER_SYSTEM); 4089 4090 // yay, no crash 4091 } 4092 4093 @Test testVisitUris()4094 public void testVisitUris() throws Exception { 4095 final Uri audioContents = Uri.parse("content://com.example/audio"); 4096 final Uri backgroundImage = Uri.parse("content://com.example/background"); 4097 4098 Bundle extras = new Bundle(); 4099 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents); 4100 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString()); 4101 4102 Notification n = new Notification.Builder(mContext, "a") 4103 .setContentTitle("notification with uris") 4104 .setSmallIcon(android.R.drawable.sym_def_app_icon) 4105 .addExtras(extras) 4106 .build(); 4107 4108 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 4109 n.visitUris(visitor); 4110 verify(visitor, times(1)).accept(eq(audioContents)); 4111 verify(visitor, times(1)).accept(eq(backgroundImage)); 4112 } 4113 4114 @Test testSetNotificationPolicy_preP_setOldFields()4115 public void testSetNotificationPolicy_preP_setOldFields() { 4116 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 4117 mService.mZenModeHelper = mZenModeHelper; 4118 NotificationManager.Policy userPolicy = 4119 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 4120 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 4121 4122 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 4123 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 4124 4125 int expected = SUPPRESSED_EFFECT_BADGE 4126 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 4127 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS 4128 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 4129 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 4130 4131 assertEquals(expected, actual); 4132 } 4133 4134 @Test testSetNotificationPolicy_preP_setNewFields()4135 public void testSetNotificationPolicy_preP_setNewFields() { 4136 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 4137 mService.mZenModeHelper = mZenModeHelper; 4138 NotificationManager.Policy userPolicy = 4139 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 4140 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 4141 4142 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 4143 SUPPRESSED_EFFECT_NOTIFICATION_LIST); 4144 4145 int expected = SUPPRESSED_EFFECT_BADGE; 4146 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 4147 4148 assertEquals(expected, actual); 4149 } 4150 4151 @Test testSetNotificationPolicy_preP_setOldNewFields()4152 public void testSetNotificationPolicy_preP_setOldNewFields() { 4153 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 4154 mService.mZenModeHelper = mZenModeHelper; 4155 NotificationManager.Policy userPolicy = 4156 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 4157 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 4158 4159 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 4160 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 4161 4162 int expected = 4163 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK; 4164 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 4165 4166 assertEquals(expected, actual); 4167 } 4168 4169 @Test testSetNotificationPolicy_P_setOldFields()4170 public void testSetNotificationPolicy_P_setOldFields() { 4171 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 4172 mService.mZenModeHelper = mZenModeHelper; 4173 NotificationManager.Policy userPolicy = 4174 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 4175 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 4176 4177 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 4178 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 4179 4180 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 4181 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT 4182 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 4183 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 4184 4185 assertEquals(expected, actual); 4186 } 4187 4188 @Test testSetNotificationPolicy_P_setNewFields()4189 public void testSetNotificationPolicy_P_setNewFields() { 4190 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 4191 mService.mZenModeHelper = mZenModeHelper; 4192 NotificationManager.Policy userPolicy = 4193 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 4194 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 4195 4196 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 4197 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT 4198 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 4199 4200 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF 4201 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS 4202 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 4203 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 4204 4205 assertEquals(expected, actual); 4206 } 4207 4208 @Test testSetNotificationPolicy_P_setOldNewFields()4209 public void testSetNotificationPolicy_P_setOldNewFields() { 4210 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 4211 mService.mZenModeHelper = mZenModeHelper; 4212 NotificationManager.Policy userPolicy = 4213 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 4214 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 4215 4216 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 4217 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 4218 4219 int expected = SUPPRESSED_EFFECT_STATUS_BAR; 4220 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 4221 4222 assertEquals(expected, actual); 4223 4224 appPolicy = new NotificationManager.Policy(0, 0, 0, 4225 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT 4226 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 4227 4228 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT 4229 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 4230 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 4231 4232 assertEquals(expected, actual); 4233 } 4234 4235 @Test testVisualDifference_foreground()4236 public void testVisualDifference_foreground() { 4237 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4238 .setContentTitle("foo"); 4239 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4240 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4241 NotificationRecord r1 = 4242 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4243 4244 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4245 .setFlag(FLAG_FOREGROUND_SERVICE, true) 4246 .setContentTitle("bar"); 4247 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4248 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4249 NotificationRecord r2 = 4250 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4251 4252 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 4253 } 4254 4255 @Test testVisualDifference_diffTitle()4256 public void testVisualDifference_diffTitle() { 4257 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4258 .setContentTitle("foo"); 4259 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4260 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4261 NotificationRecord r1 = 4262 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4263 4264 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4265 .setContentTitle("bar"); 4266 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4267 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4268 NotificationRecord r2 = 4269 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4270 4271 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 4272 } 4273 4274 @Test testVisualDifference_inboxStyle()4275 public void testVisualDifference_inboxStyle() { 4276 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4277 .setStyle(new Notification.InboxStyle() 4278 .addLine("line1").addLine("line2")); 4279 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4280 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4281 NotificationRecord r1 = 4282 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4283 4284 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4285 .setStyle(new Notification.InboxStyle() 4286 .addLine("line1").addLine("line2_changed")); 4287 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4288 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4289 NotificationRecord r2 = 4290 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4291 4292 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed 4293 4294 Notification.Builder nb3 = new Notification.Builder(mContext, "") 4295 .setStyle(new Notification.InboxStyle() 4296 .addLine("line1")); 4297 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4298 nb3.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4299 NotificationRecord r3 = 4300 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class)); 4301 4302 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed 4303 4304 Notification.Builder nb4 = new Notification.Builder(mContext, "") 4305 .setStyle(new Notification.InboxStyle() 4306 .addLine("line1").addLine("line2").addLine("line3")); 4307 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4308 nb4.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4309 NotificationRecord r4 = 4310 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class)); 4311 4312 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed 4313 4314 Notification.Builder nb5 = new Notification.Builder(mContext, "") 4315 .setContentText("not an inbox"); 4316 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4317 nb5.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4318 NotificationRecord r5 = 4319 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class)); 4320 4321 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed 4322 } 4323 4324 @Test testVisualDifference_diffText()4325 public void testVisualDifference_diffText() { 4326 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4327 .setContentText("foo"); 4328 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4329 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4330 NotificationRecord r1 = 4331 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4332 4333 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4334 .setContentText("bar"); 4335 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4336 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4337 NotificationRecord r2 = 4338 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4339 4340 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 4341 } 4342 4343 @Test testVisualDifference_sameText()4344 public void testVisualDifference_sameText() { 4345 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4346 .setContentText("foo"); 4347 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4348 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4349 NotificationRecord r1 = 4350 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4351 4352 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4353 .setContentText("foo"); 4354 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4355 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4356 NotificationRecord r2 = 4357 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4358 4359 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 4360 } 4361 4362 @Test testVisualDifference_sameTextButStyled()4363 public void testVisualDifference_sameTextButStyled() { 4364 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4365 .setContentText(Html.fromHtml("<b>foo</b>")); 4366 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4367 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4368 NotificationRecord r1 = 4369 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4370 4371 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4372 .setContentText(Html.fromHtml("<b>foo</b>")); 4373 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4374 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4375 NotificationRecord r2 = 4376 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4377 4378 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 4379 } 4380 4381 @Test testVisualDifference_diffTextButStyled()4382 public void testVisualDifference_diffTextButStyled() { 4383 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4384 .setContentText(Html.fromHtml("<b>foo</b>")); 4385 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4386 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4387 NotificationRecord r1 = 4388 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4389 4390 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4391 .setContentText(Html.fromHtml("<b>bar</b>")); 4392 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4393 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4394 NotificationRecord r2 = 4395 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4396 4397 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 4398 } 4399 4400 @Test testVisualDifference_diffProgress()4401 public void testVisualDifference_diffProgress() { 4402 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4403 .setProgress(100, 90, false); 4404 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4405 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4406 NotificationRecord r1 = 4407 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4408 4409 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4410 .setProgress(100, 100, false); 4411 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4412 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4413 NotificationRecord r2 = 4414 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4415 4416 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 4417 } 4418 4419 @Test testVisualDifference_diffProgressNotDone()4420 public void testVisualDifference_diffProgressNotDone() { 4421 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4422 .setProgress(100, 90, false); 4423 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4424 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4425 NotificationRecord r1 = 4426 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4427 4428 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4429 .setProgress(100, 91, false); 4430 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4431 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4432 NotificationRecord r2 = 4433 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4434 4435 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 4436 } 4437 4438 @Test testVisualDifference_sameProgressStillDone()4439 public void testVisualDifference_sameProgressStillDone() { 4440 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4441 .setProgress(100, 100, false); 4442 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4443 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4444 NotificationRecord r1 = 4445 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4446 4447 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4448 .setProgress(100, 100, false); 4449 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4450 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4451 NotificationRecord r2 = 4452 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4453 4454 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 4455 } 4456 4457 @Test testVisualDifference_summary()4458 public void testVisualDifference_summary() { 4459 Notification.Builder nb1 = new Notification.Builder(mContext, "") 4460 .setGroup("bananas") 4461 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 4462 .setContentText("foo"); 4463 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4464 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4465 NotificationRecord r1 = 4466 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 4467 4468 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4469 .setGroup("bananas") 4470 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 4471 .setContentText("bar"); 4472 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4473 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4474 NotificationRecord r2 = 4475 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4476 4477 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 4478 } 4479 4480 @Test testVisualDifference_summaryNewNotification()4481 public void testVisualDifference_summaryNewNotification() { 4482 Notification.Builder nb2 = new Notification.Builder(mContext, "") 4483 .setGroup("bananas") 4484 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 4485 .setContentText("bar"); 4486 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 4487 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4488 NotificationRecord r2 = 4489 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 4490 4491 assertFalse(mService.isVisuallyInterruptive(null, r2)); 4492 } 4493 4494 @Test testHideAndUnhideNotificationsOnSuspendedPackageBroadcast()4495 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() { 4496 // post 2 notification from this package 4497 final NotificationRecord notif1 = generateNotificationRecord( 4498 mTestNotificationChannel, 1, null, true); 4499 final NotificationRecord notif2 = generateNotificationRecord( 4500 mTestNotificationChannel, 2, null, false); 4501 mService.addNotification(notif1); 4502 mService.addNotification(notif2); 4503 4504 // on broadcast, hide the 2 notifications 4505 mService.simulatePackageSuspendBroadcast(true, PKG); 4506 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class); 4507 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 4508 assertEquals(2, captorHide.getValue().size()); 4509 4510 // on broadcast, unhide the 2 notifications 4511 mService.simulatePackageSuspendBroadcast(false, PKG); 4512 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class); 4513 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 4514 assertEquals(2, captorUnhide.getValue().size()); 4515 } 4516 4517 @Test testNoNotificationsHiddenOnSuspendedPackageBroadcast()4518 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() { 4519 // post 2 notification from this package 4520 final NotificationRecord notif1 = generateNotificationRecord( 4521 mTestNotificationChannel, 1, null, true); 4522 final NotificationRecord notif2 = generateNotificationRecord( 4523 mTestNotificationChannel, 2, null, false); 4524 mService.addNotification(notif1); 4525 mService.addNotification(notif2); 4526 4527 // on broadcast, nothing is hidden since no notifications are of package "test_package" 4528 mService.simulatePackageSuspendBroadcast(true, "test_package"); 4529 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 4530 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 4531 assertEquals(0, captor.getValue().size()); 4532 } 4533 4534 @Test testHideAndUnhideNotificationsOnDistractingPackageBroadcast()4535 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() { 4536 // Post 2 notifications from 2 packages 4537 NotificationRecord pkgA = new NotificationRecord(mContext, 4538 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 4539 mService.addNotification(pkgA); 4540 NotificationRecord pkgB = new NotificationRecord(mContext, 4541 generateSbn("b", 1001, 9, 0), mTestNotificationChannel); 4542 mService.addNotification(pkgB); 4543 4544 // on broadcast, hide one of the packages 4545 mService.simulatePackageDistractionBroadcast( 4546 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"}); 4547 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class); 4548 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 4549 assertEquals(1, captorHide.getValue().size()); 4550 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName()); 4551 4552 // on broadcast, unhide the package 4553 mService.simulatePackageDistractionBroadcast( 4554 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"}); 4555 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class); 4556 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 4557 assertEquals(1, captorUnhide.getValue().size()); 4558 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName()); 4559 } 4560 4561 @Test testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg()4562 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() { 4563 // Post 2 notifications from 2 packages 4564 NotificationRecord pkgA = new NotificationRecord(mContext, 4565 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 4566 mService.addNotification(pkgA); 4567 NotificationRecord pkgB = new NotificationRecord(mContext, 4568 generateSbn("b", 1001, 9, 0), mTestNotificationChannel); 4569 mService.addNotification(pkgB); 4570 4571 // on broadcast, hide one of the packages 4572 mService.simulatePackageDistractionBroadcast( 4573 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"}); 4574 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class); 4575 4576 // should be called only once. 4577 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 4578 assertEquals(2, captorHide.getValue().size()); 4579 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName()); 4580 assertEquals("b", captorHide.getValue().get(1).getSbn().getPackageName()); 4581 4582 // on broadcast, unhide the package 4583 mService.simulatePackageDistractionBroadcast( 4584 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"}); 4585 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class); 4586 4587 // should be called only once. 4588 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 4589 assertEquals(2, captorUnhide.getValue().size()); 4590 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName()); 4591 assertEquals("b", captorUnhide.getValue().get(1).getSbn().getPackageName()); 4592 } 4593 4594 @Test testNoNotificationsHiddenOnDistractingPackageBroadcast()4595 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() { 4596 // post notification from this package 4597 final NotificationRecord notif1 = generateNotificationRecord( 4598 mTestNotificationChannel, 1, null, true); 4599 mService.addNotification(notif1); 4600 4601 // on broadcast, nothing is hidden since no notifications are of package "test_package" 4602 mService.simulatePackageDistractionBroadcast( 4603 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"}); 4604 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 4605 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 4606 assertEquals(0, captor.getValue().size()); 4607 } 4608 4609 @Test testCanUseManagedServicesNullPkg()4610 public void testCanUseManagedServicesNullPkg() { 4611 assertEquals(true, mService.canUseManagedServices(null, 0, null)); 4612 } 4613 4614 4615 @Test testCanUseManagedServicesNoValidPkg()4616 public void testCanUseManagedServicesNoValidPkg() { 4617 assertEquals(true, mService.canUseManagedServices("d", 0, null)); 4618 } 4619 4620 @Test testCanUseManagedServices_hasPermission()4621 public void testCanUseManagedServices_hasPermission() throws Exception { 4622 when(mPackageManager.checkPermission("perm", "pkg", 0)) 4623 .thenReturn(PackageManager.PERMISSION_GRANTED); 4624 4625 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm")); 4626 } 4627 4628 @Test testCanUseManagedServices_noPermission()4629 public void testCanUseManagedServices_noPermission() throws Exception { 4630 when(mPackageManager.checkPermission("perm", "pkg", 0)) 4631 .thenReturn(PackageManager.PERMISSION_DENIED); 4632 4633 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm")); 4634 } 4635 4636 @Test testCanUseManagedServices_permDoesNotMatter()4637 public void testCanUseManagedServices_permDoesNotMatter() { 4638 assertEquals(true, mService.canUseManagedServices("pkg", 0, null)); 4639 } 4640 4641 @Test testOnNotificationVisibilityChanged_triggersInterruptionUsageStat()4642 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() { 4643 final NotificationRecord r = generateNotificationRecord( 4644 mTestNotificationChannel, 1, null, true); 4645 r.setTextChanged(true); 4646 mService.addNotification(r); 4647 4648 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[] 4649 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}, 4650 new NotificationVisibility[]{}); 4651 4652 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt()); 4653 } 4654 4655 @Test testOnNotificationVisibilityChanged_triggersVisibilityLog()4656 public void testOnNotificationVisibilityChanged_triggersVisibilityLog() { 4657 final NotificationRecord r = generateNotificationRecord( 4658 mTestNotificationChannel, 1, null, true); 4659 r.setTextChanged(true); 4660 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 4661 mService.addNotification(r); 4662 4663 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[] 4664 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}, 4665 new NotificationVisibility[]{}); 4666 4667 assertEquals(1, mNotificationRecordLogger.numCalls()); 4668 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN, 4669 mNotificationRecordLogger.event(0)); 4670 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 4671 4672 mService.mNotificationDelegate.onNotificationVisibilityChanged( 4673 new NotificationVisibility[]{}, 4674 new NotificationVisibility[] 4675 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)} 4676 ); 4677 4678 assertEquals(2, mNotificationRecordLogger.numCalls()); 4679 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE, 4680 mNotificationRecordLogger.event(1)); 4681 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); 4682 } 4683 4684 @Test testSetNotificationsShownFromListener_triggersInterruptionUsageStat()4685 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat() 4686 throws RemoteException { 4687 final NotificationRecord r = generateNotificationRecord( 4688 mTestNotificationChannel, 1, null, true); 4689 r.setTextChanged(true); 4690 mService.addNotification(r); 4691 4692 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()}); 4693 4694 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt()); 4695 } 4696 4697 @Test testMaybeRecordInterruptionLocked_doesNotRecordTwice()4698 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice() 4699 throws RemoteException { 4700 final NotificationRecord r = generateNotificationRecord( 4701 mTestNotificationChannel, 1, null, true); 4702 r.setInterruptive(true); 4703 mService.addNotification(r); 4704 4705 mService.maybeRecordInterruptionLocked(r); 4706 mService.maybeRecordInterruptionLocked(r); 4707 4708 verify(mAppUsageStats, times(1)).reportInterruptiveNotification( 4709 anyString(), anyString(), anyInt()); 4710 verify(mHistoryManager, times(1)).addNotification(any()); 4711 } 4712 4713 @Test testBubble()4714 public void testBubble() throws Exception { 4715 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE); 4716 assertFalse(mBinderService.areBubblesAllowed(PKG)); 4717 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid), 4718 BUBBLE_PREFERENCE_NONE); 4719 } 4720 4721 @Test testUserApprovedBubblesForPackageSelected()4722 public void testUserApprovedBubblesForPackageSelected() throws Exception { 4723 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_SELECTED); 4724 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid), 4725 BUBBLE_PREFERENCE_SELECTED); 4726 } 4727 4728 @Test testUserApprovedBubblesForPackageAll()4729 public void testUserApprovedBubblesForPackageAll() throws Exception { 4730 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_ALL); 4731 assertTrue(mBinderService.areBubblesAllowed(PKG)); 4732 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid), 4733 BUBBLE_PREFERENCE_ALL); 4734 } 4735 4736 @Test testUserRejectsBubblesForPackage()4737 public void testUserRejectsBubblesForPackage() throws Exception { 4738 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE); 4739 assertFalse(mBinderService.areBubblesAllowed(PKG)); 4740 } 4741 4742 @Test testIsCallerInstantApp_primaryUser()4743 public void testIsCallerInstantApp_primaryUser() throws Exception { 4744 ApplicationInfo info = new ApplicationInfo(); 4745 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 4746 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info); 4747 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 4748 4749 assertTrue(mService.isCallerInstantApp(45770, 0)); 4750 4751 info.privateFlags = 0; 4752 assertFalse(mService.isCallerInstantApp(575370, 0)); 4753 } 4754 4755 @Test testIsCallerInstantApp_secondaryUser()4756 public void testIsCallerInstantApp_secondaryUser() throws Exception { 4757 ApplicationInfo info = new ApplicationInfo(); 4758 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 4759 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info); 4760 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null); 4761 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 4762 4763 assertTrue(mService.isCallerInstantApp(68638450, 10)); 4764 } 4765 4766 @Test testIsCallerInstantApp_userAllNotification()4767 public void testIsCallerInstantApp_userAllNotification() throws Exception { 4768 ApplicationInfo info = new ApplicationInfo(); 4769 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 4770 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM))) 4771 .thenReturn(info); 4772 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 4773 4774 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL)); 4775 4776 info.privateFlags = 0; 4777 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL )); 4778 } 4779 4780 @Test testResolveNotificationUid_sameApp_nonSystemUser()4781 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception { 4782 ApplicationInfo info = new ApplicationInfo(); 4783 info.uid = Binder.getCallingUid(); 4784 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info); 4785 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null); 4786 4787 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10); 4788 4789 assertEquals(info.uid, actualUid); 4790 } 4791 4792 @Test testResolveNotificationUid_sameApp()4793 public void testResolveNotificationUid_sameApp() throws Exception { 4794 ApplicationInfo info = new ApplicationInfo(); 4795 info.uid = Binder.getCallingUid(); 4796 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info); 4797 4798 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0); 4799 4800 assertEquals(info.uid, actualUid); 4801 } 4802 4803 @Test testResolveNotificationUid_sameAppDiffPackage()4804 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception { 4805 ApplicationInfo info = new ApplicationInfo(); 4806 info.uid = Binder.getCallingUid(); 4807 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info); 4808 4809 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0); 4810 4811 assertEquals(info.uid, actualUid); 4812 } 4813 4814 @Test testResolveNotificationUid_sameAppWrongUid()4815 public void testResolveNotificationUid_sameAppWrongUid() throws Exception { 4816 ApplicationInfo info = new ApplicationInfo(); 4817 info.uid = 1356347; 4818 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info); 4819 4820 try { 4821 mService.resolveNotificationUid("caller", "caller", 9, 0); 4822 fail("Incorrect uid didn't throw security exception"); 4823 } catch (SecurityException e) { 4824 // yay 4825 } 4826 } 4827 4828 @Test testResolveNotificationUid_delegateAllowed()4829 public void testResolveNotificationUid_delegateAllowed() throws Exception { 4830 int expectedUid = 123; 4831 4832 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid); 4833 mService.setPreferencesHelper(mPreferencesHelper); 4834 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt())) 4835 .thenReturn(true); 4836 4837 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0)); 4838 } 4839 4840 @Test testResolveNotificationUid_androidAllowed()4841 public void testResolveNotificationUid_androidAllowed() throws Exception { 4842 int expectedUid = 123; 4843 4844 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid); 4845 // no delegate 4846 4847 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0)); 4848 } 4849 4850 @Test testPostFromAndroidForNonExistentPackage()4851 public void testPostFromAndroidForNonExistentPackage() throws Exception { 4852 final String notReal = "NOT REAL"; 4853 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow( 4854 PackageManager.NameNotFoundException.class); 4855 ApplicationInfo ai = new ApplicationInfo(); 4856 ai.uid = -1; 4857 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai); 4858 4859 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 4860 try { 4861 mInternalService.enqueueNotification(notReal, "android", 0, 0, 4862 "testPostFromAndroidForNonExistentPackage", 4863 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 4864 fail("can't post notifications for nonexistent packages, even if you exist"); 4865 } catch (SecurityException e) { 4866 // yay 4867 } 4868 } 4869 4870 @Test testCancelFromAndroidForNonExistentPackage()4871 public void testCancelFromAndroidForNonExistentPackage() throws Exception { 4872 final String notReal = "NOT REAL"; 4873 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow( 4874 PackageManager.NameNotFoundException.class); 4875 ApplicationInfo ai = new ApplicationInfo(); 4876 ai.uid = -1; 4877 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai); 4878 4879 // unlike the post case, ignore instead of throwing 4880 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 4881 4882 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag", 4883 sbn.getId(), sbn.getUserId()); 4884 } 4885 4886 @Test testResolveNotificationUid_delegateNotAllowed()4887 public void testResolveNotificationUid_delegateNotAllowed() throws Exception { 4888 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123); 4889 // no delegate 4890 4891 try { 4892 mService.resolveNotificationUid("caller", "target", 9, 0); 4893 fail("Incorrect uid didn't throw security exception"); 4894 } catch (SecurityException e) { 4895 // yay 4896 } 4897 } 4898 4899 @Test testRemoveForegroundServiceFlagFromNotification_enqueued()4900 public void testRemoveForegroundServiceFlagFromNotification_enqueued() { 4901 Notification n = new Notification.Builder(mContext, "").build(); 4902 n.flags |= FLAG_FOREGROUND_SERVICE; 4903 4904 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 4905 n, UserHandle.getUserHandleForUid(mUid), null, 0); 4906 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4907 4908 mService.addEnqueuedNotification(r); 4909 4910 mInternalService.removeForegroundServiceFlagFromNotification( 4911 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 4912 4913 waitForIdle(); 4914 4915 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any()); 4916 } 4917 4918 @Test testRemoveForegroundServiceFlagFromNotification_posted()4919 public void testRemoveForegroundServiceFlagFromNotification_posted() { 4920 Notification n = new Notification.Builder(mContext, "").build(); 4921 n.flags |= FLAG_FOREGROUND_SERVICE; 4922 4923 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 4924 n, UserHandle.getUserHandleForUid(mUid), null, 0); 4925 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4926 4927 mService.addNotification(r); 4928 4929 mInternalService.removeForegroundServiceFlagFromNotification( 4930 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 4931 4932 waitForIdle(); 4933 4934 ArgumentCaptor<NotificationRecord> captor = 4935 ArgumentCaptor.forClass(NotificationRecord.class); 4936 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any()); 4937 4938 assertEquals(0, captor.getValue().getNotification().flags); 4939 } 4940 4941 @Test testAllowForegroundCustomToasts()4942 public void testAllowForegroundCustomToasts() throws Exception { 4943 final String testPackage = "testPackageName"; 4944 assertEquals(0, mService.mToastQueue.size()); 4945 mService.isSystemUid = false; 4946 4947 // package is not suspended 4948 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 4949 .thenReturn(false); 4950 4951 // notifications from this package are blocked by the user 4952 mService.setPreferencesHelper(mPreferencesHelper); 4953 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); 4954 4955 setAppInForegroundForToasts(mUid, true); 4956 4957 // enqueue toast -> toast should still enqueue 4958 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), 4959 new TestableToastCallback(), 2000, 0); 4960 assertEquals(1, mService.mToastQueue.size()); 4961 } 4962 4963 @Test testDisallowBackgroundCustomToasts()4964 public void testDisallowBackgroundCustomToasts() throws Exception { 4965 final String testPackage = "testPackageName"; 4966 assertEquals(0, mService.mToastQueue.size()); 4967 mService.isSystemUid = false; 4968 4969 // package is not suspended 4970 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 4971 .thenReturn(false); 4972 4973 setAppInForegroundForToasts(mUid, false); 4974 4975 // enqueue toast -> no toasts enqueued 4976 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), 4977 new TestableToastCallback(), 2000, 0); 4978 assertEquals(0, mService.mToastQueue.size()); 4979 } 4980 4981 @Test testAllowForegroundTextToasts()4982 public void testAllowForegroundTextToasts() throws Exception { 4983 final String testPackage = "testPackageName"; 4984 assertEquals(0, mService.mToastQueue.size()); 4985 mService.isSystemUid = false; 4986 4987 // package is not suspended 4988 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 4989 .thenReturn(false); 4990 4991 setAppInForegroundForToasts(mUid, true); 4992 4993 // enqueue toast -> toast should still enqueue 4994 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), 4995 "Text", 2000, 0, null); 4996 assertEquals(1, mService.mToastQueue.size()); 4997 } 4998 4999 @Test testAllowBackgroundTextToasts()5000 public void testAllowBackgroundTextToasts() throws Exception { 5001 final String testPackage = "testPackageName"; 5002 assertEquals(0, mService.mToastQueue.size()); 5003 mService.isSystemUid = false; 5004 5005 // package is not suspended 5006 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 5007 .thenReturn(false); 5008 5009 setAppInForegroundForToasts(mUid, false); 5010 5011 // enqueue toast -> toast should still enqueue 5012 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), 5013 "Text", 2000, 0, null); 5014 assertEquals(1, mService.mToastQueue.size()); 5015 } 5016 5017 @Test testTextToastsCallStatusBar()5018 public void testTextToastsCallStatusBar() throws Exception { 5019 final String testPackage = "testPackageName"; 5020 assertEquals(0, mService.mToastQueue.size()); 5021 mService.isSystemUid = false; 5022 5023 // package is not suspended 5024 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 5025 .thenReturn(false); 5026 5027 // enqueue toast -> no toasts enqueued 5028 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), 5029 "Text", 2000, 0, null); 5030 verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any()); 5031 } 5032 5033 @Test testDisallowToastsFromSuspendedPackages()5034 public void testDisallowToastsFromSuspendedPackages() throws Exception { 5035 final String testPackage = "testPackageName"; 5036 assertEquals(0, mService.mToastQueue.size()); 5037 mService.isSystemUid = false; 5038 5039 // package is suspended 5040 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 5041 .thenReturn(true); 5042 5043 // notifications from this package are NOT blocked by the user 5044 mService.setPreferencesHelper(mPreferencesHelper); 5045 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW); 5046 5047 // enqueue toast -> no toasts enqueued 5048 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), 5049 new TestableToastCallback(), 2000, 0); 5050 assertEquals(0, mService.mToastQueue.size()); 5051 } 5052 5053 @Test testDisallowToastsFromBlockedApps()5054 public void testDisallowToastsFromBlockedApps() throws Exception { 5055 final String testPackage = "testPackageName"; 5056 assertEquals(0, mService.mToastQueue.size()); 5057 mService.isSystemUid = false; 5058 5059 // package is not suspended 5060 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 5061 .thenReturn(false); 5062 5063 // notifications from this package are blocked by the user 5064 mService.setPreferencesHelper(mPreferencesHelper); 5065 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); 5066 5067 setAppInForegroundForToasts(mUid, false); 5068 5069 // enqueue toast -> no toasts enqueued 5070 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), 5071 new TestableToastCallback(), 2000, 0); 5072 assertEquals(0, mService.mToastQueue.size()); 5073 } 5074 5075 @Test testAlwaysAllowSystemToasts()5076 public void testAlwaysAllowSystemToasts() throws Exception { 5077 final String testPackage = "testPackageName"; 5078 assertEquals(0, mService.mToastQueue.size()); 5079 mService.isSystemUid = true; 5080 5081 // package is suspended 5082 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 5083 .thenReturn(true); 5084 5085 // notifications from this package ARE blocked by the user 5086 mService.setPreferencesHelper(mPreferencesHelper); 5087 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); 5088 5089 setAppInForegroundForToasts(mUid, false); 5090 5091 // enqueue toast -> system toast can still be enqueued 5092 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), 5093 new TestableToastCallback(), 2000, 0); 5094 assertEquals(1, mService.mToastQueue.size()); 5095 } 5096 setAppInForegroundForToasts(int uid, boolean inForeground)5097 private void setAppInForegroundForToasts(int uid, boolean inForeground) { 5098 int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE; 5099 when(mActivityManager.getUidImportance(mUid)).thenReturn(importance); 5100 when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground); 5101 } 5102 5103 @Test testOnPanelRevealedAndHidden()5104 public void testOnPanelRevealedAndHidden() { 5105 int items = 5; 5106 mService.mNotificationDelegate.onPanelRevealed(false, items); 5107 verify(mAssistants, times(1)).onPanelRevealed(eq(items)); 5108 5109 mService.mNotificationDelegate.onPanelHidden(); 5110 verify(mAssistants, times(1)).onPanelHidden(); 5111 5112 assertEquals(2, mNotificationRecordLogger.numCalls()); 5113 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_OPEN, 5114 mNotificationRecordLogger.event(0)); 5115 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_CLOSE, 5116 mNotificationRecordLogger.event(1)); 5117 } 5118 5119 @Test testOnNotificationSmartReplySent()5120 public void testOnNotificationSmartReplySent() { 5121 final int replyIndex = 2; 5122 final String reply = "Hello"; 5123 final boolean modifiedBeforeSending = true; 5124 final boolean generatedByAssistant = true; 5125 5126 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5127 r.setSuggestionsGeneratedByAssistant(generatedByAssistant); 5128 mService.addNotification(r); 5129 5130 mService.mNotificationDelegate.onNotificationSmartReplySent( 5131 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN, 5132 modifiedBeforeSending); 5133 verify(mAssistants).notifyAssistantSuggestedReplySent( 5134 eq(r.getSbn()), eq(reply), eq(generatedByAssistant)); 5135 assertEquals(1, mNotificationRecordLogger.numCalls()); 5136 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED, 5137 mNotificationRecordLogger.event(0)); 5138 } 5139 5140 @Test testOnNotificationActionClick()5141 public void testOnNotificationActionClick() { 5142 final int actionIndex = 2; 5143 final Notification.Action action = 5144 new Notification.Action.Builder(null, "text", null).build(); 5145 final boolean generatedByAssistant = false; 5146 5147 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5148 mService.addNotification(r); 5149 5150 NotificationVisibility notificationVisibility = 5151 NotificationVisibility.obtain(r.getKey(), 1, 2, true); 5152 mService.mNotificationDelegate.onNotificationActionClick( 5153 10, 10, r.getKey(), actionIndex, action, notificationVisibility, 5154 generatedByAssistant); 5155 verify(mAssistants).notifyAssistantActionClicked( 5156 eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant)); 5157 5158 assertEquals(1, mNotificationRecordLogger.numCalls()); 5159 assertEquals( 5160 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ACTION_CLICKED_2, 5161 mNotificationRecordLogger.event(0)); 5162 } 5163 5164 @Test testOnAssistantNotificationActionClick()5165 public void testOnAssistantNotificationActionClick() { 5166 final int actionIndex = 1; 5167 final Notification.Action action = 5168 new Notification.Action.Builder(null, "text", null).build(); 5169 final boolean generatedByAssistant = true; 5170 5171 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5172 mService.addNotification(r); 5173 5174 NotificationVisibility notificationVisibility = 5175 NotificationVisibility.obtain(r.getKey(), 1, 2, true); 5176 mService.mNotificationDelegate.onNotificationActionClick( 5177 10, 10, r.getKey(), actionIndex, action, notificationVisibility, 5178 generatedByAssistant); 5179 verify(mAssistants).notifyAssistantActionClicked( 5180 eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant)); 5181 5182 assertEquals(1, mNotificationRecordLogger.numCalls()); 5183 assertEquals( 5184 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ASSIST_ACTION_CLICKED_1, 5185 mNotificationRecordLogger.event(0)); 5186 } 5187 5188 @Test testLogSmartSuggestionsVisible_triggerOnExpandAndVisible()5189 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() { 5190 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5191 mService.addNotification(r); 5192 5193 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 5194 NOTIFICATION_LOCATION_UNKNOWN); 5195 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] { 5196 NotificationVisibility.obtain(r.getKey(), 0, 0, true) 5197 }; 5198 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility, 5199 new NotificationVisibility[0]); 5200 5201 assertEquals(1, mService.countLogSmartSuggestionsVisible); 5202 } 5203 5204 @Test testLogSmartSuggestionsVisible_noTriggerOnExpand()5205 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() { 5206 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5207 mService.addNotification(r); 5208 5209 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 5210 NOTIFICATION_LOCATION_UNKNOWN); 5211 5212 assertEquals(0, mService.countLogSmartSuggestionsVisible); 5213 } 5214 5215 @Test testLogSmartSuggestionsVisible_noTriggerOnVisible()5216 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() { 5217 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5218 mService.addNotification(r); 5219 5220 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{ 5221 NotificationVisibility.obtain(r.getKey(), 0, 0, true) 5222 }; 5223 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility, 5224 new NotificationVisibility[0]); 5225 5226 assertEquals(0, mService.countLogSmartSuggestionsVisible); 5227 } 5228 5229 @Test testReportSeen_delegated()5230 public void testReportSeen_delegated() { 5231 Notification.Builder nb = 5232 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 5233 .setContentTitle("foo") 5234 .setSmallIcon(android.R.drawable.sym_def_app_icon); 5235 5236 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0, 5237 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 5238 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 5239 5240 mService.reportSeen(r); 5241 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt()); 5242 5243 } 5244 5245 @Test testReportSeen_notDelegated()5246 public void testReportSeen_notDelegated() { 5247 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5248 5249 mService.reportSeen(r); 5250 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt()); 5251 } 5252 5253 @Test testNotificationStats_notificationError()5254 public void testNotificationStats_notificationError() { 5255 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5256 mService.addNotification(r); 5257 5258 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.getSbn().getId(), 5259 r.getSbn().getTag(), mUid, 0, 5260 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(), 5261 UserHandle.getUserHandleForUid(mUid), null, 0); 5262 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 5263 mService.addEnqueuedNotification(update); 5264 assertNull(update.getSbn().getNotification().getSmallIcon()); 5265 5266 NotificationManagerService.PostNotificationRunnable runnable = 5267 mService.new PostNotificationRunnable(update.getKey()); 5268 runnable.run(); 5269 waitForIdle(); 5270 5271 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 5272 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture()); 5273 assertNotNull(captor.getValue()); 5274 } 5275 5276 @Test testCanNotifyAsUser_crossUser()5277 public void testCanNotifyAsUser_crossUser() throws Exception { 5278 // same user no problem 5279 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId()); 5280 5281 // cross user, no permission, problem 5282 try { 5283 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); 5284 fail("Should not be callable cross user without cross user permission"); 5285 } catch (SecurityException e) { 5286 // good 5287 } 5288 5289 // cross user, with permission, no problem 5290 enableInteractAcrossUsers(); 5291 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); 5292 } 5293 5294 @Test testGetNotificationChannels_crossUser()5295 public void testGetNotificationChannels_crossUser() throws Exception { 5296 // same user no problem 5297 mBinderService.getNotificationChannels("src", "target", mContext.getUserId()); 5298 5299 // cross user, no permission, problem 5300 try { 5301 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); 5302 fail("Should not be callable cross user without cross user permission"); 5303 } catch (SecurityException e) { 5304 // good 5305 } 5306 5307 // cross user, with permission, no problem 5308 enableInteractAcrossUsers(); 5309 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); 5310 } 5311 5312 @Test setDefaultAssistantForUser_fromConfigXml()5313 public void setDefaultAssistantForUser_fromConfigXml() { 5314 clearDeviceConfig(); 5315 ComponentName xmlConfig = new ComponentName("config", "xml"); 5316 ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig)); 5317 when(mResources 5318 .getString( 5319 com.android.internal.R.string.config_defaultAssistantAccessComponent)) 5320 .thenReturn(xmlConfig.flattenToString()); 5321 when(mContext.getResources()).thenReturn(mResources); 5322 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt())) 5323 .thenReturn(components); 5324 when(mAssistants.getDefaultComponents()) 5325 .thenReturn(components); 5326 mService.setNotificationAssistantAccessGrantedCallback( 5327 mNotificationAssistantAccessGrantedCallback); 5328 5329 5330 mService.setDefaultAssistantForUser(0); 5331 5332 verify(mNotificationAssistantAccessGrantedCallback) 5333 .onGranted(eq(xmlConfig), eq(0), eq(true)); 5334 } 5335 5336 @Test setDefaultAssistantForUser_fromDeviceConfig()5337 public void setDefaultAssistantForUser_fromDeviceConfig() { 5338 ComponentName xmlConfig = new ComponentName("xml", "config"); 5339 ComponentName deviceConfig = new ComponentName("device", "config"); 5340 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString()); 5341 when(mResources 5342 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent)) 5343 .thenReturn(xmlConfig.flattenToString()); 5344 when(mContext.getResources()).thenReturn(mResources); 5345 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt())) 5346 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig))); 5347 when(mAssistants.getDefaultComponents()) 5348 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig))); 5349 mService.setNotificationAssistantAccessGrantedCallback( 5350 mNotificationAssistantAccessGrantedCallback); 5351 5352 mService.setDefaultAssistantForUser(0); 5353 5354 verify(mNotificationAssistantAccessGrantedCallback) 5355 .onGranted(eq(deviceConfig), eq(0), eq(true)); 5356 } 5357 5358 @Test setDefaultAssistantForUser_deviceConfigInvalid()5359 public void setDefaultAssistantForUser_deviceConfigInvalid() { 5360 ComponentName xmlConfig = new ComponentName("xml", "config"); 5361 ComponentName deviceConfig = new ComponentName("device", "config"); 5362 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString()); 5363 when(mResources 5364 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent)) 5365 .thenReturn(xmlConfig.flattenToString()); 5366 when(mContext.getResources()).thenReturn(mResources); 5367 // Only xmlConfig is valid, deviceConfig is not. 5368 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0))) 5369 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig))); 5370 when(mAssistants.getDefaultComponents()) 5371 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig))); 5372 mService.setNotificationAssistantAccessGrantedCallback( 5373 mNotificationAssistantAccessGrantedCallback); 5374 5375 mService.setDefaultAssistantForUser(0); 5376 5377 verify(mNotificationAssistantAccessGrantedCallback) 5378 .onGranted(eq(xmlConfig), eq(0), eq(true)); 5379 } 5380 5381 @Test clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne()5382 public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException { 5383 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners = 5384 generateResetComponentValues(); 5385 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners); 5386 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>(); 5387 ComponentName deviceConfig1 = new ComponentName("device", "config1"); 5388 ComponentName deviceConfig2 = new ComponentName("device", "config2"); 5389 changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2))); 5390 changes.put(false, new ArrayList()); 5391 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes); 5392 mService.getBinderService().clearData("device", 0, false); 5393 verify(mAssistants, times(1)) 5394 .setPackageOrComponentEnabled( 5395 eq("device/config2"), 5396 eq(0), eq(true), eq(false)); 5397 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 5398 eq("device"), eq(0), eq(false), eq(true)); 5399 } 5400 5401 @Test clearDefaultListenersPackageShouldEnableIt()5402 public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException { 5403 ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants = 5404 generateResetComponentValues(); 5405 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants); 5406 ComponentName deviceConfig = new ComponentName("device", "config"); 5407 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>(); 5408 changes.put(true, new ArrayList(Arrays.asList(deviceConfig))); 5409 changes.put(false, new ArrayList()); 5410 when(mListeners.resetComponents(anyString(), anyInt())) 5411 .thenReturn(changes); 5412 mService.getBinderService().clearData("device", 0, false); 5413 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 5414 eq("device"), eq(0), eq(false), eq(true)); 5415 } 5416 5417 @Test clearDefaultDnDPackageShouldEnableIt()5418 public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException { 5419 ComponentName deviceConfig = new ComponentName("device", "config"); 5420 ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues(); 5421 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed); 5422 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed); 5423 mService.getBinderService().clearData("device", 0, false); 5424 verify(mConditionProviders, times(1)).resetPackage( 5425 eq("device"), eq(0)); 5426 } 5427 5428 @Test testFlagBubble()5429 public void testFlagBubble() throws RemoteException { 5430 setUpPrefsForBubbles(PKG, mUid, 5431 true /* global */, 5432 BUBBLE_PREFERENCE_ALL /* app */, 5433 true /* channel */); 5434 5435 NotificationRecord nr = 5436 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble"); 5437 5438 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5439 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5440 waitForIdle(); 5441 5442 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 5443 assertEquals(1, notifs.length); 5444 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0); 5445 assertTrue(mService.getNotificationRecord( 5446 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 5447 } 5448 5449 @Test testFlagBubble_noFlag_appNotAllowed()5450 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException { 5451 setUpPrefsForBubbles(PKG, mUid, 5452 true /* global */, 5453 BUBBLE_PREFERENCE_NONE /* app */, 5454 true /* channel */); 5455 5456 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 5457 "testFlagBubble_noFlag_appNotAllowed"); 5458 5459 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5460 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5461 waitForIdle(); 5462 5463 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 5464 assertEquals(1, notifs.length); 5465 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0); 5466 assertFalse(mService.getNotificationRecord( 5467 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 5468 } 5469 5470 @Test testFlagBubbleNotifs_noFlag_whenAppForeground()5471 public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException { 5472 setUpPrefsForBubbles(PKG, mUid, 5473 true /* global */, 5474 BUBBLE_PREFERENCE_ALL /* app */, 5475 true /* channel */); 5476 5477 // Notif with bubble metadata but not our other misc requirements 5478 Notification.Builder nb = new Notification.Builder(mContext, 5479 mTestNotificationChannel.getId()) 5480 .setContentTitle("foo") 5481 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5482 .setBubbleMetadata(getBubbleMetadata()); 5483 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, 5484 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 5485 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 5486 5487 // Say we're foreground 5488 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn( 5489 IMPORTANCE_FOREGROUND); 5490 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5491 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5492 waitForIdle(); 5493 5494 // if notif isn't configured properly it doesn't get to bubble just because app is 5495 // foreground. 5496 assertFalse(mService.getNotificationRecord( 5497 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 5498 } 5499 5500 @Test testFlagBubbleNotifs_flag_messaging()5501 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException { 5502 setUpPrefsForBubbles(PKG, mUid, 5503 true /* global */, 5504 BUBBLE_PREFERENCE_ALL /* app */, 5505 true /* channel */); 5506 5507 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 5508 "testFlagBubbleNotifs_flag_messaging"); 5509 5510 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5511 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5512 waitForIdle(); 5513 5514 // yes allowed, yes messaging, yes bubble 5515 assertTrue(mService.getNotificationRecord( 5516 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 5517 } 5518 5519 @Test testFlagBubbleNotifs_noFlag_noShortcut()5520 public void testFlagBubbleNotifs_noFlag_noShortcut() throws RemoteException { 5521 setUpPrefsForBubbles(PKG, mUid, 5522 true /* global */, 5523 BUBBLE_PREFERENCE_ALL /* app */, 5524 true /* channel */); 5525 5526 Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false); 5527 nb.setShortcutId(null); 5528 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 5529 null, mUid, 0, 5530 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 5531 5532 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 5533 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 5534 waitForIdle(); 5535 5536 // no shortcut no bubble 5537 assertFalse(mService.getNotificationRecord( 5538 sbn.getKey()).getNotification().isBubbleNotification()); 5539 } 5540 5541 @Test testFlagBubbleNotifs_noFlag_messaging_appNotAllowed()5542 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException { 5543 setUpPrefsForBubbles(PKG, mUid, 5544 true /* global */, 5545 BUBBLE_PREFERENCE_NONE /* app */, 5546 true /* channel */); 5547 5548 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 5549 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed"); 5550 5551 // Post the notification 5552 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5553 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5554 waitForIdle(); 5555 5556 // not allowed, no bubble 5557 assertFalse(mService.getNotificationRecord( 5558 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 5559 } 5560 5561 @Test testFlagBubbleNotifs_noFlag_notBubble()5562 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException { 5563 setUpPrefsForBubbles(PKG, mUid, 5564 true /* global */, 5565 BUBBLE_PREFERENCE_ALL /* app */, 5566 true /* channel */); 5567 5568 // Messaging notif WITHOUT bubble metadata 5569 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */, 5570 null /* groupKey */, false /* isSummary */); 5571 5572 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 5573 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0, 5574 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 5575 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 5576 5577 // Post the notification 5578 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5579 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5580 waitForIdle(); 5581 5582 // no bubble metadata, no bubble 5583 assertFalse(mService.getNotificationRecord( 5584 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 5585 } 5586 5587 @Test testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed()5588 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException { 5589 setUpPrefsForBubbles(PKG, mUid, 5590 true /* global */, 5591 BUBBLE_PREFERENCE_ALL /* app */, 5592 false /* channel */); 5593 5594 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 5595 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed"); 5596 nr.getChannel().lockFields(USER_LOCKED_ALLOW_BUBBLE); 5597 5598 // Post the notification 5599 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5600 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5601 waitForIdle(); 5602 5603 // channel not allowed, no bubble 5604 assertFalse(mService.getNotificationRecord( 5605 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 5606 } 5607 5608 @Test testCancelNotificationsFromApp_cancelsBubbles()5609 public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception { 5610 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); 5611 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE; 5612 5613 // Post the notification 5614 mBinderService.enqueueNotificationWithTag(PKG, PKG, 5615 "testAppCancelNotifications_cancelsBubbles", 5616 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(), 5617 nrBubble.getSbn().getUserId()); 5618 waitForIdle(); 5619 5620 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 5621 assertEquals(1, notifs.length); 5622 assertEquals(1, mService.getNotificationRecordCount()); 5623 5624 mBinderService.cancelNotificationWithTag(PKG, PKG, 5625 "testAppCancelNotifications_cancelsBubbles", nrBubble.getSbn().getId(), 5626 nrBubble.getSbn().getUserId()); 5627 waitForIdle(); 5628 5629 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG); 5630 assertEquals(0, notifs2.length); 5631 assertEquals(0, mService.getNotificationRecordCount()); 5632 } 5633 5634 @Test testCancelAllNotificationsFromApp_cancelsBubble()5635 public void testCancelAllNotificationsFromApp_cancelsBubble() throws Exception { 5636 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 5637 nr.getSbn().getNotification().flags |= FLAG_BUBBLE; 5638 mService.addNotification(nr); 5639 5640 mBinderService.cancelAllNotifications(PKG, nr.getSbn().getUserId()); 5641 waitForIdle(); 5642 5643 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 5644 assertEquals(0, notifs.length); 5645 assertEquals(0, mService.getNotificationRecordCount()); 5646 } 5647 5648 @Test testCancelAllNotificationsFromListener_ignoresBubbles()5649 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception { 5650 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel); 5651 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); 5652 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE; 5653 5654 mService.addNotification(nrNormal); 5655 mService.addNotification(nrBubble); 5656 5657 mService.getBinderService().cancelNotificationsFromListener(null, null); 5658 waitForIdle(); 5659 5660 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 5661 assertEquals(1, notifs.length); 5662 assertEquals(1, mService.getNotificationRecordCount()); 5663 } 5664 5665 @Test testCancelNotificationsFromListener_cancelsNonBubble()5666 public void testCancelNotificationsFromListener_cancelsNonBubble() throws Exception { 5667 // Add non-bubble notif 5668 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 5669 mService.addNotification(nr); 5670 5671 // Cancel via listener 5672 String[] keys = {nr.getSbn().getKey()}; 5673 mService.getBinderService().cancelNotificationsFromListener(null, keys); 5674 waitForIdle(); 5675 5676 // Notif not active anymore 5677 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 5678 assertEquals(0, notifs.length); 5679 assertEquals(0, mService.getNotificationRecordCount()); 5680 // Cancel event is logged 5681 assertEquals(1, mNotificationRecordLogger.numCalls()); 5682 assertEquals(NotificationRecordLogger.NotificationCancelledEvent 5683 .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0)); 5684 } 5685 5686 @Test testCancelNotificationsFromListener_suppressesBubble()5687 public void testCancelNotificationsFromListener_suppressesBubble() throws Exception { 5688 // Add bubble notif 5689 setUpPrefsForBubbles(PKG, mUid, 5690 true /* global */, 5691 BUBBLE_PREFERENCE_ALL /* app */, 5692 true /* channel */); 5693 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag"); 5694 5695 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5696 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5697 waitForIdle(); 5698 5699 // Cancel via listener 5700 String[] keys = {nr.getSbn().getKey()}; 5701 mService.getBinderService().cancelNotificationsFromListener(null, keys); 5702 waitForIdle(); 5703 5704 // Bubble notif active and suppressed 5705 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 5706 assertEquals(1, notifs.length); 5707 assertEquals(1, mService.getNotificationRecordCount()); 5708 assertTrue(notifs[0].getNotification().getBubbleMetadata().isNotificationSuppressed()); 5709 } 5710 5711 @Test testCancelAllNotificationsFromStatusBar_ignoresBubble()5712 public void testCancelAllNotificationsFromStatusBar_ignoresBubble() throws Exception { 5713 // GIVEN a notification bubble 5714 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 5715 nr.getSbn().getNotification().flags |= FLAG_BUBBLE; 5716 mService.addNotification(nr); 5717 5718 // WHEN the status bar clears all notifications 5719 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 5720 nr.getSbn().getUserId()); 5721 waitForIdle(); 5722 5723 // THEN the bubble notification does not get removed 5724 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 5725 assertEquals(1, notifs.length); 5726 assertEquals(1, mService.getNotificationRecordCount()); 5727 } 5728 5729 5730 @Test testGetAllowedAssistantAdjustments()5731 public void testGetAllowedAssistantAdjustments() throws Exception { 5732 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null); 5733 assertNotNull(capabilities); 5734 5735 for (int i = capabilities.size() - 1; i >= 0; i--) { 5736 String capability = capabilities.get(i); 5737 mBinderService.disallowAssistantAdjustment(capability); 5738 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size()); 5739 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null); 5740 assertNotNull(currentCapabilities); 5741 assertFalse(currentCapabilities.contains(capability)); 5742 } 5743 } 5744 5745 @Test testAdjustRestrictedKey()5746 public void testAdjustRestrictedKey() throws Exception { 5747 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5748 mService.addNotification(r); 5749 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 5750 5751 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true); 5752 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false); 5753 5754 Bundle signals = new Bundle(); 5755 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW); 5756 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE); 5757 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, 5758 "", r.getUser().getIdentifier()); 5759 5760 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 5761 r.applyAdjustments(); 5762 5763 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance()); 5764 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment()); 5765 } 5766 5767 @Test testAutomaticZenRuleValidation_policyFilterAgreement()5768 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception { 5769 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) 5770 .thenReturn(true); 5771 mService.setZenHelper(mock(ZenModeHelper.class)); 5772 ComponentName owner = new ComponentName(mContext, this.getClass()); 5773 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build(); 5774 boolean isEnabled = true; 5775 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 5776 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled); 5777 5778 try { 5779 mBinderService.addAutomaticZenRule(rule); 5780 fail("Zen policy only applies to priority only mode"); 5781 } catch (IllegalArgumentException e) { 5782 // yay 5783 } 5784 5785 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 5786 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled); 5787 mBinderService.addAutomaticZenRule(rule); 5788 5789 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 5790 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled); 5791 mBinderService.addAutomaticZenRule(rule); 5792 } 5793 5794 @Test testAreNotificationsEnabledForPackage_crossUser()5795 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception { 5796 try { 5797 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), 5798 mUid + UserHandle.PER_USER_RANGE); 5799 fail("Cannot call cross user without permission"); 5800 } catch (SecurityException e) { 5801 // pass 5802 } 5803 5804 // cross user, with permission, no problem 5805 enableInteractAcrossUsers(); 5806 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), 5807 mUid + UserHandle.PER_USER_RANGE); 5808 } 5809 5810 @Test testAreBubblesAllowedForPackage_crossUser()5811 public void testAreBubblesAllowedForPackage_crossUser() throws Exception { 5812 try { 5813 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(), 5814 mUid + UserHandle.PER_USER_RANGE); 5815 fail("Cannot call cross user without permission"); 5816 } catch (SecurityException e) { 5817 // pass 5818 } 5819 5820 // cross user, with permission, no problem 5821 enableInteractAcrossUsers(); 5822 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(), 5823 mUid + UserHandle.PER_USER_RANGE); 5824 } 5825 enableInteractAcrossUsers()5826 private void enableInteractAcrossUsers() { 5827 TestablePermissions perms = mContext.getTestablePermissions(); 5828 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); 5829 } 5830 5831 @Test testNotificationBubbleChanged_false()5832 public void testNotificationBubbleChanged_false() throws Exception { 5833 setUpPrefsForBubbles(PKG, mUid, 5834 true /* global */, 5835 BUBBLE_PREFERENCE_ALL /* app */, 5836 true /* channel */); 5837 5838 // Notif with bubble metadata 5839 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 5840 "testNotificationBubbleChanged_false"); 5841 5842 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5843 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5844 waitForIdle(); 5845 5846 // Reset as this is called when the notif is first sent 5847 reset(mListeners); 5848 5849 // First we were a bubble 5850 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 5851 assertEquals(1, notifsBefore.length); 5852 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0); 5853 5854 // Notify we're not a bubble 5855 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0); 5856 waitForIdle(); 5857 5858 // Make sure we are not a bubble 5859 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 5860 assertEquals(1, notifsAfter.length); 5861 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 5862 } 5863 5864 @Test testNotificationBubbleChanged_true()5865 public void testNotificationBubbleChanged_true() throws Exception { 5866 setUpPrefsForBubbles(PKG, mUid, 5867 true /* global */, 5868 BUBBLE_PREFERENCE_ALL /* app */, 5869 true /* channel */); 5870 5871 // Notif that is not a bubble 5872 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 5873 1, null, false); 5874 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5875 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5876 waitForIdle(); 5877 5878 // Would be a normal notification because wouldn't have met requirements to bubble 5879 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 5880 assertEquals(1, notifsBefore.length); 5881 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); 5882 5883 // Update the notification to be message style / meet bubble requirements 5884 NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel, 5885 nr.getSbn().getTag()); 5886 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.getSbn().getTag(), 5887 nr2.getSbn().getId(), nr2.getSbn().getNotification(), nr2.getSbn().getUserId()); 5888 waitForIdle(); 5889 5890 // Reset as this is called when the notif is first sent 5891 reset(mListeners); 5892 5893 // Notify we are now a bubble 5894 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0); 5895 waitForIdle(); 5896 5897 // Make sure we are a bubble 5898 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 5899 assertEquals(1, notifsAfter.length); 5900 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0); 5901 } 5902 5903 @Test testNotificationBubbleChanged_true_notAllowed()5904 public void testNotificationBubbleChanged_true_notAllowed() throws Exception { 5905 setUpPrefsForBubbles(PKG, mUid, 5906 true /* global */, 5907 BUBBLE_PREFERENCE_ALL /* app */, 5908 true /* channel */); 5909 5910 // Notif that is not a bubble 5911 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 5912 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5913 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5914 waitForIdle(); 5915 5916 // Reset as this is called when the notif is first sent 5917 reset(mListeners); 5918 5919 // Would be a normal notification because wouldn't have met requirements to bubble 5920 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 5921 assertEquals(1, notifsBefore.length); 5922 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); 5923 5924 // Notify we are now a bubble 5925 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0); 5926 waitForIdle(); 5927 5928 // We still wouldn't be a bubble because the notification didn't meet requirements 5929 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 5930 assertEquals(1, notifsAfter.length); 5931 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 5932 } 5933 5934 @Test testNotificationBubbleIsFlagRemoved_resetOnUpdate()5935 public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception { 5936 setUpPrefsForBubbles(PKG, mUid, 5937 true /* global */, 5938 BUBBLE_PREFERENCE_ALL /* app */, 5939 true /* channel */); 5940 5941 // Notif with bubble metadata 5942 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 5943 "testNotificationBubbleIsFlagRemoved_resetOnUpdate"); 5944 5945 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5946 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5947 waitForIdle(); 5948 // Flag shouldn't be modified 5949 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 5950 assertFalse(recordToCheck.isFlagBubbleRemoved()); 5951 5952 // Notify we're not a bubble 5953 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0); 5954 waitForIdle(); 5955 // Flag should be modified 5956 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 5957 assertTrue(recordToCheck.isFlagBubbleRemoved()); 5958 5959 5960 // Update the notif 5961 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5962 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5963 waitForIdle(); 5964 // And the flag is reset 5965 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 5966 assertFalse(recordToCheck.isFlagBubbleRemoved()); 5967 } 5968 5969 @Test testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue()5970 public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception { 5971 setUpPrefsForBubbles(PKG, mUid, 5972 true /* global */, 5973 BUBBLE_PREFERENCE_ALL /* app */, 5974 true /* channel */); 5975 5976 // Notif with bubble metadata 5977 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 5978 "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue"); 5979 5980 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 5981 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5982 waitForIdle(); 5983 // Flag shouldn't be modified 5984 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 5985 assertFalse(recordToCheck.isFlagBubbleRemoved()); 5986 5987 // Notify we're not a bubble 5988 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0); 5989 waitForIdle(); 5990 // Flag should be modified 5991 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 5992 assertTrue(recordToCheck.isFlagBubbleRemoved()); 5993 5994 // Notify we are a bubble 5995 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0); 5996 waitForIdle(); 5997 // And the flag is reset 5998 assertFalse(recordToCheck.isFlagBubbleRemoved()); 5999 } 6000 6001 @Test testOnBubbleNotificationSuppressionChanged()6002 public void testOnBubbleNotificationSuppressionChanged() throws Exception { 6003 setUpPrefsForBubbles(PKG, mUid, 6004 true /* global */, 6005 BUBBLE_PREFERENCE_ALL /* app */, 6006 true /* channel */); 6007 6008 // Bubble notification 6009 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag"); 6010 6011 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6012 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6013 waitForIdle(); 6014 6015 // NOT suppressed 6016 Notification n = mBinderService.getActiveNotifications(PKG)[0].getNotification(); 6017 assertFalse(n.getBubbleMetadata().isNotificationSuppressed()); 6018 6019 // Reset as this is called when the notif is first sent 6020 reset(mListeners); 6021 6022 // Test: update suppression to true 6023 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true); 6024 waitForIdle(); 6025 6026 // Check 6027 n = mBinderService.getActiveNotifications(PKG)[0].getNotification(); 6028 assertTrue(n.getBubbleMetadata().isNotificationSuppressed()); 6029 6030 // Reset to check again 6031 reset(mListeners); 6032 6033 // Test: update suppression to false 6034 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false); 6035 waitForIdle(); 6036 6037 // Check 6038 n = mBinderService.getActiveNotifications(PKG)[0].getNotification(); 6039 assertFalse(n.getBubbleMetadata().isNotificationSuppressed()); 6040 } 6041 6042 @Test testGrantInlineReplyUriPermission_recordExists()6043 public void testGrantInlineReplyUriPermission_recordExists() throws Exception { 6044 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0); 6045 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 6046 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6047 waitForIdle(); 6048 6049 // A notification exists for the given record 6050 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 6051 assertEquals(1, notifsBefore.length); 6052 6053 reset(mPackageManager); 6054 6055 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 6056 6057 mService.mNotificationDelegate.grantInlineReplyUriPermission( 6058 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 6059 nr.getSbn().getUid()); 6060 6061 // Grant permission called for the UID of SystemUI under the target user ID 6062 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 6063 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), 6064 anyInt(), eq(nr.getSbn().getUserId())); 6065 } 6066 6067 @Test testGrantInlineReplyUriPermission_noRecordExists()6068 public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception { 6069 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0); 6070 waitForIdle(); 6071 6072 // No notifications exist for the given record 6073 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 6074 assertEquals(0, notifsBefore.length); 6075 6076 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 6077 int uid = 0; // sysui on primary user 6078 6079 mService.mNotificationDelegate.grantInlineReplyUriPermission( 6080 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 6081 nr.getSbn().getUid()); 6082 6083 // Grant permission still called if no NotificationRecord exists for the given key 6084 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 6085 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), 6086 anyInt(), eq(nr.getSbn().getUserId())); 6087 } 6088 6089 @Test testGrantInlineReplyUriPermission_userAll()6090 public void testGrantInlineReplyUriPermission_userAll() throws Exception { 6091 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM 6092 NotificationRecord nr = 6093 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL); 6094 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 6095 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6096 waitForIdle(); 6097 6098 // A notification exists for the given record 6099 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 6100 assertEquals(1, notifsBefore.length); 6101 6102 reset(mPackageManager); 6103 6104 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 6105 6106 mService.mNotificationDelegate.grantInlineReplyUriPermission( 6107 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 6108 nr.getSbn().getUid()); 6109 6110 // Target user for the grant is USER_ALL instead of USER_SYSTEM 6111 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 6112 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), 6113 anyInt(), eq(UserHandle.USER_SYSTEM)); 6114 } 6115 6116 @Test testGrantInlineReplyUriPermission_acrossUsers()6117 public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception { 6118 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM 6119 int otherUserId = 11; 6120 NotificationRecord nr = 6121 generateNotificationRecord(mTestNotificationChannel, otherUserId); 6122 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 6123 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6124 waitForIdle(); 6125 6126 // A notification exists for the given record 6127 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 6128 assertEquals(1, notifsBefore.length); 6129 6130 reset(mPackageManager); 6131 6132 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 6133 6134 int uid = 0; // sysui on primary user 6135 int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user 6136 String sysuiPackage = "sysui"; 6137 final String[] sysuiPackages = new String[] { sysuiPackage }; 6138 when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages); 6139 6140 // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the 6141 // time this is called 6142 when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId)) 6143 .thenReturn(otherUserUid); 6144 6145 mService.mNotificationDelegate.grantInlineReplyUriPermission( 6146 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), uid); 6147 6148 // Target user for the grant is USER_ALL instead of USER_SYSTEM 6149 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 6150 eq(otherUserUid), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), anyInt(), 6151 eq(otherUserId)); 6152 } 6153 6154 @Test testClearInlineReplyUriPermission_uriRecordExists()6155 public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception { 6156 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0); 6157 reset(mPackageManager); 6158 6159 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 6160 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2); 6161 6162 // create an inline record with two uris in it 6163 mService.mNotificationDelegate.grantInlineReplyUriPermission( 6164 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 6165 nr.getSbn().getUid()); 6166 mService.mNotificationDelegate.grantInlineReplyUriPermission( 6167 nr.getKey(), uri2, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 6168 nr.getSbn().getUid()); 6169 6170 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey()); 6171 assertNotNull(record); // record exists 6172 assertEquals(record.getUris().size(), 2); // record has two uris in it 6173 6174 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), 6175 nr.getSbn().getUid()); 6176 6177 // permissionOwner destroyed 6178 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner( 6179 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId())); 6180 } 6181 6182 6183 @Test testClearInlineReplyUriPermission_noUriRecordExists()6184 public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception { 6185 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0); 6186 reset(mPackageManager); 6187 6188 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), 6189 nr.getSbn().getUid()); 6190 6191 // no permissionOwner destroyed 6192 verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner( 6193 any(), eq(null), eq(~0), eq(nr.getUserId())); 6194 } 6195 6196 @Test testClearInlineReplyUriPermission_userAll()6197 public void testClearInlineReplyUriPermission_userAll() throws Exception { 6198 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 6199 UserHandle.USER_ALL); 6200 reset(mPackageManager); 6201 6202 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 6203 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2); 6204 6205 // create an inline record a uri in it 6206 mService.mNotificationDelegate.grantInlineReplyUriPermission( 6207 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 6208 nr.getSbn().getUid()); 6209 6210 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey()); 6211 assertNotNull(record); // record exists 6212 6213 mService.mNotificationDelegate.clearInlineReplyUriPermissions( 6214 nr.getKey(), nr.getSbn().getUid()); 6215 6216 // permissionOwner destroyed for USER_SYSTEM, not USER_ALL 6217 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner( 6218 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(USER_SYSTEM)); 6219 } 6220 6221 @Test testNotificationBubbles_disabled_lowRamDevice()6222 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception { 6223 setUpPrefsForBubbles(PKG, mUid, 6224 true /* global */, 6225 BUBBLE_PREFERENCE_ALL /* app */, 6226 true /* channel */); 6227 6228 // And we are low ram 6229 when(mActivityManager.isLowRamDevice()).thenReturn(true); 6230 6231 // Notification that would typically bubble 6232 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 6233 "testNotificationBubbles_disabled_lowRamDevice"); 6234 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6235 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6236 waitForIdle(); 6237 6238 // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled. 6239 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 6240 assertEquals(1, notifsAfter.length); 6241 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 6242 } 6243 6244 @Test testRemoveLargeRemoteViews()6245 public void testRemoveLargeRemoteViews() throws Exception { 6246 int removeSize = mContext.getResources().getInteger( 6247 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes); 6248 6249 RemoteViews rv = mock(RemoteViews.class); 6250 when(rv.estimateMemoryUsage()).thenReturn(removeSize); 6251 when(rv.clone()).thenReturn(rv); 6252 RemoteViews rv1 = mock(RemoteViews.class); 6253 when(rv1.estimateMemoryUsage()).thenReturn(removeSize); 6254 when(rv1.clone()).thenReturn(rv1); 6255 RemoteViews rv2 = mock(RemoteViews.class); 6256 when(rv2.estimateMemoryUsage()).thenReturn(removeSize); 6257 when(rv2.clone()).thenReturn(rv2); 6258 RemoteViews rv3 = mock(RemoteViews.class); 6259 when(rv3.estimateMemoryUsage()).thenReturn(removeSize); 6260 when(rv3.clone()).thenReturn(rv3); 6261 RemoteViews rv4 = mock(RemoteViews.class); 6262 when(rv4.estimateMemoryUsage()).thenReturn(removeSize); 6263 when(rv4.clone()).thenReturn(rv4); 6264 // note: different! 6265 RemoteViews rv5 = mock(RemoteViews.class); 6266 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1); 6267 when(rv5.clone()).thenReturn(rv5); 6268 6269 Notification np = new Notification.Builder(mContext, "test") 6270 .setSmallIcon(android.R.drawable.sym_def_app_icon) 6271 .setContentText("test") 6272 .setCustomContentView(rv) 6273 .setCustomBigContentView(rv1) 6274 .setCustomHeadsUpContentView(rv2) 6275 .build(); 6276 Notification n = new Notification.Builder(mContext, "test") 6277 .setSmallIcon(android.R.drawable.sym_def_app_icon) 6278 .setContentText("test") 6279 .setCustomContentView(rv3) 6280 .setCustomBigContentView(rv4) 6281 .setCustomHeadsUpContentView(rv5) 6282 .setPublicVersion(np) 6283 .build(); 6284 6285 assertNotNull(np.contentView); 6286 assertNotNull(np.bigContentView); 6287 assertNotNull(np.headsUpContentView); 6288 6289 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW)); 6290 assertNotNull(n.publicVersion.contentView); 6291 assertNotNull(n.publicVersion.bigContentView); 6292 assertNotNull(n.publicVersion.headsUpContentView); 6293 6294 mService.fixNotification(n, PKG, "tag", 9, 0); 6295 6296 assertNull(n.contentView); 6297 assertNull(n.bigContentView); 6298 assertNotNull(n.headsUpContentView); 6299 assertNull(n.publicVersion.contentView); 6300 assertNull(n.publicVersion.bigContentView); 6301 assertNull(n.publicVersion.headsUpContentView); 6302 6303 verify(mUsageStats, times(5)).registerImageRemoved(PKG); 6304 } 6305 6306 @Test testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()6307 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground() 6308 throws Exception { 6309 setUpPrefsForBubbles(PKG, mUid, 6310 true /* global */, 6311 BUBBLE_PREFERENCE_ALL /* app */, 6312 true /* channel */); 6313 6314 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 6315 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground"); 6316 // Modify metadata flags 6317 nr.getSbn().getNotification().getBubbleMetadata().setFlags( 6318 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE 6319 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 6320 6321 // Ensure we're not foreground 6322 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn( 6323 IMPORTANCE_VISIBLE); 6324 6325 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6326 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6327 waitForIdle(); 6328 6329 // yes allowed, yes messaging, yes bubble 6330 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 6331 assertTrue(notif.isBubbleNotification()); 6332 6333 // Our flags should have failed since we're not foreground 6334 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble()); 6335 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed()); 6336 } 6337 6338 @Test testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()6339 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground() 6340 throws RemoteException { 6341 setUpPrefsForBubbles(PKG, mUid, 6342 true /* global */, 6343 BUBBLE_PREFERENCE_ALL /* app */, 6344 true /* channel */); 6345 6346 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 6347 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground"); 6348 // Modify metadata flags 6349 nr.getSbn().getNotification().getBubbleMetadata().setFlags( 6350 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE 6351 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 6352 6353 // Ensure we are in the foreground 6354 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn( 6355 IMPORTANCE_FOREGROUND); 6356 6357 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6358 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6359 waitForIdle(); 6360 6361 // yes allowed, yes messaging, yes bubble 6362 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 6363 assertTrue(notif.isBubbleNotification()); 6364 6365 // Our flags should have passed since we are foreground 6366 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble()); 6367 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed()); 6368 } 6369 6370 @Test testNotificationBubbles_flagRemoved_whenShortcutRemoved()6371 public void testNotificationBubbles_flagRemoved_whenShortcutRemoved() 6372 throws RemoteException { 6373 setUpPrefsForBubbles(PKG, mUid, 6374 true /* global */, 6375 BUBBLE_PREFERENCE_ALL /* app */, 6376 true /* channel */); 6377 6378 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback = 6379 ArgumentCaptor.forClass(LauncherApps.Callback.class); 6380 6381 // Messaging notification with shortcut info 6382 Notification.BubbleMetadata metadata = 6383 new Notification.BubbleMetadata.Builder(VALID_CONVO_SHORTCUT_ID).build(); 6384 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 6385 null /* groupKey */, false /* isSummary */); 6386 nb.setShortcutId(VALID_CONVO_SHORTCUT_ID); 6387 nb.setBubbleMetadata(metadata); 6388 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 6389 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6390 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 6391 6392 // Test: Send the bubble notification 6393 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6394 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6395 waitForIdle(); 6396 6397 // Verify: 6398 6399 // Make sure we register the callback for shortcut changes 6400 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any()); 6401 6402 // yes allowed, yes messaging w/shortcut, yes bubble 6403 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 6404 assertTrue(notif.isBubbleNotification()); 6405 6406 // Make sure the shortcut is cached. 6407 verify(mShortcutServiceInternal).cacheShortcuts( 6408 anyInt(), any(), eq(PKG), eq(Collections.singletonList(VALID_CONVO_SHORTCUT_ID)), 6409 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 6410 6411 // Test: Remove the shortcut 6412 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 6413 launcherAppsCallback.getValue().onShortcutsChanged(PKG, Collections.emptyList(), 6414 UserHandle.getUserHandleForUid(mUid)); 6415 waitForIdle(); 6416 6417 // Verify: 6418 6419 // Make sure callback is unregistered 6420 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue()); 6421 6422 // We're no longer a bubble 6423 NotificationRecord notif2 = mService.getNotificationRecord( 6424 nr.getSbn().getKey()); 6425 assertNull(notif2.getShortcutInfo()); 6426 assertFalse(notif2.getNotification().isBubbleNotification()); 6427 } 6428 6429 @Test testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()6430 public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved() 6431 throws RemoteException { 6432 final String shortcutId = "someshortcutId"; 6433 setUpPrefsForBubbles(PKG, mUid, 6434 true /* global */, 6435 BUBBLE_PREFERENCE_ALL /* app */, 6436 true /* channel */); 6437 6438 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback = 6439 ArgumentCaptor.forClass(LauncherApps.Callback.class); 6440 6441 // Messaging notification with shortcut info 6442 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder( 6443 shortcutId).build(); 6444 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 6445 null /* groupKey */, false /* isSummary */); 6446 nb.setShortcutId(shortcutId); 6447 nb.setBubbleMetadata(metadata); 6448 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 6449 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6450 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 6451 6452 // Pretend the shortcut exists 6453 List<ShortcutInfo> shortcutInfos = new ArrayList<>(); 6454 ShortcutInfo info = mock(ShortcutInfo.class); 6455 when(info.getPackage()).thenReturn(PKG); 6456 when(info.getId()).thenReturn(shortcutId); 6457 when(info.getUserId()).thenReturn(USER_SYSTEM); 6458 when(info.isLongLived()).thenReturn(true); 6459 when(info.isEnabled()).thenReturn(true); 6460 shortcutInfos.add(info); 6461 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos); 6462 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), 6463 anyString(), anyInt(), any())).thenReturn(true); 6464 6465 // Test: Send the bubble notification 6466 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6467 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6468 waitForIdle(); 6469 6470 // Verify: 6471 6472 // Make sure we register the callback for shortcut changes 6473 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any()); 6474 6475 // yes allowed, yes messaging w/shortcut, yes bubble 6476 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 6477 assertTrue(notif.isBubbleNotification()); 6478 6479 // Make sure the shortcut is cached. 6480 verify(mShortcutServiceInternal).cacheShortcuts( 6481 anyInt(), any(), eq(PKG), eq(Collections.singletonList(shortcutId)), 6482 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 6483 6484 // Test: Remove the notification 6485 mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6486 nr.getSbn().getId(), nr.getSbn().getUserId()); 6487 waitForIdle(); 6488 6489 // Verify: 6490 6491 // Make sure callback is unregistered 6492 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue()); 6493 } 6494 6495 @Test testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()6496 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed() 6497 throws Exception { 6498 setUpPrefsForBubbles(PKG, mUid, 6499 true /* global */, 6500 BUBBLE_PREFERENCE_ALL /* app */, 6501 true /* channel */); 6502 6503 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded( 6504 true /* summaryAutoCancel */); 6505 6506 // Dismiss summary 6507 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2, 6508 true); 6509 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, 6510 nrSummary.getSbn().getTag(), 6511 nrSummary.getSbn().getId(), nrSummary.getUserId(), nrSummary.getKey(), 6512 NotificationStats.DISMISSAL_SHADE, 6513 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv); 6514 waitForIdle(); 6515 6516 // The bubble should still exist 6517 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 6518 assertEquals(1, notifsAfter.length); 6519 } 6520 6521 @Test testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()6522 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked() 6523 throws Exception { 6524 setUpPrefsForBubbles(PKG, mUid, 6525 true /* global */, 6526 BUBBLE_PREFERENCE_ALL /* app */, 6527 true /* channel */); 6528 6529 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded( 6530 true /* summaryAutoCancel */); 6531 6532 // Click summary 6533 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2, 6534 true); 6535 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(), 6536 nrSummary.getKey(), nv); 6537 waitForIdle(); 6538 6539 // The bubble should still exist 6540 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 6541 assertEquals(1, notifsAfter.length); 6542 6543 // Check we got the click log and associated dismissal logs 6544 assertEquals(6, mNotificationRecordLogger.numCalls()); 6545 // Skip the notification-creation logs 6546 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED, 6547 mNotificationRecordLogger.event(3)); 6548 assertEquals(NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_CLICK, 6549 mNotificationRecordLogger.event(4)); 6550 assertEquals(NotificationRecordLogger.NotificationCancelledEvent 6551 .NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED, 6552 mNotificationRecordLogger.event(5)); 6553 } 6554 6555 @Test testNotificationBubbles_bubbleStays_whenClicked()6556 public void testNotificationBubbles_bubbleStays_whenClicked() 6557 throws Exception { 6558 setUpPrefsForBubbles(PKG, mUid, 6559 true /* global */, 6560 BUBBLE_PREFERENCE_ALL /* app */, 6561 true /* channel */); 6562 6563 // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble 6564 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 6565 nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL; 6566 mService.addNotification(nr); 6567 6568 // WHEN we click the notification 6569 final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true); 6570 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(), 6571 nr.getKey(), nv); 6572 waitForIdle(); 6573 6574 // THEN the bubble should still exist 6575 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 6576 assertEquals(1, notifsAfter.length); 6577 6578 // Check we got the click log 6579 assertEquals(1, mNotificationRecordLogger.numCalls()); 6580 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED, 6581 mNotificationRecordLogger.event(0)); 6582 } 6583 6584 @Test testLoadDefaultApprovedServices_emptyResources()6585 public void testLoadDefaultApprovedServices_emptyResources() { 6586 TestableResources tr = mContext.getOrCreateTestableResources(); 6587 tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, ""); 6588 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, ""); 6589 tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, ""); 6590 setDefaultAssistantInDeviceConfig(""); 6591 6592 mService.loadDefaultApprovedServices(USER_SYSTEM); 6593 6594 verify(mListeners, never()).addDefaultComponentOrPackage(anyString()); 6595 verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString()); 6596 verify(mAssistants, never()).addDefaultComponentOrPackage(anyString()); 6597 } 6598 6599 @Test testLoadDefaultApprovedServices_dnd()6600 public void testLoadDefaultApprovedServices_dnd() { 6601 TestableResources tr = mContext.getOrCreateTestableResources(); 6602 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test"); 6603 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt())) 6604 .thenReturn(new ArraySet<>()); 6605 6606 mService.loadDefaultApprovedServices(USER_SYSTEM); 6607 6608 verify(mConditionProviders, times(1)).loadDefaultsFromConfig(); 6609 } 6610 6611 // TODO: add tests for the rest of the non-empty cases 6612 6613 @Test testOnUnlockUser()6614 public void testOnUnlockUser() { 6615 UserInfo ui = new UserInfo(); 6616 ui.id = 10; 6617 mService.onUnlockUser(ui); 6618 waitForIdle(); 6619 6620 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id); 6621 } 6622 6623 @Test testOnStopUser()6624 public void testOnStopUser() { 6625 UserInfo ui = new UserInfo(); 6626 ui.id = 10; 6627 mService.onStopUser(ui); 6628 waitForIdle(); 6629 6630 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id); 6631 } 6632 6633 @Test testOnBootPhase()6634 public void testOnBootPhase() { 6635 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); 6636 6637 verify(mHistoryManager, never()).onBootPhaseAppsCanStart(); 6638 6639 mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); 6640 6641 verify(mHistoryManager, times(1)).onBootPhaseAppsCanStart(); 6642 } 6643 6644 @Test testHandleOnPackageChanged()6645 public void testHandleOnPackageChanged() { 6646 String[] pkgs = new String[] {PKG, PKG_N_MR1}; 6647 int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1}; 6648 6649 mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids); 6650 6651 verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString()); 6652 6653 mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids); 6654 6655 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]); 6656 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]); 6657 } 6658 6659 @Test testNotificationHistory_addNoisyNotification()6660 public void testNotificationHistory_addNoisyNotification() throws Exception { 6661 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 6662 null /* tvExtender */); 6663 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6664 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6665 waitForIdle(); 6666 6667 verify(mHistoryManager, times(1)).addNotification(any()); 6668 } 6669 6670 @Test createConversationNotificationChannel()6671 public void createConversationNotificationChannel() throws Exception { 6672 NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 6673 original.setAllowBubbles(!original.canBubble()); 6674 original.setShowBadge(!original.canShowBadge()); 6675 6676 Parcel parcel = Parcel.obtain(); 6677 original.writeToParcel(parcel, 0); 6678 parcel.setDataPosition(0); 6679 NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel); 6680 assertEquals(original, orig); 6681 assertFalse(TextUtils.isEmpty(orig.getName())); 6682 6683 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList( 6684 orig))); 6685 6686 mBinderService.createConversationNotificationChannelForPackage( 6687 PKG, mUid, "key", orig, "friend"); 6688 6689 NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel( 6690 PKG, 0, PKG, original.getId(), false, "friend"); 6691 6692 assertEquals(original.getName(), friendChannel.getName()); 6693 assertEquals(original.getId(), friendChannel.getParentChannelId()); 6694 assertEquals("friend", friendChannel.getConversationId()); 6695 assertEquals(null, original.getConversationId()); 6696 assertEquals(original.canShowBadge(), friendChannel.canShowBadge()); 6697 assertFalse(friendChannel.canBubble()); // can't be modified by app 6698 assertFalse(original.getId().equals(friendChannel.getId())); 6699 assertNotNull(friendChannel.getId()); 6700 } 6701 6702 @Test deleteConversationNotificationChannels()6703 public void deleteConversationNotificationChannels() throws Exception { 6704 NotificationChannel messagesParent = 6705 new NotificationChannel("messages", "messages", IMPORTANCE_HIGH); 6706 Parcel msgParcel = Parcel.obtain(); 6707 messagesParent.writeToParcel(msgParcel, 0); 6708 msgParcel.setDataPosition(0); 6709 6710 NotificationChannel callsParent = 6711 new NotificationChannel("calls", "calls", IMPORTANCE_HIGH); 6712 Parcel callParcel = Parcel.obtain(); 6713 callsParent.writeToParcel(callParcel, 0); 6714 callParcel.setDataPosition(0); 6715 6716 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList( 6717 messagesParent, callsParent))); 6718 6719 String conversationId = "friend"; 6720 6721 mBinderService.createConversationNotificationChannelForPackage( 6722 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(msgParcel), 6723 conversationId); 6724 mBinderService.createConversationNotificationChannelForPackage( 6725 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(callParcel), 6726 conversationId); 6727 6728 NotificationChannel messagesChild = mBinderService.getConversationNotificationChannel( 6729 PKG, 0, PKG, messagesParent.getId(), false, conversationId); 6730 NotificationChannel callsChild = mBinderService.getConversationNotificationChannel( 6731 PKG, 0, PKG, callsParent.getId(), false, conversationId); 6732 6733 assertEquals(messagesParent.getId(), messagesChild.getParentChannelId()); 6734 assertEquals(conversationId, messagesChild.getConversationId()); 6735 6736 assertEquals(callsParent.getId(), callsChild.getParentChannelId()); 6737 assertEquals(conversationId, callsChild.getConversationId()); 6738 6739 mBinderService.deleteConversationNotificationChannels(PKG, mUid, conversationId); 6740 6741 assertNull(mBinderService.getConversationNotificationChannel( 6742 PKG, 0, PKG, messagesParent.getId(), false, conversationId)); 6743 assertNull(mBinderService.getConversationNotificationChannel( 6744 PKG, 0, PKG, callsParent.getId(), false, conversationId)); 6745 } 6746 6747 @Test testCorrectCategory_systemOn_appCannotTurnOff()6748 public void testCorrectCategory_systemOn_appCannotTurnOff() { 6749 int requested = 0; 6750 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 6751 6752 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 6753 system); 6754 6755 assertEquals(PRIORITY_CATEGORY_CONVERSATIONS, actual); 6756 } 6757 6758 @Test testCorrectCategory_systemOff_appTurnOff_noChanges()6759 public void testCorrectCategory_systemOff_appTurnOff_noChanges() { 6760 int requested = PRIORITY_CATEGORY_CALLS; 6761 int system = PRIORITY_CATEGORY_CALLS; 6762 6763 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 6764 system); 6765 6766 assertEquals(PRIORITY_CATEGORY_CALLS, actual); 6767 } 6768 6769 @Test testCorrectCategory_systemOn_appTurnOn_noChanges()6770 public void testCorrectCategory_systemOn_appTurnOn_noChanges() { 6771 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 6772 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 6773 6774 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 6775 system); 6776 6777 assertEquals(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS, actual); 6778 } 6779 6780 @Test testCorrectCategory_systemOff_appCannotTurnOn()6781 public void testCorrectCategory_systemOff_appCannotTurnOn() { 6782 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 6783 int system = PRIORITY_CATEGORY_CALLS; 6784 6785 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 6786 system); 6787 6788 assertEquals(PRIORITY_CATEGORY_CALLS, actual); 6789 } 6790 6791 @Test testGetConversationsForPackage_hasShortcut()6792 public void testGetConversationsForPackage_hasShortcut() throws Exception { 6793 mService.setPreferencesHelper(mPreferencesHelper); 6794 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>(); 6795 ConversationChannelWrapper convo1 = new ConversationChannelWrapper(); 6796 NotificationChannel channel1 = new NotificationChannel("a", "a", 1); 6797 channel1.setConversationId("parent1", "convo 1"); 6798 convo1.setNotificationChannel(channel1); 6799 convos.add(convo1); 6800 6801 ConversationChannelWrapper convo2 = new ConversationChannelWrapper(); 6802 NotificationChannel channel2 = new NotificationChannel("b", "b", 1); 6803 channel2.setConversationId("parent1", "convo 2"); 6804 convo2.setNotificationChannel(channel2); 6805 convos.add(convo2); 6806 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos); 6807 6808 ShortcutInfo si = mock(ShortcutInfo.class); 6809 when(si.getPackage()).thenReturn(PKG_P); 6810 when(si.getId()).thenReturn("convo"); 6811 when(si.getUserId()).thenReturn(USER_SYSTEM); 6812 when(si.getLabel()).thenReturn("Hello"); 6813 when(si.isLongLived()).thenReturn(true); 6814 when(si.isEnabled()).thenReturn(true); 6815 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si)); 6816 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), 6817 anyString(), anyInt(), any())).thenReturn(true); 6818 6819 List<ConversationChannelWrapper> conversations = 6820 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 6821 assertEquals(si, conversations.get(0).getShortcutInfo()); 6822 assertEquals(si, conversations.get(1).getShortcutInfo()); 6823 } 6824 6825 @Test testGetConversationsForPackage_shortcut_notLongLived()6826 public void testGetConversationsForPackage_shortcut_notLongLived() throws Exception { 6827 mService.setPreferencesHelper(mPreferencesHelper); 6828 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>(); 6829 ConversationChannelWrapper convo1 = new ConversationChannelWrapper(); 6830 NotificationChannel channel1 = new NotificationChannel("a", "a", 1); 6831 channel1.setConversationId("parent1", "convo 1"); 6832 convo1.setNotificationChannel(channel1); 6833 convos.add(convo1); 6834 6835 ConversationChannelWrapper convo2 = new ConversationChannelWrapper(); 6836 NotificationChannel channel2 = new NotificationChannel("b", "b", 1); 6837 channel2.setConversationId("parent1", "convo 2"); 6838 convo2.setNotificationChannel(channel2); 6839 convos.add(convo2); 6840 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos); 6841 6842 ShortcutInfo si = mock(ShortcutInfo.class); 6843 when(si.getPackage()).thenReturn(PKG_P); 6844 when(si.getId()).thenReturn("convo"); 6845 when(si.getUserId()).thenReturn(USER_SYSTEM); 6846 when(si.getLabel()).thenReturn("Hello"); 6847 when(si.isLongLived()).thenReturn(false); 6848 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si)); 6849 6850 List<ConversationChannelWrapper> conversations = 6851 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 6852 assertNull(conversations.get(0).getShortcutInfo()); 6853 assertNull(conversations.get(1).getShortcutInfo()); 6854 } 6855 6856 @Test testGetConversationsForPackage_doesNotHaveShortcut()6857 public void testGetConversationsForPackage_doesNotHaveShortcut() throws Exception { 6858 mService.setPreferencesHelper(mPreferencesHelper); 6859 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>(); 6860 ConversationChannelWrapper convo1 = new ConversationChannelWrapper(); 6861 NotificationChannel channel1 = new NotificationChannel("a", "a", 1); 6862 channel1.setConversationId("parent1", "convo 1"); 6863 convo1.setNotificationChannel(channel1); 6864 convos.add(convo1); 6865 6866 ConversationChannelWrapper convo2 = new ConversationChannelWrapper(); 6867 NotificationChannel channel2 = new NotificationChannel("b", "b", 1); 6868 channel2.setConversationId("parent1", "convo 2"); 6869 convo2.setNotificationChannel(channel2); 6870 convos.add(convo2); 6871 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos); 6872 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 6873 6874 List<ConversationChannelWrapper> conversations = 6875 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 6876 assertNull(conversations.get(0).getShortcutInfo()); 6877 assertNull(conversations.get(1).getShortcutInfo()); 6878 } 6879 6880 @Test testShortcutHelperNull_doesntCrashEnqueue()6881 public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException { 6882 mService.setShortcutHelper(null); 6883 NotificationRecord nr = 6884 generateMessageBubbleNotifRecord(mTestNotificationChannel, 6885 "testShortcutHelperNull_doesntCrashEnqueue"); 6886 try { 6887 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6888 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6889 waitForIdle(); 6890 } catch (Exception e) { 6891 fail(e.getMessage()); 6892 } 6893 } 6894 6895 @Test testRecordMessages_invalidMsg()6896 public void testRecordMessages_invalidMsg() throws RemoteException { 6897 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 6898 null /* groupKey */, false /* isSummary */); 6899 nb.setShortcutId(null); 6900 StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1, 6901 "testRecordMessages_invalidMsg", mUid, 0, nb.build(), 6902 UserHandle.getUserHandleForUid(mUid), null, 0); 6903 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 6904 6905 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 6906 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(), 6907 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6908 waitForIdle(); 6909 6910 assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid)); 6911 } 6912 6913 @Test testRecordMessages_invalidMsg_notMessageStyle()6914 public void testRecordMessages_invalidMsg_notMessageStyle() throws RemoteException { 6915 Notification.Builder nb = new Notification.Builder(mContext, 6916 mTestNotificationChannel.getId()) 6917 .setContentTitle("foo") 6918 .setShortcutId(null) 6919 .setSmallIcon(android.R.drawable.sym_def_app_icon) 6920 .setCategory(Notification.CATEGORY_MESSAGE); 6921 StatusBarNotification sbn = new StatusBarNotification(PKG_O, PKG_O, 1, 6922 "testRecordMessages_invalidMsg_notMessageStyle", mUid, 0, nb.build(), 6923 UserHandle.getUserHandleForUid(mUid), null, 0); 6924 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 6925 6926 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 6927 mBinderService.enqueueNotificationWithTag(PKG_O, PKG_O, nr.getSbn().getTag(), 6928 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6929 waitForIdle(); 6930 6931 // PKG_O is allowed to be in conversation space b/c of override in 6932 // TestableNotificationManagerService 6933 assertTrue(mBinderService.isInInvalidMsgState(PKG_O, mUid)); 6934 } 6935 6936 @Test testRecordMessages_validMsg()6937 public void testRecordMessages_validMsg() throws RemoteException { 6938 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 6939 null /* groupKey */, false /* isSummary */); 6940 nb.setShortcutId(null); 6941 StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1, 6942 "testRecordMessages_validMsg", mUid, 0, nb.build(), 6943 UserHandle.getUserHandleForUid(mUid), null, 0); 6944 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 6945 6946 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(), 6947 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6948 waitForIdle(); 6949 6950 assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid)); 6951 6952 nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 6953 "testRecordMessages_validMsg"); 6954 6955 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(), 6956 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6957 waitForIdle(); 6958 6959 assertFalse(mBinderService.isInInvalidMsgState(PKG_P, mUid)); 6960 } 6961 6962 @Test testRecordMessages_invalidMsg_afterValidMsg()6963 public void testRecordMessages_invalidMsg_afterValidMsg() throws RemoteException { 6964 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 6965 "testRecordMessages_invalidMsg_afterValidMsg_1"); 6966 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6967 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6968 waitForIdle(); 6969 assertTrue(mService.getNotificationRecord(nr.getKey()).isConversation()); 6970 6971 mBinderService.cancelAllNotifications(PKG, mUid); 6972 waitForIdle(); 6973 6974 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 6975 null /* groupKey */, false /* isSummary */); 6976 nb.setShortcutId(null); 6977 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 6978 "testRecordMessages_invalidMsg_afterValidMsg_2", mUid, 0, nb.build(), 6979 UserHandle.getUserHandleForUid(mUid), null, 0); 6980 nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 6981 6982 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 6983 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 6984 waitForIdle(); 6985 6986 assertFalse(mService.getNotificationRecord(nr.getKey()).isConversation()); 6987 } 6988 6989 @Test testCanPostFgsWhenOverLimit()6990 public void testCanPostFgsWhenOverLimit() throws RemoteException { 6991 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 6992 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 6993 i, null, false).getSbn(); 6994 mBinderService.enqueueNotificationWithTag(PKG, PKG, 6995 "testCanPostFgsWhenOverLimit", 6996 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 6997 } 6998 6999 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 7000 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 7001 mBinderService.enqueueNotificationWithTag(PKG, PKG, 7002 "testCanPostFgsWhenOverLimit - fgs over limit!", 7003 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 7004 7005 waitForIdle(); 7006 7007 StatusBarNotification[] notifs = 7008 mBinderService.getActiveNotifications(sbn.getPackageName()); 7009 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); 7010 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, 7011 mService.getNotificationRecordCount()); 7012 } 7013 7014 @Test testCannotPostNonFgsWhenOverLimit()7015 public void testCannotPostNonFgsWhenOverLimit() throws RemoteException { 7016 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 7017 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 7018 i, null, false).getSbn(); 7019 mBinderService.enqueueNotificationWithTag(PKG, PKG, 7020 "testCanPostFgsWhenOverLimit", 7021 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 7022 waitForIdle(); 7023 } 7024 7025 final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 7026 100, null, false).getSbn(); 7027 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 7028 mBinderService.enqueueNotificationWithTag(PKG, PKG, 7029 "testCanPostFgsWhenOverLimit - fgs over limit!", 7030 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 7031 7032 final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel, 7033 101, null, false).getSbn(); 7034 mBinderService.enqueueNotificationWithTag(PKG, PKG, 7035 "testCanPostFgsWhenOverLimit - non fgs over limit!", 7036 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId()); 7037 7038 waitForIdle(); 7039 7040 StatusBarNotification[] notifs = 7041 mBinderService.getActiveNotifications(sbn.getPackageName()); 7042 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); 7043 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, 7044 mService.getNotificationRecordCount()); 7045 } 7046 } 7047