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.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE; 22 import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.SHOW_IMMEDIATELY; 23 import static android.app.ActivityTaskManager.INVALID_TASK_ID; 24 import static android.app.Notification.EXTRA_ALLOW_DURING_SETUP; 25 import static android.app.Notification.FLAG_AUTO_CANCEL; 26 import static android.app.Notification.FLAG_BUBBLE; 27 import static android.app.Notification.FLAG_CAN_COLORIZE; 28 import static android.app.Notification.FLAG_FOREGROUND_SERVICE; 29 import static android.app.Notification.FLAG_NO_CLEAR; 30 import static android.app.Notification.FLAG_ONGOING_EVENT; 31 import static android.app.Notification.FLAG_USER_INITIATED_JOB; 32 import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE; 33 import static android.app.NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED; 34 import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL; 35 import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE; 36 import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED; 37 import static android.app.NotificationManager.EXTRA_BLOCKED_STATE; 38 import static android.app.NotificationManager.IMPORTANCE_DEFAULT; 39 import static android.app.NotificationManager.IMPORTANCE_HIGH; 40 import static android.app.NotificationManager.IMPORTANCE_LOW; 41 import static android.app.NotificationManager.IMPORTANCE_MAX; 42 import static android.app.NotificationManager.IMPORTANCE_NONE; 43 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS; 44 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS; 45 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT; 46 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE; 47 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 48 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS; 49 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; 50 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; 51 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; 52 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; 53 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; 54 import static android.app.PendingIntent.FLAG_IMMUTABLE; 55 import static android.app.PendingIntent.FLAG_MUTABLE; 56 import static android.app.PendingIntent.FLAG_ONE_SHOT; 57 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; 58 import static android.content.pm.PackageManager.FEATURE_TELECOM; 59 import static android.content.pm.PackageManager.FEATURE_WATCH; 60 import static android.content.pm.PackageManager.PERMISSION_DENIED; 61 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 62 import static android.os.Build.VERSION_CODES.O_MR1; 63 import static android.os.Build.VERSION_CODES.P; 64 import static android.os.PowerManager.PARTIAL_WAKE_LOCK; 65 import static android.os.PowerWhitelistManager.REASON_NOTIFICATION_SERVICE; 66 import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED; 67 import static android.os.UserHandle.USER_SYSTEM; 68 import static android.os.UserManager.USER_TYPE_FULL_SECONDARY; 69 import static android.os.UserManager.USER_TYPE_PROFILE_CLONE; 70 import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED; 71 import static android.service.notification.Adjustment.KEY_IMPORTANCE; 72 import static android.service.notification.Adjustment.KEY_USER_SENTIMENT; 73 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING; 74 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS; 75 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING; 76 import static android.service.notification.NotificationListenerService.REASON_CANCEL; 77 import static android.service.notification.NotificationListenerService.REASON_LOCKDOWN; 78 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; 79 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; 80 import static android.view.Display.DEFAULT_DISPLAY; 81 import static android.view.Display.INVALID_DISPLAY; 82 import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 83 84 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.FSI_FORCE_DEMOTE; 85 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI; 86 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.WAKE_LOCK_FOR_POSTING_NOTIFICATION; 87 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; 88 import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER; 89 import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER; 90 import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER; 91 import static com.android.server.notification.NotificationManagerService.DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE; 92 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_ADJUSTED; 93 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED; 94 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED; 95 96 import static com.google.common.truth.Truth.assertThat; 97 import static com.google.common.truth.Truth.assertWithMessage; 98 99 import static junit.framework.Assert.assertEquals; 100 import static junit.framework.Assert.assertFalse; 101 import static junit.framework.Assert.assertNotNull; 102 import static junit.framework.Assert.assertNotSame; 103 import static junit.framework.Assert.assertNull; 104 import static junit.framework.Assert.assertSame; 105 import static junit.framework.Assert.assertTrue; 106 import static junit.framework.Assert.fail; 107 108 import static org.junit.Assert.assertNotEquals; 109 import static org.junit.Assert.assertThrows; 110 import static org.mockito.ArgumentMatchers.isNull; 111 import static org.mockito.Matchers.anyBoolean; 112 import static org.mockito.Matchers.anyLong; 113 import static org.mockito.Matchers.anyString; 114 import static org.mockito.Matchers.eq; 115 import static org.mockito.Mockito.any; 116 import static org.mockito.Mockito.anyInt; 117 import static org.mockito.Mockito.atLeastOnce; 118 import static org.mockito.Mockito.clearInvocations; 119 import static org.mockito.Mockito.doAnswer; 120 import static org.mockito.Mockito.doNothing; 121 import static org.mockito.Mockito.doThrow; 122 import static org.mockito.Mockito.inOrder; 123 import static org.mockito.Mockito.mock; 124 import static org.mockito.Mockito.never; 125 import static org.mockito.Mockito.reset; 126 import static org.mockito.Mockito.spy; 127 import static org.mockito.Mockito.timeout; 128 import static org.mockito.Mockito.times; 129 import static org.mockito.Mockito.verify; 130 import static org.mockito.Mockito.verifyNoMoreInteractions; 131 import static org.mockito.Mockito.verifyZeroInteractions; 132 import static org.mockito.Mockito.when; 133 134 import static java.util.Collections.emptyList; 135 import static java.util.Collections.singletonList; 136 137 import android.Manifest; 138 import android.annotation.Nullable; 139 import android.annotation.SuppressLint; 140 import android.annotation.UserIdInt; 141 import android.app.ActivityManager; 142 import android.app.ActivityManagerInternal; 143 import android.app.AlarmManager; 144 import android.app.AppOpsManager; 145 import android.app.AutomaticZenRule; 146 import android.app.IActivityManager; 147 import android.app.INotificationManager; 148 import android.app.ITransientNotification; 149 import android.app.IUriGrantsManager; 150 import android.app.Notification; 151 import android.app.Notification.MessagingStyle.Message; 152 import android.app.NotificationChannel; 153 import android.app.NotificationChannelGroup; 154 import android.app.NotificationManager; 155 import android.app.PendingIntent; 156 import android.app.Person; 157 import android.app.RemoteInput; 158 import android.app.RemoteInputHistoryItem; 159 import android.app.StatsManager; 160 import android.app.admin.DevicePolicyManagerInternal; 161 import android.app.usage.UsageStatsManagerInternal; 162 import android.companion.AssociationInfo; 163 import android.companion.ICompanionDeviceManager; 164 import android.content.BroadcastReceiver; 165 import android.content.ComponentName; 166 import android.content.ContentUris; 167 import android.content.Context; 168 import android.content.IIntentSender; 169 import android.content.Intent; 170 import android.content.IntentFilter; 171 import android.content.pm.ActivityInfo; 172 import android.content.pm.ApplicationInfo; 173 import android.content.pm.IPackageManager; 174 import android.content.pm.LauncherApps; 175 import android.content.pm.PackageManager; 176 import android.content.pm.PackageManagerInternal; 177 import android.content.pm.ParceledListSlice; 178 import android.content.pm.ShortcutInfo; 179 import android.content.pm.ShortcutServiceInternal; 180 import android.content.pm.UserInfo; 181 import android.content.pm.VersionedPackage; 182 import android.content.res.Resources; 183 import android.graphics.Color; 184 import android.graphics.drawable.Icon; 185 import android.media.AudioManager; 186 import android.media.IRingtonePlayer; 187 import android.media.session.MediaSession; 188 import android.net.Uri; 189 import android.os.Binder; 190 import android.os.Build; 191 import android.os.Bundle; 192 import android.os.IBinder; 193 import android.os.Looper; 194 import android.os.Parcel; 195 import android.os.Parcelable; 196 import android.os.PowerManager; 197 import android.os.PowerManager.WakeLock; 198 import android.os.Process; 199 import android.os.RemoteException; 200 import android.os.SystemClock; 201 import android.os.UserHandle; 202 import android.os.UserManager; 203 import android.os.WorkSource; 204 import android.permission.PermissionManager; 205 import android.provider.DeviceConfig; 206 import android.provider.MediaStore; 207 import android.provider.Settings; 208 import android.service.notification.Adjustment; 209 import android.service.notification.ConversationChannelWrapper; 210 import android.service.notification.NotificationListenerFilter; 211 import android.service.notification.NotificationListenerService; 212 import android.service.notification.NotificationRankingUpdate; 213 import android.service.notification.NotificationStats; 214 import android.service.notification.StatusBarNotification; 215 import android.service.notification.ZenPolicy; 216 import android.telecom.TelecomManager; 217 import android.telephony.TelephonyManager; 218 import android.test.suitebuilder.annotation.SmallTest; 219 import android.testing.AndroidTestingRunner; 220 import android.testing.TestableLooper; 221 import android.testing.TestableLooper.RunWithLooper; 222 import android.testing.TestablePermissions; 223 import android.testing.TestableResources; 224 import android.text.Html; 225 import android.text.TextUtils; 226 import android.util.ArrayMap; 227 import android.util.ArraySet; 228 import android.util.AtomicFile; 229 import android.util.Pair; 230 import android.util.Xml; 231 import android.widget.RemoteViews; 232 233 import androidx.test.InstrumentationRegistry; 234 235 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; 236 import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.Flag; 237 import com.android.internal.config.sysui.TestableFlagResolver; 238 import com.android.internal.logging.InstanceIdSequence; 239 import com.android.internal.logging.InstanceIdSequenceFake; 240 import com.android.internal.messages.nano.SystemMessageProto; 241 import com.android.internal.statusbar.NotificationVisibility; 242 import com.android.modules.utils.TypedXmlPullParser; 243 import com.android.modules.utils.TypedXmlSerializer; 244 import com.android.server.DeviceIdleInternal; 245 import com.android.server.LocalServices; 246 import com.android.server.SystemService; 247 import com.android.server.SystemService.TargetUser; 248 import com.android.server.UiServiceTestCase; 249 import com.android.server.job.JobSchedulerInternal; 250 import com.android.server.lights.LightsManager; 251 import com.android.server.lights.LogicalLight; 252 import com.android.server.notification.NotificationManagerService.NotificationAssistants; 253 import com.android.server.notification.NotificationManagerService.NotificationListeners; 254 import com.android.server.notification.NotificationManagerService.PostNotificationTracker; 255 import com.android.server.notification.NotificationManagerService.PostNotificationTrackerFactory; 256 import com.android.server.pm.PackageManagerService; 257 import com.android.server.pm.UserManagerInternal; 258 import com.android.server.policy.PermissionPolicyInternal; 259 import com.android.server.statusbar.StatusBarManagerInternal; 260 import com.android.server.uri.UriGrantsManagerInternal; 261 import com.android.server.utils.quota.MultiRateLimiter; 262 import com.android.server.wm.ActivityTaskManagerInternal; 263 import com.android.server.wm.WindowManagerInternal; 264 265 import com.google.android.collect.Lists; 266 import com.google.common.collect.ImmutableList; 267 268 import org.junit.After; 269 import org.junit.Assert; 270 import org.junit.Before; 271 import org.junit.Test; 272 import org.junit.runner.RunWith; 273 import org.mockito.ArgumentCaptor; 274 import org.mockito.ArgumentMatcher; 275 import org.mockito.ArgumentMatchers; 276 import org.mockito.InOrder; 277 import org.mockito.Mock; 278 import org.mockito.MockitoAnnotations; 279 import org.mockito.invocation.InvocationOnMock; 280 import org.mockito.stubbing.Answer; 281 282 import java.io.BufferedInputStream; 283 import java.io.BufferedOutputStream; 284 import java.io.ByteArrayInputStream; 285 import java.io.ByteArrayOutputStream; 286 import java.io.File; 287 import java.io.FileOutputStream; 288 import java.util.ArrayList; 289 import java.util.Arrays; 290 import java.util.Collections; 291 import java.util.List; 292 import java.util.Map; 293 import java.util.concurrent.CountDownLatch; 294 import java.util.function.Consumer; 295 296 297 @SmallTest 298 @RunWith(AndroidTestingRunner.class) 299 @SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service. 300 @RunWithLooper 301 public class NotificationManagerServiceTest extends UiServiceTestCase { 302 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId"; 303 private static final String TEST_PACKAGE = "The.name.is.Package.Test.Package"; 304 private static final String PKG_NO_CHANNELS = "com.example.no.channels"; 305 private static final int TEST_TASK_ID = 1; 306 private static final int UID_HEADLESS = 1_000_000; 307 private static final int TOAST_DURATION = 2_000; 308 private static final int SECONDARY_DISPLAY_ID = 42; 309 310 private final int mUid = Binder.getCallingUid(); 311 private final @UserIdInt int mUserId = UserHandle.getUserId(mUid); 312 313 private TestableNotificationManagerService mService; 314 private INotificationManager mBinderService; 315 private NotificationManagerInternal mInternalService; 316 private ShortcutHelper mShortcutHelper; 317 @Mock 318 private IPackageManager mPackageManager; 319 @Mock 320 private PackageManager mPackageManagerClient; 321 @Mock 322 private PackageManagerInternal mPackageManagerInternal; 323 @Mock 324 private PermissionPolicyInternal mPermissionPolicyInternal; 325 @Mock 326 private WindowManagerInternal mWindowManagerInternal; 327 @Mock 328 private PermissionHelper mPermissionHelper; 329 private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake(); 330 private final String PKG = mContext.getPackageName(); 331 private TestableLooper mTestableLooper; 332 @Mock 333 private RankingHelper mRankingHelper; 334 @Mock private PreferencesHelper mPreferencesHelper; 335 AtomicFile mPolicyFile; 336 File mFile; 337 @Mock 338 private NotificationUsageStats mUsageStats; 339 @Mock 340 private UsageStatsManagerInternal mAppUsageStats; 341 @Mock 342 private AudioManager mAudioManager; 343 @Mock 344 private LauncherApps mLauncherApps; 345 @Mock 346 private ShortcutServiceInternal mShortcutServiceInternal; 347 @Mock 348 private UserManager mUserManager; 349 @Mock 350 ActivityManager mActivityManager; 351 @Mock 352 TelecomManager mTelecomManager; 353 @Mock 354 Resources mResources; 355 @Mock 356 RankingHandler mRankingHandler; 357 @Mock 358 ActivityManagerInternal mAmi; 359 @Mock 360 JobSchedulerInternal mJsi; 361 @Mock 362 private Looper mMainLooper; 363 @Mock 364 private NotificationManager mMockNm; 365 @Mock 366 private PermissionManager mPermissionManager; 367 @Mock 368 private DevicePolicyManagerInternal mDevicePolicyManager; 369 @Mock 370 private PowerManager mPowerManager; 371 private final ArrayList<WakeLock> mAcquiredWakeLocks = new ArrayList<>(); 372 private final TestPostNotificationTrackerFactory mPostNotificationTrackerFactory = 373 new TestPostNotificationTrackerFactory(); 374 375 @Mock 376 IIntentSender pi1; 377 378 private static final int MAX_POST_DELAY = 1000; 379 380 private NotificationChannel mTestNotificationChannel = new NotificationChannel( 381 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 382 383 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0; 384 385 private static final String VALID_CONVO_SHORTCUT_ID = "shortcut"; 386 private static final String SEARCH_SELECTOR_PKG = "searchSelector"; 387 @Mock 388 private NotificationListeners mListeners; 389 @Mock 390 private NotificationListenerFilter mNlf; 391 @Mock private NotificationAssistants mAssistants; 392 @Mock private ConditionProviders mConditionProviders; 393 private ManagedServices.ManagedServiceInfo mListener; 394 @Mock private ICompanionDeviceManager mCompanionMgr; 395 @Mock SnoozeHelper mSnoozeHelper; 396 @Mock GroupHelper mGroupHelper; 397 @Mock 398 IBinder mPermOwner; 399 @Mock 400 IActivityManager mAm; 401 @Mock 402 ActivityTaskManagerInternal mAtm; 403 @Mock 404 IUriGrantsManager mUgm; 405 @Mock 406 UriGrantsManagerInternal mUgmInternal; 407 @Mock 408 AppOpsManager mAppOpsManager; 409 private AppOpsManager.OnOpChangedListener mOnPermissionChangeListener; 410 @Mock 411 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback 412 mNotificationAssistantAccessGrantedCallback; 413 @Mock 414 UserManager mUm; 415 @Mock 416 UserManagerInternal mUmInternal; 417 @Mock 418 NotificationHistoryManager mHistoryManager; 419 @Mock 420 StatsManager mStatsManager; 421 @Mock 422 AlarmManager mAlarmManager; 423 @Mock 424 MultiRateLimiter mToastRateLimiter; 425 BroadcastReceiver mPackageIntentReceiver; 426 BroadcastReceiver mUserSwitchIntentReceiver; 427 NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); 428 TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker; 429 430 TestableFlagResolver mTestFlagResolver = new TestableFlagResolver(); 431 432 private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( 433 1 << 30); 434 @Mock 435 StatusBarManagerInternal mStatusBar; 436 437 private NotificationManagerService.WorkerHandler mWorkerHandler; 438 439 private class TestableToastCallback extends ITransientNotification.Stub { 440 @Override show(IBinder windowToken)441 public void show(IBinder windowToken) { 442 } 443 444 @Override hide()445 public void hide() { 446 } 447 } 448 449 private class TestPostNotificationTrackerFactory implements PostNotificationTrackerFactory { 450 451 private final List<PostNotificationTracker> mCreatedTrackers = new ArrayList<>(); 452 453 @Override newTracker(@ullable WakeLock optionalWakeLock)454 public PostNotificationTracker newTracker(@Nullable WakeLock optionalWakeLock) { 455 PostNotificationTracker tracker = PostNotificationTrackerFactory.super.newTracker( 456 optionalWakeLock); 457 mCreatedTrackers.add(tracker); 458 return tracker; 459 } 460 } 461 462 @Before setUp()463 public void setUp() throws Exception { 464 // Shell permisssions will override permissions of our app, so add all necessary permissions 465 // for this test here: 466 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( 467 "android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG", 468 "android.permission.READ_DEVICE_CONFIG", 469 "android.permission.READ_CONTACTS"); 470 471 MockitoAnnotations.initMocks(this); 472 473 DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class); 474 when(deviceIdleInternal.getNotificationAllowlistDuration()).thenReturn(3000L); 475 476 LocalServices.removeServiceForTest(UserManagerInternal.class); 477 LocalServices.addService(UserManagerInternal.class, mUmInternal); 478 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class); 479 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal); 480 LocalServices.removeServiceForTest(WindowManagerInternal.class); 481 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal); 482 LocalServices.removeServiceForTest(StatusBarManagerInternal.class); 483 LocalServices.addService(StatusBarManagerInternal.class, mStatusBar); 484 LocalServices.removeServiceForTest(DeviceIdleInternal.class); 485 LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal); 486 LocalServices.removeServiceForTest(ActivityManagerInternal.class); 487 LocalServices.addService(ActivityManagerInternal.class, mAmi); 488 LocalServices.removeServiceForTest(JobSchedulerInternal.class); 489 LocalServices.addService(JobSchedulerInternal.class, mJsi); 490 LocalServices.removeServiceForTest(PackageManagerInternal.class); 491 LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal); 492 LocalServices.removeServiceForTest(PermissionPolicyInternal.class); 493 LocalServices.addService(PermissionPolicyInternal.class, mPermissionPolicyInternal); 494 mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager); 495 mContext.addMockSystemService(NotificationManager.class, mMockNm); 496 497 doNothing().when(mContext).sendBroadcastAsUser(any(), any()); 498 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any()); 499 500 setDpmAppOppsExemptFromDismissal(false); 501 502 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, 503 mNotificationInstanceIdSequence); 504 505 // Use this testable looper. 506 mTestableLooper = TestableLooper.get(this); 507 // MockPackageManager - default returns ApplicationInfo with matching calling UID 508 mContext.setMockPackageManager(mPackageManagerClient); 509 510 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())) 511 .thenAnswer((Answer<ApplicationInfo>) invocation -> { 512 Object[] args = invocation.getArguments(); 513 return getApplicationInfo((String) args[0], mUid); 514 }); 515 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 516 .thenAnswer((Answer<ApplicationInfo>) invocation -> { 517 Object[] args = invocation.getArguments(); 518 return getApplicationInfo((String) args[0], mUid); 519 }); 520 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid); 521 when(mPackageManagerInternal.isSameApp(anyString(), anyInt(), anyInt())).thenAnswer( 522 (Answer<Boolean>) invocation -> { 523 Object[] args = invocation.getArguments(); 524 return (int) args[1] == mUid; 525 }); 526 final LightsManager mockLightsManager = mock(LightsManager.class); 527 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class)); 528 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); 529 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 530 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner); 531 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG}); 532 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG}); 533 when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())) 534 .thenReturn(INVALID_TASK_ID); 535 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class)); 536 when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0}); 537 538 when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(true); 539 540 ActivityManager.AppTask task = mock(ActivityManager.AppTask.class); 541 List<ActivityManager.AppTask> taskList = new ArrayList<>(); 542 ActivityManager.RecentTaskInfo taskInfo = new ActivityManager.RecentTaskInfo(); 543 taskInfo.taskId = TEST_TASK_ID; 544 when(task.getTaskInfo()).thenReturn(taskInfo); 545 taskList.add(task); 546 when(mAtm.getAppTasks(anyString(), anyInt())).thenReturn(taskList); 547 548 // write to a test file; the system file isn't readable from tests 549 mFile = new File(mContext.getCacheDir(), "test.xml"); 550 mFile.createNewFile(); 551 final String preupgradeXml = "<notification-policy></notification-policy>"; 552 mPolicyFile = new AtomicFile(mFile); 553 FileOutputStream fos = mPolicyFile.startWrite(); 554 fos.write(preupgradeXml.getBytes()); 555 mPolicyFile.finishWrite(fos); 556 557 // Setup managed services 558 when(mNlf.isTypeAllowed(anyInt())).thenReturn(true); 559 when(mNlf.isPackageAllowed(any())).thenReturn(true); 560 when(mNlf.isPackageAllowed(null)).thenReturn(true); 561 when(mListeners.getNotificationListenerFilter(any())).thenReturn(mNlf); 562 mListener = mListeners.new ManagedServiceInfo( 563 null, new ComponentName(PKG, "test_class"), 564 mUserId, true, null, 0, 123); 565 ComponentName defaultComponent = ComponentName.unflattenFromString("config/device"); 566 ArraySet<ComponentName> components = new ArraySet<>(); 567 components.add(defaultComponent); 568 when(mListeners.getDefaultComponents()).thenReturn(components); 569 when(mConditionProviders.getDefaultPackages()) 570 .thenReturn(new ArraySet<>(Arrays.asList("config"))); 571 when(mAssistants.getDefaultComponents()).thenReturn(components); 572 when(mAssistants.queryPackageForServices( 573 anyString(), anyInt(), anyInt())).thenReturn(components); 574 when(mListeners.checkServiceTokenLocked(null)).thenReturn(mListener); 575 ManagedServices.Config listenerConfig = new ManagedServices.Config(); 576 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS; 577 when(mListeners.getConfig()).thenReturn(listenerConfig); 578 ManagedServices.Config assistantConfig = new ManagedServices.Config(); 579 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS; 580 when(mAssistants.getConfig()).thenReturn(assistantConfig); 581 ManagedServices.Config dndConfig = new ManagedServices.Config(); 582 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS; 583 when(mConditionProviders.getConfig()).thenReturn(dndConfig); 584 585 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true); 586 587 // Use the real PowerManager to back up the mock w.r.t. creating WakeLocks. 588 // This is because 1) we need a mock to verify() calls and tracking the created WakeLocks, 589 // but 2) PowerManager and WakeLock perform their own checks (e.g. correct arguments, don't 590 // call release twice, etc) and we want the test to fail if such misuse happens, too. 591 PowerManager realPowerManager = mContext.getSystemService(PowerManager.class); 592 when(mPowerManager.newWakeLock(anyInt(), anyString())).then( 593 (Answer<WakeLock>) invocation -> { 594 WakeLock wl = realPowerManager.newWakeLock(invocation.getArgument(0), 595 invocation.getArgument(1)); 596 mAcquiredWakeLocks.add(wl); 597 return wl; 598 }); 599 mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true); 600 DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, 601 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "true", false); 602 603 // apps allowed as convos 604 mService.setStringArrayResourceValue(PKG_O); 605 606 TestableResources tr = mContext.getOrCreateTestableResources(); 607 tr.addOverride(com.android.internal.R.string.config_defaultSearchSelectorPackageName, 608 SEARCH_SELECTOR_PKG); 609 610 doAnswer(invocation -> { 611 mOnPermissionChangeListener = invocation.getArgument(2); 612 return null; 613 }).when(mAppOpsManager).startWatchingMode(eq(AppOpsManager.OP_POST_NOTIFICATION), any(), 614 any()); 615 when(mUmInternal.isUserInitialized(anyInt())).thenReturn(true); 616 617 mWorkerHandler = spy(mService.new WorkerHandler(mTestableLooper.getLooper())); 618 mService.init(mWorkerHandler, mRankingHandler, mPackageManager, mPackageManagerClient, 619 mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr, 620 mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAtm, 621 mAppUsageStats, mDevicePolicyManager, mUgm, mUgmInternal, 622 mAppOpsManager, mUm, mHistoryManager, mStatsManager, 623 mock(TelephonyManager.class), 624 mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class), 625 mTelecomManager, mLogger, mTestFlagResolver, mPermissionManager, 626 mPowerManager, mPostNotificationTrackerFactory); 627 // Return first true for RoleObserver main-thread check 628 when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false); 629 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper); 630 verify(mHistoryManager, never()).onBootPhaseAppsCanStart(); 631 mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START, mMainLooper); 632 verify(mHistoryManager).onBootPhaseAppsCanStart(); 633 634 mService.setAudioManager(mAudioManager); 635 636 mStrongAuthTracker = mService.new StrongAuthTrackerFake(mContext); 637 mService.setStrongAuthTracker(mStrongAuthTracker); 638 639 mShortcutHelper = mService.getShortcutHelper(); 640 mShortcutHelper.setLauncherApps(mLauncherApps); 641 mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal); 642 mShortcutHelper.setUserManager(mUserManager); 643 644 // Capture PackageIntentReceiver 645 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 646 ArgumentCaptor.forClass(BroadcastReceiver.class); 647 ArgumentCaptor<IntentFilter> intentFilterCaptor = 648 ArgumentCaptor.forClass(IntentFilter.class); 649 650 verify(mContext, atLeastOnce()).registerReceiverAsUser(broadcastReceiverCaptor.capture(), 651 any(), intentFilterCaptor.capture(), any(), any()); 652 verify(mContext, atLeastOnce()).registerReceiver(broadcastReceiverCaptor.capture(), 653 intentFilterCaptor.capture()); 654 List<BroadcastReceiver> broadcastReceivers = broadcastReceiverCaptor.getAllValues(); 655 List<IntentFilter> intentFilters = intentFilterCaptor.getAllValues(); 656 657 for (int i = 0; i < intentFilters.size(); i++) { 658 final IntentFilter filter = intentFilters.get(i); 659 if (filter.hasAction(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED) 660 && filter.hasAction(Intent.ACTION_PACKAGES_UNSUSPENDED) 661 && filter.hasAction(Intent.ACTION_PACKAGES_SUSPENDED)) { 662 mPackageIntentReceiver = broadcastReceivers.get(i); 663 } 664 if (filter.hasAction(Intent.ACTION_USER_SWITCHED)) { 665 mUserSwitchIntentReceiver = broadcastReceivers.get(i); 666 } 667 } 668 assertNotNull("package intent receiver should exist", mPackageIntentReceiver); 669 assertNotNull("User-switch receiver should exist", mUserSwitchIntentReceiver); 670 671 // Pretend the shortcut exists 672 List<ShortcutInfo> shortcutInfos = new ArrayList<>(); 673 ShortcutInfo info = mock(ShortcutInfo.class); 674 when(info.getPackage()).thenReturn(PKG); 675 when(info.getId()).thenReturn(VALID_CONVO_SHORTCUT_ID); 676 when(info.getUserId()).thenReturn(USER_SYSTEM); 677 when(info.isLongLived()).thenReturn(true); 678 when(info.isEnabled()).thenReturn(true); 679 shortcutInfos.add(info); 680 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos); 681 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), 682 anyString(), anyInt(), any())).thenReturn(true); 683 when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true); 684 mockIsUserVisible(DEFAULT_DISPLAY, true); 685 mockIsVisibleBackgroundUsersSupported(false); 686 687 // Set the testable bubble extractor 688 RankingHelper rankingHelper = mService.getRankingHelper(); 689 BubbleExtractor extractor = rankingHelper.findExtractor(BubbleExtractor.class); 690 extractor.setActivityManager(mActivityManager); 691 692 // Tests call directly into the Binder. 693 mBinderService = mService.getBinderService(); 694 mInternalService = mService.getInternalService(); 695 696 mBinderService.createNotificationChannels( 697 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 698 mBinderService.createNotificationChannels( 699 PKG_P, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 700 mBinderService.createNotificationChannels( 701 PKG_O, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 702 assertNotNull(mBinderService.getNotificationChannel( 703 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID)); 704 clearInvocations(mRankingHandler); 705 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 706 707 mTestFlagResolver.setFlagOverride(FSI_FORCE_DEMOTE, false); 708 mTestFlagResolver.setFlagOverride(SHOW_STICKY_HUN_FOR_DENIED_FSI, false); 709 710 var checker = mock(TestableNotificationManagerService.ComponentPermissionChecker.class); 711 mService.permissionChecker = checker; 712 when(checker.check(anyString(), anyInt(), anyInt(), anyBoolean())) 713 .thenReturn(PackageManager.PERMISSION_DENIED); 714 } 715 716 @After assertNotificationRecordLoggerCallsValid()717 public void assertNotificationRecordLoggerCallsValid() { 718 waitForIdle(); // Finish async work, including all logging calls done by Runnables. 719 for (NotificationRecordLoggerFake.CallRecord call : mNotificationRecordLogger.getCalls()) { 720 if (call.wasLogged) { 721 assertNotNull(call.event); 722 if (call.event == NOTIFICATION_POSTED || call.event == NOTIFICATION_UPDATED) { 723 assertThat(call.postDurationMillisLogged).isGreaterThan(0); 724 } else { 725 assertThat(call.postDurationMillisLogged).isNull(); 726 } 727 } 728 } 729 assertThat(mNotificationRecordLogger.getPendingLogs()).isEmpty(); 730 } 731 732 @After assertAllTrackersFinishedOrCancelled()733 public void assertAllTrackersFinishedOrCancelled() { 734 waitForIdle(); // Finish async work. 735 // Verify that no trackers were left dangling. 736 for (PostNotificationTracker tracker : mPostNotificationTrackerFactory.mCreatedTrackers) { 737 assertThat(tracker.isOngoing()).isFalse(); 738 } 739 mPostNotificationTrackerFactory.mCreatedTrackers.clear(); 740 } 741 742 @After assertAllWakeLocksReleased()743 public void assertAllWakeLocksReleased() { 744 waitForIdle(); // Finish async work. 745 for (WakeLock wakeLock : mAcquiredWakeLocks) { 746 assertThat(wakeLock.isHeld()).isFalse(); 747 } 748 } 749 750 @After tearDown()751 public void tearDown() throws Exception { 752 if (mFile != null) mFile.delete(); 753 clearDeviceConfig(); 754 755 try { 756 mService.onDestroy(); 757 } catch (IllegalStateException | IllegalArgumentException e) { 758 // can throw if a broadcast receiver was never registered 759 } 760 761 InstrumentationRegistry.getInstrumentation() 762 .getUiAutomation().dropShellPermissionIdentity(); 763 // Remove scheduled messages that would be processed when the test is already done, and 764 // could cause issues, for example, messages that remove/cancel shown toasts (this causes 765 // problematic interactions with mocks when they're no longer working as expected). 766 mWorkerHandler.removeCallbacksAndMessages(null); 767 } 768 simulatePackageSuspendBroadcast(boolean suspend, String pkg, int uid)769 private void simulatePackageSuspendBroadcast(boolean suspend, String pkg, 770 int uid) { 771 // mimics receive broadcast that package is (un)suspended 772 // but does not actually (un)suspend the package 773 final Bundle extras = new Bundle(); 774 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, 775 new String[]{pkg}); 776 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, new int[]{uid}); 777 778 final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED 779 : Intent.ACTION_PACKAGES_UNSUSPENDED; 780 final Intent intent = new Intent(action); 781 intent.putExtras(extras); 782 783 mPackageIntentReceiver.onReceive(getContext(), intent); 784 } 785 simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids)786 private void simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids) { 787 // mimics receive broadcast that package is (un)distracting 788 // but does not actually register that info with packagemanager 789 final Bundle extras = new Bundle(); 790 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgs); 791 extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, flag); 792 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uids); 793 794 final Intent intent = new Intent(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED); 795 intent.putExtras(extras); 796 797 mPackageIntentReceiver.onReceive(getContext(), intent); 798 } 799 generateResetComponentValues()800 private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() { 801 ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>(); 802 changed.put(true, new ArrayList<>()); 803 changed.put(false, new ArrayList<>()); 804 return changed; 805 } getApplicationInfo(String pkg, int uid)806 private ApplicationInfo getApplicationInfo(String pkg, int uid) { 807 final ApplicationInfo applicationInfo = new ApplicationInfo(); 808 applicationInfo.uid = uid; 809 switch (pkg) { 810 case PKG_N_MR1: 811 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1; 812 break; 813 case PKG_O: 814 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O; 815 break; 816 case PKG_P: 817 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P; 818 break; 819 default: 820 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; 821 break; 822 } 823 return applicationInfo; 824 } 825 waitForIdle()826 public void waitForIdle() { 827 mTestableLooper.processAllMessages(); 828 } 829 setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled, int pkgPref, boolean channelEnabled)830 private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled, 831 int pkgPref, boolean channelEnabled) { 832 Settings.Secure.putInt(mContext.getContentResolver(), 833 Settings.Secure.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0); 834 mService.mPreferencesHelper.updateBubblesEnabled(); 835 assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled( 836 mock(UserHandle.class))); 837 try { 838 mBinderService.setBubblesAllowed(pkg, uid, pkgPref); 839 } catch (RemoteException e) { 840 e.printStackTrace(); 841 } 842 mTestNotificationChannel.setAllowBubbles(channelEnabled); 843 } 844 generateSbn(String pkg, int uid, long postTime, int userId)845 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) { 846 Notification.Builder nb = new Notification.Builder(mContext, "a") 847 .setContentTitle("foo") 848 .setSmallIcon(android.R.drawable.sym_def_app_icon); 849 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, 850 "tag" + System.currentTimeMillis(), uid, 0, 851 nb.build(), new UserHandle(userId), null, postTime); 852 return sbn; 853 } 854 generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary)855 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, 856 String groupKey, boolean isSummary) { 857 return generateNotificationRecord(channel, id, "tag" + System.currentTimeMillis(), groupKey, 858 isSummary); 859 } 860 generateNotificationRecord(NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary)861 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, 862 String tag, String groupKey, boolean isSummary) { 863 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 864 .setContentTitle("foo") 865 .setSmallIcon(android.R.drawable.sym_def_app_icon) 866 .setGroup(groupKey) 867 .setGroupSummary(isSummary); 868 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, 869 tag, mUid, 0, 870 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 871 return new NotificationRecord(mContext, sbn, channel); 872 } 873 generateNotificationRecord(NotificationChannel channel)874 private NotificationRecord generateNotificationRecord(NotificationChannel channel) { 875 return generateNotificationRecord(channel, null); 876 } 877 generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender)878 private NotificationRecord generateNotificationRecord(NotificationChannel channel, 879 Notification.TvExtender extender) { 880 if (channel == null) { 881 channel = mTestNotificationChannel; 882 } 883 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 884 .setContentTitle("foo") 885 .setSmallIcon(android.R.drawable.sym_def_app_icon) 886 .addAction(new Notification.Action.Builder(null, "test", null).build()); 887 if (extender != null) { 888 nb.extend(extender); 889 } 890 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 891 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 892 return new NotificationRecord(mContext, sbn, channel); 893 } 894 generateNotificationRecord(NotificationChannel channel, int userId)895 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) { 896 return generateNotificationRecord(channel, 1, userId); 897 } 898 generateNotificationRecord(NotificationChannel channel, int id, int userId)899 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, 900 int userId) { 901 if (channel == null) { 902 channel = mTestNotificationChannel; 903 } 904 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 905 .setContentTitle("foo") 906 .setSmallIcon(android.R.drawable.sym_def_app_icon); 907 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0, 908 nb.build(), new UserHandle(userId), null, 0); 909 return new NotificationRecord(mContext, sbn, channel); 910 } 911 generateMessageBubbleNotifRecord(NotificationChannel channel, String tag)912 private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel, 913 String tag) { 914 return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false); 915 } 916 generateMessageBubbleNotifRecord(boolean addMetadata, NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary)917 private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata, 918 NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) { 919 if (channel == null) { 920 channel = mTestNotificationChannel; 921 } 922 if (tag == null) { 923 tag = "tag"; 924 } 925 Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary); 926 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, 927 tag, mUid, 0, 928 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 929 return new NotificationRecord(mContext, sbn, channel); 930 } 931 getSignalExtractorSideEffects()932 private Map<String, Answer> getSignalExtractorSideEffects() { 933 Map<String, Answer> answers = new ArrayMap<>(); 934 935 answers.put("override group key", invocationOnMock -> { 936 ((NotificationRecord) invocationOnMock.getArguments()[0]) 937 .setOverrideGroupKey("bananas"); 938 return null; 939 }); 940 answers.put("override people", invocationOnMock -> { 941 ((NotificationRecord) invocationOnMock.getArguments()[0]) 942 .setPeopleOverride(new ArrayList<>()); 943 return null; 944 }); 945 answers.put("snooze criteria", invocationOnMock -> { 946 ((NotificationRecord) invocationOnMock.getArguments()[0]) 947 .setSnoozeCriteria(new ArrayList<>()); 948 return null; 949 }); 950 answers.put("notification channel", invocationOnMock -> { 951 ((NotificationRecord) invocationOnMock.getArguments()[0]) 952 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW)); 953 return null; 954 }); 955 answers.put("badging", invocationOnMock -> { 956 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0]; 957 r.setShowBadge(!r.canShowBadge()); 958 return null; 959 }); 960 answers.put("bubbles", invocationOnMock -> { 961 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0]; 962 r.setAllowBubble(!r.canBubble()); 963 return null; 964 }); 965 answers.put("package visibility", invocationOnMock -> { 966 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride( 967 Notification.VISIBILITY_SECRET); 968 return null; 969 }); 970 971 return answers; 972 } 973 clearDeviceConfig()974 private void clearDeviceConfig() { 975 DeviceConfig.resetToDefaults( 976 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI); 977 } 978 setDefaultAssistantInDeviceConfig(String componentName)979 private void setDefaultAssistantInDeviceConfig(String componentName) { 980 DeviceConfig.setProperty( 981 DeviceConfig.NAMESPACE_SYSTEMUI, 982 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE, 983 componentName, 984 false); 985 } 986 getMessageStyleNotifBuilder(boolean addBubbleMetadata, String groupKey, boolean isSummary)987 private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata, 988 String groupKey, boolean isSummary) { 989 // Give it a person 990 Person person = new Person.Builder() 991 .setName("bubblebot") 992 .build(); 993 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); 994 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, 995 new Intent().setPackage(mContext.getPackageName()), 996 PendingIntent.FLAG_MUTABLE); 997 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); 998 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", 999 inputIntent).addRemoteInput(remoteInput) 1000 .build(); 1001 // Make it messaging style 1002 Notification.Builder nb = new Notification.Builder(mContext, 1003 mTestNotificationChannel.getId()) 1004 .setContentTitle("foo") 1005 .setStyle(new Notification.MessagingStyle(person) 1006 .setConversationTitle("Bubble Chat") 1007 .addMessage("Hello?", 1008 SystemClock.currentThreadTimeMillis() - 300000, person) 1009 .addMessage("Is it me you're looking for?", 1010 SystemClock.currentThreadTimeMillis(), person) 1011 ) 1012 .setActions(replyAction) 1013 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1014 .setShortcutId(VALID_CONVO_SHORTCUT_ID) 1015 .setGroupSummary(isSummary); 1016 if (groupKey != null) { 1017 nb.setGroup(groupKey); 1018 } 1019 if (addBubbleMetadata) { 1020 nb.setBubbleMetadata(getBubbleMetadata()); 1021 } 1022 return nb; 1023 } 1024 getBubbleMetadata()1025 private Notification.BubbleMetadata getBubbleMetadata() { 1026 PendingIntent pendingIntent = mock(PendingIntent.class); 1027 Intent intent = mock(Intent.class); 1028 when(pendingIntent.getIntent()).thenReturn(intent); 1029 when(pendingIntent.getTarget()).thenReturn(pi1); 1030 1031 ActivityInfo info = new ActivityInfo(); 1032 info.resizeMode = RESIZE_MODE_RESIZEABLE; 1033 when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info); 1034 1035 return new Notification.BubbleMetadata.Builder( 1036 pendingIntent, 1037 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon)) 1038 .build(); 1039 } 1040 addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)1041 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel) 1042 throws RemoteException { 1043 1044 String groupKey = "BUBBLE_GROUP"; 1045 1046 // Notification that has bubble metadata 1047 NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */, 1048 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */); 1049 1050 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.getSbn().getTag(), 1051 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(), 1052 nrBubble.getSbn().getUserId()); 1053 waitForIdle(); 1054 1055 // Make sure we are a bubble 1056 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 1057 assertEquals(1, notifsAfter.length); 1058 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0); 1059 1060 // Notification without bubble metadata 1061 NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */, 1062 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */); 1063 1064 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.getSbn().getTag(), 1065 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(), 1066 nrPlain.getSbn().getUserId()); 1067 waitForIdle(); 1068 1069 notifsAfter = mBinderService.getActiveNotifications(PKG); 1070 assertEquals(2, notifsAfter.length); 1071 1072 // Summary notification for both of those 1073 NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */, 1074 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */); 1075 1076 if (summaryAutoCancel) { 1077 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL; 1078 } 1079 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.getSbn().getTag(), 1080 nrSummary.getSbn().getId(), nrSummary.getSbn().getNotification(), 1081 nrSummary.getSbn().getUserId()); 1082 waitForIdle(); 1083 1084 notifsAfter = mBinderService.getActiveNotifications(PKG); 1085 assertEquals(3, notifsAfter.length); 1086 1087 return nrSummary; 1088 } 1089 1090 @Test testLimitTimeOutBroadcast()1091 public void testLimitTimeOutBroadcast() { 1092 NotificationChannel channel = new NotificationChannel("id", "name", 1093 NotificationManager.IMPORTANCE_HIGH); 1094 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 1095 .setContentTitle("foo") 1096 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1097 .setTimeoutAfter(1); 1098 1099 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 1100 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 1101 NotificationRecord r = new NotificationRecord(mContext, sbn, channel); 1102 1103 mService.scheduleTimeoutLocked(r); 1104 ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class); 1105 verify(mAlarmManager).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture()); 1106 assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME, 1107 captor.getValue().getIntent().getPackage()); 1108 } 1109 1110 @Test testDefaultAssistant_overrideDefault()1111 public void testDefaultAssistant_overrideDefault() { 1112 final int userId = mContext.getUserId(); 1113 final String testComponent = "package/class"; 1114 final List<UserInfo> userInfos = new ArrayList<>(); 1115 userInfos.add(new UserInfo(userId, "", 0)); 1116 final ArraySet<ComponentName> validAssistants = new ArraySet<>(); 1117 validAssistants.add(ComponentName.unflattenFromString(testComponent)); 1118 when(mActivityManager.isLowRamDevice()).thenReturn(false); 1119 when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt())) 1120 .thenReturn(validAssistants); 1121 when(mAssistants.getDefaultComponents()).thenReturn(validAssistants); 1122 when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos); 1123 1124 mService.setDefaultAssistantForUser(userId); 1125 1126 verify(mAssistants).setPackageOrComponentEnabled( 1127 eq(testComponent), eq(userId), eq(true), eq(true), eq(false)); 1128 } 1129 1130 @Test testCreateNotificationChannels_SingleChannel()1131 public void testCreateNotificationChannels_SingleChannel() throws Exception { 1132 final NotificationChannel channel = 1133 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1134 mBinderService.createNotificationChannels(PKG, 1135 new ParceledListSlice(Arrays.asList(channel))); 1136 final NotificationChannel createdChannel = 1137 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 1138 assertTrue(createdChannel != null); 1139 } 1140 1141 @Test testCreateNotificationChannels_NullChannelThrowsException()1142 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception { 1143 try { 1144 mBinderService.createNotificationChannels(PKG, 1145 new ParceledListSlice(Arrays.asList((Object[])null))); 1146 fail("Exception should be thrown immediately."); 1147 } catch (NullPointerException e) { 1148 // pass 1149 } 1150 } 1151 1152 @Test testCreateNotificationChannels_FirstChannelWithFgndTaskStartsPermDialog()1153 public void testCreateNotificationChannels_FirstChannelWithFgndTaskStartsPermDialog() 1154 throws Exception { 1155 when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID); 1156 final NotificationChannel channel = 1157 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1158 mBinderService.createNotificationChannels(PKG_NO_CHANNELS, 1159 new ParceledListSlice(Arrays.asList(channel))); 1160 verify(mWorkerHandler).post(eq(new NotificationManagerService 1161 .ShowNotificationPermissionPromptRunnable(PKG_NO_CHANNELS, 1162 mUserId, TEST_TASK_ID, mPermissionPolicyInternal))); 1163 } 1164 1165 @Test testCreateNotificationChannels_SecondChannelWithFgndTaskDoesntStartPermDialog()1166 public void testCreateNotificationChannels_SecondChannelWithFgndTaskDoesntStartPermDialog() 1167 throws Exception { 1168 when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID); 1169 assertTrue(mBinderService.getNumNotificationChannelsForPackage(PKG, mUid, true) > 0); 1170 1171 final NotificationChannel channel = 1172 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1173 mBinderService.createNotificationChannels(PKG, 1174 new ParceledListSlice(Arrays.asList(channel))); 1175 verify(mWorkerHandler, never()).post(any( 1176 NotificationManagerService.ShowNotificationPermissionPromptRunnable.class)); 1177 } 1178 1179 @Test testCreateNotificationChannels_FirstChannelWithBgndTaskDoesntStartPermDialog()1180 public void testCreateNotificationChannels_FirstChannelWithBgndTaskDoesntStartPermDialog() 1181 throws Exception { 1182 reset(mPermissionPolicyInternal); 1183 when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID); 1184 1185 final NotificationChannel channel = 1186 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1187 mBinderService.createNotificationChannels(PKG, 1188 new ParceledListSlice(Arrays.asList(channel))); 1189 1190 verify(mWorkerHandler, never()).post(any( 1191 NotificationManagerService.ShowNotificationPermissionPromptRunnable.class)); 1192 } 1193 1194 @Test testCreateNotificationChannels_TwoChannels()1195 public void testCreateNotificationChannels_TwoChannels() throws Exception { 1196 final NotificationChannel channel1 = 1197 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT); 1198 final NotificationChannel channel2 = 1199 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT); 1200 mBinderService.createNotificationChannels(PKG, 1201 new ParceledListSlice(Arrays.asList(channel1, channel2))); 1202 assertTrue(mBinderService.getNotificationChannel( 1203 PKG, mContext.getUserId(), PKG, "id1") != null); 1204 assertTrue(mBinderService.getNotificationChannel( 1205 PKG, mContext.getUserId(), PKG, "id2") != null); 1206 } 1207 1208 @Test testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()1209 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance() 1210 throws Exception { 1211 final NotificationChannel channel = 1212 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1213 mBinderService.createNotificationChannels(PKG, 1214 new ParceledListSlice(Arrays.asList(channel))); 1215 1216 // Recreating the channel doesn't throw, but ignores importance. 1217 final NotificationChannel dupeChannel = 1218 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 1219 mBinderService.createNotificationChannels(PKG, 1220 new ParceledListSlice(Arrays.asList(dupeChannel))); 1221 final NotificationChannel createdChannel = 1222 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 1223 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); 1224 } 1225 1226 @Test testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()1227 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance() 1228 throws Exception { 1229 final NotificationChannel channel = 1230 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1231 mBinderService.createNotificationChannels(PKG, 1232 new ParceledListSlice(Arrays.asList(channel))); 1233 1234 // Recreating with a lower importance is allowed to modify the channel. 1235 final NotificationChannel dupeChannel = 1236 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); 1237 mBinderService.createNotificationChannels(PKG, 1238 new ParceledListSlice(Arrays.asList(dupeChannel))); 1239 final NotificationChannel createdChannel = 1240 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 1241 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance()); 1242 } 1243 1244 @Test testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()1245 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated() 1246 throws Exception { 1247 final NotificationChannel channel = 1248 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1249 mBinderService.createNotificationChannels(PKG, 1250 new ParceledListSlice(Arrays.asList(channel))); 1251 1252 // The user modifies importance directly, can no longer be changed by the app. 1253 final NotificationChannel updatedChannel = 1254 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 1255 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel); 1256 1257 // Recreating with a lower importance leaves channel unchanged. 1258 final NotificationChannel dupeChannel = 1259 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); 1260 mBinderService.createNotificationChannels(PKG, 1261 new ParceledListSlice(Arrays.asList(dupeChannel))); 1262 final NotificationChannel createdChannel = 1263 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 1264 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance()); 1265 } 1266 1267 @Test testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()1268 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond() 1269 throws Exception { 1270 final NotificationChannel channel1 = 1271 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1272 final NotificationChannel channel2 = 1273 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 1274 mBinderService.createNotificationChannels(PKG, 1275 new ParceledListSlice(Arrays.asList(channel1, channel2))); 1276 final NotificationChannel createdChannel = 1277 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 1278 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); 1279 } 1280 1281 @Test testBlockedNotifications_suspended()1282 public void testBlockedNotifications_suspended() throws Exception { 1283 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true); 1284 1285 NotificationChannel channel = new NotificationChannel("id", "name", 1286 IMPORTANCE_HIGH); 1287 NotificationRecord r = generateNotificationRecord(channel); 1288 1289 // isBlocked is only used for user blocking, not app suspension 1290 assertFalse(mService.isRecordBlockedLocked(r)); 1291 } 1292 1293 @Test testBlockedNotifications_blockedChannel()1294 public void testBlockedNotifications_blockedChannel() throws Exception { 1295 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1296 1297 NotificationChannel channel = new NotificationChannel("id", "name", 1298 NotificationManager.IMPORTANCE_NONE); 1299 NotificationRecord r = generateNotificationRecord(channel); 1300 assertTrue(mService.isRecordBlockedLocked(r)); 1301 1302 mBinderService.createNotificationChannels( 1303 PKG, new ParceledListSlice(Arrays.asList(channel))); 1304 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn(); 1305 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1306 "testBlockedNotifications_blockedChannel", 1307 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1308 waitForIdle(); 1309 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1310 } 1311 1312 @Test testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()1313 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService() 1314 throws Exception { 1315 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1316 when(mAmi.applyForegroundServiceNotification( 1317 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY); 1318 1319 NotificationChannel channel = new NotificationChannel("blocked", "name", 1320 NotificationManager.IMPORTANCE_NONE); 1321 mBinderService.createNotificationChannels( 1322 PKG, new ParceledListSlice(Arrays.asList(channel))); 1323 1324 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn(); 1325 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1326 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 1327 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1328 waitForIdle(); 1329 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1330 assertEquals(IMPORTANCE_LOW, 1331 mService.getNotificationRecord(sbn.getKey()).getImportance()); 1332 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel( 1333 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1334 } 1335 1336 @Test testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()1337 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService() 1338 throws Exception { 1339 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1340 when(mAmi.applyForegroundServiceNotification( 1341 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY); 1342 1343 NotificationChannel channel = 1344 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH); 1345 mBinderService.createNotificationChannels( 1346 PKG, new ParceledListSlice(Arrays.asList(channel))); 1347 1348 NotificationChannel update = 1349 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); 1350 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); 1351 waitForIdle(); 1352 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 1353 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1354 1355 StatusBarNotification sbn = generateNotificationRecord(channel).getSbn(); 1356 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1357 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 1358 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1359 waitForIdle(); 1360 // The first time a foreground service notification is shown, we allow the channel 1361 // to be updated to allow it to be seen. 1362 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1363 assertEquals(IMPORTANCE_LOW, 1364 mService.getNotificationRecord(sbn.getKey()).getImportance()); 1365 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel( 1366 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1367 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); 1368 waitForIdle(); 1369 1370 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); 1371 update.setUserVisibleTaskShown(true); 1372 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); 1373 waitForIdle(); 1374 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 1375 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1376 1377 sbn = generateNotificationRecord(channel).getSbn(); 1378 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1379 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1380 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService", 1381 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1382 waitForIdle(); 1383 // The second time it is shown, we keep the user's preference. 1384 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1385 assertNull(mService.getNotificationRecord(sbn.getKey())); 1386 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 1387 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1388 } 1389 1390 @Test testBlockedNotifications_blockedChannelGroup()1391 public void testBlockedNotifications_blockedChannelGroup() throws Exception { 1392 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1393 mService.setPreferencesHelper(mPreferencesHelper); 1394 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())). 1395 thenReturn(true); 1396 1397 NotificationChannel channel = new NotificationChannel("id", "name", 1398 NotificationManager.IMPORTANCE_HIGH); 1399 channel.setGroup("something"); 1400 NotificationRecord r = generateNotificationRecord(channel); 1401 assertTrue(mService.isRecordBlockedLocked(r)); 1402 } 1403 1404 @Test testEnqueuedBlockedNotifications_blockedApp()1405 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception { 1406 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1407 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 1408 1409 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1410 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1411 "testEnqueuedBlockedNotifications_blockedApp", 1412 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1413 waitForIdle(); 1414 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1415 } 1416 1417 @Test testEnqueuedBlockedNotifications_blockedAppForegroundService()1418 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception { 1419 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1420 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 1421 when(mAmi.applyForegroundServiceNotification( 1422 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY); 1423 1424 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1425 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1426 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1427 "testEnqueuedBlockedNotifications_blockedAppForegroundService", 1428 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1429 waitForIdle(); 1430 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1431 assertNull(mService.getNotificationRecord(sbn.getKey())); 1432 } 1433 1434 /** 1435 * Confirm an application with the SEND_CATEGORY_CAR_NOTIFICATIONS permission on automotive 1436 * devices can use car categories. 1437 */ 1438 @Test testEnqueuedRestrictedNotifications_hasPermission()1439 public void testEnqueuedRestrictedNotifications_hasPermission() throws Exception { 1440 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 1441 .thenReturn(true); 1442 // SEND_CATEGORY_CAR_NOTIFICATIONS is a system-level permission that this test cannot 1443 // obtain. Mocking out enforce permission call to ensure notifications can be created when 1444 // permitted. 1445 doNothing().when(mContext).enforceCallingPermission( 1446 eq("android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"), anyString()); 1447 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 1448 Notification.CATEGORY_CAR_WARNING, 1449 Notification.CATEGORY_CAR_INFORMATION); 1450 int id = 0; 1451 for (String category: categories) { 1452 final StatusBarNotification sbn = 1453 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn(); 1454 sbn.getNotification().category = category; 1455 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1456 "testEnqueuedRestrictedNotifications_asSystem", 1457 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1458 } 1459 waitForIdle(); 1460 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length); 1461 } 1462 1463 1464 /** 1465 * Confirm restricted notification categories only apply to automotive. 1466 */ 1467 @Test testEnqueuedRestrictedNotifications_notAutomotive()1468 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception { 1469 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 1470 .thenReturn(false); 1471 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 1472 Notification.CATEGORY_CAR_WARNING, 1473 Notification.CATEGORY_CAR_INFORMATION); 1474 int id = 0; 1475 for (String category: categories) { 1476 final StatusBarNotification sbn = 1477 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn(); 1478 sbn.getNotification().category = category; 1479 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1480 "testEnqueuedRestrictedNotifications_notAutomotive", 1481 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1482 } 1483 waitForIdle(); 1484 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length); 1485 } 1486 1487 /** 1488 * Confirm if an application tries to use the car categories on a automotive device without the 1489 * SEND_CATEGORY_CAR_NOTIFICATIONS permission that a security exception will be thrown. 1490 */ 1491 @Test testEnqueuedRestrictedNotifications_noPermission()1492 public void testEnqueuedRestrictedNotifications_noPermission() throws Exception { 1493 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 1494 .thenReturn(true); 1495 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 1496 Notification.CATEGORY_CAR_WARNING, 1497 Notification.CATEGORY_CAR_INFORMATION); 1498 for (String category: categories) { 1499 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1500 sbn.getNotification().category = category; 1501 try { 1502 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1503 "testEnqueuedRestrictedNotifications_badUser", 1504 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1505 fail("Calls from non system apps should not allow use of restricted categories"); 1506 } catch (SecurityException e) { 1507 // pass 1508 } 1509 } 1510 waitForIdle(); 1511 assertEquals(0, mBinderService.getActiveNotifications(PKG).length); 1512 } 1513 1514 @Test testSetNotificationsEnabledForPackage_noChange()1515 public void testSetNotificationsEnabledForPackage_noChange() throws Exception { 1516 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 1517 mBinderService.setNotificationsEnabledForPackage(mContext.getPackageName(), mUid, true); 1518 1519 verify(mPermissionHelper, never()).setNotificationPermission( 1520 anyString(), anyInt(), anyBoolean(), anyBoolean()); 1521 } 1522 1523 @Test testSetNotificationsEnabledForPackage()1524 public void testSetNotificationsEnabledForPackage() throws Exception { 1525 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 1526 mBinderService.setNotificationsEnabledForPackage(mContext.getPackageName(), mUid, false); 1527 1528 verify(mPermissionHelper).setNotificationPermission( 1529 mContext.getPackageName(), mUserId, false, true); 1530 1531 verify(mAppOpsManager, never()).setMode(anyInt(), anyInt(), anyString(), anyInt()); 1532 List<NotificationChannelLoggerFake.CallRecord> calls = mLogger.getCalls(); 1533 Assert.assertEquals( 1534 NotificationChannelLogger.NotificationChannelEvent.APP_NOTIFICATIONS_BLOCKED, 1535 calls.get(calls.size() -1).event); 1536 } 1537 1538 @Test testBlockedNotifications_blockedByAssistant()1539 public void testBlockedNotifications_blockedByAssistant() throws Exception { 1540 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1541 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 1542 1543 NotificationChannel channel = new NotificationChannel("id", "name", 1544 NotificationManager.IMPORTANCE_HIGH); 1545 NotificationRecord r = generateNotificationRecord(channel); 1546 mService.addEnqueuedNotification(r); 1547 1548 Bundle bundle = new Bundle(); 1549 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE); 1550 Adjustment adjustment = new Adjustment( 1551 r.getSbn().getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier()); 1552 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 1553 1554 NotificationManagerService.PostNotificationRunnable runnable = 1555 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 1556 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 1557 runnable.run(); 1558 waitForIdle(); 1559 1560 verify(mUsageStats, never()).registerPostedByApp(any()); 1561 } 1562 1563 @Test testBlockedNotifications_blockedByUser()1564 public void testBlockedNotifications_blockedByUser() throws Exception { 1565 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1566 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 1567 1568 NotificationChannel channel = new NotificationChannel("id", "name", 1569 NotificationManager.IMPORTANCE_HIGH); 1570 NotificationRecord r = generateNotificationRecord(channel); 1571 mService.addEnqueuedNotification(r); 1572 1573 when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false); 1574 1575 NotificationManagerService.PostNotificationRunnable runnable = 1576 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 1577 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 1578 runnable.run(); 1579 waitForIdle(); 1580 1581 verify(mUsageStats).registerBlocked(any()); 1582 verify(mUsageStats, never()).registerPostedByApp(any()); 1583 } 1584 1585 @Test testEnqueueNotificationInternal_noChannel()1586 public void testEnqueueNotificationInternal_noChannel() throws Exception { 1587 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 1588 NotificationRecord nr = generateNotificationRecord( 1589 new NotificationChannel("did not create", "", IMPORTANCE_DEFAULT)); 1590 1591 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 1592 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 1593 waitForIdle(); 1594 1595 verify(mPermissionHelper).hasPermission(mUid); 1596 verify(mPermissionHelper, never()).hasPermission(Process.SYSTEM_UID); 1597 1598 reset(mPermissionHelper); 1599 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 1600 1601 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 1602 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 1603 waitForIdle(); 1604 1605 verify(mPermissionHelper).hasPermission(mUid); 1606 assertThat(mService.mChannelToastsSent).contains(mUid); 1607 } 1608 1609 @Test testEnqueueNotification_appBlocked()1610 public void testEnqueueNotification_appBlocked() throws Exception { 1611 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 1612 1613 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1614 "testEnqueueNotification_appBlocked", 0, 1615 generateNotificationRecord(null).getNotification(), 0); 1616 waitForIdle(); 1617 verify(mWorkerHandler, never()).post( 1618 any(NotificationManagerService.EnqueueNotificationRunnable.class)); 1619 } 1620 1621 @Test testEnqueueNotificationWithTag_PopulatesGetActiveNotifications()1622 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception { 1623 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1624 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1625 generateNotificationRecord(null).getNotification(), 0); 1626 waitForIdle(); 1627 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 1628 assertEquals(1, notifs.length); 1629 assertEquals(1, mService.getNotificationRecordCount()); 1630 } 1631 1632 @Test testEnqueueNotificationWithTag_WritesExpectedLogs()1633 public void testEnqueueNotificationWithTag_WritesExpectedLogs() throws Exception { 1634 final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog"; 1635 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1636 generateNotificationRecord(null).getNotification(), 0); 1637 waitForIdle(); 1638 assertEquals(1, mNotificationRecordLogger.numCalls()); 1639 1640 NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0); 1641 assertTrue(call.wasLogged); 1642 assertEquals(NOTIFICATION_POSTED, call.event); 1643 assertNotNull(call.r); 1644 assertNull(call.old); 1645 assertEquals(0, call.position); 1646 assertEquals(0, call.buzzBeepBlink); 1647 assertEquals(PKG, call.r.getSbn().getPackageName()); 1648 assertEquals(0, call.r.getSbn().getId()); 1649 assertEquals(tag, call.r.getSbn().getTag()); 1650 assertEquals(1, call.getInstanceId()); // Fake instance IDs are assigned in order 1651 assertThat(call.postDurationMillisLogged).isGreaterThan(0); 1652 } 1653 1654 @Test testEnqueueNotificationWithTag_LogsOnMajorUpdates()1655 public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception { 1656 final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates"; 1657 Notification original = new Notification.Builder(mContext, 1658 mTestNotificationChannel.getId()) 1659 .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); 1660 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0); 1661 Notification update = new Notification.Builder(mContext, 1662 mTestNotificationChannel.getId()) 1663 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1664 .setCategory(Notification.CATEGORY_ALARM).build(); 1665 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0); 1666 waitForIdle(); 1667 assertEquals(2, mNotificationRecordLogger.numCalls()); 1668 1669 assertTrue(mNotificationRecordLogger.get(0).wasLogged); 1670 assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0)); 1671 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 1672 assertThat(mNotificationRecordLogger.get(0).postDurationMillisLogged).isGreaterThan(0); 1673 1674 assertTrue(mNotificationRecordLogger.get(1).wasLogged); 1675 assertEquals(NOTIFICATION_UPDATED, mNotificationRecordLogger.event(1)); 1676 // Instance ID doesn't change on update of an active notification 1677 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); 1678 assertThat(mNotificationRecordLogger.get(1).postDurationMillisLogged).isGreaterThan(0); 1679 } 1680 1681 @Test testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate()1682 public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate() throws Exception { 1683 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate"; 1684 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1685 generateNotificationRecord(null).getNotification(), 0); 1686 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1687 generateNotificationRecord(null).getNotification(), 0); 1688 waitForIdle(); 1689 assertEquals(2, mNotificationRecordLogger.numCalls()); 1690 assertTrue(mNotificationRecordLogger.get(0).wasLogged); 1691 assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0)); 1692 assertFalse(mNotificationRecordLogger.get(1).wasLogged); 1693 assertNull(mNotificationRecordLogger.event(1)); 1694 } 1695 1696 @Test testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate()1697 public void testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate() throws Exception { 1698 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate"; 1699 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1700 generateNotificationRecord(null).getNotification(), 1701 0); 1702 final Notification notif = generateNotificationRecord(null).getNotification(); 1703 notif.extras.putString(Notification.EXTRA_TITLE, "Changed title"); 1704 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notif, 0); 1705 waitForIdle(); 1706 assertEquals(2, mNotificationRecordLogger.numCalls()); 1707 assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0)); 1708 assertNull(mNotificationRecordLogger.event(1)); 1709 } 1710 1711 @Test testEnqueueNotificationWithTag_LogsAgainAfterCancel()1712 public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception { 1713 final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel"; 1714 Notification notification = new Notification.Builder(mContext, 1715 mTestNotificationChannel.getId()) 1716 .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); 1717 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0); 1718 waitForIdle(); 1719 mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0); 1720 waitForIdle(); 1721 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0); 1722 waitForIdle(); 1723 assertEquals(3, mNotificationRecordLogger.numCalls()); 1724 1725 assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0)); 1726 assertTrue(mNotificationRecordLogger.get(0).wasLogged); 1727 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 1728 assertThat(mNotificationRecordLogger.get(0).postDurationMillisLogged).isGreaterThan(0); 1729 1730 assertEquals( 1731 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL, 1732 mNotificationRecordLogger.event(1)); 1733 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); 1734 // Cancel is not post, so no logged post_duration_millis. 1735 assertThat(mNotificationRecordLogger.get(1).postDurationMillisLogged).isNull(); 1736 1737 assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(2)); 1738 assertTrue(mNotificationRecordLogger.get(2).wasLogged); 1739 // New instance ID because notification was canceled before re-post 1740 assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId()); 1741 assertThat(mNotificationRecordLogger.get(2).postDurationMillisLogged).isGreaterThan(0); 1742 } 1743 1744 @Test testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed()1745 public void testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed() throws Exception { 1746 when(mAmi.applyForegroundServiceNotification( 1747 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY); 1748 mContext.getTestablePermissions().setPermission( 1749 android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_GRANTED); 1750 1751 final String tag = "testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed"; 1752 1753 Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId()) 1754 .setContentTitle("foo") 1755 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1756 .setFlag(FLAG_FOREGROUND_SERVICE, true) 1757 .build(); 1758 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, tag, mUid, 0, 1759 n, UserHandle.getUserHandleForUid(mUid), null, 0); 1760 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 1761 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1762 waitForIdle(); 1763 1764 StatusBarNotification[] notifs = 1765 mBinderService.getActiveNotifications(PKG); 1766 assertThat(notifs[0].getNotification().flags).isEqualTo( 1767 FLAG_FOREGROUND_SERVICE | FLAG_CAN_COLORIZE | FLAG_NO_CLEAR); 1768 } 1769 1770 @Test testEnqueueNotificationWithTag_nullAction_fixed()1771 public void testEnqueueNotificationWithTag_nullAction_fixed() throws Exception { 1772 Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId()) 1773 .setContentTitle("foo") 1774 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1775 .addAction(new Notification.Action.Builder(null, "one", null).build()) 1776 .addAction(new Notification.Action.Builder(null, "two", null).build()) 1777 .addAction(new Notification.Action.Builder(null, "three", null).build()) 1778 .build(); 1779 n.actions[1] = null; 1780 1781 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, 0); 1782 waitForIdle(); 1783 1784 StatusBarNotification[] posted = mBinderService.getActiveNotifications(PKG); 1785 assertThat(posted).hasLength(1); 1786 assertThat(posted[0].getNotification().actions).hasLength(2); 1787 assertThat(posted[0].getNotification().actions[0].title.toString()).isEqualTo("one"); 1788 assertThat(posted[0].getNotification().actions[1].title.toString()).isEqualTo("three"); 1789 } 1790 1791 @Test testEnqueueNotificationWithTag_allNullActions_fixed()1792 public void testEnqueueNotificationWithTag_allNullActions_fixed() throws Exception { 1793 Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId()) 1794 .setContentTitle("foo") 1795 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1796 .addAction(new Notification.Action.Builder(null, "one", null).build()) 1797 .addAction(new Notification.Action.Builder(null, "two", null).build()) 1798 .build(); 1799 n.actions[0] = null; 1800 n.actions[1] = null; 1801 1802 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, 0); 1803 waitForIdle(); 1804 1805 StatusBarNotification[] posted = mBinderService.getActiveNotifications(PKG); 1806 assertThat(posted).hasLength(1); 1807 assertThat(posted[0].getNotification().actions).isNull(); 1808 } 1809 1810 @Test enqueueNotificationWithTag_usesAndFinishesTracker()1811 public void enqueueNotificationWithTag_usesAndFinishesTracker() throws Exception { 1812 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1813 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1814 generateNotificationRecord(null).getNotification(), 0); 1815 1816 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1); 1817 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isTrue(); 1818 1819 waitForIdle(); 1820 1821 assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(1); 1822 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1); 1823 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse(); 1824 } 1825 1826 @Test enqueueNotificationWithTag_throws_usesAndCancelsTracker()1827 public void enqueueNotificationWithTag_throws_usesAndCancelsTracker() throws Exception { 1828 // Simulate not enqueued due to rejected inputs. 1829 assertThrows(Exception.class, 1830 () -> mBinderService.enqueueNotificationWithTag(PKG, PKG, 1831 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1832 /* notification= */ null, 0)); 1833 1834 waitForIdle(); 1835 1836 assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0); 1837 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1); 1838 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse(); 1839 } 1840 1841 @Test enqueueNotificationWithTag_notEnqueued_usesAndCancelsTracker()1842 public void enqueueNotificationWithTag_notEnqueued_usesAndCancelsTracker() throws Exception { 1843 // Simulate not enqueued due to snoozing inputs. 1844 when(mSnoozeHelper.getSnoozeContextForUnpostedNotification(anyInt(), any(), any())) 1845 .thenReturn("zzzzzzz"); 1846 1847 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1848 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1849 generateNotificationRecord(null).getNotification(), 0); 1850 waitForIdle(); 1851 1852 assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0); 1853 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1); 1854 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse(); 1855 } 1856 1857 @Test enqueueNotificationWithTag_notPosted_usesAndCancelsTracker()1858 public void enqueueNotificationWithTag_notPosted_usesAndCancelsTracker() throws Exception { 1859 // Simulate not posted due to blocked app. 1860 when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false); 1861 1862 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1863 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1864 generateNotificationRecord(null).getNotification(), 0); 1865 waitForIdle(); 1866 1867 assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0); 1868 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1); 1869 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse(); 1870 } 1871 1872 @Test enqueueNotification_acquiresAndReleasesWakeLock()1873 public void enqueueNotification_acquiresAndReleasesWakeLock() throws Exception { 1874 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1875 "enqueueNotification_acquiresAndReleasesWakeLock", 0, 1876 generateNotificationRecord(null).getNotification(), 0); 1877 1878 verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString()); 1879 assertThat(mAcquiredWakeLocks).hasSize(1); 1880 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue(); 1881 1882 waitForIdle(); 1883 1884 assertThat(mAcquiredWakeLocks).hasSize(1); 1885 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse(); 1886 } 1887 1888 @Test enqueueNotification_throws_acquiresAndReleasesWakeLock()1889 public void enqueueNotification_throws_acquiresAndReleasesWakeLock() throws Exception { 1890 // Simulate not enqueued due to rejected inputs. 1891 assertThrows(Exception.class, 1892 () -> mBinderService.enqueueNotificationWithTag(PKG, PKG, 1893 "enqueueNotification_throws_acquiresAndReleasesWakeLock", 0, 1894 /* notification= */ null, 0)); 1895 1896 verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString()); 1897 assertThat(mAcquiredWakeLocks).hasSize(1); 1898 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse(); 1899 } 1900 1901 @Test enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock()1902 public void enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock() throws Exception { 1903 // Simulate not enqueued due to snoozing inputs. 1904 when(mSnoozeHelper.getSnoozeContextForUnpostedNotification(anyInt(), any(), any())) 1905 .thenReturn("zzzzzzz"); 1906 1907 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1908 "enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock", 0, 1909 generateNotificationRecord(null).getNotification(), 0); 1910 1911 verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString()); 1912 assertThat(mAcquiredWakeLocks).hasSize(1); 1913 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue(); 1914 1915 waitForIdle(); 1916 1917 assertThat(mAcquiredWakeLocks).hasSize(1); 1918 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse(); 1919 } 1920 1921 @Test enqueueNotification_notPosted_acquiresAndReleasesWakeLock()1922 public void enqueueNotification_notPosted_acquiresAndReleasesWakeLock() throws Exception { 1923 // Simulate enqueued but not posted due to missing small icon. 1924 Notification notif = new Notification.Builder(mContext, mTestNotificationChannel.getId()) 1925 .setContentTitle("foo") 1926 .build(); 1927 1928 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1929 "enqueueNotification_notPosted_acquiresAndReleasesWakeLock", 0, 1930 notif, 0); 1931 1932 verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString()); 1933 assertThat(mAcquiredWakeLocks).hasSize(1); 1934 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue(); 1935 1936 waitForIdle(); 1937 1938 // NLSes were not called. 1939 verify(mListeners, never()).prepareNotifyPostedLocked(any(), any(), anyBoolean()); 1940 1941 assertThat(mAcquiredWakeLocks).hasSize(1); 1942 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse(); 1943 } 1944 1945 @Test enqueueNotification_setsWakeLockWorkSource()1946 public void enqueueNotification_setsWakeLockWorkSource() throws Exception { 1947 // Use a "full" mock for the PowerManager (instead of the one that delegates to the real 1948 // service) so we can return a mocked WakeLock that we can verify() on. 1949 reset(mPowerManager); 1950 WakeLock wakeLock = mock(WakeLock.class); 1951 when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(wakeLock); 1952 1953 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1954 "enqueueNotification_setsWakeLockWorkSource", 0, 1955 generateNotificationRecord(null).getNotification(), 0); 1956 waitForIdle(); 1957 1958 InOrder inOrder = inOrder(mPowerManager, wakeLock); 1959 inOrder.verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString()); 1960 inOrder.verify(wakeLock).setWorkSource(eq(new WorkSource(mUid, PKG))); 1961 inOrder.verify(wakeLock).acquire(anyLong()); 1962 inOrder.verify(wakeLock).release(); 1963 inOrder.verifyNoMoreInteractions(); 1964 } 1965 1966 @Test enqueueNotification_wakeLockSystemPropertyOff_noWakeLock()1967 public void enqueueNotification_wakeLockSystemPropertyOff_noWakeLock() throws Exception { 1968 mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, false); 1969 DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, 1970 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "true", false); 1971 1972 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1973 "enqueueNotification_setsWakeLockWorkSource", 0, 1974 generateNotificationRecord(null).getNotification(), 0); 1975 waitForIdle(); 1976 1977 verifyZeroInteractions(mPowerManager); 1978 } 1979 1980 @Test enqueueNotification_wakeLockDeviceConfigOff_noWakeLock()1981 public void enqueueNotification_wakeLockDeviceConfigOff_noWakeLock() throws Exception { 1982 mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true); 1983 DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, 1984 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "false", false); 1985 1986 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1987 "enqueueNotification_setsWakeLockWorkSource", 0, 1988 generateNotificationRecord(null).getNotification(), 0); 1989 waitForIdle(); 1990 1991 verifyZeroInteractions(mPowerManager); 1992 } 1993 1994 @Test testCancelNonexistentNotification()1995 public void testCancelNonexistentNotification() throws Exception { 1996 mBinderService.cancelNotificationWithTag(PKG, PKG, 1997 "testCancelNonexistentNotification", 0, 0); 1998 waitForIdle(); 1999 // The notification record logger doesn't even get called when a nonexistent notification 2000 // is cancelled, because that happens very frequently and is not interesting. 2001 assertEquals(0, mNotificationRecordLogger.numCalls()); 2002 } 2003 2004 @Test testCancelNotificationImmediatelyAfterEnqueue()2005 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception { 2006 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2007 "testCancelNotificationImmediatelyAfterEnqueue", 0, 2008 generateNotificationRecord(null).getNotification(), 0); 2009 mBinderService.cancelNotificationWithTag(PKG, PKG, 2010 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0); 2011 waitForIdle(); 2012 StatusBarNotification[] notifs = 2013 mBinderService.getActiveNotifications(PKG); 2014 assertEquals(0, notifs.length); 2015 assertEquals(0, mService.getNotificationRecordCount()); 2016 } 2017 2018 @Test testPostCancelPostNotifiesListeners()2019 public void testPostCancelPostNotifiesListeners() throws Exception { 2020 // WHEN a notification is posted 2021 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2022 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), 2023 sbn.getNotification(), sbn.getUserId()); 2024 mTestableLooper.moveTimeForward(1); 2025 // THEN it is canceled 2026 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); 2027 mTestableLooper.moveTimeForward(1); 2028 // THEN it is posted again (before the cancel has a chance to finish) 2029 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), 2030 sbn.getNotification(), sbn.getUserId()); 2031 // THEN the later enqueue isn't swallowed by the cancel. I.e., ordering is respected 2032 waitForIdle(); 2033 2034 // The final enqueue made it to the listener instead of being canceled 2035 StatusBarNotification[] notifs = 2036 mBinderService.getActiveNotifications(PKG); 2037 assertEquals(1, notifs.length); 2038 assertEquals(1, mService.getNotificationRecordCount()); 2039 } 2040 2041 @Test testCancelNotificationWhilePostedAndEnqueued()2042 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception { 2043 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2044 "testCancelNotificationWhilePostedAndEnqueued", 0, 2045 generateNotificationRecord(null).getNotification(), 0); 2046 waitForIdle(); 2047 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2048 "testCancelNotificationWhilePostedAndEnqueued", 0, 2049 generateNotificationRecord(null).getNotification(), 0); 2050 mBinderService.cancelNotificationWithTag(PKG, PKG, 2051 "testCancelNotificationWhilePostedAndEnqueued", 0, 0); 2052 waitForIdle(); 2053 StatusBarNotification[] notifs = 2054 mBinderService.getActiveNotifications(PKG); 2055 assertEquals(0, notifs.length); 2056 assertEquals(0, mService.getNotificationRecordCount()); 2057 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 2058 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture()); 2059 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface()); 2060 } 2061 2062 @Test testCancelNotificationsFromListenerImmediatelyAfterEnqueue()2063 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception { 2064 NotificationRecord r = generateNotificationRecord(null); 2065 final StatusBarNotification sbn = r.getSbn(); 2066 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2067 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue", 2068 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2069 mBinderService.cancelNotificationsFromListener(null, null); 2070 waitForIdle(); 2071 StatusBarNotification[] notifs = 2072 mBinderService.getActiveNotifications(sbn.getPackageName()); 2073 assertEquals(0, notifs.length); 2074 assertEquals(0, mService.getNotificationRecordCount()); 2075 } 2076 2077 @Test testCancelAllNotificationsImmediatelyAfterEnqueue()2078 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception { 2079 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2080 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2081 "testCancelAllNotificationsImmediatelyAfterEnqueue", 2082 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2083 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2084 waitForIdle(); 2085 StatusBarNotification[] notifs = 2086 mBinderService.getActiveNotifications(sbn.getPackageName()); 2087 assertEquals(0, notifs.length); 2088 assertEquals(0, mService.getNotificationRecordCount()); 2089 } 2090 2091 @Test testUserInitiatedClearAll_noLeak()2092 public void testUserInitiatedClearAll_noLeak() throws Exception { 2093 final NotificationRecord n = generateNotificationRecord( 2094 mTestNotificationChannel, 1, "group", true); 2095 2096 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2097 "testUserInitiatedClearAll_noLeak", 2098 n.getSbn().getId(), n.getSbn().getNotification(), n.getSbn().getUserId()); 2099 waitForIdle(); 2100 2101 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 2102 n.getUserId()); 2103 waitForIdle(); 2104 StatusBarNotification[] notifs = 2105 mBinderService.getActiveNotifications(n.getSbn().getPackageName()); 2106 assertEquals(0, notifs.length); 2107 assertEquals(0, mService.getNotificationRecordCount()); 2108 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 2109 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture()); 2110 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface()); 2111 } 2112 2113 @Test testCancelAllNotificationsCancelsChildren()2114 public void testCancelAllNotificationsCancelsChildren() throws Exception { 2115 final NotificationRecord parent = generateNotificationRecord( 2116 mTestNotificationChannel, 1, "group1", true); 2117 final NotificationRecord child = generateNotificationRecord( 2118 mTestNotificationChannel, 2, "group1", false); 2119 2120 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2121 "testCancelAllNotificationsCancelsChildren", 2122 parent.getSbn().getId(), parent.getSbn().getNotification(), 2123 parent.getSbn().getUserId()); 2124 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2125 "testCancelAllNotificationsCancelsChildren", 2126 child.getSbn().getId(), child.getSbn().getNotification(), 2127 child.getSbn().getUserId()); 2128 waitForIdle(); 2129 2130 mBinderService.cancelAllNotifications(PKG, parent.getSbn().getUserId()); 2131 waitForIdle(); 2132 assertEquals(0, mService.getNotificationRecordCount()); 2133 } 2134 2135 @Test testCancelAllNotificationsMultipleEnqueuedDoesNotCrash()2136 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception { 2137 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2138 for (int i = 0; i < 10; i++) { 2139 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2140 "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash", 2141 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2142 } 2143 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2144 waitForIdle(); 2145 2146 assertEquals(0, mService.getNotificationRecordCount()); 2147 } 2148 2149 @Test testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash()2150 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception { 2151 final NotificationRecord parent = generateNotificationRecord( 2152 mTestNotificationChannel, 1, "group1", true); 2153 final NotificationRecord parentAsChild = generateNotificationRecord( 2154 mTestNotificationChannel, 1, "group1", false); 2155 final NotificationRecord child = generateNotificationRecord( 2156 mTestNotificationChannel, 2, "group1", false); 2157 2158 // fully post parent notification 2159 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2160 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", 2161 parent.getSbn().getId(), parent.getSbn().getNotification(), 2162 parent.getSbn().getUserId()); 2163 waitForIdle(); 2164 2165 // enqueue the child several times 2166 for (int i = 0; i < 10; i++) { 2167 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2168 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", 2169 child.getSbn().getId(), child.getSbn().getNotification(), 2170 child.getSbn().getUserId()); 2171 } 2172 // make the parent a child, which will cancel the child notification 2173 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2174 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", 2175 parentAsChild.getSbn().getId(), parentAsChild.getSbn().getNotification(), 2176 parentAsChild.getSbn().getUserId()); 2177 waitForIdle(); 2178 2179 assertEquals(0, mService.getNotificationRecordCount()); 2180 } 2181 2182 @Test testAutobundledSummary_notificationAdded()2183 public void testAutobundledSummary_notificationAdded() { 2184 NotificationRecord summary = 2185 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true); 2186 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY; 2187 mService.addNotification(summary); 2188 mService.mSummaryByGroupKey.put("pkg", summary); 2189 mService.mAutobundledSummaries.put(0, new ArrayMap<>()); 2190 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey()); 2191 2192 mService.updateAutobundledSummaryFlags( 2193 0, "pkg", GroupHelper.BASE_FLAGS | FLAG_ONGOING_EVENT, false); 2194 waitForIdle(); 2195 2196 assertTrue(summary.getSbn().isOngoing()); 2197 } 2198 2199 @Test testAutobundledSummary_notificationRemoved()2200 public void testAutobundledSummary_notificationRemoved() { 2201 NotificationRecord summary = 2202 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true); 2203 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY; 2204 summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 2205 mService.addNotification(summary); 2206 mService.mAutobundledSummaries.put(0, new ArrayMap<>()); 2207 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey()); 2208 mService.mSummaryByGroupKey.put("pkg", summary); 2209 2210 mService.updateAutobundledSummaryFlags(0, "pkg", GroupHelper.BASE_FLAGS, false); 2211 waitForIdle(); 2212 2213 assertFalse(summary.getSbn().isOngoing()); 2214 } 2215 2216 @Test testCancelAllNotifications_IgnoreForegroundService()2217 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception { 2218 when(mAmi.applyForegroundServiceNotification( 2219 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY); 2220 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2221 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2222 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2223 "testCancelAllNotifications_IgnoreForegroundService", 2224 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2225 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2226 waitForIdle(); 2227 StatusBarNotification[] notifs = 2228 mBinderService.getActiveNotifications(sbn.getPackageName()); 2229 assertEquals(1, notifs.length); 2230 assertEquals(1, mService.getNotificationRecordCount()); 2231 } 2232 2233 @Test testCancelAllNotifications_FgsFlag_NoFgs_Allowed()2234 public void testCancelAllNotifications_FgsFlag_NoFgs_Allowed() throws Exception { 2235 when(mAmi.applyForegroundServiceNotification( 2236 any(), anyString(), anyInt(), anyString(), anyInt())) 2237 .thenReturn(NOT_FOREGROUND_SERVICE); 2238 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2239 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2240 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2241 "testCancelAllNotifications_IgnoreForegroundService", 2242 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2243 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2244 waitForIdle(); 2245 StatusBarNotification[] notifs = 2246 mBinderService.getActiveNotifications(sbn.getPackageName()); 2247 assertEquals(0, notifs.length); 2248 } 2249 2250 @Test testCancelAllNotifications_IgnoreOtherPackages()2251 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception { 2252 when(mAmi.applyForegroundServiceNotification( 2253 any(), anyString(), anyInt(), anyString(), anyInt())) 2254 .thenReturn(SHOW_IMMEDIATELY); 2255 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2256 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2257 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2258 "testCancelAllNotifications_IgnoreOtherPackages", 2259 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2260 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId()); 2261 waitForIdle(); 2262 StatusBarNotification[] notifs = 2263 mBinderService.getActiveNotifications(sbn.getPackageName()); 2264 assertEquals(1, notifs.length); 2265 assertEquals(1, mService.getNotificationRecordCount()); 2266 } 2267 2268 @Test testCancelAllNotifications_NullPkgRemovesAll()2269 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception { 2270 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2271 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2272 "testCancelAllNotifications_NullPkgRemovesAll", 2273 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2274 mBinderService.cancelAllNotifications(null, sbn.getUserId()); 2275 waitForIdle(); 2276 StatusBarNotification[] notifs = 2277 mBinderService.getActiveNotifications(sbn.getPackageName()); 2278 assertEquals(0, notifs.length); 2279 assertEquals(0, mService.getNotificationRecordCount()); 2280 } 2281 2282 @Test testCancelAllNotifications_NullPkgIgnoresUserAllNotifications()2283 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception { 2284 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2285 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2286 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications", 2287 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL); 2288 // Null pkg is how we signal a user switch. 2289 mBinderService.cancelAllNotifications(null, sbn.getUserId()); 2290 waitForIdle(); 2291 StatusBarNotification[] notifs = 2292 mBinderService.getActiveNotifications(sbn.getPackageName()); 2293 assertEquals(1, notifs.length); 2294 assertEquals(1, mService.getNotificationRecordCount()); 2295 } 2296 2297 @Test testAppInitiatedCancelAllNotifications_CancelsNoClearFlag()2298 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception { 2299 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2300 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR; 2301 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2302 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag", 2303 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2304 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2305 waitForIdle(); 2306 StatusBarNotification[] notifs = 2307 mBinderService.getActiveNotifications(sbn.getPackageName()); 2308 assertEquals(0, notifs.length); 2309 } 2310 2311 @Test testCancelAllNotifications_CancelsNoClearFlag()2312 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception { 2313 final NotificationRecord notif = generateNotificationRecord( 2314 mTestNotificationChannel, 1, "group", true); 2315 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 2316 mService.addNotification(notif); 2317 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, 2318 notif.getUserId(), REASON_CANCEL); 2319 waitForIdle(); 2320 StatusBarNotification[] notifs = 2321 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 2322 assertEquals(0, notifs.length); 2323 } 2324 2325 @Test testUserInitiatedCancelAllOnClearAll_NoClearFlag()2326 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception { 2327 final NotificationRecord notif = generateNotificationRecord( 2328 mTestNotificationChannel, 1, "group", true); 2329 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 2330 mService.addNotification(notif); 2331 2332 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 2333 notif.getUserId()); 2334 waitForIdle(); 2335 StatusBarNotification[] notifs = 2336 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 2337 assertEquals(1, notifs.length); 2338 } 2339 2340 @Test testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue()2341 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception { 2342 when(mAmi.applyForegroundServiceNotification( 2343 any(), anyString(), anyInt(), anyString(), anyInt())) 2344 .thenReturn(SHOW_IMMEDIATELY); 2345 Notification n = 2346 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 2347 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2348 .build(); 2349 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0, 2350 n, UserHandle.getUserHandleForUid(mUid), null, 0); 2351 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2352 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 2353 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2354 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(), 2355 sbn.getUserId()); 2356 waitForIdle(); 2357 StatusBarNotification[] notifs = 2358 mBinderService.getActiveNotifications(sbn.getPackageName()); 2359 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE); 2360 } 2361 2362 @Test testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag()2363 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception { 2364 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2365 sbn.getNotification().flags = 2366 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; 2367 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 2368 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2369 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT; 2370 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 2371 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2372 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), 2373 sbn.getUserId()); 2374 waitForIdle(); 2375 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 2376 assertEquals(0, mService.getNotificationRecordCount()); 2377 } 2378 2379 @Test testCancelNotificationWithTag_fromApp_cannotCancelFgsChild()2380 public void testCancelNotificationWithTag_fromApp_cannotCancelFgsChild() 2381 throws Exception { 2382 when(mAmi.applyForegroundServiceNotification( 2383 any(), anyString(), anyInt(), anyString(), anyInt())) 2384 .thenReturn(SHOW_IMMEDIATELY); 2385 mService.isSystemUid = false; 2386 mService.isSystemAppId = false; 2387 final NotificationRecord parent = generateNotificationRecord( 2388 mTestNotificationChannel, 1, "group", true); 2389 final NotificationRecord child = generateNotificationRecord( 2390 mTestNotificationChannel, 2, "group", false); 2391 final NotificationRecord child2 = generateNotificationRecord( 2392 mTestNotificationChannel, 3, "group", false); 2393 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2394 mService.addNotification(parent); 2395 mService.addNotification(child); 2396 mService.addNotification(child2); 2397 mService.getBinderService().cancelNotificationWithTag( 2398 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 2399 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 2400 waitForIdle(); 2401 StatusBarNotification[] notifs = 2402 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2403 assertEquals(1, notifs.length); 2404 } 2405 2406 @Test testCancelNotificationWithTag_fromApp_cannotCancelFgsParent()2407 public void testCancelNotificationWithTag_fromApp_cannotCancelFgsParent() 2408 throws Exception { 2409 when(mAmi.applyForegroundServiceNotification( 2410 any(), anyString(), anyInt(), anyString(), anyInt())) 2411 .thenReturn(SHOW_IMMEDIATELY); 2412 mService.isSystemUid = false; 2413 mService.isSystemAppId = false; 2414 final NotificationRecord parent = generateNotificationRecord( 2415 mTestNotificationChannel, 1, "group", true); 2416 parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2417 final NotificationRecord child = generateNotificationRecord( 2418 mTestNotificationChannel, 2, "group", false); 2419 final NotificationRecord child2 = generateNotificationRecord( 2420 mTestNotificationChannel, 3, "group", false); 2421 mService.addNotification(parent); 2422 mService.addNotification(child); 2423 mService.addNotification(child2); 2424 mService.getBinderService().cancelNotificationWithTag( 2425 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 2426 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 2427 waitForIdle(); 2428 StatusBarNotification[] notifs = 2429 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2430 assertEquals(3, notifs.length); 2431 } 2432 2433 @Test testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearChild()2434 public void testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearChild() 2435 throws Exception { 2436 mService.isSystemUid = false; 2437 mService.isSystemAppId = false; 2438 final NotificationRecord parent = generateNotificationRecord( 2439 mTestNotificationChannel, 1, "group", true); 2440 final NotificationRecord child = generateNotificationRecord( 2441 mTestNotificationChannel, 2, "group", false); 2442 final NotificationRecord child2 = generateNotificationRecord( 2443 mTestNotificationChannel, 3, "group", false); 2444 child2.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR; 2445 mService.addNotification(parent); 2446 mService.addNotification(child); 2447 mService.addNotification(child2); 2448 mService.getBinderService().cancelNotificationWithTag( 2449 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 2450 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 2451 waitForIdle(); 2452 StatusBarNotification[] notifs = 2453 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2454 assertEquals(0, notifs.length); 2455 } 2456 2457 @Test testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearParent()2458 public void testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearParent() 2459 throws Exception { 2460 mService.isSystemUid = false; 2461 mService.isSystemAppId = false; 2462 final NotificationRecord parent = generateNotificationRecord( 2463 mTestNotificationChannel, 1, "group", true); 2464 parent.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR; 2465 final NotificationRecord child = generateNotificationRecord( 2466 mTestNotificationChannel, 2, "group", false); 2467 final NotificationRecord child2 = generateNotificationRecord( 2468 mTestNotificationChannel, 3, "group", false); 2469 mService.addNotification(parent); 2470 mService.addNotification(child); 2471 mService.addNotification(child2); 2472 mService.getBinderService().cancelNotificationWithTag( 2473 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 2474 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 2475 waitForIdle(); 2476 StatusBarNotification[] notifs = 2477 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2478 assertEquals(0, notifs.length); 2479 } 2480 2481 @Test testCancelAllNotificationsFromApp_cannotCancelFgsChild()2482 public void testCancelAllNotificationsFromApp_cannotCancelFgsChild() 2483 throws Exception { 2484 when(mAmi.applyForegroundServiceNotification( 2485 any(), anyString(), anyInt(), anyString(), anyInt())) 2486 .thenReturn(SHOW_IMMEDIATELY); 2487 mService.isSystemUid = false; 2488 mService.isSystemAppId = false; 2489 final NotificationRecord parent = generateNotificationRecord( 2490 mTestNotificationChannel, 1, "group", true); 2491 final NotificationRecord child = generateNotificationRecord( 2492 mTestNotificationChannel, 2, "group", false); 2493 final NotificationRecord child2 = generateNotificationRecord( 2494 mTestNotificationChannel, 3, "group", false); 2495 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2496 final NotificationRecord newGroup = generateNotificationRecord( 2497 mTestNotificationChannel, 4, "group2", false); 2498 mService.addNotification(parent); 2499 mService.addNotification(child); 2500 mService.addNotification(child2); 2501 mService.addNotification(newGroup); 2502 mService.getBinderService().cancelAllNotifications( 2503 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 2504 waitForIdle(); 2505 StatusBarNotification[] notifs = 2506 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2507 assertEquals(1, notifs.length); 2508 } 2509 2510 @Test testCancelAllNotifications_fromApp_cannotCancelFgsParent()2511 public void testCancelAllNotifications_fromApp_cannotCancelFgsParent() 2512 throws Exception { 2513 when(mAmi.applyForegroundServiceNotification( 2514 any(), anyString(), anyInt(), anyString(), anyInt())) 2515 .thenReturn(SHOW_IMMEDIATELY); 2516 mService.isSystemUid = false; 2517 mService.isSystemAppId = false; 2518 final NotificationRecord parent = generateNotificationRecord( 2519 mTestNotificationChannel, 1, "group", true); 2520 parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2521 final NotificationRecord child = generateNotificationRecord( 2522 mTestNotificationChannel, 2, "group", false); 2523 final NotificationRecord child2 = generateNotificationRecord( 2524 mTestNotificationChannel, 3, "group", false); 2525 final NotificationRecord newGroup = generateNotificationRecord( 2526 mTestNotificationChannel, 4, "group2", false); 2527 mService.addNotification(parent); 2528 mService.addNotification(child); 2529 mService.addNotification(child2); 2530 mService.addNotification(newGroup); 2531 mService.getBinderService().cancelAllNotifications( 2532 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 2533 waitForIdle(); 2534 StatusBarNotification[] notifs = 2535 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2536 assertEquals(1, notifs.length); 2537 } 2538 2539 @Test testCancelAllNotifications_fromApp_canCancelOngoingNoClearChild()2540 public void testCancelAllNotifications_fromApp_canCancelOngoingNoClearChild() 2541 throws Exception { 2542 mService.isSystemUid = false; 2543 mService.isSystemAppId = false; 2544 final NotificationRecord parent = generateNotificationRecord( 2545 mTestNotificationChannel, 1, "group", true); 2546 final NotificationRecord child = generateNotificationRecord( 2547 mTestNotificationChannel, 2, "group", false); 2548 final NotificationRecord child2 = generateNotificationRecord( 2549 mTestNotificationChannel, 3, "group", false); 2550 child2.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR; 2551 final NotificationRecord newGroup = generateNotificationRecord( 2552 mTestNotificationChannel, 4, "group2", false); 2553 mService.addNotification(parent); 2554 mService.addNotification(child); 2555 mService.addNotification(child2); 2556 mService.addNotification(newGroup); 2557 mService.getBinderService().cancelAllNotifications( 2558 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 2559 waitForIdle(); 2560 StatusBarNotification[] notifs = 2561 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2562 assertEquals(0, notifs.length); 2563 } 2564 2565 @Test testCancelAllNotifications_fromApp_canCancelOngoingNoClearParent()2566 public void testCancelAllNotifications_fromApp_canCancelOngoingNoClearParent() 2567 throws Exception { 2568 mService.isSystemUid = false; 2569 mService.isSystemAppId = false; 2570 final NotificationRecord parent = generateNotificationRecord( 2571 mTestNotificationChannel, 1, "group", true); 2572 parent.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR; 2573 final NotificationRecord child = generateNotificationRecord( 2574 mTestNotificationChannel, 2, "group", false); 2575 final NotificationRecord child2 = generateNotificationRecord( 2576 mTestNotificationChannel, 3, "group", false); 2577 final NotificationRecord newGroup = generateNotificationRecord( 2578 mTestNotificationChannel, 4, "group2", false); 2579 mService.addNotification(parent); 2580 mService.addNotification(child); 2581 mService.addNotification(child2); 2582 mService.addNotification(newGroup); 2583 mService.getBinderService().cancelAllNotifications( 2584 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 2585 waitForIdle(); 2586 StatusBarNotification[] notifs = 2587 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2588 assertEquals(0, notifs.length); 2589 } 2590 2591 @Test testCancelNotificationsFromListener_clearAll_GroupWithOngoingParent()2592 public void testCancelNotificationsFromListener_clearAll_GroupWithOngoingParent() 2593 throws Exception { 2594 final NotificationRecord parent = generateNotificationRecord( 2595 mTestNotificationChannel, 1, "group", true); 2596 parent.getNotification().flags |= FLAG_ONGOING_EVENT; 2597 final NotificationRecord child = generateNotificationRecord( 2598 mTestNotificationChannel, 2, "group", false); 2599 final NotificationRecord child2 = generateNotificationRecord( 2600 mTestNotificationChannel, 3, "group", false); 2601 final NotificationRecord newGroup = generateNotificationRecord( 2602 mTestNotificationChannel, 4, "group2", false); 2603 mService.addNotification(parent); 2604 mService.addNotification(child); 2605 mService.addNotification(child2); 2606 mService.addNotification(newGroup); 2607 mService.getBinderService().cancelNotificationsFromListener(null, null); 2608 waitForIdle(); 2609 StatusBarNotification[] notifs = 2610 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2611 assertEquals(1, notifs.length); 2612 } 2613 2614 @Test testCancelNotificationsFromListener_clearAll_GroupWithOngoingChild()2615 public void testCancelNotificationsFromListener_clearAll_GroupWithOngoingChild() 2616 throws Exception { 2617 final NotificationRecord parent = generateNotificationRecord( 2618 mTestNotificationChannel, 1, "group", true); 2619 final NotificationRecord child = generateNotificationRecord( 2620 mTestNotificationChannel, 2, "group", false); 2621 final NotificationRecord child2 = generateNotificationRecord( 2622 mTestNotificationChannel, 3, "group", false); 2623 child2.getNotification().flags |= FLAG_ONGOING_EVENT; 2624 final NotificationRecord newGroup = generateNotificationRecord( 2625 mTestNotificationChannel, 4, "group2", false); 2626 mService.addNotification(parent); 2627 mService.addNotification(child); 2628 mService.addNotification(child2); 2629 mService.addNotification(newGroup); 2630 mService.getBinderService().cancelNotificationsFromListener(null, null); 2631 waitForIdle(); 2632 StatusBarNotification[] notifs = 2633 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2634 assertEquals(1, notifs.length); 2635 } 2636 2637 @Test testCancelNotificationsFromListener_clearAll_GroupWithFgsParent()2638 public void testCancelNotificationsFromListener_clearAll_GroupWithFgsParent() 2639 throws Exception { 2640 when(mAmi.applyForegroundServiceNotification( 2641 any(), anyString(), anyInt(), anyString(), anyInt())) 2642 .thenReturn(SHOW_IMMEDIATELY); 2643 final NotificationRecord parent = generateNotificationRecord( 2644 mTestNotificationChannel, 1, "group", true); 2645 parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2646 final NotificationRecord child = generateNotificationRecord( 2647 mTestNotificationChannel, 2, "group", false); 2648 final NotificationRecord child2 = generateNotificationRecord( 2649 mTestNotificationChannel, 3, "group", false); 2650 final NotificationRecord newGroup = generateNotificationRecord( 2651 mTestNotificationChannel, 4, "group2", false); 2652 mService.addNotification(parent); 2653 mService.addNotification(child); 2654 mService.addNotification(child2); 2655 mService.addNotification(newGroup); 2656 mService.getBinderService().cancelNotificationsFromListener(null, null); 2657 waitForIdle(); 2658 StatusBarNotification[] notifs = 2659 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2660 assertEquals(0, notifs.length); 2661 } 2662 2663 @Test testCancelNotificationsFromListener_clearAll_GroupWithFgsChild()2664 public void testCancelNotificationsFromListener_clearAll_GroupWithFgsChild() 2665 throws Exception { 2666 when(mAmi.applyForegroundServiceNotification( 2667 any(), anyString(), anyInt(), anyString(), anyInt())) 2668 .thenReturn(SHOW_IMMEDIATELY); 2669 final NotificationRecord parent = generateNotificationRecord( 2670 mTestNotificationChannel, 1, "group", true); 2671 final NotificationRecord child = generateNotificationRecord( 2672 mTestNotificationChannel, 2, "group", false); 2673 final NotificationRecord child2 = generateNotificationRecord( 2674 mTestNotificationChannel, 3, "group", false); 2675 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2676 final NotificationRecord newGroup = generateNotificationRecord( 2677 mTestNotificationChannel, 4, "group2", false); 2678 mService.addNotification(parent); 2679 mService.addNotification(child); 2680 mService.addNotification(child2); 2681 mService.addNotification(newGroup); 2682 mService.getBinderService().cancelNotificationsFromListener(null, null); 2683 waitForIdle(); 2684 StatusBarNotification[] notifs = 2685 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2686 assertEquals(0, notifs.length); 2687 } 2688 2689 @Test testCancelNotificationsFromListener_clearAll_GroupWithNoClearParent()2690 public void testCancelNotificationsFromListener_clearAll_GroupWithNoClearParent() 2691 throws Exception { 2692 final NotificationRecord parent = generateNotificationRecord( 2693 mTestNotificationChannel, 1, "group", true); 2694 parent.getNotification().flags |= FLAG_NO_CLEAR; 2695 final NotificationRecord child = generateNotificationRecord( 2696 mTestNotificationChannel, 2, "group", false); 2697 final NotificationRecord child2 = generateNotificationRecord( 2698 mTestNotificationChannel, 3, "group", false); 2699 final NotificationRecord newGroup = generateNotificationRecord( 2700 mTestNotificationChannel, 4, "group2", false); 2701 mService.addNotification(parent); 2702 mService.addNotification(child); 2703 mService.addNotification(child2); 2704 mService.addNotification(newGroup); 2705 mService.getBinderService().cancelNotificationsFromListener(null, null); 2706 waitForIdle(); 2707 StatusBarNotification[] notifs = 2708 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2709 assertEquals(1, notifs.length); 2710 } 2711 2712 @Test testCancelNotificationsFromListener_clearAll_GroupWithNoClearChild()2713 public void testCancelNotificationsFromListener_clearAll_GroupWithNoClearChild() 2714 throws Exception { 2715 final NotificationRecord parent = generateNotificationRecord( 2716 mTestNotificationChannel, 1, "group", true); 2717 final NotificationRecord child = generateNotificationRecord( 2718 mTestNotificationChannel, 2, "group", false); 2719 final NotificationRecord child2 = generateNotificationRecord( 2720 mTestNotificationChannel, 3, "group", false); 2721 child2.getNotification().flags |= FLAG_NO_CLEAR; 2722 final NotificationRecord newGroup = generateNotificationRecord( 2723 mTestNotificationChannel, 4, "group2", false); 2724 mService.addNotification(parent); 2725 mService.addNotification(child); 2726 mService.addNotification(child2); 2727 mService.addNotification(newGroup); 2728 mService.getBinderService().cancelNotificationsFromListener(null, null); 2729 waitForIdle(); 2730 StatusBarNotification[] notifs = 2731 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2732 assertEquals(1, notifs.length); 2733 } 2734 2735 @Test testCancelNotificationsFromListener_clearAll_Ongoing()2736 public void testCancelNotificationsFromListener_clearAll_Ongoing() 2737 throws Exception { 2738 final NotificationRecord child2 = generateNotificationRecord( 2739 mTestNotificationChannel, 3, null, false); 2740 child2.getNotification().flags |= FLAG_ONGOING_EVENT; 2741 mService.addNotification(child2); 2742 String[] keys = {child2.getSbn().getKey()}; 2743 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2744 waitForIdle(); 2745 StatusBarNotification[] notifs = 2746 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2747 assertEquals(1, notifs.length); 2748 } 2749 2750 @Test testCancelNotificationsFromListener_clearAll_NoClear()2751 public void testCancelNotificationsFromListener_clearAll_NoClear() 2752 throws Exception { 2753 final NotificationRecord child2 = generateNotificationRecord( 2754 mTestNotificationChannel, 3, null, false); 2755 child2.getNotification().flags |= FLAG_NO_CLEAR; 2756 mService.addNotification(child2); 2757 mService.getBinderService().cancelNotificationsFromListener(null, null); 2758 waitForIdle(); 2759 StatusBarNotification[] notifs = 2760 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2761 assertEquals(1, notifs.length); 2762 } 2763 2764 @Test testCancelNotificationsFromListener_clearAll_Fgs()2765 public void testCancelNotificationsFromListener_clearAll_Fgs() 2766 throws Exception { 2767 when(mAmi.applyForegroundServiceNotification( 2768 any(), anyString(), anyInt(), anyString(), anyInt())) 2769 .thenReturn(SHOW_IMMEDIATELY); 2770 final NotificationRecord child2 = generateNotificationRecord( 2771 mTestNotificationChannel, 3, null, false); 2772 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2773 mService.addNotification(child2); 2774 mService.getBinderService().cancelNotificationsFromListener(null, null); 2775 waitForIdle(); 2776 StatusBarNotification[] notifs = 2777 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2778 assertEquals(0, notifs.length); 2779 } 2780 2781 @Test testCancelNotificationsFromListener_byKey_GroupWithOngoingParent()2782 public void testCancelNotificationsFromListener_byKey_GroupWithOngoingParent() 2783 throws Exception { 2784 final NotificationRecord parent = generateNotificationRecord( 2785 mTestNotificationChannel, 1, "group", true); 2786 parent.getNotification().flags |= FLAG_ONGOING_EVENT; 2787 final NotificationRecord child = generateNotificationRecord( 2788 mTestNotificationChannel, 2, "group", false); 2789 final NotificationRecord child2 = generateNotificationRecord( 2790 mTestNotificationChannel, 3, "group", false); 2791 final NotificationRecord newGroup = generateNotificationRecord( 2792 mTestNotificationChannel, 4, "group2", false); 2793 mService.addNotification(parent); 2794 mService.addNotification(child); 2795 mService.addNotification(child2); 2796 mService.addNotification(newGroup); 2797 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2798 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2799 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2800 waitForIdle(); 2801 StatusBarNotification[] notifs = 2802 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2803 assertEquals(1, notifs.length); 2804 } 2805 2806 @Test testCancelNotificationsFromListener_byKey_GroupWithOngoingChild()2807 public void testCancelNotificationsFromListener_byKey_GroupWithOngoingChild() 2808 throws Exception { 2809 final NotificationRecord parent = generateNotificationRecord( 2810 mTestNotificationChannel, 1, "group", true); 2811 final NotificationRecord child = generateNotificationRecord( 2812 mTestNotificationChannel, 2, "group", false); 2813 final NotificationRecord child2 = generateNotificationRecord( 2814 mTestNotificationChannel, 3, "group", false); 2815 child2.getNotification().flags |= FLAG_ONGOING_EVENT; 2816 final NotificationRecord newGroup = generateNotificationRecord( 2817 mTestNotificationChannel, 4, "group2", false); 2818 mService.addNotification(parent); 2819 mService.addNotification(child); 2820 mService.addNotification(child2); 2821 mService.addNotification(newGroup); 2822 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2823 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2824 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2825 waitForIdle(); 2826 StatusBarNotification[] notifs = 2827 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2828 assertEquals(1, notifs.length); 2829 } 2830 2831 @Test testCancelNotificationsFromListener_byKey_GroupWithFgsParent()2832 public void testCancelNotificationsFromListener_byKey_GroupWithFgsParent() 2833 throws Exception { 2834 when(mAmi.applyForegroundServiceNotification( 2835 any(), anyString(), anyInt(), anyString(), anyInt())) 2836 .thenReturn(SHOW_IMMEDIATELY); 2837 final NotificationRecord parent = generateNotificationRecord( 2838 mTestNotificationChannel, 1, "group", true); 2839 parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2840 final NotificationRecord child = generateNotificationRecord( 2841 mTestNotificationChannel, 2, "group", false); 2842 final NotificationRecord child2 = generateNotificationRecord( 2843 mTestNotificationChannel, 3, "group", false); 2844 final NotificationRecord newGroup = generateNotificationRecord( 2845 mTestNotificationChannel, 4, "group2", false); 2846 mService.addNotification(parent); 2847 mService.addNotification(child); 2848 mService.addNotification(child2); 2849 mService.addNotification(newGroup); 2850 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2851 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2852 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2853 waitForIdle(); 2854 StatusBarNotification[] notifs = 2855 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2856 assertEquals(0, notifs.length); 2857 } 2858 2859 @Test testCancelNotificationsFromListener_byKey_GroupWithFgsChild()2860 public void testCancelNotificationsFromListener_byKey_GroupWithFgsChild() 2861 throws Exception { 2862 when(mAmi.applyForegroundServiceNotification( 2863 any(), anyString(), anyInt(), anyString(), anyInt())) 2864 .thenReturn(SHOW_IMMEDIATELY); 2865 final NotificationRecord parent = generateNotificationRecord( 2866 mTestNotificationChannel, 1, "group", true); 2867 final NotificationRecord child = generateNotificationRecord( 2868 mTestNotificationChannel, 2, "group", false); 2869 final NotificationRecord child2 = generateNotificationRecord( 2870 mTestNotificationChannel, 3, "group", false); 2871 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2872 final NotificationRecord newGroup = generateNotificationRecord( 2873 mTestNotificationChannel, 4, "group2", false); 2874 mService.addNotification(parent); 2875 mService.addNotification(child); 2876 mService.addNotification(child2); 2877 mService.addNotification(newGroup); 2878 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2879 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2880 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2881 waitForIdle(); 2882 StatusBarNotification[] notifs = 2883 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2884 assertEquals(0, notifs.length); 2885 } 2886 2887 @Test testCancelNotificationsFromListener_byKey_GroupWithNoClearParent()2888 public void testCancelNotificationsFromListener_byKey_GroupWithNoClearParent() 2889 throws Exception { 2890 final NotificationRecord parent = generateNotificationRecord( 2891 mTestNotificationChannel, 1, "group", true); 2892 parent.getNotification().flags |= FLAG_NO_CLEAR; 2893 final NotificationRecord child = generateNotificationRecord( 2894 mTestNotificationChannel, 2, "group", false); 2895 final NotificationRecord child2 = generateNotificationRecord( 2896 mTestNotificationChannel, 3, "group", false); 2897 final NotificationRecord newGroup = generateNotificationRecord( 2898 mTestNotificationChannel, 4, "group2", false); 2899 mService.addNotification(parent); 2900 mService.addNotification(child); 2901 mService.addNotification(child2); 2902 mService.addNotification(newGroup); 2903 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2904 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2905 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2906 waitForIdle(); 2907 StatusBarNotification[] notifs = 2908 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2909 assertEquals(0, notifs.length); 2910 } 2911 2912 @Test testCancelNotificationsFromListener_byKey_GroupWithNoClearChild()2913 public void testCancelNotificationsFromListener_byKey_GroupWithNoClearChild() 2914 throws Exception { 2915 final NotificationRecord parent = generateNotificationRecord( 2916 mTestNotificationChannel, 1, "group", true); 2917 final NotificationRecord child = generateNotificationRecord( 2918 mTestNotificationChannel, 2, "group", false); 2919 final NotificationRecord child2 = generateNotificationRecord( 2920 mTestNotificationChannel, 3, "group", false); 2921 child2.getNotification().flags |= FLAG_NO_CLEAR; 2922 final NotificationRecord newGroup = generateNotificationRecord( 2923 mTestNotificationChannel, 4, "group2", false); 2924 mService.addNotification(parent); 2925 mService.addNotification(child); 2926 mService.addNotification(child2); 2927 mService.addNotification(newGroup); 2928 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2929 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2930 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2931 waitForIdle(); 2932 StatusBarNotification[] notifs = 2933 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2934 assertEquals(0, notifs.length); 2935 } 2936 2937 @Test testCancelNotificationsFromListener_byKey_Ongoing()2938 public void testCancelNotificationsFromListener_byKey_Ongoing() 2939 throws Exception { 2940 final NotificationRecord child2 = generateNotificationRecord( 2941 mTestNotificationChannel, 3, null, false); 2942 child2.getNotification().flags |= FLAG_ONGOING_EVENT; 2943 mService.addNotification(child2); 2944 String[] keys = {child2.getSbn().getKey()}; 2945 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2946 waitForIdle(); 2947 StatusBarNotification[] notifs = 2948 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2949 assertEquals(1, notifs.length); 2950 } 2951 2952 @Test testCancelNotificationsFromListener_byKey_NoClear()2953 public void testCancelNotificationsFromListener_byKey_NoClear() 2954 throws Exception { 2955 final NotificationRecord child2 = generateNotificationRecord( 2956 mTestNotificationChannel, 3, null, false); 2957 child2.getNotification().flags |= FLAG_NO_CLEAR; 2958 mService.addNotification(child2); 2959 String[] keys = {child2.getSbn().getKey()}; 2960 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2961 waitForIdle(); 2962 StatusBarNotification[] notifs = 2963 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2964 assertEquals(0, notifs.length); 2965 } 2966 2967 @Test testCancelNotificationsFromListener_byKey_Fgs()2968 public void testCancelNotificationsFromListener_byKey_Fgs() 2969 throws Exception { 2970 when(mAmi.applyForegroundServiceNotification( 2971 any(), anyString(), anyInt(), anyString(), anyInt())) 2972 .thenReturn(SHOW_IMMEDIATELY); 2973 final NotificationRecord child2 = generateNotificationRecord( 2974 mTestNotificationChannel, 3, null, false); 2975 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2976 mService.addNotification(child2); 2977 String[] keys = {child2.getSbn().getKey()}; 2978 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2979 waitForIdle(); 2980 StatusBarNotification[] notifs = 2981 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2982 assertEquals(0, notifs.length); 2983 } 2984 2985 @Test testGroupInstanceIds()2986 public void testGroupInstanceIds() throws Exception { 2987 final NotificationRecord group1 = generateNotificationRecord( 2988 mTestNotificationChannel, 1, "group1", true); 2989 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testGroupInstanceIds", 2990 group1.getSbn().getId(), group1.getSbn().getNotification(), 2991 group1.getSbn().getUserId()); 2992 waitForIdle(); 2993 2994 // same group, child, should be returned 2995 final NotificationRecord group1Child = generateNotificationRecord( 2996 mTestNotificationChannel, 2, "group1", false); 2997 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testGroupInstanceIds", 2998 group1Child.getSbn().getId(), 2999 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId()); 3000 waitForIdle(); 3001 3002 assertEquals(2, mNotificationRecordLogger.numCalls()); 3003 assertEquals(mNotificationRecordLogger.get(0).getInstanceId(), 3004 mNotificationRecordLogger.get(1).groupInstanceId.getId()); 3005 } 3006 3007 @Test testFindGroupNotificationsLocked()3008 public void testFindGroupNotificationsLocked() throws Exception { 3009 // make sure the same notification can be found in both lists and returned 3010 final NotificationRecord group1 = generateNotificationRecord( 3011 mTestNotificationChannel, 1, "group1", true); 3012 mService.addEnqueuedNotification(group1); 3013 mService.addNotification(group1); 3014 3015 // should not be returned 3016 final NotificationRecord group2 = generateNotificationRecord( 3017 mTestNotificationChannel, 2, "group2", true); 3018 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 3019 group2.getSbn().getId(), group2.getSbn().getNotification(), 3020 group2.getSbn().getUserId()); 3021 waitForIdle(); 3022 3023 // should not be returned 3024 final NotificationRecord nonGroup = generateNotificationRecord( 3025 mTestNotificationChannel, 3, null, false); 3026 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 3027 nonGroup.getSbn().getId(), nonGroup.getSbn().getNotification(), 3028 nonGroup.getSbn().getUserId()); 3029 waitForIdle(); 3030 3031 // same group, child, should be returned 3032 final NotificationRecord group1Child = generateNotificationRecord( 3033 mTestNotificationChannel, 4, "group1", false); 3034 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 3035 group1Child.getSbn().getId(), 3036 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId()); 3037 waitForIdle(); 3038 3039 List<NotificationRecord> inGroup1 = 3040 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(), 3041 group1.getSbn().getUserId()); 3042 assertEquals(3, inGroup1.size()); 3043 for (NotificationRecord record : inGroup1) { 3044 assertTrue(record.getGroupKey().equals(group1.getGroupKey())); 3045 assertTrue(record.getSbn().getId() == 1 || record.getSbn().getId() == 4); 3046 } 3047 } 3048 3049 @Test testCancelAllNotificationsInt_CancelsNoClearFlagOnGoing()3050 public void testCancelAllNotificationsInt_CancelsNoClearFlagOnGoing() throws Exception { 3051 final NotificationRecord notif = generateNotificationRecord( 3052 mTestNotificationChannel, 1, "group", true); 3053 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 3054 mService.addNotification(notif); 3055 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 3056 Notification.FLAG_ONGOING_EVENT, notif.getUserId(), REASON_CANCEL); 3057 waitForIdle(); 3058 StatusBarNotification[] notifs = 3059 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 3060 assertEquals(0, notifs.length); 3061 } 3062 3063 @Test testAppInitiatedCancelAllNotifications_CancelsOngoingFlag()3064 public void testAppInitiatedCancelAllNotifications_CancelsOngoingFlag() throws Exception { 3065 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 3066 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 3067 mBinderService.enqueueNotificationWithTag(PKG, PKG, 3068 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag", 3069 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 3070 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 3071 waitForIdle(); 3072 StatusBarNotification[] notifs = 3073 mBinderService.getActiveNotifications(sbn.getPackageName()); 3074 assertEquals(0, notifs.length); 3075 } 3076 3077 @Test testCancelAllNotificationsInt_CancelsOngoingFlag()3078 public void testCancelAllNotificationsInt_CancelsOngoingFlag() throws Exception { 3079 final NotificationRecord notif = generateNotificationRecord( 3080 mTestNotificationChannel, 1, "group", true); 3081 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 3082 mService.addNotification(notif); 3083 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, 3084 notif.getUserId(), REASON_CANCEL); 3085 waitForIdle(); 3086 StatusBarNotification[] notifs = 3087 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 3088 assertEquals(0, notifs.length); 3089 } 3090 3091 @Test testUserInitiatedCancelAllWithGroup_OngoingFlag()3092 public void testUserInitiatedCancelAllWithGroup_OngoingFlag() throws Exception { 3093 final NotificationRecord parent = generateNotificationRecord( 3094 mTestNotificationChannel, 1, "group", true); 3095 final NotificationRecord child = generateNotificationRecord( 3096 mTestNotificationChannel, 2, "group", false); 3097 final NotificationRecord child2 = generateNotificationRecord( 3098 mTestNotificationChannel, 3, "group", false); 3099 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 3100 final NotificationRecord newGroup = generateNotificationRecord( 3101 mTestNotificationChannel, 4, "group2", false); 3102 mService.addNotification(parent); 3103 mService.addNotification(child); 3104 mService.addNotification(child2); 3105 mService.addNotification(newGroup); 3106 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 3107 parent.getUserId()); 3108 waitForIdle(); 3109 StatusBarNotification[] notifs = 3110 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 3111 assertEquals(1, notifs.length); 3112 } 3113 3114 @Test testUserInitiatedCancelAllWithGroup_NoClearFlag()3115 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception { 3116 final NotificationRecord parent = generateNotificationRecord( 3117 mTestNotificationChannel, 1, "group", true); 3118 final NotificationRecord child = generateNotificationRecord( 3119 mTestNotificationChannel, 2, "group", false); 3120 final NotificationRecord child2 = generateNotificationRecord( 3121 mTestNotificationChannel, 3, "group", false); 3122 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 3123 final NotificationRecord newGroup = generateNotificationRecord( 3124 mTestNotificationChannel, 4, "group2", false); 3125 mService.addNotification(parent); 3126 mService.addNotification(child); 3127 mService.addNotification(child2); 3128 mService.addNotification(newGroup); 3129 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 3130 parent.getUserId()); 3131 waitForIdle(); 3132 StatusBarNotification[] notifs = 3133 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 3134 assertEquals(1, notifs.length); 3135 } 3136 3137 @Test testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag()3138 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception { 3139 when(mAmi.applyForegroundServiceNotification( 3140 any(), anyString(), anyInt(), anyString(), anyInt())) 3141 .thenReturn(SHOW_IMMEDIATELY); 3142 final NotificationRecord parent = generateNotificationRecord( 3143 mTestNotificationChannel, 1, "group", true); 3144 final NotificationRecord child = generateNotificationRecord( 3145 mTestNotificationChannel, 2, "group", false); 3146 final NotificationRecord child2 = generateNotificationRecord( 3147 mTestNotificationChannel, 3, "group", false); 3148 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 3149 final NotificationRecord newGroup = generateNotificationRecord( 3150 mTestNotificationChannel, 4, "group2", false); 3151 mService.addNotification(parent); 3152 mService.addNotification(child); 3153 mService.addNotification(child2); 3154 mService.addNotification(newGroup); 3155 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 3156 parent.getUserId()); 3157 waitForIdle(); 3158 StatusBarNotification[] notifs = 3159 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 3160 assertEquals(0, notifs.length); 3161 } 3162 3163 @Test testDefaultChannelUpdatesApp_postMigrationToPermissions()3164 public void testDefaultChannelUpdatesApp_postMigrationToPermissions() throws Exception { 3165 final NotificationChannel defaultChannel = mBinderService.getNotificationChannel( 3166 PKG_N_MR1, ActivityManager.getCurrentUser(), PKG_N_MR1, 3167 NotificationChannel.DEFAULT_CHANNEL_ID); 3168 defaultChannel.setImportance(IMPORTANCE_NONE); 3169 3170 mBinderService.updateNotificationChannelForPackage(PKG_N_MR1, mUid, defaultChannel); 3171 3172 verify(mPermissionHelper).setNotificationPermission( 3173 PKG_N_MR1, ActivityManager.getCurrentUser(), false, true); 3174 } 3175 3176 @Test testPostNotification_appPermissionFixed()3177 public void testPostNotification_appPermissionFixed() throws Exception { 3178 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 3179 when(mPermissionHelper.isPermissionFixed(PKG, 0)).thenReturn(true); 3180 3181 NotificationRecord temp = generateNotificationRecord(mTestNotificationChannel); 3182 mBinderService.enqueueNotificationWithTag(PKG, PKG, 3183 "testPostNotification_appPermissionFixed", 0, 3184 temp.getNotification(), 0); 3185 waitForIdle(); 3186 assertThat(mService.getNotificationRecordCount()).isEqualTo(1); 3187 StatusBarNotification[] notifs = 3188 mBinderService.getActiveNotifications(PKG); 3189 assertThat(mService.getNotificationRecord(notifs[0].getKey()).isImportanceFixed()).isTrue(); 3190 } 3191 3192 @Test testSummaryNotification_appPermissionFixed()3193 public void testSummaryNotification_appPermissionFixed() { 3194 NotificationRecord temp = generateNotificationRecord(mTestNotificationChannel); 3195 mService.addNotification(temp); 3196 3197 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 3198 when(mPermissionHelper.isPermissionFixed(PKG, temp.getUserId())).thenReturn(true); 3199 3200 NotificationRecord r = mService.createAutoGroupSummary( 3201 temp.getUserId(), temp.getSbn().getPackageName(), temp.getKey(), 0); 3202 3203 assertThat(r.isImportanceFixed()).isTrue(); 3204 } 3205 3206 @Test testTvExtenderChannelOverride_onTv()3207 public void testTvExtenderChannelOverride_onTv() throws Exception { 3208 mService.setIsTelevision(true); 3209 mService.setPreferencesHelper(mPreferencesHelper); 3210 when(mPreferencesHelper.getNotificationChannel( 3211 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn( 3212 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH)); 3213 3214 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); 3215 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0, 3216 generateNotificationRecord(null, tv).getNotification(), 0); 3217 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel( 3218 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean()); 3219 } 3220 3221 @Test testTvExtenderChannelOverride_notOnTv()3222 public void testTvExtenderChannelOverride_notOnTv() throws Exception { 3223 mService.setIsTelevision(false); 3224 mService.setPreferencesHelper(mPreferencesHelper); 3225 when(mPreferencesHelper.getNotificationChannel( 3226 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn( 3227 mTestNotificationChannel); 3228 3229 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); 3230 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv", 3231 0, generateNotificationRecord(null, tv).getNotification(), 0); 3232 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel( 3233 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null), 3234 anyBoolean(), anyBoolean()); 3235 } 3236 3237 @Test onOpChanged_permissionRevoked_cancelsAllNotificationsFromPackage()3238 public void onOpChanged_permissionRevoked_cancelsAllNotificationsFromPackage() 3239 throws RemoteException { 3240 // Have preexisting posted notifications from revoked package and other packages. 3241 mService.addNotification(new NotificationRecord(mContext, 3242 generateSbn("revoked", 1001, 1, 0), mTestNotificationChannel)); 3243 mService.addNotification(new NotificationRecord(mContext, 3244 generateSbn("other", 1002, 2, 0), mTestNotificationChannel)); 3245 // Have preexisting enqueued notifications from revoked package and other packages. 3246 mService.addEnqueuedNotification(new NotificationRecord(mContext, 3247 generateSbn("revoked", 1001, 3, 0), mTestNotificationChannel)); 3248 mService.addEnqueuedNotification(new NotificationRecord(mContext, 3249 generateSbn("other", 1002, 4, 0), mTestNotificationChannel)); 3250 assertThat(mService.mNotificationList).hasSize(2); 3251 assertThat(mService.mEnqueuedNotifications).hasSize(2); 3252 3253 when(mPackageManagerInternal.getPackageUid("revoked", 0, 0)).thenReturn(1001); 3254 when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(false); 3255 3256 mOnPermissionChangeListener.onOpChanged( 3257 AppOpsManager.OPSTR_POST_NOTIFICATION, "revoked", 0); 3258 waitForIdle(); 3259 3260 assertThat(mService.mNotificationList).hasSize(1); 3261 assertThat(mService.mNotificationList.get(0).getSbn().getPackageName()).isEqualTo("other"); 3262 assertThat(mService.mEnqueuedNotifications).hasSize(1); 3263 assertThat(mService.mEnqueuedNotifications.get(0).getSbn().getPackageName()).isEqualTo( 3264 "other"); 3265 } 3266 3267 @Test onOpChanged_permissionStillGranted_notificationsAreNotAffected()3268 public void onOpChanged_permissionStillGranted_notificationsAreNotAffected() 3269 throws RemoteException { 3270 // NOTE: This combination (receiving the onOpChanged broadcast for a package, the permission 3271 // being now granted, AND having previously posted notifications from said package) should 3272 // never happen (if we trust the broadcasts are correct). So this test is for a what-if 3273 // scenario, to verify we still handle it reasonably. 3274 3275 // Have preexisting posted notifications from specific package and other packages. 3276 mService.addNotification(new NotificationRecord(mContext, 3277 generateSbn("granted", 1001, 1, 0), mTestNotificationChannel)); 3278 mService.addNotification(new NotificationRecord(mContext, 3279 generateSbn("other", 1002, 2, 0), mTestNotificationChannel)); 3280 // Have preexisting enqueued notifications from specific package and other packages. 3281 mService.addEnqueuedNotification(new NotificationRecord(mContext, 3282 generateSbn("granted", 1001, 3, 0), mTestNotificationChannel)); 3283 mService.addEnqueuedNotification(new NotificationRecord(mContext, 3284 generateSbn("other", 1002, 4, 0), mTestNotificationChannel)); 3285 assertThat(mService.mNotificationList).hasSize(2); 3286 assertThat(mService.mEnqueuedNotifications).hasSize(2); 3287 3288 when(mPackageManagerInternal.getPackageUid("granted", 0, 0)).thenReturn(1001); 3289 when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(true); 3290 3291 mOnPermissionChangeListener.onOpChanged( 3292 AppOpsManager.OPSTR_POST_NOTIFICATION, "granted", 0); 3293 waitForIdle(); 3294 3295 assertThat(mService.mNotificationList).hasSize(2); 3296 assertThat(mService.mEnqueuedNotifications).hasSize(2); 3297 } 3298 3299 @Test onOpChanged_notInitializedUser_ignored()3300 public void onOpChanged_notInitializedUser_ignored() throws RemoteException { 3301 when(mUmInternal.isUserInitialized(eq(0))).thenReturn(false); 3302 3303 mOnPermissionChangeListener.onOpChanged( 3304 AppOpsManager.OPSTR_POST_NOTIFICATION, "package", 0); 3305 waitForIdle(); 3306 3307 // We early-exited and didn't even query PM for package details. 3308 verify(mPackageManagerInternal, never()).getPackageUid(any(), anyLong(), anyInt()); 3309 } 3310 3311 @Test setNotificationsEnabledForPackage_disabling_clearsNotifications()3312 public void setNotificationsEnabledForPackage_disabling_clearsNotifications() throws Exception { 3313 mService.addNotification(new NotificationRecord(mContext, 3314 generateSbn("package", 1001, 1, 0), mTestNotificationChannel)); 3315 assertThat(mService.mNotificationList).hasSize(1); 3316 when(mPackageManagerInternal.getPackageUid("package", 0, 0)).thenReturn(1001); 3317 when(mPermissionHelper.hasRequestedPermission(any(), eq("package"), anyInt())).thenReturn( 3318 true); 3319 3320 // Start with granted permission and simulate effect of revoking it. 3321 when(mPermissionHelper.hasPermission(1001)).thenReturn(true); 3322 doAnswer(invocation -> { 3323 when(mPermissionHelper.hasPermission(1001)).thenReturn(false); 3324 mOnPermissionChangeListener.onOpChanged( 3325 AppOpsManager.OPSTR_POST_NOTIFICATION, "package", 0); 3326 return null; 3327 }).when(mPermissionHelper).setNotificationPermission("package", 0, false, true); 3328 3329 mBinderService.setNotificationsEnabledForPackage("package", 1001, false); 3330 waitForIdle(); 3331 3332 assertThat(mService.mNotificationList).hasSize(0); 3333 3334 mTestableLooper.moveTimeForward(500); 3335 waitForIdle(); 3336 verify(mContext).sendBroadcastAsUser(any(), eq(UserHandle.of(0)), eq(null)); 3337 } 3338 3339 @Test testUpdateAppNotifyCreatorBlock()3340 public void testUpdateAppNotifyCreatorBlock() throws Exception { 3341 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 3342 3343 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); 3344 Thread.sleep(500); 3345 waitForIdle(); 3346 3347 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3348 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3349 3350 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED, 3351 captor.getValue().getAction()); 3352 assertEquals(PKG, captor.getValue().getPackage()); 3353 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true)); 3354 } 3355 3356 @Test testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting()3357 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception { 3358 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 3359 3360 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false); 3361 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 3362 } 3363 3364 @Test testUpdateAppNotifyCreatorUnblock()3365 public void testUpdateAppNotifyCreatorUnblock() throws Exception { 3366 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 3367 3368 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, true); 3369 Thread.sleep(500); 3370 waitForIdle(); 3371 3372 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3373 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3374 3375 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED, 3376 captor.getValue().getAction()); 3377 assertEquals(PKG, captor.getValue().getPackage()); 3378 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true)); 3379 } 3380 3381 @Test testUpdateChannelNotifyCreatorBlock()3382 public void testUpdateChannelNotifyCreatorBlock() throws Exception { 3383 mService.setPreferencesHelper(mPreferencesHelper); 3384 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3385 eq(mTestNotificationChannel.getId()), anyBoolean())) 3386 .thenReturn(mTestNotificationChannel); 3387 3388 NotificationChannel updatedChannel = 3389 new NotificationChannel(mTestNotificationChannel.getId(), 3390 mTestNotificationChannel.getName(), IMPORTANCE_NONE); 3391 3392 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel); 3393 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3394 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3395 3396 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, 3397 captor.getValue().getAction()); 3398 assertEquals(PKG, captor.getValue().getPackage()); 3399 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra( 3400 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID)); 3401 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 3402 } 3403 3404 @Test testUpdateChannelNotifyCreatorUnblock()3405 public void testUpdateChannelNotifyCreatorUnblock() throws Exception { 3406 NotificationChannel existingChannel = 3407 new NotificationChannel(mTestNotificationChannel.getId(), 3408 mTestNotificationChannel.getName(), IMPORTANCE_NONE); 3409 mService.setPreferencesHelper(mPreferencesHelper); 3410 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3411 eq(mTestNotificationChannel.getId()), anyBoolean())) 3412 .thenReturn(existingChannel); 3413 3414 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 3415 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3416 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3417 3418 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, 3419 captor.getValue().getAction()); 3420 assertEquals(PKG, captor.getValue().getPackage()); 3421 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra( 3422 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID)); 3423 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 3424 } 3425 3426 @Test testUpdateChannelNoNotifyCreatorOtherChanges()3427 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception { 3428 NotificationChannel existingChannel = 3429 new NotificationChannel(mTestNotificationChannel.getId(), 3430 mTestNotificationChannel.getName(), IMPORTANCE_MAX); 3431 mService.setPreferencesHelper(mPreferencesHelper); 3432 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3433 eq(mTestNotificationChannel.getId()), anyBoolean())) 3434 .thenReturn(existingChannel); 3435 3436 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 3437 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 3438 } 3439 3440 @Test testUpdateGroupNotifyCreatorBlock()3441 public void testUpdateGroupNotifyCreatorBlock() throws Exception { 3442 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 3443 mService.setPreferencesHelper(mPreferencesHelper); 3444 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), 3445 eq(PKG), anyInt())) 3446 .thenReturn(existing); 3447 3448 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name"); 3449 updated.setBlocked(true); 3450 3451 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated); 3452 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3453 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3454 3455 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED, 3456 captor.getValue().getAction()); 3457 assertEquals(PKG, captor.getValue().getPackage()); 3458 assertEquals(existing.getId(), captor.getValue().getStringExtra( 3459 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID)); 3460 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 3461 } 3462 3463 @Test testUpdateGroupNotifyCreatorUnblock()3464 public void testUpdateGroupNotifyCreatorUnblock() throws Exception { 3465 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 3466 existing.setBlocked(true); 3467 mService.setPreferencesHelper(mPreferencesHelper); 3468 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), 3469 eq(PKG), anyInt())) 3470 .thenReturn(existing); 3471 3472 mBinderService.updateNotificationChannelGroupForPackage( 3473 PKG, 0, new NotificationChannelGroup("id", "name")); 3474 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3475 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3476 3477 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED, 3478 captor.getValue().getAction()); 3479 assertEquals(PKG, captor.getValue().getPackage()); 3480 assertEquals(existing.getId(), captor.getValue().getStringExtra( 3481 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID)); 3482 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 3483 } 3484 3485 @Test testUpdateGroupNoNotifyCreatorOtherChanges()3486 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception { 3487 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 3488 mService.setPreferencesHelper(mPreferencesHelper); 3489 when(mPreferencesHelper.getNotificationChannelGroup( 3490 eq(existing.getId()), eq(PKG), anyInt())) 3491 .thenReturn(existing); 3492 3493 mBinderService.updateNotificationChannelGroupForPackage( 3494 PKG, 0, new NotificationChannelGroup("id", "new name")); 3495 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 3496 } 3497 3498 @Test testCreateChannelNotifyListener()3499 public void testCreateChannelNotifyListener() throws Exception { 3500 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3501 .thenReturn(singletonList(mock(AssociationInfo.class))); 3502 mService.setPreferencesHelper(mPreferencesHelper); 3503 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3504 eq(mTestNotificationChannel.getId()), anyBoolean())) 3505 .thenReturn(mTestNotificationChannel); 3506 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW); 3507 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3508 eq(channel2.getId()), anyBoolean())) 3509 .thenReturn(channel2); 3510 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(), 3511 eq(channel2), anyBoolean(), anyBoolean(), anyInt(), anyBoolean())) 3512 .thenReturn(true); 3513 3514 reset(mListeners); 3515 mBinderService.createNotificationChannels(PKG, 3516 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2))); 3517 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 3518 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3519 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 3520 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 3521 eq(Process.myUserHandle()), eq(channel2), 3522 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 3523 } 3524 3525 @Test testCreateChannelGroupNotifyListener()3526 public void testCreateChannelGroupNotifyListener() throws Exception { 3527 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3528 .thenReturn(singletonList(mock(AssociationInfo.class))); 3529 mService.setPreferencesHelper(mPreferencesHelper); 3530 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b"); 3531 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m"); 3532 3533 reset(mListeners); 3534 mBinderService.createNotificationChannelGroups(PKG, 3535 new ParceledListSlice(Arrays.asList(group1, group2))); 3536 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 3537 eq(Process.myUserHandle()), eq(group1), 3538 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 3539 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 3540 eq(Process.myUserHandle()), eq(group2), 3541 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 3542 } 3543 3544 @Test testUpdateChannelNotifyListener()3545 public void testUpdateChannelNotifyListener() throws Exception { 3546 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3547 .thenReturn(singletonList(mock(AssociationInfo.class))); 3548 mService.setPreferencesHelper(mPreferencesHelper); 3549 mTestNotificationChannel.setLightColor(Color.CYAN); 3550 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3551 eq(mTestNotificationChannel.getId()), anyBoolean())) 3552 .thenReturn(mTestNotificationChannel); 3553 3554 reset(mListeners); 3555 mBinderService.updateNotificationChannelForPackage(PKG, mUid, mTestNotificationChannel); 3556 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 3557 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3558 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 3559 } 3560 3561 @Test testDeleteChannelNotifyListener()3562 public void testDeleteChannelNotifyListener() throws Exception { 3563 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3564 .thenReturn(singletonList(mock(AssociationInfo.class))); 3565 mService.setPreferencesHelper(mPreferencesHelper); 3566 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3567 eq(mTestNotificationChannel.getId()), anyBoolean())) 3568 .thenReturn(mTestNotificationChannel); 3569 when(mPreferencesHelper.deleteNotificationChannel(eq(PKG), anyInt(), 3570 eq(mTestNotificationChannel.getId()), anyInt(), anyBoolean())).thenReturn(true); 3571 reset(mListeners); 3572 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId()); 3573 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 3574 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3575 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); 3576 } 3577 3578 @Test testDeleteChannelOnlyDoExtraWorkIfExisted()3579 public void testDeleteChannelOnlyDoExtraWorkIfExisted() throws Exception { 3580 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3581 .thenReturn(singletonList(mock(AssociationInfo.class))); 3582 mService.setPreferencesHelper(mPreferencesHelper); 3583 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3584 eq(mTestNotificationChannel.getId()), anyBoolean())) 3585 .thenReturn(null); 3586 reset(mListeners); 3587 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId()); 3588 verifyNoMoreInteractions(mListeners); 3589 verifyNoMoreInteractions(mHistoryManager); 3590 } 3591 3592 @Test testDeleteChannelGroupNotifyListener()3593 public void testDeleteChannelGroupNotifyListener() throws Exception { 3594 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3595 .thenReturn(singletonList(mock(AssociationInfo.class))); 3596 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c"); 3597 mService.setPreferencesHelper(mPreferencesHelper); 3598 when(mPreferencesHelper.getNotificationChannelGroupWithChannels( 3599 eq(PKG), anyInt(), eq(ncg.getId()), anyBoolean())) 3600 .thenReturn(ncg); 3601 reset(mListeners); 3602 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId()); 3603 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 3604 eq(Process.myUserHandle()), eq(ncg), 3605 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); 3606 } 3607 3608 @Test testDeleteChannelGroupChecksForFgses()3609 public void testDeleteChannelGroupChecksForFgses() throws Exception { 3610 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3611 .thenReturn(singletonList(mock(AssociationInfo.class))); 3612 CountDownLatch latch = new CountDownLatch(2); 3613 mService.createNotificationChannelGroup( 3614 PKG, mUid, new NotificationChannelGroup("group", "group"), true, false); 3615 new Thread(() -> { 3616 NotificationChannel notificationChannel = new NotificationChannel("id", "id", 3617 NotificationManager.IMPORTANCE_HIGH); 3618 notificationChannel.setGroup("group"); 3619 ParceledListSlice<NotificationChannel> pls = 3620 new ParceledListSlice(ImmutableList.of(notificationChannel)); 3621 try { 3622 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); 3623 } catch (RemoteException e) { 3624 throw new RuntimeException(e); 3625 } 3626 latch.countDown(); 3627 }).start(); 3628 new Thread(() -> { 3629 try { 3630 synchronized (this) { 3631 wait(5000); 3632 } 3633 mService.createNotificationChannelGroup(PKG, mUid, 3634 new NotificationChannelGroup("new", "new group"), true, false); 3635 NotificationChannel notificationChannel = 3636 new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH); 3637 notificationChannel.setGroup("new"); 3638 ParceledListSlice<NotificationChannel> pls = 3639 new ParceledListSlice(ImmutableList.of(notificationChannel)); 3640 try { 3641 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); 3642 mBinderService.deleteNotificationChannelGroup(PKG, "group"); 3643 } catch (RemoteException e) { 3644 throw new RuntimeException(e); 3645 } 3646 } catch (Exception e) { 3647 e.printStackTrace(); 3648 } 3649 latch.countDown(); 3650 }).start(); 3651 3652 latch.await(); 3653 verify(mAmi).hasForegroundServiceNotification(anyString(), anyInt(), anyString()); 3654 } 3655 3656 @Test testUpdateNotificationChannelFromPrivilegedListener_success()3657 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception { 3658 mService.setPreferencesHelper(mPreferencesHelper); 3659 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3660 .thenReturn(singletonList(mock(AssociationInfo.class))); 3661 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3662 eq(mTestNotificationChannel.getId()), anyBoolean())) 3663 .thenReturn(mTestNotificationChannel); 3664 3665 mBinderService.updateNotificationChannelFromPrivilegedListener( 3666 null, PKG, Process.myUserHandle(), mTestNotificationChannel); 3667 3668 verify(mPreferencesHelper, times(1)).updateNotificationChannel( 3669 anyString(), anyInt(), any(), anyBoolean(), anyInt(), anyBoolean()); 3670 3671 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 3672 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3673 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 3674 } 3675 3676 @Test testUpdateNotificationChannelFromPrivilegedListener_noAccess()3677 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception { 3678 mService.setPreferencesHelper(mPreferencesHelper); 3679 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3680 .thenReturn(emptyList()); 3681 3682 try { 3683 mBinderService.updateNotificationChannelFromPrivilegedListener( 3684 null, PKG, Process.myUserHandle(), mTestNotificationChannel); 3685 fail("listeners that don't have a companion device shouldn't be able to call this"); 3686 } catch (SecurityException e) { 3687 // pass 3688 } 3689 3690 verify(mPreferencesHelper, never()).updateNotificationChannel( 3691 anyString(), anyInt(), any(), anyBoolean(), anyInt(), anyBoolean()); 3692 3693 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 3694 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3695 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 3696 } 3697 3698 @Test testUpdateNotificationChannelFromPrivilegedListener_badUser()3699 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception { 3700 mService.setPreferencesHelper(mPreferencesHelper); 3701 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3702 .thenReturn(singletonList(mock(AssociationInfo.class))); 3703 mListener = mock(ManagedServices.ManagedServiceInfo.class); 3704 mListener.component = new ComponentName(PKG, PKG); 3705 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 3706 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 3707 3708 try { 3709 mBinderService.updateNotificationChannelFromPrivilegedListener( 3710 null, PKG, UserHandle.ALL, mTestNotificationChannel); 3711 fail("incorrectly allowed a change to a user listener cannot see"); 3712 } catch (SecurityException e) { 3713 // pass 3714 } 3715 3716 verify(mPreferencesHelper, never()).updateNotificationChannel( 3717 anyString(), anyInt(), any(), anyBoolean(), anyInt(), anyBoolean()); 3718 3719 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 3720 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3721 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 3722 } 3723 3724 @Test testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission()3725 public void testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission() 3726 throws Exception { 3727 mService.setPreferencesHelper(mPreferencesHelper); 3728 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3729 .thenReturn(singletonList(mock(AssociationInfo.class))); 3730 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3731 eq(mTestNotificationChannel.getId()), anyBoolean())) 3732 .thenReturn(mTestNotificationChannel); 3733 3734 final Uri soundUri = Uri.parse("content://media/test/sound/uri"); 3735 final NotificationChannel updatedNotificationChannel = new NotificationChannel( 3736 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 3737 updatedNotificationChannel.setSound(soundUri, 3738 updatedNotificationChannel.getAudioAttributes()); 3739 3740 doThrow(new SecurityException("no access")).when(mUgmInternal) 3741 .checkGrantUriPermission(eq(Process.myUid()), any(), eq(soundUri), 3742 anyInt(), eq(Process.myUserHandle().getIdentifier())); 3743 3744 assertThrows(SecurityException.class, 3745 () -> mBinderService.updateNotificationChannelFromPrivilegedListener(null, PKG, 3746 Process.myUserHandle(), updatedNotificationChannel)); 3747 3748 verify(mPreferencesHelper, never()).updateNotificationChannel( 3749 anyString(), anyInt(), any(), anyBoolean(), anyInt(), anyBoolean()); 3750 3751 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 3752 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3753 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 3754 } 3755 3756 @Test testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission_sameSound()3757 public void testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission_sameSound() 3758 throws Exception { 3759 mService.setPreferencesHelper(mPreferencesHelper); 3760 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3761 .thenReturn(singletonList(mock(AssociationInfo.class))); 3762 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3763 eq(mTestNotificationChannel.getId()), anyBoolean())) 3764 .thenReturn(mTestNotificationChannel); 3765 3766 final Uri soundUri = Settings.System.DEFAULT_NOTIFICATION_URI; 3767 final NotificationChannel updatedNotificationChannel = new NotificationChannel( 3768 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 3769 updatedNotificationChannel.setSound(soundUri, 3770 updatedNotificationChannel.getAudioAttributes()); 3771 3772 doThrow(new SecurityException("no access")).when(mUgmInternal) 3773 .checkGrantUriPermission(eq(Process.myUid()), any(), eq(soundUri), 3774 anyInt(), eq(Process.myUserHandle().getIdentifier())); 3775 3776 mBinderService.updateNotificationChannelFromPrivilegedListener( 3777 null, PKG, Process.myUserHandle(), updatedNotificationChannel); 3778 3779 verify(mPreferencesHelper, times(1)).updateNotificationChannel( 3780 anyString(), anyInt(), any(), anyBoolean(), anyInt(), anyBoolean()); 3781 3782 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 3783 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3784 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 3785 } 3786 3787 @Test testGetNotificationChannelFromPrivilegedListener_cdm_success()3788 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception { 3789 mService.setPreferencesHelper(mPreferencesHelper); 3790 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3791 .thenReturn(singletonList(mock(AssociationInfo.class))); 3792 3793 mBinderService.getNotificationChannelsFromPrivilegedListener( 3794 null, PKG, Process.myUserHandle()); 3795 3796 verify(mPreferencesHelper, times(1)).getNotificationChannels( 3797 anyString(), anyInt(), anyBoolean()); 3798 } 3799 3800 @Test testGetNotificationChannelFromPrivilegedListener_cdm_noAccess()3801 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception { 3802 mService.setPreferencesHelper(mPreferencesHelper); 3803 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3804 .thenReturn(emptyList()); 3805 3806 try { 3807 mBinderService.getNotificationChannelsFromPrivilegedListener( 3808 null, PKG, Process.myUserHandle()); 3809 fail("listeners that don't have a companion device shouldn't be able to call this"); 3810 } catch (SecurityException e) { 3811 // pass 3812 } 3813 3814 verify(mPreferencesHelper, never()).getNotificationChannels( 3815 anyString(), anyInt(), anyBoolean()); 3816 } 3817 3818 @Test testGetNotificationChannelFromPrivilegedListener_assistant_success()3819 public void testGetNotificationChannelFromPrivilegedListener_assistant_success() 3820 throws Exception { 3821 mService.setPreferencesHelper(mPreferencesHelper); 3822 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3823 .thenReturn(emptyList()); 3824 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); 3825 3826 mBinderService.getNotificationChannelsFromPrivilegedListener( 3827 null, PKG, Process.myUserHandle()); 3828 3829 verify(mPreferencesHelper, times(1)).getNotificationChannels( 3830 anyString(), anyInt(), anyBoolean()); 3831 } 3832 3833 @Test testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()3834 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess() 3835 throws Exception { 3836 mService.setPreferencesHelper(mPreferencesHelper); 3837 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3838 .thenReturn(emptyList()); 3839 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false); 3840 3841 try { 3842 mBinderService.getNotificationChannelsFromPrivilegedListener( 3843 null, PKG, Process.myUserHandle()); 3844 fail("listeners that don't have a companion device shouldn't be able to call this"); 3845 } catch (SecurityException e) { 3846 // pass 3847 } 3848 3849 verify(mPreferencesHelper, never()).getNotificationChannels( 3850 anyString(), anyInt(), anyBoolean()); 3851 } 3852 3853 @Test testGetNotificationChannelFromPrivilegedListener_badUser()3854 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception { 3855 mService.setPreferencesHelper(mPreferencesHelper); 3856 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3857 .thenReturn(singletonList(mock(AssociationInfo.class))); 3858 mListener = mock(ManagedServices.ManagedServiceInfo.class); 3859 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 3860 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 3861 3862 try { 3863 mBinderService.getNotificationChannelsFromPrivilegedListener( 3864 null, PKG, Process.myUserHandle()); 3865 fail("listener getting channels from a user they cannot see"); 3866 } catch (SecurityException e) { 3867 // pass 3868 } 3869 3870 verify(mPreferencesHelper, never()).getNotificationChannels( 3871 anyString(), anyInt(), anyBoolean()); 3872 } 3873 3874 @Test testGetNotificationChannelGroupsFromPrivilegedListener_success()3875 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception { 3876 mService.setPreferencesHelper(mPreferencesHelper); 3877 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3878 .thenReturn(singletonList(mock(AssociationInfo.class))); 3879 3880 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 3881 null, PKG, Process.myUserHandle()); 3882 3883 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt()); 3884 } 3885 3886 @Test testGetNotificationChannelGroupsFromPrivilegedListener_noAccess()3887 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception { 3888 mService.setPreferencesHelper(mPreferencesHelper); 3889 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3890 .thenReturn(emptyList()); 3891 3892 try { 3893 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 3894 null, PKG, Process.myUserHandle()); 3895 fail("listeners that don't have a companion device shouldn't be able to call this"); 3896 } catch (SecurityException e) { 3897 // pass 3898 } 3899 3900 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); 3901 } 3902 3903 @Test testGetNotificationChannelGroupsFromPrivilegedListener_badUser()3904 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception { 3905 mService.setPreferencesHelper(mPreferencesHelper); 3906 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3907 .thenReturn(emptyList()); 3908 mListener = mock(ManagedServices.ManagedServiceInfo.class); 3909 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 3910 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 3911 try { 3912 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 3913 null, PKG, Process.myUserHandle()); 3914 fail("listeners that don't have a companion device shouldn't be able to call this"); 3915 } catch (SecurityException e) { 3916 // pass 3917 } 3918 3919 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); 3920 } 3921 3922 @Test testHasCompanionDevice_failure()3923 public void testHasCompanionDevice_failure() throws Exception { 3924 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow( 3925 new IllegalArgumentException()); 3926 mService.hasCompanionDevice(mListener); 3927 } 3928 3929 @Test testHasCompanionDevice_noService()3930 public void testHasCompanionDevice_noService() { 3931 NotificationManagerService noManService = 3932 new TestableNotificationManagerService(mContext, mNotificationRecordLogger, 3933 mNotificationInstanceIdSequence); 3934 3935 assertFalse(noManService.hasCompanionDevice(mListener)); 3936 } 3937 3938 @Test testCrossUserSnooze()3939 public void testCrossUserSnooze() { 3940 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10); 3941 mService.addNotification(r); 3942 NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0); 3943 mService.addNotification(r2); 3944 3945 mListener = mock(ManagedServices.ManagedServiceInfo.class); 3946 mListener.component = new ComponentName(PKG, PKG); 3947 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 3948 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 3949 3950 mService.snoozeNotificationInt(r.getKey(), 1000, null, mListener); 3951 3952 verify(mWorkerHandler, never()).post( 3953 any(NotificationManagerService.SnoozeNotificationRunnable.class)); 3954 } 3955 3956 @Test testSameUserSnooze()3957 public void testSameUserSnooze() { 3958 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10); 3959 mService.addNotification(r); 3960 NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0); 3961 mService.addNotification(r2); 3962 3963 mListener = mock(ManagedServices.ManagedServiceInfo.class); 3964 mListener.component = new ComponentName(PKG, PKG); 3965 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(true); 3966 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 3967 3968 mService.snoozeNotificationInt(r2.getKey(), 1000, null, mListener); 3969 3970 verify(mWorkerHandler).post( 3971 any(NotificationManagerService.SnoozeNotificationRunnable.class)); 3972 } 3973 3974 @Test testSnoozeRunnable_tooManySnoozed_singleNotification()3975 public void testSnoozeRunnable_tooManySnoozed_singleNotification() { 3976 final NotificationRecord notification = generateNotificationRecord( 3977 mTestNotificationChannel, 1, null, true); 3978 mService.addNotification(notification); 3979 3980 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 3981 when(mSnoozeHelper.canSnooze(1)).thenReturn(false); 3982 3983 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 3984 mService.new SnoozeNotificationRunnable( 3985 notification.getKey(), 100, null); 3986 snoozeNotificationRunnable.run(); 3987 3988 verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong()); 3989 assertThat(mService.getNotificationRecordCount()).isEqualTo(1); 3990 } 3991 3992 @Test testSnoozeRunnable_tooManySnoozed_singleGroupChildNotification()3993 public void testSnoozeRunnable_tooManySnoozed_singleGroupChildNotification() { 3994 final NotificationRecord notification = generateNotificationRecord( 3995 mTestNotificationChannel, 1, "group", true); 3996 final NotificationRecord notificationChild = generateNotificationRecord( 3997 mTestNotificationChannel, 1, "group", false); 3998 mService.addNotification(notification); 3999 mService.addNotification(notificationChild); 4000 4001 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4002 when(mSnoozeHelper.canSnooze(2)).thenReturn(false); 4003 4004 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4005 mService.new SnoozeNotificationRunnable( 4006 notificationChild.getKey(), 100, null); 4007 snoozeNotificationRunnable.run(); 4008 4009 verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong()); 4010 assertThat(mService.getNotificationRecordCount()).isEqualTo(2); 4011 } 4012 4013 @Test testSnoozeRunnable_tooManySnoozed_summaryNotification()4014 public void testSnoozeRunnable_tooManySnoozed_summaryNotification() { 4015 final NotificationRecord notification = generateNotificationRecord( 4016 mTestNotificationChannel, 1, "group", true); 4017 final NotificationRecord notificationChild = generateNotificationRecord( 4018 mTestNotificationChannel, 12, "group", false); 4019 final NotificationRecord notificationChild2 = generateNotificationRecord( 4020 mTestNotificationChannel, 13, "group", false); 4021 mService.addNotification(notification); 4022 mService.addNotification(notificationChild); 4023 mService.addNotification(notificationChild2); 4024 4025 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4026 when(mSnoozeHelper.canSnooze(3)).thenReturn(false); 4027 4028 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4029 mService.new SnoozeNotificationRunnable( 4030 notification.getKey(), 100, null); 4031 snoozeNotificationRunnable.run(); 4032 4033 verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong()); 4034 assertThat(mService.getNotificationRecordCount()).isEqualTo(3); 4035 } 4036 4037 @Test testSnoozeRunnable_reSnoozeASingleSnoozedNotification()4038 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() { 4039 final NotificationRecord notification = generateNotificationRecord( 4040 mTestNotificationChannel, 1, null, true); 4041 mService.addNotification(notification); 4042 when(mSnoozeHelper.getNotification(any())).thenReturn(notification); 4043 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4044 4045 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4046 mService.new SnoozeNotificationRunnable( 4047 notification.getKey(), 100, null); 4048 snoozeNotificationRunnable.run(); 4049 snoozeNotificationRunnable.run(); 4050 4051 // snooze twice 4052 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 4053 } 4054 4055 @Test testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey()4056 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() { 4057 final NotificationRecord notification = generateNotificationRecord( 4058 mTestNotificationChannel, 1, "group", true); 4059 mService.addNotification(notification); 4060 when(mSnoozeHelper.getNotification(any())).thenReturn(notification); 4061 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4062 4063 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4064 mService.new SnoozeNotificationRunnable( 4065 notification.getKey(), 100, null); 4066 snoozeNotificationRunnable.run(); 4067 snoozeNotificationRunnable.run(); 4068 4069 // snooze twice 4070 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 4071 } 4072 4073 @Test testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey()4074 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception { 4075 final NotificationRecord notification = generateNotificationRecord( 4076 mTestNotificationChannel, 1, "group", true); 4077 final NotificationRecord notification2 = generateNotificationRecord( 4078 mTestNotificationChannel, 2, "group", true); 4079 mService.addNotification(notification); 4080 mService.addNotification(notification2); 4081 when(mSnoozeHelper.getNotification(any())).thenReturn(notification); 4082 when(mSnoozeHelper.getNotifications( 4083 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>()); 4084 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4085 4086 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4087 mService.new SnoozeNotificationRunnable( 4088 notification.getKey(), 100, null); 4089 snoozeNotificationRunnable.run(); 4090 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt())) 4091 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2))); 4092 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 = 4093 mService.new SnoozeNotificationRunnable( 4094 notification2.getKey(), 100, null); 4095 snoozeNotificationRunnable2.run(); 4096 4097 // snooze twice 4098 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong()); 4099 } 4100 4101 @Test testSnoozeRunnable_snoozeNonGrouped()4102 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception { 4103 final NotificationRecord nonGrouped = generateNotificationRecord( 4104 mTestNotificationChannel, 1, null, false); 4105 final NotificationRecord grouped = generateNotificationRecord( 4106 mTestNotificationChannel, 2, "group", false); 4107 mService.addNotification(grouped); 4108 mService.addNotification(nonGrouped); 4109 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4110 4111 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4112 mService.new SnoozeNotificationRunnable( 4113 nonGrouped.getKey(), 100, null); 4114 snoozeNotificationRunnable.run(); 4115 4116 // only snooze the one notification 4117 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 4118 assertTrue(nonGrouped.getStats().hasSnoozed()); 4119 4120 assertEquals(2, mNotificationRecordLogger.numCalls()); 4121 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4122 mNotificationRecordLogger.event(0)); 4123 assertEquals( 4124 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 4125 mNotificationRecordLogger.event(1)); 4126 } 4127 4128 @Test testSnoozeRunnable_snoozeSummary_withChildren()4129 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception { 4130 final NotificationRecord parent = generateNotificationRecord( 4131 mTestNotificationChannel, 1, "group", true); 4132 final NotificationRecord child = generateNotificationRecord( 4133 mTestNotificationChannel, 2, "group", false); 4134 final NotificationRecord child2 = generateNotificationRecord( 4135 mTestNotificationChannel, 3, "group", false); 4136 mService.addNotification(parent); 4137 mService.addNotification(child); 4138 mService.addNotification(child2); 4139 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4140 4141 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4142 mService.new SnoozeNotificationRunnable( 4143 parent.getKey(), 100, null); 4144 snoozeNotificationRunnable.run(); 4145 4146 // snooze parent and children 4147 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong()); 4148 } 4149 4150 @Test testSnoozeRunnable_snoozeGroupChild_fellowChildren()4151 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception { 4152 final NotificationRecord parent = generateNotificationRecord( 4153 mTestNotificationChannel, 1, "group", true); 4154 final NotificationRecord child = generateNotificationRecord( 4155 mTestNotificationChannel, 2, "group", false); 4156 final NotificationRecord child2 = generateNotificationRecord( 4157 mTestNotificationChannel, 3, "group", false); 4158 mService.addNotification(parent); 4159 mService.addNotification(child); 4160 mService.addNotification(child2); 4161 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4162 4163 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4164 mService.new SnoozeNotificationRunnable( 4165 child2.getKey(), 100, null); 4166 snoozeNotificationRunnable.run(); 4167 4168 // only snooze the one child 4169 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 4170 4171 assertEquals(2, mNotificationRecordLogger.numCalls()); 4172 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4173 mNotificationRecordLogger.event(0)); 4174 assertEquals(NotificationRecordLogger.NotificationCancelledEvent 4175 .NOTIFICATION_CANCEL_SNOOZED, mNotificationRecordLogger.event(1)); 4176 } 4177 4178 @Test testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary()4179 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception { 4180 final NotificationRecord parent = generateNotificationRecord( 4181 mTestNotificationChannel, 1, "group", true); 4182 assertTrue(parent.getSbn().getNotification().isGroupSummary()); 4183 final NotificationRecord child = generateNotificationRecord( 4184 mTestNotificationChannel, 2, "group", false); 4185 mService.addNotification(parent); 4186 mService.addNotification(child); 4187 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4188 4189 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4190 mService.new SnoozeNotificationRunnable( 4191 child.getKey(), 100, null); 4192 snoozeNotificationRunnable.run(); 4193 4194 // snooze child and summary 4195 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 4196 4197 assertEquals(4, mNotificationRecordLogger.numCalls()); 4198 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4199 mNotificationRecordLogger.event(0)); 4200 assertEquals( 4201 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 4202 mNotificationRecordLogger.event(1)); 4203 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4204 mNotificationRecordLogger.event(2)); 4205 assertEquals( 4206 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 4207 mNotificationRecordLogger.event(3)); 4208 } 4209 4210 @Test testSnoozeRunnable_snoozeGroupChild_noOthersInGroup()4211 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception { 4212 final NotificationRecord child = generateNotificationRecord( 4213 mTestNotificationChannel, 2, "group", false); 4214 mService.addNotification(child); 4215 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4216 4217 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4218 mService.new SnoozeNotificationRunnable( 4219 child.getKey(), 100, null); 4220 snoozeNotificationRunnable.run(); 4221 4222 // snooze child only 4223 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 4224 4225 assertEquals(2, mNotificationRecordLogger.numCalls()); 4226 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4227 mNotificationRecordLogger.event(0)); 4228 assertEquals( 4229 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 4230 mNotificationRecordLogger.event(1)); 4231 } 4232 4233 @Test testSnoozeRunnable_snoozeAutoGroupChild_summaryNotSnoozed()4234 public void testSnoozeRunnable_snoozeAutoGroupChild_summaryNotSnoozed() throws Exception { 4235 final NotificationRecord parent = generateNotificationRecord( 4236 mTestNotificationChannel, 1, GroupHelper.AUTOGROUP_KEY, true); 4237 final NotificationRecord child = generateNotificationRecord( 4238 mTestNotificationChannel, 2, GroupHelper.AUTOGROUP_KEY, false); 4239 mService.addNotification(parent); 4240 mService.addNotification(child); 4241 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4242 4243 // snooze child only 4244 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4245 mService.new SnoozeNotificationRunnable( 4246 child.getKey(), 100, null); 4247 snoozeNotificationRunnable.run(); 4248 4249 // only child should be snoozed 4250 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 4251 4252 // both group summary and child should be cancelled 4253 assertNull(mService.getNotificationRecord(parent.getKey())); 4254 assertNull(mService.getNotificationRecord(child.getKey())); 4255 4256 assertEquals(4, mNotificationRecordLogger.numCalls()); 4257 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4258 mNotificationRecordLogger.event(0)); 4259 assertEquals( 4260 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 4261 mNotificationRecordLogger.event(1)); 4262 } 4263 4264 @Test testPostGroupChild_unsnoozeParent()4265 public void testPostGroupChild_unsnoozeParent() throws Exception { 4266 final NotificationRecord child = generateNotificationRecord( 4267 mTestNotificationChannel, 2, "group", false); 4268 4269 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing", 4270 child.getSbn().getId(), child.getSbn().getNotification(), 4271 child.getSbn().getUserId()); 4272 waitForIdle(); 4273 4274 verify(mSnoozeHelper, times(1)).repostGroupSummary( 4275 anyString(), anyInt(), eq(child.getGroupKey())); 4276 } 4277 4278 @Test testPostNonGroup_noUnsnoozing()4279 public void testPostNonGroup_noUnsnoozing() throws Exception { 4280 final NotificationRecord record = generateNotificationRecord( 4281 mTestNotificationChannel, 2, null, false); 4282 4283 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing", 4284 record.getSbn().getId(), record.getSbn().getNotification(), 4285 record.getSbn().getUserId()); 4286 waitForIdle(); 4287 4288 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); 4289 } 4290 4291 @Test testPostGroupSummary_noUnsnoozing()4292 public void testPostGroupSummary_noUnsnoozing() throws Exception { 4293 final NotificationRecord parent = generateNotificationRecord( 4294 mTestNotificationChannel, 2, "group", true); 4295 4296 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing", 4297 parent.getSbn().getId(), parent.getSbn().getNotification(), 4298 parent.getSbn().getUserId()); 4299 waitForIdle(); 4300 4301 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); 4302 } 4303 4304 @Test testSystemNotificationListenerCanUnsnooze()4305 public void testSystemNotificationListenerCanUnsnooze() throws Exception { 4306 final NotificationRecord nr = generateNotificationRecord( 4307 mTestNotificationChannel, 2, "group", false); 4308 4309 mBinderService.enqueueNotificationWithTag(PKG, PKG, 4310 "testSystemNotificationListenerCanUnsnooze", 4311 nr.getSbn().getId(), nr.getSbn().getNotification(), 4312 nr.getSbn().getUserId()); 4313 waitForIdle(); 4314 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4315 mService.new SnoozeNotificationRunnable( 4316 nr.getKey(), 100, null); 4317 snoozeNotificationRunnable.run(); 4318 4319 ManagedServices.ManagedServiceInfo listener = mListeners.new ManagedServiceInfo( 4320 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0, 234); 4321 listener.isSystem = true; 4322 when(mListeners.checkServiceTokenLocked(any())).thenReturn(listener); 4323 4324 mBinderService.unsnoozeNotificationFromSystemListener(null, nr.getKey()); 4325 waitForIdle(); 4326 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 4327 assertEquals(1, notifs.length); 4328 assertNotNull(notifs[0].getKey());//mService.getNotificationRecord(nr.getSbn().getKey())); 4329 } 4330 4331 @Test testSetListenerAccessForUser()4332 public void testSetListenerAccessForUser() throws Exception { 4333 UserHandle user = UserHandle.of(mContext.getUserId() + 10); 4334 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4335 mBinderService.setNotificationListenerAccessGrantedForUser( 4336 c, user.getIdentifier(), true, true); 4337 4338 4339 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 4340 verify(mListeners, times(1)).setPackageOrComponentEnabled( 4341 c.flattenToString(), user.getIdentifier(), true, true, true); 4342 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4343 c.flattenToString(), user.getIdentifier(), false, true, true); 4344 verify(mAssistants, never()).setPackageOrComponentEnabled( 4345 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4346 } 4347 4348 @Test testSetListenerAccessForUser_grantWithNameTooLong_throws()4349 public void testSetListenerAccessForUser_grantWithNameTooLong_throws() { 4350 UserHandle user = UserHandle.of(mContext.getUserId() + 10); 4351 ComponentName c = new ComponentName("com.example.package", 4352 com.google.common.base.Strings.repeat("Blah", 150)); 4353 4354 assertThrows(IllegalArgumentException.class, 4355 () -> mBinderService.setNotificationListenerAccessGrantedForUser( 4356 c, user.getIdentifier(), /* enabled= */ true, true)); 4357 } 4358 4359 @Test testSetListenerAccessForUser_revokeWithNameTooLong_okay()4360 public void testSetListenerAccessForUser_revokeWithNameTooLong_okay() throws Exception { 4361 UserHandle user = UserHandle.of(mContext.getUserId() + 10); 4362 ComponentName c = new ComponentName("com.example.package", 4363 com.google.common.base.Strings.repeat("Blah", 150)); 4364 4365 mBinderService.setNotificationListenerAccessGrantedForUser( 4366 c, user.getIdentifier(), /* enabled= */ false, true); 4367 4368 verify(mListeners).setPackageOrComponentEnabled( 4369 c.flattenToString(), user.getIdentifier(), true, /* enabled= */ false, true); 4370 } 4371 4372 @Test testSetAssistantAccessForUser()4373 public void testSetAssistantAccessForUser() throws Exception { 4374 UserInfo ui = new UserInfo(); 4375 ui.id = mContext.getUserId() + 10; 4376 UserHandle user = UserHandle.of(ui.id); 4377 List<UserInfo> uis = new ArrayList<>(); 4378 uis.add(ui); 4379 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4380 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4381 4382 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true); 4383 4384 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 4385 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4386 c.flattenToString(), user.getIdentifier(), true, true, true); 4387 verify(mAssistants).setUserSet(ui.id, true); 4388 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4389 c.flattenToString(), user.getIdentifier(), false, true); 4390 verify(mListeners, never()).setPackageOrComponentEnabled( 4391 any(), anyInt(), anyBoolean(), anyBoolean()); 4392 } 4393 4394 @Test testGetAssistantAllowedForUser()4395 public void testGetAssistantAllowedForUser() throws Exception { 4396 UserHandle user = UserHandle.of(mContext.getUserId() + 10); 4397 try { 4398 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier()); 4399 } catch (IllegalStateException e) { 4400 if (!e.getMessage().contains("At most one NotificationAssistant")) { 4401 throw e; 4402 } 4403 } 4404 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier()); 4405 } 4406 4407 @Test testGetAssistantAllowed()4408 public void testGetAssistantAllowed() throws Exception { 4409 try { 4410 mBinderService.getAllowedNotificationAssistant(); 4411 } catch (IllegalStateException e) { 4412 if (!e.getMessage().contains("At most one NotificationAssistant")) { 4413 throw e; 4414 } 4415 } 4416 verify(mAssistants, times(1)).getAllowedComponents(mContext.getUserId()); 4417 } 4418 4419 @Test testSetNASMigrationDoneAndResetDefault_enableNAS()4420 public void testSetNASMigrationDoneAndResetDefault_enableNAS() throws Exception { 4421 int userId = 10; 4422 setNASMigrationDone(false, userId); 4423 when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId}); 4424 4425 mBinderService.setNASMigrationDoneAndResetDefault(userId, true); 4426 4427 assertTrue(mService.isNASMigrationDone(userId)); 4428 verify(mAssistants, times(1)).resetDefaultFromConfig(); 4429 } 4430 4431 @Test testSetNASMigrationDoneAndResetDefault_disableNAS()4432 public void testSetNASMigrationDoneAndResetDefault_disableNAS() throws Exception { 4433 int userId = 10; 4434 setNASMigrationDone(false, userId); 4435 when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId}); 4436 4437 mBinderService.setNASMigrationDoneAndResetDefault(userId, false); 4438 4439 assertTrue(mService.isNASMigrationDone(userId)); 4440 verify(mAssistants, times(1)).clearDefaults(); 4441 } 4442 4443 @Test testSetNASMigrationDoneAndResetDefault_multiProfile()4444 public void testSetNASMigrationDoneAndResetDefault_multiProfile() throws Exception { 4445 int userId1 = 11; 4446 int userId2 = 12; //work profile 4447 setNASMigrationDone(false, userId1); 4448 setNASMigrationDone(false, userId2); 4449 setUsers(new int[]{userId1, userId2}); 4450 when(mUm.isManagedProfile(userId2)).thenReturn(true); 4451 when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1, userId2}); 4452 4453 mBinderService.setNASMigrationDoneAndResetDefault(userId1, true); 4454 assertTrue(mService.isNASMigrationDone(userId1)); 4455 assertTrue(mService.isNASMigrationDone(userId2)); 4456 } 4457 4458 @Test testSetNASMigrationDoneAndResetDefault_multiUser()4459 public void testSetNASMigrationDoneAndResetDefault_multiUser() throws Exception { 4460 int userId1 = 11; 4461 int userId2 = 12; 4462 setNASMigrationDone(false, userId1); 4463 setNASMigrationDone(false, userId2); 4464 setUsers(new int[]{userId1, userId2}); 4465 when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1}); 4466 when(mUm.getProfileIds(userId2, false)).thenReturn(new int[]{userId2}); 4467 4468 mBinderService.setNASMigrationDoneAndResetDefault(userId1, true); 4469 assertTrue(mService.isNASMigrationDone(userId1)); 4470 assertFalse(mService.isNASMigrationDone(userId2)); 4471 } 4472 4473 @Test testSetDndAccessForUser()4474 public void testSetDndAccessForUser() throws Exception { 4475 UserHandle user = UserHandle.of(mContext.getUserId() + 10); 4476 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4477 mBinderService.setNotificationPolicyAccessGrantedForUser( 4478 c.getPackageName(), user.getIdentifier(), true); 4479 4480 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 4481 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4482 c.getPackageName(), user.getIdentifier(), true, true); 4483 verify(mAssistants, never()).setPackageOrComponentEnabled( 4484 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4485 verify(mListeners, never()).setPackageOrComponentEnabled( 4486 any(), anyInt(), anyBoolean(), anyBoolean()); 4487 } 4488 4489 @Test testSetListenerAccess()4490 public void testSetListenerAccess() throws Exception { 4491 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4492 mBinderService.setNotificationListenerAccessGranted(c, true, true); 4493 4494 verify(mListeners, times(1)).setPackageOrComponentEnabled( 4495 c.flattenToString(), mContext.getUserId(), true, true, true); 4496 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4497 c.flattenToString(), mContext.getUserId(), false, true, true); 4498 verify(mAssistants, never()).setPackageOrComponentEnabled( 4499 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4500 } 4501 4502 @Test testSetAssistantAccess()4503 public void testSetAssistantAccess() throws Exception { 4504 List<UserInfo> uis = new ArrayList<>(); 4505 UserInfo ui = new UserInfo(); 4506 ui.id = mContext.getUserId(); 4507 uis.add(ui); 4508 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4509 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4510 4511 mBinderService.setNotificationAssistantAccessGranted(c, true); 4512 4513 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4514 c.flattenToString(), ui.id, true, true, true); 4515 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4516 c.flattenToString(), ui.id, false, true); 4517 verify(mListeners, never()).setPackageOrComponentEnabled( 4518 any(), anyInt(), anyBoolean(), anyBoolean()); 4519 } 4520 4521 @Test testSetAssistantAccess_multiProfile()4522 public void testSetAssistantAccess_multiProfile() throws Exception { 4523 List<UserInfo> uis = new ArrayList<>(); 4524 UserInfo ui = new UserInfo(); 4525 ui.id = mContext.getUserId(); 4526 uis.add(ui); 4527 UserInfo ui10 = new UserInfo(); 4528 ui10.id = mContext.getUserId() + 10; 4529 uis.add(ui10); 4530 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4531 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4532 4533 mBinderService.setNotificationAssistantAccessGranted(c, true); 4534 4535 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4536 c.flattenToString(), ui.id, true, true, true); 4537 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4538 c.flattenToString(), ui10.id, true, true, true); 4539 4540 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4541 c.flattenToString(), ui.id, false, true); 4542 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4543 c.flattenToString(), ui10.id, false, true); 4544 verify(mListeners, never()).setPackageOrComponentEnabled( 4545 any(), anyInt(), anyBoolean(), anyBoolean()); 4546 } 4547 4548 @Test testSetAssistantAccess_nullWithAllowedAssistant()4549 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception { 4550 ArrayList<ComponentName> componentList = new ArrayList<>(); 4551 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4552 componentList.add(c); 4553 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 4554 List<UserInfo> uis = new ArrayList<>(); 4555 UserInfo ui = new UserInfo(); 4556 ui.id = mContext.getUserId(); 4557 uis.add(ui); 4558 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4559 4560 mBinderService.setNotificationAssistantAccessGranted(null, true); 4561 4562 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4563 c.flattenToString(), ui.id, true, false, true); 4564 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4565 c.flattenToString(), ui.id, false, false); 4566 verify(mListeners, never()).setPackageOrComponentEnabled( 4567 any(), anyInt(), anyBoolean(), anyBoolean()); 4568 } 4569 4570 @Test testSetAssistantAccessForUser_nullWithAllowedAssistant()4571 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception { 4572 List<UserInfo> uis = new ArrayList<>(); 4573 UserInfo ui = new UserInfo(); 4574 ui.id = mContext.getUserId() + 10; 4575 uis.add(ui); 4576 UserHandle user = ui.getUserHandle(); 4577 ArrayList<ComponentName> componentList = new ArrayList<>(); 4578 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4579 componentList.add(c); 4580 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 4581 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4582 4583 mBinderService.setNotificationAssistantAccessGrantedForUser( 4584 null, user.getIdentifier(), true); 4585 4586 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4587 c.flattenToString(), user.getIdentifier(), true, false, true); 4588 verify(mAssistants).setUserSet(ui.id, true); 4589 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4590 c.flattenToString(), user.getIdentifier(), false, false); 4591 verify(mListeners, never()).setPackageOrComponentEnabled( 4592 any(), anyInt(), anyBoolean(), anyBoolean()); 4593 } 4594 4595 @Test testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()4596 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant() 4597 throws Exception { 4598 List<UserInfo> uis = new ArrayList<>(); 4599 UserInfo ui = new UserInfo(); 4600 ui.id = mContext.getUserId(); 4601 uis.add(ui); 4602 UserInfo ui10 = new UserInfo(); 4603 ui10.id = mContext.getUserId() + 10; 4604 uis.add(ui10); 4605 UserHandle user = ui.getUserHandle(); 4606 ArrayList<ComponentName> componentList = new ArrayList<>(); 4607 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4608 componentList.add(c); 4609 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 4610 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4611 4612 mBinderService.setNotificationAssistantAccessGrantedForUser( 4613 null, user.getIdentifier(), true); 4614 4615 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4616 c.flattenToString(), user.getIdentifier(), true, false, true); 4617 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4618 c.flattenToString(), ui10.id, true, false, true); 4619 verify(mAssistants).setUserSet(ui.id, true); 4620 verify(mAssistants).setUserSet(ui10.id, true); 4621 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4622 c.flattenToString(), user.getIdentifier(), false, false); 4623 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4624 c.flattenToString(), ui10.id, false, false); 4625 verify(mListeners, never()).setPackageOrComponentEnabled( 4626 any(), anyInt(), anyBoolean(), anyBoolean()); 4627 } 4628 4629 @Test testSetDndAccess()4630 public void testSetDndAccess() throws Exception { 4631 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4632 4633 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 4634 4635 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4636 c.getPackageName(), mContext.getUserId(), true, true); 4637 verify(mAssistants, never()).setPackageOrComponentEnabled( 4638 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4639 verify(mListeners, never()).setPackageOrComponentEnabled( 4640 any(), anyInt(), anyBoolean(), anyBoolean()); 4641 } 4642 4643 @Test testSetListenerAccess_onLowRam()4644 public void testSetListenerAccess_onLowRam() throws Exception { 4645 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4646 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4647 mBinderService.setNotificationListenerAccessGranted(c, true, true); 4648 4649 verify(mListeners).setPackageOrComponentEnabled( 4650 anyString(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4651 verify(mConditionProviders).setPackageOrComponentEnabled( 4652 anyString(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4653 verify(mAssistants).migrateToXml(); 4654 verify(mAssistants).resetDefaultAssistantsIfNecessary(); 4655 } 4656 4657 @Test testSetAssistantAccess_onLowRam()4658 public void testSetAssistantAccess_onLowRam() throws Exception { 4659 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4660 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4661 List<UserInfo> uis = new ArrayList<>(); 4662 UserInfo ui = new UserInfo(); 4663 ui.id = mContext.getUserId(); 4664 uis.add(ui); 4665 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4666 4667 mBinderService.setNotificationAssistantAccessGranted(c, true); 4668 4669 verify(mListeners).migrateToXml(); 4670 verify(mConditionProviders).setPackageOrComponentEnabled( 4671 anyString(), anyInt(), anyBoolean(), anyBoolean()); 4672 verify(mAssistants).migrateToXml(); 4673 verify(mAssistants).resetDefaultAssistantsIfNecessary(); 4674 } 4675 4676 @Test testSetDndAccess_onLowRam()4677 public void testSetDndAccess_onLowRam() throws Exception { 4678 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4679 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4680 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 4681 4682 verify(mListeners).migrateToXml(); 4683 verify(mConditionProviders).setPackageOrComponentEnabled( 4684 anyString(), anyInt(), anyBoolean(), anyBoolean()); 4685 verify(mAssistants).migrateToXml(); 4686 verify(mAssistants).resetDefaultAssistantsIfNecessary(); 4687 } 4688 4689 @Test testSetListenerAccess_doesNothingOnLowRam_exceptWatch()4690 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 4691 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 4692 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4693 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4694 4695 mBinderService.setNotificationListenerAccessGranted(c, true, true); 4696 4697 verify(mListeners, times(1)).setPackageOrComponentEnabled( 4698 c.flattenToString(), mContext.getUserId(), true, true, true); 4699 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4700 c.flattenToString(), mContext.getUserId(), false, true, true); 4701 verify(mAssistants, never()).setPackageOrComponentEnabled( 4702 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4703 } 4704 4705 @Test testSetAssistantAccess_doesNothingOnLowRam_exceptWatch()4706 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 4707 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 4708 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4709 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4710 List<UserInfo> uis = new ArrayList<>(); 4711 UserInfo ui = new UserInfo(); 4712 ui.id = mContext.getUserId(); 4713 uis.add(ui); 4714 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4715 4716 mBinderService.setNotificationAssistantAccessGranted(c, true); 4717 4718 verify(mListeners, never()).setPackageOrComponentEnabled( 4719 anyString(), anyInt(), anyBoolean(), anyBoolean()); 4720 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4721 c.flattenToString(), ui.id, false, true); 4722 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4723 c.flattenToString(), ui.id, true, true, true); 4724 } 4725 4726 @Test testSetDndAccess_doesNothingOnLowRam_exceptWatch()4727 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 4728 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 4729 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4730 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4731 4732 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 4733 4734 verify(mListeners, never()).setPackageOrComponentEnabled( 4735 anyString(), anyInt(), anyBoolean(), anyBoolean()); 4736 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4737 c.getPackageName(), mContext.getUserId(), true, true); 4738 verify(mAssistants, never()).setPackageOrComponentEnabled( 4739 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4740 } 4741 4742 @Test testOnlyAutogroupIfNeeded_newNotification_ghUpdate()4743 public void testOnlyAutogroupIfNeeded_newNotification_ghUpdate() { 4744 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 4745 mService.addEnqueuedNotification(r); 4746 NotificationManagerService.PostNotificationRunnable runnable = 4747 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 4748 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 4749 runnable.run(); 4750 waitForIdle(); 4751 4752 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 4753 } 4754 4755 @Test testOnlyAutogroupIfNeeded_groupChanged_ghUpdate()4756 public void testOnlyAutogroupIfNeeded_groupChanged_ghUpdate() { 4757 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, 4758 "testOnlyAutogroupIfNeeded_groupChanged_ghUpdate", "group", false); 4759 mService.addNotification(r); 4760 4761 NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0, 4762 "testOnlyAutogroupIfNeeded_groupChanged_ghUpdate", null, false); 4763 mService.addEnqueuedNotification(update); 4764 NotificationManagerService.PostNotificationRunnable runnable = 4765 mService.new PostNotificationRunnable(update.getKey(), 4766 update.getSbn().getPackageName(), update.getUid(), 4767 mPostNotificationTrackerFactory.newTracker(null)); 4768 runnable.run(); 4769 waitForIdle(); 4770 4771 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 4772 } 4773 4774 @Test testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate()4775 public void testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate() { 4776 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, 4777 "testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate", "group", false); 4778 mService.addNotification(r); 4779 4780 NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0, 4781 "testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate", null, false); 4782 update.getNotification().flags = FLAG_AUTO_CANCEL; 4783 mService.addEnqueuedNotification(update); 4784 NotificationManagerService.PostNotificationRunnable runnable = 4785 mService.new PostNotificationRunnable(update.getKey(), 4786 update.getSbn().getPackageName(), update.getUid(), 4787 mPostNotificationTrackerFactory.newTracker(null)); 4788 runnable.run(); 4789 waitForIdle(); 4790 4791 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 4792 } 4793 4794 @Test testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate()4795 public void testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate() { 4796 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, 4797 "testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate", null, false); 4798 mService.addNotification(r); 4799 NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0, 4800 "testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate", null, false); 4801 update.getNotification().color = Color.BLACK; 4802 mService.addEnqueuedNotification(update); 4803 4804 NotificationManagerService.PostNotificationRunnable runnable = 4805 mService.new PostNotificationRunnable(update.getKey(), 4806 update.getSbn().getPackageName(), 4807 update.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 4808 runnable.run(); 4809 waitForIdle(); 4810 4811 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean()); 4812 } 4813 4814 @Test testDontAutogroupIfCritical()4815 public void testDontAutogroupIfCritical() throws Exception { 4816 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 4817 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW); 4818 mService.addEnqueuedNotification(r); 4819 NotificationManagerService.PostNotificationRunnable runnable = 4820 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 4821 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 4822 runnable.run(); 4823 4824 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false); 4825 r.setCriticality(CriticalNotificationExtractor.CRITICAL); 4826 runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 4827 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 4828 mService.addEnqueuedNotification(r); 4829 4830 runnable.run(); 4831 waitForIdle(); 4832 4833 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean()); 4834 } 4835 4836 @Test testNoNotificationDuringSetupPermission()4837 public void testNoNotificationDuringSetupPermission() throws Exception { 4838 mContext.getTestablePermissions().setPermission( 4839 android.Manifest.permission.NOTIFICATION_DURING_SETUP, PERMISSION_GRANTED); 4840 Bundle extras = new Bundle(); 4841 extras.putBoolean(EXTRA_ALLOW_DURING_SETUP, true); 4842 Notification.Builder nb = new Notification.Builder(mContext, 4843 mTestNotificationChannel.getId()) 4844 .setContentTitle("foo") 4845 .addExtras(extras) 4846 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4847 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4848 "testNoNotificationDuringSetupPermission", mUid, 0, 4849 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4850 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4851 4852 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4853 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4854 waitForIdle(); 4855 4856 NotificationRecord posted = mService.findNotificationLocked( 4857 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4858 4859 assertTrue(posted.getNotification().extras.containsKey(EXTRA_ALLOW_DURING_SETUP)); 4860 } 4861 4862 @Test testNoFakeColorizedPermission()4863 public void testNoFakeColorizedPermission() throws Exception { 4864 mContext.getTestablePermissions().setPermission( 4865 android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_DENIED); 4866 Notification.Builder nb = new Notification.Builder(mContext, 4867 mTestNotificationChannel.getId()) 4868 .setContentTitle("foo") 4869 .setColorized(true).setColor(Color.WHITE) 4870 .setFlag(FLAG_CAN_COLORIZE, true) 4871 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4872 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4873 "testNoFakeColorizedPermission", mUid, 0, 4874 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4875 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4876 4877 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4878 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4879 waitForIdle(); 4880 4881 NotificationRecord posted = mService.findNotificationLocked( 4882 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4883 4884 assertFalse(posted.getNotification().isColorized()); 4885 } 4886 4887 @Test testMediaStyleRemote_hasPermission()4888 public void testMediaStyleRemote_hasPermission() throws RemoteException { 4889 String deviceName = "device"; 4890 mContext.getTestablePermissions().setPermission( 4891 android.Manifest.permission.MEDIA_CONTENT_CONTROL, PERMISSION_GRANTED); 4892 Notification.MediaStyle style = new Notification.MediaStyle(); 4893 style.setRemotePlaybackInfo(deviceName, 0, null); 4894 Notification.Builder nb = new Notification.Builder(mContext, 4895 mTestNotificationChannel.getId()) 4896 .setStyle(style); 4897 4898 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4899 "testMediaStyleRemoteHasPermission", mUid, 0, 4900 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4901 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4902 4903 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4904 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4905 waitForIdle(); 4906 4907 NotificationRecord posted = mService.findNotificationLocked( 4908 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4909 Bundle extras = posted.getNotification().extras; 4910 4911 assertTrue(extras.containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); 4912 assertEquals(deviceName, extras.getString(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); 4913 } 4914 4915 @Test testMediaStyleRemote_noPermission()4916 public void testMediaStyleRemote_noPermission() throws RemoteException { 4917 String deviceName = "device"; 4918 mContext.getTestablePermissions().setPermission( 4919 android.Manifest.permission.MEDIA_CONTENT_CONTROL, PERMISSION_DENIED); 4920 Notification.MediaStyle style = new Notification.MediaStyle(); 4921 style.setRemotePlaybackInfo(deviceName, 0, null); 4922 Notification.Builder nb = new Notification.Builder(mContext, 4923 mTestNotificationChannel.getId()) 4924 .setStyle(style); 4925 4926 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4927 "testMediaStyleRemoteNoPermission", mUid, 0, 4928 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4929 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4930 4931 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4932 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4933 waitForIdle(); 4934 4935 NotificationRecord posted = mService.findNotificationLocked( 4936 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4937 4938 assertFalse(posted.getNotification().extras 4939 .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); 4940 assertFalse(posted.getNotification().extras 4941 .containsKey(Notification.EXTRA_MEDIA_REMOTE_ICON)); 4942 assertFalse(posted.getNotification().extras 4943 .containsKey(Notification.EXTRA_MEDIA_REMOTE_INTENT)); 4944 } 4945 4946 @Test testCustomMediaStyleRemote_noPermission()4947 public void testCustomMediaStyleRemote_noPermission() throws RemoteException { 4948 String deviceName = "device"; 4949 when(mPackageManager.checkPermission( 4950 eq(android.Manifest.permission.MEDIA_CONTENT_CONTROL), any(), anyInt())) 4951 .thenReturn(PERMISSION_DENIED); 4952 Notification.DecoratedMediaCustomViewStyle style = 4953 new Notification.DecoratedMediaCustomViewStyle(); 4954 style.setRemotePlaybackInfo(deviceName, 0, null); 4955 Notification.Builder nb = new Notification.Builder(mContext, 4956 mTestNotificationChannel.getId()) 4957 .setStyle(style); 4958 4959 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4960 "testCustomMediaStyleRemoteNoPermission", mUid, 0, 4961 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4962 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4963 4964 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4965 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4966 waitForIdle(); 4967 4968 NotificationRecord posted = mService.findNotificationLocked( 4969 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4970 4971 assertFalse(posted.getNotification().extras 4972 .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); 4973 assertFalse(posted.getNotification().extras 4974 .containsKey(Notification.EXTRA_MEDIA_REMOTE_ICON)); 4975 assertFalse(posted.getNotification().extras 4976 .containsKey(Notification.EXTRA_MEDIA_REMOTE_INTENT)); 4977 } 4978 4979 @Test testSubstituteAppName_hasPermission()4980 public void testSubstituteAppName_hasPermission() throws RemoteException { 4981 String subName = "Substitute Name"; 4982 mContext.getTestablePermissions().setPermission( 4983 android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME, PERMISSION_GRANTED); 4984 Bundle extras = new Bundle(); 4985 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, subName); 4986 Notification.Builder nb = new Notification.Builder(mContext, 4987 mTestNotificationChannel.getId()) 4988 .addExtras(extras); 4989 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4990 "testSubstituteAppNamePermission", mUid, 0, 4991 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4992 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4993 4994 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4995 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4996 waitForIdle(); 4997 NotificationRecord posted = mService.findNotificationLocked( 4998 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4999 5000 assertTrue(posted.getNotification().extras 5001 .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)); 5002 assertEquals(posted.getNotification().extras 5003 .getString(Notification.EXTRA_SUBSTITUTE_APP_NAME), subName); 5004 } 5005 5006 @Test testSubstituteAppName_noPermission()5007 public void testSubstituteAppName_noPermission() throws RemoteException { 5008 mContext.getTestablePermissions().setPermission( 5009 android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME, PERMISSION_DENIED); 5010 Bundle extras = new Bundle(); 5011 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, "Substitute Name"); 5012 Notification.Builder nb = new Notification.Builder(mContext, 5013 mTestNotificationChannel.getId()) 5014 .addExtras(extras); 5015 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 5016 "testSubstituteAppNamePermission", mUid, 0, 5017 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 5018 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 5019 5020 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 5021 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 5022 waitForIdle(); 5023 NotificationRecord posted = mService.findNotificationLocked( 5024 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 5025 5026 assertFalse(posted.getNotification().extras 5027 .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)); 5028 } 5029 5030 @Test testGetNotificationCountLocked()5031 public void testGetNotificationCountLocked() { 5032 String sampleTagToExclude = null; 5033 int sampleIdToExclude = 0; 5034 for (int i = 0; i < 20; i++) { 5035 NotificationRecord r = 5036 generateNotificationRecord(mTestNotificationChannel, i, null, false); 5037 mService.addEnqueuedNotification(r); 5038 5039 } 5040 for (int i = 0; i < 20; i++) { 5041 NotificationRecord r = 5042 generateNotificationRecord(mTestNotificationChannel, i, null, false); 5043 mService.addNotification(r); 5044 sampleTagToExclude = r.getSbn().getTag(); 5045 sampleIdToExclude = i; 5046 } 5047 5048 // another package 5049 Notification n = 5050 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 5051 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5052 .build(); 5053 5054 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0, 5055 n, UserHandle.getUserHandleForUid(mUid), null, 0); 5056 NotificationRecord otherPackage = 5057 new NotificationRecord(mContext, sbn, mTestNotificationChannel); 5058 mService.addEnqueuedNotification(otherPackage); 5059 mService.addNotification(otherPackage); 5060 5061 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match 5062 // anything that's currently enqueued or posted 5063 int userId = mUserId; 5064 assertEquals(40, 5065 mService.getNotificationCount(PKG, userId, 0, null)); 5066 assertEquals(40, 5067 mService.getNotificationCount(PKG, userId, 0, "tag2")); 5068 5069 // return all for package "a" - "banana" tag isn't used 5070 assertEquals(2, 5071 mService.getNotificationCount("a", userId, 0, "banana")); 5072 5073 // exclude a known notification - it's excluded from only the posted list, not enqueued 5074 assertEquals(39, mService.getNotificationCount( 5075 PKG, userId, sampleIdToExclude, sampleTagToExclude)); 5076 } 5077 5078 @Test testAddAutogroup_requestsSort()5079 public void testAddAutogroup_requestsSort() throws Exception { 5080 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5081 mService.addNotification(r); 5082 mService.addAutogroupKeyLocked(r.getKey()); 5083 5084 verify(mRankingHandler, times(1)).requestSort(); 5085 } 5086 5087 @Test testRemoveAutogroup_requestsSort()5088 public void testRemoveAutogroup_requestsSort() throws Exception { 5089 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5090 r.setOverrideGroupKey("TEST"); 5091 mService.addNotification(r); 5092 mService.removeAutogroupKeyLocked(r.getKey()); 5093 5094 verify(mRankingHandler, times(1)).requestSort(); 5095 } 5096 5097 @Test testReaddAutogroup_noSort()5098 public void testReaddAutogroup_noSort() throws Exception { 5099 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5100 r.setOverrideGroupKey("TEST"); 5101 mService.addNotification(r); 5102 mService.addAutogroupKeyLocked(r.getKey()); 5103 5104 verify(mRankingHandler, never()).requestSort(); 5105 } 5106 5107 @Test testHandleRankingSort_sendsUpdateOnSignalExtractorChange()5108 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception { 5109 mService.setPreferencesHelper(mPreferencesHelper); 5110 NotificationManagerService.WorkerHandler handler = mock( 5111 NotificationManagerService.WorkerHandler.class); 5112 mService.setHandler(handler); 5113 5114 Map<String, Answer> answers = getSignalExtractorSideEffects(); 5115 for (String message : answers.keySet()) { 5116 mService.clearNotifications(); 5117 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5118 mService.addNotification(r); 5119 5120 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r); 5121 5122 mService.handleRankingSort(); 5123 } 5124 verify(handler, times(answers.size())).scheduleSendRankingUpdate(); 5125 } 5126 5127 @Test testHandleRankingSort_noUpdateWhenNoSignalChange()5128 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception { 5129 mService.setRankingHelper(mRankingHelper); 5130 NotificationManagerService.WorkerHandler handler = mock( 5131 NotificationManagerService.WorkerHandler.class); 5132 mService.setHandler(handler); 5133 5134 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5135 mService.addNotification(r); 5136 5137 mService.handleRankingSort(); 5138 verify(handler, never()).scheduleSendRankingUpdate(); 5139 } 5140 5141 @Test testReadPolicyXml_readApprovedServicesFromXml()5142 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception { 5143 final String upgradeXml = "<notification-policy version=\"1\">" 5144 + "<ranking></ranking>" 5145 + "<enabled_listeners>" 5146 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 5147 + "</enabled_listeners>" 5148 + "<enabled_assistants>" 5149 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 5150 + "</enabled_assistants>" 5151 + "<dnd_apps>" 5152 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 5153 + "</dnd_apps>" 5154 + "</notification-policy>"; 5155 mService.readPolicyXml( 5156 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())), 5157 false, 5158 UserHandle.USER_ALL); 5159 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 5160 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 5161 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 5162 5163 // numbers are inflated for setup 5164 verify(mListeners, times(1)).migrateToXml(); 5165 verify(mConditionProviders, times(1)).migrateToXml(); 5166 verify(mAssistants, times(1)).migrateToXml(); 5167 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary(); 5168 } 5169 5170 @Test testReadPolicyXml_readSnoozedNotificationsFromXml()5171 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception { 5172 final String upgradeXml = "<notification-policy version=\"1\">" 5173 + "<snoozed-notifications>></snoozed-notifications>" 5174 + "</notification-policy>"; 5175 mService.readPolicyXml( 5176 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())), 5177 false, 5178 UserHandle.USER_ALL); 5179 verify(mSnoozeHelper, times(1)).readXml(any(TypedXmlPullParser.class), anyLong()); 5180 } 5181 5182 @Test testReadPolicyXml_readApprovedServicesFromSettings()5183 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception { 5184 final String preupgradeXml = "<notification-policy version=\"1\">" 5185 + "<ranking></ranking>" 5186 + "</notification-policy>"; 5187 mService.readPolicyXml( 5188 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), 5189 false, 5190 UserHandle.USER_ALL); 5191 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt()); 5192 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt()); 5193 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt()); 5194 5195 // numbers are inflated for setup 5196 verify(mListeners, times(2)).migrateToXml(); 5197 verify(mConditionProviders, times(2)).migrateToXml(); 5198 verify(mAssistants, times(2)).migrateToXml(); 5199 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary(); 5200 } 5201 5202 @Test testReadPolicyXml_doesNotRestoreManagedServicesForCloneUser()5203 public void testReadPolicyXml_doesNotRestoreManagedServicesForCloneUser() throws Exception { 5204 final String policyXml = "<notification-policy version=\"1\">" 5205 + "<ranking></ranking>" 5206 + "<enabled_listeners>" 5207 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5208 + "</enabled_listeners>" 5209 + "<enabled_assistants>" 5210 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5211 + "</enabled_assistants>" 5212 + "<dnd_apps>" 5213 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5214 + "</dnd_apps>" 5215 + "</notification-policy>"; 5216 UserInfo ui = new UserInfo(); 5217 ui.id = 10; 5218 ui.userType = USER_TYPE_PROFILE_CLONE; 5219 when(mUmInternal.getUserInfo(10)).thenReturn(ui); 5220 mService.readPolicyXml( 5221 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())), 5222 true, 5223 10); 5224 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10)); 5225 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10)); 5226 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10)); 5227 } 5228 5229 @Test testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser()5230 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception { 5231 final String policyXml = "<notification-policy version=\"1\">" 5232 + "<ranking></ranking>" 5233 + "<enabled_listeners>" 5234 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5235 + "</enabled_listeners>" 5236 + "<enabled_assistants>" 5237 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5238 + "</enabled_assistants>" 5239 + "<dnd_apps>" 5240 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5241 + "</dnd_apps>" 5242 + "</notification-policy>"; 5243 UserInfo ui = new UserInfo(); 5244 ui.id = 10; 5245 ui.userType = USER_TYPE_PROFILE_MANAGED; 5246 when(mUmInternal.getUserInfo(10)).thenReturn(ui); 5247 mService.readPolicyXml( 5248 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())), 5249 true, 5250 10); 5251 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10)); 5252 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10)); 5253 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10)); 5254 } 5255 5256 @Test testReadPolicyXml_restoresManagedServicesForNonManagedUser()5257 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception { 5258 final String policyXml = "<notification-policy version=\"1\">" 5259 + "<ranking></ranking>" 5260 + "<enabled_listeners>" 5261 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5262 + "</enabled_listeners>" 5263 + "<enabled_assistants>" 5264 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5265 + "</enabled_assistants>" 5266 + "<dnd_apps>" 5267 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5268 + "</dnd_apps>" 5269 + "</notification-policy>"; 5270 UserInfo ui = new UserInfo(); 5271 ui.id = 10; 5272 ui.userType = USER_TYPE_FULL_SECONDARY; 5273 when(mUmInternal.getUserInfo(10)).thenReturn(ui); 5274 mService.readPolicyXml( 5275 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())), 5276 true, 5277 10); 5278 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10)); 5279 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10)); 5280 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10)); 5281 } 5282 5283 @Test testLocaleChangedCallsUpdateDefaultZenModeRules()5284 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception { 5285 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 5286 mService.mZenModeHelper = mZenModeHelper; 5287 mService.mLocaleChangeReceiver.onReceive(mContext, 5288 new Intent(Intent.ACTION_LOCALE_CHANGED)); 5289 5290 verify(mZenModeHelper, times(1)).updateDefaultZenRules( 5291 anyInt(), anyBoolean()); 5292 } 5293 5294 @Test testBumpFGImportance_channelChangePreOApp()5295 public void testBumpFGImportance_channelChangePreOApp() throws Exception { 5296 String preOPkg = PKG_N_MR1; 5297 final ApplicationInfo legacy = new ApplicationInfo(); 5298 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 5299 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt())) 5300 .thenReturn(legacy); 5301 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt())) 5302 .thenReturn(Binder.getCallingUid()); 5303 getContext().setMockPackageManager(mPackageManagerClient); 5304 5305 Notification.Builder nb = new Notification.Builder(mContext, 5306 NotificationChannel.DEFAULT_CHANNEL_ID) 5307 .setContentTitle("foo") 5308 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5309 .setFlag(FLAG_FOREGROUND_SERVICE, true) 5310 .setPriority(Notification.PRIORITY_MIN); 5311 5312 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, 5313 "testBumpFGImportance_channelChangePreOApp", 5314 Binder.getCallingUid(), 0, nb.build(), 5315 UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0); 5316 5317 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(), 5318 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId()); 5319 waitForIdle(); 5320 5321 assertEquals(IMPORTANCE_LOW, 5322 mService.getNotificationRecord(sbn.getKey()).getImportance()); 5323 assertEquals(IMPORTANCE_DEFAULT, mBinderService.getPackageImportance( 5324 sbn.getPackageName())); 5325 5326 nb = new Notification.Builder(mContext) 5327 .setContentTitle("foo") 5328 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5329 .setFlag(FLAG_FOREGROUND_SERVICE, true) 5330 .setPriority(Notification.PRIORITY_MIN); 5331 5332 sbn = new StatusBarNotification(preOPkg, preOPkg, 9, 5333 "testBumpFGImportance_channelChangePreOApp", Binder.getCallingUid(), 5334 0, nb.build(), UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0); 5335 5336 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, 5337 "testBumpFGImportance_channelChangePreOApp", 5338 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 5339 waitForIdle(); 5340 assertEquals(IMPORTANCE_LOW, 5341 mService.getNotificationRecord(sbn.getKey()).getImportance()); 5342 5343 NotificationChannel defaultChannel = mBinderService.getNotificationChannel( 5344 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID); 5345 assertEquals(IMPORTANCE_LOW, defaultChannel.getImportance()); 5346 } 5347 5348 @Test testStats_updatedOnDirectReply()5349 public void testStats_updatedOnDirectReply() throws Exception { 5350 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5351 mService.addNotification(r); 5352 5353 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey()); 5354 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied()); 5355 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r)); 5356 5357 assertEquals(1, mNotificationRecordLogger.numCalls()); 5358 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DIRECT_REPLIED, 5359 mNotificationRecordLogger.event(0)); 5360 } 5361 5362 @Test testStats_updatedOnUserExpansion()5363 public void testStats_updatedOnUserExpansion() throws Exception { 5364 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5365 mService.addNotification(r); 5366 5367 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true, 5368 NOTIFICATION_LOCATION_UNKNOWN); 5369 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), 5370 eq(FLAG_FILTER_TYPE_ALERTING), eq(true), eq((true))); 5371 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 5372 5373 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false, 5374 NOTIFICATION_LOCATION_UNKNOWN); 5375 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), 5376 eq(FLAG_FILTER_TYPE_ALERTING), eq(true), eq((false))); 5377 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 5378 5379 assertEquals(2, mNotificationRecordLogger.numCalls()); 5380 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_OPEN_USER, 5381 mNotificationRecordLogger.event(0)); 5382 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_CLOSE_USER, 5383 mNotificationRecordLogger.event(1)); 5384 } 5385 5386 @Test testStats_notUpdatedOnAutoExpansion()5387 public void testStats_notUpdatedOnAutoExpansion() throws Exception { 5388 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5389 mService.addNotification(r); 5390 5391 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 5392 NOTIFICATION_LOCATION_UNKNOWN); 5393 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 5394 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), 5395 eq(FLAG_FILTER_TYPE_ALERTING), eq(false), eq((true))); 5396 5397 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false, 5398 NOTIFICATION_LOCATION_UNKNOWN); 5399 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 5400 verify(mAssistants).notifyAssistantExpansionChangedLocked( 5401 eq(r.getSbn()), eq(FLAG_FILTER_TYPE_ALERTING), eq(false), eq((false))); 5402 } 5403 5404 @Test testStats_updatedOnViewSettings()5405 public void testStats_updatedOnViewSettings() throws Exception { 5406 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5407 mService.addNotification(r); 5408 5409 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey()); 5410 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings()); 5411 } 5412 5413 @Test testStats_updatedOnVisibilityChanged()5414 public void testStats_updatedOnVisibilityChanged() throws Exception { 5415 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5416 mService.addNotification(r); 5417 5418 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true); 5419 mService.mNotificationDelegate.onNotificationVisibilityChanged( 5420 new NotificationVisibility[] {nv}, new NotificationVisibility[]{}); 5421 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r), eq(true)); 5422 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen()); 5423 mService.mNotificationDelegate.onNotificationVisibilityChanged( 5424 new NotificationVisibility[] {}, new NotificationVisibility[]{nv}); 5425 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r), eq(false)); 5426 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen()); 5427 } 5428 5429 @Test testStats_dismissalSurface()5430 public void testStats_dismissalSurface() throws Exception { 5431 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5432 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5433 mService.addNotification(r); 5434 5435 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true); 5436 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(), 5437 r.getKey(), NotificationStats.DISMISSAL_AOD, 5438 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv); 5439 waitForIdle(); 5440 5441 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface()); 5442 5443 // Using mService.addNotification() does not generate a NotificationRecordLogger log, 5444 // so we only get the cancel notification. 5445 assertEquals(1, mNotificationRecordLogger.numCalls()); 5446 5447 assertEquals( 5448 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD, 5449 mNotificationRecordLogger.event(0)); 5450 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 5451 } 5452 5453 @Test testStats_dismissalSentiment()5454 public void testStats_dismissalSentiment() throws Exception { 5455 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5456 mService.addNotification(r); 5457 5458 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true); 5459 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(), 5460 r.getKey(), NotificationStats.DISMISSAL_AOD, 5461 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv); 5462 waitForIdle(); 5463 5464 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE, 5465 r.getStats().getDismissalSentiment()); 5466 } 5467 5468 @Test testTextChangedSet_forNewNotifs()5469 public void testTextChangedSet_forNewNotifs() throws Exception { 5470 NotificationRecord original = generateNotificationRecord(mTestNotificationChannel); 5471 mService.addEnqueuedNotification(original); 5472 5473 NotificationManagerService.PostNotificationRunnable runnable = 5474 mService.new PostNotificationRunnable(original.getKey(), 5475 original.getSbn().getPackageName(), 5476 original.getUid(), 5477 mPostNotificationTrackerFactory.newTracker(null)); 5478 runnable.run(); 5479 waitForIdle(); 5480 5481 assertTrue(original.isTextChanged()); 5482 } 5483 5484 @Test testVisuallyInterruptive_notSeen()5485 public void testVisuallyInterruptive_notSeen() throws Exception { 5486 NotificationRecord original = generateNotificationRecord(mTestNotificationChannel); 5487 mService.addNotification(original); 5488 5489 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, original.getSbn().getId(), 5490 original.getSbn().getTag(), mUid, 0, 5491 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 5492 .setContentTitle("new title").build(), 5493 UserHandle.getUserHandleForUid(mUid), null, 0); 5494 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 5495 mService.addEnqueuedNotification(update); 5496 5497 NotificationManagerService.PostNotificationRunnable runnable = 5498 mService.new PostNotificationRunnable(update.getKey(), 5499 update.getSbn().getPackageName(), 5500 update.getUid(), 5501 mPostNotificationTrackerFactory.newTracker(null)); 5502 runnable.run(); 5503 waitForIdle(); 5504 5505 assertFalse(update.isInterruptive()); 5506 } 5507 5508 @Test testApplyAdjustmentMultiUser()5509 public void testApplyAdjustmentMultiUser() throws Exception { 5510 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5511 mService.addNotification(r); 5512 NotificationManagerService.WorkerHandler handler = mock( 5513 NotificationManagerService.WorkerHandler.class); 5514 mService.setHandler(handler); 5515 5516 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false); 5517 5518 Bundle signals = new Bundle(); 5519 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5520 USER_SENTIMENT_NEGATIVE); 5521 Adjustment adjustment = new Adjustment( 5522 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5523 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 5524 5525 waitForIdle(); 5526 5527 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 5528 } 5529 5530 @Test testAssistantBlockingTriggersCancel()5531 public void testAssistantBlockingTriggersCancel() throws Exception { 5532 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5533 mService.addNotification(r); 5534 NotificationManagerService.WorkerHandler handler = mock( 5535 NotificationManagerService.WorkerHandler.class); 5536 mService.setHandler(handler); 5537 5538 Bundle signals = new Bundle(); 5539 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE); 5540 Adjustment adjustment = new Adjustment( 5541 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5542 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 5543 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 5544 5545 waitForIdle(); 5546 5547 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 5548 verify(handler, times(1)).scheduleCancelNotification(any()); 5549 } 5550 5551 @Test testApplyEnqueuedAdjustmentFromAssistant_singleUser()5552 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception { 5553 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5554 mService.addEnqueuedNotification(r); 5555 NotificationManagerService.WorkerHandler handler = mock( 5556 NotificationManagerService.WorkerHandler.class); 5557 mService.setHandler(handler); 5558 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5559 5560 Bundle signals = new Bundle(); 5561 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5562 USER_SENTIMENT_NEGATIVE); 5563 Adjustment adjustment = new Adjustment( 5564 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5565 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5566 5567 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment()); 5568 } 5569 5570 @Test testApplyEnqueuedAdjustmentFromAssistant_importance()5571 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception { 5572 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5573 mService.addEnqueuedNotification(r); 5574 NotificationManagerService.WorkerHandler handler = mock( 5575 NotificationManagerService.WorkerHandler.class); 5576 mService.setHandler(handler); 5577 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5578 5579 Bundle signals = new Bundle(); 5580 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW); 5581 Adjustment adjustment = new Adjustment( 5582 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5583 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5584 5585 assertEquals(IMPORTANCE_LOW, r.getImportance()); 5586 } 5587 5588 @Test testApplyEnqueuedAdjustmentFromAssistant_crossUser()5589 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception { 5590 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5591 mService.addEnqueuedNotification(r); 5592 NotificationManagerService.WorkerHandler handler = mock( 5593 NotificationManagerService.WorkerHandler.class); 5594 mService.setHandler(handler); 5595 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false); 5596 5597 Bundle signals = new Bundle(); 5598 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5599 USER_SENTIMENT_NEGATIVE); 5600 Adjustment adjustment = new Adjustment( 5601 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5602 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5603 5604 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment()); 5605 5606 waitForIdle(); 5607 5608 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 5609 } 5610 5611 @Test testUserSentimentChangeTriggersUpdate()5612 public void testUserSentimentChangeTriggersUpdate() throws Exception { 5613 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5614 mService.addNotification(r); 5615 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5616 5617 Bundle signals = new Bundle(); 5618 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5619 USER_SENTIMENT_NEGATIVE); 5620 Adjustment adjustment = new Adjustment( 5621 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5622 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 5623 5624 waitForIdle(); 5625 5626 verify(mRankingHandler, timeout(300).times(1)).requestSort(); 5627 } 5628 5629 @Test testTooLateAdjustmentTriggersUpdate()5630 public void testTooLateAdjustmentTriggersUpdate() throws Exception { 5631 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5632 mService.addNotification(r); 5633 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5634 5635 Bundle signals = new Bundle(); 5636 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5637 USER_SENTIMENT_NEGATIVE); 5638 Adjustment adjustment = new Adjustment( 5639 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5640 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5641 5642 waitForIdle(); 5643 5644 verify(mRankingHandler, times(1)).requestSort(); 5645 } 5646 5647 @Test testApplyAdjustmentsLogged()5648 public void testApplyAdjustmentsLogged() throws Exception { 5649 NotificationManagerService.WorkerHandler handler = mock( 5650 NotificationManagerService.WorkerHandler.class); 5651 mService.setHandler(handler); 5652 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5653 5654 // Set up notifications that will be adjusted 5655 final NotificationRecord r1 = generateNotificationRecord( 5656 mTestNotificationChannel, 1, null, true); 5657 r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5658 mService.addNotification(r1); 5659 final NotificationRecord r2 = generateNotificationRecord( 5660 mTestNotificationChannel, 2, null, true); 5661 r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5662 mService.addNotification(r2); 5663 5664 // Third notification that's NOT adjusted, just to make sure that doesn't get spuriously 5665 // logged. 5666 final NotificationRecord r3 = generateNotificationRecord( 5667 mTestNotificationChannel, 3, null, true); 5668 r3.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5669 mService.addNotification(r3); 5670 5671 List<Adjustment> adjustments = new ArrayList<>(); 5672 5673 // Test an adjustment that's associated with a ranking change and one that's not 5674 Bundle signals1 = new Bundle(); 5675 signals1.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_HIGH); 5676 Adjustment adjustment1 = new Adjustment( 5677 r1.getSbn().getPackageName(), r1.getKey(), signals1, "", 5678 r1.getUser().getIdentifier()); 5679 adjustments.add(adjustment1); 5680 5681 // This one wouldn't trigger a ranking change, but should still trigger a log. 5682 Bundle signals2 = new Bundle(); 5683 signals2.putFloat(Adjustment.KEY_RANKING_SCORE, -0.5f); 5684 Adjustment adjustment2 = new Adjustment( 5685 r2.getSbn().getPackageName(), r2.getKey(), signals2, "", 5686 r2.getUser().getIdentifier()); 5687 adjustments.add(adjustment2); 5688 5689 mBinderService.applyAdjustmentsFromAssistant(null, adjustments); 5690 verify(mRankingHandler, times(1)).requestSort(); 5691 5692 // Actually apply the adjustments & recalculate importance when run 5693 doAnswer(invocationOnMock -> { 5694 ((NotificationRecord) invocationOnMock.getArguments()[0]) 5695 .applyAdjustments(); 5696 ((NotificationRecord) invocationOnMock.getArguments()[0]) 5697 .calculateImportance(); 5698 return null; 5699 }).when(mRankingHelper).extractSignals(any(NotificationRecord.class)); 5700 5701 // Now make sure that when the sort happens, we actually log the changes. 5702 mService.handleRankingSort(); 5703 5704 // Even though the ranking score change is not meant to trigger a ranking update, 5705 // during this process the package visibility & canShowBadge values are changing 5706 // in all notifications, so all 3 seem to trigger a ranking change. Here we check instead 5707 // that scheduleSendRankingUpdate is sent and that the relevant fields have been changed 5708 // accordingly to confirm the adjustments happened to the 2 relevant notifications. 5709 verify(handler, times(3)).scheduleSendRankingUpdate(); 5710 assertEquals(IMPORTANCE_HIGH, r1.getImportance()); 5711 assertTrue(r2.rankingScoreMatches(-0.5f)); 5712 assertEquals(2, mNotificationRecordLogger.numCalls()); 5713 assertEquals(NOTIFICATION_ADJUSTED, mNotificationRecordLogger.event(0)); 5714 assertEquals(NOTIFICATION_ADJUSTED, mNotificationRecordLogger.event(1)); 5715 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 5716 assertEquals(2, mNotificationRecordLogger.get(1).getInstanceId()); 5717 } 5718 5719 @Test testAdjustmentToImportanceNone_cancelsNotification()5720 public void testAdjustmentToImportanceNone_cancelsNotification() throws Exception { 5721 NotificationManagerService.WorkerHandler handler = mock( 5722 NotificationManagerService.WorkerHandler.class); 5723 mService.setHandler(handler); 5724 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5725 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); 5726 5727 // Set up notifications: r1 is adjusted, r2 is not 5728 final NotificationRecord r1 = generateNotificationRecord( 5729 mTestNotificationChannel, 1, null, true); 5730 r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5731 mService.addNotification(r1); 5732 final NotificationRecord r2 = generateNotificationRecord( 5733 mTestNotificationChannel, 2, null, true); 5734 r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5735 mService.addNotification(r2); 5736 5737 // Test an adjustment that sets importance to none (meaning it's cancelling) 5738 Bundle signals1 = new Bundle(); 5739 signals1.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_NONE); 5740 Adjustment adjustment1 = new Adjustment( 5741 r1.getSbn().getPackageName(), r1.getKey(), signals1, "", 5742 r1.getUser().getIdentifier()); 5743 5744 mBinderService.applyAdjustmentFromAssistant(null, adjustment1); 5745 5746 // Actually apply the adjustments & recalculate importance when run 5747 doAnswer(invocationOnMock -> { 5748 ((NotificationRecord) invocationOnMock.getArguments()[0]) 5749 .applyAdjustments(); 5750 ((NotificationRecord) invocationOnMock.getArguments()[0]) 5751 .calculateImportance(); 5752 return null; 5753 }).when(mRankingHelper).extractSignals(any(NotificationRecord.class)); 5754 5755 // run the CancelNotificationRunnable when it happens 5756 ArgumentCaptor<NotificationManagerService.CancelNotificationRunnable> captor = 5757 ArgumentCaptor.forClass( 5758 NotificationManagerService.CancelNotificationRunnable.class); 5759 5760 verify(handler, times(1)).scheduleCancelNotification( 5761 captor.capture()); 5762 5763 // Run the runnable given to the cancel notification, and see if it logs properly 5764 NotificationManagerService.CancelNotificationRunnable runnable = captor.getValue(); 5765 runnable.run(); 5766 assertEquals(1, mNotificationRecordLogger.numCalls()); 5767 assertEquals( 5768 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_ASSISTANT, 5769 mNotificationRecordLogger.event(0)); 5770 } 5771 5772 @Test testEnqueuedAdjustmentAppliesAdjustments()5773 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception { 5774 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5775 mService.addEnqueuedNotification(r); 5776 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5777 5778 Bundle signals = new Bundle(); 5779 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5780 USER_SENTIMENT_NEGATIVE); 5781 Adjustment adjustment = new Adjustment( 5782 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5783 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5784 5785 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment()); 5786 } 5787 5788 @Test testEnqueuedAdjustmentAppliesAdjustments_MultiNotifications()5789 public void testEnqueuedAdjustmentAppliesAdjustments_MultiNotifications() throws Exception { 5790 final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel); 5791 final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel); 5792 mService.addEnqueuedNotification(r1); 5793 mService.addEnqueuedNotification(r2); 5794 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5795 5796 Bundle signals = new Bundle(); 5797 signals.putInt(Adjustment.KEY_IMPORTANCE, 5798 IMPORTANCE_HIGH); 5799 Adjustment adjustment = new Adjustment( 5800 r1.getSbn().getPackageName(), r1.getKey(), signals, 5801 "", r1.getUser().getIdentifier()); 5802 5803 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5804 5805 assertEquals(IMPORTANCE_HIGH, r1.getImportance()); 5806 assertEquals(IMPORTANCE_HIGH, r2.getImportance()); 5807 } 5808 5809 @Test testRestore()5810 public void testRestore() throws Exception { 5811 int systemChecks = mService.countSystemChecks; 5812 mBinderService.applyRestore(null, USER_SYSTEM); 5813 assertEquals(1, mService.countSystemChecks - systemChecks); 5814 } 5815 5816 @Test testBackupEmptySound()5817 public void testBackupEmptySound() throws Exception { 5818 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); 5819 channel.setSound(Uri.EMPTY, null); 5820 5821 TypedXmlSerializer serializer = Xml.newFastSerializer(); 5822 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 5823 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 5824 channel.writeXmlForBackup(serializer, getContext()); 5825 5826 TypedXmlPullParser parser = Xml.newFastPullParser(); 5827 parser.setInput(new BufferedInputStream( 5828 new ByteArrayInputStream(baos.toByteArray())), null); 5829 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); 5830 restored.populateFromXmlForRestore(parser, true, getContext()); 5831 5832 assertNull(restored.getSound()); 5833 } 5834 5835 @Test testBackup()5836 public void testBackup() throws Exception { 5837 mService.setPreferencesHelper(mPreferencesHelper); 5838 int systemChecks = mService.countSystemChecks; 5839 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt())) 5840 .thenReturn(new ArraySet<>()); 5841 mBinderService.getBackupPayload(1); 5842 assertEquals(1, mService.countSystemChecks - systemChecks); 5843 } 5844 5845 @Test testEmptyVibration_noException()5846 public void testEmptyVibration_noException() throws Exception { 5847 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); 5848 channel.setVibrationPattern(new long[0]); 5849 5850 TypedXmlSerializer serializer = Xml.newFastSerializer(); 5851 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 5852 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 5853 channel.writeXml(serializer); 5854 } 5855 5856 @Test updateUriPermissions_update()5857 public void updateUriPermissions_update() throws Exception { 5858 NotificationChannel c = new NotificationChannel( 5859 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 5860 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT); 5861 Message message1 = new Message("", 0, ""); 5862 message1.setData("", 5863 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1)); 5864 Message message2 = new Message("", 1, ""); 5865 message2.setData("", 5866 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2)); 5867 5868 Notification.Builder nbA = new Notification.Builder(mContext, c.getId()) 5869 .setContentTitle("foo") 5870 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5871 .setStyle(new Notification.MessagingStyle("") 5872 .addMessage(message1) 5873 .addMessage(message2)); 5874 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification( 5875 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid), 5876 null, 0), c); 5877 5878 // First post means we grant access to both 5879 reset(mUgm); 5880 reset(mUgmInternal); 5881 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder()); 5882 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), 5883 USER_SYSTEM); 5884 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 5885 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt()); 5886 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 5887 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt()); 5888 5889 Notification.Builder nbB = new Notification.Builder(mContext, c.getId()) 5890 .setContentTitle("foo") 5891 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5892 .setStyle(new Notification.MessagingStyle("").addMessage(message2)); 5893 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG, 5894 PKG, 0, "tag", mUid, 0, nbB.build(), UserHandle.getUserHandleForUid(mUid), null, 0), 5895 c); 5896 5897 // Update means we drop access to first 5898 reset(mUgmInternal); 5899 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(), 5900 USER_SYSTEM); 5901 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), 5902 eq(message1.getDataUri()), anyInt(), anyInt(), eq(null), eq(-1)); 5903 5904 // Update back means we grant access to first again 5905 reset(mUgm); 5906 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(), 5907 USER_SYSTEM); 5908 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 5909 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt()); 5910 5911 // And update to empty means we drop everything 5912 reset(mUgmInternal); 5913 mService.updateUriPermissions(null, recordB, mContext.getPackageName(), 5914 USER_SYSTEM); 5915 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null), 5916 anyInt(), anyInt()); 5917 } 5918 5919 @Test updateUriPermissions_posterDoesNotOwnUri()5920 public void updateUriPermissions_posterDoesNotOwnUri() throws Exception { 5921 NotificationChannel c = new NotificationChannel( 5922 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 5923 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT); 5924 Message message1 = new Message("", 0, ""); 5925 message1.setData("", 5926 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1)); 5927 5928 Notification.Builder nbA = new Notification.Builder(mContext, c.getId()) 5929 .setContentTitle("foo") 5930 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5931 .setStyle(new Notification.MessagingStyle("") 5932 .addMessage(message1)); 5933 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification( 5934 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid), 5935 null, 0), c); 5936 5937 doThrow(new SecurityException("no access")).when(mUgm) 5938 .grantUriPermissionFromOwner( 5939 any(), anyInt(), any(), any(), anyInt(), anyInt(), anyInt()); 5940 5941 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder()); 5942 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), USER_SYSTEM); 5943 5944 // yay, no crash 5945 } 5946 5947 @Test testVisitUris()5948 public void testVisitUris() throws Exception { 5949 final Uri audioContents = Uri.parse("content://com.example/audio"); 5950 final Uri backgroundImage = Uri.parse("content://com.example/background"); 5951 final Icon smallIcon = Icon.createWithContentUri("content://media/small/icon"); 5952 final Icon largeIcon = Icon.createWithContentUri("content://media/large/icon"); 5953 final Icon personIcon1 = Icon.createWithContentUri("content://media/person1"); 5954 final Icon personIcon2 = Icon.createWithContentUri("content://media/person2"); 5955 final Icon personIcon3 = Icon.createWithContentUri("content://media/person3"); 5956 final Person person1 = new Person.Builder() 5957 .setName("Messaging Person") 5958 .setIcon(personIcon1) 5959 .build(); 5960 final Person person2 = new Person.Builder() 5961 .setName("People List Person 1") 5962 .setIcon(personIcon2) 5963 .build(); 5964 final Person person3 = new Person.Builder() 5965 .setName("People List Person 2") 5966 .setIcon(personIcon3) 5967 .build(); 5968 final Uri historyUri1 = Uri.parse("content://com.example/history1"); 5969 final Uri historyUri2 = Uri.parse("content://com.example/history2"); 5970 final RemoteInputHistoryItem historyItem1 = new RemoteInputHistoryItem(null, historyUri1, 5971 "a"); 5972 final RemoteInputHistoryItem historyItem2 = new RemoteInputHistoryItem(null, historyUri2, 5973 "b"); 5974 5975 Bundle extras = new Bundle(); 5976 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents); 5977 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString()); 5978 extras.putParcelable(Notification.EXTRA_MESSAGING_PERSON, person1); 5979 extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, 5980 new ArrayList<>(Arrays.asList(person2, person3))); 5981 extras.putParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS, 5982 new RemoteInputHistoryItem[]{historyItem1, historyItem2}); 5983 5984 Notification n = new Notification.Builder(mContext, "a") 5985 .setContentTitle("notification with uris") 5986 .setSmallIcon(smallIcon) 5987 .setLargeIcon(largeIcon) 5988 .addExtras(extras) 5989 .build(); 5990 5991 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 5992 n.visitUris(visitor); 5993 verify(visitor, times(1)).accept(eq(audioContents)); 5994 verify(visitor, times(1)).accept(eq(backgroundImage)); 5995 verify(visitor, times(1)).accept(eq(smallIcon.getUri())); 5996 verify(visitor, times(1)).accept(eq(largeIcon.getUri())); 5997 verify(visitor, times(1)).accept(eq(personIcon1.getUri())); 5998 verify(visitor, times(1)).accept(eq(personIcon2.getUri())); 5999 verify(visitor, times(1)).accept(eq(personIcon3.getUri())); 6000 verify(visitor, times(1)).accept(eq(historyUri1)); 6001 verify(visitor, times(1)).accept(eq(historyUri2)); 6002 } 6003 6004 @Test testVisitUris_publicVersion()6005 public void testVisitUris_publicVersion() throws Exception { 6006 final Icon smallIconPublic = Icon.createWithContentUri("content://media/small/icon"); 6007 final Icon largeIconPrivate = Icon.createWithContentUri("content://media/large/icon"); 6008 6009 Notification publicVersion = new Notification.Builder(mContext, "a") 6010 .setContentTitle("notification with uris") 6011 .setSmallIcon(smallIconPublic) 6012 .build(); 6013 Notification n = new Notification.Builder(mContext, "a") 6014 .setLargeIcon(largeIconPrivate) 6015 .setPublicVersion(publicVersion) 6016 .build(); 6017 6018 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 6019 n.visitUris(visitor); 6020 verify(visitor, times(1)).accept(eq(smallIconPublic.getUri())); 6021 verify(visitor, times(1)).accept(eq(largeIconPrivate.getUri())); 6022 } 6023 6024 @Test testVisitUris_audioContentsString()6025 public void testVisitUris_audioContentsString() throws Exception { 6026 final Uri audioContents = Uri.parse("content://com.example/audio"); 6027 6028 Bundle extras = new Bundle(); 6029 extras.putString(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents.toString()); 6030 6031 Notification n = new Notification.Builder(mContext, "a") 6032 .setContentTitle("notification with uris") 6033 .setSmallIcon(android.R.drawable.sym_def_app_icon) 6034 .addExtras(extras) 6035 .build(); 6036 6037 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 6038 n.visitUris(visitor); 6039 verify(visitor, times(1)).accept(eq(audioContents)); 6040 } 6041 6042 @Test testVisitUris_messagingStyle()6043 public void testVisitUris_messagingStyle() { 6044 final Icon personIcon1 = Icon.createWithContentUri("content://media/person1"); 6045 final Icon personIcon2 = Icon.createWithContentUri("content://media/person2"); 6046 final Icon personIcon3 = Icon.createWithContentUri("content://media/person3"); 6047 final Person person1 = new Person.Builder() 6048 .setName("Messaging Person 1") 6049 .setIcon(personIcon1) 6050 .build(); 6051 final Person person2 = new Person.Builder() 6052 .setName("Messaging Person 2") 6053 .setIcon(personIcon2) 6054 .build(); 6055 final Person person3 = new Person.Builder() 6056 .setName("Messaging Person 3") 6057 .setIcon(personIcon3) 6058 .build(); 6059 Icon shortcutIcon = Icon.createWithContentUri("content://media/shortcut"); 6060 6061 Notification.Builder builder = new Notification.Builder(mContext, "a") 6062 .setCategory(Notification.CATEGORY_MESSAGE) 6063 .setContentTitle("new message!") 6064 .setContentText("Conversation Notification") 6065 .setSmallIcon(android.R.drawable.sym_def_app_icon); 6066 Notification.MessagingStyle.Message message1 = new Notification.MessagingStyle.Message( 6067 "Marco?", System.currentTimeMillis(), person2); 6068 Notification.MessagingStyle.Message message2 = new Notification.MessagingStyle.Message( 6069 "Polo!", System.currentTimeMillis(), person3); 6070 Notification.MessagingStyle style = new Notification.MessagingStyle(person1) 6071 .addMessage(message1) 6072 .addMessage(message2) 6073 .setShortcutIcon(shortcutIcon); 6074 builder.setStyle(style); 6075 Notification n = builder.build(); 6076 6077 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 6078 n.visitUris(visitor); 6079 6080 verify(visitor, times(1)).accept(eq(shortcutIcon.getUri())); 6081 verify(visitor, times(1)).accept(eq(personIcon1.getUri())); 6082 verify(visitor, times(1)).accept(eq(personIcon2.getUri())); 6083 verify(visitor, times(1)).accept(eq(personIcon3.getUri())); 6084 } 6085 6086 @Test testVisitUris_callStyle()6087 public void testVisitUris_callStyle() { 6088 Icon personIcon = Icon.createWithContentUri("content://media/person"); 6089 Icon verificationIcon = Icon.createWithContentUri("content://media/verification"); 6090 Person callingPerson = new Person.Builder().setName("Someone") 6091 .setIcon(personIcon) 6092 .build(); 6093 PendingIntent hangUpIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 6094 PendingIntent.FLAG_IMMUTABLE); 6095 Notification n = new Notification.Builder(mContext, "a") 6096 .setStyle(Notification.CallStyle.forOngoingCall(callingPerson, hangUpIntent) 6097 .setVerificationIcon(verificationIcon)) 6098 .setContentTitle("Calling...") 6099 .setSmallIcon(android.R.drawable.sym_def_app_icon) 6100 .build(); 6101 6102 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 6103 n.visitUris(visitor); 6104 6105 verify(visitor, times(1)).accept(eq(personIcon.getUri())); 6106 verify(visitor, times(1)).accept(eq(verificationIcon.getUri())); 6107 } 6108 6109 @Test testVisitUris_styleExtrasWithoutStyle()6110 public void testVisitUris_styleExtrasWithoutStyle() { 6111 Notification notification = new Notification.Builder(mContext, "a") 6112 .setSmallIcon(android.R.drawable.sym_def_app_icon) 6113 .build(); 6114 6115 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle( 6116 personWithIcon("content://user")) 6117 .addHistoricMessage(new Notification.MessagingStyle.Message("Heyhey!", 6118 System.currentTimeMillis(), 6119 personWithIcon("content://historicalMessenger"))) 6120 .addMessage(new Notification.MessagingStyle.Message("Are you there", 6121 System.currentTimeMillis(), 6122 personWithIcon("content://messenger"))) 6123 .setShortcutIcon( 6124 Icon.createWithContentUri("content://conversationShortcut")); 6125 messagingStyle.addExtras(notification.extras); // Instead of Builder.setStyle(style). 6126 6127 Notification.CallStyle callStyle = Notification.CallStyle.forOngoingCall( 6128 personWithIcon("content://caller"), 6129 PendingIntent.getActivity(mContext, 0, new Intent(), 6130 PendingIntent.FLAG_IMMUTABLE)) 6131 .setVerificationIcon(Icon.createWithContentUri("content://callVerification")); 6132 callStyle.addExtras(notification.extras); // Same. 6133 6134 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 6135 notification.visitUris(visitor); 6136 6137 verify(visitor).accept(eq(Uri.parse("content://user"))); 6138 verify(visitor).accept(eq(Uri.parse("content://historicalMessenger"))); 6139 verify(visitor).accept(eq(Uri.parse("content://messenger"))); 6140 verify(visitor).accept(eq(Uri.parse("content://conversationShortcut"))); 6141 verify(visitor).accept(eq(Uri.parse("content://caller"))); 6142 verify(visitor).accept(eq(Uri.parse("content://callVerification"))); 6143 } 6144 personWithIcon(String iconUri)6145 private static Person personWithIcon(String iconUri) { 6146 return new Person.Builder() 6147 .setName("Mr " + iconUri) 6148 .setIcon(Icon.createWithContentUri(iconUri)) 6149 .build(); 6150 } 6151 6152 @Test testVisitUris_wearableExtender()6153 public void testVisitUris_wearableExtender() { 6154 Icon actionIcon = Icon.createWithContentUri("content://media/action"); 6155 Icon wearActionIcon = Icon.createWithContentUri("content://media/wearAction"); 6156 PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent(), 6157 PendingIntent.FLAG_IMMUTABLE); 6158 Notification n = new Notification.Builder(mContext, "a") 6159 .setSmallIcon(android.R.drawable.sym_def_app_icon) 6160 .addAction(new Notification.Action.Builder(actionIcon, "Hey!", intent).build()) 6161 .extend(new Notification.WearableExtender().addAction( 6162 new Notification.Action.Builder(wearActionIcon, "Wear!", intent).build())) 6163 .build(); 6164 6165 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 6166 n.visitUris(visitor); 6167 6168 verify(visitor).accept(eq(actionIcon.getUri())); 6169 verify(visitor).accept(eq(wearActionIcon.getUri())); 6170 } 6171 6172 @Test testSetNotificationPolicy_preP_setOldFields()6173 public void testSetNotificationPolicy_preP_setOldFields() { 6174 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6175 mService.mZenModeHelper = mZenModeHelper; 6176 NotificationManager.Policy userPolicy = 6177 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6178 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6179 6180 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6181 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 6182 6183 int expected = SUPPRESSED_EFFECT_BADGE 6184 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 6185 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS 6186 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 6187 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 6188 6189 assertEquals(expected, actual); 6190 } 6191 6192 @Test testSetNotificationPolicy_preP_setNewFields()6193 public void testSetNotificationPolicy_preP_setNewFields() { 6194 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6195 mService.mZenModeHelper = mZenModeHelper; 6196 NotificationManager.Policy userPolicy = 6197 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6198 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6199 6200 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6201 SUPPRESSED_EFFECT_NOTIFICATION_LIST); 6202 6203 int expected = SUPPRESSED_EFFECT_BADGE; 6204 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 6205 6206 assertEquals(expected, actual); 6207 } 6208 6209 @Test testSetNotificationPolicy_preP_setOldNewFields()6210 public void testSetNotificationPolicy_preP_setOldNewFields() { 6211 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6212 mService.mZenModeHelper = mZenModeHelper; 6213 NotificationManager.Policy userPolicy = 6214 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6215 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6216 6217 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6218 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 6219 6220 int expected = 6221 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK; 6222 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 6223 6224 assertEquals(expected, actual); 6225 } 6226 6227 @Test testSetNotificationPolicy_P_setOldFields()6228 public void testSetNotificationPolicy_P_setOldFields() { 6229 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6230 mService.mZenModeHelper = mZenModeHelper; 6231 NotificationManager.Policy userPolicy = 6232 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6233 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6234 6235 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6236 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 6237 6238 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 6239 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT 6240 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 6241 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 6242 6243 assertEquals(expected, actual); 6244 } 6245 6246 @Test testSetNotificationPolicy_P_setNewFields()6247 public void testSetNotificationPolicy_P_setNewFields() { 6248 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6249 mService.mZenModeHelper = mZenModeHelper; 6250 NotificationManager.Policy userPolicy = 6251 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6252 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6253 6254 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6255 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT 6256 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 6257 6258 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF 6259 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS 6260 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 6261 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 6262 6263 assertEquals(expected, actual); 6264 } 6265 6266 @Test testSetNotificationPolicy_P_setOldNewFields()6267 public void testSetNotificationPolicy_P_setOldNewFields() { 6268 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6269 mService.mZenModeHelper = mZenModeHelper; 6270 NotificationManager.Policy userPolicy = 6271 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6272 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6273 6274 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6275 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 6276 6277 int expected = SUPPRESSED_EFFECT_STATUS_BAR; 6278 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 6279 6280 assertEquals(expected, actual); 6281 6282 appPolicy = new NotificationManager.Policy(0, 0, 0, 6283 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT 6284 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 6285 6286 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT 6287 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 6288 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 6289 6290 assertEquals(expected, actual); 6291 } 6292 6293 @Test testVisualDifference_foreground()6294 public void testVisualDifference_foreground() { 6295 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6296 .setContentTitle("foo"); 6297 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6298 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6299 NotificationRecord r1 = 6300 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6301 6302 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6303 .setFlag(FLAG_FOREGROUND_SERVICE, true) 6304 .setContentTitle("bar"); 6305 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6306 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6307 NotificationRecord r2 = 6308 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6309 6310 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6311 } 6312 6313 @Test testVisualDifference_diffTitle()6314 public void testVisualDifference_diffTitle() { 6315 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6316 .setContentTitle("foo"); 6317 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6318 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6319 NotificationRecord r1 = 6320 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6321 6322 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6323 .setContentTitle("bar"); 6324 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6325 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6326 NotificationRecord r2 = 6327 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6328 6329 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 6330 } 6331 6332 @Test testVisualDifference_inboxStyle()6333 public void testVisualDifference_inboxStyle() { 6334 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6335 .setStyle(new Notification.InboxStyle() 6336 .addLine("line1").addLine("line2")); 6337 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6338 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6339 NotificationRecord r1 = 6340 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6341 6342 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6343 .setStyle(new Notification.InboxStyle() 6344 .addLine("line1").addLine("line2_changed")); 6345 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6346 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6347 NotificationRecord r2 = 6348 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6349 6350 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed 6351 6352 Notification.Builder nb3 = new Notification.Builder(mContext, "") 6353 .setStyle(new Notification.InboxStyle() 6354 .addLine("line1")); 6355 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6356 nb3.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6357 NotificationRecord r3 = 6358 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class)); 6359 6360 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed 6361 6362 Notification.Builder nb4 = new Notification.Builder(mContext, "") 6363 .setStyle(new Notification.InboxStyle() 6364 .addLine("line1").addLine("line2").addLine("line3")); 6365 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6366 nb4.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6367 NotificationRecord r4 = 6368 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class)); 6369 6370 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed 6371 6372 Notification.Builder nb5 = new Notification.Builder(mContext, "") 6373 .setContentText("not an inbox"); 6374 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6375 nb5.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6376 NotificationRecord r5 = 6377 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class)); 6378 6379 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed 6380 } 6381 6382 @Test testVisualDifference_diffText()6383 public void testVisualDifference_diffText() { 6384 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6385 .setContentText("foo"); 6386 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6387 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6388 NotificationRecord r1 = 6389 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6390 6391 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6392 .setContentText("bar"); 6393 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6394 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6395 NotificationRecord r2 = 6396 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6397 6398 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 6399 } 6400 6401 @Test testVisualDifference_sameText()6402 public void testVisualDifference_sameText() { 6403 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6404 .setContentText("foo"); 6405 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6406 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6407 NotificationRecord r1 = 6408 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6409 6410 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6411 .setContentText("foo"); 6412 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6413 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6414 NotificationRecord r2 = 6415 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6416 6417 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6418 } 6419 6420 @Test testVisualDifference_sameTextButStyled()6421 public void testVisualDifference_sameTextButStyled() { 6422 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6423 .setContentText(Html.fromHtml("<b>foo</b>")); 6424 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6425 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6426 NotificationRecord r1 = 6427 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6428 6429 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6430 .setContentText(Html.fromHtml("<b>foo</b>")); 6431 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6432 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6433 NotificationRecord r2 = 6434 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6435 6436 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6437 } 6438 6439 @Test testVisualDifference_diffTextButStyled()6440 public void testVisualDifference_diffTextButStyled() { 6441 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6442 .setContentText(Html.fromHtml("<b>foo</b>")); 6443 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6444 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6445 NotificationRecord r1 = 6446 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6447 6448 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6449 .setContentText(Html.fromHtml("<b>bar</b>")); 6450 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6451 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6452 NotificationRecord r2 = 6453 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6454 6455 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 6456 } 6457 6458 @Test testVisualDifference_diffProgress()6459 public void testVisualDifference_diffProgress() { 6460 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6461 .setProgress(100, 90, false); 6462 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6463 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6464 NotificationRecord r1 = 6465 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6466 6467 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6468 .setProgress(100, 100, false); 6469 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6470 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6471 NotificationRecord r2 = 6472 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6473 6474 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 6475 } 6476 6477 @Test testVisualDifference_diffProgressNotDone()6478 public void testVisualDifference_diffProgressNotDone() { 6479 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6480 .setProgress(100, 90, false); 6481 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6482 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6483 NotificationRecord r1 = 6484 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6485 6486 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6487 .setProgress(100, 91, false); 6488 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6489 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6490 NotificationRecord r2 = 6491 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6492 6493 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6494 } 6495 6496 @Test testVisualDifference_sameProgressStillDone()6497 public void testVisualDifference_sameProgressStillDone() { 6498 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6499 .setProgress(100, 100, false); 6500 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6501 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6502 NotificationRecord r1 = 6503 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6504 6505 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6506 .setProgress(100, 100, false); 6507 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6508 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6509 NotificationRecord r2 = 6510 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6511 6512 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6513 } 6514 6515 @Test testVisualDifference_summary()6516 public void testVisualDifference_summary() { 6517 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6518 .setGroup("bananas") 6519 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 6520 .setContentText("foo"); 6521 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6522 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6523 NotificationRecord r1 = 6524 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6525 6526 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6527 .setGroup("bananas") 6528 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 6529 .setContentText("bar"); 6530 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6531 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6532 NotificationRecord r2 = 6533 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6534 6535 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6536 } 6537 6538 @Test testVisualDifference_summaryNewNotification()6539 public void testVisualDifference_summaryNewNotification() { 6540 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6541 .setGroup("bananas") 6542 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 6543 .setContentText("bar"); 6544 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6545 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6546 NotificationRecord r2 = 6547 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6548 6549 assertFalse(mService.isVisuallyInterruptive(null, r2)); 6550 } 6551 6552 @Test testVisualDifference_sameImages()6553 public void testVisualDifference_sameImages() { 6554 Icon large = Icon.createWithResource(mContext, 1); 6555 Notification n1 = new Notification.Builder(mContext, "channel") 6556 .setSmallIcon(1).setLargeIcon(large).build(); 6557 Notification n2 = new Notification.Builder(mContext, "channel") 6558 .setSmallIcon(1).setLargeIcon(large).build(); 6559 6560 NotificationRecord r1 = notificationToRecord(n1); 6561 NotificationRecord r2 = notificationToRecord(n2); 6562 6563 assertThat(mService.isVisuallyInterruptive(r1, r2)).isFalse(); 6564 } 6565 6566 @Test testVisualDifference_differentSmallImage()6567 public void testVisualDifference_differentSmallImage() { 6568 Icon large = Icon.createWithResource(mContext, 1); 6569 Notification n1 = new Notification.Builder(mContext, "channel") 6570 .setSmallIcon(1).setLargeIcon(large).build(); 6571 Notification n2 = new Notification.Builder(mContext, "channel") 6572 .setSmallIcon(2).setLargeIcon(large).build(); 6573 6574 NotificationRecord r1 = notificationToRecord(n1); 6575 NotificationRecord r2 = notificationToRecord(n2); 6576 6577 assertThat(mService.isVisuallyInterruptive(r1, r2)).isTrue(); 6578 } 6579 6580 @Test testVisualDifference_differentLargeImage()6581 public void testVisualDifference_differentLargeImage() { 6582 Icon large1 = Icon.createWithResource(mContext, 1); 6583 Icon large2 = Icon.createWithResource(mContext, 2); 6584 Notification n1 = new Notification.Builder(mContext, "channel") 6585 .setSmallIcon(1).setLargeIcon(large1).build(); 6586 Notification n2 = new Notification.Builder(mContext, "channel") 6587 .setSmallIcon(1).setLargeIcon(large2).build(); 6588 6589 NotificationRecord r1 = notificationToRecord(n1); 6590 NotificationRecord r2 = notificationToRecord(n2); 6591 6592 assertThat(mService.isVisuallyInterruptive(r1, r2)).isTrue(); 6593 } 6594 notificationToRecord(Notification n)6595 private NotificationRecord notificationToRecord(Notification n) { 6596 return new NotificationRecord( 6597 mContext, 6598 new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, n, 6599 UserHandle.getUserHandleForUid(mUid), null, 0), 6600 mock(NotificationChannel.class)); 6601 } 6602 6603 @Test testHideAndUnhideNotificationsOnSuspendedPackageBroadcast()6604 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() { 6605 // post 2 notification from this package 6606 final NotificationRecord notif1 = generateNotificationRecord( 6607 mTestNotificationChannel, 1, null, true); 6608 final NotificationRecord notif2 = generateNotificationRecord( 6609 mTestNotificationChannel, 2, null, false); 6610 mService.addNotification(notif1); 6611 mService.addNotification(notif2); 6612 6613 // on broadcast, hide the 2 notifications 6614 simulatePackageSuspendBroadcast(true, PKG, notif1.getUid()); 6615 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class); 6616 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 6617 assertEquals(2, captorHide.getValue().size()); 6618 6619 // on broadcast, unhide the 2 notifications 6620 simulatePackageSuspendBroadcast(false, PKG, notif1.getUid()); 6621 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class); 6622 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 6623 assertEquals(2, captorUnhide.getValue().size()); 6624 } 6625 6626 @Test testNoNotificationsHiddenOnSuspendedPackageBroadcast()6627 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() { 6628 // post 2 notification from this package 6629 final NotificationRecord notif1 = generateNotificationRecord( 6630 mTestNotificationChannel, 1, null, true); 6631 final NotificationRecord notif2 = generateNotificationRecord( 6632 mTestNotificationChannel, 2, null, false); 6633 mService.addNotification(notif1); 6634 mService.addNotification(notif2); 6635 6636 // on broadcast, nothing is hidden since no notifications are of package "test_package" 6637 simulatePackageSuspendBroadcast(true, "test_package", notif1.getUid()); 6638 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 6639 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 6640 assertEquals(0, captor.getValue().size()); 6641 } 6642 6643 @Test testNotificationFromDifferentUserHidden()6644 public void testNotificationFromDifferentUserHidden() { 6645 // post 2 notification from this package 6646 final NotificationRecord notif1 = generateNotificationRecord( 6647 mTestNotificationChannel, 1, null, true); 6648 final NotificationRecord notif2 = generateNotificationRecord( 6649 mTestNotificationChannel, 2, null, false); 6650 mService.addNotification(notif1); 6651 mService.addNotification(notif2); 6652 6653 // on broadcast, nothing is hidden since no notifications are of user 10 with package PKG 6654 simulatePackageSuspendBroadcast(true, PKG, 10); 6655 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 6656 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 6657 assertEquals(0, captor.getValue().size()); 6658 } 6659 6660 @Test testHideAndUnhideNotificationsOnDistractingPackageBroadcast()6661 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() { 6662 // Post 2 notifications from 2 packages 6663 NotificationRecord pkgA = new NotificationRecord(mContext, 6664 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 6665 mService.addNotification(pkgA); 6666 NotificationRecord pkgB = new NotificationRecord(mContext, 6667 generateSbn("b", 1001, 9, 0), mTestNotificationChannel); 6668 mService.addNotification(pkgB); 6669 6670 // on broadcast, hide one of the packages 6671 simulatePackageDistractionBroadcast( 6672 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"}, 6673 new int[] {1000}); 6674 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class); 6675 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 6676 assertEquals(1, captorHide.getValue().size()); 6677 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName()); 6678 6679 // on broadcast, unhide the package 6680 simulatePackageDistractionBroadcast( 6681 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"}, 6682 new int[] {1000}); 6683 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class); 6684 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 6685 assertEquals(1, captorUnhide.getValue().size()); 6686 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName()); 6687 } 6688 6689 @Test testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg()6690 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() { 6691 // Post 2 notifications from 2 packages 6692 NotificationRecord pkgA = new NotificationRecord(mContext, 6693 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 6694 mService.addNotification(pkgA); 6695 NotificationRecord pkgB = new NotificationRecord(mContext, 6696 generateSbn("b", 1001, 9, 0), mTestNotificationChannel); 6697 mService.addNotification(pkgB); 6698 6699 // on broadcast, hide one of the packages 6700 simulatePackageDistractionBroadcast( 6701 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"}, 6702 new int[] {1000, 1001}); 6703 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class); 6704 6705 // should be called only once. 6706 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 6707 assertEquals(2, captorHide.getValue().size()); 6708 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName()); 6709 assertEquals("b", captorHide.getValue().get(1).getSbn().getPackageName()); 6710 6711 // on broadcast, unhide the package 6712 simulatePackageDistractionBroadcast( 6713 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"}, 6714 new int[] {1000, 1001}); 6715 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class); 6716 6717 // should be called only once. 6718 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 6719 assertEquals(2, captorUnhide.getValue().size()); 6720 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName()); 6721 assertEquals("b", captorUnhide.getValue().get(1).getSbn().getPackageName()); 6722 } 6723 6724 @Test testNoNotificationsHiddenOnDistractingPackageBroadcast()6725 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() { 6726 // post notification from this package 6727 final NotificationRecord notif1 = generateNotificationRecord( 6728 mTestNotificationChannel, 1, null, true); 6729 mService.addNotification(notif1); 6730 6731 // on broadcast, nothing is hidden since no notifications are of package "test_package" 6732 simulatePackageDistractionBroadcast( 6733 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"}, 6734 new int[]{notif1.getUid()}); 6735 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 6736 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 6737 assertEquals(0, captor.getValue().size()); 6738 } 6739 6740 @Test testCanUseManagedServicesNullPkg()6741 public void testCanUseManagedServicesNullPkg() { 6742 assertEquals(true, mService.canUseManagedServices(null, 0, null)); 6743 } 6744 6745 6746 @Test testCanUseManagedServicesNoValidPkg()6747 public void testCanUseManagedServicesNoValidPkg() { 6748 assertEquals(true, mService.canUseManagedServices("d", 0, null)); 6749 } 6750 6751 @Test testCanUseManagedServices_hasPermission()6752 public void testCanUseManagedServices_hasPermission() throws Exception { 6753 when(mPackageManager.checkPermission("perm", "pkg", 0)) 6754 .thenReturn(PackageManager.PERMISSION_GRANTED); 6755 6756 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm")); 6757 } 6758 6759 @Test testCanUseManagedServices_noPermission()6760 public void testCanUseManagedServices_noPermission() throws Exception { 6761 when(mPackageManager.checkPermission("perm", "pkg", 0)) 6762 .thenReturn(PackageManager.PERMISSION_DENIED); 6763 6764 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm")); 6765 } 6766 6767 @Test testCanUseManagedServices_permDoesNotMatter()6768 public void testCanUseManagedServices_permDoesNotMatter() { 6769 assertEquals(true, mService.canUseManagedServices("pkg", 0, null)); 6770 } 6771 6772 @Test testOnNotificationVisibilityChanged_triggersInterruptionUsageStat()6773 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() { 6774 final NotificationRecord r = generateNotificationRecord( 6775 mTestNotificationChannel, 1, null, true); 6776 r.setTextChanged(true); 6777 mService.addNotification(r); 6778 6779 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[] 6780 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}, 6781 new NotificationVisibility[]{}); 6782 6783 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt()); 6784 } 6785 6786 @Test testOnNotificationVisibilityChanged_triggersVisibilityLog()6787 public void testOnNotificationVisibilityChanged_triggersVisibilityLog() { 6788 final NotificationRecord r = generateNotificationRecord( 6789 mTestNotificationChannel, 1, null, true); 6790 r.setTextChanged(true); 6791 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 6792 mService.addNotification(r); 6793 6794 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[] 6795 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}, 6796 new NotificationVisibility[]{}); 6797 6798 assertEquals(1, mNotificationRecordLogger.numCalls()); 6799 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN, 6800 mNotificationRecordLogger.event(0)); 6801 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 6802 6803 mService.mNotificationDelegate.onNotificationVisibilityChanged( 6804 new NotificationVisibility[]{}, 6805 new NotificationVisibility[] 6806 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)} 6807 ); 6808 6809 assertEquals(2, mNotificationRecordLogger.numCalls()); 6810 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE, 6811 mNotificationRecordLogger.event(1)); 6812 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); 6813 } 6814 6815 @Test testSetNotificationsShownFromListener_triggersInterruptionUsageStat()6816 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat() 6817 throws RemoteException { 6818 final NotificationRecord r = generateNotificationRecord( 6819 mTestNotificationChannel, 1, null, true); 6820 r.setTextChanged(true); 6821 mService.addNotification(r); 6822 6823 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()}); 6824 6825 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt()); 6826 } 6827 6828 @Test testSetNotificationsShownFromListener_protectsCrossUserInformation()6829 public void testSetNotificationsShownFromListener_protectsCrossUserInformation() 6830 throws RemoteException { 6831 Notification.Builder nb = new Notification.Builder( 6832 mContext, mTestNotificationChannel.getId()) 6833 .setContentTitle("foo") 6834 .setSmallIcon(android.R.drawable.sym_def_app_icon); 6835 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 6836 "tag" + System.currentTimeMillis(), UserHandle.PER_USER_RANGE, 0, 6837 nb.build(), UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE), 6838 null, 0); 6839 final NotificationRecord r = 6840 new NotificationRecord(mContext, sbn, mTestNotificationChannel); 6841 r.setTextChanged(true); 6842 mService.addNotification(r); 6843 6844 // no security exception! 6845 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()}); 6846 6847 verify(mAppUsageStats, never()).reportInterruptiveNotification( 6848 anyString(), anyString(), anyInt()); 6849 } 6850 6851 @Test testCancelNotificationsFromListener_protectsCrossUserInformation()6852 public void testCancelNotificationsFromListener_protectsCrossUserInformation() 6853 throws RemoteException { 6854 Notification.Builder nb = new Notification.Builder( 6855 mContext, mTestNotificationChannel.getId()) 6856 .setContentTitle("foo") 6857 .setSmallIcon(android.R.drawable.sym_def_app_icon); 6858 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 6859 "tag" + System.currentTimeMillis(), UserHandle.PER_USER_RANGE, 0, 6860 nb.build(), UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE), 6861 null, 0); 6862 final NotificationRecord r = 6863 new NotificationRecord(mContext, sbn, mTestNotificationChannel); 6864 r.setTextChanged(true); 6865 mService.addNotification(r); 6866 6867 // no security exception! 6868 mBinderService.cancelNotificationsFromListener(null, new String[] {r.getKey()}); 6869 6870 waitForIdle(); 6871 assertEquals(1, mService.getNotificationRecordCount()); 6872 } 6873 6874 @Test testMaybeRecordInterruptionLocked_doesNotRecordTwice()6875 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice() 6876 throws RemoteException { 6877 final NotificationRecord r = generateNotificationRecord( 6878 mTestNotificationChannel, 1, null, true); 6879 r.setInterruptive(true); 6880 mService.addNotification(r); 6881 6882 mService.maybeRecordInterruptionLocked(r); 6883 mService.maybeRecordInterruptionLocked(r); 6884 6885 verify(mAppUsageStats, times(1)).reportInterruptiveNotification( 6886 anyString(), anyString(), anyInt()); 6887 verify(mHistoryManager, times(1)).addNotification(any()); 6888 } 6889 6890 @Test testMaybeRecordInterruptionLocked_smallIconsRequiredForHistory()6891 public void testMaybeRecordInterruptionLocked_smallIconsRequiredForHistory() 6892 throws RemoteException { 6893 final NotificationRecord r = generateNotificationRecord( 6894 mTestNotificationChannel, 1, null, true); 6895 r.setInterruptive(true); 6896 r.getSbn().getNotification().setSmallIcon(null); 6897 mService.addNotification(r); 6898 6899 mService.maybeRecordInterruptionLocked(r); 6900 6901 verify(mAppUsageStats, times(1)).reportInterruptiveNotification( 6902 anyString(), anyString(), anyInt()); 6903 verify(mHistoryManager, never()).addNotification(any()); 6904 } 6905 6906 @Test testBubble()6907 public void testBubble() throws Exception { 6908 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE); 6909 assertFalse(mBinderService.areBubblesAllowed(PKG)); 6910 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid), 6911 BUBBLE_PREFERENCE_NONE); 6912 } 6913 6914 @Test testUserApprovedBubblesForPackageSelected()6915 public void testUserApprovedBubblesForPackageSelected() throws Exception { 6916 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_SELECTED); 6917 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid), 6918 BUBBLE_PREFERENCE_SELECTED); 6919 } 6920 6921 @Test testUserApprovedBubblesForPackageAll()6922 public void testUserApprovedBubblesForPackageAll() throws Exception { 6923 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_ALL); 6924 assertTrue(mBinderService.areBubblesAllowed(PKG)); 6925 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid), 6926 BUBBLE_PREFERENCE_ALL); 6927 } 6928 6929 @Test testUserRejectsBubblesForPackage()6930 public void testUserRejectsBubblesForPackage() throws Exception { 6931 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE); 6932 assertFalse(mBinderService.areBubblesAllowed(PKG)); 6933 } 6934 6935 @Test testAreBubblesEnabled()6936 public void testAreBubblesEnabled() throws Exception { 6937 Settings.Secure.putInt(mContext.getContentResolver(), 6938 Settings.Secure.NOTIFICATION_BUBBLES, 1); 6939 mService.mPreferencesHelper.updateBubblesEnabled(); 6940 assertTrue(mBinderService.areBubblesEnabled(UserHandle.getUserHandleForUid(mUid))); 6941 } 6942 6943 @Test testAreBubblesEnabled_false()6944 public void testAreBubblesEnabled_false() throws Exception { 6945 Settings.Secure.putInt(mContext.getContentResolver(), 6946 Settings.Secure.NOTIFICATION_BUBBLES, 0); 6947 mService.mPreferencesHelper.updateBubblesEnabled(); 6948 assertFalse(mBinderService.areBubblesEnabled(UserHandle.getUserHandleForUid(mUid))); 6949 } 6950 6951 @Test testAreBubblesEnabled_exception()6952 public void testAreBubblesEnabled_exception() throws Exception { 6953 try { 6954 assertTrue(mBinderService.areBubblesEnabled( 6955 UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE))); 6956 fail("Cannot call cross user without permission"); 6957 } catch (SecurityException e) { 6958 // pass 6959 } 6960 // cross user, with permission, no problem 6961 enableInteractAcrossUsers(); 6962 assertTrue(mBinderService.areBubblesEnabled( 6963 UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE))); 6964 } 6965 6966 @Test testIsCallerInstantApp_primaryUser()6967 public void testIsCallerInstantApp_primaryUser() throws Exception { 6968 ApplicationInfo info = new ApplicationInfo(); 6969 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 6970 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info); 6971 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 6972 6973 assertTrue(mService.isCallerInstantApp(45770, 0)); 6974 6975 info.privateFlags = 0; 6976 assertFalse(mService.isCallerInstantApp(575370, 0)); 6977 } 6978 6979 @Test testIsCallerInstantApp_secondaryUser()6980 public void testIsCallerInstantApp_secondaryUser() throws Exception { 6981 ApplicationInfo info = new ApplicationInfo(); 6982 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 6983 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(10))).thenReturn(info); 6984 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(null); 6985 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 6986 6987 assertTrue(mService.isCallerInstantApp(68638450, 10)); 6988 } 6989 6990 @Test testIsCallerInstantApp_userAllNotification()6991 public void testIsCallerInstantApp_userAllNotification() throws Exception { 6992 ApplicationInfo info = new ApplicationInfo(); 6993 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 6994 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(USER_SYSTEM))) 6995 .thenReturn(info); 6996 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 6997 6998 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL)); 6999 7000 info.privateFlags = 0; 7001 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL )); 7002 } 7003 7004 @Test testResolveNotificationUid_sameApp_nonSystemUser()7005 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception { 7006 ApplicationInfo info = new ApplicationInfo(); 7007 info.uid = Binder.getCallingUid(); 7008 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(10))).thenReturn(info); 7009 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(null); 7010 7011 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10); 7012 7013 assertEquals(info.uid, actualUid); 7014 } 7015 7016 @Test testResolveNotificationUid_sameApp()7017 public void testResolveNotificationUid_sameApp() throws Exception { 7018 ApplicationInfo info = new ApplicationInfo(); 7019 info.uid = Binder.getCallingUid(); 7020 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info); 7021 7022 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0); 7023 7024 assertEquals(info.uid, actualUid); 7025 } 7026 7027 @Test testResolveNotificationUid_sameAppDiffPackage()7028 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception { 7029 ApplicationInfo info = new ApplicationInfo(); 7030 info.uid = Binder.getCallingUid(); 7031 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info); 7032 7033 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0); 7034 7035 assertEquals(info.uid, actualUid); 7036 } 7037 7038 @Test testResolveNotificationUid_sameAppWrongUid()7039 public void testResolveNotificationUid_sameAppWrongUid() throws Exception { 7040 ApplicationInfo info = new ApplicationInfo(); 7041 info.uid = 1356347; 7042 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(info); 7043 7044 try { 7045 mService.resolveNotificationUid("caller", "caller", 9, 0); 7046 fail("Incorrect uid didn't throw security exception"); 7047 } catch (SecurityException e) { 7048 // yay 7049 } 7050 } 7051 7052 @Test testResolveNotificationUid_delegateAllowed()7053 public void testResolveNotificationUid_delegateAllowed() throws Exception { 7054 int expectedUid = 123; 7055 7056 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid); 7057 mService.setPreferencesHelper(mPreferencesHelper); 7058 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt())) 7059 .thenReturn(true); 7060 7061 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0)); 7062 } 7063 7064 @Test testResolveNotificationUid_androidAllowed()7065 public void testResolveNotificationUid_androidAllowed() throws Exception { 7066 int expectedUid = 123; 7067 7068 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid); 7069 // no delegate 7070 7071 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0)); 7072 } 7073 7074 @Test testPostFromAndroidForNonExistentPackage()7075 public void testPostFromAndroidForNonExistentPackage() throws Exception { 7076 final String notReal = "NOT REAL"; 7077 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow( 7078 PackageManager.NameNotFoundException.class); 7079 ApplicationInfo ai = new ApplicationInfo(); 7080 ai.uid = -1; 7081 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(ai); 7082 7083 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 7084 try { 7085 mInternalService.enqueueNotification(notReal, "android", 0, 0, 7086 "testPostFromAndroidForNonExistentPackage", 7087 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 7088 fail("can't post notifications for nonexistent packages, even if you exist"); 7089 } catch (SecurityException e) { 7090 // yay 7091 } 7092 } 7093 7094 @Test testCancelFromAndroidForNonExistentPackage()7095 public void testCancelFromAndroidForNonExistentPackage() throws Exception { 7096 final String notReal = "NOT REAL"; 7097 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow( 7098 PackageManager.NameNotFoundException.class); 7099 ApplicationInfo ai = new ApplicationInfo(); 7100 ai.uid = -1; 7101 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(ai); 7102 7103 // unlike the post case, ignore instead of throwing 7104 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 7105 7106 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag", 7107 sbn.getId(), sbn.getUserId()); 7108 } 7109 7110 @Test testResolveNotificationUid_delegateNotAllowed()7111 public void testResolveNotificationUid_delegateNotAllowed() throws Exception { 7112 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123); 7113 // no delegate 7114 7115 try { 7116 mService.resolveNotificationUid("caller", "target", 9, 0); 7117 fail("Incorrect uid didn't throw security exception"); 7118 } catch (SecurityException e) { 7119 // yay 7120 } 7121 } 7122 7123 @Test testRemoveForegroundServiceFlagFromNotification_enqueued()7124 public void testRemoveForegroundServiceFlagFromNotification_enqueued() { 7125 when(mAmi.applyForegroundServiceNotification( 7126 any(), anyString(), anyInt(), anyString(), anyInt())) 7127 .thenReturn(SHOW_IMMEDIATELY); 7128 Notification n = new Notification.Builder(mContext, "").build(); 7129 n.flags |= FLAG_FOREGROUND_SERVICE; 7130 7131 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 7132 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7133 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7134 7135 mService.addEnqueuedNotification(r); 7136 7137 mInternalService.removeForegroundServiceFlagFromNotification( 7138 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 7139 7140 waitForIdle(); 7141 7142 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any()); 7143 } 7144 7145 @Test testRemoveForegroundServiceFlagFromNotification_posted()7146 public void testRemoveForegroundServiceFlagFromNotification_posted() { 7147 when(mAmi.applyForegroundServiceNotification( 7148 any(), anyString(), anyInt(), anyString(), anyInt())) 7149 .thenReturn(SHOW_IMMEDIATELY); 7150 Notification n = new Notification.Builder(mContext, "").build(); 7151 n.flags |= FLAG_FOREGROUND_SERVICE; 7152 7153 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 7154 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7155 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7156 7157 mService.addNotification(r); 7158 7159 mInternalService.removeForegroundServiceFlagFromNotification( 7160 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 7161 7162 waitForIdle(); 7163 7164 ArgumentCaptor<NotificationRecord> captor = 7165 ArgumentCaptor.forClass(NotificationRecord.class); 7166 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any()); 7167 7168 assertEquals(0, captor.getValue().getNotification().flags); 7169 } 7170 7171 @Test testCannotRemoveForegroundFlagWhenOverLimit_enqueued()7172 public void testCannotRemoveForegroundFlagWhenOverLimit_enqueued() { 7173 when(mAmi.applyForegroundServiceNotification( 7174 any(), anyString(), anyInt(), anyString(), anyInt())) 7175 .thenReturn(SHOW_IMMEDIATELY); 7176 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 7177 Notification n = new Notification.Builder(mContext, "").build(); 7178 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0, 7179 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7180 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7181 mService.addEnqueuedNotification(r); 7182 } 7183 Notification n = new Notification.Builder(mContext, "").build(); 7184 n.flags |= FLAG_FOREGROUND_SERVICE; 7185 7186 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 7187 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0, 7188 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7189 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7190 7191 mService.addEnqueuedNotification(r); 7192 7193 mInternalService.removeForegroundServiceFlagFromNotification( 7194 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 7195 7196 waitForIdle(); 7197 7198 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, 7199 mService.getNotificationRecordCount()); 7200 } 7201 7202 @Test testCannotRemoveForegroundFlagWhenOverLimit_posted()7203 public void testCannotRemoveForegroundFlagWhenOverLimit_posted() { 7204 when(mAmi.applyForegroundServiceNotification( 7205 any(), anyString(), anyInt(), anyString(), anyInt())) 7206 .thenReturn(SHOW_IMMEDIATELY); 7207 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 7208 Notification n = new Notification.Builder(mContext, "").build(); 7209 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0, 7210 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7211 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7212 mService.addNotification(r); 7213 } 7214 Notification n = new Notification.Builder(mContext, "").build(); 7215 n.flags |= FLAG_FOREGROUND_SERVICE; 7216 7217 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 7218 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0, 7219 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7220 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7221 7222 mService.addNotification(r); 7223 7224 mInternalService.removeForegroundServiceFlagFromNotification( 7225 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 7226 7227 waitForIdle(); 7228 7229 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, 7230 mService.getNotificationRecordCount()); 7231 } 7232 7233 @Test testAllowForegroundCustomToasts()7234 public void testAllowForegroundCustomToasts() throws Exception { 7235 final String testPackage = "testPackageName"; 7236 assertEquals(0, mService.mToastQueue.size()); 7237 mService.isSystemUid = false; 7238 mService.isSystemAppId = false; 7239 setToastRateIsWithinQuota(true); 7240 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7241 7242 // package is not suspended 7243 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7244 .thenReturn(false); 7245 7246 // notifications from this package are blocked by the user 7247 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 7248 7249 setAppInForegroundForToasts(mUid, true); 7250 7251 // enqueue toast -> toast should still enqueue 7252 enqueueToast(testPackage, new TestableToastCallback()); 7253 assertEquals(1, mService.mToastQueue.size()); 7254 } 7255 7256 @Test testDisallowBackgroundCustomToasts()7257 public void testDisallowBackgroundCustomToasts() throws Exception { 7258 final String testPackage = "testPackageName"; 7259 assertEquals(0, mService.mToastQueue.size()); 7260 mService.isSystemUid = false; 7261 mService.isSystemAppId = false; 7262 setToastRateIsWithinQuota(true); 7263 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7264 7265 // package is not suspended 7266 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7267 .thenReturn(false); 7268 7269 setAppInForegroundForToasts(mUid, false); 7270 7271 // enqueue toast -> no toasts enqueued 7272 enqueueToast(testPackage, new TestableToastCallback()); 7273 assertEquals(0, mService.mToastQueue.size()); 7274 } 7275 7276 @Test testDontCallShowToastAgainOnTheSameCustomToast()7277 public void testDontCallShowToastAgainOnTheSameCustomToast() throws Exception { 7278 final String testPackage = "testPackageName"; 7279 assertEquals(0, mService.mToastQueue.size()); 7280 mService.isSystemUid = false; 7281 mService.isSystemAppId = false; 7282 setToastRateIsWithinQuota(true); 7283 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7284 7285 // package is not suspended 7286 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7287 .thenReturn(false); 7288 7289 setAppInForegroundForToasts(mUid, true); 7290 7291 Binder token = new Binder(); 7292 ITransientNotification callback = mock(ITransientNotification.class); 7293 INotificationManager nmService = (INotificationManager) mService.mService; 7294 7295 // first time trying to show the toast, showToast gets called 7296 enqueueToast(nmService, testPackage, token, callback); 7297 verify(callback, times(1)).show(any()); 7298 7299 // second time trying to show the same toast, showToast isn't called again (total number of 7300 // invocations stays at one) 7301 enqueueToast(nmService, testPackage, token, callback); 7302 verify(callback, times(1)).show(any()); 7303 } 7304 7305 @Test testToastRateLimiterWontPreventShowCallForCustomToastWhenInForeground()7306 public void testToastRateLimiterWontPreventShowCallForCustomToastWhenInForeground() 7307 throws Exception { 7308 final String testPackage = "testPackageName"; 7309 assertEquals(0, mService.mToastQueue.size()); 7310 mService.isSystemUid = false; 7311 mService.isSystemAppId = false; 7312 setToastRateIsWithinQuota(false); // rate limit reached 7313 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7314 7315 // package is not suspended 7316 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7317 .thenReturn(false); 7318 7319 setAppInForegroundForToasts(mUid, true); 7320 7321 Binder token = new Binder(); 7322 ITransientNotification callback = mock(ITransientNotification.class); 7323 INotificationManager nmService = (INotificationManager) mService.mService; 7324 7325 enqueueToast(nmService, testPackage, token, callback); 7326 verify(callback, times(1)).show(any()); 7327 } 7328 7329 @Test testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground()7330 public void testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground() 7331 throws Exception { 7332 final String testPackage = "testPackageName"; 7333 assertEquals(0, mService.mToastQueue.size()); 7334 mService.isSystemUid = false; 7335 mService.isSystemAppId = false; 7336 setToastRateIsWithinQuota(true); 7337 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7338 7339 // package is not suspended 7340 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7341 .thenReturn(false); 7342 7343 setAppInForegroundForToasts(mUid, true); 7344 7345 Binder token1 = new Binder(); 7346 Binder token2 = new Binder(); 7347 ITransientNotification callback1 = mock(ITransientNotification.class); 7348 ITransientNotification callback2 = mock(ITransientNotification.class); 7349 INotificationManager nmService = (INotificationManager) mService.mService; 7350 7351 enqueueToast(nmService, testPackage, token1, callback1); 7352 enqueueToast(nmService, testPackage, token2, callback2); 7353 7354 assertEquals(2, mService.mToastQueue.size()); // Both toasts enqueued. 7355 verify(callback1, times(1)).show(any()); // First toast shown. 7356 7357 setAppInForegroundForToasts(mUid, false); 7358 7359 mService.cancelToastLocked(0); // Remove the first toast, and show next. 7360 7361 assertEquals(0, mService.mToastQueue.size()); // Both toasts processed. 7362 verify(callback2, never()).show(any()); // Second toast was never shown. 7363 } 7364 7365 @Test testAllowForegroundTextToasts()7366 public void testAllowForegroundTextToasts() throws Exception { 7367 final String testPackage = "testPackageName"; 7368 assertEquals(0, mService.mToastQueue.size()); 7369 mService.isSystemUid = false; 7370 mService.isSystemAppId = false; 7371 setToastRateIsWithinQuota(true); 7372 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7373 7374 // package is not suspended 7375 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7376 .thenReturn(false); 7377 7378 setAppInForegroundForToasts(mUid, true); 7379 7380 // enqueue toast -> toast should still enqueue 7381 enqueueTextToast(testPackage, "Text"); 7382 assertEquals(1, mService.mToastQueue.size()); 7383 } 7384 7385 @Test testAllowBackgroundTextToasts()7386 public void testAllowBackgroundTextToasts() throws Exception { 7387 final String testPackage = "testPackageName"; 7388 assertEquals(0, mService.mToastQueue.size()); 7389 mService.isSystemUid = false; 7390 mService.isSystemAppId = false; 7391 setToastRateIsWithinQuota(true); 7392 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7393 7394 // package is not suspended 7395 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7396 .thenReturn(false); 7397 7398 setAppInForegroundForToasts(mUid, false); 7399 7400 // enqueue toast -> toast should still enqueue 7401 enqueueTextToast(testPackage, "Text"); 7402 assertEquals(1, mService.mToastQueue.size()); 7403 } 7404 7405 @Test testDontCallShowToastAgainOnTheSameTextToast()7406 public void testDontCallShowToastAgainOnTheSameTextToast() throws Exception { 7407 final String testPackage = "testPackageName"; 7408 assertEquals(0, mService.mToastQueue.size()); 7409 mService.isSystemUid = false; 7410 mService.isSystemAppId = false; 7411 setToastRateIsWithinQuota(true); 7412 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7413 7414 // package is not suspended 7415 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7416 .thenReturn(false); 7417 7418 setAppInForegroundForToasts(mUid, true); 7419 7420 Binder token = new Binder(); 7421 INotificationManager nmService = (INotificationManager) mService.mService; 7422 7423 // first time trying to show the toast, showToast gets called 7424 enqueueTextToast(testPackage, "Text"); 7425 verify(mStatusBar, times(1)) 7426 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt()); 7427 7428 // second time trying to show the same toast, showToast isn't called again (total number of 7429 // invocations stays at one) 7430 enqueueTextToast(testPackage, "Text"); 7431 verify(mStatusBar, times(1)) 7432 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt()); 7433 } 7434 7435 @Test testToastRateLimiterCanPreventShowCallForTextToast_whenInBackground()7436 public void testToastRateLimiterCanPreventShowCallForTextToast_whenInBackground() 7437 throws Exception { 7438 final String testPackage = "testPackageName"; 7439 assertEquals(0, mService.mToastQueue.size()); 7440 mService.isSystemUid = false; 7441 mService.isSystemAppId = false; 7442 setToastRateIsWithinQuota(false); // rate limit reached 7443 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7444 setAppInForegroundForToasts(mUid, false); 7445 7446 // package is not suspended 7447 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7448 .thenReturn(false); 7449 7450 Binder token = new Binder(); 7451 INotificationManager nmService = (INotificationManager) mService.mService; 7452 7453 enqueueTextToast(testPackage, "Text"); 7454 verify(mStatusBar, times(0)) 7455 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt()); 7456 } 7457 7458 @Test testToastRateLimiterWontPreventShowCallForTextToast_whenInForeground()7459 public void testToastRateLimiterWontPreventShowCallForTextToast_whenInForeground() 7460 throws Exception { 7461 final String testPackage = "testPackageName"; 7462 assertEquals(0, mService.mToastQueue.size()); 7463 mService.isSystemUid = false; 7464 mService.isSystemAppId = false; 7465 setToastRateIsWithinQuota(false); // rate limit reached 7466 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7467 setAppInForegroundForToasts(mUid, true); 7468 7469 // package is not suspended 7470 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7471 .thenReturn(false); 7472 7473 Binder token = new Binder(); 7474 INotificationManager nmService = (INotificationManager) mService.mService; 7475 7476 enqueueTextToast(testPackage, "Text"); 7477 verify(mStatusBar, times(1)) 7478 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt()); 7479 } 7480 7481 @Test testTextToastRateLimiterAllowsLimitAvoidanceWithPermission()7482 public void testTextToastRateLimiterAllowsLimitAvoidanceWithPermission() throws Exception { 7483 final String testPackage = "testPackageName"; 7484 assertEquals(0, mService.mToastQueue.size()); 7485 mService.isSystemUid = false; 7486 mService.isSystemAppId = false; 7487 setToastRateIsWithinQuota(false); // rate limit reached 7488 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, true); 7489 setAppInForegroundForToasts(mUid, false); 7490 7491 // package is not suspended 7492 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7493 .thenReturn(false); 7494 7495 Binder token = new Binder(); 7496 INotificationManager nmService = (INotificationManager) mService.mService; 7497 7498 enqueueTextToast(testPackage, "Text"); 7499 verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), 7500 anyInt()); 7501 } 7502 7503 @Test testRateLimitedToasts_windowsRemoved()7504 public void testRateLimitedToasts_windowsRemoved() throws Exception { 7505 final String testPackage = "testPackageName"; 7506 assertEquals(0, mService.mToastQueue.size()); 7507 mService.isSystemUid = false; 7508 mService.isSystemAppId = false; 7509 setToastRateIsWithinQuota(false); // rate limit reached 7510 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7511 setAppInForegroundForToasts(mUid, false); 7512 7513 // package is not suspended 7514 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7515 .thenReturn(false); 7516 7517 Binder token = new Binder(); 7518 INotificationManager nmService = (INotificationManager) mService.mService; 7519 7520 enqueueTextToast(testPackage, "Text"); 7521 7522 // window token was added when enqueued 7523 ArgumentCaptor<Binder> binderCaptor = 7524 ArgumentCaptor.forClass(Binder.class); 7525 verify(mWindowManagerInternal).addWindowToken(binderCaptor.capture(), 7526 eq(TYPE_TOAST), anyInt(), eq(null)); 7527 7528 // but never shown 7529 verify(mStatusBar, times(0)) 7530 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt()); 7531 7532 // and removed when rate limited 7533 verify(mWindowManagerInternal) 7534 .removeWindowToken(eq(binderCaptor.getValue()), eq(true), anyInt()); 7535 } 7536 7537 @Test backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast()7538 public void backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast() throws 7539 Exception { 7540 final String testPackage = "testPackageName"; 7541 assertEquals(0, mService.mToastQueue.size()); 7542 mService.isSystemUid = true; 7543 setToastRateIsWithinQuota(true); 7544 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7545 7546 // package is not suspended 7547 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7548 .thenReturn(false); 7549 7550 // notifications from this package are blocked by the user 7551 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 7552 7553 setAppInForegroundForToasts(mUid, false); 7554 7555 // enqueue toast -> toast should still enqueue 7556 enqueueToast(testPackage, new TestableToastCallback()); 7557 assertEquals(1, mService.mToastQueue.size()); 7558 verify(mAm).setProcessImportant(any(), anyInt(), eq(true), any()); 7559 } 7560 7561 @Test foregroundTextToast_callsSetProcessImportantAsNotForegroundForToast()7562 public void foregroundTextToast_callsSetProcessImportantAsNotForegroundForToast() throws 7563 Exception { 7564 final String testPackage = "testPackageName"; 7565 assertEquals(0, mService.mToastQueue.size()); 7566 mService.isSystemUid = false; 7567 mService.isSystemAppId = false; 7568 setToastRateIsWithinQuota(true); 7569 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7570 7571 // package is not suspended 7572 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7573 .thenReturn(false); 7574 7575 setAppInForegroundForToasts(mUid, true); 7576 7577 // enqueue toast -> toast should still enqueue 7578 enqueueTextToast(testPackage, "Text"); 7579 assertEquals(1, mService.mToastQueue.size()); 7580 verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any()); 7581 } 7582 7583 @Test backgroundTextToast_callsSetProcessImportantAsNotForegroundForToast()7584 public void backgroundTextToast_callsSetProcessImportantAsNotForegroundForToast() throws 7585 Exception { 7586 final String testPackage = "testPackageName"; 7587 assertEquals(0, mService.mToastQueue.size()); 7588 mService.isSystemUid = false; 7589 mService.isSystemAppId = false; 7590 setToastRateIsWithinQuota(true); 7591 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7592 7593 // package is not suspended 7594 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7595 .thenReturn(false); 7596 7597 setAppInForegroundForToasts(mUid, false); 7598 7599 // enqueue toast -> toast should still enqueue 7600 enqueueTextToast(testPackage, "Text"); 7601 assertEquals(1, mService.mToastQueue.size()); 7602 verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any()); 7603 } 7604 7605 @Test testTextToastsCallStatusBar()7606 public void testTextToastsCallStatusBar() throws Exception { 7607 allowTestPackageToToast(); 7608 7609 // enqueue toast -> no toasts enqueued 7610 enqueueTextToast(TEST_PACKAGE, "Text"); 7611 7612 verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY); 7613 } 7614 7615 @Test testTextToastsCallStatusBar_nonUiContext_defaultDisplay()7616 public void testTextToastsCallStatusBar_nonUiContext_defaultDisplay() 7617 throws Exception { 7618 allowTestPackageToToast(); 7619 7620 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, DEFAULT_DISPLAY); 7621 7622 verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY); 7623 } 7624 7625 @Test testTextToastsCallStatusBar_nonUiContext_secondaryDisplay()7626 public void testTextToastsCallStatusBar_nonUiContext_secondaryDisplay() 7627 throws Exception { 7628 allowTestPackageToToast(); 7629 mockIsUserVisible(SECONDARY_DISPLAY_ID, true); 7630 7631 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, SECONDARY_DISPLAY_ID); 7632 7633 verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID); 7634 } 7635 7636 @Test testTextToastsCallStatusBar_visibleBgUsers_uiContext_defaultDisplay()7637 public void testTextToastsCallStatusBar_visibleBgUsers_uiContext_defaultDisplay() 7638 throws Exception { 7639 mockIsVisibleBackgroundUsersSupported(true); 7640 mockDisplayAssignedToUser(SECONDARY_DISPLAY_ID); 7641 allowTestPackageToToast(); 7642 7643 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ true, DEFAULT_DISPLAY); 7644 7645 verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY); 7646 7647 } 7648 7649 @Test testTextToastsCallStatusBar_visibleBgUsers_uiContext_secondaryDisplay()7650 public void testTextToastsCallStatusBar_visibleBgUsers_uiContext_secondaryDisplay() 7651 throws Exception { 7652 mockIsVisibleBackgroundUsersSupported(true); 7653 mockIsUserVisible(SECONDARY_DISPLAY_ID, true); 7654 mockDisplayAssignedToUser(INVALID_DISPLAY); // make sure it's not used 7655 allowTestPackageToToast(); 7656 7657 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ true, SECONDARY_DISPLAY_ID); 7658 7659 verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID); 7660 } 7661 7662 @Test testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_defaultDisplay()7663 public void testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_defaultDisplay() 7664 throws Exception { 7665 mockIsVisibleBackgroundUsersSupported(true); 7666 mockIsUserVisible(SECONDARY_DISPLAY_ID, true); 7667 mockDisplayAssignedToUser(SECONDARY_DISPLAY_ID); 7668 allowTestPackageToToast(); 7669 7670 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, DEFAULT_DISPLAY); 7671 7672 verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID); 7673 } 7674 7675 @Test testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_secondaryDisplay()7676 public void testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_secondaryDisplay() 7677 throws Exception { 7678 mockIsVisibleBackgroundUsersSupported(true); 7679 mockIsUserVisible(SECONDARY_DISPLAY_ID, true); 7680 mockDisplayAssignedToUser(INVALID_DISPLAY); // make sure it's not used 7681 allowTestPackageToToast(); 7682 7683 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, SECONDARY_DISPLAY_ID); 7684 7685 verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID); 7686 } 7687 7688 @Test testTextToastsCallStatusBar_userNotVisibleOnDisplay()7689 public void testTextToastsCallStatusBar_userNotVisibleOnDisplay() throws Exception { 7690 final String testPackage = "testPackageName"; 7691 assertEquals(0, mService.mToastQueue.size()); 7692 mService.isSystemUid = false; 7693 mService.isSystemAppId = false; 7694 setToastRateIsWithinQuota(true); 7695 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7696 mockIsUserVisible(DEFAULT_DISPLAY, false); 7697 7698 // package is not suspended 7699 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 7700 .thenReturn(false); 7701 7702 // enqueue toast -> no toasts enqueued 7703 enqueueTextToast(testPackage, "Text"); 7704 verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), 7705 anyInt()); 7706 assertEquals(0, mService.mToastQueue.size()); 7707 } 7708 7709 @Test testDisallowToastsFromSuspendedPackages()7710 public void testDisallowToastsFromSuspendedPackages() throws Exception { 7711 final String testPackage = "testPackageName"; 7712 assertEquals(0, mService.mToastQueue.size()); 7713 mService.isSystemUid = false; 7714 mService.isSystemAppId = false; 7715 setToastRateIsWithinQuota(true); 7716 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7717 7718 // package is suspended 7719 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7720 .thenReturn(true); 7721 7722 // notifications from this package are NOT blocked by the user 7723 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 7724 7725 // enqueue toast -> no toasts enqueued 7726 enqueueToast(testPackage, new TestableToastCallback()); 7727 verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), 7728 anyInt()); 7729 assertEquals(0, mService.mToastQueue.size()); 7730 } 7731 7732 @Test testDisallowToastsFromBlockedApps()7733 public void testDisallowToastsFromBlockedApps() throws Exception { 7734 final String testPackage = "testPackageName"; 7735 assertEquals(0, mService.mToastQueue.size()); 7736 mService.isSystemUid = false; 7737 mService.isSystemAppId = false; 7738 setToastRateIsWithinQuota(true); 7739 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7740 7741 // package is not suspended 7742 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7743 .thenReturn(false); 7744 7745 // notifications from this package are blocked by the user 7746 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 7747 7748 setAppInForegroundForToasts(mUid, false); 7749 7750 // enqueue toast -> no toasts enqueued 7751 enqueueToast(testPackage, new TestableToastCallback()); 7752 assertEquals(0, mService.mToastQueue.size()); 7753 } 7754 7755 @Test testAlwaysAllowSystemToasts()7756 public void testAlwaysAllowSystemToasts() throws Exception { 7757 final String testPackage = "testPackageName"; 7758 assertEquals(0, mService.mToastQueue.size()); 7759 mService.isSystemUid = true; 7760 setToastRateIsWithinQuota(true); 7761 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7762 7763 // package is suspended 7764 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7765 .thenReturn(true); 7766 7767 // notifications from this package ARE blocked by the user 7768 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 7769 7770 setAppInForegroundForToasts(mUid, false); 7771 7772 // enqueue toast -> system toast can still be enqueued 7773 enqueueToast(testPackage, new TestableToastCallback()); 7774 assertEquals(1, mService.mToastQueue.size()); 7775 } 7776 7777 @Test testLimitNumberOfQueuedToastsFromPackage()7778 public void testLimitNumberOfQueuedToastsFromPackage() throws Exception { 7779 final String testPackage = "testPackageName"; 7780 assertEquals(0, mService.mToastQueue.size()); 7781 mService.isSystemUid = false; 7782 mService.isSystemAppId = false; 7783 setToastRateIsWithinQuota(true); 7784 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7785 7786 // package is not suspended 7787 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7788 .thenReturn(false); 7789 7790 INotificationManager nmService = (INotificationManager) mService.mService; 7791 7792 // Trying to quickly enqueue more toast than allowed. 7793 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS + 1; i++) { 7794 enqueueTextToast(testPackage, "Text"); 7795 } 7796 // Only allowed number enqueued, rest ignored. 7797 assertEquals(NotificationManagerService.MAX_PACKAGE_TOASTS, mService.mToastQueue.size()); 7798 } 7799 7800 @Test testPrioritizeSystemToasts()7801 public void testPrioritizeSystemToasts() throws Exception { 7802 // Insert non-system toasts 7803 final String testPackage = "testPackageName"; 7804 assertEquals(0, mService.mToastQueue.size()); 7805 mService.isSystemUid = false; 7806 mService.isSystemAppId = false; 7807 setToastRateIsWithinQuota(true); 7808 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7809 7810 // package is not suspended 7811 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7812 .thenReturn(false); 7813 7814 INotificationManager nmService = (INotificationManager) mService.mService; 7815 7816 // Enqueue maximum number of toasts for test package 7817 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS; i++) { 7818 enqueueTextToast(testPackage, "Text"); 7819 } 7820 7821 // Enqueue system toast 7822 final String testPackageSystem = "testPackageNameSystem"; 7823 mService.isSystemUid = true; 7824 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackageSystem, false); 7825 when(mPackageManager.isPackageSuspendedForUser(testPackageSystem, mUserId)) 7826 .thenReturn(false); 7827 7828 enqueueToast(testPackageSystem, new TestableToastCallback()); 7829 7830 // System toast is inserted at the front of the queue, behind current showing toast 7831 assertEquals(testPackageSystem, mService.mToastQueue.get(1).pkg); 7832 } 7833 7834 @Test testPrioritizeSystemToasts_enqueueAfterExistingSystemToast()7835 public void testPrioritizeSystemToasts_enqueueAfterExistingSystemToast() throws Exception { 7836 // Insert system toasts 7837 final String testPackageSystem1 = "testPackageNameSystem1"; 7838 assertEquals(0, mService.mToastQueue.size()); 7839 mService.isSystemUid = true; 7840 setToastRateIsWithinQuota(true); 7841 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackageSystem1, false); 7842 7843 // package is not suspended 7844 when(mPackageManager.isPackageSuspendedForUser(testPackageSystem1, mUserId)) 7845 .thenReturn(false); 7846 7847 INotificationManager nmService = (INotificationManager) mService.mService; 7848 7849 // Enqueue maximum number of toasts for test package 7850 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS; i++) { 7851 enqueueTextToast(testPackageSystem1, "Text"); 7852 } 7853 7854 // Enqueue another system toast 7855 final String testPackageSystem2 = "testPackageNameSystem2"; 7856 mService.isSystemUid = true; 7857 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackageSystem2, false); 7858 when(mPackageManager.isPackageSuspendedForUser(testPackageSystem2, mUserId)) 7859 .thenReturn(false); 7860 7861 enqueueToast(testPackageSystem2, new TestableToastCallback()); 7862 7863 // System toast is inserted at the back of the queue, after the other system toasts 7864 assertEquals(testPackageSystem2, 7865 mService.mToastQueue.get(mService.mToastQueue.size() - 1).pkg); 7866 } 7867 setAppInForegroundForToasts(int uid, boolean inForeground)7868 private void setAppInForegroundForToasts(int uid, boolean inForeground) { 7869 int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE; 7870 when(mActivityManager.getUidImportance(mUid)).thenReturn(importance); 7871 when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground); 7872 } 7873 setToastRateIsWithinQuota(boolean isWithinQuota)7874 private void setToastRateIsWithinQuota(boolean isWithinQuota) { 7875 when(mToastRateLimiter.isWithinQuota( 7876 anyInt(), 7877 anyString(), 7878 eq(NotificationManagerService.TOAST_QUOTA_TAG))) 7879 .thenReturn(isWithinQuota); 7880 } 7881 setIfPackageHasPermissionToAvoidToastRateLimiting( String pkg, boolean hasPermission)7882 private void setIfPackageHasPermissionToAvoidToastRateLimiting( 7883 String pkg, boolean hasPermission) throws Exception { 7884 when(mPackageManager.checkPermission(android.Manifest.permission.UNLIMITED_TOASTS, 7885 pkg, mUserId)) 7886 .thenReturn(hasPermission ? PERMISSION_GRANTED : PERMISSION_DENIED); 7887 } 7888 7889 @Test testOnPanelRevealedAndHidden()7890 public void testOnPanelRevealedAndHidden() { 7891 int items = 5; 7892 mService.mNotificationDelegate.onPanelRevealed(false, items); 7893 verify(mAssistants, times(1)).onPanelRevealed(eq(items)); 7894 7895 mService.mNotificationDelegate.onPanelHidden(); 7896 verify(mAssistants, times(1)).onPanelHidden(); 7897 7898 assertEquals(2, mNotificationRecordLogger.numCalls()); 7899 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_OPEN, 7900 mNotificationRecordLogger.event(0)); 7901 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_CLOSE, 7902 mNotificationRecordLogger.event(1)); 7903 } 7904 7905 @Test testOnNotificationSmartReplySent()7906 public void testOnNotificationSmartReplySent() { 7907 final int replyIndex = 2; 7908 final String reply = "Hello"; 7909 final boolean modifiedBeforeSending = true; 7910 final boolean generatedByAssistant = true; 7911 7912 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7913 r.setSuggestionsGeneratedByAssistant(generatedByAssistant); 7914 mService.addNotification(r); 7915 7916 mService.mNotificationDelegate.onNotificationSmartReplySent( 7917 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN, 7918 modifiedBeforeSending); 7919 verify(mAssistants).notifyAssistantSuggestedReplySent( 7920 eq(r.getSbn()), eq(FLAG_FILTER_TYPE_ALERTING), eq(reply), eq(generatedByAssistant)); 7921 assertEquals(1, mNotificationRecordLogger.numCalls()); 7922 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED, 7923 mNotificationRecordLogger.event(0)); 7924 } 7925 7926 @Test testOnNotificationActionClick()7927 public void testOnNotificationActionClick() { 7928 final int actionIndex = 2; 7929 final Notification.Action action = 7930 new Notification.Action.Builder(null, "text", PendingIntent.getActivity( 7931 mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build(); 7932 final boolean generatedByAssistant = false; 7933 7934 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7935 mService.addNotification(r); 7936 7937 NotificationVisibility notificationVisibility = 7938 NotificationVisibility.obtain(r.getKey(), 1, 2, true); 7939 mService.mNotificationDelegate.onNotificationActionClick( 7940 10, 10, r.getKey(), actionIndex, action, notificationVisibility, 7941 generatedByAssistant); 7942 verify(mAssistants).notifyAssistantActionClicked( 7943 eq(r), eq(action), eq(generatedByAssistant)); 7944 7945 assertEquals(1, mNotificationRecordLogger.numCalls()); 7946 assertEquals( 7947 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ACTION_CLICKED_2, 7948 mNotificationRecordLogger.event(0)); 7949 } 7950 7951 @Test testOnAssistantNotificationActionClick()7952 public void testOnAssistantNotificationActionClick() { 7953 final int actionIndex = 1; 7954 final Notification.Action action = 7955 new Notification.Action.Builder(null, "text", PendingIntent.getActivity( 7956 mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build(); 7957 final boolean generatedByAssistant = true; 7958 7959 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7960 mService.addNotification(r); 7961 7962 NotificationVisibility notificationVisibility = 7963 NotificationVisibility.obtain(r.getKey(), 1, 2, true); 7964 mService.mNotificationDelegate.onNotificationActionClick( 7965 10, 10, r.getKey(), actionIndex, action, notificationVisibility, 7966 generatedByAssistant); 7967 verify(mAssistants).notifyAssistantActionClicked( 7968 eq(r), eq(action), eq(generatedByAssistant)); 7969 7970 assertEquals(1, mNotificationRecordLogger.numCalls()); 7971 assertEquals( 7972 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ASSIST_ACTION_CLICKED_1, 7973 mNotificationRecordLogger.event(0)); 7974 } 7975 7976 @Test testLogSmartSuggestionsVisible_triggerOnExpandAndVisible()7977 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() { 7978 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7979 mService.addNotification(r); 7980 7981 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 7982 NOTIFICATION_LOCATION_UNKNOWN); 7983 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] { 7984 NotificationVisibility.obtain(r.getKey(), 0, 0, true) 7985 }; 7986 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility, 7987 new NotificationVisibility[0]); 7988 7989 assertEquals(1, mService.countLogSmartSuggestionsVisible); 7990 } 7991 7992 @Test testLogSmartSuggestionsVisible_noTriggerOnExpand()7993 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() { 7994 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7995 mService.addNotification(r); 7996 7997 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 7998 NOTIFICATION_LOCATION_UNKNOWN); 7999 8000 assertEquals(0, mService.countLogSmartSuggestionsVisible); 8001 } 8002 8003 @Test testLogSmartSuggestionsVisible_noTriggerOnVisible()8004 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() { 8005 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 8006 mService.addNotification(r); 8007 8008 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{ 8009 NotificationVisibility.obtain(r.getKey(), 0, 0, true) 8010 }; 8011 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility, 8012 new NotificationVisibility[0]); 8013 8014 assertEquals(0, mService.countLogSmartSuggestionsVisible); 8015 } 8016 8017 @Test testReportSeen_delegated()8018 public void testReportSeen_delegated() { 8019 Notification.Builder nb = 8020 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 8021 .setContentTitle("foo") 8022 .setSmallIcon(android.R.drawable.sym_def_app_icon); 8023 8024 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0, 8025 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 8026 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 8027 8028 mService.reportSeen(r); 8029 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt()); 8030 8031 } 8032 8033 @Test testReportSeen_notDelegated()8034 public void testReportSeen_notDelegated() { 8035 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 8036 8037 mService.reportSeen(r); 8038 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt()); 8039 } 8040 8041 @Test testNotificationStats_notificationError()8042 public void testNotificationStats_notificationError() { 8043 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 8044 mService.addNotification(r); 8045 8046 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.getSbn().getId(), 8047 r.getSbn().getTag(), mUid, 0, 8048 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(), 8049 UserHandle.getUserHandleForUid(mUid), null, 0); 8050 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 8051 mService.addEnqueuedNotification(update); 8052 assertNull(update.getSbn().getNotification().getSmallIcon()); 8053 8054 NotificationManagerService.PostNotificationRunnable runnable = 8055 mService.new PostNotificationRunnable(update.getKey(), r.getSbn().getPackageName(), 8056 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 8057 runnable.run(); 8058 waitForIdle(); 8059 8060 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 8061 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture()); 8062 assertNotNull(captor.getValue()); 8063 } 8064 8065 @Test testCanNotifyAsUser_crossUser()8066 public void testCanNotifyAsUser_crossUser() throws Exception { 8067 // same user no problem 8068 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId()); 8069 8070 // cross user, no permission, problem 8071 try { 8072 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); 8073 fail("Should not be callable cross user without cross user permission"); 8074 } catch (SecurityException e) { 8075 // good 8076 } 8077 8078 // cross user, with permission, no problem 8079 enableInteractAcrossUsers(); 8080 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); 8081 } 8082 8083 @Test testGetNotificationChannels_crossUser()8084 public void testGetNotificationChannels_crossUser() throws Exception { 8085 // same user no problem 8086 mBinderService.getNotificationChannels("src", "target", mContext.getUserId()); 8087 8088 // cross user, no permission, problem 8089 try { 8090 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); 8091 fail("Should not be callable cross user without cross user permission"); 8092 } catch (SecurityException e) { 8093 // good 8094 } 8095 8096 // cross user, with permission, no problem 8097 enableInteractAcrossUsers(); 8098 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); 8099 } 8100 8101 @Test setDefaultAssistantForUser_fromConfigXml()8102 public void setDefaultAssistantForUser_fromConfigXml() { 8103 clearDeviceConfig(); 8104 ComponentName xmlConfig = new ComponentName("config", "xml"); 8105 ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig)); 8106 when(mResources 8107 .getString( 8108 com.android.internal.R.string.config_defaultAssistantAccessComponent)) 8109 .thenReturn(xmlConfig.flattenToString()); 8110 when(mContext.getResources()).thenReturn(mResources); 8111 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt())) 8112 .thenReturn(components); 8113 when(mAssistants.getDefaultComponents()) 8114 .thenReturn(components); 8115 mService.setNotificationAssistantAccessGrantedCallback( 8116 mNotificationAssistantAccessGrantedCallback); 8117 8118 8119 mService.setDefaultAssistantForUser(0); 8120 8121 verify(mNotificationAssistantAccessGrantedCallback) 8122 .onGranted(eq(xmlConfig), eq(0), eq(true), eq(false)); 8123 } 8124 8125 @Test setDefaultAssistantForUser_fromDeviceConfig()8126 public void setDefaultAssistantForUser_fromDeviceConfig() { 8127 ComponentName xmlConfig = new ComponentName("xml", "config"); 8128 ComponentName deviceConfig = new ComponentName("device", "config"); 8129 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString()); 8130 when(mResources 8131 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent)) 8132 .thenReturn(xmlConfig.flattenToString()); 8133 when(mContext.getResources()).thenReturn(mResources); 8134 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt())) 8135 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig))); 8136 when(mAssistants.getDefaultComponents()) 8137 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig))); 8138 mService.setNotificationAssistantAccessGrantedCallback( 8139 mNotificationAssistantAccessGrantedCallback); 8140 8141 mService.setDefaultAssistantForUser(0); 8142 8143 verify(mNotificationAssistantAccessGrantedCallback) 8144 .onGranted(eq(deviceConfig), eq(0), eq(true), eq(false)); 8145 } 8146 8147 @Test setDefaultAssistantForUser_deviceConfigInvalid()8148 public void setDefaultAssistantForUser_deviceConfigInvalid() { 8149 ComponentName xmlConfig = new ComponentName("xml", "config"); 8150 ComponentName deviceConfig = new ComponentName("device", "config"); 8151 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString()); 8152 when(mResources 8153 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent)) 8154 .thenReturn(xmlConfig.flattenToString()); 8155 when(mContext.getResources()).thenReturn(mResources); 8156 // Only xmlConfig is valid, deviceConfig is not. 8157 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0))) 8158 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig))); 8159 when(mAssistants.getDefaultComponents()) 8160 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig))); 8161 mService.setNotificationAssistantAccessGrantedCallback( 8162 mNotificationAssistantAccessGrantedCallback); 8163 8164 mService.setDefaultAssistantForUser(0); 8165 8166 verify(mNotificationAssistantAccessGrantedCallback) 8167 .onGranted(eq(xmlConfig), eq(0), eq(true), eq(false)); 8168 } 8169 8170 @Test clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne()8171 public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException { 8172 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners = 8173 generateResetComponentValues(); 8174 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners); 8175 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>(); 8176 ComponentName deviceConfig1 = new ComponentName("device", "config1"); 8177 ComponentName deviceConfig2 = new ComponentName("device", "config2"); 8178 changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2))); 8179 changes.put(false, new ArrayList()); 8180 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes); 8181 mService.getBinderService().clearData("device", 0, false); 8182 verify(mAssistants, times(1)) 8183 .setPackageOrComponentEnabled( 8184 eq("device/config2"), 8185 eq(0), eq(true), eq(false)); 8186 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 8187 eq("device"), eq(0), eq(false), eq(true)); 8188 } 8189 8190 @Test testNASSettingUpgrade_userSetNull()8191 public void testNASSettingUpgrade_userSetNull() throws RemoteException { 8192 ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component1"); 8193 TestableNotificationManagerService service = spy(mService); 8194 int userId = 11; 8195 setUsers(new int[]{userId}); 8196 when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId}); 8197 setNASMigrationDone(false, userId); 8198 when(mAssistants.getDefaultFromConfig()) 8199 .thenReturn(newDefaultComponent); 8200 when(mAssistants.getAllowedComponents(anyInt())) 8201 .thenReturn(new ArrayList<>()); 8202 when(mAssistants.hasUserSet(userId)).thenReturn(true); 8203 8204 service.migrateDefaultNAS(); 8205 assertTrue(service.isNASMigrationDone(userId)); 8206 verify(mAssistants, times(1)).clearDefaults(); 8207 } 8208 8209 @Test testNASSettingUpgrade_userSet()8210 public void testNASSettingUpgrade_userSet() throws RemoteException { 8211 ComponentName defaultComponent = ComponentName.unflattenFromString("package/Component1"); 8212 TestableNotificationManagerService service = spy(mService); 8213 int userId = 11; 8214 setUsers(new int[]{userId}); 8215 when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId}); 8216 setNASMigrationDone(false, userId); 8217 when(mAssistants.getDefaultFromConfig()) 8218 .thenReturn(defaultComponent); 8219 when(mAssistants.getAllowedComponents(anyInt())) 8220 .thenReturn(new ArrayList(Arrays.asList(defaultComponent))); 8221 when(mAssistants.hasUserSet(userId)).thenReturn(true); 8222 8223 service.migrateDefaultNAS(); 8224 verify(mAssistants, times(1)).setUserSet(userId, false); 8225 //resetDefaultAssistantsIfNecessary should invoke from readPolicyXml() and migration 8226 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary(); 8227 } 8228 8229 @Test testNASSettingUpgrade_multiUser()8230 public void testNASSettingUpgrade_multiUser() throws RemoteException { 8231 ComponentName oldDefaultComponent = ComponentName.unflattenFromString("package/Component1"); 8232 ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component2"); 8233 TestableNotificationManagerService service = spy(mService); 8234 int userId1 = 11; 8235 int userId2 = 12; 8236 setUsers(new int[]{userId1, userId2}); 8237 when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1}); 8238 when(mUm.getProfileIds(userId2, false)).thenReturn(new int[]{userId2}); 8239 8240 setNASMigrationDone(false, userId1); 8241 setNASMigrationDone(false, userId2); 8242 when(mAssistants.getDefaultComponents()) 8243 .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent))); 8244 when(mAssistants.getDefaultFromConfig()) 8245 .thenReturn(newDefaultComponent); 8246 //User1: set different NAS 8247 when(mAssistants.getAllowedComponents(userId1)) 8248 .thenReturn(Arrays.asList(oldDefaultComponent)); 8249 //User2: set to none 8250 when(mAssistants.getAllowedComponents(userId2)) 8251 .thenReturn(new ArrayList<>()); 8252 8253 when(mAssistants.hasUserSet(userId1)).thenReturn(true); 8254 when(mAssistants.hasUserSet(userId2)).thenReturn(true); 8255 8256 service.migrateDefaultNAS(); 8257 // user1's setting get reset 8258 verify(mAssistants, times(1)).setUserSet(userId1, false); 8259 verify(mAssistants, times(0)).setUserSet(eq(userId2), anyBoolean()); 8260 assertTrue(service.isNASMigrationDone(userId2)); 8261 8262 } 8263 8264 @Test testNASSettingUpgrade_multiProfile()8265 public void testNASSettingUpgrade_multiProfile() throws RemoteException { 8266 ComponentName oldDefaultComponent = ComponentName.unflattenFromString("package/Component1"); 8267 ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component2"); 8268 TestableNotificationManagerService service = spy(mService); 8269 int userId1 = 11; 8270 int userId2 = 12; //work profile 8271 setUsers(new int[]{userId1, userId2}); 8272 when(mUm.isManagedProfile(userId2)).thenReturn(true); 8273 when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1, userId2}); 8274 8275 setNASMigrationDone(false, userId1); 8276 setNASMigrationDone(false, userId2); 8277 when(mAssistants.getDefaultComponents()) 8278 .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent))); 8279 when(mAssistants.getDefaultFromConfig()) 8280 .thenReturn(newDefaultComponent); 8281 //Both profiles: set different NAS 8282 when(mAssistants.getAllowedComponents(userId1)) 8283 .thenReturn(Arrays.asList(oldDefaultComponent)); 8284 when(mAssistants.getAllowedComponents(userId2)) 8285 .thenReturn(Arrays.asList(oldDefaultComponent)); 8286 8287 when(mAssistants.hasUserSet(userId1)).thenReturn(true); 8288 when(mAssistants.hasUserSet(userId2)).thenReturn(true); 8289 8290 service.migrateDefaultNAS(); 8291 assertFalse(service.isNASMigrationDone(userId1)); 8292 assertFalse(service.isNASMigrationDone(userId2)); 8293 } 8294 8295 8296 8297 @Test testNASSettingUpgrade_clearDataAfterMigrationIsDone()8298 public void testNASSettingUpgrade_clearDataAfterMigrationIsDone() throws RemoteException { 8299 ComponentName defaultComponent = ComponentName.unflattenFromString("package/Component"); 8300 TestableNotificationManagerService service = spy(mService); 8301 int userId = 12; 8302 setUsers(new int[]{userId}); 8303 when(mAssistants.getDefaultComponents()) 8304 .thenReturn(new ArraySet<>(Arrays.asList(defaultComponent))); 8305 when(mAssistants.hasUserSet(userId)).thenReturn(true); 8306 setNASMigrationDone(true, userId); 8307 8308 //Test User clear data 8309 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners = 8310 generateResetComponentValues(); 8311 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners); 8312 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>(); 8313 changes.put(true, new ArrayList(Arrays.asList(defaultComponent))); 8314 changes.put(false, new ArrayList()); 8315 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes); 8316 8317 //Clear data 8318 service.getBinderService().clearData("package", userId, false); 8319 //Test migrate flow again 8320 service.migrateDefaultNAS(); 8321 8322 //Migration should not happen again 8323 verify(mAssistants, times(0)).setUserSet(userId, false); 8324 verify(mAssistants, times(0)).clearDefaults(); 8325 //resetDefaultAssistantsIfNecessary should only invoke once from readPolicyXml() 8326 verify(mAssistants, times(1)).resetDefaultAssistantsIfNecessary(); 8327 8328 } 8329 setNASMigrationDone(boolean done, int userId)8330 private void setNASMigrationDone(boolean done, int userId) { 8331 Settings.Secure.putIntForUser(mContext.getContentResolver(), 8332 Settings.Secure.NAS_SETTINGS_UPDATED, done ? 1 : 0, userId); 8333 } 8334 setUsers(int[] userIds)8335 private void setUsers(int[] userIds) { 8336 List<UserInfo> users = new ArrayList<>(); 8337 for (int id: userIds) { 8338 users.add(new UserInfo(id, String.valueOf(id), 0)); 8339 } 8340 for (UserInfo user : users) { 8341 when(mUm.getUserInfo(eq(user.id))).thenReturn(user); 8342 } 8343 when(mUm.getUsers()).thenReturn(users); 8344 } 8345 8346 @Test clearDefaultListenersPackageShouldEnableIt()8347 public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException { 8348 ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants = 8349 generateResetComponentValues(); 8350 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants); 8351 ComponentName deviceConfig = new ComponentName("device", "config"); 8352 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>(); 8353 changes.put(true, new ArrayList(Arrays.asList(deviceConfig))); 8354 changes.put(false, new ArrayList()); 8355 when(mListeners.resetComponents(anyString(), anyInt())) 8356 .thenReturn(changes); 8357 mService.getBinderService().clearData("device", 0, false); 8358 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 8359 eq("device"), eq(0), eq(false), eq(true)); 8360 } 8361 8362 @Test clearDefaultDnDPackageShouldEnableIt()8363 public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException { 8364 ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues(); 8365 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed); 8366 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed); 8367 mService.getBinderService().clearData("pkgName", 0, false); 8368 verify(mConditionProviders, times(1)).resetPackage( 8369 eq("pkgName"), eq(0)); 8370 } 8371 8372 @Test testFlagBubble()8373 public void testFlagBubble() throws RemoteException { 8374 setUpPrefsForBubbles(PKG, mUid, 8375 true /* global */, 8376 BUBBLE_PREFERENCE_ALL /* app */, 8377 true /* channel */); 8378 8379 NotificationRecord nr = 8380 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble"); 8381 8382 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8383 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8384 waitForIdle(); 8385 8386 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8387 assertEquals(1, notifs.length); 8388 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0); 8389 assertTrue(mService.getNotificationRecord( 8390 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8391 } 8392 8393 @Test testFlagBubble_noFlag_appNotAllowed()8394 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException { 8395 setUpPrefsForBubbles(PKG, mUid, 8396 true /* global */, 8397 BUBBLE_PREFERENCE_NONE /* app */, 8398 true /* channel */); 8399 8400 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8401 "testFlagBubble_noFlag_appNotAllowed"); 8402 8403 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8404 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8405 waitForIdle(); 8406 8407 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8408 assertEquals(1, notifs.length); 8409 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0); 8410 assertFalse(mService.getNotificationRecord( 8411 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8412 } 8413 8414 @Test testFlagBubbleNotifs_noFlag_whenAppForeground()8415 public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException { 8416 setUpPrefsForBubbles(PKG, mUid, 8417 true /* global */, 8418 BUBBLE_PREFERENCE_ALL /* app */, 8419 true /* channel */); 8420 8421 // Notif with bubble metadata but not our other misc requirements 8422 Notification.Builder nb = new Notification.Builder(mContext, 8423 mTestNotificationChannel.getId()) 8424 .setContentTitle("foo") 8425 .setSmallIcon(android.R.drawable.sym_def_app_icon) 8426 .setBubbleMetadata(getBubbleMetadata()); 8427 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, 8428 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 8429 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 8430 8431 // Say we're foreground 8432 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn( 8433 IMPORTANCE_FOREGROUND); 8434 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8435 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8436 waitForIdle(); 8437 8438 // if notif isn't configured properly it doesn't get to bubble just because app is 8439 // foreground. 8440 assertFalse(mService.getNotificationRecord( 8441 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8442 } 8443 8444 @Test testFlagBubbleNotifs_flag_messaging()8445 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException { 8446 setUpPrefsForBubbles(PKG, mUid, 8447 true /* global */, 8448 BUBBLE_PREFERENCE_ALL /* app */, 8449 true /* channel */); 8450 8451 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8452 "testFlagBubbleNotifs_flag_messaging"); 8453 8454 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8455 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8456 waitForIdle(); 8457 8458 // yes allowed, yes messaging, yes bubble 8459 assertTrue(mService.getNotificationRecord( 8460 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8461 } 8462 8463 @Test testFlagBubbleNotifs_noFlag_noShortcut()8464 public void testFlagBubbleNotifs_noFlag_noShortcut() throws RemoteException { 8465 setUpPrefsForBubbles(PKG, mUid, 8466 true /* global */, 8467 BUBBLE_PREFERENCE_ALL /* app */, 8468 true /* channel */); 8469 8470 Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false); 8471 nb.setShortcutId(null); 8472 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 8473 null, mUid, 0, 8474 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 8475 8476 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 8477 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 8478 waitForIdle(); 8479 8480 // no shortcut no bubble 8481 assertFalse(mService.getNotificationRecord( 8482 sbn.getKey()).getNotification().isBubbleNotification()); 8483 } 8484 8485 @Test testFlagBubbleNotifs_noFlag_messaging_appNotAllowed()8486 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException { 8487 setUpPrefsForBubbles(PKG, mUid, 8488 true /* global */, 8489 BUBBLE_PREFERENCE_NONE /* app */, 8490 true /* channel */); 8491 8492 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8493 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed"); 8494 8495 // Post the notification 8496 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8497 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8498 waitForIdle(); 8499 8500 // not allowed, no bubble 8501 assertFalse(mService.getNotificationRecord( 8502 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8503 } 8504 8505 @Test testFlagBubbleNotifs_noFlag_notBubble()8506 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException { 8507 setUpPrefsForBubbles(PKG, mUid, 8508 true /* global */, 8509 BUBBLE_PREFERENCE_ALL /* app */, 8510 true /* channel */); 8511 8512 // Messaging notif WITHOUT bubble metadata 8513 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */, 8514 null /* groupKey */, false /* isSummary */); 8515 8516 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 8517 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0, 8518 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 8519 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 8520 8521 // Post the notification 8522 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8523 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8524 waitForIdle(); 8525 8526 // no bubble metadata, no bubble 8527 assertFalse(mService.getNotificationRecord( 8528 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8529 } 8530 8531 @Test testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed()8532 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException { 8533 setUpPrefsForBubbles(PKG, mUid, 8534 true /* global */, 8535 BUBBLE_PREFERENCE_ALL /* app */, 8536 false /* channel */); 8537 8538 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8539 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed"); 8540 nr.getChannel().lockFields(USER_LOCKED_ALLOW_BUBBLE); 8541 8542 // Post the notification 8543 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8544 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8545 waitForIdle(); 8546 8547 // channel not allowed, no bubble 8548 assertFalse(mService.getNotificationRecord( 8549 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8550 } 8551 8552 @Test testCancelNotificationsFromApp_cancelsBubbles()8553 public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception { 8554 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); 8555 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE; 8556 8557 // Post the notification 8558 mBinderService.enqueueNotificationWithTag(PKG, PKG, 8559 "testAppCancelNotifications_cancelsBubbles", 8560 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(), 8561 nrBubble.getSbn().getUserId()); 8562 waitForIdle(); 8563 8564 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8565 assertEquals(1, notifs.length); 8566 assertEquals(1, mService.getNotificationRecordCount()); 8567 8568 mBinderService.cancelNotificationWithTag(PKG, PKG, 8569 "testAppCancelNotifications_cancelsBubbles", nrBubble.getSbn().getId(), 8570 nrBubble.getSbn().getUserId()); 8571 waitForIdle(); 8572 8573 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG); 8574 assertEquals(0, notifs2.length); 8575 assertEquals(0, mService.getNotificationRecordCount()); 8576 } 8577 8578 @Test testCancelAllNotificationsFromApp_cancelsBubble()8579 public void testCancelAllNotificationsFromApp_cancelsBubble() throws Exception { 8580 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 8581 nr.getSbn().getNotification().flags |= FLAG_BUBBLE; 8582 mService.addNotification(nr); 8583 8584 mBinderService.cancelAllNotifications(PKG, nr.getSbn().getUserId()); 8585 waitForIdle(); 8586 8587 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8588 assertEquals(0, notifs.length); 8589 assertEquals(0, mService.getNotificationRecordCount()); 8590 } 8591 8592 @Test testCancelAllNotificationsFromListener_ignoresBubbles()8593 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception { 8594 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel); 8595 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); 8596 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE; 8597 8598 mService.addNotification(nrNormal); 8599 mService.addNotification(nrBubble); 8600 8601 mService.getBinderService().cancelNotificationsFromListener(null, null); 8602 waitForIdle(); 8603 8604 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8605 assertEquals(1, notifs.length); 8606 assertEquals(1, mService.getNotificationRecordCount()); 8607 } 8608 8609 @Test testCancelNotificationsFromListener_cancelsNonBubble()8610 public void testCancelNotificationsFromListener_cancelsNonBubble() throws Exception { 8611 // Add non-bubble notif 8612 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 8613 mService.addNotification(nr); 8614 8615 // Cancel via listener 8616 String[] keys = {nr.getSbn().getKey()}; 8617 mService.getBinderService().cancelNotificationsFromListener(null, keys); 8618 waitForIdle(); 8619 8620 // Notif not active anymore 8621 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8622 assertEquals(0, notifs.length); 8623 assertEquals(0, mService.getNotificationRecordCount()); 8624 // Cancel event is logged 8625 assertEquals(1, mNotificationRecordLogger.numCalls()); 8626 assertEquals(NotificationRecordLogger.NotificationCancelledEvent 8627 .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0)); 8628 } 8629 8630 @Test testCancelNotificationsFromListener_suppressesBubble()8631 public void testCancelNotificationsFromListener_suppressesBubble() throws Exception { 8632 // Add bubble notif 8633 setUpPrefsForBubbles(PKG, mUid, 8634 true /* global */, 8635 BUBBLE_PREFERENCE_ALL /* app */, 8636 true /* channel */); 8637 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag"); 8638 8639 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8640 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8641 waitForIdle(); 8642 8643 // Cancel via listener 8644 String[] keys = {nr.getSbn().getKey()}; 8645 mService.getBinderService().cancelNotificationsFromListener(null, keys); 8646 waitForIdle(); 8647 8648 // Bubble notif active and suppressed 8649 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8650 assertEquals(1, notifs.length); 8651 assertEquals(1, mService.getNotificationRecordCount()); 8652 assertTrue(notifs[0].getNotification().getBubbleMetadata().isNotificationSuppressed()); 8653 } 8654 8655 @Test testCancelAllNotificationsFromStatusBar_ignoresBubble()8656 public void testCancelAllNotificationsFromStatusBar_ignoresBubble() throws Exception { 8657 // GIVEN a notification bubble 8658 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 8659 nr.getSbn().getNotification().flags |= FLAG_BUBBLE; 8660 mService.addNotification(nr); 8661 8662 // WHEN the status bar clears all notifications 8663 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 8664 nr.getSbn().getUserId()); 8665 waitForIdle(); 8666 8667 // THEN the bubble notification does not get removed 8668 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8669 assertEquals(1, notifs.length); 8670 assertEquals(1, mService.getNotificationRecordCount()); 8671 } 8672 8673 8674 @Test testGetAllowedAssistantAdjustments()8675 public void testGetAllowedAssistantAdjustments() throws Exception { 8676 List<String> adjustments = mBinderService.getAllowedAssistantAdjustments(null); 8677 assertNotNull(adjustments); 8678 } 8679 8680 @Test testAdjustRestrictedKey()8681 public void testAdjustRestrictedKey() throws Exception { 8682 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 8683 mService.addNotification(r); 8684 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 8685 8686 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true); 8687 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false); 8688 8689 Bundle signals = new Bundle(); 8690 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW); 8691 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE); 8692 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, 8693 "", r.getUser().getIdentifier()); 8694 8695 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 8696 r.applyAdjustments(); 8697 8698 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance()); 8699 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment()); 8700 } 8701 8702 @Test testAutomaticZenRuleValidation_policyFilterAgreement()8703 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception { 8704 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) 8705 .thenReturn(true); 8706 mService.setZenHelper(mock(ZenModeHelper.class)); 8707 ComponentName owner = new ComponentName(mContext, this.getClass()); 8708 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build(); 8709 boolean isEnabled = true; 8710 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8711 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled); 8712 8713 try { 8714 mBinderService.addAutomaticZenRule(rule, mContext.getPackageName()); 8715 fail("Zen policy only applies to priority only mode"); 8716 } catch (IllegalArgumentException e) { 8717 // yay 8718 } 8719 8720 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8721 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled); 8722 mBinderService.addAutomaticZenRule(rule, mContext.getPackageName()); 8723 8724 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8725 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled); 8726 mBinderService.addAutomaticZenRule(rule, mContext.getPackageName()); 8727 } 8728 8729 @Test testAddAutomaticZenRule_systemCallTakesPackageFromOwner()8730 public void testAddAutomaticZenRule_systemCallTakesPackageFromOwner() throws Exception { 8731 mService.isSystemUid = true; 8732 ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class); 8733 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) 8734 .thenReturn(true); 8735 mService.setZenHelper(mockZenModeHelper); 8736 ComponentName owner = new ComponentName("android", "ProviderName"); 8737 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build(); 8738 boolean isEnabled = true; 8739 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8740 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled); 8741 mBinderService.addAutomaticZenRule(rule, "com.android.settings"); 8742 8743 // verify that zen mode helper gets passed in a package name of "android" 8744 verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString(), 8745 anyInt(), eq(true)); // system call counts as "is system or system ui" 8746 } 8747 8748 @Test testAddAutomaticZenRule_systemAppIdCallTakesPackageFromOwner()8749 public void testAddAutomaticZenRule_systemAppIdCallTakesPackageFromOwner() throws Exception { 8750 // The multi-user case: where the calling uid doesn't match the system uid, but the calling 8751 // *appid* is the system. 8752 mService.isSystemUid = false; 8753 mService.isSystemAppId = true; 8754 ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class); 8755 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) 8756 .thenReturn(true); 8757 mService.setZenHelper(mockZenModeHelper); 8758 ComponentName owner = new ComponentName("android", "ProviderName"); 8759 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build(); 8760 boolean isEnabled = true; 8761 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8762 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled); 8763 mBinderService.addAutomaticZenRule(rule, "com.android.settings"); 8764 8765 // verify that zen mode helper gets passed in a package name of "android" 8766 verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString(), 8767 anyInt(), eq(true)); // system call counts as "system or system ui" 8768 } 8769 8770 @Test testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg()8771 public void testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg() throws Exception { 8772 mService.isSystemUid = false; 8773 mService.isSystemAppId = false; 8774 ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class); 8775 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) 8776 .thenReturn(true); 8777 mService.setZenHelper(mockZenModeHelper); 8778 ComponentName owner = new ComponentName("android", "ProviderName"); 8779 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build(); 8780 boolean isEnabled = true; 8781 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8782 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled); 8783 mBinderService.addAutomaticZenRule(rule, "another.package"); 8784 8785 // verify that zen mode helper gets passed in the package name from the arg, not the owner 8786 verify(mockZenModeHelper).addAutomaticZenRule( 8787 eq("another.package"), eq(rule), anyString(), anyInt(), 8788 eq(false)); // doesn't count as a system/systemui call 8789 } 8790 8791 @Test onZenModeChanged_sendsBroadcasts()8792 public void onZenModeChanged_sendsBroadcasts() throws Exception { 8793 when(mAmi.getCurrentUserId()).thenReturn(100); 8794 when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102}); 8795 when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() { 8796 @Override 8797 public List<String> answer(InvocationOnMock invocation) { 8798 int userId = invocation.getArgument(0); 8799 switch (userId) { 8800 case 100: 8801 return Lists.newArrayList("a", "b", "c"); 8802 case 101: 8803 return Lists.newArrayList(); 8804 case 102: 8805 return Lists.newArrayList("b"); 8806 default: 8807 throw new IllegalArgumentException( 8808 "Why would you ask for packages of userId " + userId + "?"); 8809 } 8810 } 8811 }); 8812 8813 mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null, 8814 "testing!"); 8815 waitForIdle(); 8816 8817 InOrder inOrder = inOrder(mContext); 8818 // Verify broadcasts for registered receivers 8819 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent( 8820 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags( 8821 Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(100)), eq(null)); 8822 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent( 8823 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags( 8824 Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(101)), eq(null)); 8825 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent( 8826 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags( 8827 Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(102)), eq(null)); 8828 8829 // Verify broadcast for packages that manage DND. 8830 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent( 8831 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("a").setFlags( 8832 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100))); 8833 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent( 8834 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags( 8835 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100))); 8836 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent( 8837 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("c").setFlags( 8838 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100))); 8839 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent( 8840 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags( 8841 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102))); 8842 } 8843 eqIntent(Intent wanted)8844 private static Intent eqIntent(Intent wanted) { 8845 return ArgumentMatchers.argThat( 8846 new ArgumentMatcher<Intent>() { 8847 @Override 8848 public boolean matches(Intent argument) { 8849 return wanted.filterEquals(argument) 8850 && wanted.getFlags() == argument.getFlags(); 8851 } 8852 8853 @Override 8854 public String toString() { 8855 return wanted.toString(); 8856 } 8857 }); 8858 } 8859 8860 @Test 8861 public void testAreNotificationsEnabledForPackage() throws Exception { 8862 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), 8863 mUid); 8864 8865 verify(mPermissionHelper).hasPermission(mUid); 8866 } 8867 8868 @Test 8869 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception { 8870 try { 8871 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), 8872 mUid + UserHandle.PER_USER_RANGE); 8873 fail("Cannot call cross user without permission"); 8874 } catch (SecurityException e) { 8875 // pass 8876 } 8877 verify(mPermissionHelper, never()).hasPermission(anyInt()); 8878 8879 // cross user, with permission, no problem 8880 enableInteractAcrossUsers(); 8881 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), 8882 mUid + UserHandle.PER_USER_RANGE); 8883 8884 verify(mPermissionHelper).hasPermission(mUid + UserHandle.PER_USER_RANGE); 8885 } 8886 8887 @Test 8888 public void testAreNotificationsEnabledForPackage_viaInternalService() { 8889 mInternalService.areNotificationsEnabledForPackage(mContext.getPackageName(), mUid); 8890 verify(mPermissionHelper).hasPermission(mUid); 8891 } 8892 8893 @Test 8894 public void testGetPackageImportance() throws Exception { 8895 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 8896 assertThat(mBinderService.getPackageImportance(mContext.getPackageName())) 8897 .isEqualTo(IMPORTANCE_DEFAULT); 8898 8899 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 8900 assertThat(mBinderService.getPackageImportance(mContext.getPackageName())) 8901 .isEqualTo(IMPORTANCE_NONE); 8902 } 8903 8904 @Test 8905 public void testAreBubblesAllowedForPackage_crossUser() throws Exception { 8906 try { 8907 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(), 8908 mUid + UserHandle.PER_USER_RANGE); 8909 fail("Cannot call cross user without permission"); 8910 } catch (SecurityException e) { 8911 // pass 8912 } 8913 8914 // cross user, with permission, no problem 8915 enableInteractAcrossUsers(); 8916 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(), 8917 mUid + UserHandle.PER_USER_RANGE); 8918 } 8919 8920 private void enableInteractAcrossUsers() { 8921 TestablePermissions perms = mContext.getTestablePermissions(); 8922 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); 8923 } 8924 8925 @Test 8926 public void testNotificationBubbleChanged_false() throws Exception { 8927 setUpPrefsForBubbles(PKG, mUid, 8928 true /* global */, 8929 BUBBLE_PREFERENCE_ALL /* app */, 8930 true /* channel */); 8931 8932 // Notif with bubble metadata 8933 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8934 "testNotificationBubbleChanged_false"); 8935 8936 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8937 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8938 waitForIdle(); 8939 8940 // Reset as this is called when the notif is first sent 8941 reset(mListeners); 8942 8943 // First we were a bubble 8944 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 8945 assertEquals(1, notifsBefore.length); 8946 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0); 8947 8948 // Notify we're not a bubble 8949 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0); 8950 waitForIdle(); 8951 8952 // Make sure we are not a bubble 8953 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 8954 assertEquals(1, notifsAfter.length); 8955 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 8956 } 8957 8958 @Test 8959 public void testNotificationBubbleChanged_true() throws Exception { 8960 setUpPrefsForBubbles(PKG, mUid, 8961 true /* global */, 8962 BUBBLE_PREFERENCE_ALL /* app */, 8963 true /* channel */); 8964 8965 // Notif that is not a bubble 8966 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 8967 1, null, false); 8968 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8969 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8970 waitForIdle(); 8971 8972 // Would be a normal notification because wouldn't have met requirements to bubble 8973 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 8974 assertEquals(1, notifsBefore.length); 8975 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); 8976 8977 // Update the notification to be message style / meet bubble requirements 8978 NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8979 nr.getSbn().getTag()); 8980 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.getSbn().getTag(), 8981 nr2.getSbn().getId(), nr2.getSbn().getNotification(), nr2.getSbn().getUserId()); 8982 waitForIdle(); 8983 8984 // Reset as this is called when the notif is first sent 8985 reset(mListeners); 8986 8987 // Notify we are now a bubble 8988 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0); 8989 waitForIdle(); 8990 8991 // Make sure we are a bubble 8992 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 8993 assertEquals(1, notifsAfter.length); 8994 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0); 8995 } 8996 8997 @Test 8998 public void testNotificationBubbleChanged_true_notAllowed() throws Exception { 8999 setUpPrefsForBubbles(PKG, mUid, 9000 true /* global */, 9001 BUBBLE_PREFERENCE_ALL /* app */, 9002 true /* channel */); 9003 9004 // Notif that is not a bubble 9005 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 9006 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9007 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9008 waitForIdle(); 9009 9010 // Reset as this is called when the notif is first sent 9011 reset(mListeners); 9012 9013 // Would be a normal notification because wouldn't have met requirements to bubble 9014 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 9015 assertEquals(1, notifsBefore.length); 9016 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); 9017 9018 // Notify we are now a bubble 9019 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0); 9020 waitForIdle(); 9021 9022 // We still wouldn't be a bubble because the notification didn't meet requirements 9023 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9024 assertEquals(1, notifsAfter.length); 9025 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 9026 } 9027 9028 @Test 9029 public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception { 9030 setUpPrefsForBubbles(PKG, mUid, 9031 true /* global */, 9032 BUBBLE_PREFERENCE_ALL /* app */, 9033 true /* channel */); 9034 9035 // Notif with bubble metadata 9036 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 9037 "testNotificationBubbleIsFlagRemoved_resetOnUpdate"); 9038 9039 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9040 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9041 waitForIdle(); 9042 // Flag shouldn't be modified 9043 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 9044 assertFalse(recordToCheck.isFlagBubbleRemoved()); 9045 9046 // Notify we're not a bubble 9047 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0); 9048 waitForIdle(); 9049 // Flag should be modified 9050 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 9051 assertTrue(recordToCheck.isFlagBubbleRemoved()); 9052 9053 9054 // Update the notif 9055 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9056 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9057 waitForIdle(); 9058 // And the flag is reset 9059 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 9060 assertFalse(recordToCheck.isFlagBubbleRemoved()); 9061 } 9062 9063 @Test 9064 public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception { 9065 setUpPrefsForBubbles(PKG, mUid, 9066 true /* global */, 9067 BUBBLE_PREFERENCE_ALL /* app */, 9068 true /* channel */); 9069 9070 // Notif with bubble metadata 9071 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 9072 "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue"); 9073 9074 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9075 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9076 waitForIdle(); 9077 // Flag shouldn't be modified 9078 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 9079 assertFalse(recordToCheck.isFlagBubbleRemoved()); 9080 9081 // Notify we're not a bubble 9082 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0); 9083 waitForIdle(); 9084 // Flag should be modified 9085 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 9086 assertTrue(recordToCheck.isFlagBubbleRemoved()); 9087 9088 // Notify we are a bubble 9089 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0); 9090 waitForIdle(); 9091 // And the flag is reset 9092 assertFalse(recordToCheck.isFlagBubbleRemoved()); 9093 } 9094 9095 @Test 9096 public void testOnBubbleMetadataFlagChanged() throws Exception { 9097 setUpPrefsForBubbles(PKG, mUid, 9098 true /* global */, 9099 BUBBLE_PREFERENCE_ALL /* app */, 9100 true /* channel */); 9101 9102 // Post a bubble notification 9103 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag"); 9104 // Set this so that the bubble can be suppressed 9105 nr.getNotification().getBubbleMetadata().setFlags( 9106 Notification.BubbleMetadata.FLAG_SUPPRESSABLE_BUBBLE); 9107 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9108 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9109 waitForIdle(); 9110 9111 // Check the flags 9112 Notification n = mBinderService.getActiveNotifications(PKG)[0].getNotification(); 9113 assertFalse(n.getBubbleMetadata().isNotificationSuppressed()); 9114 assertFalse(n.getBubbleMetadata().getAutoExpandBubble()); 9115 assertFalse(n.getBubbleMetadata().isBubbleSuppressed()); 9116 assertTrue(n.getBubbleMetadata().isBubbleSuppressable()); 9117 9118 // Reset as this is called when the notif is first sent 9119 reset(mListeners); 9120 9121 // Test: change the flags 9122 int flags = Notification.BubbleMetadata.FLAG_SUPPRESSABLE_BUBBLE; 9123 flags |= Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE; 9124 flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; 9125 flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_BUBBLE; 9126 mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(), flags); 9127 waitForIdle(); 9128 9129 // Check 9130 n = mBinderService.getActiveNotifications(PKG)[0].getNotification(); 9131 assertEquals(flags, n.getBubbleMetadata().getFlags()); 9132 9133 // Reset to check again 9134 reset(mListeners); 9135 9136 // Test: clear flags 9137 mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(), 0); 9138 waitForIdle(); 9139 9140 // Check 9141 n = mBinderService.getActiveNotifications(PKG)[0].getNotification(); 9142 assertEquals(0, n.getBubbleMetadata().getFlags()); 9143 } 9144 9145 @Test 9146 public void testOnBubbleMetadataChangedToSuppressNotification_soundStopped() 9147 throws RemoteException { 9148 IRingtonePlayer mockPlayer = mock(IRingtonePlayer.class); 9149 when(mAudioManager.getRingtonePlayer()).thenReturn(mockPlayer); 9150 // Set up volume to be above 0 for the sound to actually play 9151 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10); 9152 9153 setUpPrefsForBubbles(PKG, mUid, 9154 true /* global */, 9155 BUBBLE_PREFERENCE_ALL /* app */, 9156 true /* channel */); 9157 9158 // Post a bubble notification 9159 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag"); 9160 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9161 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9162 waitForIdle(); 9163 9164 // Test: suppress notification via bubble metadata update 9165 mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(), 9166 Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 9167 waitForIdle(); 9168 9169 // Check audio is stopped 9170 verify(mockPlayer).stopAsync(); 9171 } 9172 9173 @Test 9174 public void testGrantInlineReplyUriPermission_recordExists() throws Exception { 9175 int userId = UserManager.isHeadlessSystemUserMode() 9176 ? UserHandle.getUserId(UID_HEADLESS) 9177 : USER_SYSTEM; 9178 9179 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId); 9180 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 9181 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9182 waitForIdle(); 9183 9184 // A notification exists for the given record 9185 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 9186 assertEquals(1, notifsBefore.length); 9187 9188 reset(mPackageManager); 9189 9190 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9191 9192 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9193 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9194 nr.getSbn().getUid()); 9195 9196 // Grant permission called for the UID of SystemUI under the target user ID 9197 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 9198 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), 9199 anyInt(), eq(nr.getSbn().getUserId())); 9200 } 9201 9202 @Test 9203 public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception { 9204 int userId = UserManager.isHeadlessSystemUserMode() 9205 ? UserHandle.getUserId(UID_HEADLESS) 9206 : USER_SYSTEM; 9207 9208 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId); 9209 waitForIdle(); 9210 9211 // No notifications exist for the given record 9212 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 9213 assertEquals(0, notifsBefore.length); 9214 9215 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9216 9217 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9218 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9219 nr.getSbn().getUid()); 9220 9221 // Grant permission still called if no NotificationRecord exists for the given key 9222 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 9223 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), 9224 anyInt(), eq(nr.getSbn().getUserId())); 9225 } 9226 9227 @Test 9228 public void testGrantInlineReplyUriPermission_userAll() throws Exception { 9229 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM 9230 NotificationRecord nr = 9231 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL); 9232 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 9233 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9234 waitForIdle(); 9235 9236 // A notification exists for the given record 9237 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 9238 assertEquals(1, notifsBefore.length); 9239 9240 reset(mPackageManager); 9241 9242 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9243 9244 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9245 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9246 nr.getSbn().getUid()); 9247 9248 // Target user for the grant is USER_ALL instead of USER_SYSTEM 9249 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 9250 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), 9251 anyInt(), UserManager.isHeadlessSystemUserMode() 9252 ? eq(UserHandle.getUserId(UID_HEADLESS)) 9253 : eq(USER_SYSTEM)); 9254 } 9255 9256 @Test 9257 public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception { 9258 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM 9259 int otherUserId = 11; 9260 NotificationRecord nr = 9261 generateNotificationRecord(mTestNotificationChannel, otherUserId); 9262 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 9263 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9264 waitForIdle(); 9265 9266 // A notification exists for the given record 9267 List<StatusBarNotification> notifsBefore = 9268 mBinderService.getAppActiveNotifications(PKG, nr.getSbn().getUserId()).getList(); 9269 assertEquals(1, notifsBefore.size()); 9270 9271 reset(mPackageManager); 9272 9273 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9274 9275 int uid = 0; // sysui on primary user 9276 int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user 9277 String sysuiPackage = "sysui"; 9278 final String[] sysuiPackages = new String[] { sysuiPackage }; 9279 when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages); 9280 9281 // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the 9282 // time this is called 9283 when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId)) 9284 .thenReturn(otherUserUid); 9285 9286 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9287 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), uid); 9288 9289 // Target user for the grant is USER_ALL instead of USER_SYSTEM 9290 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 9291 eq(otherUserUid), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), anyInt(), 9292 eq(otherUserId)); 9293 } 9294 9295 @Test 9296 public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception { 9297 int userId = UserManager.isHeadlessSystemUserMode() 9298 ? UserHandle.getUserId(UID_HEADLESS) 9299 : USER_SYSTEM; 9300 9301 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId); 9302 reset(mPackageManager); 9303 9304 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9305 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2); 9306 9307 // create an inline record with two uris in it 9308 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9309 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9310 nr.getSbn().getUid()); 9311 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9312 nr.getKey(), uri2, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9313 nr.getSbn().getUid()); 9314 9315 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey()); 9316 assertNotNull(record); // record exists 9317 assertEquals(record.getUris().size(), 2); // record has two uris in it 9318 9319 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), 9320 nr.getSbn().getUid()); 9321 9322 // permissionOwner destroyed 9323 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner( 9324 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId())); 9325 } 9326 9327 9328 @Test 9329 public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception { 9330 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0); 9331 reset(mPackageManager); 9332 9333 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), 9334 nr.getSbn().getUid()); 9335 9336 // no permissionOwner destroyed 9337 verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner( 9338 any(), eq(null), eq(~0), eq(nr.getUserId())); 9339 } 9340 9341 @Test 9342 public void testClearInlineReplyUriPermission_userAll() throws Exception { 9343 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 9344 UserHandle.USER_ALL); 9345 reset(mPackageManager); 9346 9347 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9348 9349 // create an inline record a uri in it 9350 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9351 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9352 nr.getSbn().getUid()); 9353 9354 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey()); 9355 assertNotNull(record); // record exists 9356 9357 mService.mNotificationDelegate.clearInlineReplyUriPermissions( 9358 nr.getKey(), nr.getSbn().getUid()); 9359 9360 // permissionOwner destroyed for USER_SYSTEM, not USER_ALL 9361 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner( 9362 eq(record.getPermissionOwner()), eq(null), eq(~0), 9363 UserManager.isHeadlessSystemUserMode() 9364 ? eq(UserHandle.getUserId(UID_HEADLESS)) 9365 : eq(USER_SYSTEM)); 9366 } 9367 9368 @Test 9369 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception { 9370 setUpPrefsForBubbles(PKG, mUid, 9371 true /* global */, 9372 BUBBLE_PREFERENCE_ALL /* app */, 9373 true /* channel */); 9374 9375 // And we are low ram 9376 when(mActivityManager.isLowRamDevice()).thenReturn(true); 9377 9378 // Notification that would typically bubble 9379 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 9380 "testNotificationBubbles_disabled_lowRamDevice"); 9381 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9382 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9383 waitForIdle(); 9384 9385 // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled. 9386 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9387 assertEquals(1, notifsAfter.length); 9388 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 9389 } 9390 9391 @Test 9392 public void testRemoveLargeRemoteViews() throws Exception { 9393 int removeSize = mContext.getResources().getInteger( 9394 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes); 9395 9396 RemoteViews rv = mock(RemoteViews.class); 9397 when(rv.estimateMemoryUsage()).thenReturn(removeSize); 9398 when(rv.clone()).thenReturn(rv); 9399 RemoteViews rv1 = mock(RemoteViews.class); 9400 when(rv1.estimateMemoryUsage()).thenReturn(removeSize); 9401 when(rv1.clone()).thenReturn(rv1); 9402 RemoteViews rv2 = mock(RemoteViews.class); 9403 when(rv2.estimateMemoryUsage()).thenReturn(removeSize); 9404 when(rv2.clone()).thenReturn(rv2); 9405 RemoteViews rv3 = mock(RemoteViews.class); 9406 when(rv3.estimateMemoryUsage()).thenReturn(removeSize); 9407 when(rv3.clone()).thenReturn(rv3); 9408 RemoteViews rv4 = mock(RemoteViews.class); 9409 when(rv4.estimateMemoryUsage()).thenReturn(removeSize); 9410 when(rv4.clone()).thenReturn(rv4); 9411 // note: different! 9412 RemoteViews rv5 = mock(RemoteViews.class); 9413 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1); 9414 when(rv5.clone()).thenReturn(rv5); 9415 9416 Notification np = new Notification.Builder(mContext, "test") 9417 .setSmallIcon(android.R.drawable.sym_def_app_icon) 9418 .setContentText("test") 9419 .setCustomContentView(rv) 9420 .setCustomBigContentView(rv1) 9421 .setCustomHeadsUpContentView(rv2) 9422 .build(); 9423 Notification n = new Notification.Builder(mContext, "test") 9424 .setSmallIcon(android.R.drawable.sym_def_app_icon) 9425 .setContentText("test") 9426 .setCustomContentView(rv3) 9427 .setCustomBigContentView(rv4) 9428 .setCustomHeadsUpContentView(rv5) 9429 .setPublicVersion(np) 9430 .build(); 9431 9432 assertNotNull(np.contentView); 9433 assertNotNull(np.bigContentView); 9434 assertNotNull(np.headsUpContentView); 9435 9436 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW)); 9437 assertNotNull(n.publicVersion.contentView); 9438 assertNotNull(n.publicVersion.bigContentView); 9439 assertNotNull(n.publicVersion.headsUpContentView); 9440 9441 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 9442 9443 assertNull(n.contentView); 9444 assertNull(n.bigContentView); 9445 assertNotNull(n.headsUpContentView); 9446 assertNull(n.publicVersion.contentView); 9447 assertNull(n.publicVersion.bigContentView); 9448 assertNull(n.publicVersion.headsUpContentView); 9449 9450 verify(mUsageStats, times(5)).registerImageRemoved(PKG); 9451 } 9452 9453 @Test 9454 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground() 9455 throws Exception { 9456 setUpPrefsForBubbles(PKG, mUid, 9457 true /* global */, 9458 BUBBLE_PREFERENCE_ALL /* app */, 9459 true /* channel */); 9460 9461 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 9462 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground"); 9463 // Modify metadata flags 9464 nr.getSbn().getNotification().getBubbleMetadata().setFlags( 9465 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE 9466 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 9467 9468 // Ensure we're not foreground 9469 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn( 9470 IMPORTANCE_VISIBLE); 9471 9472 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9473 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9474 waitForIdle(); 9475 9476 // yes allowed, yes messaging, yes bubble 9477 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 9478 assertTrue(notif.isBubbleNotification()); 9479 9480 // The flag should have failed since we're not foreground 9481 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble()); 9482 } 9483 9484 @Test 9485 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground() 9486 throws RemoteException { 9487 setUpPrefsForBubbles(PKG, mUid, 9488 true /* global */, 9489 BUBBLE_PREFERENCE_ALL /* app */, 9490 true /* channel */); 9491 9492 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 9493 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground"); 9494 // Modify metadata flags 9495 nr.getSbn().getNotification().getBubbleMetadata().setFlags( 9496 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE 9497 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 9498 9499 // Ensure we are in the foreground 9500 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn( 9501 IMPORTANCE_FOREGROUND); 9502 9503 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9504 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9505 waitForIdle(); 9506 9507 // yes allowed, yes messaging, yes bubble 9508 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 9509 assertTrue(notif.isBubbleNotification()); 9510 9511 // Our flags should have passed since we are foreground 9512 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble()); 9513 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed()); 9514 } 9515 9516 @Test 9517 public void testNotificationBubbles_flagRemoved_whenShortcutRemoved() 9518 throws RemoteException { 9519 setUpPrefsForBubbles(PKG, mUid, 9520 true /* global */, 9521 BUBBLE_PREFERENCE_ALL /* app */, 9522 true /* channel */); 9523 9524 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback = 9525 ArgumentCaptor.forClass(LauncherApps.Callback.class); 9526 9527 // Messaging notification with shortcut info 9528 Notification.BubbleMetadata metadata = 9529 new Notification.BubbleMetadata.Builder(VALID_CONVO_SHORTCUT_ID).build(); 9530 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 9531 null /* groupKey */, false /* isSummary */); 9532 nb.setShortcutId(VALID_CONVO_SHORTCUT_ID); 9533 nb.setBubbleMetadata(metadata); 9534 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 9535 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 9536 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 9537 9538 // Test: Send the bubble notification 9539 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9540 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9541 waitForIdle(); 9542 9543 // Verify: 9544 9545 // Make sure we register the callback for shortcut changes 9546 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any()); 9547 9548 // yes allowed, yes messaging w/shortcut, yes bubble 9549 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 9550 assertTrue(notif.isBubbleNotification()); 9551 9552 // Make sure the shortcut is cached. 9553 verify(mShortcutServiceInternal).cacheShortcuts( 9554 anyInt(), any(), eq(PKG), eq(singletonList(VALID_CONVO_SHORTCUT_ID)), 9555 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 9556 9557 // Test: Remove the shortcut 9558 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 9559 launcherAppsCallback.getValue().onShortcutsChanged(PKG, emptyList(), 9560 UserHandle.getUserHandleForUid(mUid)); 9561 waitForIdle(); 9562 9563 // Verify: 9564 9565 // Make sure callback is unregistered 9566 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue()); 9567 9568 // We're no longer a bubble 9569 NotificationRecord notif2 = mService.getNotificationRecord( 9570 nr.getSbn().getKey()); 9571 assertNull(notif2.getShortcutInfo()); 9572 assertFalse(notif2.getNotification().isBubbleNotification()); 9573 } 9574 9575 @Test 9576 public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved() 9577 throws RemoteException { 9578 final String shortcutId = "someshortcutId"; 9579 setUpPrefsForBubbles(PKG, mUid, 9580 true /* global */, 9581 BUBBLE_PREFERENCE_ALL /* app */, 9582 true /* channel */); 9583 9584 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback = 9585 ArgumentCaptor.forClass(LauncherApps.Callback.class); 9586 9587 // Messaging notification with shortcut info 9588 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder( 9589 shortcutId).build(); 9590 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 9591 null /* groupKey */, false /* isSummary */); 9592 nb.setShortcutId(shortcutId); 9593 nb.setBubbleMetadata(metadata); 9594 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 9595 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 9596 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 9597 9598 // Pretend the shortcut exists 9599 List<ShortcutInfo> shortcutInfos = new ArrayList<>(); 9600 ShortcutInfo info = mock(ShortcutInfo.class); 9601 when(info.getPackage()).thenReturn(PKG); 9602 when(info.getId()).thenReturn(shortcutId); 9603 when(info.getUserId()).thenReturn(USER_SYSTEM); 9604 when(info.isLongLived()).thenReturn(true); 9605 when(info.isEnabled()).thenReturn(true); 9606 shortcutInfos.add(info); 9607 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos); 9608 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), 9609 anyString(), anyInt(), any())).thenReturn(true); 9610 9611 // Test: Send the bubble notification 9612 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9613 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9614 waitForIdle(); 9615 9616 // Verify: 9617 9618 // Make sure we register the callback for shortcut changes 9619 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any()); 9620 9621 // yes allowed, yes messaging w/shortcut, yes bubble 9622 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 9623 assertTrue(notif.isBubbleNotification()); 9624 9625 // Make sure the shortcut is cached. 9626 verify(mShortcutServiceInternal).cacheShortcuts( 9627 anyInt(), any(), eq(PKG), eq(singletonList(shortcutId)), 9628 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 9629 9630 // Test: Remove the notification 9631 mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9632 nr.getSbn().getId(), nr.getSbn().getUserId()); 9633 waitForIdle(); 9634 9635 // Verify: 9636 9637 // Make sure callback is unregistered 9638 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue()); 9639 } 9640 9641 @Test 9642 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed() 9643 throws Exception { 9644 setUpPrefsForBubbles(PKG, mUid, 9645 true /* global */, 9646 BUBBLE_PREFERENCE_ALL /* app */, 9647 true /* channel */); 9648 9649 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded( 9650 true /* summaryAutoCancel */); 9651 9652 // Dismiss summary 9653 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2, 9654 true); 9655 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, 9656 nrSummary.getUserId(), nrSummary.getKey(), 9657 NotificationStats.DISMISSAL_SHADE, 9658 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv); 9659 waitForIdle(); 9660 9661 // The bubble should still exist 9662 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9663 assertEquals(1, notifsAfter.length); 9664 } 9665 9666 @Test 9667 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked() 9668 throws Exception { 9669 setUpPrefsForBubbles(PKG, mUid, 9670 true /* global */, 9671 BUBBLE_PREFERENCE_ALL /* app */, 9672 true /* channel */); 9673 9674 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded( 9675 true /* summaryAutoCancel */); 9676 9677 // Click summary 9678 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2, 9679 true); 9680 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(), 9681 nrSummary.getKey(), nv); 9682 waitForIdle(); 9683 9684 // The bubble should still exist 9685 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9686 assertEquals(1, notifsAfter.length); 9687 9688 // Check we got the click log and associated dismissal logs 9689 assertEquals(6, mNotificationRecordLogger.numCalls()); 9690 // Skip the notification-creation logs 9691 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED, 9692 mNotificationRecordLogger.event(3)); 9693 assertEquals(NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_CLICK, 9694 mNotificationRecordLogger.event(4)); 9695 assertEquals(NotificationRecordLogger.NotificationCancelledEvent 9696 .NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED, 9697 mNotificationRecordLogger.event(5)); 9698 } 9699 9700 @Test 9701 public void testNotificationBubbles_bubbleStays_whenClicked() 9702 throws Exception { 9703 setUpPrefsForBubbles(PKG, mUid, 9704 true /* global */, 9705 BUBBLE_PREFERENCE_ALL /* app */, 9706 true /* channel */); 9707 9708 // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble 9709 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 9710 nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL; 9711 mService.addNotification(nr); 9712 9713 // WHEN we click the notification 9714 final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true); 9715 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(), 9716 nr.getKey(), nv); 9717 waitForIdle(); 9718 9719 // THEN the bubble should still exist 9720 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9721 assertEquals(1, notifsAfter.length); 9722 9723 // Check we got the click log 9724 assertEquals(1, mNotificationRecordLogger.numCalls()); 9725 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED, 9726 mNotificationRecordLogger.event(0)); 9727 } 9728 9729 /** 9730 * When something is bubble'd and the bubble is dismissed, but the notification is still 9731 * visible, clicking on the notification shouldn't auto-cancel it because clicking on 9732 * it will produce a bubble. 9733 */ 9734 @Test 9735 public void testNotificationBubbles_bubbleStays_whenClicked_afterBubbleDismissed() 9736 throws Exception { 9737 setUpPrefsForBubbles(PKG, mUid, 9738 true /* global */, 9739 BUBBLE_PREFERENCE_ALL /* app */, 9740 true /* channel */); 9741 9742 // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble 9743 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 9744 nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL; 9745 nr.setAllowBubble(true); 9746 mService.addNotification(nr); 9747 9748 // And the bubble is dismissed 9749 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), 9750 false /* isBubble */, 0 /* bubbleFlags */); 9751 waitForIdle(); 9752 assertTrue(nr.isFlagBubbleRemoved()); 9753 9754 // WHEN we click the notification 9755 final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true); 9756 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(), 9757 nr.getKey(), nv); 9758 waitForIdle(); 9759 9760 // THEN the bubble should still exist 9761 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9762 assertEquals(1, notifsAfter.length); 9763 9764 // Check we got the click log 9765 assertEquals(1, mNotificationRecordLogger.numCalls()); 9766 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED, 9767 mNotificationRecordLogger.event(0)); 9768 } 9769 9770 @Test 9771 public void testLoadDefaultApprovedServices_emptyResources() { 9772 TestableResources tr = mContext.getOrCreateTestableResources(); 9773 tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, ""); 9774 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, ""); 9775 tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, ""); 9776 setDefaultAssistantInDeviceConfig(""); 9777 9778 mService.loadDefaultApprovedServices(USER_SYSTEM); 9779 9780 verify(mListeners, never()).addDefaultComponentOrPackage(anyString()); 9781 verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString()); 9782 verify(mAssistants, never()).addDefaultComponentOrPackage(anyString()); 9783 } 9784 9785 @Test 9786 public void testLoadDefaultApprovedServices_dnd() { 9787 TestableResources tr = mContext.getOrCreateTestableResources(); 9788 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test"); 9789 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt())) 9790 .thenReturn(new ArraySet<>()); 9791 9792 mService.loadDefaultApprovedServices(USER_SYSTEM); 9793 9794 verify(mConditionProviders, times(1)).loadDefaultsFromConfig(); 9795 } 9796 9797 // TODO: add tests for the rest of the non-empty cases 9798 9799 @Test 9800 public void testOnUnlockUser() { 9801 UserInfo ui = new UserInfo(); 9802 ui.id = 10; 9803 mService.onUserUnlocked(new TargetUser(ui)); 9804 waitForIdle(); 9805 9806 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id); 9807 } 9808 9809 @Test 9810 public void testOnStopUser() { 9811 UserInfo ui = new UserInfo(); 9812 ui.id = 10; 9813 mService.onUserStopping(new TargetUser(ui)); 9814 waitForIdle(); 9815 9816 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id); 9817 } 9818 9819 @Test 9820 public void testHandleOnPackageChanged() { 9821 String[] pkgs = new String[] {PKG, PKG_N_MR1}; 9822 int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1}; 9823 9824 mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids); 9825 9826 verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString()); 9827 9828 mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids); 9829 9830 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]); 9831 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]); 9832 } 9833 9834 @Test 9835 public void testNotificationHistory_addNoisyNotification() throws Exception { 9836 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 9837 null /* tvExtender */); 9838 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9839 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9840 waitForIdle(); 9841 9842 verify(mHistoryManager, times(1)).addNotification(any()); 9843 } 9844 9845 @Test 9846 public void createConversationNotificationChannel() throws Exception { 9847 int userId = UserManager.isHeadlessSystemUserMode() 9848 ? UserHandle.getUserId(UID_HEADLESS) 9849 : USER_SYSTEM; 9850 9851 NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 9852 original.setAllowBubbles(!original.canBubble()); 9853 original.setShowBadge(!original.canShowBadge()); 9854 9855 Parcel parcel = Parcel.obtain(); 9856 original.writeToParcel(parcel, 0); 9857 parcel.setDataPosition(0); 9858 NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel); 9859 assertEquals(original, orig); 9860 assertFalse(TextUtils.isEmpty(orig.getName())); 9861 9862 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList( 9863 orig))); 9864 9865 mBinderService.createConversationNotificationChannelForPackage( 9866 PKG, mUid, orig, "friend"); 9867 9868 NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel( 9869 PKG, userId, PKG, original.getId(), false, "friend"); 9870 9871 assertEquals(original.getName(), friendChannel.getName()); 9872 assertEquals(original.getId(), friendChannel.getParentChannelId()); 9873 assertEquals("friend", friendChannel.getConversationId()); 9874 assertEquals(null, original.getConversationId()); 9875 assertEquals(original.canShowBadge(), friendChannel.canShowBadge()); 9876 assertFalse(friendChannel.canBubble()); // can't be modified by app 9877 assertFalse(original.getId().equals(friendChannel.getId())); 9878 assertNotNull(friendChannel.getId()); 9879 } 9880 9881 @Test 9882 public void testCorrectCategory_systemOn_appCannotTurnOff() { 9883 int requested = 0; 9884 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 9885 9886 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 9887 system); 9888 9889 assertEquals(PRIORITY_CATEGORY_CONVERSATIONS, actual); 9890 } 9891 9892 @Test 9893 public void testCorrectCategory_systemOff_appTurnOff_noChanges() { 9894 int requested = PRIORITY_CATEGORY_CALLS; 9895 int system = PRIORITY_CATEGORY_CALLS; 9896 9897 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 9898 system); 9899 9900 assertEquals(PRIORITY_CATEGORY_CALLS, actual); 9901 } 9902 9903 @Test 9904 public void testCorrectCategory_systemOn_appTurnOn_noChanges() { 9905 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 9906 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 9907 9908 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 9909 system); 9910 9911 assertEquals(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS, actual); 9912 } 9913 9914 @Test 9915 public void testCorrectCategory_systemOff_appCannotTurnOn() { 9916 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 9917 int system = PRIORITY_CATEGORY_CALLS; 9918 9919 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 9920 system); 9921 9922 assertEquals(PRIORITY_CATEGORY_CALLS, actual); 9923 } 9924 9925 @Test 9926 public void testGetConversationsForPackage_hasShortcut() throws Exception { 9927 mService.setPreferencesHelper(mPreferencesHelper); 9928 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>(); 9929 ConversationChannelWrapper convo1 = new ConversationChannelWrapper(); 9930 NotificationChannel channel1 = new NotificationChannel("a", "a", 1); 9931 channel1.setConversationId("parent1", "convo 1"); 9932 convo1.setNotificationChannel(channel1); 9933 convos.add(convo1); 9934 9935 ConversationChannelWrapper convo2 = new ConversationChannelWrapper(); 9936 NotificationChannel channel2 = new NotificationChannel("b", "b", 1); 9937 channel2.setConversationId("parent1", "convo 2"); 9938 convo2.setNotificationChannel(channel2); 9939 convos.add(convo2); 9940 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos); 9941 9942 ShortcutInfo si = mock(ShortcutInfo.class); 9943 when(si.getPackage()).thenReturn(PKG_P); 9944 when(si.getId()).thenReturn("convo"); 9945 when(si.getUserId()).thenReturn(USER_SYSTEM); 9946 when(si.getLabel()).thenReturn("Hello"); 9947 when(si.isLongLived()).thenReturn(true); 9948 when(si.isEnabled()).thenReturn(true); 9949 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si)); 9950 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), 9951 anyString(), anyInt(), any())).thenReturn(true); 9952 9953 List<ConversationChannelWrapper> conversations = 9954 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 9955 assertEquals(si, conversations.get(0).getShortcutInfo()); 9956 assertEquals(si, conversations.get(1).getShortcutInfo()); 9957 9958 // Returns null shortcuts when locked. 9959 when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(false); 9960 conversations = 9961 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 9962 assertThat(conversations.get(0).getShortcutInfo()).isNull(); 9963 assertThat(conversations.get(1).getShortcutInfo()).isNull(); 9964 } 9965 9966 @Test 9967 public void testGetConversationsForPackage_shortcut_notLongLived() throws Exception { 9968 mService.setPreferencesHelper(mPreferencesHelper); 9969 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>(); 9970 ConversationChannelWrapper convo1 = new ConversationChannelWrapper(); 9971 NotificationChannel channel1 = new NotificationChannel("a", "a", 1); 9972 channel1.setConversationId("parent1", "convo 1"); 9973 convo1.setNotificationChannel(channel1); 9974 convos.add(convo1); 9975 9976 ConversationChannelWrapper convo2 = new ConversationChannelWrapper(); 9977 NotificationChannel channel2 = new NotificationChannel("b", "b", 1); 9978 channel2.setConversationId("parent1", "convo 2"); 9979 convo2.setNotificationChannel(channel2); 9980 convos.add(convo2); 9981 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos); 9982 9983 ShortcutInfo si = mock(ShortcutInfo.class); 9984 when(si.getPackage()).thenReturn(PKG_P); 9985 when(si.getId()).thenReturn("convo"); 9986 when(si.getUserId()).thenReturn(USER_SYSTEM); 9987 when(si.getLabel()).thenReturn("Hello"); 9988 when(si.isLongLived()).thenReturn(false); 9989 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si)); 9990 9991 List<ConversationChannelWrapper> conversations = 9992 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 9993 assertNull(conversations.get(0).getShortcutInfo()); 9994 assertNull(conversations.get(1).getShortcutInfo()); 9995 } 9996 9997 @Test 9998 public void testGetConversationsForPackage_doesNotHaveShortcut() throws Exception { 9999 mService.setPreferencesHelper(mPreferencesHelper); 10000 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>(); 10001 ConversationChannelWrapper convo1 = new ConversationChannelWrapper(); 10002 NotificationChannel channel1 = new NotificationChannel("a", "a", 1); 10003 channel1.setConversationId("parent1", "convo 1"); 10004 convo1.setNotificationChannel(channel1); 10005 convos.add(convo1); 10006 10007 ConversationChannelWrapper convo2 = new ConversationChannelWrapper(); 10008 NotificationChannel channel2 = new NotificationChannel("b", "b", 1); 10009 channel2.setConversationId("parent1", "convo 2"); 10010 convo2.setNotificationChannel(channel2); 10011 convos.add(convo2); 10012 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos); 10013 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 10014 10015 List<ConversationChannelWrapper> conversations = 10016 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 10017 assertNull(conversations.get(0).getShortcutInfo()); 10018 assertNull(conversations.get(1).getShortcutInfo()); 10019 } 10020 10021 @Test 10022 public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException { 10023 mService.setShortcutHelper(null); 10024 NotificationRecord nr = 10025 generateMessageBubbleNotifRecord(mTestNotificationChannel, 10026 "testShortcutHelperNull_doesntCrashEnqueue"); 10027 try { 10028 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 10029 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 10030 waitForIdle(); 10031 } catch (Exception e) { 10032 fail(e.getMessage()); 10033 } 10034 } 10035 10036 @Test 10037 public void testRecordMessages_invalidMsg() throws RemoteException { 10038 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 10039 null /* groupKey */, false /* isSummary */); 10040 nb.setShortcutId(null); 10041 StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1, 10042 "testRecordMessages_invalidMsg", mUid, 0, nb.build(), 10043 UserHandle.getUserHandleForUid(mUid), null, 0); 10044 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10045 10046 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 10047 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(), 10048 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 10049 waitForIdle(); 10050 10051 assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid)); 10052 } 10053 10054 @Test 10055 public void testRecordMessages_invalidMsg_notMessageStyle() throws RemoteException { 10056 Notification.Builder nb = new Notification.Builder(mContext, 10057 mTestNotificationChannel.getId()) 10058 .setContentTitle("foo") 10059 .setShortcutId(null) 10060 .setSmallIcon(android.R.drawable.sym_def_app_icon) 10061 .setCategory(Notification.CATEGORY_MESSAGE); 10062 StatusBarNotification sbn = new StatusBarNotification(PKG_O, PKG_O, 1, 10063 "testRecordMessages_invalidMsg_notMessageStyle", mUid, 0, nb.build(), 10064 UserHandle.getUserHandleForUid(mUid), null, 0); 10065 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10066 10067 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 10068 mBinderService.enqueueNotificationWithTag(PKG_O, PKG_O, nr.getSbn().getTag(), 10069 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 10070 waitForIdle(); 10071 10072 // PKG_O is allowed to be in conversation space b/c of override in 10073 // TestableNotificationManagerService 10074 assertTrue(mBinderService.isInInvalidMsgState(PKG_O, mUid)); 10075 } 10076 10077 @Test 10078 public void testRecordMessages_validMsg() throws RemoteException { 10079 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 10080 null /* groupKey */, false /* isSummary */); 10081 nb.setShortcutId(null); 10082 StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1, 10083 "testRecordMessages_validMsg", mUid, 0, nb.build(), 10084 UserHandle.getUserHandleForUid(mUid), null, 0); 10085 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10086 10087 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(), 10088 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 10089 waitForIdle(); 10090 10091 assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid)); 10092 10093 nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 10094 "testRecordMessages_validMsg"); 10095 10096 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(), 10097 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 10098 waitForIdle(); 10099 10100 assertFalse(mBinderService.isInInvalidMsgState(PKG_P, mUid)); 10101 } 10102 10103 @Test 10104 public void testRecordMessages_invalidMsg_afterValidMsg() throws RemoteException { 10105 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 10106 "testRecordMessages_invalidMsg_afterValidMsg_1"); 10107 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 10108 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 10109 waitForIdle(); 10110 assertTrue(mService.getNotificationRecord(nr.getKey()).isConversation()); 10111 10112 mBinderService.cancelAllNotifications(PKG, mUid); 10113 waitForIdle(); 10114 10115 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 10116 null /* groupKey */, false /* isSummary */); 10117 nb.setShortcutId(null); 10118 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 10119 "testRecordMessages_invalidMsg_afterValidMsg_2", mUid, 0, nb.build(), 10120 UserHandle.getUserHandleForUid(mUid), null, 0); 10121 nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10122 10123 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 10124 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 10125 waitForIdle(); 10126 10127 assertFalse(mService.getNotificationRecord(nr.getKey()).isConversation()); 10128 } 10129 10130 @Test 10131 public void testCanPostFgsWhenOverLimit() throws RemoteException { 10132 when(mAmi.applyForegroundServiceNotification( 10133 any(), anyString(), anyInt(), anyString(), anyInt())) 10134 .thenReturn(SHOW_IMMEDIATELY); 10135 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 10136 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 10137 i, null, false).getSbn(); 10138 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10139 "testCanPostFgsWhenOverLimit", 10140 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 10141 } 10142 10143 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 10144 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 10145 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10146 "testCanPostFgsWhenOverLimit - fgs over limit!", 10147 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 10148 10149 waitForIdle(); 10150 10151 StatusBarNotification[] notifs = 10152 mBinderService.getActiveNotifications(sbn.getPackageName()); 10153 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); 10154 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, 10155 mService.getNotificationRecordCount()); 10156 } 10157 10158 @Test 10159 public void testCannotPostNonFgsWhenOverLimit() throws RemoteException { 10160 when(mAmi.applyForegroundServiceNotification( 10161 any(), anyString(), anyInt(), anyString(), anyInt())) 10162 .thenReturn(SHOW_IMMEDIATELY); 10163 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 10164 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 10165 i, null, false).getSbn(); 10166 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10167 "testCanPostFgsWhenOverLimit", 10168 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 10169 waitForIdle(); 10170 } 10171 10172 final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 10173 100, null, false).getSbn(); 10174 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 10175 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10176 "testCanPostFgsWhenOverLimit - fgs over limit!", 10177 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 10178 10179 final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel, 10180 101, null, false).getSbn(); 10181 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10182 "testCanPostFgsWhenOverLimit - non fgs over limit!", 10183 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId()); 10184 10185 10186 when(mAmi.applyForegroundServiceNotification( 10187 any(), anyString(), anyInt(), anyString(), anyInt())) 10188 .thenReturn(NOT_FOREGROUND_SERVICE); 10189 final StatusBarNotification sbn3 = generateNotificationRecord(mTestNotificationChannel, 10190 101, null, false).getSbn(); 10191 sbn3.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 10192 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10193 "testCanPostFgsWhenOverLimit - fake fgs over limit!", 10194 sbn3.getId(), sbn3.getNotification(), sbn3.getUserId()); 10195 10196 waitForIdle(); 10197 10198 StatusBarNotification[] notifs = 10199 mBinderService.getActiveNotifications(sbn.getPackageName()); 10200 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); 10201 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, 10202 mService.getNotificationRecordCount()); 10203 } 10204 10205 @Test 10206 public void testIsVisibleToListener_notEnabled() { 10207 StatusBarNotification sbn = mock(StatusBarNotification.class); 10208 when(sbn.getUserId()).thenReturn(10); 10209 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10210 ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class); 10211 info.userid = 10; 10212 when(info.isSameUser(anyInt())).thenReturn(true); 10213 when(assistant.isSameUser(anyInt())).thenReturn(true); 10214 when(info.enabledAndUserMatches(info.userid)).thenReturn(false); 10215 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant); 10216 10217 assertFalse(mService.isVisibleToListener(sbn, 0, info)); 10218 } 10219 10220 @Test 10221 public void testIsVisibleToListener_noAssistant() { 10222 StatusBarNotification sbn = mock(StatusBarNotification.class); 10223 when(sbn.getUserId()).thenReturn(10); 10224 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10225 info.userid = 10; 10226 when(info.isSameUser(anyInt())).thenReturn(true); 10227 when(info.enabledAndUserMatches(info.userid)).thenReturn(true); 10228 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(null); 10229 10230 assertTrue(mService.isVisibleToListener(sbn, 0, info)); 10231 } 10232 10233 @Test 10234 public void testIsVisibleToListener_assistant_differentUser() { 10235 StatusBarNotification sbn = mock(StatusBarNotification.class); 10236 when(sbn.getUserId()).thenReturn(10); 10237 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10238 ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class); 10239 info.userid = 0; 10240 when(info.isSameUser(anyInt())).thenReturn(true); 10241 when(assistant.isSameUser(anyInt())).thenReturn(true); 10242 when(info.enabledAndUserMatches(info.userid)).thenReturn(true); 10243 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant); 10244 10245 assertFalse(mService.isVisibleToListener(sbn, 0, info)); 10246 } 10247 10248 @Test 10249 public void testIsVisibleToListener_assistant_sameUser() { 10250 StatusBarNotification sbn = mock(StatusBarNotification.class); 10251 when(sbn.getUserId()).thenReturn(10); 10252 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10253 ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class); 10254 info.userid = 10; 10255 when(info.isSameUser(anyInt())).thenReturn(true); 10256 when(assistant.isSameUser(anyInt())).thenReturn(true); 10257 when(info.enabledAndUserMatches(info.userid)).thenReturn(true); 10258 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant); 10259 10260 assertTrue(mService.isVisibleToListener(sbn, 0, info)); 10261 } 10262 10263 @Test 10264 public void testIsVisibleToListener_mismatchedType() { 10265 when(mNlf.isTypeAllowed(anyInt())).thenReturn(false); 10266 10267 StatusBarNotification sbn = mock(StatusBarNotification.class); 10268 when(sbn.getUserId()).thenReturn(10); 10269 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10270 ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class); 10271 info.userid = 10; 10272 when(info.isSameUser(anyInt())).thenReturn(true); 10273 when(assistant.isSameUser(anyInt())).thenReturn(true); 10274 when(info.enabledAndUserMatches(info.userid)).thenReturn(true); 10275 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant); 10276 10277 assertFalse(mService.isVisibleToListener(sbn, 0, info)); 10278 } 10279 10280 @Test 10281 public void testIsVisibleToListener_disallowedPackage() { 10282 when(mNlf.isPackageAllowed(any())).thenReturn(false); 10283 10284 StatusBarNotification sbn = mock(StatusBarNotification.class); 10285 when(sbn.getUserId()).thenReturn(10); 10286 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10287 ManagedServices.ManagedServiceInfo assistant = 10288 mock(ManagedServices.ManagedServiceInfo.class); 10289 info.userid = 10; 10290 when(info.isSameUser(anyInt())).thenReturn(true); 10291 when(assistant.isSameUser(anyInt())).thenReturn(true); 10292 when(info.enabledAndUserMatches(info.userid)).thenReturn(true); 10293 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant); 10294 10295 assertFalse(mService.isVisibleToListener(sbn, 0, info)); 10296 } 10297 10298 @Test 10299 public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedFirst() { 10300 final NotificationRecord parent = spy(generateNotificationRecord( 10301 mTestNotificationChannel, 1, "group", true)); 10302 final NotificationRecord child = spy(generateNotificationRecord( 10303 mTestNotificationChannel, 2, "group", false)); 10304 mService.addNotification(parent); 10305 mService.addNotification(child); 10306 10307 InOrder inOrder = inOrder(parent, child); 10308 10309 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 10310 parent.getUserId()); 10311 waitForIdle(); 10312 inOrder.verify(parent).recordDismissalSentiment(anyInt()); 10313 inOrder.verify(child).recordDismissalSentiment(anyInt()); 10314 } 10315 10316 @Test 10317 public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedSecond() { 10318 final NotificationRecord parent = spy(generateNotificationRecord( 10319 mTestNotificationChannel, 1, "group", true)); 10320 final NotificationRecord child = spy(generateNotificationRecord( 10321 mTestNotificationChannel, 2, "group", false)); 10322 mService.addNotification(child); 10323 mService.addNotification(parent); 10324 10325 InOrder inOrder = inOrder(parent, child); 10326 10327 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 10328 parent.getUserId()); 10329 waitForIdle(); 10330 inOrder.verify(parent).recordDismissalSentiment(anyInt()); 10331 inOrder.verify(child).recordDismissalSentiment(anyInt()); 10332 } 10333 10334 @Test 10335 public void testImmutableBubbleIntent() throws Exception { 10336 when(mAmi.getPendingIntentFlags(pi1)) 10337 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT); 10338 NotificationRecord r = generateMessageBubbleNotifRecord(true, 10339 mTestNotificationChannel, 7, "testImmutableBubbleIntent", null, false); 10340 try { 10341 mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(), 10342 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId()); 10343 10344 waitForIdle(); 10345 fail("Allowed a bubble with an immutable intent to be posted"); 10346 } catch (IllegalArgumentException e) { 10347 // good 10348 } 10349 } 10350 10351 @Test 10352 public void testMutableBubbleIntent() throws Exception { 10353 when(mAmi.getPendingIntentFlags(pi1)) 10354 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); 10355 NotificationRecord r = generateMessageBubbleNotifRecord(true, 10356 mTestNotificationChannel, 7, "testMutableBubbleIntent", null, false); 10357 10358 mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(), 10359 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId()); 10360 10361 waitForIdle(); 10362 StatusBarNotification[] notifs = 10363 mBinderService.getActiveNotifications(r.getSbn().getPackageName()); 10364 assertEquals(1, notifs.length); 10365 } 10366 10367 @Test 10368 public void testImmutableDirectReplyActionIntent() throws Exception { 10369 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10370 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT); 10371 NotificationRecord r = generateMessageBubbleNotifRecord(false, 10372 mTestNotificationChannel, 7, "testImmutableDirectReplyActionIntent", null, false); 10373 try { 10374 mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(), 10375 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId()); 10376 10377 waitForIdle(); 10378 fail("Allowed a direct reply with an immutable intent to be posted"); 10379 } catch (IllegalArgumentException e) { 10380 // good 10381 } 10382 } 10383 10384 @Test 10385 public void testMutableDirectReplyActionIntent() throws Exception { 10386 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10387 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); 10388 NotificationRecord r = generateMessageBubbleNotifRecord(false, 10389 mTestNotificationChannel, 7, "testMutableDirectReplyActionIntent", null, false); 10390 mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(), 10391 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId()); 10392 10393 waitForIdle(); 10394 StatusBarNotification[] notifs = 10395 mBinderService.getActiveNotifications(r.getSbn().getPackageName()); 10396 assertEquals(1, notifs.length); 10397 } 10398 10399 @Test 10400 public void testImmutableDirectReplyContextualActionIntent() throws Exception { 10401 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10402 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT); 10403 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10404 10405 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 10406 ArrayList<Notification.Action> extraAction = new ArrayList<>(); 10407 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); 10408 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 10409 PendingIntent.FLAG_IMMUTABLE); 10410 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); 10411 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", 10412 inputIntent).addRemoteInput(remoteInput) 10413 .build(); 10414 extraAction.add(replyAction); 10415 Bundle signals = new Bundle(); 10416 signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction); 10417 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "", 10418 r.getUser()); 10419 r.addAdjustment(adjustment); 10420 r.applyAdjustments(); 10421 10422 try { 10423 mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(), 10424 r.getSbn().getTag(), r, false, false); 10425 fail("Allowed a contextual direct reply with an immutable intent to be posted"); 10426 } catch (IllegalArgumentException e) { 10427 // good 10428 } 10429 } 10430 10431 @Test 10432 public void testMutableDirectReplyContextualActionIntent() throws Exception { 10433 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10434 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); 10435 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10436 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 10437 ArrayList<Notification.Action> extraAction = new ArrayList<>(); 10438 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); 10439 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, 10440 new Intent().setPackage(mContext.getPackageName()), 10441 PendingIntent.FLAG_MUTABLE); 10442 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); 10443 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", 10444 inputIntent).addRemoteInput(remoteInput) 10445 .build(); 10446 extraAction.add(replyAction); 10447 Bundle signals = new Bundle(); 10448 signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction); 10449 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "", 10450 r.getUser()); 10451 r.addAdjustment(adjustment); 10452 r.applyAdjustments(); 10453 10454 mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(), 10455 r.getSbn().getTag(), r, false, false); 10456 } 10457 10458 @Test 10459 public void testImmutableActionIntent() throws Exception { 10460 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10461 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT); 10462 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 10463 10464 mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(), 10465 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId()); 10466 10467 waitForIdle(); 10468 StatusBarNotification[] notifs = 10469 mBinderService.getActiveNotifications(r.getSbn().getPackageName()); 10470 assertEquals(1, notifs.length); 10471 } 10472 10473 @Test 10474 public void testImmutableContextualActionIntent() throws Exception { 10475 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10476 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT); 10477 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10478 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 10479 ArrayList<Notification.Action> extraAction = new ArrayList<>(); 10480 extraAction.add(new Notification.Action(0, "hello", null)); 10481 Bundle signals = new Bundle(); 10482 signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction); 10483 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "", 10484 r.getUser()); 10485 r.addAdjustment(adjustment); 10486 r.applyAdjustments(); 10487 10488 mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(), 10489 r.getSbn().getTag(), r, false, false); 10490 } 10491 10492 @Test 10493 public void testMigrateNotificationFilter_migrationAllAllowed() throws Exception { 10494 int uid = 9000; 10495 int[] userIds = new int[] {mUserId, 1000}; 10496 when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds); 10497 List<String> disallowedApps = ImmutableList.of("apples", "bananas", "cherries"); 10498 for (int userId : userIds) { 10499 for (String pkg : disallowedApps) { 10500 when(mPackageManager.getPackageUid(pkg, 0, userId)).thenReturn(uid++); 10501 } 10502 } 10503 10504 when(mListeners.getNotificationListenerFilter(any())).thenReturn( 10505 new NotificationListenerFilter()); 10506 10507 mBinderService.migrateNotificationFilter(null, 10508 FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING, 10509 disallowedApps); 10510 10511 ArgumentCaptor<NotificationListenerFilter> captor = 10512 ArgumentCaptor.forClass(NotificationListenerFilter.class); 10513 verify(mListeners).setNotificationListenerFilter(any(), captor.capture()); 10514 10515 assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING, 10516 captor.getValue().getTypes()); 10517 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 9000))); 10518 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("cherries", 9002))); 10519 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 9003))); 10520 10521 // hypothetical other user untouched 10522 assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 10000))); 10523 } 10524 10525 @Test 10526 public void testMigrateNotificationFilter_invalidPackage() throws Exception { 10527 int[] userIds = new int[] {mUserId, 1000}; 10528 when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds); 10529 List<String> disallowedApps = ImmutableList.of("apples", "bananas", "cherries"); 10530 for (int userId : userIds) { 10531 when(mPackageManager.getPackageUid("apples", 0, userId)).thenThrow( 10532 new RemoteException("")); 10533 when(mPackageManager.getPackageUid("bananas", 0, userId)).thenReturn(9000); 10534 when(mPackageManager.getPackageUid("cherries", 0, userId)).thenReturn(9001); 10535 } 10536 10537 when(mListeners.getNotificationListenerFilter(any())).thenReturn( 10538 new NotificationListenerFilter()); 10539 10540 mBinderService.migrateNotificationFilter(null, 10541 FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING, 10542 disallowedApps); 10543 10544 ArgumentCaptor<NotificationListenerFilter> captor = 10545 ArgumentCaptor.forClass(NotificationListenerFilter.class); 10546 verify(mListeners).setNotificationListenerFilter(any(), captor.capture()); 10547 10548 assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING, 10549 captor.getValue().getTypes()); 10550 // valid values stay 10551 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("bananas", 9000))); 10552 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("cherries", 9001))); 10553 // don't store invalid values 10554 for (VersionedPackage vp : captor.getValue().getDisallowedPackages()) { 10555 assertNotEquals("apples", vp.getPackageName()); 10556 } 10557 } 10558 10559 @Test 10560 public void testMigrateNotificationFilter_noPreexistingFilter() throws Exception { 10561 int[] userIds = new int[] {mUserId}; 10562 when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds); 10563 List<String> disallowedApps = ImmutableList.of("apples"); 10564 when(mPackageManager.getPackageUid("apples", 0, mUserId)) 10565 .thenReturn(1001); 10566 10567 when(mListeners.getNotificationListenerFilter(any())).thenReturn(null); 10568 10569 mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING, 10570 disallowedApps); 10571 10572 ArgumentCaptor<NotificationListenerFilter> captor = 10573 ArgumentCaptor.forClass(NotificationListenerFilter.class); 10574 verify(mListeners).setNotificationListenerFilter(any(), captor.capture()); 10575 10576 assertEquals(FLAG_FILTER_TYPE_ONGOING, captor.getValue().getTypes()); 10577 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001))); 10578 } 10579 10580 @Test 10581 public void testMigrateNotificationFilter_existingTypeFilter() throws Exception { 10582 int[] userIds = new int[] {mUserId}; 10583 when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds); 10584 List<String> disallowedApps = ImmutableList.of("apples"); 10585 when(mPackageManager.getPackageUid("apples", 0, mUserId)) 10586 .thenReturn(1001); 10587 10588 when(mListeners.getNotificationListenerFilter(any())).thenReturn( 10589 new NotificationListenerFilter(FLAG_FILTER_TYPE_CONVERSATIONS, new ArraySet<>())); 10590 10591 mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING, 10592 disallowedApps); 10593 10594 ArgumentCaptor<NotificationListenerFilter> captor = 10595 ArgumentCaptor.forClass(NotificationListenerFilter.class); 10596 verify(mListeners).setNotificationListenerFilter(any(), captor.capture()); 10597 10598 // type isn't saved but pkg list is 10599 assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS, captor.getValue().getTypes()); 10600 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001))); 10601 } 10602 10603 @Test 10604 public void testMigrateNotificationFilter_existingPkgFilter() throws Exception { 10605 int[] userIds = new int[] {mUserId}; 10606 when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds); 10607 List<String> disallowedApps = ImmutableList.of("apples"); 10608 when(mPackageManager.getPackageUid("apples", 0, mUserId)) 10609 .thenReturn(1001); 10610 10611 NotificationListenerFilter preexisting = new NotificationListenerFilter(); 10612 preexisting.addPackage(new VersionedPackage("test", 1002)); 10613 when(mListeners.getNotificationListenerFilter(any())).thenReturn(preexisting); 10614 10615 mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING, 10616 disallowedApps); 10617 10618 ArgumentCaptor<NotificationListenerFilter> captor = 10619 ArgumentCaptor.forClass(NotificationListenerFilter.class); 10620 verify(mListeners).setNotificationListenerFilter(any(), captor.capture()); 10621 10622 // type is saved but pkg list isn't 10623 assertEquals(FLAG_FILTER_TYPE_ONGOING, captor.getValue().getTypes()); 10624 assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001))); 10625 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("test", 1002))); 10626 } 10627 10628 @Test 10629 public void testGetNotificationChannelsBypassingDnd_blocked() throws RemoteException { 10630 mService.setPreferencesHelper(mPreferencesHelper); 10631 10632 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 10633 10634 assertThat(mBinderService.getNotificationChannelsBypassingDnd(PKG, mUid).getList()) 10635 .isEmpty(); 10636 verify(mPreferencesHelper, never()).getNotificationChannelsBypassingDnd(PKG, mUid); 10637 } 10638 10639 @Test 10640 public void testMatchesCallFilter_noPermissionShouldThrow() throws Exception { 10641 // set the testable NMS to not system uid/appid 10642 mService.isSystemUid = false; 10643 mService.isSystemAppId = false; 10644 10645 // make sure a caller without listener access or read_contacts permission can't call 10646 // matchesCallFilter. 10647 when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false); 10648 doThrow(new SecurityException()).when(mContext).enforceCallingPermission( 10649 eq("android.permission.READ_CONTACTS"), anyString()); 10650 10651 try { 10652 // shouldn't matter what we're passing in, if we get past this line fail immediately 10653 ((INotificationManager) mService.mService).matchesCallFilter(null); 10654 fail("call to matchesCallFilter with no permissions should fail"); 10655 } catch (SecurityException e) { 10656 // pass 10657 } 10658 } 10659 10660 @Test 10661 public void testMatchesCallFilter_hasSystemPermission() throws Exception { 10662 // set the testable NMS to system uid 10663 mService.isSystemUid = true; 10664 10665 // make sure caller doesn't have listener access or read_contacts permission 10666 when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false); 10667 doThrow(new SecurityException()).when(mContext).enforceCallingPermission( 10668 eq("android.permission.READ_CONTACTS"), anyString()); 10669 10670 try { 10671 ((INotificationManager) mService.mService).matchesCallFilter(null); 10672 // pass, but check that we actually checked for system permissions 10673 assertTrue(mService.countSystemChecks > 0); 10674 } catch (SecurityException e) { 10675 fail("call to matchesCallFilter with just system permissions should work"); 10676 } 10677 } 10678 10679 @Test 10680 public void testMatchesCallFilter_hasListenerPermission() throws Exception { 10681 mService.isSystemUid = false; 10682 mService.isSystemAppId = false; 10683 10684 // make sure a caller with only listener access and not read_contacts permission can call 10685 // matchesCallFilter. 10686 when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(true); 10687 doThrow(new SecurityException()).when(mContext).enforceCallingPermission( 10688 eq("android.permission.READ_CONTACTS"), anyString()); 10689 10690 try { 10691 ((INotificationManager) mService.mService).matchesCallFilter(null); 10692 // pass, this is not a functionality test 10693 } catch (SecurityException e) { 10694 fail("call to matchesCallFilter with listener permissions should work"); 10695 } 10696 } 10697 10698 @Test 10699 public void testMatchesCallFilter_hasContactsPermission() throws Exception { 10700 mService.isSystemUid = false; 10701 mService.isSystemAppId = false; 10702 10703 // make sure a caller with only read_contacts permission and not listener access can call 10704 // matchesCallFilter. 10705 when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false); 10706 doNothing().when(mContext).enforceCallingPermission( 10707 eq("android.permission.READ_CONTACTS"), anyString()); 10708 10709 try { 10710 ((INotificationManager) mService.mService).matchesCallFilter(null); 10711 // pass, this is not a functionality test 10712 } catch (SecurityException e) { 10713 fail("call to matchesCallFilter with listener permissions should work"); 10714 } 10715 } 10716 10717 @Test 10718 public void testMediaNotificationsBypassBlock() throws Exception { 10719 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10720 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); 10721 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10722 10723 Notification.Builder nb = new Notification.Builder( 10724 mContext, mTestNotificationChannel.getId()) 10725 .setContentTitle("foo") 10726 .setSmallIcon(android.R.drawable.sym_def_app_icon) 10727 .addAction(new Notification.Action.Builder(null, "test", null).build()); 10728 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10729 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10730 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10731 10732 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 10733 10734 // normal blocked notifications - blocked 10735 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10736 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse(); 10737 10738 // just using the style - blocked 10739 nb.setStyle(new Notification.MediaStyle()); 10740 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10741 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10742 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10743 10744 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10745 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse(); 10746 10747 // using the style, but incorrect type in session - blocked 10748 nb.setStyle(new Notification.MediaStyle()); 10749 Bundle extras = new Bundle(); 10750 extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent()); 10751 nb.addExtras(extras); 10752 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10753 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10754 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10755 10756 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10757 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse(); 10758 10759 // style + media session - bypasses block 10760 nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class))); 10761 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10762 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10763 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10764 10765 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10766 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 10767 } 10768 10769 @Test 10770 public void testMediaNotificationsBypassBlock_atPost() throws Exception { 10771 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 10772 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10773 10774 Notification.Builder nb = new Notification.Builder( 10775 mContext, mTestNotificationChannel.getId()) 10776 .setContentTitle("foo") 10777 .setSmallIcon(android.R.drawable.sym_def_app_icon) 10778 .addAction(new Notification.Action.Builder(null, "test", null).build()); 10779 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10780 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10781 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10782 10783 when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false); 10784 10785 mService.addEnqueuedNotification(r); 10786 NotificationManagerService.PostNotificationRunnable runnable = 10787 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 10788 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 10789 runnable.run(); 10790 waitForIdle(); 10791 10792 verify(mUsageStats).registerBlocked(any()); 10793 verify(mUsageStats, never()).registerPostedByApp(any()); 10794 10795 // just using the style - blocked 10796 mService.clearNotifications(); 10797 reset(mUsageStats); 10798 nb.setStyle(new Notification.MediaStyle()); 10799 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10800 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10801 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10802 10803 mService.addEnqueuedNotification(r); 10804 runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 10805 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 10806 runnable.run(); 10807 waitForIdle(); 10808 10809 verify(mUsageStats).registerBlocked(any()); 10810 verify(mUsageStats, never()).registerPostedByApp(any()); 10811 10812 // style + media session - bypasses block 10813 mService.clearNotifications(); 10814 reset(mUsageStats); 10815 nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class))); 10816 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10817 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10818 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10819 10820 mService.addEnqueuedNotification(r); 10821 runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 10822 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 10823 runnable.run(); 10824 waitForIdle(); 10825 10826 verify(mUsageStats, never()).registerBlocked(any()); 10827 verify(mUsageStats).registerPostedByApp(any()); 10828 } 10829 10830 @Test 10831 public void testCallNotificationsBypassBlock() throws Exception { 10832 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10833 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); 10834 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10835 10836 Notification.Builder nb = new Notification.Builder( 10837 mContext, mTestNotificationChannel.getId()) 10838 .setContentTitle("foo") 10839 .setSmallIcon(android.R.drawable.sym_def_app_icon) 10840 .addAction(new Notification.Action.Builder(null, "test", null).build()); 10841 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10842 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10843 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10844 10845 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 10846 10847 // normal blocked notifications - blocked 10848 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10849 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse(); 10850 10851 // just using the style - blocked 10852 Person person = new Person.Builder() 10853 .setName("caller") 10854 .build(); 10855 nb.setStyle(Notification.CallStyle.forOngoingCall( 10856 person, mock(PendingIntent.class))); 10857 nb.setFullScreenIntent(mock(PendingIntent.class), true); 10858 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10859 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10860 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10861 10862 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10863 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse(); 10864 10865 // style + managed call - bypasses block 10866 when(mTelecomManager.isInManagedCall()).thenReturn(true); 10867 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10868 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 10869 10870 // style + self managed call - bypasses block 10871 when(mTelecomManager.isInSelfManagedCall( 10872 r.getSbn().getPackageName(), r.getUser())).thenReturn(true); 10873 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10874 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 10875 10876 // set telecom manager to null - blocked 10877 mService.setTelecomManager(null); 10878 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10879 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)) 10880 .isFalse(); 10881 10882 // set telecom feature to false - blocked 10883 when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false); 10884 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10885 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)) 10886 .isFalse(); 10887 10888 // telecom manager is not ready - blocked 10889 mService.setTelecomManager(mTelecomManager); 10890 when(mTelecomManager.isInCall()).thenThrow(new IllegalStateException("not ready")); 10891 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10892 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)) 10893 .isFalse(); 10894 } 10895 10896 @Test 10897 public void testCallNotificationsBypassBlock_atPost() throws Exception { 10898 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 10899 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10900 10901 Notification.Builder nb = 10902 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 10903 .setContentTitle("foo") 10904 .setSmallIcon(android.R.drawable.sym_def_app_icon) 10905 .addAction(new Notification.Action.Builder(null, "test", null).build()); 10906 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10907 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10908 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10909 10910 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 10911 10912 // normal blocked notifications - blocked 10913 mService.addEnqueuedNotification(r); 10914 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10915 mPostNotificationTrackerFactory.newTracker(null)).run(); 10916 waitForIdle(); 10917 10918 verify(mUsageStats).registerBlocked(any()); 10919 verify(mUsageStats, never()).registerPostedByApp(any()); 10920 10921 // just using the style - blocked 10922 mService.clearNotifications(); 10923 reset(mUsageStats); 10924 Person person = new Person.Builder().setName("caller").build(); 10925 nb.setStyle(Notification.CallStyle.forOngoingCall(person, mock(PendingIntent.class))); 10926 nb.setFullScreenIntent(mock(PendingIntent.class), true); 10927 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, nb.build(), 10928 UserHandle.getUserHandleForUid(mUid), null, 0); 10929 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10930 10931 mService.addEnqueuedNotification(r); 10932 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10933 mPostNotificationTrackerFactory.newTracker(null)).run(); 10934 waitForIdle(); 10935 10936 verify(mUsageStats).registerBlocked(any()); 10937 verify(mUsageStats, never()).registerPostedByApp(any()); 10938 10939 // style + managed call - bypasses block 10940 mService.clearNotifications(); 10941 reset(mUsageStats); 10942 when(mTelecomManager.isInManagedCall()).thenReturn(true); 10943 10944 mService.addEnqueuedNotification(r); 10945 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10946 mPostNotificationTrackerFactory.newTracker(null)).run(); 10947 waitForIdle(); 10948 10949 verify(mUsageStats, never()).registerBlocked(any()); 10950 verify(mUsageStats).registerPostedByApp(any()); 10951 10952 // style + self managed call - bypasses block 10953 mService.clearNotifications(); 10954 reset(mUsageStats); 10955 when(mTelecomManager.isInSelfManagedCall(r.getSbn().getPackageName(), r.getUser())) 10956 .thenReturn(true); 10957 10958 mService.addEnqueuedNotification(r); 10959 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10960 mPostNotificationTrackerFactory.newTracker(null)).run(); 10961 waitForIdle(); 10962 10963 verify(mUsageStats, never()).registerBlocked(any()); 10964 verify(mUsageStats).registerPostedByApp(any()); 10965 10966 // set telecom manager to null - notifications should be blocked 10967 // but post notifications runnable should not crash 10968 mService.clearNotifications(); 10969 reset(mUsageStats); 10970 mService.setTelecomManager(null); 10971 10972 mService.addEnqueuedNotification(r); 10973 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10974 mPostNotificationTrackerFactory.newTracker(null)).run(); 10975 waitForIdle(); 10976 10977 verify(mUsageStats).registerBlocked(any()); 10978 verify(mUsageStats, never()).registerPostedByApp(any()); 10979 10980 // set FEATURE_TELECOM to false - notifications should be blocked 10981 // but post notifications runnable should not crash 10982 mService.setTelecomManager(mTelecomManager); 10983 when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false); 10984 reset(mUsageStats); 10985 mService.setTelecomManager(null); 10986 10987 mService.addEnqueuedNotification(r); 10988 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10989 mPostNotificationTrackerFactory.newTracker(null)).run(); 10990 waitForIdle(); 10991 10992 verify(mUsageStats).registerBlocked(any()); 10993 verify(mUsageStats, never()).registerPostedByApp(any()); 10994 10995 // telecom is not ready - notifications should be blocked but no crashes 10996 mService.setTelecomManager(mTelecomManager); 10997 when(mTelecomManager.isInCall()).thenThrow(new IllegalStateException("not ready")); 10998 reset(mUsageStats); 10999 11000 mService.addEnqueuedNotification(r); 11001 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 11002 mPostNotificationTrackerFactory.newTracker(null)).run(); 11003 waitForIdle(); 11004 11005 verify(mUsageStats).registerBlocked(any()); 11006 verify(mUsageStats, never()).registerPostedByApp(any()); 11007 } 11008 11009 @Test 11010 public void testGetAllUsersNotificationPermissions() { 11011 // In this case, there are multiple users each with notification permissions (and also, 11012 // for good measure, some without). 11013 // make sure the collection returned contains info for all of them 11014 final List<UserInfo> userInfos = new ArrayList<>(); 11015 userInfos.add(new UserInfo(0, "user0", 0)); 11016 userInfos.add(new UserInfo(1, "user1", 0)); 11017 userInfos.add(new UserInfo(2, "user2", 0)); 11018 when(mUm.getUsers()).thenReturn(userInfos); 11019 11020 // construct the permissions for each of them 11021 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> permissions0 = new ArrayMap<>(), 11022 permissions1 = new ArrayMap<>(); 11023 permissions0.put(new Pair<>(10, "package1"), new Pair<>(true, false)); 11024 permissions0.put(new Pair<>(20, "package2"), new Pair<>(false, true)); 11025 permissions1.put(new Pair<>(11, "package1"), new Pair<>(false, false)); 11026 permissions1.put(new Pair<>(21, "package2"), new Pair<>(true, true)); 11027 when(mPermissionHelper.getNotificationPermissionValues(0)).thenReturn(permissions0); 11028 when(mPermissionHelper.getNotificationPermissionValues(1)).thenReturn(permissions1); 11029 when(mPermissionHelper.getNotificationPermissionValues(2)).thenReturn(new ArrayMap<>()); 11030 11031 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> combinedPermissions = 11032 mService.getAllUsersNotificationPermissions(); 11033 assertTrue(combinedPermissions.get(new Pair<>(10, "package1")).first); 11034 assertFalse(combinedPermissions.get(new Pair<>(10, "package1")).second); 11035 assertFalse(combinedPermissions.get(new Pair<>(20, "package2")).first); 11036 assertTrue(combinedPermissions.get(new Pair<>(20, "package2")).second); 11037 assertFalse(combinedPermissions.get(new Pair<>(11, "package1")).first); 11038 assertFalse(combinedPermissions.get(new Pair<>(11, "package1")).second); 11039 assertTrue(combinedPermissions.get(new Pair<>(21, "package2")).first); 11040 assertTrue(combinedPermissions.get(new Pair<>(21, "package2")).second); 11041 } 11042 11043 @Test 11044 public void testGetActiveNotification_filtersUsers() throws Exception { 11045 when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0, 10}); 11046 11047 NotificationRecord nr0 = 11048 generateNotificationRecord(mTestNotificationChannel, 0); 11049 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag0", 11050 nr0.getSbn().getId(), nr0.getSbn().getNotification(), nr0.getSbn().getUserId()); 11051 11052 NotificationRecord nr10 = 11053 generateNotificationRecord(mTestNotificationChannel, 10); 11054 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag10", 11055 nr10.getSbn().getId(), nr10.getSbn().getNotification(), nr10.getSbn().getUserId()); 11056 11057 NotificationRecord nr11 = 11058 generateNotificationRecord(mTestNotificationChannel, 11); 11059 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag11", 11060 nr11.getSbn().getId(), nr11.getSbn().getNotification(), nr11.getSbn().getUserId()); 11061 waitForIdle(); 11062 11063 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 11064 assertEquals(2, notifs.length); 11065 for (StatusBarNotification sbn : notifs) { 11066 if (sbn.getUserId() == 11) { 11067 fail("leaked data across users"); 11068 } 11069 } 11070 } 11071 11072 @Test 11073 public void testUngroupingOngoingAutoSummary() throws Exception { 11074 NotificationRecord nr0 = 11075 generateNotificationRecord(mTestNotificationChannel, 0); 11076 NotificationRecord nr1 = 11077 generateNotificationRecord(mTestNotificationChannel, 0); 11078 nr1.getSbn().getNotification().flags |= FLAG_ONGOING_EVENT; 11079 11080 mService.addNotification(nr0); 11081 mService.addNotification(nr1); 11082 11083 // grouphelper is a mock here, so make the calls it would make 11084 11085 // add summary 11086 mService.addNotification(mService.createAutoGroupSummary(nr1.getUserId(), 11087 nr1.getSbn().getPackageName(), nr1.getKey(), 11088 GroupHelper.BASE_FLAGS | FLAG_ONGOING_EVENT)); 11089 11090 // cancel both children 11091 mBinderService.cancelNotificationWithTag(PKG, PKG, nr0.getSbn().getTag(), 11092 nr0.getSbn().getId(), nr0.getSbn().getUserId()); 11093 mBinderService.cancelNotificationWithTag(PKG, PKG, nr1.getSbn().getTag(), 11094 nr1.getSbn().getId(), nr1.getSbn().getUserId()); 11095 waitForIdle(); 11096 11097 // group helper would send 'remove summary' event 11098 mService.clearAutogroupSummaryLocked(nr1.getUserId(), nr1.getSbn().getPackageName()); 11099 waitForIdle(); 11100 11101 // make sure the summary was removed and not re-posted 11102 assertThat(mService.getNotificationRecordCount()).isEqualTo(0); 11103 } 11104 11105 @Test 11106 public void testUngroupingAutoSummary_differentUsers() throws Exception { 11107 NotificationRecord nr0 = 11108 generateNotificationRecord(mTestNotificationChannel, 0, USER_SYSTEM); 11109 NotificationRecord nr1 = 11110 generateNotificationRecord(mTestNotificationChannel, 1, USER_SYSTEM); 11111 11112 // add notifications + summary for USER_SYSTEM 11113 mService.addNotification(nr0); 11114 mService.addNotification(nr1); 11115 mService.addNotification(mService.createAutoGroupSummary(nr1.getUserId(), 11116 nr1.getSbn().getPackageName(), nr1.getKey(), GroupHelper.BASE_FLAGS)); 11117 11118 // add notifications + summary for USER_ALL 11119 NotificationRecord nr0_all = 11120 generateNotificationRecord(mTestNotificationChannel, 2, UserHandle.USER_ALL); 11121 NotificationRecord nr1_all = 11122 generateNotificationRecord(mTestNotificationChannel, 3, UserHandle.USER_ALL); 11123 11124 mService.addNotification(nr0_all); 11125 mService.addNotification(nr1_all); 11126 mService.addNotification(mService.createAutoGroupSummary(nr0_all.getUserId(), 11127 nr0_all.getSbn().getPackageName(), nr0_all.getKey(), GroupHelper.BASE_FLAGS)); 11128 11129 // cancel both children for USER_ALL 11130 mBinderService.cancelNotificationWithTag(PKG, PKG, nr0_all.getSbn().getTag(), 11131 nr0_all.getSbn().getId(), UserHandle.USER_ALL); 11132 mBinderService.cancelNotificationWithTag(PKG, PKG, nr1_all.getSbn().getTag(), 11133 nr1_all.getSbn().getId(), UserHandle.USER_ALL); 11134 waitForIdle(); 11135 11136 // group helper would send 'remove summary' event 11137 mService.clearAutogroupSummaryLocked(UserHandle.USER_ALL, 11138 nr0_all.getSbn().getPackageName()); 11139 waitForIdle(); 11140 11141 // make sure the right summary was removed 11142 assertThat(mService.getNotificationCount(nr0_all.getSbn().getPackageName(), 11143 UserHandle.USER_ALL, 0, null)).isEqualTo(0); 11144 11145 // the USER_SYSTEM notifications + summary were not removed 11146 assertThat(mService.getNotificationCount(nr0.getSbn().getPackageName(), 11147 USER_SYSTEM, 0, null)).isEqualTo(3); 11148 } 11149 11150 @Test 11151 public void testStrongAuthTracker_isInLockDownMode() { 11152 mStrongAuthTracker.setGetStrongAuthForUserReturnValue( 11153 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); 11154 mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId()); 11155 assertTrue(mStrongAuthTracker.isInLockDownMode(mContext.getUserId())); 11156 mStrongAuthTracker.setGetStrongAuthForUserReturnValue(mContext.getUserId()); 11157 mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId()); 11158 assertFalse(mStrongAuthTracker.isInLockDownMode(mContext.getUserId())); 11159 } 11160 11161 @Test 11162 public void testCancelAndPostNotificationsWhenEnterAndExitLockDownMode() { 11163 // post 2 notifications from 2 packages 11164 NotificationRecord pkgA = new NotificationRecord(mContext, 11165 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 11166 mService.addNotification(pkgA); 11167 NotificationRecord pkgB = new NotificationRecord(mContext, 11168 generateSbn("b", 1001, 9, 0), mTestNotificationChannel); 11169 mService.addNotification(pkgB); 11170 11171 // when entering the lockdown mode, cancel the 2 notifications. 11172 mStrongAuthTracker.setGetStrongAuthForUserReturnValue( 11173 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); 11174 mStrongAuthTracker.onStrongAuthRequiredChanged(0); 11175 assertTrue(mStrongAuthTracker.isInLockDownMode(0)); 11176 11177 // the notifyRemovedLocked function is called twice due to REASON_LOCKDOWN. 11178 ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class); 11179 verify(mListeners, times(2)).notifyRemovedLocked(any(), captor.capture(), any()); 11180 assertEquals(REASON_LOCKDOWN, captor.getValue().intValue()); 11181 11182 // exit lockdown mode. 11183 mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0); 11184 mStrongAuthTracker.onStrongAuthRequiredChanged(0); 11185 assertFalse(mStrongAuthTracker.isInLockDownMode(0)); 11186 11187 // the notifyPostedLocked function is called twice. 11188 verify(mWorkerHandler, times(2)).postDelayed(any(Runnable.class), anyLong()); 11189 //verify(mListeners, times(2)).notifyPostedLocked(any(), any()); 11190 } 11191 11192 @Test 11193 public void testMakeRankingUpdateLockedInLockDownMode() { 11194 // post 2 notifications from a same package 11195 NotificationRecord pkgA = new NotificationRecord(mContext, 11196 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 11197 mService.addNotification(pkgA); 11198 NotificationRecord pkgB = new NotificationRecord(mContext, 11199 generateSbn("a", 1000, 9, 1), mTestNotificationChannel); 11200 mService.addNotification(pkgB); 11201 11202 mService.setIsVisibleToListenerReturnValue(true); 11203 NotificationRankingUpdate nru = mService.makeRankingUpdateLocked(null); 11204 assertEquals(2, nru.getRankingMap().getOrderedKeys().length); 11205 11206 // when only user 0 entering the lockdown mode, its notification will be suppressed. 11207 mStrongAuthTracker.setGetStrongAuthForUserReturnValue( 11208 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); 11209 mStrongAuthTracker.onStrongAuthRequiredChanged(0); 11210 assertTrue(mStrongAuthTracker.isInLockDownMode(0)); 11211 assertFalse(mStrongAuthTracker.isInLockDownMode(1)); 11212 11213 nru = mService.makeRankingUpdateLocked(null); 11214 assertEquals(1, nru.getRankingMap().getOrderedKeys().length); 11215 11216 // User 0 exits lockdown mode. Its notification will be resumed. 11217 mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0); 11218 mStrongAuthTracker.onStrongAuthRequiredChanged(0); 11219 assertFalse(mStrongAuthTracker.isInLockDownMode(0)); 11220 assertFalse(mStrongAuthTracker.isInLockDownMode(1)); 11221 11222 nru = mService.makeRankingUpdateLocked(null); 11223 assertEquals(2, nru.getRankingMap().getOrderedKeys().length); 11224 } 11225 11226 @Test 11227 public void testMaybeShowReviewPermissionsNotification_flagOff() { 11228 mService.setShowReviewPermissionsNotification(false); 11229 reset(mMockNm); 11230 11231 // If state is SHOULD_SHOW, it would show, but not if the flag is off! 11232 Settings.Global.putInt(mContext.getContentResolver(), 11233 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11234 NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW); 11235 mService.maybeShowInitialReviewPermissionsNotification(); 11236 verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class)); 11237 } 11238 11239 @Test 11240 public void testMaybeShowReviewPermissionsNotification_unknown() { 11241 mService.setShowReviewPermissionsNotification(true); 11242 reset(mMockNm); 11243 11244 // Set up various possible states of the settings int and confirm whether or not the 11245 // notification is shown as expected 11246 11247 // Initial state: default/unknown setting, make sure nothing happens 11248 Settings.Global.putInt(mContext.getContentResolver(), 11249 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11250 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN); 11251 mService.maybeShowInitialReviewPermissionsNotification(); 11252 verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class)); 11253 } 11254 11255 @Test 11256 public void testMaybeShowReviewPermissionsNotification_shouldShow() { 11257 mService.setShowReviewPermissionsNotification(true); 11258 reset(mMockNm); 11259 11260 // If state is SHOULD_SHOW, it ... should show 11261 Settings.Global.putInt(mContext.getContentResolver(), 11262 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11263 NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW); 11264 mService.maybeShowInitialReviewPermissionsNotification(); 11265 verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG), 11266 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS), 11267 any(Notification.class)); 11268 } 11269 11270 @Test 11271 public void testMaybeShowReviewPermissionsNotification_alreadyShown() { 11272 mService.setShowReviewPermissionsNotification(true); 11273 reset(mMockNm); 11274 11275 // If state is either USER_INTERACTED or DISMISSED, we should not show this on boot 11276 Settings.Global.putInt(mContext.getContentResolver(), 11277 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11278 NotificationManagerService.REVIEW_NOTIF_STATE_USER_INTERACTED); 11279 mService.maybeShowInitialReviewPermissionsNotification(); 11280 11281 Settings.Global.putInt(mContext.getContentResolver(), 11282 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11283 NotificationManagerService.REVIEW_NOTIF_STATE_DISMISSED); 11284 mService.maybeShowInitialReviewPermissionsNotification(); 11285 11286 verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class)); 11287 } 11288 11289 @Test 11290 public void testMaybeShowReviewPermissionsNotification_reshown() { 11291 mService.setShowReviewPermissionsNotification(true); 11292 reset(mMockNm); 11293 11294 // If we have re-shown the notification and the user did not subsequently interacted with 11295 // it, then make sure we show when trying on boot 11296 Settings.Global.putInt(mContext.getContentResolver(), 11297 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11298 NotificationManagerService.REVIEW_NOTIF_STATE_RESHOWN); 11299 mService.maybeShowInitialReviewPermissionsNotification(); 11300 verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG), 11301 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS), 11302 any(Notification.class)); 11303 } 11304 11305 @Test 11306 public void testRescheduledReviewPermissionsNotification() { 11307 mService.setShowReviewPermissionsNotification(true); 11308 reset(mMockNm); 11309 11310 // when rescheduled, the notification goes through the NotificationManagerInternal service 11311 // this call doesn't need to know anything about previously scheduled state -- if called, 11312 // it should send the notification & write the appropriate int to Settings 11313 mInternalService.sendReviewPermissionsNotification(); 11314 11315 // Notification should be sent 11316 verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG), 11317 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS), 11318 any(Notification.class)); 11319 11320 // write STATE_RESHOWN to settings 11321 assertEquals(NotificationManagerService.REVIEW_NOTIF_STATE_RESHOWN, 11322 Settings.Global.getInt(mContext.getContentResolver(), 11323 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11324 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN)); 11325 } 11326 11327 @Test 11328 public void testRescheduledReviewPermissionsNotification_flagOff() { 11329 mService.setShowReviewPermissionsNotification(false); 11330 reset(mMockNm); 11331 11332 // no notification should be sent if the flag is off 11333 mInternalService.sendReviewPermissionsNotification(); 11334 verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class)); 11335 } 11336 11337 private void verifyStickyHun(Flag flag, int permissionState, boolean appRequested, 11338 boolean isSticky) throws Exception { 11339 11340 when(mPermissionHelper.hasRequestedPermission(Manifest.permission.USE_FULL_SCREEN_INTENT, 11341 PKG, mUserId)).thenReturn(appRequested); 11342 11343 mTestFlagResolver.setFlagOverride(flag, true); 11344 11345 when(mPermissionManager.checkPermissionForDataDelivery( 11346 eq(Manifest.permission.USE_FULL_SCREEN_INTENT), any(), any())) 11347 .thenReturn(permissionState); 11348 11349 Notification n = new Notification.Builder(mContext, "test") 11350 .setFullScreenIntent(mock(PendingIntent.class), true) 11351 .build(); 11352 11353 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11354 11355 final int stickyFlag = n.flags & Notification.FLAG_FSI_REQUESTED_BUT_DENIED; 11356 11357 if (isSticky) { 11358 assertNotSame(0, stickyFlag); 11359 } else { 11360 assertSame(0, stickyFlag); 11361 } 11362 } 11363 11364 @Test 11365 public void testFixNotification_flagEnableStickyHun_fsiPermissionHardDenied_showStickyHun() 11366 throws Exception { 11367 11368 verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, 11369 /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED, true, 11370 /* isSticky= */ true); 11371 } 11372 11373 @Test 11374 public void testFixNotification_flagEnableStickyHun_fsiPermissionSoftDenied_showStickyHun() 11375 throws Exception { 11376 11377 verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, 11378 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, true, 11379 /* isSticky= */ true); 11380 } 11381 11382 @Test 11383 public void testFixNotification_fsiPermissionSoftDenied_appNotRequest_noShowStickyHun() 11384 throws Exception { 11385 verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, 11386 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, false, 11387 /* isSticky= */ false); 11388 } 11389 11390 11391 @Test 11392 public void testFixNotification_flagEnableStickyHun_fsiPermissionGranted_showFsi() 11393 throws Exception { 11394 11395 verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, 11396 /* permissionState= */ PermissionManager.PERMISSION_GRANTED, true, 11397 /* isSticky= */ false); 11398 } 11399 11400 @Test 11401 public void testFixNotification_flagForceStickyHun_fsiPermissionHardDenied_showStickyHun() 11402 throws Exception { 11403 11404 verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, 11405 /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED, true, 11406 /* isSticky= */ true); 11407 } 11408 11409 @Test 11410 public void testFixNotification_flagForceStickyHun_fsiPermissionSoftDenied_showStickyHun() 11411 throws Exception { 11412 11413 verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, 11414 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, true, 11415 /* isSticky= */ true); 11416 } 11417 11418 @Test 11419 public void testFixNotification_flagForceStickyHun_fsiPermissionGranted_showStickyHun() 11420 throws Exception { 11421 11422 verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, 11423 /* permissionState= */ PermissionManager.PERMISSION_GRANTED, true, 11424 /* isSticky= */ true); 11425 } 11426 11427 @Test 11428 public void fixNotification_withFgsFlag_butIsNotFgs() throws Exception { 11429 final ApplicationInfo applicationInfo = new ApplicationInfo(); 11430 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 11431 .thenReturn(applicationInfo); 11432 11433 Notification n = new Notification.Builder(mContext, "test") 11434 .setFlag(FLAG_FOREGROUND_SERVICE, true) 11435 .setFlag(FLAG_CAN_COLORIZE, true) 11436 .build(); 11437 11438 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11439 11440 assertFalse(n.isForegroundService()); 11441 assertFalse(n.hasColorizedPermission()); 11442 } 11443 11444 @Test 11445 public void checkCallStyleNotification_withoutAnyValidUseCase_throws() throws Exception { 11446 Person person = new Person.Builder().setName("caller").build(); 11447 Notification n = new Notification.Builder(mContext, "test") 11448 .setStyle(Notification.CallStyle.forOngoingCall( 11449 person, mock(PendingIntent.class))) 11450 .build(); 11451 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11452 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11453 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11454 11455 try { 11456 mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11457 r.getSbn().getId(), r.getSbn().getTag(), r, false, false); 11458 assertFalse("CallStyle should not be allowed without a valid use case", true); 11459 } catch (IllegalArgumentException error) { 11460 assertThat(error.getMessage()).contains("CallStyle"); 11461 } 11462 } 11463 11464 @Test 11465 public void checkCallStyleNotification_allowedForFgs() throws Exception { 11466 Person person = new Person.Builder().setName("caller").build(); 11467 Notification n = new Notification.Builder(mContext, "test") 11468 .setFlag(FLAG_FOREGROUND_SERVICE, true) 11469 .setStyle(Notification.CallStyle.forOngoingCall( 11470 person, mock(PendingIntent.class))) 11471 .build(); 11472 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11473 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11474 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11475 11476 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11477 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 11478 } 11479 11480 @Test 11481 public void checkCallStyleNotification_allowedForByForegroundService() throws Exception { 11482 Person person = new Person.Builder().setName("caller").build(); 11483 Notification n = new Notification.Builder(mContext, "test") 11484 // Without FLAG_FOREGROUND_SERVICE. 11485 //.setFlag(FLAG_FOREGROUND_SERVICE, true) 11486 .setStyle(Notification.CallStyle.forOngoingCall( 11487 person, mock(PendingIntent.class))) 11488 .build(); 11489 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11490 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11491 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11492 11493 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11494 r.getSbn().getId(), r.getSbn().getTag(), r, false, 11495 true /* byForegroundService */)).isTrue(); 11496 } 11497 11498 @Test 11499 public void checkCallStyleNotification_allowedForUij() throws Exception { 11500 Person person = new Person.Builder().setName("caller").build(); 11501 Notification n = new Notification.Builder(mContext, "test") 11502 .setFlag(FLAG_USER_INITIATED_JOB, true) 11503 .setStyle(Notification.CallStyle.forOngoingCall( 11504 person, mock(PendingIntent.class))) 11505 .build(); 11506 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11507 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11508 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11509 11510 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11511 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 11512 } 11513 11514 @Test 11515 public void checkCallStyleNotification_allowedForFsiAllowed() throws Exception { 11516 Person person = new Person.Builder().setName("caller").build(); 11517 Notification n = new Notification.Builder(mContext, "test") 11518 .setFullScreenIntent(mock(PendingIntent.class), true) 11519 .setStyle(Notification.CallStyle.forOngoingCall( 11520 person, mock(PendingIntent.class))) 11521 .build(); 11522 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11523 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11524 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11525 11526 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11527 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 11528 } 11529 11530 @Test 11531 public void checkCallStyleNotification_allowedForFsiDenied() throws Exception { 11532 Person person = new Person.Builder().setName("caller").build(); 11533 Notification n = new Notification.Builder(mContext, "test") 11534 .setFlag(Notification.FLAG_FSI_REQUESTED_BUT_DENIED, true) 11535 .setStyle(Notification.CallStyle.forOngoingCall( 11536 person, mock(PendingIntent.class))) 11537 .build(); 11538 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11539 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11540 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11541 11542 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11543 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 11544 } 11545 11546 @Test 11547 public void fixSystemNotification_withOnGoingFlag_shouldBeDismissible() 11548 throws Exception { 11549 final ApplicationInfo ai = new ApplicationInfo(); 11550 ai.packageName = "pkg"; 11551 ai.uid = mUid; 11552 ai.flags |= ApplicationInfo.FLAG_SYSTEM; 11553 11554 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 11555 .thenReturn(ai); 11556 when(mAppOpsManager.checkOpNoThrow( 11557 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid, 11558 ai.packageName)).thenReturn(AppOpsManager.MODE_IGNORED); 11559 // Given: a notification from an app on the system partition has the flag 11560 // FLAG_ONGOING_EVENT set 11561 Notification n = new Notification.Builder(mContext, "test") 11562 .setOngoing(true) 11563 .build(); 11564 11565 // When: fix the notification with NotificationManagerService 11566 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11567 11568 // Then: the notification's flag FLAG_NO_DISMISS should not be set 11569 assertSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11570 } 11571 11572 @Test 11573 public void fixMediaNotification_withOnGoingFlag_shouldBeNonDismissible() 11574 throws Exception { 11575 // Given: a media notification has the flag FLAG_ONGOING_EVENT set 11576 Notification n = new Notification.Builder(mContext, "test") 11577 .setOngoing(true) 11578 .setStyle(new Notification.MediaStyle() 11579 .setMediaSession(mock(MediaSession.Token.class))) 11580 .build(); 11581 11582 // When: fix the notification with NotificationManagerService 11583 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11584 11585 // Then: the notification's flag FLAG_NO_DISMISS should be set 11586 assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11587 } 11588 11589 @Test 11590 public void fixSystemNotification_defaultSearchSelectior_withOnGoingFlag_nondismissible() 11591 throws Exception { 11592 final ApplicationInfo ai = new ApplicationInfo(); 11593 ai.packageName = SEARCH_SELECTOR_PKG; 11594 ai.uid = mUid; 11595 ai.flags |= ApplicationInfo.FLAG_SYSTEM; 11596 11597 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 11598 .thenReturn(ai); 11599 when(mAppOpsManager.checkOpNoThrow( 11600 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid, 11601 ai.packageName)).thenReturn(AppOpsManager.MODE_IGNORED); 11602 // Given: a notification from an app on the system partition has the flag 11603 // FLAG_ONGOING_EVENT set 11604 Notification n = new Notification.Builder(mContext, "test") 11605 .setOngoing(true) 11606 .build(); 11607 11608 // When: fix the notification with NotificationManagerService 11609 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11610 11611 // Then: the notification's flag FLAG_NO_DISMISS should be set 11612 assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11613 } 11614 11615 @Test 11616 public void fixCallNotification_withOnGoingFlag_shouldNotBeNonDismissible() 11617 throws Exception { 11618 // Given: a call notification has the flag FLAG_ONGOING_EVENT set 11619 Person person = new Person.Builder() 11620 .setName("caller") 11621 .build(); 11622 Notification n = new Notification.Builder(mContext, "test") 11623 .setOngoing(true) 11624 .setStyle(Notification.CallStyle.forOngoingCall( 11625 person, mock(PendingIntent.class))) 11626 .build(); 11627 11628 // When: fix the notification with NotificationManagerService 11629 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11630 11631 // Then: the notification's flag FLAG_NO_DISMISS should be set 11632 assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11633 } 11634 11635 11636 @Test 11637 public void fixNonExemptNotification_withOnGoingFlag_shouldBeDismissible() throws Exception { 11638 // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set 11639 Notification n = new Notification.Builder(mContext, "test") 11640 .setOngoing(true) 11641 .build(); 11642 11643 // When: fix the notification with NotificationManagerService 11644 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11645 11646 // Then: the notification's flag FLAG_NO_DISMISS should not be set 11647 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11648 } 11649 11650 @Test 11651 public void fixNonExemptNotification_withNoDismissFlag_shouldBeDismissible() 11652 throws Exception { 11653 // Given: a non-exempt notification has the flag FLAG_NO_DISMISS set (even though this is 11654 // not allowed) 11655 Notification n = new Notification.Builder(mContext, "test") 11656 .build(); 11657 n.flags |= Notification.FLAG_NO_DISMISS; 11658 11659 // When: fix the notification with NotificationManagerService 11660 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11661 11662 // Then: the notification's flag FLAG_NO_DISMISS should be cleared 11663 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11664 } 11665 11666 @Test 11667 public void fixMediaNotification_withoutOnGoingFlag_shouldBeDismissible() throws Exception { 11668 // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set 11669 Notification n = new Notification.Builder(mContext, "test") 11670 .setOngoing(false) 11671 .setStyle(new Notification.MediaStyle() 11672 .setMediaSession(mock(MediaSession.Token.class))) 11673 .build(); 11674 11675 // When: fix the notification with NotificationManagerService 11676 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11677 11678 // Then: the notification's flag FLAG_NO_DISMISS should not be set 11679 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11680 } 11681 11682 @Test 11683 public void fixMediaNotification_withoutOnGoingFlag_withNoDismissFlag_shouldBeDismissible() 11684 throws Exception { 11685 // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set, 11686 // but has the flag FLAG_NO_DISMISS set 11687 Notification n = new Notification.Builder(mContext, "test") 11688 .setOngoing(false) 11689 .setStyle(new Notification.MediaStyle() 11690 .setMediaSession(mock(MediaSession.Token.class))) 11691 .build(); 11692 n.flags |= Notification.FLAG_NO_DISMISS; 11693 11694 // When: fix the notification with NotificationManagerService 11695 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11696 11697 // Then: the notification's flag FLAG_NO_DISMISS should be cleared 11698 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11699 } 11700 11701 @Test 11702 public void fixNonExempt_Notification_withoutOnGoingFlag_shouldBeDismissible() 11703 throws Exception { 11704 // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set 11705 Notification n = new Notification.Builder(mContext, "test") 11706 .setOngoing(false) 11707 .build(); 11708 11709 // When: fix the notification with NotificationManagerService 11710 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11711 11712 // Then: the notification's flag FLAG_NO_DISMISS should not be set 11713 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11714 } 11715 11716 @Test 11717 public void fixOrganizationAdminNotification_withOnGoingFlag_shouldBeNonDismissible() 11718 throws Exception { 11719 when(mDevicePolicyManager.isActiveDeviceOwner(mUid)).thenReturn(true); 11720 // Given: a notification has the flag FLAG_ONGOING_EVENT set 11721 setDpmAppOppsExemptFromDismissal(false); 11722 Notification n = new Notification.Builder(mContext, "test") 11723 .setOngoing(true) 11724 .build(); 11725 11726 // When: fix the notification with NotificationManagerService 11727 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11728 11729 // Then: the notification's flag FLAG_NO_DISMISS should be set 11730 assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11731 } 11732 11733 @Test 11734 public void fixExemptAppOpNotification_withFlag_shouldBeNonDismissible() 11735 throws Exception { 11736 final ApplicationInfo ai = new ApplicationInfo(); 11737 ai.packageName = PKG; 11738 ai.uid = mUid; 11739 ai.flags |= ApplicationInfo.FLAG_SYSTEM; 11740 11741 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 11742 .thenReturn(ai); 11743 when(mAppOpsManager.checkOpNoThrow( 11744 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid, 11745 PKG)).thenReturn(AppOpsManager.MODE_ALLOWED); 11746 // Given: a notification has the flag FLAG_ONGOING_EVENT set 11747 setDpmAppOppsExemptFromDismissal(true); 11748 Notification n = new Notification.Builder(mContext, "test") 11749 .setOngoing(true) 11750 .build(); 11751 11752 // When: fix the notification with NotificationManagerService 11753 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11754 11755 // Then: the notification's flag FLAG_NO_DISMISS should be cleared 11756 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11757 } 11758 11759 @Test 11760 public void fixExemptAppOpNotification_withoutAppOpsFlag_shouldBeDismissible() 11761 throws Exception { 11762 when(mAppOpsManager.checkOpNoThrow( 11763 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid, 11764 PKG)).thenReturn(AppOpsManager.MODE_ALLOWED); 11765 // Given: a notification has the flag FLAG_ONGOING_EVENT set 11766 setDpmAppOppsExemptFromDismissal(false); 11767 Notification n = new Notification.Builder(mContext, "test") 11768 .setOngoing(true) 11769 .build(); 11770 11771 // When: fix the notification with NotificationManagerService 11772 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11773 11774 // Then: the notification's flag FLAG_NO_DISMISS should not be set 11775 assertSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11776 } 11777 11778 @Test 11779 public void testCancelAllNotifications_IgnoreUserInitiatedJob() throws Exception { 11780 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11781 .thenReturn(true); 11782 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 11783 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11784 mBinderService.enqueueNotificationWithTag(PKG, PKG, 11785 "testCancelAllNotifications_IgnoreUserInitiatedJob", 11786 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11787 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 11788 waitForIdle(); 11789 StatusBarNotification[] notifs = 11790 mBinderService.getActiveNotifications(sbn.getPackageName()); 11791 assertEquals(1, notifs.length); 11792 assertEquals(1, mService.getNotificationRecordCount()); 11793 } 11794 11795 @Test 11796 public void testCancelAllNotifications_UijFlag_NoUij_Allowed() throws Exception { 11797 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11798 .thenReturn(false); 11799 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 11800 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11801 mBinderService.enqueueNotificationWithTag(PKG, PKG, 11802 "testCancelAllNotifications_UijFlag_NoUij_Allowed", 11803 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11804 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 11805 waitForIdle(); 11806 StatusBarNotification[] notifs = 11807 mBinderService.getActiveNotifications(sbn.getPackageName()); 11808 assertEquals(0, notifs.length); 11809 } 11810 11811 @Test 11812 public void testCancelAllNotificationsOtherPackage_IgnoresUijNotification() throws Exception { 11813 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11814 .thenReturn(true); 11815 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 11816 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11817 mBinderService.enqueueNotificationWithTag(PKG, PKG, 11818 "testCancelAllNotifications_IgnoreOtherPackages", 11819 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11820 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId()); 11821 waitForIdle(); 11822 StatusBarNotification[] notifs = 11823 mBinderService.getActiveNotifications(sbn.getPackageName()); 11824 assertEquals(1, notifs.length); 11825 assertEquals(1, mService.getNotificationRecordCount()); 11826 } 11827 11828 @Test 11829 public void testRemoveUserInitiatedJobFlag_ImmediatelyAfterEnqueue() throws Exception { 11830 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11831 .thenReturn(true); 11832 Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId()) 11833 .setSmallIcon(android.R.drawable.sym_def_app_icon) 11834 .build(); 11835 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0, 11836 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11837 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11838 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 11839 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11840 mInternalService.removeUserInitiatedJobFlagFromNotification(PKG, sbn.getId(), 11841 sbn.getUserId()); 11842 waitForIdle(); 11843 StatusBarNotification[] notifs = 11844 mBinderService.getActiveNotifications(sbn.getPackageName()); 11845 assertFalse(notifs[0].getNotification().isUserInitiatedJob()); 11846 } 11847 11848 @Test 11849 public void testCancelAfterSecondEnqueueDoesNotSpecifyUserInitiatedJobFlag() throws Exception { 11850 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 11851 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT | FLAG_USER_INITIATED_JOB; 11852 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 11853 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11854 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT; 11855 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 11856 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11857 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), 11858 sbn.getUserId()); 11859 waitForIdle(); 11860 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 11861 assertEquals(0, mService.getNotificationRecordCount()); 11862 } 11863 11864 @Test 11865 public void testCancelNotificationWithTag_fromApp_cannotCancelUijChild() throws Exception { 11866 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11867 .thenReturn(true); 11868 mService.isSystemUid = false; 11869 mService.isSystemAppId = false; 11870 final NotificationRecord parent = generateNotificationRecord( 11871 mTestNotificationChannel, 1, "group", true); 11872 final NotificationRecord child = generateNotificationRecord( 11873 mTestNotificationChannel, 2, "group", false); 11874 final NotificationRecord child2 = generateNotificationRecord( 11875 mTestNotificationChannel, 3, "group", false); 11876 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11877 mService.addNotification(parent); 11878 mService.addNotification(child); 11879 mService.addNotification(child2); 11880 mService.getBinderService().cancelNotificationWithTag( 11881 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 11882 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 11883 waitForIdle(); 11884 StatusBarNotification[] notifs = 11885 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11886 assertEquals(1, notifs.length); 11887 } 11888 11889 @Test 11890 public void testCancelNotificationWithTag_fromApp_cannotCancelUijParent() throws Exception { 11891 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11892 .thenReturn(true); 11893 mService.isSystemUid = false; 11894 mService.isSystemAppId = false; 11895 final NotificationRecord parent = generateNotificationRecord( 11896 mTestNotificationChannel, 1, "group", true); 11897 parent.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11898 final NotificationRecord child = generateNotificationRecord( 11899 mTestNotificationChannel, 2, "group", false); 11900 final NotificationRecord child2 = generateNotificationRecord( 11901 mTestNotificationChannel, 3, "group", false); 11902 mService.addNotification(parent); 11903 mService.addNotification(child); 11904 mService.addNotification(child2); 11905 mService.getBinderService().cancelNotificationWithTag( 11906 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 11907 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 11908 waitForIdle(); 11909 StatusBarNotification[] notifs = 11910 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11911 assertEquals(3, notifs.length); 11912 } 11913 11914 @Test 11915 public void testCancelAllNotificationsFromApp_cannotCancelUijChild() throws Exception { 11916 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11917 .thenReturn(true); 11918 mService.isSystemUid = false; 11919 mService.isSystemAppId = false; 11920 final NotificationRecord parent = generateNotificationRecord( 11921 mTestNotificationChannel, 1, "group", true); 11922 final NotificationRecord child = generateNotificationRecord( 11923 mTestNotificationChannel, 2, "group", false); 11924 final NotificationRecord child2 = generateNotificationRecord( 11925 mTestNotificationChannel, 3, "group", false); 11926 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11927 final NotificationRecord newGroup = generateNotificationRecord( 11928 mTestNotificationChannel, 4, "group2", false); 11929 mService.addNotification(parent); 11930 mService.addNotification(child); 11931 mService.addNotification(child2); 11932 mService.addNotification(newGroup); 11933 mService.getBinderService().cancelAllNotifications( 11934 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 11935 waitForIdle(); 11936 StatusBarNotification[] notifs = 11937 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11938 assertEquals(1, notifs.length); 11939 } 11940 11941 @Test 11942 public void testCancelAllNotifications_fromApp_cannotCancelUijParent() throws Exception { 11943 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11944 .thenReturn(true); 11945 mService.isSystemUid = false; 11946 mService.isSystemAppId = false; 11947 final NotificationRecord parent = generateNotificationRecord( 11948 mTestNotificationChannel, 1, "group", true); 11949 parent.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11950 final NotificationRecord child = generateNotificationRecord( 11951 mTestNotificationChannel, 2, "group", false); 11952 final NotificationRecord child2 = generateNotificationRecord( 11953 mTestNotificationChannel, 3, "group", false); 11954 final NotificationRecord newGroup = generateNotificationRecord( 11955 mTestNotificationChannel, 4, "group2", false); 11956 mService.addNotification(parent); 11957 mService.addNotification(child); 11958 mService.addNotification(child2); 11959 mService.addNotification(newGroup); 11960 mService.getBinderService().cancelAllNotifications( 11961 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 11962 waitForIdle(); 11963 StatusBarNotification[] notifs = 11964 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11965 assertEquals(1, notifs.length); 11966 } 11967 11968 @Test 11969 public void testCancelNotificationsFromListener_clearAll_GroupWithUijParent() throws Exception { 11970 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11971 .thenReturn(true); 11972 final NotificationRecord parent = generateNotificationRecord( 11973 mTestNotificationChannel, 1, "group", true); 11974 parent.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11975 final NotificationRecord child = generateNotificationRecord( 11976 mTestNotificationChannel, 2, "group", false); 11977 final NotificationRecord child2 = generateNotificationRecord( 11978 mTestNotificationChannel, 3, "group", false); 11979 final NotificationRecord newGroup = generateNotificationRecord( 11980 mTestNotificationChannel, 4, "group2", false); 11981 mService.addNotification(parent); 11982 mService.addNotification(child); 11983 mService.addNotification(child2); 11984 mService.addNotification(newGroup); 11985 mService.getBinderService().cancelNotificationsFromListener(null, null); 11986 waitForIdle(); 11987 StatusBarNotification[] notifs = 11988 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11989 assertEquals(0, notifs.length); 11990 } 11991 11992 @Test 11993 public void testCancelNotificationsFromListener_clearAll_GroupWithUijChild() throws Exception { 11994 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11995 .thenReturn(true); 11996 final NotificationRecord parent = generateNotificationRecord( 11997 mTestNotificationChannel, 1, "group", true); 11998 final NotificationRecord child = generateNotificationRecord( 11999 mTestNotificationChannel, 2, "group", false); 12000 final NotificationRecord child2 = generateNotificationRecord( 12001 mTestNotificationChannel, 3, "group", false); 12002 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12003 final NotificationRecord newGroup = generateNotificationRecord( 12004 mTestNotificationChannel, 4, "group2", false); 12005 mService.addNotification(parent); 12006 mService.addNotification(child); 12007 mService.addNotification(child2); 12008 mService.addNotification(newGroup); 12009 mService.getBinderService().cancelNotificationsFromListener(null, null); 12010 waitForIdle(); 12011 StatusBarNotification[] notifs = 12012 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 12013 assertEquals(0, notifs.length); 12014 } 12015 12016 @Test 12017 public void testCancelNotificationsFromListener_clearAll_Uij() throws Exception { 12018 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12019 .thenReturn(true); 12020 final NotificationRecord child2 = generateNotificationRecord( 12021 mTestNotificationChannel, 3, null, false); 12022 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12023 mService.addNotification(child2); 12024 mService.getBinderService().cancelNotificationsFromListener(null, null); 12025 waitForIdle(); 12026 StatusBarNotification[] notifs = 12027 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 12028 assertEquals(0, notifs.length); 12029 } 12030 12031 @Test 12032 public void testCancelNotificationsFromListener_byKey_GroupWithUijParent() throws Exception { 12033 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12034 .thenReturn(true); 12035 final NotificationRecord parent = generateNotificationRecord( 12036 mTestNotificationChannel, 1, "group", true); 12037 parent.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12038 final NotificationRecord child = generateNotificationRecord( 12039 mTestNotificationChannel, 2, "group", false); 12040 final NotificationRecord child2 = generateNotificationRecord( 12041 mTestNotificationChannel, 3, "group", false); 12042 final NotificationRecord newGroup = generateNotificationRecord( 12043 mTestNotificationChannel, 4, "group2", false); 12044 mService.addNotification(parent); 12045 mService.addNotification(child); 12046 mService.addNotification(child2); 12047 mService.addNotification(newGroup); 12048 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 12049 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 12050 mService.getBinderService().cancelNotificationsFromListener(null, keys); 12051 waitForIdle(); 12052 StatusBarNotification[] notifs = 12053 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 12054 assertEquals(0, notifs.length); 12055 } 12056 12057 @Test 12058 public void testCancelNotificationsFromListener_byKey_GroupWithUijChild() throws Exception { 12059 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12060 .thenReturn(true); 12061 final NotificationRecord parent = generateNotificationRecord( 12062 mTestNotificationChannel, 1, "group", true); 12063 final NotificationRecord child = generateNotificationRecord( 12064 mTestNotificationChannel, 2, "group", false); 12065 final NotificationRecord child2 = generateNotificationRecord( 12066 mTestNotificationChannel, 3, "group", false); 12067 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12068 final NotificationRecord newGroup = generateNotificationRecord( 12069 mTestNotificationChannel, 4, "group2", false); 12070 mService.addNotification(parent); 12071 mService.addNotification(child); 12072 mService.addNotification(child2); 12073 mService.addNotification(newGroup); 12074 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 12075 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 12076 mService.getBinderService().cancelNotificationsFromListener(null, keys); 12077 waitForIdle(); 12078 StatusBarNotification[] notifs = 12079 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 12080 assertEquals(0, notifs.length); 12081 } 12082 12083 @Test 12084 public void testCancelNotificationsFromListener_byKey_Uij() throws Exception { 12085 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12086 .thenReturn(true); 12087 final NotificationRecord child = generateNotificationRecord( 12088 mTestNotificationChannel, 3, null, false); 12089 child.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12090 mService.addNotification(child); 12091 String[] keys = {child.getSbn().getKey()}; 12092 mService.getBinderService().cancelNotificationsFromListener(null, keys); 12093 waitForIdle(); 12094 StatusBarNotification[] notifs = 12095 mBinderService.getActiveNotifications(child.getSbn().getPackageName()); 12096 assertEquals(0, notifs.length); 12097 } 12098 12099 @Test 12100 public void testUserInitiatedCancelAllWithGroup_UserInitiatedFlag() throws Exception { 12101 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12102 .thenReturn(true); 12103 final NotificationRecord parent = generateNotificationRecord( 12104 mTestNotificationChannel, 1, "group", true); 12105 final NotificationRecord child = generateNotificationRecord( 12106 mTestNotificationChannel, 2, "group", false); 12107 final NotificationRecord child2 = generateNotificationRecord( 12108 mTestNotificationChannel, 3, "group", false); 12109 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12110 final NotificationRecord newGroup = generateNotificationRecord( 12111 mTestNotificationChannel, 4, "group2", false); 12112 mService.addNotification(parent); 12113 mService.addNotification(child); 12114 mService.addNotification(child2); 12115 mService.addNotification(newGroup); 12116 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), parent.getUserId()); 12117 waitForIdle(); 12118 StatusBarNotification[] notifs = 12119 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 12120 assertEquals(0, notifs.length); 12121 } 12122 12123 @Test 12124 public void testDeleteChannelGroupChecksForUijs() throws Exception { 12125 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 12126 .thenReturn(singletonList(mock(AssociationInfo.class))); 12127 CountDownLatch latch = new CountDownLatch(2); 12128 mService.createNotificationChannelGroup(PKG, mUid, 12129 new NotificationChannelGroup("group", "group"), true, false); 12130 new Thread(() -> { 12131 NotificationChannel notificationChannel = new NotificationChannel("id", "id", 12132 NotificationManager.IMPORTANCE_HIGH); 12133 notificationChannel.setGroup("group"); 12134 ParceledListSlice<NotificationChannel> pls = 12135 new ParceledListSlice(ImmutableList.of(notificationChannel)); 12136 try { 12137 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); 12138 } catch (RemoteException e) { 12139 throw new RuntimeException(e); 12140 } 12141 latch.countDown(); 12142 }).start(); 12143 new Thread(() -> { 12144 try { 12145 synchronized (this) { 12146 wait(5000); 12147 } 12148 mService.createNotificationChannelGroup(PKG, mUid, 12149 new NotificationChannelGroup("new", "new group"), true, false); 12150 NotificationChannel notificationChannel = 12151 new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH); 12152 notificationChannel.setGroup("new"); 12153 ParceledListSlice<NotificationChannel> pls = 12154 new ParceledListSlice(ImmutableList.of(notificationChannel)); 12155 try { 12156 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); 12157 mBinderService.deleteNotificationChannelGroup(PKG, "group"); 12158 } catch (RemoteException e) { 12159 throw new RuntimeException(e); 12160 } 12161 } catch (Exception e) { 12162 e.printStackTrace(); 12163 } 12164 latch.countDown(); 12165 }).start(); 12166 12167 latch.await(); 12168 verify(mJsi).isNotificationChannelAssociatedWithAnyUserInitiatedJobs( 12169 anyString(), anyInt(), anyString()); 12170 } 12171 12172 @Test 12173 public void testRemoveUserInitiatedJobFlagFromNotification_enqueued() { 12174 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12175 .thenReturn(true); 12176 Notification n = new Notification.Builder(mContext, "").build(); 12177 n.flags |= FLAG_USER_INITIATED_JOB; 12178 12179 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 12180 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12181 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12182 12183 mService.addEnqueuedNotification(r); 12184 12185 mInternalService.removeUserInitiatedJobFlagFromNotification( 12186 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 12187 12188 waitForIdle(); 12189 12190 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any()); 12191 } 12192 12193 @Test 12194 public void testRemoveUserInitiatedJobFlagFromNotification_posted() { 12195 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12196 .thenReturn(true); 12197 Notification n = new Notification.Builder(mContext, "").build(); 12198 n.flags |= FLAG_USER_INITIATED_JOB; 12199 12200 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 12201 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12202 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12203 12204 mService.addNotification(r); 12205 12206 mInternalService.removeUserInitiatedJobFlagFromNotification( 12207 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 12208 12209 waitForIdle(); 12210 12211 ArgumentCaptor<NotificationRecord> captor = 12212 ArgumentCaptor.forClass(NotificationRecord.class); 12213 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any()); 12214 12215 assertEquals(0, captor.getValue().getNotification().flags); 12216 } 12217 12218 @Test 12219 public void testCannotRemoveUserInitiatedJobFlagWhenOverLimit_enqueued() { 12220 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 12221 Notification n = new Notification.Builder(mContext, "").build(); 12222 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0, 12223 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12224 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12225 mService.addEnqueuedNotification(r); 12226 } 12227 Notification n = new Notification.Builder(mContext, "").build(); 12228 n.flags |= FLAG_USER_INITIATED_JOB; 12229 12230 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 12231 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0, 12232 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12233 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12234 12235 mService.addEnqueuedNotification(r); 12236 12237 mInternalService.removeUserInitiatedJobFlagFromNotification( 12238 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 12239 12240 waitForIdle(); 12241 12242 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, 12243 mService.getNotificationRecordCount()); 12244 } 12245 12246 @Test 12247 public void testCannotRemoveUserInitiatedJobFlagWhenOverLimit_posted() { 12248 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12249 .thenReturn(true); 12250 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 12251 Notification n = new Notification.Builder(mContext, "").build(); 12252 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0, 12253 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12254 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12255 mService.addNotification(r); 12256 } 12257 Notification n = new Notification.Builder(mContext, "").build(); 12258 n.flags |= FLAG_USER_INITIATED_JOB; 12259 12260 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 12261 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0, 12262 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12263 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12264 12265 mService.addNotification(r); 12266 12267 mInternalService.removeUserInitiatedJobFlagFromNotification( 12268 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 12269 12270 waitForIdle(); 12271 12272 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, 12273 mService.getNotificationRecordCount()); 12274 } 12275 12276 @Test 12277 public void testCanPostUijWhenOverLimit() throws RemoteException { 12278 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12279 .thenReturn(true); 12280 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 12281 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 12282 i, null, false).getSbn(); 12283 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testCanPostUijWhenOverLimit", 12284 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 12285 } 12286 12287 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 12288 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12289 mBinderService.enqueueNotificationWithTag(PKG, PKG, 12290 "testCanPostUijWhenOverLimit - uij over limit!", 12291 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 12292 12293 waitForIdle(); 12294 12295 StatusBarNotification[] notifs = 12296 mBinderService.getActiveNotifications(sbn.getPackageName()); 12297 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); 12298 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, 12299 mService.getNotificationRecordCount()); 12300 } 12301 12302 @Test 12303 public void testCannotPostNonUijWhenOverLimit() throws RemoteException { 12304 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12305 .thenReturn(true); 12306 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 12307 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 12308 i, null, false).getSbn(); 12309 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testCannotPostNonUijWhenOverLimit", 12310 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 12311 waitForIdle(); 12312 } 12313 12314 final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 12315 100, null, false).getSbn(); 12316 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12317 mBinderService.enqueueNotificationWithTag(PKG, PKG, 12318 "testCannotPostNonUijWhenOverLimit - uij over limit!", 12319 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 12320 12321 final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel, 12322 101, null, false).getSbn(); 12323 mBinderService.enqueueNotificationWithTag(PKG, PKG, 12324 "testCannotPostNonUijWhenOverLimit - non uij over limit!", 12325 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId()); 12326 12327 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12328 .thenReturn(false); 12329 final StatusBarNotification sbn3 = generateNotificationRecord(mTestNotificationChannel, 12330 101, null, false).getSbn(); 12331 sbn3.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12332 mBinderService.enqueueNotificationWithTag(PKG, PKG, 12333 "testCannotPostNonUijWhenOverLimit - fake uij over limit!", 12334 sbn3.getId(), sbn3.getNotification(), sbn3.getUserId()); 12335 12336 waitForIdle(); 12337 12338 StatusBarNotification[] notifs = 12339 mBinderService.getActiveNotifications(sbn.getPackageName()); 12340 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); 12341 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, 12342 mService.getNotificationRecordCount()); 12343 } 12344 12345 @Test 12346 public void fixNotification_withUijFlag_butIsNotUij() throws Exception { 12347 final ApplicationInfo applicationInfo = new ApplicationInfo(); 12348 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 12349 .thenReturn(applicationInfo); 12350 12351 Notification n = new Notification.Builder(mContext, "test") 12352 .setFlag(FLAG_USER_INITIATED_JOB, true) 12353 .build(); 12354 12355 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 12356 assertFalse(n.isUserInitiatedJob()); 12357 } 12358 12359 @Test 12360 public void enqueue_updatesEnqueueRate() throws Exception { 12361 Notification n = generateNotificationRecord(null).getNotification(); 12362 12363 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId); 12364 // Don't waitForIdle() here. We want to verify the "intermediate" state. 12365 12366 verify(mUsageStats).registerEnqueuedByApp(eq(PKG)); 12367 verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG)); 12368 verify(mUsageStats, never()).registerPostedByApp(any()); 12369 12370 waitForIdle(); 12371 } 12372 12373 @Test 12374 public void enqueue_withPost_updatesEnqueueRateAndPost() throws Exception { 12375 Notification n = generateNotificationRecord(null).getNotification(); 12376 12377 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId); 12378 waitForIdle(); 12379 12380 verify(mUsageStats).registerEnqueuedByApp(eq(PKG)); 12381 verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG)); 12382 verify(mUsageStats).registerPostedByApp(any()); 12383 } 12384 12385 @Test 12386 public void enqueueNew_whenOverEnqueueRate_accepts() throws Exception { 12387 Notification n = generateNotificationRecord(null).getNotification(); 12388 when(mUsageStats.getAppEnqueueRate(eq(PKG))) 12389 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE + 1f); 12390 12391 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId); 12392 waitForIdle(); 12393 12394 assertThat(mService.mNotificationsByKey).hasSize(1); 12395 verify(mUsageStats).registerEnqueuedByApp(eq(PKG)); 12396 verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG)); 12397 verify(mUsageStats).registerPostedByApp(any()); 12398 } 12399 12400 @Test 12401 public void enqueueUpdate_whenBelowMaxEnqueueRate_accepts() throws Exception { 12402 // Post the first version. 12403 Notification original = generateNotificationRecord(null).getNotification(); 12404 original.when = 111; 12405 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, original, mUserId); 12406 waitForIdle(); 12407 assertThat(mService.mNotificationList).hasSize(1); 12408 assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111); 12409 12410 reset(mUsageStats); 12411 when(mUsageStats.getAppEnqueueRate(eq(PKG))) 12412 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE - 1f); 12413 12414 // Post the update. 12415 Notification update = generateNotificationRecord(null).getNotification(); 12416 update.when = 222; 12417 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, update, mUserId); 12418 waitForIdle(); 12419 12420 verify(mUsageStats).registerEnqueuedByApp(eq(PKG)); 12421 verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG)); 12422 verify(mUsageStats, never()).registerPostedByApp(any()); 12423 verify(mUsageStats).registerUpdatedByApp(any(), any()); 12424 assertThat(mService.mNotificationList).hasSize(1); 12425 assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(222); 12426 } 12427 12428 @Test 12429 public void enqueueUpdate_whenAboveMaxEnqueueRate_rejects() throws Exception { 12430 // Post the first version. 12431 Notification original = generateNotificationRecord(null).getNotification(); 12432 original.when = 111; 12433 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, original, mUserId); 12434 waitForIdle(); 12435 assertThat(mService.mNotificationList).hasSize(1); 12436 assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111); 12437 12438 reset(mUsageStats); 12439 when(mUsageStats.getAppEnqueueRate(eq(PKG))) 12440 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE + 1f); 12441 12442 // Post the update. 12443 Notification update = generateNotificationRecord(null).getNotification(); 12444 update.when = 222; 12445 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, update, mUserId); 12446 waitForIdle(); 12447 12448 verify(mUsageStats).registerEnqueuedByApp(eq(PKG)); 12449 verify(mUsageStats, never()).registerEnqueuedByAppAndAccepted(any()); 12450 verify(mUsageStats, never()).registerPostedByApp(any()); 12451 verify(mUsageStats, never()).registerUpdatedByApp(any(), any()); 12452 assertThat(mService.mNotificationList).hasSize(1); 12453 assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111); // old 12454 } 12455 12456 @Test 12457 public void enqueueNotification_allowlistsPendingIntents() throws RemoteException { 12458 PendingIntent contentIntent = createPendingIntent("content"); 12459 PendingIntent actionIntent1 = createPendingIntent("action1"); 12460 PendingIntent actionIntent2 = createPendingIntent("action2"); 12461 Notification n = new Notification.Builder(mContext, TEST_CHANNEL_ID) 12462 .setContentIntent(contentIntent) 12463 .addAction(new Notification.Action.Builder(null, "action1", actionIntent1).build()) 12464 .addAction(new Notification.Action.Builder(null, "action2", actionIntent2).build()) 12465 .build(); 12466 12467 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1, 12468 parcelAndUnparcel(n, Notification.CREATOR), mUserId); 12469 12470 verify(mAmi, times(3)).setPendingIntentAllowlistDuration( 12471 any(), any(), anyLong(), 12472 eq(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED), 12473 eq(REASON_NOTIFICATION_SERVICE), any()); 12474 verify(mAmi, times(3)).setPendingIntentAllowBgActivityStarts(any(), 12475 any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER)); 12476 } 12477 12478 @Test 12479 public void enqueueNotification_allowlistsPendingIntents_includingFromPublicVersion() 12480 throws RemoteException { 12481 PendingIntent contentIntent = createPendingIntent("content"); 12482 PendingIntent actionIntent = createPendingIntent("action"); 12483 PendingIntent publicContentIntent = createPendingIntent("publicContent"); 12484 PendingIntent publicActionIntent = createPendingIntent("publicAction"); 12485 Notification source = new Notification.Builder(mContext, TEST_CHANNEL_ID) 12486 .setContentIntent(contentIntent) 12487 .addAction(new Notification.Action.Builder(null, "action", actionIntent).build()) 12488 .setPublicVersion(new Notification.Builder(mContext, "channel") 12489 .setContentIntent(publicContentIntent) 12490 .addAction(new Notification.Action.Builder( 12491 null, "publicAction", publicActionIntent).build()) 12492 .build()) 12493 .build(); 12494 12495 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1, 12496 parcelAndUnparcel(source, Notification.CREATOR), mUserId); 12497 12498 verify(mAmi, times(4)).setPendingIntentAllowlistDuration( 12499 any(), any(), anyLong(), 12500 eq(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED), 12501 eq(REASON_NOTIFICATION_SERVICE), any()); 12502 verify(mAmi, times(4)).setPendingIntentAllowBgActivityStarts(any(), 12503 any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER)); 12504 } 12505 12506 @Test 12507 public void onUserSwitched_updatesZenModeAndChannelsBypassingDnd() { 12508 Intent intent = new Intent(Intent.ACTION_USER_SWITCHED); 12509 intent.putExtra(Intent.EXTRA_USER_HANDLE, 20); 12510 mService.mZenModeHelper = mock(ZenModeHelper.class); 12511 mService.setPreferencesHelper(mPreferencesHelper); 12512 12513 mUserSwitchIntentReceiver.onReceive(mContext, intent); 12514 12515 InOrder inOrder = inOrder(mPreferencesHelper, mService.mZenModeHelper); 12516 inOrder.verify(mService.mZenModeHelper).onUserSwitched(eq(20)); 12517 inOrder.verify(mPreferencesHelper).syncChannelsBypassingDnd(); 12518 inOrder.verifyNoMoreInteractions(); 12519 } 12520 12521 @Test 12522 public void isNotificationPolicyAccessGranted_invalidPackage() throws Exception { 12523 final String notReal = "NOT REAL"; 12524 final var checker = mService.permissionChecker; 12525 12526 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow( 12527 PackageManager.NameNotFoundException.class); 12528 12529 assertThat(mBinderService.isNotificationPolicyAccessGranted(notReal)).isFalse(); 12530 verify(mPackageManagerClient).getPackageUidAsUser(eq(notReal), anyInt()); 12531 verify(checker, never()).check(any(), anyInt(), anyInt(), anyBoolean()); 12532 verify(mConditionProviders, never()).isPackageOrComponentAllowed(eq(notReal), anyInt()); 12533 verify(mListeners, never()).isComponentEnabledForPackage(any()); 12534 verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt()); 12535 } 12536 12537 @Test 12538 public void isNotificationPolicyAccessGranted_hasPermission() throws Exception { 12539 final String packageName = "target"; 12540 final int uid = 123; 12541 final var checker = mService.permissionChecker; 12542 12543 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12544 when(checker.check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true)) 12545 .thenReturn(PackageManager.PERMISSION_GRANTED); 12546 12547 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue(); 12548 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12549 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12550 verify(mConditionProviders, never()).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12551 verify(mListeners, never()).isComponentEnabledForPackage(any()); 12552 verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt()); 12553 } 12554 12555 @Test 12556 public void isNotificationPolicyAccessGranted_isPackageAllowed() throws Exception { 12557 final String packageName = "target"; 12558 final int uid = 123; 12559 final var checker = mService.permissionChecker; 12560 12561 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12562 when(mConditionProviders.isPackageOrComponentAllowed(eq(packageName), anyInt())) 12563 .thenReturn(true); 12564 12565 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue(); 12566 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12567 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12568 verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12569 verify(mListeners, never()).isComponentEnabledForPackage(any()); 12570 verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt()); 12571 } 12572 12573 @Test 12574 public void isNotificationPolicyAccessGranted_isComponentEnabled() throws Exception { 12575 final String packageName = "target"; 12576 final int uid = 123; 12577 final var checker = mService.permissionChecker; 12578 12579 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12580 when(mListeners.isComponentEnabledForPackage(packageName)).thenReturn(true); 12581 12582 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue(); 12583 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12584 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12585 verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12586 verify(mListeners).isComponentEnabledForPackage(packageName); 12587 verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt()); 12588 } 12589 12590 @Test 12591 public void isNotificationPolicyAccessGranted_isDeviceOwner() throws Exception { 12592 final String packageName = "target"; 12593 final int uid = 123; 12594 final var checker = mService.permissionChecker; 12595 12596 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12597 when(mDevicePolicyManager.isActiveDeviceOwner(uid)).thenReturn(true); 12598 12599 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue(); 12600 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12601 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12602 verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12603 verify(mListeners).isComponentEnabledForPackage(packageName); 12604 verify(mDevicePolicyManager).isActiveDeviceOwner(uid); 12605 } 12606 12607 /** 12608 * b/292163859 12609 */ 12610 @Test 12611 public void isNotificationPolicyAccessGranted_callerIsDeviceOwner() throws Exception { 12612 final String packageName = "target"; 12613 final int uid = 123; 12614 final int callingUid = Binder.getCallingUid(); 12615 final var checker = mService.permissionChecker; 12616 12617 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12618 when(mDevicePolicyManager.isActiveDeviceOwner(callingUid)).thenReturn(true); 12619 12620 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isFalse(); 12621 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12622 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12623 verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12624 verify(mListeners).isComponentEnabledForPackage(packageName); 12625 verify(mDevicePolicyManager).isActiveDeviceOwner(uid); 12626 verify(mDevicePolicyManager, never()).isActiveDeviceOwner(callingUid); 12627 } 12628 12629 @Test 12630 public void isNotificationPolicyAccessGranted_notGranted() throws Exception { 12631 final String packageName = "target"; 12632 final int uid = 123; 12633 final var checker = mService.permissionChecker; 12634 12635 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12636 12637 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isFalse(); 12638 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12639 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12640 verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12641 verify(mListeners).isComponentEnabledForPackage(packageName); 12642 verify(mDevicePolicyManager).isActiveDeviceOwner(uid); 12643 } 12644 12645 private static <T extends Parcelable> T parcelAndUnparcel(T source, 12646 Parcelable.Creator<T> creator) { 12647 Parcel parcel = Parcel.obtain(); 12648 source.writeToParcel(parcel, 0); 12649 parcel.setDataPosition(0); 12650 return creator.createFromParcel(parcel); 12651 } 12652 12653 private PendingIntent createPendingIntent(String action) { 12654 return PendingIntent.getActivity(mContext, 0, 12655 new Intent(action).setPackage(mContext.getPackageName()), 12656 PendingIntent.FLAG_MUTABLE); 12657 } 12658 12659 private void setDpmAppOppsExemptFromDismissal(boolean isOn) { 12660 DeviceConfig.setProperty( 12661 DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER, 12662 /* name= */ "application_exemptions", 12663 String.valueOf(isOn), 12664 /* makeDefault= */ false); 12665 } 12666 12667 private void allowTestPackageToToast() throws Exception { 12668 assertWithMessage("toast queue").that(mService.mToastQueue).isEmpty(); 12669 mService.isSystemUid = false; 12670 mService.isSystemAppId = false; 12671 setToastRateIsWithinQuota(true); 12672 setIfPackageHasPermissionToAvoidToastRateLimiting(TEST_PACKAGE, false); 12673 // package is not suspended 12674 when(mPackageManager.isPackageSuspendedForUser(TEST_PACKAGE, mUserId)) 12675 .thenReturn(false); 12676 } 12677 12678 private void enqueueToast(String testPackage, ITransientNotification callback) 12679 throws RemoteException { 12680 enqueueToast((INotificationManager) mService.mService, testPackage, new Binder(), callback); 12681 } 12682 12683 private void enqueueToast(INotificationManager service, String testPackage, 12684 IBinder token, ITransientNotification callback) throws RemoteException { 12685 service.enqueueToast(testPackage, token, callback, TOAST_DURATION, /* isUiContext= */ true, 12686 DEFAULT_DISPLAY); 12687 } 12688 12689 private void enqueueTextToast(String testPackage, CharSequence text) throws RemoteException { 12690 enqueueTextToast(testPackage, text, /* isUiContext= */ true, DEFAULT_DISPLAY); 12691 } 12692 12693 private void enqueueTextToast(String testPackage, CharSequence text, boolean isUiContext, 12694 int displayId) throws RemoteException { 12695 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), text, 12696 TOAST_DURATION, isUiContext, displayId, /* textCallback= */ null); 12697 } 12698 12699 private void mockIsVisibleBackgroundUsersSupported(boolean supported) { 12700 when(mUm.isVisibleBackgroundUsersSupported()).thenReturn(supported); 12701 } 12702 12703 private void mockIsUserVisible(int displayId, boolean visible) { 12704 when(mUmInternal.isUserVisible(mUserId, displayId)).thenReturn(visible); 12705 } 12706 12707 private void mockDisplayAssignedToUser(int displayId) { 12708 when(mUmInternal.getMainDisplayAssignedToUser(mUserId)).thenReturn(displayId); 12709 } 12710 12711 private void verifyToastShownForTestPackage(String text, int displayId) { 12712 verify(mStatusBar).showToast(eq(mUid), eq(TEST_PACKAGE), any(), eq(text), any(), 12713 eq(TOAST_DURATION), any(), eq(displayId)); 12714 } 12715 } 12716