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