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